Repository: microsoft/profile-explorer Branch: main Commit: 0bd4f8a96f28 Files: 1054 Total size: 33.6 MB Directory structure: gitextract_u18f_5li/ ├── .github/ │ └── workflows/ │ ├── codeql.yml │ ├── dotnet-desktop.yml │ └── installer.yml ├── .gitignore ├── .gitmodules ├── AGENTS.md ├── CLAUDE.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.MD ├── CodeQL.yml ├── LICENSE.TXT ├── NOTICE.md ├── README.md ├── SECURITY.md ├── build-arm64.cmd ├── build.cmd ├── docs/ │ ├── build.cmd │ ├── docs/ │ │ ├── about.md │ │ ├── assembly-view.md │ │ ├── call-tree-panel.md │ │ ├── caller-panel.md │ │ ├── demos.md │ │ ├── flame-graph-panel.md │ │ ├── flow-graph-panel.md │ │ ├── index.json │ │ ├── intro.md │ │ ├── options.md │ │ ├── profile-marking.md │ │ ├── profiling-ui.md │ │ ├── rust.md │ │ ├── source-panel.md │ │ ├── style.css │ │ ├── summary-panel.md │ │ ├── timeline-panel.md │ │ ├── trace-loading.md │ │ ├── trace-overview.md │ │ ├── trace-recording.md │ │ └── workspaces │ └── mkdocs.yml ├── installer/ │ ├── arm64/ │ │ ├── installer.iss │ │ ├── prepare-installer.cmd │ │ ├── prepare-out.cmd │ │ └── prepare.cmd │ ├── environment.iss │ └── x64/ │ ├── installer.iss │ ├── prepare-installer.cmd │ ├── prepare-out.cmd │ └── prepare.cmd ├── resources/ │ ├── asm/ │ │ ├── arm64-asm.xshd │ │ ├── function-markings.json │ │ └── x86-asm.xshd │ ├── documentStyles.xml │ ├── ir.xshd │ ├── llvm/ │ │ └── llvm.xshd │ ├── scripts/ │ │ └── ssa-checker.cs │ └── workspaces/ │ ├── Profiling - Compact.xml │ ├── Profiling - Source.xml │ ├── Profiling - Wide Alt.xml │ ├── Profiling - Wide.xml │ └── Profiling.xml ├── scripts/ │ └── Analyze-DiagnosticLog.ps1 └── src/ ├── .editorconfig ├── .gitattributes ├── GrpcLib/ │ ├── DebugService.proto │ └── GrpcLib.csproj ├── ManagedProfiler/ │ ├── CLRDataTarget.h │ ├── CapstoneWrappers.h │ ├── Common.h │ ├── CoreProfiler.cpp │ ├── CoreProfiler.h │ ├── CoreProfilerFactory.cpp │ ├── CoreProfilerFactory.h │ ├── IRExplorerProfiler.vcxproj.filters │ ├── ManagedProfiler.def │ ├── ManagedProfiler.vcxproj │ ├── NamedPipeClient.h │ ├── dllmain.cpp │ ├── external/ │ │ └── coreclr/ │ │ ├── inc/ │ │ │ ├── CrstTypeTool.cs │ │ │ ├── CrstTypes.def │ │ │ ├── OpCodeGen.pl │ │ │ ├── allocacheck.h │ │ │ ├── arrayholder.h │ │ │ ├── arraylist.h │ │ │ ├── assemblybinderutil.h │ │ │ ├── bitmask.h │ │ │ ├── bitmask.inl │ │ │ ├── bitposition.h │ │ │ ├── bitvector.h │ │ │ ├── blobfetcher.h │ │ │ ├── bundle.h │ │ │ ├── cahlpr.h │ │ │ ├── caparser.h │ │ │ ├── ceefilegenwriter.h │ │ │ ├── ceegen.h │ │ │ ├── ceegentokenmapper.h │ │ │ ├── ceesectionstring.h │ │ │ ├── cfi.h │ │ │ ├── check.h │ │ │ ├── check.inl │ │ │ ├── clr/ │ │ │ │ ├── fs/ │ │ │ │ │ └── path.h │ │ │ │ ├── fs.h │ │ │ │ ├── stack.h │ │ │ │ ├── str.h │ │ │ │ └── win32.h │ │ │ ├── clr_std/ │ │ │ │ ├── algorithm │ │ │ │ ├── string │ │ │ │ ├── type_traits │ │ │ │ ├── utility │ │ │ │ └── vector │ │ │ ├── clrconfig.h │ │ │ ├── clrconfignocache.h │ │ │ ├── clrconfigvalues.h │ │ │ ├── clrdata.idl │ │ │ ├── clrhost.h │ │ │ ├── clrinternal.idl │ │ │ ├── clrnt.h │ │ │ ├── clrtypes.h │ │ │ ├── clrversion.h │ │ │ ├── complex.h │ │ │ ├── configuration.h │ │ │ ├── contract.h │ │ │ ├── contract.inl │ │ │ ├── cor.h │ │ │ ├── corcompile.h │ │ │ ├── cordbpriv.h │ │ │ ├── cordebug.idl │ │ │ ├── cordebuginfo.h │ │ │ ├── coredistools.h │ │ │ ├── corerror.xml │ │ │ ├── corexcep.h │ │ │ ├── corhdr.h │ │ │ ├── corhlpr.cpp │ │ │ ├── corhlpr.h │ │ │ ├── corhlprpriv.cpp │ │ │ ├── corhlprpriv.h │ │ │ ├── corhost.h │ │ │ ├── corimage.h │ │ │ ├── corinfo.h │ │ │ ├── corinfoinstructionset.h │ │ │ ├── corjit.h │ │ │ ├── corjitflags.h │ │ │ ├── corjithost.h │ │ │ ├── corpriv.h │ │ │ ├── corprof.idl │ │ │ ├── corpub.idl │ │ │ ├── corsym.idl │ │ │ ├── cortypeinfo.h │ │ │ ├── crosscomp.h │ │ │ ├── crsttypes_generated.h │ │ │ ├── crtwrap.h │ │ │ ├── cvconst.h │ │ │ ├── cvinfo.h │ │ │ ├── cycletimer.h │ │ │ ├── daccess.h │ │ │ ├── dacprivate.h │ │ │ ├── dacvars.h │ │ │ ├── dbgenginemetrics.h │ │ │ ├── dbgmeta.h │ │ │ ├── dbgportable.h │ │ │ ├── debugmacros.h │ │ │ ├── debugmacrosext.h │ │ │ ├── debugreturn.h │ │ │ ├── dlwrap.h │ │ │ ├── ecmakey.h │ │ │ ├── eetwain.h │ │ │ ├── eexcp.h │ │ │ ├── eventtrace.h │ │ │ ├── eventtracebase.h │ │ │ ├── ex.h │ │ │ ├── executableallocator.h │ │ │ ├── factory.h │ │ │ ├── factory.inl │ │ │ ├── formattype.cpp │ │ │ ├── formattype.h │ │ │ ├── fstream.h │ │ │ ├── fstring.h │ │ │ ├── gcdecoder.cpp │ │ │ ├── gcdump.h │ │ │ ├── gcinfo.h │ │ │ ├── gcinfoarraylist.h │ │ │ ├── gcinfodecoder.h │ │ │ ├── gcinfodumper.h │ │ │ ├── gcinfoencoder.h │ │ │ ├── gcinfotypes.h │ │ │ ├── gcmsg.inl │ │ │ ├── gcrefmap.h │ │ │ ├── genheaders.cs │ │ │ ├── genrops.pl │ │ │ ├── gfunc_list.h │ │ │ ├── guidfromname.h │ │ │ ├── holder.h │ │ │ ├── iallocator.h │ │ │ ├── iceefilegen.h │ │ │ ├── icorjitinfoimpl_generated.h │ │ │ ├── il_kywd.h │ │ │ ├── ilformatter.h │ │ │ ├── internalunknownimpl.h │ │ │ ├── intrinsic.h │ │ │ ├── iterator.h │ │ │ ├── jiteeversionguid.h │ │ │ ├── jithelpers.h │ │ │ ├── livedatatarget.h │ │ │ ├── llvm/ │ │ │ │ ├── Dwarf.def │ │ │ │ ├── Dwarf.h │ │ │ │ └── ELF.h │ │ │ ├── loaderheap.h │ │ │ ├── log.h │ │ │ ├── loglf.h │ │ │ ├── longfilepathwrappers.h │ │ │ ├── md5.h │ │ │ ├── mdcommon.h │ │ │ ├── mdfileformat.h │ │ │ ├── memorypool.h │ │ │ ├── memoryrange.h │ │ │ ├── metadata.h │ │ │ ├── metadataexports.h │ │ │ ├── metahost.idl │ │ │ ├── metamodelpub.h │ │ │ ├── mpl/ │ │ │ │ └── type_list │ │ │ ├── mscoree.idl │ │ │ ├── msodw.h │ │ │ ├── msodwwrap.h │ │ │ ├── nativevaraccessors.h │ │ │ ├── new.hpp │ │ │ ├── nibblemapmacros.h │ │ │ ├── nibblestream.h │ │ │ ├── nsutilpriv.h │ │ │ ├── opcode.def │ │ │ ├── openum.h │ │ │ ├── opinfo.h │ │ │ ├── optdefault.h │ │ │ ├── optsmallperfcritical.h │ │ │ ├── ostype.h │ │ │ ├── outstring.h │ │ │ ├── palclr.h │ │ │ ├── palclr_win.h │ │ │ ├── patchpointinfo.h │ │ │ ├── pedecoder.h │ │ │ ├── pedecoder.inl │ │ │ ├── pesectionman.h │ │ │ ├── pgo_formatprocessing.h │ │ │ ├── pinvokeoverride.h │ │ │ ├── posterror.h │ │ │ ├── predeftlsslot.h │ │ │ ├── prettyprintsig.h │ │ │ ├── profilepriv.h │ │ │ ├── profilepriv.inl │ │ │ ├── random.h │ │ │ ├── readme.md │ │ │ ├── readytorun.h │ │ │ ├── readytorunhelpers.h │ │ │ ├── readytoruninstructionset.h │ │ │ ├── regdisp.h │ │ │ ├── releaseholder.h │ │ │ ├── safemath.h │ │ │ ├── safewrap.h │ │ │ ├── sarray.h │ │ │ ├── sarray.inl │ │ │ ├── sbuffer.h │ │ │ ├── sbuffer.inl │ │ │ ├── sha1.h │ │ │ ├── shash.h │ │ │ ├── shash.inl │ │ │ ├── shimload.h │ │ │ ├── sigbuilder.h │ │ │ ├── sigparser.h │ │ │ ├── simplerhash.h │ │ │ ├── simplerhash.inl │ │ │ ├── slist.h │ │ │ ├── sospriv.idl │ │ │ ├── sstring.h │ │ │ ├── sstring.inl │ │ │ ├── stack.h │ │ │ ├── stackframe.h │ │ │ ├── stacktrace.h │ │ │ ├── static_assert.h │ │ │ ├── staticcontract.h │ │ │ ├── stdmacros.h │ │ │ ├── stgpool.h │ │ │ ├── stgpooli.h │ │ │ ├── stresslog.h │ │ │ ├── stringarraylist.h │ │ │ ├── stringarraylist.inl │ │ │ ├── strongnameholders.h │ │ │ ├── strongnameinternal.h │ │ │ ├── switches.h │ │ │ ├── targetosarch.h │ │ │ ├── thekey.h │ │ │ ├── tls.h │ │ │ ├── unreachable.h │ │ │ ├── utilcode.h │ │ │ ├── utsem.h │ │ │ ├── volatile.h │ │ │ ├── vptr_list.h │ │ │ ├── win64unwind.h │ │ │ ├── winwrap.h │ │ │ ├── xclrdata.idl │ │ │ ├── xcordebug.idl │ │ │ └── yieldprocessornormalized.h │ │ └── pal/ │ │ └── prebuilt/ │ │ └── inc/ │ │ ├── clrdata.h │ │ ├── clrinternal.h │ │ ├── cordebug.h │ │ ├── corerror.h │ │ ├── corprof.h │ │ ├── corpub.h │ │ ├── corsym.h │ │ ├── fxver.h │ │ ├── fxver.rc │ │ ├── metahost.h │ │ ├── mscoree.h │ │ ├── sospriv.h │ │ ├── xclrdata.h │ │ └── xcordebug.h │ └── framework.h ├── PDBViewer/ │ ├── AboutBox.Designer.cs │ ├── AboutBox.cs │ ├── AboutBox.resx │ ├── DebugInfoModel.cs │ ├── MainForm.Designer.cs │ ├── MainForm.cs │ ├── MainForm.resx │ ├── PDBViewer.csproj │ ├── Program.cs │ └── Properties/ │ ├── Resources.Designer.cs │ └── Resources.resx ├── ProfileExplorer.Mcp/ │ ├── IMcpActionExecutor.cs │ ├── McpServerConfiguration.cs │ ├── ProfileExplorer.Mcp.csproj │ ├── ProfileExplorerMcpServer.cs │ ├── Program.cs │ └── README.md ├── ProfileExplorer.sln ├── ProfileExplorerCore/ │ ├── Analysis/ │ │ ├── CFGBlockOrdering.cs │ │ ├── CFGReachability.cs │ │ ├── CFGReachabilityReferenceFilter.cs │ │ ├── CallGraph.cs │ │ ├── DominanceFrontier.cs │ │ ├── DominatorAlgorithm.cs │ │ ├── FunctionAnalysisCache.cs │ │ ├── LoopGraph.cs │ │ ├── ReferenceFinder.cs │ │ └── SimilarValueFinder.cs │ ├── Binary/ │ │ ├── Disassembler.cs │ │ ├── DotNetDebugInfoProvider.cs │ │ ├── FunctionDebugInfo.cs │ │ ├── IBinaryInfoProvider.cs │ │ ├── IDebugInfoProvider.cs │ │ ├── JsonDebugInfoProvider.cs │ │ ├── PDBDebugInfoProvider.cs │ │ ├── PEBinaryInfoProvider.cs │ │ ├── SourceFileDebugInfo.cs │ │ ├── SourceLineDebugInfo.cs │ │ └── SymbolFileCache.cs │ ├── Collections/ │ │ ├── CompressedSegmentedList.cs │ │ ├── SparseBitVector.cs │ │ ├── StringTrie.cs │ │ └── TinyList.cs │ ├── Compilers/ │ │ ├── ASM/ │ │ │ ├── ARM64Opcodes.cs │ │ │ ├── ASMBinaryFileFinder.cs │ │ │ ├── ASMCompilerIRInfo.cs │ │ │ ├── ASMCompilerInfoProvider.cs │ │ │ ├── ASMDebugFileFinder.cs │ │ │ ├── ASMDebugInfoProviderFactory.cs │ │ │ ├── ASMDiffFilterProvider.cs │ │ │ ├── ASMDiffInputFilter.cs │ │ │ ├── ASMIRSectionParser.cs │ │ │ ├── ASMIRSectionReader.cs │ │ │ ├── ASMNameProvider.cs │ │ │ ├── ASMParser.cs │ │ │ ├── DisassemblerSectionLoader.cs │ │ │ └── X86Opcodes.cs │ │ ├── Architecture/ │ │ │ ├── ARM64RegisterTable.cs │ │ │ ├── IRMode.cs │ │ │ ├── RegisterTables.cs │ │ │ └── X86RegisterTable.cs │ │ ├── Defaults/ │ │ │ ├── DefaultDiffOutputFilter.cs │ │ │ └── DefaultNameProvider.cs │ │ └── LLVM/ │ │ ├── LLVMBinaryFileFinder.cs │ │ ├── LLVMCompilerIRInfo.cs │ │ ├── LLVMCompilerInfoProvider.cs │ │ ├── LLVMDebugFileFinder.cs │ │ ├── LLVMDebugInfoProviderFactory.cs │ │ ├── LLVMDiffFilterProvider.cs │ │ └── LLVMSectionReader.cs │ ├── Controls/ │ │ └── IRElementReference.cs │ ├── Core.vsdoc │ ├── Diff/ │ │ ├── BeyondCompareDiffBuilder.cs │ │ ├── DocumentDiffBuilder.cs │ │ ├── IDiffFilterProvider.cs │ │ └── IDiffOutputFilter.cs │ ├── Document/ │ │ └── Renderers/ │ │ └── Highlighters/ │ │ └── DiffKind.cs │ ├── DocumentSectionLoader.cs │ ├── FileFormat/ │ │ └── FileArchive.cs │ ├── Graph/ │ │ ├── CallGraphPrinter.cs │ │ ├── DominatorTreePrinter.cs │ │ ├── ExpressionGraphPrinter.cs │ │ ├── FlowGraphPrinter.cs │ │ ├── Graph.cs │ │ ├── GraphPrinterFactory.cs │ │ ├── GraphvizPrinter.cs │ │ └── GraphvizReader.cs │ ├── ICompilerIRInfo.cs │ ├── IR/ │ │ ├── BlockIR.cs │ │ ├── BlockLabelIR.cs │ │ ├── FunctionIR.cs │ │ ├── IRElement.cs │ │ ├── IRElementId.cs │ │ ├── IRPrinter.cs │ │ ├── IRVisitor.cs │ │ ├── ITag.cs │ │ ├── InstructionIR.cs │ │ ├── OperandIR.cs │ │ ├── RegisterIR.cs │ │ ├── RegisterTable.cs │ │ ├── TaggedObject.cs │ │ ├── Tags/ │ │ │ ├── AssemblyMetadataTag.cs │ │ │ ├── LoopTag.cs │ │ │ ├── NotesTag.cs │ │ │ ├── RegisterTag.cs │ │ │ ├── SSATags.cs │ │ │ ├── SourceLocationTag.cs │ │ │ └── SourceStackTrace.cs │ │ ├── TupleIR.cs │ │ └── TypeIR.cs │ ├── IRPassOutput.cs │ ├── IRSectionReader.cs │ ├── IRTextFunction.cs │ ├── IRTextSection.cs │ ├── IRTextSectionLoader.cs │ ├── IRTextSummary.cs │ ├── Lexer/ │ │ ├── CharSource.cs │ │ ├── CharTable.cs │ │ ├── Lexer.cs │ │ └── Token.cs │ ├── Parser/ │ │ ├── IRSectionParser.cs │ │ ├── ParserBase.cs │ │ └── ParsingErrorHandler.cs │ ├── Profile/ │ │ ├── CallTree/ │ │ │ ├── ProfileCallSite.cs │ │ │ ├── ProfileCallTree.cs │ │ │ └── ProfileCallTreeNode.cs │ │ ├── Data/ │ │ │ ├── FunctionProfileData.cs │ │ │ ├── IProfileDataProvider.cs │ │ │ ├── IpToImageCache.cs │ │ │ ├── ManagedRawProfileData.cs │ │ │ ├── ModuleProfileInfo.cs │ │ │ ├── PerformanceCounters.cs │ │ │ ├── ProcessSummaryBuilder.cs │ │ │ ├── ProfileData.cs │ │ │ ├── ProfileDataReport.cs │ │ │ ├── ProfileModuleBuilder.cs │ │ │ ├── RawProfileData.cs │ │ │ ├── RawProfileModel.cs │ │ │ └── ResolvedProfileStack.cs │ │ ├── ETW/ │ │ │ ├── ETWEventProcessor.cs │ │ │ ├── ETWEventProcessorManaged.cs │ │ │ ├── ETWProfileDataProvider.cs │ │ │ ├── ETWRecordingSession.cs │ │ │ └── ProfilerNamedPipeServer.cs │ │ ├── Processing/ │ │ │ ├── CallTreeProcessor.cs │ │ │ ├── FunctionProfileProcessor.cs │ │ │ ├── FunctionSamplesProcessor.cs │ │ │ ├── FunctionsForSamplesProcessor.cs │ │ │ ├── ProfileSampleFilter.cs │ │ │ └── ProfileSampleProcessor.cs │ │ ├── Timeline/ │ │ │ └── ActivityView.cs │ │ └── Utils/ │ │ ├── DummySectionLoader.cs │ │ ├── NamedPipeServer.cs │ │ └── ThreadSuspender.cs │ ├── ProfileExplorerCore.csproj │ ├── Providers/ │ │ ├── CompilerIRKind.cs │ │ ├── IBinaryFileFinder.cs │ │ ├── ICompilerInfoProvider.cs │ │ ├── IDebugFileFinder.cs │ │ ├── IDebugInfoProviderFactory.cs │ │ └── INameProvider.cs │ ├── SectionReaderBase.cs │ ├── Session/ │ │ ├── BaseSession.cs │ │ ├── ILoadedDocument.cs │ │ ├── ILoadedDocumentState.cs │ │ ├── ISession.cs │ │ ├── LoadedDocument.cs │ │ └── StateSerializer.cs │ ├── Settings/ │ │ ├── DiffSettings.cs │ │ ├── GeneralSettings.cs │ │ ├── ISettingsProvider.cs │ │ ├── ISettingsTypeConverter.cs │ │ ├── ProfileDataProviderOptions.cs │ │ ├── ProfileOptions.cs │ │ ├── SectionSettings.cs │ │ ├── SettingsBase.cs │ │ └── SymbolFileSourceSettings.cs │ ├── SourceParser/ │ │ ├── SourceCodeParser.cs │ │ ├── SourceSyntaxTree.cs │ │ └── TreeSitter.cs │ ├── TextLocation.cs │ └── Utilities/ │ ├── BindableObject.cs │ ├── CancelableTask.cs │ ├── CancelableTaskInstance.cs │ ├── CollectionExtensionMethods.cs │ ├── CompressionUtils.cs │ ├── CoreSettingsProvider.cs │ ├── DebugObjectId.cs │ ├── DiagnosticLogger.cs │ ├── ExtensionMethods.cs │ ├── JsonUtils.cs │ ├── NativeMethods.cs │ ├── Optional.cs │ ├── SourceFileMapper.cs │ └── Utils.cs ├── ProfileExplorerCoreTests/ │ ├── ASMIRSectionReaderTests.cs │ ├── CompressedSegmentedListTests.cs │ ├── ETWUnmappedFrameResolutionTests.cs │ ├── EndToEndWorkflowTests.cs │ ├── ExtensionMethodsTests.cs │ ├── FileFormat/ │ │ └── FileArchiveTest.cs │ ├── ProfileExplorerCoreTests.csproj │ ├── SourceFileMapperTests.cs │ ├── SparseBitVectorTests.cs │ ├── StringTrieTests.cs │ ├── TestData/ │ │ ├── MsoTrace/ │ │ │ ├── assembly_Mso20win32client.dll_baseline.csv │ │ │ ├── functions_AppvIsvSubsystems64.dll_baseline.csv │ │ │ ├── functions_C2R64.dll_baseline.csv │ │ │ ├── functions_CI.dll_baseline.csv │ │ │ ├── functions_CoreMessaging.dll_baseline.csv │ │ │ ├── functions_DWrite.dll_baseline.csv │ │ │ ├── functions_EMSMDB32.DLL_baseline.csv │ │ │ ├── functions_FLTMGR.SYS_baseline.csv │ │ │ ├── functions_FlightSettings.dll_baseline.csv │ │ │ ├── functions_IPHLPAPI.DLL_baseline.csv │ │ │ ├── functions_KernelBase.dll_baseline.csv │ │ │ ├── functions_MSO.DLL_baseline.csv │ │ │ ├── functions_MSOARIA.DLL_baseline.csv │ │ │ ├── functions_MSPST32.DLL_baseline.csv │ │ │ ├── functions_MSPTLS.DLL_baseline.csv │ │ │ ├── functions_MicrosoftAccountWAMExtension.dll_baseline.csv │ │ │ ├── functions_Mso20win32client.dll_baseline.csv │ │ │ ├── functions_Mso30win32client.dll_baseline.csv │ │ │ ├── functions_Mso40UIwin32client.dll_baseline.csv │ │ │ ├── functions_Mso50win32client.dll_baseline.csv │ │ │ ├── functions_Mso98win32client.dll_baseline.csv │ │ │ ├── functions_NETIO.SYS_baseline.csv │ │ │ ├── functions_Ntfs.sys_baseline.csv │ │ │ ├── functions_OART.DLL_baseline.csv │ │ │ ├── functions_OLMAPI32.DLL_baseline.csv │ │ │ ├── functions_OneCoreUAPCommonProxyStub.dll_baseline.csv │ │ │ ├── functions_PPCORE.DLL_baseline.csv │ │ │ ├── functions_PktMon.sys_baseline.csv │ │ │ ├── functions_TextShaping.dll_baseline.csv │ │ │ ├── functions_UIAutomationCore.dll_baseline.csv │ │ │ ├── functions_WdFilter.sys_baseline.csv │ │ │ ├── functions_WinTypes.dll_baseline.csv │ │ │ ├── functions_Windows.Networking.Connectivity.dll_baseline.csv │ │ │ ├── functions_Windows.Security.Authentication.Web.Core.dll_baseline.csv │ │ │ ├── functions_Windows.StateRepositoryCore.dll_baseline.csv │ │ │ ├── functions_Windows.Web.dll_baseline.csv │ │ │ ├── functions_WindowsCodecs.dll_baseline.csv │ │ │ ├── functions_Wldap32.dll_baseline.csv │ │ │ ├── functions_ahcache.sys_baseline.csv │ │ │ ├── functions_aitrx.dll_baseline.csv │ │ │ ├── functions_bcrypt.dll_baseline.csv │ │ │ ├── functions_bcryptprimitives.dll_baseline.csv │ │ │ ├── functions_bindflt.sys_baseline.csv │ │ │ ├── functions_cng.sys_baseline.csv │ │ │ ├── functions_combase.dll_baseline.csv │ │ │ ├── functions_comctl32.dll_baseline.csv │ │ │ ├── functions_cpprestsdk.dll_baseline.csv │ │ │ ├── functions_crypt32.dll_baseline.csv │ │ │ ├── functions_d2d1.dll_baseline.csv │ │ │ ├── functions_d3d11.dll_baseline.csv │ │ │ ├── functions_dcomp.dll_baseline.csv │ │ │ ├── functions_dhcpcsvc.dll_baseline.csv │ │ │ ├── functions_dhcpcsvc6.dll_baseline.csv │ │ │ ├── functions_dpapi.dll_baseline.csv │ │ │ ├── functions_dxgi.dll_baseline.csv │ │ │ ├── functions_dxgkrnl.sys_baseline.csv │ │ │ ├── functions_dxgmms2.sys_baseline.csv │ │ │ ├── functions_e1d.sys_baseline.csv │ │ │ ├── functions_fcon.dll_baseline.csv │ │ │ ├── functions_fileinfo.sys_baseline.csv │ │ │ ├── functions_fvevol.sys_baseline.csv │ │ │ ├── functions_gdi32full.dll_baseline.csv │ │ │ ├── functions_iertutil.dll_baseline.csv │ │ │ ├── functions_imagehlp.dll_baseline.csv │ │ │ ├── functions_intelppm.sys_baseline.csv │ │ │ ├── functions_kernel32.dll_baseline.csv │ │ │ ├── functions_ksecdd.sys_baseline.csv │ │ │ ├── functions_msasn1.dll_baseline.csv │ │ │ ├── functions_mssecflt.sys_baseline.csv │ │ │ ├── functions_msvcp140.dll_baseline.csv │ │ │ ├── functions_mswsock.dll_baseline.csv │ │ │ ├── functions_msxml6.dll_baseline.csv │ │ │ ├── functions_ntdll.dll_baseline.csv │ │ │ ├── functions_ntoskrnl.exe_baseline.csv │ │ │ ├── functions_nvlddmkm.sys_baseline.csv │ │ │ ├── functions_nvldumdx.dll_baseline.csv │ │ │ ├── functions_nvwgf2umx_cfg.dll_baseline.csv │ │ │ ├── functions_oleaut32.dll_baseline.csv │ │ │ ├── functions_rpcrt4.dll_baseline.csv │ │ │ ├── functions_schannel.dll_baseline.csv │ │ │ ├── functions_sechost.dll_baseline.csv │ │ │ ├── functions_sspicli.dll_baseline.csv │ │ │ ├── functions_ucrtbase.dll_baseline.csv │ │ │ ├── functions_user32.dll_baseline.csv │ │ │ ├── functions_uxtheme.dll_baseline.csv │ │ │ ├── functions_vaultcli.dll_baseline.csv │ │ │ ├── functions_vcruntime140.dll_baseline.csv │ │ │ ├── functions_webio.dll_baseline.csv │ │ │ ├── functions_webservices.dll_baseline.csv │ │ │ ├── functions_win32kbase.sys_baseline.csv │ │ │ ├── functions_win32kbase_rs.sys_baseline.csv │ │ │ ├── functions_win32kfull.sys_baseline.csv │ │ │ ├── functions_win32u.dll_baseline.csv │ │ │ ├── functions_windows.storage.dll_baseline.csv │ │ │ ├── functions_winhttp.dll_baseline.csv │ │ │ ├── functions_wininet.dll_baseline.csv │ │ │ ├── functions_wosc.dll_baseline.csv │ │ │ ├── functions_ws2_32.dll_baseline.csv │ │ │ ├── functions_xmllite.dll_baseline.csv │ │ │ ├── modules_baseline.csv │ │ │ └── processes_baseline.csv │ │ ├── Symbols/ │ │ │ └── MsoTrace/ │ │ │ └── Mso20Win32Client.pdb │ │ └── Traces/ │ │ └── MsoTrace/ │ │ └── trace.etl │ └── TestDataHelper.cs ├── ProfileExplorerUI/ │ ├── App.xaml │ ├── App.xaml.cs │ ├── Client.vsdoc │ ├── Compilers/ │ │ ├── ASM/ │ │ │ └── ASMLoadedSectionHandler.cs │ │ ├── Default/ │ │ │ ├── BuiltinFunctionTasks/ │ │ │ │ └── UnusedInstructionsFunctionTask.cs │ │ │ ├── BuiltinQueries/ │ │ │ │ ├── RegisterQuery.cs │ │ │ │ └── ValueNumberQuery.cs │ │ │ ├── DefaultRemarkParser.cs │ │ │ ├── DefaultRemarkProvider.cs │ │ │ └── DefaultSectionStyleProvider.cs │ │ └── LLVM/ │ │ └── LLVMLoadedSectionHandler.cs │ ├── Controls/ │ │ ├── ColorPaletteSelector.xaml │ │ ├── ColorPaletteSelector.xaml.cs │ │ ├── ColorPaletteViewer.xaml │ │ ├── ColorPaletteViewer.xaml.cs │ │ ├── ColorSelector.xaml │ │ ├── ColorSelector.xaml.cs │ │ ├── DraggablePopup.cs │ │ ├── FileSystemTextBox.cs │ │ ├── Graph/ │ │ │ ├── CallGraphStyleProvider.cs │ │ │ ├── ColorPalette.cs │ │ │ ├── ExpressionGraphStyleProvider.cs │ │ │ ├── FlowGraphStyleProvider.cs │ │ │ ├── GraphNodeTag.cs │ │ │ ├── GraphRenderer.cs │ │ │ ├── GraphViewer.xaml │ │ │ └── GraphViewer.xaml.cs │ │ ├── HoverPreview.cs │ │ ├── IRDocumentPopup.xaml │ │ ├── IRDocumentPopup.xaml.cs │ │ ├── IconSelector.xaml │ │ ├── IconSelector.xaml.cs │ │ ├── NotesPopup.xaml │ │ ├── NotesPopup.xaml.cs │ │ ├── OptionalColumn.cs │ │ ├── PanelToolbarTray.xaml │ │ ├── PanelToolbarTray.xaml.cs │ │ ├── ResizeGrip.xaml │ │ ├── ResizeGrip.xaml.cs │ │ ├── WebViewPopup.xaml │ │ └── WebViewPopup.xaml.cs │ ├── Converters.xaml │ ├── Diff/ │ │ └── DocumentDiffUpdater.cs │ ├── Document/ │ │ ├── ActionPanel.xaml │ │ ├── ActionPanel.xaml.cs │ │ ├── BasicBlockFoldingStrategy.cs │ │ ├── BasicBlockFoldingStrategyProvider.cs │ │ ├── DocumentAction.cs │ │ ├── DocumentExporting.cs │ │ ├── DocumentUtils.cs │ │ ├── Highlighting/ │ │ │ ├── DefaultHighlightingStyles.cs │ │ │ ├── HighlightedElementGroup.cs │ │ │ ├── HighlightingStyle.cs │ │ │ └── IRElementSegment.cs │ │ ├── ILoadedSectionHandler.cs │ │ ├── IRDocument.cs │ │ ├── IRDocumentColumnData.cs │ │ ├── IRDocumentHost.xaml │ │ ├── IRDocumentHost.xaml.cs │ │ ├── IRDocumentState.cs │ │ ├── LightIRDocument.cs │ │ ├── RemarkPreviewPanel.xaml │ │ ├── RemarkPreviewPanel.xaml.cs │ │ ├── RemarkTag.cs │ │ ├── Renderers/ │ │ │ ├── DocumentMargin.cs │ │ │ ├── Highlighters/ │ │ │ │ ├── BlockBackgroundHighlighter.cs │ │ │ │ ├── CurrentLineHighlighter.cs │ │ │ │ ├── DiffLineHighlighter.cs │ │ │ │ ├── ElementHighlighter.cs │ │ │ │ └── RemarkHighlighter.cs │ │ │ ├── IElementOverlay.cs │ │ │ ├── IconDrawing.cs │ │ │ ├── MarkerScroolBar.cs │ │ │ ├── OverlayRenderer.cs │ │ │ └── Overlays/ │ │ │ ├── ElementOverlayBase.cs │ │ │ ├── IconElementOverlay.cs │ │ │ └── TextElementOverlay.cs │ │ ├── SearchInfo.cs │ │ ├── SearchPanel.xaml │ │ ├── SearchPanel.xaml.cs │ │ ├── SearcheableIRDocument.xaml │ │ └── SearcheableIRDocument.xaml.cs │ ├── GlobalSuppressions.cs │ ├── GrpcServer/ │ │ ├── DebugSectionLoader.cs │ │ └── DebugService.cs │ ├── Icons.xaml │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── MainWindowDebugRpc.cs │ ├── MainWindowDiff.cs │ ├── MainWindowPanels.cs │ ├── MainWindowProfiling.cs │ ├── MainWindowSession.cs │ ├── Mcp/ │ │ └── McpActionExecutor.cs │ ├── OptionsPanels/ │ │ ├── CallTreeOptionsPanel.xaml │ │ ├── CallTreeOptionsPanel.xaml.cs │ │ ├── ColumnOptionsPanel.xaml │ │ ├── ColumnOptionsPanel.xaml.cs │ │ ├── DiffOptionsPanel.xaml │ │ ├── DiffOptionsPanel.xaml.cs │ │ ├── DocumentOptionsPanel.xaml │ │ ├── DocumentOptionsPanel.xaml.cs │ │ ├── DocumentProfilingOptionsPanel.xaml │ │ ├── DocumentProfilingOptionsPanel.xaml.cs │ │ ├── ExpressionGraphOptionsPanel.xaml │ │ ├── ExpressionGraphOptionsPanel.xaml.cs │ │ ├── FlameGraphOptionsPanel.xaml │ │ ├── FlameGraphOptionsPanel.xaml.cs │ │ ├── FlowGraphOptionsPanel.xaml │ │ ├── FlowGraphOptionsPanel.xaml.cs │ │ ├── FunctionMarkingOptionsPanel.xaml │ │ ├── FunctionMarkingOptionsPanel.xaml.cs │ │ ├── GeneralOptionsPanel.xaml │ │ ├── GeneralOptionsPanel.xaml.cs │ │ ├── LightDocumentOptionsPanel.xaml │ │ ├── LightDocumentOptionsPanel.xaml.cs │ │ ├── OptionsPanelBase.cs │ │ ├── OptionsPanelHostPopup.xaml │ │ ├── OptionsPanelHostPopup.xaml.cs │ │ ├── PreviewPopupOptionsPanel.xaml │ │ ├── PreviewPopupOptionsPanel.xaml.cs │ │ ├── ProfilingOptionsPanel.xaml │ │ ├── ProfilingOptionsPanel.xaml.cs │ │ ├── RemarkOptionsPanel.xaml │ │ ├── RemarkOptionsPanel.xaml.cs │ │ ├── SectionOptionsPanel.xaml │ │ ├── SectionOptionsPanel.xaml.cs │ │ ├── SourceFileOptionsPanel.xaml │ │ ├── SourceFileOptionsPanel.xaml.cs │ │ ├── SymbolOptionsPanel.xaml │ │ ├── SymbolOptionsPanel.xaml.cs │ │ ├── TimelineOptionsPanel.xaml │ │ └── TimelineOptionsPanel.xaml.cs │ ├── Panels/ │ │ ├── BookmarksPanel.xaml │ │ ├── BookmarksPanel.xaml.cs │ │ ├── CallGraphPanel.cs │ │ ├── CallerCalleePanel.cs │ │ ├── DefinitionPanel.xaml │ │ ├── DefinitionPanel.xaml.cs │ │ ├── DeveloperPanel.xaml │ │ ├── DeveloperPanel.xaml.cs │ │ ├── DocumentSearchPanel.xaml │ │ ├── DocumentSearchPanel.xaml.cs │ │ ├── DominatorTreePanel.cs │ │ ├── ExpressionGraphPanel.cs │ │ ├── FunctionCodeStatistics.cs │ │ ├── GraphCommand.cs │ │ ├── GraphPanel.xaml │ │ ├── GraphPanel.xaml.cs │ │ ├── HelpPanel.xaml │ │ ├── HelpPanel.xaml.cs │ │ ├── IToolPanel.cs │ │ ├── ModuleReport.cs │ │ ├── ModuleReportPanel.xaml │ │ ├── ModuleReportPanel.xaml.cs │ │ ├── NotesPanel.xaml │ │ ├── NotesPanel.xaml.cs │ │ ├── PassOutputPanel.xaml │ │ ├── PassOutputPanel.xaml.cs │ │ ├── PostDominatorTreePanel.cs │ │ ├── ReferencesPanel.xaml │ │ ├── ReferencesPanel.xaml.cs │ │ ├── ScriptingPanel.xaml │ │ ├── ScriptingPanel.xaml.cs │ │ ├── SearchResultsPanel.xaml │ │ ├── SearchResultsPanel.xaml.cs │ │ ├── SectionPanel.xaml │ │ ├── SectionPanel.xaml.cs │ │ ├── SectionPanelPair.xaml │ │ ├── SectionPanelPair.xaml.cs │ │ ├── SourceFilePanel.xaml │ │ ├── SourceFilePanel.xaml.cs │ │ ├── StartPagePanel.xaml │ │ ├── StartPagePanel.xaml.cs │ │ ├── ToolPanelControl.cs │ │ ├── ValueStatisticPanel.xaml │ │ └── ValueStatisticPanel.xaml.cs │ ├── Profile/ │ │ ├── CallTreeNodePanel.xaml │ │ ├── CallTreeNodePanel.xaml.cs │ │ ├── CallTreeNodePopup.xaml │ │ ├── CallTreeNodePopup.xaml.cs │ │ ├── CallTreePanel.xaml │ │ ├── CallTreePanel.xaml.cs │ │ ├── Document/ │ │ │ ├── DocumentColumns.xaml │ │ │ ├── DocumentColumns.xaml.cs │ │ │ ├── InlineAssemblyHelpers.cs │ │ │ ├── ProfileDocumentMarker.cs │ │ │ ├── ProfileHistoryManager.cs │ │ │ ├── ProfileIRDocument.xaml │ │ │ ├── ProfileIRDocument.xaml.cs │ │ │ ├── ProfileMenuItem.cs │ │ │ ├── ProfileSourceSyntaxNode.cs │ │ │ ├── ProfilingExporting.cs │ │ │ ├── ProfilingUtils.cs │ │ │ └── SourceDocumentMarker.cs │ │ ├── FlameGraph/ │ │ │ ├── FlameGraph.cs │ │ │ ├── FlameGraphHost.xaml │ │ │ ├── FlameGraphHost.xaml.cs │ │ │ ├── FlameGraphPanel.xaml │ │ │ ├── FlameGraphPanel.xaml.cs │ │ │ ├── FlameGraphRenderer.cs │ │ │ ├── FlameGraphViewer.xaml │ │ │ └── FlameGraphViewer.xaml.cs │ │ ├── ProfileListView.xaml │ │ ├── ProfileListView.xaml.cs │ │ ├── ProfileReportPanel.xaml │ │ ├── ProfileReportPanel.xaml.cs │ │ ├── SearchableProfileItem.cs │ │ ├── Timeline/ │ │ │ ├── ActivityTimelineView.xaml │ │ │ ├── ActivityTimelineView.xaml.cs │ │ │ ├── ActivityView.xaml │ │ │ ├── ActivityView.xaml.cs │ │ │ ├── TImelinePanel.xaml │ │ │ └── TImelinePanel.xaml.cs │ │ └── Utils/ │ │ ├── GlyphRunCache.cs │ │ ├── QuadTree.cs │ │ └── SourceFileFinder.cs │ ├── ProfileExplorerUI.csproj │ ├── ProfileStyles.xaml │ ├── Properties/ │ │ ├── Resources.Designer.cs │ │ ├── Resources.resx │ │ ├── Settings.Designer.cs │ │ ├── Settings.settings │ │ └── launchSettings.json │ ├── Providers/ │ │ ├── IBlockFoldingStrategyProvider.cs │ │ ├── IRemarkProvider.cs │ │ └── ISectionStyleProvider.cs │ ├── Query/ │ │ ├── BuiltinElementQuery.cs │ │ ├── BuiltinFunctionTask.cs │ │ ├── Buitin/ │ │ │ ├── InstructionSSAInfoQuery.cs │ │ │ └── OperandSSAInfoQuery.cs │ │ ├── ButtonQueryViewElement .xaml │ │ ├── ButtonQueryViewElement .xaml.cs │ │ ├── ElementQuery.cs │ │ ├── FunctionTask.cs │ │ ├── FunctionTaskDefinition.cs │ │ ├── FunctionTaskOptionsSerializer.cs │ │ ├── InputQueryViewElement.xaml │ │ ├── InputQueryViewElement.xaml.cs │ │ ├── OutputQueryViewElement.xaml │ │ ├── OutputQueryViewElement.xaml.cs │ │ ├── QueryData.cs │ │ ├── QueryPanel.xaml │ │ ├── QueryPanel.xaml.cs │ │ ├── QueryValues.cs │ │ ├── QueryView.xaml │ │ ├── QueryView.xaml.cs │ │ └── ScriptFunctionTask.cs │ ├── Remarks/ │ │ ├── Remark.cs │ │ ├── RemarkLineGroup.cs │ │ └── RemarksDefinitionSerializer.cs │ ├── Scripting/ │ │ ├── ElementQueryScript.cs │ │ ├── Script.cs │ │ ├── ScriptAutoComplete.cs │ │ └── ScriptSession.cs │ ├── Session/ │ │ ├── Bookmark.cs │ │ ├── BookmarkManager.cs │ │ ├── DiffModeInfo.cs │ │ ├── GraphLayoutCache.cs │ │ ├── IUILoadedDocument.cs │ │ ├── IUILoadedDocumentState.cs │ │ ├── IUISession.cs │ │ ├── PanelStateManager.cs │ │ ├── SessionStateManager.cs │ │ ├── UILoadedDocument.cs │ │ └── UIStateSerializer.cs │ ├── Settings/ │ │ ├── ApplicationSettings.cs │ │ ├── CallTreeNodeSettings.cs │ │ ├── CallTreeSettings.cs │ │ ├── ColorSettingsConverter.cs │ │ ├── ColumnSettings.cs │ │ ├── DocumentSettings.cs │ │ ├── ExpressionGraphSettings.cs │ │ ├── FlameGraphSettings.cs │ │ ├── FlowGraphSettings.cs │ │ ├── FunctionMarkingSettings.cs │ │ ├── FunctionTaskSettings.cs │ │ ├── GraphSettings.cs │ │ ├── OptionalColumnSettings.cs │ │ ├── PreviewPopupSettings.cs │ │ ├── ProfileDocumentMarkerSettings.cs │ │ ├── RemarkSettings.cs │ │ ├── SourceDocumentMarkerSettings.cs │ │ ├── SourceFileSettings.cs │ │ ├── TextViewSettingsBase.cs │ │ ├── TimelineSettings.cs │ │ ├── UIDiffSettings.cs │ │ ├── UISectionSettings.cs │ │ ├── UISettingsProvider.cs │ │ └── WorkspaceSettings.cs │ ├── Styles.xaml │ ├── Utilities/ │ │ ├── CallGraphUtils.cs │ │ ├── DelayedAction.cs │ │ ├── ErrorReporting.cs │ │ ├── ExtensionMethods.cs │ │ ├── LongRunningAction.cs │ │ ├── ObservableCollectionRefresh.cs │ │ ├── RelayCommand.cs │ │ ├── SectionTextSearcher.cs │ │ ├── TextSearcher.cs │ │ ├── UI/ │ │ │ ├── Behaviors.cs │ │ │ ├── ColorBrushes.cs │ │ │ ├── ColorPens.cs │ │ │ ├── ColorUtils.cs │ │ │ ├── Converters.cs │ │ │ ├── DialogCenteringHelper.cs │ │ │ ├── GridViewColumnValueSorter.cs │ │ │ ├── MouseHoverLogic.cs │ │ │ ├── PasswordHelper.cs │ │ │ ├── SortAdorner.cs │ │ │ └── WindowPlacement.cs │ │ ├── UICollectionExtensionMethods.cs │ │ ├── UIJsonUtils.cs │ │ └── Utils.cs │ ├── Windows/ │ │ ├── AboutWindow.xaml │ │ ├── AboutWindow.xaml.cs │ │ ├── DiffOpenWindow.xaml │ │ ├── DiffOpenWindow.xaml.cs │ │ ├── OptionsWindow.xaml │ │ ├── OptionsWindow.xaml.cs │ │ ├── ProfileLoadWindow.xaml │ │ ├── ProfileLoadWindow.xaml.cs │ │ ├── RecordingSession.cs │ │ ├── TextInputWindow.xaml │ │ ├── TextInputWindow.xaml.cs │ │ ├── UpdateWindow.xaml │ │ ├── UpdateWindow.xaml.cs │ │ ├── WorkspacesWindow.xaml │ │ └── WorkspacesWindow.xaml.cs │ ├── app.manifest │ └── runtimeconfig.template.json ├── ProfileExplorerUITests/ │ ├── CollectionExtensionMethodsTests.cs │ ├── GlobalUsings.cs │ ├── PDBDebugInfoProviderTests.cs │ ├── ProfileExplorerUITests.csproj │ ├── SettingsBaseTests.cs │ └── SyntheticProfileTests.cs ├── VSExtension/ │ ├── App.config │ ├── ClientInstance.cs │ ├── Commands/ │ │ ├── AttachCommand.cs │ │ ├── CommandBase.cs │ │ ├── EnableCommand.cs │ │ ├── MarkElementCommand.cs │ │ ├── MarkExpressionCommand.cs │ │ ├── MarkReferencesCommand.cs │ │ ├── MarkUsesCommand.cs │ │ ├── ShowExpressionGraphCommand.cs │ │ ├── ShowReferencesCommand.cs │ │ ├── ShowUsesCommand.cs │ │ └── UpdateIRCommand.cs │ ├── DebuggerExpression.cs │ ├── DebuggerInstance.cs │ ├── Lexer/ │ │ ├── CharSource.cs │ │ ├── CharTable.cs │ │ ├── Lexer.cs │ │ ├── TextLocation.cs │ │ └── Token.cs │ ├── Logger.cs │ ├── MouseEventProcessor.cs │ ├── NativeMethods.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── VSExtension.csproj │ ├── VSExtensionPackage.cs │ ├── VSExtensionPackage.vsct │ └── source.extension.vsixmanifest └── external/ ├── TreeListView/ │ ├── AssemblyInfo.cs │ ├── Collection.cs │ ├── LICENSE │ ├── README.md │ ├── Themes/ │ │ └── Generic.xaml │ ├── Tree/ │ │ ├── Converters.cs │ │ ├── ITreeModel.cs │ │ ├── RowExpander.cs │ │ ├── TreeList.cs │ │ ├── TreeListItem.cs │ │ └── TreeNode.cs │ ├── TreeListView.csproj │ └── TreeListView.sln ├── arm64/ │ └── config6 ├── build-capstone-arm64.cmd ├── build-capstone-debug.cmd ├── build-capstone.cmd ├── build-external-arm64.cmd ├── build-external.cmd ├── build-graphviz-arm64.cmd ├── build-graphviz-pgo-instrument-arm64.cmd ├── build-graphviz-pgo-instrument.cmd ├── build-graphviz-pgo.cmd ├── build-graphviz.cmd ├── build-tree-sitter-arm64.cmd ├── build-tree-sitter.cmd ├── config6 ├── pgo/ │ ├── copy-graphviz-arm64.cmd │ ├── copy-graphviz.cmd │ ├── train-graphviz-arm64.cmd │ ├── train-graphviz.cmd │ └── training/ │ ├── input-1032.txt │ ├── input-1691.txt │ ├── input-1864.txt │ ├── input-202.txt │ ├── input-204.txt │ ├── input-208.txt │ ├── input-213.txt │ ├── input-2131.txt │ ├── input-2148.txt │ ├── input-215.txt │ ├── input-216.txt │ ├── input-217.txt │ ├── input-218.txt │ ├── input-242.txt │ ├── input-244.txt │ ├── input-248.txt │ ├── input-250.txt │ ├── input-259.txt │ ├── input-262.txt │ ├── input-276.txt │ ├── input-303.txt │ ├── input-3219.txt │ ├── input-322.txt │ ├── input-375.txt │ ├── input-3807.txt │ ├── input-383.txt │ ├── input-436.txt │ ├── input-478.txt │ ├── input-485.txt │ ├── input-568.txt │ ├── input-583.txt │ └── input-741.txt └── tree-sitter/ ├── Makefile ├── tree-sitter-c-sharp.def └── tree-sitter-rust.def ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/codeql.yml ================================================ # For most projects, this workflow file will not need changing; you simply need # to commit it to your repository. # # You may wish to alter this file to override the set of languages analyzed, # or to provide custom queries or build logic. # # ******** NOTE ******** # We have attempted to detect the languages in your repository. Please check # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # name: "CodeQL" on: push: branches: [ "main" ] pull_request: branches: [ "main" ] schedule: - cron: '31 19 * * 2' jobs: analyze: name: Analyze (${{ matrix.language }}) # Runner size impacts CodeQL analysis time. To learn more, please see: # - https://gh.io/recommended-hardware-resources-for-running-codeql # - https://gh.io/supported-runners-and-hardware-resources # - https://gh.io/using-larger-runners (GitHub.com only) # Consider using larger runners or machines with greater resources for possible analysis time improvements. runs-on: ${{ 'windows-latest' }} timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} permissions: # required for all workflows security-events: write # required to fetch internal or private CodeQL packs packages: read # only required for workflows in private repositories actions: read contents: read strategy: fail-fast: false matrix: include: - language: c-cpp build-mode: manual - language: csharp build-mode: autobuild # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' # Use `c-cpp` to analyze code written in C, C++ or both # Use 'java-kotlin' to analyze code written in Java, Kotlin or both # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages steps: - name: Checkout repository uses: actions/checkout@v4 with: submodules: 'recursive' # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} build-mode: ${{ matrix.build-mode }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs # queries: security-extended,security-and-quality # If the analyze step fails for one of the languages you are analyzing with # "We were unable to automatically build your code", modify the matrix above # to set the build mode to "manual" for that language. Then modify this step # to build your code. # ℹ️ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - if: matrix.build-mode == 'manual' shell: cmd run: | build.cmd - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 with: category: "/language:${{matrix.language}}" ================================================ FILE: .github/workflows/dotnet-desktop.yml ================================================ # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # This workflow will build, test, sign and package a WPF or Windows Forms desktop application # built on .NET Core. # To learn how to migrate your existing application to .NET Core, # refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework # # To configure this workflow: # # 1. Configure environment variables # GitHub sets default environment variables for every workflow run. # Replace the variables relative to your project in the "env" section below. # # 2. Signing # Generate a signing certificate in the Windows Application # Packaging Project or add an existing signing certificate to the project. # Next, use PowerShell to encode the .pfx file using Base64 encoding # by running the following Powershell script to generate the output string: # # $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte # [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt' # # Open the output file, SigningCertificate_Encoded.txt, and copy the # string inside. Then, add the string to the repo as a GitHub secret # and name it "Base64_Encoded_Pfx." # For more information on how to configure your signing certificate for # this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing # # Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key". # See "Build the Windows Application Packaging project" below to see how the secret is used. # # For more information on GitHub Actions, refer to https://github.com/features/actions # For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications, # refer to https://github.com/microsoft/github-actions-for-desktop-apps name: .NET Core Desktop on: push: branches: [ "main" ] pull_request: branches: [ "main" ] jobs: build: strategy: matrix: configuration: [Debug, Release] runs-on: windows-latest # For a list of available runner types, refer to # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on env: Solution_Name: src/ProfileExplorer.sln # Replace with your solution name, i.e. MyWpfApp.sln. Test_Project_Path: your-test-project-path # Replace with the path to your test project, i.e. MyWpfApp.Tests\MyWpfApp.Tests.csproj. Wap_Project_Directory: your-wap-project-directory-name # Replace with the Wap project directory relative to the solution, i.e. MyWpfApp.Package. Wap_Project_Path: your-wap-project-path # Replace with the path to your Wap project, i.e. MyWpf.App.Package\MyWpfApp.Package.wapproj. steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 # Install the .NET Core workload - name: Install .NET Core uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild - name: Setup MSBuild.exe uses: microsoft/setup-msbuild@v2 # Execute unit tests for Core and UI projects - name: Execute unit tests run: | dotnet test src\ProfileExplorerCoreTests\ProfileExplorerCoreTests.csproj dotnet test src\ProfileExplorerUITests\ProfileExplorerUITests.csproj # Build the solution - name: Build debug run: dotnet publish -c "Debug" src\ProfileExplorerUI\ProfileExplorerUI.csproj env: Configuration: ${{ matrix.configuration }} - name: Build release run: dotnet publish -c "Release" src\ProfileExplorerUI\ProfileExplorerUI.csproj env: Configuration: ${{ matrix.configuration }} ================================================ FILE: .github/workflows/installer.yml ================================================ # This workflow uses actions that are not certified by GitHub. # They are provided by a third-party and are governed by # separate terms of service, privacy policy, and support # documentation. # This workflow will build, test, sign and package a WPF or Windows Forms desktop application # built on .NET Core. # To learn how to migrate your existing application to .NET Core, # refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework # # To configure this workflow: # # 1. Configure environment variables # GitHub sets default environment variables for every workflow run. # Replace the variables relative to your project in the "env" section below. # # 2. Signing # Generate a signing certificate in the Windows Application # Packaging Project or add an existing signing certificate to the project. # Next, use PowerShell to encode the .pfx file using Base64 encoding # by running the following Powershell script to generate the output string: # # $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte # [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt' # # Open the output file, SigningCertificate_Encoded.txt, and copy the # string inside. Then, add the string to the repo as a GitHub secret # and name it "Base64_Encoded_Pfx." # For more information on how to configure your signing certificate for # this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing # # Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key". # See "Build the Windows Application Packaging project" below to see how the secret is used. # # For more information on GitHub Actions, refer to https://github.com/features/actions # For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications, # refer to https://github.com/microsoft/github-actions-for-desktop-apps name: Installer on: workflow_dispatch: jobs: build: strategy: matrix: configuration: [Release] runs-on: windows-latest # For a list of available runner types, refer to # https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on env: Solution_Name: src/ProfileExplorer.sln # Replace with your solution name, i.e. MyWpfApp.sln. steps: - name: Checkout uses: actions/checkout@v4 with: submodules: 'recursive' # Install the .NET Core workload - name: Install .NET Core uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x # Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild - name: Setup MSBuild.exe uses: microsoft/setup-msbuild@v2 - name: Install Inno Setup shell: cmd run: choco install innosetup # Build the project and installer - name: Build x64 shell: cmd working-directory: installer\x64 run: call prepare-out.cmd env: Configuration: ${{ matrix.configuration }} - name: Create x64 installer shell: cmd working-directory: installer\x64 run: call prepare-installer.cmd env: Configuration: ${{ matrix.configuration }} - name: Build ARM64 shell: cmd working-directory: installer\arm64 run: call prepare-out.cmd env: Configuration: ${{ matrix.configuration }} - name: Create ARM64 installer shell: cmd working-directory: installer\arm64 run: call prepare-installer.cmd env: Configuration: ${{ matrix.configuration }} - uses: actions/upload-artifact@v4 with: name: Upload x64 output path: installer\x64\out\**\* - uses: actions/upload-artifact@v4 with: name: Upload ARM64 output path: installer\arm64\out\**\* - uses: actions/upload-artifact@v4 with: name: Upload x64 installer path: installer\x64\*.exe - uses: actions/upload-artifact@v4 with: name: Upload ARM64 installer path: installer\arm64\*.exe ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files *.rsuser *.suo *.user *.userosscache *.sln.docstates *.tlog *.lib *.dll *.exp *.recipe *.exe *.gz .vshistory/ # Setup files installer/out* installer/publish* # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Mono auto generated files mono_crash.* # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ [Aa][Rr][Mm]/ [Aa][Rr][Mm]64/ !installer/*/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ [Ll]ogs/ vcpkg/ # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # Visual Studio 2017 auto generated files Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUnit *.VisualState.xml TestResult.xml nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ # .NET Core project.lock.json project.fragment.lock.json artifacts/ # StyleCop StyleCopReport.xml # Files built by Visual Studio *_i.c *_p.c *_h.h *.ilk *.meta *.obj *.iobj *.pch *.pdb *.ipdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *_wpftmp.csproj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # Visual Studio Trace Files *.e2e # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # AxoCover is a Code Coverage Tool .axoCover/* !.axoCover/settings.json # Visual Studio code coverage results *.coverage *.coveragexml # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # NuGet Symbol Packages *.snupkg # The packages folder can be ignored because of Package Restore **/[Pp]ackages/* # except build/, which is used as an MSBuild target. !**/[Pp]ackages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/[Pp]ackages/repositories.config # NuGet v3's project.json files produces more ignorable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt *.appx *.appxbundle *.appxupload # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !?*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings orleans.codegen.cs # Including strong name files can present a security risk # (https://github.com/github/gitignore/pull/2483#issue-259490424) #*.snk # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm ServiceFabricBackup/ *.rptproj.bak # SQL Server files *.mdf *.ldf *.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings *.rptproj.rsuser *- [Bb]ackup.rdl *- [Bb]ackup ([0-9]).rdl *- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat node_modules/ # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) *.vbw # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # CodeRush personal settings .cr/personal # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc # Cake - Uncomment if you are using it # tools/** # !tools/packages.config # Tabs Studio *.tss # Telerik's JustMock configuration file *.jmconfig # BizTalk build output *.btp.cs *.btm.cs *.odx.cs *.xsd.cs # OpenCover UI analysis results OpenCover/ # Azure Stream Analytics local run output ASALocalRun/ # MSBuild Binary and Structured Log *.binlog # NVidia Nsight GPU debugger configuration file *.nvuser # MFractors (Xamarin productivity tool) working folder .mfractor/ # Local History for Visual Studio .localhistory/ # BeatPulse healthcheck temp database healthchecksdb # Backup folder for Package Reference Convert tool in Visual Studio 2017 MigrationBackup/ # Ionide (cross platform F# VS Code tools) working folder .ionide/ src/.idea src/GrpcCppLib/ReleaseStaticLib # Include test data files (allow all file types in TestData folder) !/src/ProfileExplorerCoreTests/TestData/** # Include some pre-built binaries !/src/external/* !/src/external/arm64/* # Don't include MCP-generated temporary files src/tmp/* ================================================ FILE: .gitmodules ================================================ [submodule "src/external/capstone"] path = src/external/capstone url = https://github.com/capstone-engine/capstone.git [submodule "src/external/graphviz"] path = src/external/graphviz url = https://github.com/bgn64/graphviz.git [submodule "src/external/tree-sitter/csharp-tree-sitter"] path = src/external/tree-sitter/csharp-tree-sitter url = https://github.com/bgn64/csharp-tree-sitter.git [submodule "src/external/tree-sitter/tree-sitter-c-sharp"] path = src/external/tree-sitter/tree-sitter-c-sharp url = https://github.com/tree-sitter/tree-sitter-c-sharp.git [submodule "src/external/tree-sitter/tree-sitter-rust"] path = src/external/tree-sitter/tree-sitter-rust url = https://github.com/tree-sitter/tree-sitter-rust.git ================================================ FILE: AGENTS.md ================================================ # Agent Instructions for Profile Explorer ## Git Policy **NEVER commit or git add without explicit user permission.** When asked for a commit message, provide the message text only - do not execute `git commit` or `git add`. ## Building **IMPORTANT: Always use Release configuration (`-c Release`). The user runs Release builds, not Debug.** ### Before Building Always check if ProfileExplorer is running before attempting a build - it locks the DLLs: ```bash tasklist /FI "IMAGENAME eq ProfileExplorer.exe" 2>nul | find /i "ProfileExplorer" ``` If running, ask the user to close it before building. ### Build Commands ```bash # Full UI build (Release) dotnet build "C:/src/profile-explorer/src/ProfileExplorerUI/ProfileExplorerUI.csproj" -c Release # Core library only (faster, for checking compilation) dotnet build "C:/src/profile-explorer/src/ProfileExplorerCore/ProfileExplorerCore.csproj" -c Release ``` ### Iterative Development For faster iteration when ProfileExplorer is running: 1. Build just the Core project first to check for compilation errors 2. Ask user to close ProfileExplorer 3. Build the full UI project 4. User can relaunch and test The Core project build is much faster (~2-3s) and doesn't require ProfileExplorer to be closed. ## Diagnostic Logging Enable diagnostic logging with: ```powershell $env:PROFILE_EXPLORER_DEBUG = "1" ``` Logs are written to `%TEMP%\ProfileExplorer_Diagnostic_*.log` ### Analyzing Logs Use the analysis script (don't read raw logs - they're ~12MB): ```powershell C:\src\profile-explorer\scripts\Analyze-DiagnosticLog.ps1 -LogPath ``` Or grep for specific patterns: ```bash grep -i "pattern" | head -30 ``` ## Key Files ### Symbol Loading Performance - `ETWProfileDataProvider.cs` - Main symbol loading orchestration (~lines 759-1150) - `SymbolFileSourceSettings.cs` - Symbol settings including timeouts, filters, caching - `PEBinaryInfoProvider.cs` - Binary file downloading - `PDBDebugInfoProvider.cs` - PDB file downloading ### Important Settings (SymbolFileSourceSettings) - `SymbolServerTimeoutSeconds` - Normal timeout (default: 10s) - `BellwetherTestEnabled` - Test symbol server health before bulk downloads - `BellwetherTimeoutSeconds` - Timeout for bellwether test (default: 5s) - `DegradedTimeoutSeconds` - Reduced timeout when server is slow (default: 3s) - `RejectPreviouslyFailedFiles` - Negative caching for failed downloads - `WindowsPathFilterEnabled` - Skip non-Windows binaries - `CompanyFilterEnabled` - Only load symbols for specific companies (e.g., Microsoft) ================================================ FILE: CLAUDE.md ================================================ # Claude Code Instructions for Profile Explorer ## Git Policy **NEVER commit or git add without explicit user permission.** When asked for a commit message, provide the message text only - do not execute `git commit` or `git add`. ## Building **IMPORTANT: Always use Release configuration (`-c Release`). The user runs Release builds, not Debug.** ```bash # Full UI build (Release) dotnet build "C:/src/profile-explorer/src/ProfileExplorerUI/ProfileExplorerUI.csproj" -c Release # Core library only (faster, for checking compilation) dotnet build "C:/src/profile-explorer/src/ProfileExplorerCore/ProfileExplorerCore.csproj" -c Release ``` ### Before Building Check if ProfileExplorer is running before attempting a build - it locks the DLLs: ```bash tasklist /FI "IMAGENAME eq ProfileExplorer.exe" 2>nul | find /i "ProfileExplorer" ``` If running, ask the user to close it before building. ## See Also See `AGENTS.md` for more detailed instructions including: - Diagnostic logging setup - Key files for symbol loading - Important settings ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Microsoft Open Source Code of Conduct This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). Resources: - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns - Employees can reach out at [aka.ms/opensource/moderation-support](https://aka.ms/opensource/moderation-support) ================================================ FILE: CONTRIBUTING.MD ================================================ # Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repositories using our CLA. This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. ================================================ FILE: CodeQL.yml ================================================ path_classifiers: library: - "**/src/external" ================================================ FILE: LICENSE.TXT ================================================ MIT License Copyright (c) Microsoft Corporation. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE ================================================ FILE: NOTICE.md ================================================ NOTICES This software incorporates material from third parties as listed below. --------------------------------------------------------- Autoupdater.NET.Official - MIT Copyright 2012-2024 RBSoft Copyright (c) 2012-2024 RBSoft Copyright 2012-2024 RBSoft AutoUpdater.NET MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- AvalonEdit - MIT Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Core - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Azure.Identity - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- ClosedXML - MIT Copyright 2013 The Carlito Project MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- ClosedXML.Parser - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- CS-Script.Core - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- DiffPlex - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Dirkster.AvalonDock - MS-PL (c) Microsoft 2023 Ms-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- Dirkster.AvalonDock.Themes.Aero - MS-PL (c) Microsoft 2023 Ms-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- Dirkster.AvalonDock.Themes.Metro - MS-PL (c) Microsoft 2023 Ms-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- Dirkster.AvalonDock.Themes.VS2010 - MS-PL (c) Microsoft 2023 Ms-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- Dirkster.AvalonDock.Themes.VS2013 - MS-PL (c) Microsoft 2023 Ms-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- DotNetProjects.Extended.Wpf.Toolkit - MS-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- DotNetProjects.WpfToolkit.Input - MS-PL Microsoft Public License (Ms-PL) This license governs use of the accompanying software. If you use the software, you accept this license. If you do not accept the license, do not use the software. 1. Definitions The terms "reproduce," "reproduction," "derivative works," and "distribution" have the same meaning here as under U.S. copyright law. A "contribution" is the original software, or any additions or changes to the software. A "contributor" is any person that distributes its contribution under this license. "Licensed patents" are a contributor's patent claims that read directly on its contribution. 2. Grant of Rights (A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create. (B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software. 3. Conditions and Limitations (A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks. (B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically. (C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software. (D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license. (E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees, or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement. --------------------------------------------------------- --------------------------------------------------------- protobuf-net - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- protobuf-net.Core - Apache-2.0 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Google.Protobuf - BSD-3-Clause Copyright 2015, Google Inc. Copyright 2015, Google Inc. Protocol Buffers Binary Serialization Format Google Copyright (c) . All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- Grpc - Apache-2.0 Copyright 2015 The gRPC Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Grpc.Core - Apache-2.0 (c) 2006 Entrust, Inc. Copyright 2015 The gRPC (c) 1999 Entrust.net Limited (c) 2009 Entrust, Inc. - for (c) 2012 Entrust, Inc. - for (c) 2015 Entrust, Inc. - for Copyright (c) by P.J. Plauger Copyright 1995-2022 Mark Adler Copyright 1995-2022 Jean-loup Gailly and Mark Adler (c) 2006 Entrust, Inc. Label Entrust Root Certification (c) 1999 Entrust.net Limited Label Entrust.net Premium 2048 Secure Server CA Serial Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Grpc.Core.Api - Apache-2.0 Copyright 2019 The gRPC Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- Grpc.Tools - Apache-2.0 Copyright 2018 The gRPC Copyright 2008 Google Inc. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- HtmlAgilityPack - MIT Copyright ZZZ Projects Inc. Copyright (c) ZZZ Projects Inc. Copyright ZZZ Projects Inc. Html Agility Pack MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Diagnostics.Tracing.TraceEvent - MIT Copyright Microsoft 2010 (c) Microsoft Corporation Copyright 1995-2022 Mark Adler Copyright Microsoft 2010 TraceEvent Copyright Microsoft 2010 Serialization MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- Microsoft.Xaml.Behaviors.Wpf - MIT (c) Microsoft Corporation MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OxyPlot.Core - MIT Copyright (c) 2014 OxyPlot (c) 2009 by Charles Petzold Copyright GetNearestHit Portrait MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- OxyPlot.Wpf - MIT MIT License Copyright (c) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- tree-sitter - MIT https://github.com/tree-sitter#readme Copyright (c) 2014-2023 Max Brunsfeld, Damien Guard, Amaan Qureshi, and contributors The MIT License (MIT) Copyright (c) 2014-2023 Max Brunsfeld, Damien Guard, Amaan Qureshi, and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- tree-sitter-cpp - MIT https://github.com/tree-sitter/tree-sitter-cpp#readme Copyright (c) 2014 Max Brunsfeld Copyright (c) 2021, tree-sitter-cpp The MIT License (MIT) Copyright (c) 2014 Max Brunsfeld Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- tree-sitter-c-sharp - MIT https://github.com/tree-sitter/tree-sitter-c-sharp#readme Copyright (c) 2014-2023 Max Brunsfeld, Damien Guard, Amaan Qureshi, and contributors The MIT License (MIT) Copyright (c) 2014-2023 Max Brunsfeld, Damien Guard, Amaan Qureshi, and contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- tree-sitter-rust - MIT https://github.com/tree-sitter/tree-sitter-rust#readme The MIT License (MIT) Copyright (c) 2017 Maxim Sokolov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. --------------------------------------------------------- --------------------------------------------------------- graphviz - Eclipse Public License - v 1.0 https://gitlab.com/graphviz/graphviz#readme Eclipse Public License - v 1.0 THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 1. DEFINITIONS "Contribution" means: a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and b) in the case of each subsequent Contributor: i) changes to the Program, and ii) additions to the Program; where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program. "Contributor" means any person or entity that distributes the Program. "Licensed Patents" mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program. "Program" means the Contributions distributed in accordance with this Agreement. "Recipient" means anyone who receives the Program under this Agreement, including all Contributors. 2. GRANT OF RIGHTS a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form. b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder. c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program. d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement. 3. REQUIREMENTS A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that: a) it complies with the terms and conditions of this Agreement; and b) its license agreement: i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose; ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits; iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange. When the Program is made available in source code form: a) it must be made available under this Agreement; and b) a copy of this Agreement must be included with each copy of the Program. Contributors may not remove or alter any copyright notices contained within the Program. Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution. 4. COMMERCIAL DISTRIBUTION Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense. For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages. 5. NO WARRANTY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. 6. DISCLAIMER OF LIABILITY EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 7. GENERAL If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable. If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed. All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive. Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved. This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation. Primary contact. Please submit patches or enhancements to https://gitlab.com/graphviz/graphviz --------------- Primary Authors: (In alphabetical order.) John Ellson Emden Gansner Yifan Hu Stephen North Auxiliary Authors: (In alphabetical order.) Don Caldwell David Dobkin Tim Dwyer Eleftherios Koutsofios Kiem-Phong Vo Gordon Woodhull --------------- See https://graphviz.org/credits/ for further information. --------------------------------------------------------- --------------------------------------------------------- capstone - BSD https://github.com/capstone-engine/capstone#readme This is the software license for Capstone disassembly framework. Capstone has been designed & implemented by Nguyen Anh Quynh See http://www.capstone-engine.org for further information. Copyright (c) 2013, COSEINC. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the developer(s) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------- --------------------------------------------------------- TreeListView - Apache-2.0 https://github.com/hazzik/TreeListView#readme Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --------------------------------------------------------- --------------------------------------------------------- octicons - MIT https://github.com/primer/octicons#readme MIT License Copyright (c) 2024 GitHub Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ## Profile Explorer [![Static Badge](https://img.shields.io/badge/Download-x64-orange)](https://github.com/microsoft/profile-explorer/releases/latest/download/profile_explorer_installer_x64.exe) [![Static Badge](https://img.shields.io/badge/Download-ARM64-orange)](https://github.com/microsoft/profile-explorer/releases/latest/download/profile_explorer_installer_arm64.exe) [![Static Badge](https://img.shields.io/badge/Documentation-blue)](https://microsoft.github.io/profile-explorer/) Profile Explorer is a tool for viewing CPU profiling traces collected through the [Event Tracing for Windows (ETW)](https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-) infrastructure on machines with x64 and ARM64 CPUs. Its focus is on presenting the slowest parts of the profiled application through an easy-to-use but detailed UI consisting of several views, such as a hot function list, flame graph, call tree, timeline, assembly code view, and source file view. The application can be viewed as a companion to [Windows Performance Analyzer (WPA)](https://learn.microsoft.com/en-us/windows-hardware/test/wpt/windows-performance-analyzer), offering some unique features based on the binary analysis it performs and the IDE-like UI, such as easy navigation through disassembly, improved mapping to source lines, displaying the function control-flow graph, viewing of multiple functions at the same time, marking, searching, filtering and much more. One of the app's key advantages is its performance. It loads traces fast and offers near-instant UI interaction, even for very large traces (over 10 GB ETL files). Most profile processing steps and algorithms are multi-threaded and don't block the UI. #### Summary, Flame Graph and Timeline views of a trace: image #### Assembly, Source File and Flow Graph views of a function: image #### Video introduction https://github.com/user-attachments/assets/d9a281d3-dc92-4cbe-a3e5-80c4588676a2 ### ⬇️ Download Installers for the latest version: - [x64 installer](https://github.com/microsoft/profile-explorer/releases/latest/download/profile_explorer_installer_x64.exe) - [ARM64 installer](https://github.com/microsoft/profile-explorer/releases/latest/download/profile_explorer_installer_arm64.exe) Use the ARM64 installer if you have a machine with an ARM64 CPU, since it includes a native build of the app (no emulation), otherwise use the x64 installer. Note that the x64 app can open traces taken on ARM64 machines and vice versa. The app also has a built-in auto-update feature that will notify you when a new version is released and offer to download and install it. The installers for previous versions can be downloaded from the [Releases](https://github.com/microsoft/profile-explorer/releases) page. ### 📖 Documentation The documentation pages are available here: #### [https://microsoft.github.io/profile-explorer](https://microsoft.github.io/profile-explorer/) The app also has a built-in *Help panel* that can display the same documentation. Most views have a *question mark* icon in the upper-right corner that opens the *Help panel* on the view's documentation page. ### 🛠️ Building To build the application and its external dependencies, ensure the following build tools are installed on a Windows 11 machine: - recent Visual Studio 2022 with the following workflows: - *.NET desktop development* - *Desktop development with C++* - *C++ ARM64/ARM64EC build tools (Latest)* - for native ARM64 builds - [.NET 8.0 SDK ](https://dotnet.microsoft.com/en-us/download/dotnet/8.0) (should be installed by Visual Studio 2022 already) From a an *admin* command-line window, run: - ```build.cmd [debug|release]``` for an x64 build. - ```build-arm64.cmd [debug|release]``` for a native ARM64 build. The debug or release build mode is used for the main project; external dependencies are always built in release mode. The admin mode for the command-line is required to register msdia140.dll using regsvr32; it needs to be done once on a machine. The build script will update the git submodules, build the main project and external dependencies, and then copy the built dependencies and other resources to the output directory. The output directory with *ProfileExplorer.exe* will be found at: ```src\ProfileExplorerUI\bin\[Debug|Release]\net8.0-windows```. After the initial build, open the solution file ```src\ProfileExplorer.sln``` and use the *ProfileExplorerUI* project as the build and startup target. ### 📦 Publishing and creating the installer To publish the application and create an installer, from a command-line window run: - ```installer\x64\prepare.cmd``` for an x64 build. - ```installer\arm64\prepare.cmd``` for a native arm64 build. This will build the main project as a self-contained application, build the external dependencies, and create the installer executable, with build output files found at: - ```installer\[x64|arm64]\out``` - ```installer\[x64|arm64]\profile_explorer_installer_VERSION.exe``` Currently [InnoSetup](https://jrsoftware.org/isdl.php) is used to create the installer and it must be already installed on the machine and *iscc.exe* found on *PATH*. ### 📑 Project structure Below is a high-level overview of the main parts of the application. | Location | Description | | --- | --- | | src/ProfileExplorerUI | The main project and application UI, implemented using WPF. | | src/ProfileExplorerCore | The UI-independent part that defines the intermediate representation (IR), parsing functions, Graphviz and Tree Sitter support, various data structures, algorithms and utilities. | | src/ProfileExplorerUITests | Unit tests for the ProfileExplorerUI project. | | src/ProfileExplorerCoreTests | Unit tests for the ProfileExplorerCore project. | | src/ManagedProfiler | .NET JIT profiler extension for capturing JIT output assembly code. | | src/PDBViewer | A small utility displaying the contents of PDB debug info files, implemented using WinForms. | | src/VSExtension | A Visual Studio extension that connects to the application. Not used for profiling functionality. | | src/GrpcLib | Defines the GRPC protobuf format used by the Visual Studio extension to communicate with the application. Not used for profiling functionality. | The following projects are build from source, as either x64 or native arm64 binaries. | Location | Description | | --- | --- | | src/external/capstone | [Capstone](https://github.com/capstone-engine/capstone) disassembly framework, submodule. | | src/external/graphviz | [Graphviz](https://gitlab.com/graphviz/graphviz) graph visualization tools, submodule. | | src/external/tree-sitter | [Tree-sitter](https://tree-sitter.github.io/tree-sitter/) parser generator, with support for C/C++, C# and Rust, submodules. | | src/external/TreeListView | [TreeListView](https://github.com/hazzik/TreeListView), WPF tree list view control. | ### Profiling architecture - Profiling UI compoments are independent from the profiling trace source. - Loading the trace produces a set of profile samples and associated call stacks – building blocks for the call tree, flame graph, function list, assembly view. - Debuging info (PDB) files are downloaded in parallel, source line info read on-demand per function. - Binary disassembly done on-demand per function. - Initial trace processing and subsequent filtering is multi-threaded. - UI updates are mostly async and multi-threaded. - Opening binaries without a profiling trace is supported. ### History The application started as a tool for helping compiler developers interact with and better understand a compiler's [intermediate representation (IR)](https://en.wikipedia.org/wiki/Intermediate_representation). After adding simple support for viewing profile traces, it gradually gained more profiling features and primarily became a profile viewer. The tool's initial focus on compilers has led to some distinctive features, such as the ability to parse assembly code into an internal IR. This enables an interactive view of assembly code and the visualization of control-flow graphs, for example. ### Contributing This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. ### Trademarks This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. ================================================ FILE: SECURITY.md ================================================ ## Security Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin). If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp). You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. ## Preferred Languages We prefer all communications to be in English. ## Policy Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). ================================================ FILE: build-arm64.cmd ================================================ @echo off setlocal set _BUILD_TARGET="src\ProfileExplorerUI\ProfileExplorerUI.csproj" set _FRAMEWORK_PATH=net8.0-windows set _PROFILER_PATH="src\ManagedProfiler" set _EXTERNALS_PATH="src\external" set _EXTERNALS_PATH_ARM64="..\..\src\external\arm64" set _RESOURCES_PATH="..\..\resources" if "%1"=="" ( echo "Usage: build.bat [debug|release]" echo "Defaulting to Release mode..." ) set _CONFIG=%1 if /I "%_CONFIG%"=="debug" ( set _BUILD_CONFIG=Debug echo Building in Debug mode... ) else if /I "%_CONFIG%"=="release" ( set _BUILD_CONFIG=Release echo Building in Release mode... ) else ( set _BUILD_CONFIG=Release echo Building in Release mode... ) set _OUT_PATH="src\ProfileExplorerUI\bin\%_BUILD_CONFIG%\%_FRAMEWORK_PATH%" echo %_OUT_PATH% rem Update git submodules for external projects git submodule update --init --recursive rem Build main project dotnet restore %_BUILD_TARGET% dotnet build -c %_BUILD_CONFIG% %_BUILD_TARGET% /p:Platform=AnyCPU for /f "delims=" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -all -prerelease -property installationPath') do set _VS=%%i set _VS_ENV=%_VS%\VC\Auxiliary\Build\vcvarsamd64_arm64.bat call "%_VS_ENV%" rem Build external projects pushd %_EXTERNALS_PATH% call build-external-arm64.cmd popd rem Build managed profiler msbuild %_PROFILER_PATH%\ManagedProfiler.vcxproj /t:Rebuild /p:Configuration=Release /p:Platform=arm64 copy %_PROFILER_PATH%\arm64\Release\ManagedProfiler.dll %_OUT_PATH% rem Copy over native DLLs and other resources xcopy %_RESOURCES_PATH% %_OUT_PATH% /i /c /e /y xcopy %_EXTERNALS_PATH_ARM64%\*.dll %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH_ARM64%\config6 %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH%\tree-sitter\build_arm64\*.dll %_OUT_PATH% /i /c /y copy %_EXTERNALS_PATH%\capstone\build_arm64\Release\capstone.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\cmd\dot\Release\dot.exe %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\cdt\Release\cdt.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\cgraph\Release\cgraph.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\gvc\Release\gvc.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\pathplan\Release\pathplan.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\xdot\Release\xdot.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\plugin\core\Release\gvplugin_core.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\plugin\dot_layout\Release\gvplugin_dot_layout.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\zlib1.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\libexpat.dll %_OUT_PATH% rem Register msdia140.dll regsvr32 /s %_OUT_PATH%\msdia140.dll ================================================ FILE: build.cmd ================================================ @echo off setlocal set _BUILD_TARGET="src\ProfileExplorerUI\ProfileExplorerUI.csproj" set _FRAMEWORK_PATH=net8.0-windows set _PROFILER_PATH="src\ManagedProfiler" set _EXTERNALS_PATH="src\external" set _RESOURCES_PATH="..\..\resources" if "%1"=="" ( echo "Usage: build.bat [debug|release]" echo "Defaulting to Release mode..." ) set _CONFIG=%1 if /I "%_CONFIG%"=="debug" ( set _BUILD_CONFIG=Debug echo Building in Debug mode... ) else if /I "%_CONFIG%"=="release" ( set _BUILD_CONFIG=Release echo Building in Release mode... ) else ( set _BUILD_CONFIG=Release echo Building in Release mode... ) set _OUT_PATH="src\ProfileExplorerUI\bin\%_BUILD_CONFIG%\%_FRAMEWORK_PATH%" echo %_OUT_PATH% rem Update git submodules for external projects git submodule update --init --recursive rem Build main project dotnet restore %_BUILD_TARGET% dotnet build -c %_BUILD_CONFIG% %_BUILD_TARGET% /p:Platform=AnyCPU for /f "delims=" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -all -prerelease -property installationPath') do set _VS=%%i set _VS_ENV=%_VS%\VC\Auxiliary\Build\vcvars64.bat call "%_VS_ENV%" rem Build external projects pushd %_EXTERNALS_PATH% call build-external.cmd popd rem Build managed profiler msbuild %_PROFILER_PATH%\ManagedProfiler.vcxproj /t:Rebuild /p:_CONFIG=Release /p:Platform=x64 rem Copy over native DLLs and other resources xcopy %_RESOURCES_PATH% %_OUT_PATH% /i /c /e /y xcopy %_EXTERNALS_PATH%\config6 %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH%\*.dll %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH%\tree-sitter\build\*.dll %_OUT_PATH% /i /c /y copy %_EXTERNALS_PATH%\capstone\build\Release\capstone.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\cmd\dot\Release\dot.exe %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\cdt\Release\cdt.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\cgraph\Release\cgraph.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\gvc\Release\gvc.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\pathplan\Release\pathplan.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\xdot\Release\xdot.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\plugin\core\Release\gvplugin_core.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\plugin\dot_layout\Release\gvplugin_dot_layout.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\zlib1.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\libexpat.dll %_OUT_PATH% rem Register msdia140.dll regsvr32 /s %_OUT_PATH%\msdia140.dll ================================================ FILE: docs/build.cmd ================================================ pip install mkdocs pip install mkdocs-material mkdocs build ================================================ FILE: docs/docs/about.md ================================================ #### Overview Profile Explorer is a tool for viewing CPU profiling traces collected through the [Event Tracing for Windows (ETW)]((https://learn.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-)) infrastructure on machines with x64 and ARM64 CPUs. Its focus is on presenting the slowest parts of the profiled application through an easy-to-use but detailed UI consisting of several views, such as slow functions list, flame graph, call tree, timeline, assembly code view, and *Source File* view. The app offers some unique features based on the binary analysis it performs and the IDE-like UI, such as easy navigation through disassembly, improved mapping to source lines, displaying the function [control-flow graph](https://en.wikipedia.org/wiki/Control-flow_graph), viewing of multiple functions at the same time, marking, searching, filtering and much more. One of the app's key advantages is its performance. It loads traces fast and offers near-instant UI interaction, even for very large traces (over 10 GB ETL files). Most profile processing steps and algorithms are multi-threaded and don't block the UI. #### Automatic updates The app includes an auto-update feature that notifies you when a new version is available and offers to download and install it. When the app starts, if a new version is available, an *Update Available* button is displayed in the status bar. *Click* on it to see the release notes and install the update. ![](img/update-ckeck.png){:style="width:400px"} #### Download Installers for the latest version: - [x64 installer](https://github.com/microsoft/profile-explorer/releases/latest/download/profile_explorer_installer_x64.exe) - [ARM64 installer](https://github.com/microsoft/profile-explorer/releases/latest/download/profile_explorer_installer_arm64.exe) Use the ARM64 installer if you have a machine with an ARM64 CPU, since it includes a native build of the app (no emulation), otherwise use the x64 installer. Note that the x64 app can open traces recorded on ARM64 machines and vice versa. The installers for previous versions can be downloaded from the [Releases](https://github.com/microsoft/profile-explorer/releases) page. ================================================ FILE: docs/docs/assembly-view.md ================================================ #### Overview The Assembly view shows the function's machine code after disassembly, with syntax highlighting for x86_64/ARM64 architectures. The view is interactive, with the text being parsed into instructions with operands and higher-level constructs such as [basic blocks](https://en.wikipedia.org/wiki/Basic_block) and loops are recovered. The assembly instructions are augmented with annotations from the debug info files, such as source line numbers and inlinees, and combined with the execution time from the profile trace. [![Profiling UI screenshot](img/assembly-view_1164x473.png)](img/assembly-view_1164x473.png){:target="_blank"} The view has four parts: - a main toolbar at the top, with general action buttons. - a secondary toolbar underneath with profiling-specific info and action buttons. - the text view with the function's assembly. - several columns on the right side with the profiling data for each instruction. If CPU performance counters are found and loaded from the trace, the additional columns with metrics and the counters are appended after the last column. ???+ note When a function is opened in the *Assembly* view, its corresponding source file is automatically loaded in the *Source File* view and its [control-flow graph (CFG)](https://en.wikipedia.org/wiki/Control-flow_graph) displayed in the *Flow Graph* view.
[![Profiling UI screenshot](img/assembly-source_1073x279.png)](img/assembly-source_1073x279.png){:target="_blank"} #### Assembly text view The function assembly area can be treated a read-only code editor. Each line corresponds to one instruction, with the following values from left to right: [![Profiling UI screenshot](img/assembly-line_1018x41.png)](img/assembly-line_1018x41.png){:target="_blank"} - instruction number (line number in the text). - optional marking icon for call targets. - instruction virtual address (blue text). - instruction opcode (bold text). - an optional list of instruction operands. - source line number associated with the instruction, obtained from the debug info (gray text). - inlinees (inlined functions) associated with the instruction, obtained from the debug info (green text). - profiling data columns, such as the execution time percentage and value. ##### Source lines The debug info files usually contain a mapping between the source line numbers and the instructions that were generated for those lines. The source line number is appended at the end of an instruction if available. Note that the accuracy of this mapping usually depends on the compiler optimization level, with higher levels being less accurate or even lacking the mapping for some instructions. *Hovering* over the line number shows a tooltip with the name and path of the source file. To copy this info to clipboard, first *click* the line number, then press *Ctrl+C*. [![Profiling UI screenshot](img/assemlby-line-number_816x106.png){: style="width:500px"}](img/assemlby-line-number_816x106.png){:target="_blank"} ???+ note *Click* on an instruction selects and brings into view its corresponding source line in the *Source File* view and its basic block in the *Flow Graph* view. ##### Inlinees When a function is inlined, the compiler may keep extra details about the function code that is being inlined so that the original location of an instruction can be saved into the debug info file. If available, the inlined functions are added after the source line number, separated by the "|" letter. For example, if a function contains a call chain like "foo() -> bar()", and both calls are inlined, the final instructions will indicate that they come from "bar", which was inlined into "foo", and then "foo" was inlined into the function. *Hovering* over the inlined function shows a tooltip with the call path (stack trace) of the functions inlined at that point. To copy this information to the clipboard, first *click* the inlined function, then press *Ctrl+C*. [![Profiling UI screenshot](img/assembly-inlinees_926x222.png){: style="width:500px"}](img/assembly-inlinees_926x222.png){:target="_blank"} ##### Basic blocks The assembly is parsed and analyzed to recover the function's [control-flow graph (CFG)](https://en.wikipedia.org/wiki/Control-flow_graph), identifying [basic blocks](https://en.wikipedia.org/wiki/Basic_block) and loops. This information is used to split the assembly text into basic blocks and to display the Flow Graph view. The example below shows a subset of a function's basic blocks, with the corresponding control-flow graph part from the *Flow Graph* view. The basic blocks B3-B6 are marked on the left side as folding sections that can be collapsed/expanded with a *click* on the -/+ buttons. Notice how B5 is recognized as forming a loop (the last instruction in the block jumps to the start of the block). The Flow Graph view uses a green arrow to mark loops - B4 is also the start block of a larger loop. [![Profiling UI screenshot](img/assembly-flow-graph_579x600.png){: style="width:500px"}](img/assembly-flow-graph_579x600.png){:target="_blank"} ???+ note *Click* on the target address of a jump/branch instructions marks the target instruction and its basic block in the *Flow Graph* view (uses a green background color by default). *Double-click* on a target address operand jumps to the target instruction. ##### Profiling annotations Instruction execution time is displayed and annotated on several parts of the assembly instructions, columns, basic blocks, and the control-flow graph using text, colors, and flame icons: [![Profiling UI screenshot](img/assembly-marking_1235x202.png)](img/assembly-marking_1235x202.png){:target="_blank"} - the *Time (%)* column displays the instruction's execution time percentage relative to the total function execution time. The column style can be changed in the [Assembly options](#view-options). - the *Time (ms)* column displays the instruction's execution time value. The time unit and column style can be changed in the [Assembly options](#view-options).. - the instruction background is colored based on its execution time - the slowest instruction has a red color, next slowest orange, then shades of yellow. The instruction location is also marked in the vertical text scrollbar. - the three slowest instructions also have a flame icon in the *Time (%)* column using the same color coding. [![Profiling UI screenshot](img/assembly-marking-blocks_793x203.png)](img/assembly-marking-blocks_793x203.png){:target="_blank"} - the basic blocks have a label with the block's execution time percentage, as a sum of its instruction's execution time (in the example above, the 55.73% label for B4). *Hovering* over the label shows the block's execution time value. The label background color uses the same color coding. - the basic blocks in the *Flow Graph* view have below the same execution time percentage label as in the *Assembly* view, with the corresponding background color. When displaying a function for the first time, by default, the slowest instruction is selected and brought into view (this can be configured in the [Assembly options](#view-options)). When the function is displayed subsequently, the last vertical scroll position is used instead. To jump at any time to the slowest instruction, *click* the red ![](img/flame-icon.png) from the toolbar or the *Ctrl+H* keyboard shortcut. ???+ note When multiple instructions are selected, the application status bar displays the sum of their execution time as a percentage and value. [![Profiling UI screenshot](img/assembly-selection_868x170.png)](img/assembly-selection_868x170.png){:target="_blank"} ##### Call targets Combining the parsed assembly and profiling information, call instructions are marked with their target(s) and have an arrow icon placed before the call opcode: - A black arrow icon is used for direct calls (target is a function name/address). - A green arrow icon is used for indirect or virtual function calls (target is a register or memory operand). *Hovering* with the mouse over the arrow displays a list of target functions with details about their execution time. For example, the indirect call below at runtime has the *std::_Random_device* function as the only target: [![Profiling UI screenshot](img/assembly-call-target_691x172.png){: style="width:500px"}](img/assembly-call-target_691x172.png){:target="_blank"} ???+ note Functions in the list have a right-click context menu with options to open the *Assembly* view, preview popup, and select the function in the other views. *Double-click/Ctrl+Return* opens the *Assembly** view for the selected function. Combine these shortcuts with the *Shift* key to open the **Assembly* view in a new tab instead. Call instructions with a known target have the function name operand changed into a link (underlined, bold, blue text). The link makes it easy to navigate to the called function and the function history to go back to the caller. - *Double-click* on the function name (or the *Return* key with the name selected) opens the called function in the same tab. - *Shift+Double-Click* (or Shift+Return) opens the called function in a new tab. - *Alt+Return* shows a preview popup with the called function's assembly. Press the *Escape* key to close the popup. - *Hovering* with the mouse over the function name also shows the preview popup. - Use the shortcuts from the *Opened function history* section below to return to the caller. [![Profiling UI screenshot](img/assembly-call-hover_922x278.png)](img/assembly-call-hover_922x278.png){:target="_blank"} ##### Opened functions history When multiple functions were opened in the same tab, a history is kept per tab that makes it possible to go back/forward to a previous/next opened function. The history is especially useful when navigating to a called function by *double-clicking* its name in the assembly since it makes it easy to get back to the caller.   - *Click* the *Back* button in the toolbar to navigate back to the previous function in the sequence (or press the *Backspace* key or the optional *Back* button on the mouse). The back button also has a menu that lists the previous functions. - *Click* the > button in the toolbar to navigate to the following function in the sequence (or press the optional *Forward* button on the mouse). [![Profiling UI screenshot](img/assembly-back-menu_608x154.png){: style="width:450px"}](img/assembly-back-menu_608x154.png){:target="_blank"} #### Profiling toolbar The profiling toolbar provides more advanced functionality for identifying the slow parts of a function and filtering the profiling data based on a function instance and the threads the function executed on. The following sections document the main functionality. ##### Profile Displays a menu with the slowest instructions, sorted by execution time in decreasing order. - *Click* on a menu entry to select and bring the instruction into view. - *Click* the ![](img/flame-icon.png) icon to jump to the slowest instruction in the function. - *Click* the +/- buttons to jump to the next/previous slowest instruction in the sequence. [![Profiling UI screenshot](img/assembly-profile_782x436.png){: style="width:550px"}](img/assembly-profile_782x436.png){:target="_blank"} ##### Blocks Displays a menu with the slowest blocks, sorted by execution time in decreasing order. *Click* on a menu entry to select and bring the start of the block into view. [![Profiling UI screenshot](img/assembly-blocks_560x439.png){: style="width:400px"}](img/assembly-blocks_560x439.png){:target="_blank"} ##### Inlinees Displays a menu with the inlinees (inlined functions) that directly contribute to slow instructions, sorted by the execution time of all instructions originating from a particular inlinee in decreasing order. [![Profiling UI screenshot](img/assembly-inlinees_1303x459.png)](img/assembly-inlinees_1303x459.png){:target="_blank"} *Click* on a menu entry to select all instruction associated with the inlinee and brings the first one into view. In the example above, most of the execution time (46.79%) is taken by instructions originating in the *std::_Rng_from_...* inlinee, while only 3.60% of execution time is from non-inlined instructions. ##### Instances By default, the *Assembly** view displays the function profile accumulated across all instances of the function (see the [Flame Graph view](flame-graph-panel.md) documentation for more details about instances). Filtering the function profile based on an instance makes it possible to understand better when certain parts dominate execution time (for example, based on a parameter passed by the caller, one part or another of the function executes).   The Instances menu displays the call paths leading to all instances of the function, with their execution time percentage and value. The menu entries use a compact form of the call path, where the first name is the caller, then its caller, and so on going up the call tree until the paths reach a common node. *Hover* over an entry to display a tooltip with the complete call path up to the entry point node. [![Profiling UI screenshot](img/assembly-instances_1027x182.png)](img/assembly-instances_1027x182.png){:target="_blank"} *Click* on a menu entry to filter the profile data to include only the selected instance, updating the execution time and all profiling annotations for instructions and basic blocks. The menu entries are checkboxes which allows selecting multiple instances to be included. Use the *All Instances* entry or uncheck all instances to view the entire function profile again. ##### Threads By default, the *Assembly* view displays the function profile accumulated across all threads the function executed on. Similar to instances, the profile can be filtered to consider only a subset of the threads. The Threads menu displays the threads IDs and their execution time percentage and value. The menu entries are checkboxes that allow multiple instances to be selected and included.   Use the *All Threads* entry or uncheck all instances to view the entire function profile again. [![Profiling UI screenshot](img/assembly-threads_560x214.png){: style="width:350px"}](img/assembly-threads_560x214.png){:target="_blank"} ???+ note *Hovering* with the mouse over the *Assembly* view tab displays a tooltip with details such as the total/self execution time, module and complete function name and, if filtering is used, the name of the instances and threads included in the view. ##### Export See the [Exporting](#exporting) documentation section below. ##### View Displays a menu which allows selecting the columns that should be displayed. The settings are saved across sessions when closing the application. [![Profiling UI screenshot](img/assembly-view-menu_523x243.png){: style="width:350px"}](img/assembly-view-menu_523x243.png){:target="_blank"} #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/assembly-toolbar-nav.png)| Navigate back to a previously opened function or the next one in the sequence. See the [Opened functions history](#opened-functions-history) section for more details. | | ![](img/assembly-toolbar-block-nav.png){: style="width:200px"} | The dropdown displays a list of all basic blocks, selecting one jumps to it. | | ![](img/assemlby-toolbar-block-updown.png) | Jumps to the previous/next basic block in the function. | | ![](img/assembly-toolbar-bookmarks.png) | Displays a menu with options for viewing, setting and removing bookmarks associated with instructions. The up/down arrows jump to the previous/next bookmark. | | ![](img/assembly-toolbar-clear.png) | Displays a menu with options for removing markings from the selected or all instructions and operands. | | ![](img/assembly-toolbar-popup.png) | Opens the current function into a new preview popup. | | ![](img/assembly-toolbar-search.png) | Displays the text search panel. Press the *Escape* key to reset the search and close the panel. | ???+ abstract "Mouse shortcuts" | Action | Description | | ------ | ------------| | Hover | Hovering over a call target function name displays a popup with the function's assembly. Pin or drag the popup to keep it open. | | Click | Selects an instruction and also selects and brings into view its corresponding source line in the *Source File* view and its basic block in the *Flow Graph* view. | | Double-click | If an instruction operand is selected, jumps to its definition.
For jump/branch target address, jumps to the destination basic block.
For call target function names, it opens the target function in the active tab. | | Shift+Double-click | For call target function names, it opens the target function in a new tab. | | Right-click | Shows the context menu for the selected instructions. | | Back | If the mouse has a *Back* button, navigates back to the previous opened function in the tab. | | Forward | If the mouse has a *Forward* button, Navigates forward to the next opened function in the tab. | ???+ abstract "Keyboard shortcuts" | Keys | Description | | ------ | ------------| | Return | If an instruction operand is selected, jumps to its definition.
For jump/branch target address, jumps to the destination basic block.
For call target function names, it opens the target function in the active tab. | | Ctrl+Return | For direct call target function names, it opens the target function in a new tab. | | Alt+Return | For direct call target function names, displays a preview popup with the target function's assembly. | | Backspace | Navigates back to the previous opened function in the tab. | | Shift+Backspace | Navigates forward to the next opened function in the tab. | | Ctrl+H | Jumps to the slowest instruction. | | F2 | Jumps to the next slowest instruction in the sequence. | | Shift+F2 | Jumps to the next previous instruction in the sequence. | | Ctrl+C | Copies to clipboard a HTML and Markdown table with a summary of the selected instructions. | | Ctrl+Shift+C | Copies to clipboard the assembly text of the selected instructions. | | Ctrl+F | Displays the text search panel. | | F3 | Jumps to the next text search result. | | Shift+F3 | Jumps to the previous text search result. | | Escape | Resets text searching and closed the text search panel. | | Ctrl+B | Add a bookmark associated with the selected instruction. | | Ctrl+Arrow Up | Jumps to the previous basic block. | | Ctrl+Arrow Down | Jumps to the next basic block. | | Page Up/Down
Arrow keys | Scroll text view similar to other text editors. | #### Exporting The function's assembly, combined with source line numbers and profiling annotations and execution time can be exported and saved into multiple formats, with the slowest instructions marked using a similar style as in the application: - Excel worksheet (*.xlsx) [![Profiling UI screenshot](img/assembly-export-excel_780x441.png){: style="width:480px"}](img/assembly-export-excel_780x441.png){:target="_blank"} - HTML table (*.html) [![Profiling UI screenshot](img/assembly-export-html_721x536.png){: style="width:480px"}](img/summary-export-html_1209x287.png){:target="_blank"} - Markdown table (*.md) [![Profiling UI screenshot](img/assembly-export-markdown_984x365.png){: style="width:480px"}](img/assembly-export-markdown_984x365.png){:target="_blank"} The Export menu in the toolbar also has an option to copy to clipboard the function's assembly as a HTML/Markdown table (pasting in an application supporting HTML - such as the Microsoft Office suite and online editors - will use the HTML version, code/text editors will use Markdown version instead). The Ctrl+C keyboard shortcut copies to the clipboard only the selected instructions as a HTML/Markdown table. #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Assembly Code* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/assembly-options-general_559x643.png){: style="width:400px"}](img/details-panel-info_565x786.png){:target="_blank"} === "Appearance" [![Profiling UI screenshot](img/assembly-options-appearance_554x501.png){: style="width:400px"}](img/assembly-options-appearance_554x501.png){:target="_blank"} === "Source File" [![Profiling UI screenshot](img/assembly-options-source_553x422.png){: style="width:400px"}](img/assembly-options-source_553x422.png){:target="_blank"} === "Profiling" [![Profiling UI screenshot](img/assembly-options-profiling_555x758.png){: style="width:400px"}](img/assembly-options-profiling_555x758.png){:target="_blank"} #### Column options *Right-click* on a column, such as the *Time* columns, displays the option panel that allows changing the style and displayed information by the selected column. Each column can have a different style if desired. [![Profiling UI screenshot](img/assembly-column-options_463x393.png){: style="width:320px"}](img/assembly-column-options_463x393.png){:target="_blank"} #### Documentation in progress - View options - Column options ================================================ FILE: docs/docs/call-tree-panel.md ================================================ #### Overview The Call Tree view displays the tree derived from combining the call stacks associated with all profile samples in the trace, with each node representing a unique instance of a function. The node's children represent the callees (called functions), and the parent is the caller function.   *Total (inclusive) execution time* is computed by accumulating the time of all samples with the instance in the call stack. *Self (exclusive) execution time* is computed by subtracting the time spent in children nodes from the total execution time. [![Profiling UI screenshot](img/call-tree-view_1081x540.png){: style="width:700px"}](img/call-tree-view_1081x540.png){:target="_blank"} The view has two parts: - a toolbar at the top, with action buttons and the *Search* input box. - the tree list view displaying the call tree. A function node has the demangled (undecorated) function name, optionally prepended with the module name, the total execution time percentage (relative to the entire trace), followed by total/self execution time and module columns. ???+ note By default, several levels of the call path with the longest execution time is expanded. This can be configured in the *Call Tree options* panel. The columns in all list views can be resized and reorder. The new layout is saved across sessions when closing the application. #### Searching functions Use the *search input box* in the toolbar to search for functions with a specific name using a case-insensitive substring search. Matching nodes and function names are marked, and the *up/down* buttons on the right can be used to navigate between results. Press the *Escape* key to reset the search or the X button next to the input box. [![Profiling UI screenshot](img/call-tree-search_1077x402.png){: style="width:700px"}](img/call-tree-search_1077x402.png){:target="_blank"} #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/flame-graph-toolbar-reset.png) | Resets the view to the initial state. | | ![](img/call-tree-toobar-flame.png) | Expands several levels of the the slowest path in the call tree. | | ![](img/flame-graph-toolbar-sync.png) | If enabled, selecting a node also selects the associated function in the other profiling views. | | ![](img/flame-graph-toolbar-source.png) | If enabled, selecting a node also displays the associated function in the *Source File* view, with the source lines annotated with profiling data. | | ![](img/flame-graph-toolbar-module.png) | If enabled, display the module name before the function name in the nodes as module!function. | | Search box | Search for nodes with a specific function name using a case-insensitive substring search. Press the *Escape* key to reset the search or the *X* button next to the input box. | ???+ abstract "Mouse shortcuts" | Action | Description | | ------ | ------------| | Hover | Hovering over a node briefly displays a preview popup with the complete function name and total/self execution times. *Clicking* the *Pin button* or dragging the popup expands it into a panel equivalent to the *Details panel*. Multiple such panels can be kept open at the same time. | | Click | Selects a function. If *Sync* is enabled in the toolbar, the function is also selected in the other panels. Displays the associated function in the *Source File* view if *Source* is enabled in the toolbar. | | Double-click | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Double-click | Opens the *Assembly* view of the selected function in a new tab. | | Shift+Double-click | Opens the *Assembly* view of the selected function in the active tab, with profile data filtered to include only the selected instance. | | Ctrl+Shift+Double-click | Opens the *Assembly* view of the selected function in a new tab, with profile data filtered to include only the selected instance. | | Right-click | Shows the context menu for the selected function. | ???+ abstract "Keyboard shortcuts" | Keys | Description | | ------ | ------------| | Space | Expands (zooms-in) the pointed node to cover the view's width, adjusting child node widths accordingly. | | Return | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Return | Opens the *Assembly* view of the selected function in a new tab. | | Alt+Return | Opens a preview popup with the assembly of the selected function. Press the *Escape* key to close the popup.

Multiple preview popups can be can be kept open at the same time. | | Shift+Return | Opens the *Assembly* view of the selected function in the active tab, with profile data filtered to include only the selected instance. | | Ctrl+Shift+Return | Opens the *Assembly* view of the selected function in a new tab, with profile data filtered to include only the selected instance. | | Alt+Shift+Return | Opens a preview popup with the assembly of the selected function, with profile data filtered to include only the selected instance. | | Ctrl+C | Copies to clipboard a HTML and Markdown table with a summary of the selected nodes. | | Ctrl+Shift+C | Copies to clipboard the function names of the selected nodes. | | Ctrl+Alt+C | Copies to clipboard the mangled/decorated function names of the selected nodes. | | Ctrl+= | Expands several levels of the the slowest path of children of the selected function. | | Ctrl+- | Collapses all children of the selected function. | | Ctrl+0
Ctrl+R | Resets the view to the initial state. | | Left-arrow key | Collapses the children of the selected function and goes up one level. | | Right-arrow key | Expands the children of the selected function and goes down one level. | ???+ abstract "Right-click context menu" [![Profiling UI screenshot](img/call-tree-context-menu_524x517.png){: style="width:380px"}](img/call-tree-context-menu_524x517.png){:target="_blank"} #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Call Tree* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/call-options-general_584x282.png){: style="width:400px"}](img/call-options-general_584x282.png){:target="_blank"} #### Documentation in progress - Marking nodes - View options ================================================ FILE: docs/docs/caller-panel.md ================================================ #### Overview The Caller/Callee view displays the active function's list of callers and callees (function being called by it). It can be viewed as an extension of the [Call Tree view](call-tree-panel.md) focused on a single function. [![Profiling UI screenshot](img/caller-view_1002x539.png){: style="width:700px"}](img/caller-view_1002x539.png){:target="_blank"} The view has four parts: - a toolbar at the top, with action buttons and the *Search* input box. - a function node representing the active function, with a 100% total execution time. - the *Calling* tree list view displaying the callee functions. - the *Callers* tree list view displaying the caller functions. A function node has the demangled (undecorated) function name, optionally prepended with the module name, the total execution time percentage (relative to the entire trace), followed by total/self execution time and module columns. ???+ note The columns in all list views can be resized and reorder. The new layout is saved across sessions when closing the application. By default, all function instances are displayed combined, with the lists of callers and callees merged and execution time summed up. To display individual instances instead, disable *Combine* in the toolbar. [![Profiling UI screenshot](img/call-tree-instances_1005x311.png){: style="width:700px"}](img/call-tree-instances_1005x311.png){:target="_blank"} Expanding a caller function form the list goes up the call tree, showing a list of callers which forms a stack trace leading to the entry function. This makes it easy to see the call path that leads to a caller. [![Profiling UI screenshot](img/caller-expand-caller_804x233.png){: style="width:500px"}](img/caller-expand-caller_804x233.png){:target="_blank"} Expanding a callee function from the list goes down the call tree, showing a list of callees until a leaf node is reached. This makes it easy to see which functions are being called starting with a callee. [![Profiling UI screenshot](img/caller-expand-calling_724x210.png){: style="width:500px"}](img/caller-expand-calling_724x210.png){:target="_blank"} #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/flame-graph-toolbar-back.png) | Navigates back to the previous viewed function in the view. | | ![](img/flame-graph-toolbar-sync.png) | If enabled, selecting a node also selects the associated function in the other profiling views. | | ![](img/flame-graph-toolbar-source.png) | If enabled, selecting a node also displays the associated function in the *Source File* view, with the source lines annotated with profiling data. | | ![](img/call-tree-toolbar-combine.png) | If enabled, all function instances are displayed combined, with the lists of callers and callees merged and execution time summed up. | | ![](img/flame-graph-toolbar-module.png) | If enabled, display the module name before the function name in the nodes as module!function. | | Search box | Search for nodes with a specific function name using a case-insensitive substring search. Press the *Escape* key to reset the search or the *X* button next to the input box. | ???+ abstract "Mouse shortcuts" | Action | Description | | ------ | ------------| | Hover | Hovering over a node briefly displays a preview popup with the complete function name and total/self execution times, similar to the *Flame Graph* view. | | Double-click | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Double-click | Opens the *Assembly* view of the selected function in a new tab. | | Shift+Double-click | Opens the *Assembly* view of the selected function in the active tab, with profile data filtered to include only the selected instance. | | Ctrl+Shift+Double-click | Opens the *Assembly* view of the selected function in a new tab, with profile data filtered to include only the selected instance. | | Right-click | Shows the context menu for the selected function. | | Back | If the mouse has a *Back* button, navigates back to the previous viewed function in the view. | ???+ abstract "Keyboard shortcuts" | Keys | Description | | ------ | ------------| | Return | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Return | Opens the *Assembly* view of the selected function in a new tab. | | Alt+Return | Opens a preview popup with the assembly of the selected function. Press the *Escape* key to close the popup.

Multiple preview popups can be can be kept open at the same time. | | Shift+Return | Opens the *Assembly* view of the selected function in the active tab, with profile data filtered to include only the selected instance. | | Ctrl+Shift+Return | Opens the *Assembly* view of the selected function in a new tab, with profile data filtered to include only the selected instance. | | Alt+Shift+Return | Opens a preview popup with the assembly of the selected function, with profile data filtered to include only the selected instance. | | Ctrl+C | Copies to clipboard a HTML and Markdown table with a summary of the selected nodes. | | Ctrl+Shift+C | Copies to clipboard the function names of the selected nodes. | | Ctrl+Alt+C | Copies to clipboard the mangled/decorated function names of the selected nodes. | | Backspace | navigates back to the previous viewed function in the view. | | Ctrl+= | Expands several levels of the the slowest path of children of the selected function. | | Ctrl+- | Collapses all children of the selected function. | | Ctrl+0
Ctrl+R | Resets the view to the initial state. | | Left-arrow key | Collapses the children of the selected function and goes up one level. | | Right-arrow key | Expands the children of the selected function and goes down one level. | ???+ abstract "Right-click context menu" [![Profiling UI screenshot](img/call-tree-context-menu_524x517.png){: style="width:380px"}](img/call-tree-context-menu_524x517.png){:target="_blank"} #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Caller/Callee* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/call-options-general_584x282.png){: style="width:400px"}](img/call-options-general_584x282.png){:target="_blank"} #### Documentation in progress - Marking nodes - View options ================================================ FILE: docs/docs/demos.md ================================================ #### UI overview, loading and navigating a trace ================================================ FILE: docs/docs/flame-graph-panel.md ================================================ #### Overview The Flame Graph view is the main means of identifying the parts of the application where most time is spent. The flame graph displays nodes representing functions stacked top to bottom according to the call tree paths forming the stack traces. [![Profiling UI screenshot](img/flame-graph-panel_1435x557.png)](img/flame-graph-panel_1435x557.png){:target="_blank"} The view has three parts: - a toolbar at the top, with action buttons and the *Search* input box. - the interactive flame graph view. - the [Details panel](#details-panel) on the right side. The panel displays detailed info about the selected node(s), and its visibility can be toggled using the *Details* button in the toolbar. ???+ note "Introduction to flame graphs" A flame graph is an alternative, more compact way of viewing a call tree. In this view, function instances are nodes with a size proportional to the time spent relative to the caller (parent) function and makes it easier to identify the portions of the app that take most of the time. Nodes are sorted in the horizontal direction based on decreasing time relative to their parent node, while the ordering in the vertical direction forms a stack trace (a path in the call tree). The function taking the most time in the application is then found in the leftmost, bottom part of the flame graph. ![flame graph diagram](img/flame-graph.png){: style="width:320px"} In the example above, the *main* function is considered the process entry point, calling *foo* and *bar*, with *foo* taking 60% of the time and *bar* 40%. Function *foo* spends a part of its total (inclusive) time in the calls to *baz* and *etc1*, while the rest is self (exclusive) time, meaning instructions part of *foo* which are not calls to other functions. Note that there are two instances of the function *baz* with different execution times, each with a unique path to it in the call tree starting from *main* (all other functions have a single instance). You can see the time of each instance by *hovering* with the mouse over it or in the *Details panel* after it's selected. The following links provide an introduction to the flame graph visualization concept, its history, and how it's being used across the industry for performance investigations. - [CPU Flame Graphs (brendangregg.com)](https://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html) - [Visualizing Performance - The Developers’ Guide to Flame Graphs (youtube.com)](https://www.youtube.com/watch?v=VMpTU15rIZY) ##### Flame graph nodes Each node is a unique instance of a function — a function having multiple instances means there are several paths in the call tree that call the function.   Each node has the demangled (undecorated) function name, optionally prepended with the module name, followed by the execution time percentage relative to the entire trace and the execution time.   By default, the nodes are color-coded based on the module names to which the functions belong. Nodes for functions executing in the kernel/managed context are marked with a different text and border color (blue by default). The displayed text fields and colors can be customized in the flame graph options.   ???+ note When the called function nodes are too small to be visible in the view, they are collapsed under a placeholder node rendered with a hatch pattern. Placeholder nodes are expanded into individual nodes when zooming in the view.   ##### Navigating the flame graph *Middle-click* on a node expands it to cover the entire view and may expand collapsed child nodes. For example, the called nodes become visible after expanding the node hovered in the screenshot above. Alternatively, with a node already selected press the *Space* key to expand it. [![Profiling UI screenshot](img/flame-graph-expand_944x428.png)](img/flame-graph-expand_944x428.png){:target="_blank"} Expanding a node can be repeated to go deeper down the call path. The *Back* button in the toolbar (or *Backspace* key/*Back* mouse button) undoes the operation and returns the view to its previous state.   [![Profiling UI screenshot](img/flame-graph-expand2_947x456.png)](img/flame-graph-expand2_947x456.png){:target="_blank"} ???+ note In the screenshot above, the nodes starting with *ntoskrnl.exe!KiPageFault* use a different style to mark code executing in kernel mode. The user mode and kernel mode call stacks are automatically combined. ##### Changing the root node It can be helpful to view only a subregion of the flame graph. By changing the root node, only nodes for functions starting with the new root are displayed, and execution time percentages are computed relative to the new root, which starts at 100%. To change the root node, from the right-click context menu, select *Set Function as Root* (alternatively, use the *Alt+Double-click* shortcut). After the switch, the toolbar displays the name of the current root node. Setting a new root node can be repeated in the new view. To remove the root node and view the entire flame graph, *click* the *X* button next to its name in the toolbar. If multiple nested root nodes were set, removing the current node activates the previous one. [![Profiling UI screenshot](img/flame-graph-root_946x435.png)](img/flame-graph-root_946x435.png){:target="_blank"} #### Searching functions Use the *search input box* in the toolbar to search for functions with a specific name using a case-insensitive substring search. Matching nodes and function names are marked, and the *up/down* buttons on the right can be used to navigate between results. Press the *Escape* key to reset the search or the X button next to the input box. [![Profiling UI screenshot](img/flame-graph-search_1078x286.png)](img/flame-graph-search_1078x286.png){:target="_blank"} #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/flame-graph-toolbar-back.png) | Undoes the previous action, such as expanding a node or changing the root node. | | ![](img/flame-graph-toolbar-reset.png) | Resets the view to it's original state, displaying the entire flame graph. | | ![](img/flame-graph-toolbar-minus.png) | Zooms out the view around the center point. | | ![](img/flame-graph-toolbar-plus.png) | Zooms in the view around the center point. | | ![](img/flame-graph-toolbar-sync.png) | If enabled, selecting a node also selects the associated function in the other profiling views. | | ![](img/flame-graph-toolbar-source.png) | If enabled, selecting a node also displays the associated function in the *Source File* view, with the source lines annotated with profiling data. | | ![](img/flame-graph-toolbar-module.png) | If enabled, display the module name before the function name in the nodes as module!function. | | ![](img/flame-graph-toolbar-details.png) | If enabled, display the *Details panel* on the right side of the *Flame Graph* view. | | Search box | Search for nodes with a specific function name using a case-insensitive substring search. Press the *Escape* key to reset the search or the *X* button next to the input box. | ???+ abstract "Mouse shortcuts" | Action | Description | | ------ | ------------| | Hover | Hovering over a node briefly displays a preview popup with the complete function name and total/self execution times. *Clicking* the *Pin button* or dragging the popup expands it into a panel equivalent to the *Details panel*. Multiple such panels can be kept open at the same time. | | Click | Selects a node and deselects any previously selected nodes. The *Details panel* is updated and, if *Sync* is enabled in the toolbar, the function is selected in the other panels. Displays the associated function in the *Source File* view if *Source* is enabled in the toolbar.

*Clicking* an empty part of the view deselects all nodes. | | Ctrl+Click | Selects the pointed node and keeps the previously selected nodes (append). The *Details panel* is updated to display a combined view of all selected nodes. | | Shift+Click | When a node is selected, it expands the selection to include all nodes in the call stack between the pointed node and the selected one. The *Details panel* is updated to display a combined view of all selected nodes. | | Middle-click | Expands (zooms-in) the pointed node to cover the view's width, adjusting child node widths accordingly. | | Back | If the mouse has a *Back* button, this undoes the previous action, such as expanding a node (double-click) or changing the root node. An alternative is pressing the *Backspace* key or the *Back* button in the toolbar.| | Double-click | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Double-click | Opens the *Assembly* view of the selected function in a new tab. | | Shift+Double-click | Opens the *Assembly* view of the selected function in the active tab, with profile data filtered to include only the selected instance. | | Ctrl+Shift+Double-click | Opens the *Assembly* view of the selected function in a new tab, with profile data filtered to include only the selected instance. | | Alt+Double-click | Sets the selected node as the root node of the flame graph. | | Right-click | Shows the context menu for the selected nodes. | | Click+Drag | If the flame graph is larger than the view, *clicking* on and dragging an empty part of the view moves the view in the direction of the mouse. | | Scroll wheel | Scrolls the view vertically if the flame graph is larger than the view. | | Shift+Scroll wheel | Scrolls the view horizontally if the flame graph is larger than the view. | | Ctrl+Scroll wheel | Zooms in or out the view around the mouse pointer position. | | Click+Scroll wheel | Zooms in or out the view around the mouse pointer position. | !!! note When multiple nodes are selected, the application status bar displays the sum of their execution time as a percentage and value. [![Profiling UI screenshot](img/flame-graph-selection_619x155.png){: style="width:450px"}](img/flame-graph-selection_619x155.png){:target="_blank"} ???+ abstract "Keyboard shortcuts" | Keys | Description | | ------ | ------------| | Space | Expands (zooms-in) the pointed node to cover the view's width, adjusting child node widths accordingly. | | Return | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Return | Opens the *Assembly* view of the selected function in a new tab. | | Alt+Return | Opens a preview popup with the assembly of the selected function. Press the *Escape* key to close the popup.

Multiple preview popups can be can be kept open at the same time. | | Shift+Return | Opens the *Assembly* view of the selected function in the active tab, with profile data filtered to include only the selected instance. | | Ctrl+Shift+Return | Opens the *Assembly* view of the selected function in a new tab, with profile data filtered to include only the selected instance. | | Alt+Shift+Return | Opens a preview popup with the assembly of the selected function, with profile data filtered to include only the selected instance. | | Ctrl+C | Copies to clipboard a HTML and Markdown table with a summary of the selected nodes. | | Ctrl+Shift+C | Copies to clipboard the function names of the selected nodes. | | Ctrl+Alt+C | Copies to clipboard the mangled/decorated function names of the selected nodes. | | Backspace | Undoes the previous action, such as expanding a node (double-click) or changing the root node. | | Ctrl+= | Zooms in the view around the center point. | | Ctrl+- | Zooms out the view around the center point. | | Ctrl+0
Ctrl+R | Resets the view to the initial state. | | Arrow keys | Scrolls the view in the horizontal and vertical directions if the flame graph is larger than the view. | ???+ abstract "Right-click context menu" [![Profiling UI screenshot](img/flame-graph-context-menu_539x651.png){: style="width:380px"}](img/flame-graph-context-menu_539x651.png){:target="_blank"} #### Details panel The Details panel shows extended information about the selected node(s) in the flame graph. It provides a quick overview of the slowest functions and modules being called directly or through other functions starting with the selection.   The top shows the *Total* (inclusive) execution time and *Self* (exclusive) execution time values for the selected node (function instance). The right side shows the index of the chosen instance, among all instances, with the slowest instance having the lowest index. Use the left/right arrow buttons to switch to the previous/next function instance.   ???+ note Functions in the lists have a right-click context menu with options to open the *Assembly* view, preview popup, and select the function in the other views. *Double-click/Ctrl+Return* opens the *Assembly** view for the selected function. Combine these shortcuts with the *Shift* key to open the **Assembly* view in a new tab instead. *Hovering* with the mouse over a function opens a preview popup with the function's assembly. When multiple functions are selected, the application status bar displays the sum of their execution time as a percentage and value. The information displayed in the tabs below is for the selected function instance only, except the *Info* tab which displays statistics for all instances instead. === "Info" [![Profiling UI screenshot](img/details-panel-info_565x786.png){: style="width:380px"}](img/details-panel-info_565x786.png){:target="_blank"} The Info tab displays details and statistics about all instances of the selected funcion node. | Section | Description | | ------ | ------------| | Instances | Displays total execution time (sum), average, and median across all function instances, as a total/self execution time percentage relative to the entire trace and execution time value. | | Histogram | The histogram displays the time distribution across all function instances. Instances with similar times are grouped, and the number of instances in each group is shown above, with more details when *hovering* over a group with the mouse.

*Clicking* on a group selects the first node from the group in the *Flame Graph* view. The *Total/Self* radio buttons switch between using the total time or self time for the histogram.

In the above example, there are 3 instances of function *genString*, one with an execution time of ~1.5ms and two, binned together, with ~1sec each. The time of the selected instance is marked with a green arrow, and the average/median times are indicated by red/blue dotted lines. | | Threads | Displays the list of threads on which all function instances execute, with each thread's total/self execution time percentage and execution time value.

*Right-clicking* a thread shows a context menu with options to open the *Assembly* view with profile data filtered to include only the selected thread and multiple options for changing the thread filtering for the entire trace.

*Double-clicking* a thread filters the entire trace to show only code executing on that thread. | | Module | Displays the name of the module to which the function belongs. Shortcut buttons on the right side:
![](img/details-panel-mark-module.png){: style="width:24px"} Marks all function nodes belonging to the module with a color.
![](img/details-panel-copy.png){: style="width:24px"} Copies to clipboard the module name.
| | Function | Displays the complete function name, followed by the execution context as U/K/M standing for User/Kernel/Managed mode. Shortcut buttons on the right side:
![](img/details-panel-preview.png){: style="width:24px"} Opens a preview popup with the function's assembly.
![](img/details-panel-tab.png){: style="width:24px"} Opens the function's *Assembly* view in a new tab.
![](img/details-panel-mark-module.png){: style="width:24px"} Marks all function nodes with a color.
![](img/details-panel-copy.png){: style="width:24px"} Copies to clipboard the function name.
| === "Stack" [![Profiling UI screenshot](img/details-panel-stack_565x706.png){: style="width:380px"}](img/details-panel-stack_565x706.png){:target="_blank"} The Stack tab displays the call stack (stack trace) leading to the selected function instance node. === "Functions" [![Profiling UI screenshot](img/details-panel-functions_565x706.png){: style="width:380px"}](img/details-panel-functions_565x706.png){:target="_blank"} The Functions tab lists the slowest functions being called directly or through other functions, starting with the selected function instance node. By default, the list is sorted by self (exclusive) time in descending order. The flame graph options can change the sorting to consider total (inclusive) time instead. === "Modules" [![Profiling UI screenshot](img/details-panel-modules_565x706.png){: style="width:380px"}](img/details-panel-modules_565x706.png){:target="_blank"} The Modules tab is similar to the Functions tab, with the difference that functions are first grouped by the module they belong to, and the execution time per module is also displayed. Selecting a module shows the list of the slowest functions. === "Categories" [![Profiling UI screenshot](img/details-panel-categories_565x706.png){: style="width:380px"}](img/details-panel-categories_565x706.png){:target="_blank"} The Categories tab is similar to the Functions tab, with the difference that functions are first grouped by the category they belong to, and the execution time per category is also displayed. Selecting a category shows the list of the slowest functions.

*Right-click* on a category shows options to export a report as a HTML/Markdown file and copy the report to clipboard. === "Instances" [![Profiling UI screenshot](img/details-panel-instances_565x706.png){: style="width:380px"}](img/details-panel-instances_565x706.png){:target="_blank"} The Instances tab lists all instances of the function, sorted by total (inclusive) execution time. #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Flame Graph* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/flame-graph-options-general_586x337.png){: style="width:400px"}](img/flame-graph-options-general_586x337.png){:target="_blank"} === "Appearance" [![Profiling UI screenshot](img/flame-graph-options-appearance_592x809.png){: style="width:400px"}](img/flame-graph-options-appearance_592x809.png){:target="_blank"} === "Details Panel" [![Profiling UI screenshot](img/flame-graph-options-details_590x690.png){: style="width:400px"}](img/flame-graph-options-details_590x690.png){:target="_blank"} #### Documentation in progress - Marking nodes - View options ================================================ FILE: docs/docs/flow-graph-panel.md ================================================ #### Overview The Flow Graph view displays the [control-flow graph (CFG)](https://en.wikipedia.org/wiki/Control-flow_graph) of the function viewed in the active *Assembly* view. The function CFG makes it easier to see the structure of a function and control-flow created by jumps, branches, and loops. The slowest [basic blocks](https://en.wikipedia.org/wiki/Basic_block) are annotated with profiling information. [![Profiling UI screenshot](img/flow-graph-view_501x693.png){: style="width:320px"}](img/flow-graph-view_501x693.png){:target="_blank"} The view has two parts: - a main toolbar at the top, with general action buttons. - an interactive CFG area, supporting zooming and panning. Each basic block is represented by a rectangle, with the block number as the label. An edge between two blocks means the source and destination block are connected either through a jump/branch or fall-through code. ##### Color coding Different colors of the blocks and edges are used to help identify control flow. The used colors can be customized in the [Flow Graph options](#view-options). Block border colors coding (default colors): - blue: blocks ends with a branch instruction. - green: block is the target of a loop back-edge (it's a loop header). - red: block ends with a return instruction (it's a function exit), Edge color coding (default colors): - blue: target block is a branch target (branch in the source block jumps to it). - green: loop back-edge, target block is a loop header (start of a loop). - red: target block is a function exit block. - dotted: target block is the [immediate dominator](https://en.wikipedia.org/wiki/Dominator_(graph_theory)) of the source block. ##### Selection sync When a block is selected, the corresponding instructions are also selected in the *Assembly* view, like in the example below where B5 is selected. Notice that B5 is a single-block, nested loop, while B4 is the loop header block of a larger loop including B5. [![Profiling UI screenshot](img/flow-graph-select_1277x370.png)](img/flow-graph-select_1277x370.png){:target="_blank"} #### Profiling annotations Blocks with a significant execution time are marked by using bold text for the block number and changing their background color (same color coding as in the *Assembly* view). A label is displayed underneath with the block's execution time percentage relative to the function's total execution time. #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/flame-graph-toolbar-reset.png) | Resets the view to it's original state. | | ![](img/flame-graph-toolbar-minus.png) | Zooms out the view around the center point. | | ![](img/flame-graph-toolbar-plus.png) | Zooms in the view around the center point. | | ![](img/flow-graph-toolbar-width.png) | Resizes the view so that the width of the graph matches the available horizontal area. | | ![](img/flow-graph-toolbar-all.png) | Resizes the view so that the entire graph is visible. | | ![](img/flow-graph-toolbar-clear.png) | Displays a menu with options for clearing marker for the selected block or all blocks. | ???+ abstract "Mouse shortcuts" | Action | Description | | ------ | ------------| | Hover | Hovering over a block displays a preview popup with the corresponding instructions from the *Assembly* view. | | Click | Selects a block and also selects the corresponding instructions the *Assembly* view (can be configured in the [Flow Graph options](#view-options)) | | Right-click | Shows the context menu for the selected block. | | Click+Drag | *Clicking* on and dragging an empty part of the view moves the view in the direction of the mouse. | | Scroll wheel | Scrolls the view vertically if graph is larger than the view. | | Ctrl+Scroll wheel | Zooms in or out the view around the mouse pointer position. | ???+ abstract "Keyboard shortcuts" | Keys | Description | | ------ | ------------| | Ctrl+= | Zooms in the view around the center point. | | Ctrl+- | Zooms out the view around the center point. | | Ctrl+0
Ctrl+R | Resets the view to the initial state. | | Ctrl+W | Resizes the view so that the width of the graph matches the available horizontal area. | | Ctrl+A | Resizes the view so that the entire graph is visible. | | Arrow keys | Scrolls the view in the horizontal and vertical directions if the flame graph is larger than the view. | ???+ abstract "Right-click context menu" [![Profiling UI screenshot](img/flow-graph-context-menu_383x548.png){: style="width:380px"}](img/flow-graph-context-menu_383x548.png){:target="_blank"} #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Flow Graph* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/flow-graph-options-general_558x423.png){: style="width:400px"}](img/flow-graph-options-general_558x423.png){:target="_blank"} === "Appearance" [![Profiling UI screenshot](img/flow-graph-options-appearance_527x594.png){: style="width:400px"}](img/flow-graph-options-appearance_527x594.png){:target="_blank"} #### Documentation in progress - View options ================================================ FILE: docs/docs/index.json ================================================ { "Topics": [ { "Title": "Introduction", "URL": "intro.html", "SubTopics": null }, { "Title": "Getting started", "URL": "", "SubTopics": [ { "Title": "About", "URL": "about.html", "SubTopics": null }, { "Title": "Profiling UI overview", "URL": "profiling-ui.html", "SubTopics": null }, { "Title": "Video Demos", "URL": "demos.html", "SubTopics": null } ] }, { "Title": "Trace loading and recording", "URL": "", "SubTopics": [ { "Title": "Loading a trace", "URL": "trace-loading.html", "SubTopics": null }, { "Title": "Recording a trace", "URL": "trace-recording.html", "SubTopics": null } ] }, { "Title": "Trace profile views", "URL": "", "SubTopics": [ { "Title": "Summary view", "URL": "summary-panel.html", "SubTopics": null }, { "Title": "Flame Graph view", "URL": "flame-graph-panel.html", "SubTopics": null }, { "Title": "Timeline view", "URL": "timeline-panel.html", "SubTopics": null }, { "Title": "Call Tree view", "URL": "call-tree-panel.html", "SubTopics": null }, { "Title": "Caller/Callee view", "URL": "caller-panel.html", "SubTopics": null } ] }, { "Title": "Function profile views", "URL": "", "SubTopics": [ { "Title": "Assembly view", "URL": "assembly-view.html", "SubTopics": null }, { "Title": "Source File view", "URL": "source-panel.html", "SubTopics": null }, { "Title": "Flow Graph view", "URL": "flow-graph-panel.html", "SubTopics": null } ] } ], "PanelTopics": { "section": { "Title": "Summary view", "URL": "summary-panel.html", "SubTopics": null }, "flameGraph": { "Title": "Flame Graph view", "URL": "flame-graph-panel.html", "SubTopics": null }, "timeline": { "Title": "Timeline view", "URL": "timeline-panel.html", "SubTopics": null }, "callTree": { "Title": "Call Tree view", "URL": "call-tree-panel.html", "SubTopics": null }, "callerCallee": { "Title": "Caller/Callee view", "URL": "caller-panel.html", "SubTopics": null }, "other": { "Title": "Assembly view", "URL": "assembly-view.html", "SubTopics": null }, "source": { "Title": "Source File view", "URL": "source-panel.html", "SubTopics": null }, "flowGraph": { "Title": "Flow Graph view", "URL": "flow-graph-panel.html", "SubTopics": null } }, "HomeTopic": { "Title": "Home", "URL": "intro.html", "SubTopics": null } } ================================================ FILE: docs/docs/intro.md ================================================ #### Getting started - [About](about.md): provides an introduction to the application. - [Profiling UI overview](profiling-ui.md): provides an overview of the main profiling views. - [Video Demos](demos.md): has several screen recording videos presenting the UI and features. ##### Trace loading and recording - [Loading a trace](trace-loading.md) - [Recording a trace](trace-recording.md) - [Trace overview report](trace-overview.md) ##### Profiling views Trace profiling views: - [Summary view](summary-panel.md) - [Flame Graph view](flame-graph-panel.md) - [Timeline view](timeline-panel.md) - [Call Tree view](call-tree-panel.md) - [Caller/Callee view](caller-panel.md) Function profiling views (focus on an individual function): - [Assembly view](assembly-view.md) - [Source File view](source-panel.md) - [Flow Graph view](flow-graph-panel.md) ???+ note The documentation is currently being worked on. Several pages need to be completed or are currently missing (the *Additional functionality* section). #### Documentation tips Most app views have a *question mark* button in the upper-right corner. *Click* it to view the panel's documentation page in the app's built-in *Help* panel. **Images** *Click* on an image to enlarge it. Depending on where the documentation is viewed: - the image is opened in a new tab if viewed in a browser. - the image is opened in a preview popup if viewed from the app's built-in *Help* panel. To close the preview popup, *click* again on the image (either in the preview popup or in the page) or press the *Escape* key. **Videos** *Click* on a video's full-screen button in the bottom-right corner to enlarge it. To restore to default size, *click* again on the full-screen button or press the *Escape* key. ================================================ FILE: docs/docs/options.md ================================================ ???+ note The documentation is currently being worked on. ================================================ FILE: docs/docs/profile-marking.md ================================================ ???+ note The documentation is currently being worked on. ================================================ FILE: docs/docs/profiling-ui.md ================================================ #### Trace views Once a trace is loaded, the *Summary*, *Flame Graph*, and *Timeline* views provide a high-level overview of the profiled application's slowest parts. These views allow you to identify the functions where most time is spent and when they execute. [![Profiling UI screenshot](img/profiling-ui-labels.png)](img/profiling-ui_1998x1377.png){:target="_blank"} - [Summary view](summary-panel.md): displays all the functions with profiling data, which are sorted by default based on their exclusive (self) duration. The left side of the panel lists the modules (binaries) with profiling data, sorted based on the total time used by the functions part of the module. - [Flame Graph view](flame-graph-panel.md): displays an interactive *Flame Graph* view of the call tree. The right side of the panel shows detailed information about the selected node(s). - [Timeline view](timeline-panel.md): displays the thread activity during the entire duration of the trace and allows filtering of the displayed profiling data to specific threads and time ranges. - [Call Tree view](call-tree-panel.md): displays nested call tree view showing the function call sequence for the entire trace. - [Caller/Callee view](caller-panel.md): displays for the function selected in the Summary view the list of callers (functions calling the selected one) and callees (functions called by the selected one). #### Single function views Open a function to display the *Assembly*, *Source File*, and *Flow Graph* views and see which parts take the most time (a *double-click* or the *Return* key in any of the views opens the function's *Assembly* view). [![Profiling UI screenshot](img/profiling-ui2-labels.png)](img/profiling-ui2_1998x1377.png){:target="_blank"} - [Assembly view](assembly-view.md): displays the function's assembly code, where each instruction is annotated with the corresponding source line number and inlining information. The right side shows the time percentage (relative to the function's time) and time taken by each instruction. The slowest instructions are marked with colors and flame icons. *Clicking* an instruction selects its corresponding source line in the *Source File* view. - [Source File view](source-panel.md): displays the function's source file and, optionally, the assembly code generated for each line. The right side shows the time percentage (relative to the function's time) and time taken by each line. The slowest lines are marked with colors and flame icons. *Clicking* a line selects the corresponding instructions in the *Assembly* view. - [Flow Graph view](source-panel.md): displays the function's [control-flow graph](https://en.wikipedia.org/wiki/Control-flow_graph){:target="_blank"}, constructed by analyzing the assembly code and forming basic blocks (a sequence of instructions that starts with jump targets and ends with jumps or branch instructions). The slowest blocks are marked with colors and labeled with the time percentage (relative to the function's time). Blocks forming a loop are marked with a green arrow. ================================================ FILE: docs/docs/rust.md ================================================ ???+ note The documentation is currently being worked on. ================================================ FILE: docs/docs/source-panel.md ================================================ #### Overview The Source File view displays the source code of the function viewed in the active *Assembly** view. When a function is opened in the **Assembly* view, using the debug info file, its corresponding source file is identified, downloaded if needed, and loaded in the view, with source lines annotated with profiling information. [![Profiling UI screenshot](img/source-view_1000x503.png)](img/source-view_1000x503.png){:target="_blank"} ##### Finding source files Locating the source file to load is done with the help of the debug info file, which usually records the file path associated with each function. In some cases, additional information is available to locate and download source files from remote locations and [Source Servers](https://learn.microsoft.com/en-us/windows/win32/debug/source-server-and-source-indexing). Steps for locating a source file: - check the local file system using the debug info file path. This check handles the case of the trace being opened on the same machine where the application was built or the source is available at the exact file system location. - check and download the source file from a [Source Server](https://learn.microsoft.com/en-us/windows/win32/debug/source-server-and-source-indexing) if the debug info file has additional remote file mapping information such as [SourceLink](https://github.com/dotnet/sourcelink) or built-in commands for retrieving the file. In case authentication is needed, it can be configured in the *Load Profile Trace* window [options](trace-loading.md#authentication). - if neither of the above steps works, ask the user to manually locate the source file on a local file system or network share. The mapping between the expected and actual source file locations is saved across sessions when the application is closed. See the [Mapping source files](#mapping-source-file-locations) section below for more details. Once a source file is available, its signature is computed and compared with the expected signature from the debug info file. If it does not match, it means the source file was modified between the time the application was built and the trace being loaded, and the file will be rejected (a future version will allow ignoring such a mismatch).   ##### Missing source files If a source file cannot be found, the app will show a dialog asking if it should continue trying to locate the same source file in the future; if not, the file is added to an exclusion list saved across sessions.   The same dialog also has the option to stop asking to locate source files manually during the current session altogether. Use the *Reset* button in the toolbar to remove the exclusion from the current file, all files or clear all exclusion and mapping settings. The [Source File options](#view-options) displays editable lists of exclusions and mappings.   ##### Mapping source file locations When a local source file is manually selected, a mapping between the original debug file path and the local file path is created. This mapping is used to locate the same source file later and to help locate other source files found in the same or a nearby location.   For example, if the original path from the build machine was saved in the debug info file as: ```C:\server\src\subdir\source.cpp``` and the selected local file path is: ```D:\local\project\src\subdir\source.cpp``` several path mappings are created between the original and local directories such as: ```C:\build\src\subdir -> D:\local\project\src\subdir``` ```C:\build\src -> D:\local\project\src``` ```C:\build -> D:\local\project``` When another source file is searched, starting with the debug info path, the mappings are used to locate it in the local file system. The mapping also works with intermediate directories between the file name and the mapped directories. For example: ```C:\build\src\other\nested\subdir\file.cpp``` found as ```D:\local\project\src\other\nested\subdir\file.cpp``` #### Source code view The view is similar to the *Assembly* view, having four parts: - a main toolbar at the top, with general action buttons. - a secondary toolbar underneath with profiling-specific info and action buttons. - the text view with the source file. - several columns on the right side with the profiling data for each source line. If CPU performance counters are found and loaded from the trace, the additional columns with metrics and the counters are appended after the last column. Each line corresponds to one source line, with the following values and buttons from left to right: [![Profiling UI screenshot](img/source-line_911x65.png){: style="width:550px"}](img/source-line_911x65.png){:target="_blank"} - source line number. - optional ASM section expand/collapse +/- button. - optional marking icons for statements and call targets. - source line text. - profiling data columns, such as the execution time percentage and value. ##### Selection sync When a source line is selected, if *Sync* is enabled in the toolbar, the associated instructions are also selected in the *Assembly* view. In the example below, the start of the loop on line 21 is selected, with the instructions forming the loop header selected in the *Assembly* view; the selected instructions corresponding to the loop back-edge are not visible in the screenshot. [![Profiling UI screenshot](img/source-selection-sync_934x400.png)](img/source-selection-sync_934x400.png){:target="_blank"} Vice versa, selecting an instruction in the *Assembly* view also selects the corresponding source line. ##### Profiling annotations Similar to the *Assembly* view, execution time is displayed and annotated on several parts of the source lines and columns using text, colors, and flame icons: - the *Time (%)* column displays the source line's execution time percentage relative to the total function execution time. The column style can be changed in the [Source File options](#view-options). - the *Time (ms)* column displays the source files's execution time value. The time unit and column style can be changed in the [Source File options](#view-options). - the source line background is colored based on its execution time - the slowest source line has a red color, next slowest orange, then shades of yellow. The line is also marked in the vertical text scrollbar. - the three slowest source lines also have a flame icon in the *Time (%)* column using the same color coding. When loading a source file, the slowest source line is selected and brought into view by default (this can be configured in the [Source File options](#view-options)). To jump at any time to the slowest source line, *click* the ![](img/flame-icon.png) icon from the toolbar or the *Ctrl+H* keyboard shortcut. ???+ note When multiple source lines are selected, the application status bar displays the sum of their execution time as a percentage and value. [![Profiling UI screenshot](img/source-selection_983x255.png)](img/source-selection_983x255.png){:target="_blank"} ##### Assembly code sections IIf enabled, each source line is followed by a section with the assembly instructions generated for it based on the debug info file. By default, the sections are collapsed and can be expanded by *clicking* the + button on the left of the source lines. Each line of assembly has the same profiling annotations as the source lines. [![Profiling UI screenshot](img/source-assembly_816x233.png)](img/source-assembly_816x233.png){:target="_blank"} To view the assembly sections, toggle the ASM button in the toolbar (enabled by default). The *Expand* and *Collapse* buttons in the toolbar can be used to toggle the visibility of all assembly sections together. ##### Call targets Combining the parsed assembly code and profiling information, source lines with associated call instructions are marked with their target(s) and have an arrow icon placed before the call opcode: - for direct calls (target is an function name/address), a black arrow is used. - for indirect or virtual function calls (target is a register or memory operand), a green arrow is used. *Hovering* with the mouse over the arrow displays a list of target functions with details about their execution time. Note that the list may contain a function that doesn't appear directly in the source code due to function inlining, like in the example below. [![Profiling UI screenshot](img/source-call-target_845x164.png)](img/source-call-target_845x164.png){:target="_blank"} ##### Source code outline On load, source files are parsed using [tree-sitter](https://tree-sitter.github.io/tree-sitter/) in order to build an [Abstract Syntax Tree (AST)](https://en.wikipedia.org/wiki/Abstract_syntax_tree). The AST identifies and marks some of the high-level parts of the function's source code, such as if/else/switch statements, for/do/while loops, and call expressions. The supported languages are C, C++, C#, and Rust. For each such statement and expression, the execution time is computed by accumulating the time of each source line found in its range. This makes it easier, for example, to see the amount of time spent in an entire *loop* (or *nested loop*), the *then/else* branch of an *if* statement, or a specific *case* of a *switch* statement. Source lines that start a statement are marked with an icon based on the statement kind on the left side and in the execution time percentage column (configurable in the [Source File options](#view-options)). *Hovering* with the mouse over a statement marking shows its execution time as a percentage and value relative to the function time and highlights the source lines part of the statement. [![Profiling UI screenshot](img/source-outline-loop_991x228.png)](img/source-outline-loop_991x228.png){:target="_blank"} Use the *Outline* button from the profiling toolbar displays to display a menu summarizing the nested statements and their execution time. Each menu entry has the source line number, statement kind icon, statement start source code, execution time percentage, and value.   *Click* on a menu entry to jump to the statement start. *Hovering* with the mouse over a menu entry highlights the source lines part of the statement. The example below shows the outline of a function having three nested loops, with if/else statements in the last level loop. [![Profiling UI screenshot](img/source-outline_953_289.png)](img/source-outline_953_289.png){:target="_blank"} #### Profiling toolbar The profiling toolbar provides more advanced functionality for identifying the slow parts of a function and filtering the profiling data based on a function instance and the threads the function executed on. The following sections document the main functionality. ##### Profile Displays a menu with the slowest source lines, sorted by execution time in decreasing order. Even if assembly sections are enabled, instructions are not included. - *Click* on a menu entry to select and bring the source line into view. - *Click* the ![](img/flame-icon.png) icon to jump to the slowest source line in the function. - *Click* the +/- buttons to jump to the next/previous slowest source line in the sequence. [![Profiling UI screenshot](img/source-profile_920x251.png){: style="width:550px"}](img/source-profile_920x251.png){:target="_blank"} ##### Outline Displays a menu that summarizes the nested statements and their execution time. See the [Source code outline](#source-code-outline) section above for documentation. ##### Instances The Instances menu displays the call paths leading to all instances of the function, with their execution time percentage and value, similar to the *Assembly* view feature. See the [Profiling toolbar: Instances](assembly-view.md#instances) section in the *Assembly* view page for details. ##### Threads The Threads menu displays the threads IDs and their execution time percentage and value, similar to the *Assembly* view feature. See the [Profiling toolbar: Threads](assembly-view.md#threads) section in the *Assembly* view page for details. #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/source-toolbar-open.png) | Shows an *Open File* dialog to select a local source file to load in the view. | | ![](img/source-toolbar-reset.png) | Displays a menu with options for resetting exclusions set on the current source file or all source files. | | ![](img/source-toolbar-path.png) | Displays a menu with options for copying the source file path to clipboard, navigating to the source file in *File Explorer* and opening the source file in the default editor. | | ![](img/flame-graph-toolbar-sync.png) | If enabled, selecting a source lines also selects all associated instructions in the *Assembly* view. | | ![](img/source-toolbar-asm.png) | If enabled, each source line is followed by a section with the assembly instructions generated for it, based on the debug info file. See [Assembly code sections](#assembly-code-sections) above for details. | | ![](img/source-toolbar-asm-collapse.png) | Hides (collapses) all assembly sections. | | ![](img/source-toolbar-asm-expand.png) | Shows (expands) all assembly sections. | | ![](img/assembly-toolbar-popup.png) | Opens the current source file into a new preview popup. | #### Exporting The function's source code, combined with profiling annotations and execution time can be exported and saved into multiple formats, with the slowest source lines marked using a similar style as in the application: - Excel worksheet (*.xlsx) [![Profiling UI screenshot](img/source-export-excel_876x439.png){: style="width:480px"}](img/source-export-excel_876x439.png){:target="_blank"} - HTML table (*.html) [![Profiling UI screenshot](img/source-export-html_926x537.png){: style="width:480px"}](img/source-export-html_926x537.png){:target="_blank"} - Markdown table (*.md) [![Profiling UI screenshot](img/source-export-markdown_987x453.png){: style="width:480px"}](img/source-export-markdown_987x453.png){:target="_blank"} The Export menu in the toolbar also has an option to copy to clipboard the function's source code as a HTML/Markdown table (pasting in an application supporting HTML - such as the Microsoft Office suite and online editors - will use the HTML version, code/text editors will use Markdown version instead). The *Ctrl+C* keyboard shortcut copies to the clipboard only the selected source lines as a HTML/Markdown table. #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Source File* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/source-options-general_599x702.png){: style="width:400px"}](img/source-options-general_599x702.png){:target="_blank"} === "Source Files" [![Profiling UI screenshot](img/source-options-files_590x441.png){: style="width:400px"}](img/source-options-files_590x441.png){:target="_blank"} === "Profiling" [![Profiling UI screenshot](img/source-options-profiling_591x583.png){: style="width:400px"}](img/source-options-profiling_591x583.png){:target="_blank"} #### More documentation in progress - options panel ================================================ FILE: docs/docs/style.css ================================================ .md-typeset h4 { font-size: 18px; } .md-typeset h5 { text-transform: none; font-size: 16px; font-weight: 600; padding: 0; margin: 0; } .md-typeset h1, .md-content__button { display: none; } .md-content__inner { padding-top: 0; } .md-main__inner { margin-top: 0; } .md-typeset__table { line-height: 1; } .md-typeset__table table:not([class]) { font-size: .8rem; } .md-typeset table:not([class]) th, .md-typeset table:not([class]) td { padding: 8px 12px; vertical-align:middle; } .md-typeset .admonition,.md-typeset details { font-size: .7rem; } .md-typeset table:not([class]) { overflow: hidden; } .md-typeset .admonition, .md-typeset details { border-width: 0; border-bottom-width: 1px; } li + li { margin-top: -5px; } .md-typeset .tabbed-labels>label { font-size: .7rem; color:black; } html { font-size:larger; } ================================================ FILE: docs/docs/summary-panel.md ================================================ #### Overview The summary view displays all modules (binaries) and functions that have profile data in the trace, making it easy to identify the functions where most time is spent — otherwise known as application hotspots. [![Profiling UI screenshot](img/summary-panel_1233x417.png)](img/summary-panel_1233x417.png){:target="_blank"} The view has three parts: - a toolbar at the top, with action buttons and the *Search* input box. - the Modules panel on the left side. Its visibility can be toggled using the *Modules* button in the toolbar. - the list of functions from either the entire trace or filtered to display only the functions part of a single module. By default, the list is sorted by self (exclusive) time in descending order. ##### Modules list The modules list has an entry for each module with profile data and starts with an *All* entry representing all modules combined. Each entry has the module name, total (inclusive) execution time percentage relative to the entire trace and the time value, with a background color based on its name. Modules are sorted by their execution time in descending order. By default, the *All* entry is active and the function list displays all functions with profile data in the trace. *Double-click* a module (or press the *Return* key) to display only its functions. Selecting a module while the *All* entry is active selects its functions in the list. ##### Functions list The function list has an entry for each function with profile data. Each entry has: - the [demangled](https://en.wikipedia.org/wiki/Name_mangling) (undecorated) function name. - module name, a background color based on its name. - self (exclusive) execution time percentage relative to the entire trace and the time value. - total (inclusive) execution time percentage relative to the entire trace and the time value. - optionally, the mangled (decorated) function name, configurable in the [Summary options](#view-options). If CPU performance counters are found and loaded from the trace, the additional columns with metrics and the counters are appended after the last column. The list is filtered based on the active module. The function list is by default sorted by the self (exclusive) execution time in decreasing sorting order. The displayed columns and style can be customized in the [Summary options](#view-options). *Click* the same column header to toggle between decreasing and increasing sorting order. *Click* on a column to sort the list based on its values. ???+ note The same sorting actions apply to other list views in the application. Not all list views support sorting currently. The columns in all list views can be resized and reorder. The new layout is saved across sessions when closing the application. If marking of functions based on name or module is active, the function entries use the matching marking background color. Hovering over a function displays a popup with the slowest stack trace (call path) ending at the function instance with most execution time. Pin or drag the popup to keep it open. [![Profiling UI screenshot](img/summary-preview_654x551.png){: style="width:450px"}](img/summary-preview_654x551.png){:target="_blank"} #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/flame-graph-toolbar-sync.png) | If enabled, selecting a function also selects it in the other profiling views. | | ![](img/flame-graph-toolbar-source.png) | If enabled, selecting a function also displays the source in the *Source File* view, with the source lines annotated with profiling data. | | Export | Export the current function list into one of multiple formats (Excel, HTML and Markdown) or copy to clipboard the function list as a HTML/Markdown table. | | Search box | Search for functions with a specific name using a case-insensitive substring search. Searching filters the list down to display only the matching entries. Press the *Escape* key to reset the search or the *X* button next to the input box. | | ![](img/summary-toolbar-up.png) | Scrolls up the list to the start (equivalent to pressing *Ctrl+Home*). | ???+ abstract "Mouse shortcuts" | Action | Description | | ------ | ------------| | Hover | Hovering over a function displays a popup with the stack trace (call path) end with the slowest function's instance. Pin or drag the popup to keep it open.| | Click | Selects the function in the other views if *Sync* is enabled in the toolbar and displays the source in the *Source File* view if *Source* is enabled in the toolbar. | | Double-click | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Double-click | Opens the *Assembly* view of the selected function in a new tab. | | Right-click | Shows the context menu for the selected functions. | !!! note When multiple functions are selected, the application status bar displays the sum of their execution time as a percentage and value. ???+ abstract "Keyboard shortcuts" | Keys | Description | | ------ | ------------| | Return | Opens the *Assembly* view of the selected function in the active tab. | | Ctrl+Return | Opens the *Assembly* view of the selected function in a new tab. | | Ctrl+Left | Opens the *Assembly* view of the selected function in a new tab docked to the left of the active tab. | | Ctrl+Right | Opens the *Assembly* view of the selected function in a new tab docked to the right of the active tab. | | Alt+Return | Opens a preview popup with the assembly of the selected function. Press the *Escape* key to close the popup.

Multiple preview popups can be can be kept open at the same time. | | Ctrl+C | Copies to clipboard a HTML and Markdown table with a summary of the selected functions. | | Ctrl+Shift+C | Copies to clipboard the function names of the selected functions. | | Ctrl+Alt+C | Copies to clipboard the mangled/decorated function names of the selected functions. | ???+ abstract "Right-click context menu" [![Profiling UI screenshot](img/summary-context-menu_569x661.png){: style="width:380px"}](img/summary-context-menu_569x661.png){:target="_blank"} #### Exporting the function list The current function list can be exported and saved into multiple formats, with the slowest functions marked using a similar style as in the application: - Excel worksheet (*.xlsx) [![Profiling UI screenshot](img/summary-export-excel_1366x327.png)](img/summary-export-excel_1366x327.png){:target="_blank"} - HTML table (*.html) [![Profiling UI screenshot](img/summary-export-html_1209x287.png)](img/summary-export-html_1209x287.png){:target="_blank"} - Markdown table (*.md) [![Profiling UI screenshot](img/summary-export-markdown_1003x172.png)](img/summary-export-markdown_1003x172.png){:target="_blank"} The *Export* menu in the toolbar also has an option to copy to the clipboard the current function list as an HTML/Markdown table (pasting in an application supporting HTML - such as the Microsoft Office suite and online editors - will use the HTML version, code/text editors will use Markdown version instead).   The *Ctrl+C* keyboard shortcut copies to the clipboard only the selected functions as a HTML/Markdown table. #### View options *Click* on the *Gears* icon in the top-right part of the view displays the options panel (alternatively, use the *Summary* tab in the application *Settings* window.). The tabs below describe each page of the options panel: === "General" [![Profiling UI screenshot](img/summary-options-general_575x573.png){: style="width:400px"}](img/summary-options-general_575x573.png){:target="_blank"} === "Profiling" [![Profiling UI screenshot](img/summary-options-general_577x398.png){: style="width:400px"}](img/summary-options-general_577x398.png){:target="_blank"} #### More documentation in progress - Context menu - Marking functions - Options ================================================ FILE: docs/docs/timeline-panel.md ================================================ #### Overview The Timeline view displays the application's activity for the entire trace duration, with each thread having a histogram showing the CPU usage based on the number of profile samples collected over time. This view helps identify the threads and time ranges with CPU activity (or lack thereof due to locks and I/O). It also has features for filtering the entire profile data to consider only specific threads and time ranges.   [![Profiling UI screenshot](img/timeline-view_1028x418.png)](img/timeline-view_1028x418.png){:target="_blank"} The view has three parts: - a main toolbar at the top, with general action buttons. - a graph showing the activity of the entire application, with the activity across all threads combined. - for each thread, a graph showing the thread's activity. The thread list is sorted by the execution time in descending order. The *All Threads* entry displays the trace duration range on top, split into time units. The maximum number of CPU cores the application uses is displayed on the left. Individual threads use, at most, one core.   Each individual thread entry has the following values and buttons: [![Profiling UI screenshot](img/timeline-threads_599x159.png){: style="width:500px"}](img/timeline-threads_599x159.png){:target="_blank"} - thread visibility button indicating if the samples from the thread are included in the profile data or not. *Click* to toggle between included ![](img/timeline-eye-button.png) or excluded state ![](img/timeline-eye-button-disabled.png). - thread context menu button ![](img/timeline-menu-button.png) that shows thread filtering actions. - the thread ID number. - the thread execution time as a sum of the duration of all samples that ran on the thread. - if available in the trace, the thread name. #### Mouse actions *Moving* the mouse over the graphs shows the time position and the approximate number of cores used at that point. [![Profiling UI screenshot](img/timeline-position_570x116.png){: style="width:500px"}](img/timeline-position_570x116.png){:target="_blank"} *Hovering* with the mouse over the graph shows a preview popup with the slowest call path (stack trace) active at that point. [![Profiling UI screenshot](img/timeline-hover_829x394.png){: style="width:600px"}](img/timeline-hover_829x394.png){:target="_blank"} *Clicking* a thread ID or name creates a time range selection for the thread covering the entire trace duration. If *Sync* is enabled in the toolbar, all functions executing on the selected thread are also selected in the other profiling views. ##### Selecting a time range - To select a time range that includes all threads, *click and drag* over the desired range in the top *All Threads* graph. The duration of the current selection is displayed in the top *All Threads* graph. Note that if some threads are excluded, the selection will not consider them.   [![Profiling UI screenshot](img/timeline-select_879x239.png)](img/timeline-select_879x239.png){:target="_blank"} - To select a time range for a single thread, *click and drag* over the desired range in the specific thread graph. To include another thread in the same time range, from the thread action menu, **click* *Include thread* or use the ![](img/timeline-eye-button.png) icon.   [![Profiling UI screenshot](img/timeline-select-single_879x199.png)](img/timeline-select-single_879x199.png){:target="_blank"} ???+ note If the *Sync* option is enabled, selecting a time range also selects the functions executing during that time in the other profiling views, considering if all threads or a subset are included. #### Filtering the profile The entire profile can be filtered so that only specific threads and time ranges are displayed, with the profiling views updated to include only the profile samples accepted by the filter. The active filter is displayed in both the toolbar and the application menu bar. ##### Filtering based on a time range Select the desired time range, then *double-click* the selection (alternatively, *right-click* the selection and *click* "Filter to Time Range*). If a single thread is selected, a filter that displays only the selected thread and excludes all others is also added.   [![Profiling UI screenshot](img/timeline-filter-time_878x320.png)](img/timeline-filter-time_878x320.png){:target="_blank"} ##### Filtering based on a thread There are multiple ways to filter based on one or multiple threads, optionally combined with a time range filter. [![Profiling UI screenshot](img/timeline-thread-menu_480x317.png){: style="width:350px"}](img/timeline-thread-menu_480x317.png){:target="_blank"} - to include a single thread and exclude all others, *double-click* the thread ID or *click* *Filter to Thread* from the thread action menu. - to include another thread, *click* the ![](img/timeline-eye-button-disabled.png) icon or *click* *Include Thread*. - to include all threads with the same name and exclude all others, *click* *Filter to Same Name Threads*. - to include all threads with the same name, *click* *Filter to Same Name Threads*. - to exclude a thread, *click* the ![](img/timeline-eye-button.png) icon or *click* *Exclude Thread*. - to exclude all threads with the same name, *click* *Exclude Same Name Threads*. Example of a filter including a single thread (58540) and a time range of ~2 sec. Excluded threads and time ranges are displayed using faded colors. Use the X buttons next to *Time* and *Threads* in the toolbar to remove the filter. [![Profiling UI screenshot](img/timeline-filter-time-thread_889x317.png)](img/timeline-filter-time-thread_889x317.png){:target="_blank"} #### Marking samples The samples corresponding to a function instance can be marked from the *Flame Graph* view using the right-click context menu of a node and selecting a color from the *Mark In Timeline* menu entry. [![Profiling UI screenshot](img/timeline-mark-menu_907x233.png)](img/timeline-mark-menu_907x233.png){:target="_blank"} The *Markers* menu in the toolbar displays the currently marked functions. *Click* on a menu entry to remove the marker. [![Profiling UI screenshot](img/timeline-marking_929x333.png)](img/timeline-marking_929x333.png){:target="_blank"} #### View interaction ???+ abstract "Toolbar" | Button | Description | | ------ | ------------| | ![](img/flame-graph-toolbar-reset.png) | Resets the view to it's original state, displaying the thread graphs for the entire trace duration. | | ![](img/flame-graph-toolbar-minus.png) | Zooms out the thread graphs and updates the time units. | | ![](img/flame-graph-toolbar-plus.png) | Zooms in the thread graphs and updates the time units. | | ![](img/flame-graph-toolbar-sync.png) | If enabled, selecting a time range also selects executing during that time in the other profiling views. | | Markers | Search for nodes with a specific function name using a case-insensitive substring search. Press the *Escape* key to reset the search or the *X* button next to the input box. | #### Documentation in progress - View options ================================================ FILE: docs/docs/trace-loading.md ================================================ #### Loading a new trace There are several ways to open a new ETW trace file (*.etl): - Use the **Open** button in the *Start Page* displayed on startup. - Use the **Profiling** -> **Load Profile** menu. - Use the **Ctrl+O** keyboard shortcut. Once the trace file is selected in the *Open File dialog*, the **Load profile trace** window is displayed. It lists the processes (applications) that are captured in the trace, sorted by weight (number of samples). [![Load profile window screenshot](img/load-trace_1332x738.png)](img/load-trace_1332x738.png){:target="_blank"} From the list, select the process you want to analyze and *click* the **Load Profile** button (alternatively, *double-click* or press the *Return* key). The selected process is loaded from the trace file, any required binary and symbol files are downloaded and the profiling data is analyzed. Once loading is completed, the window closes and the profiling views are populated, as described in [Profiling UI overview](profiling-ui.md). ???+ note If the trace fails to load, the *Profiling Trace Report* windows is automatically opened. The *Modules tab* lists the modules referenced by the trace and indicates whether the binary and debug info symbols could be found and loaded. See the [Profiling Trace report](trace-overview.md) page for more details. #### Loading a previously opened trace Previously opened traces are saved as sessions. Recent sessions can be quickly opened again for the same process using either the *Start page* or the session list on the left of the *Load profile trace* window (*double-click* an entry or press the *Return* key). [![Start page screenshot](img/start-page_825x459.png)](img/start-page_825x459.png){:target="_blank"} #### Symbols configuration Symbols are the binary (EXE/DLL) and debug info (PDB) files required to analyze the processes recorded in a trace. The binaries are used to disassembly individual functions and the debug files are used to resolve function names and provide the source file and line number information. [![Load profile window options screenshot](img/symbols_1332x826.png)](img/symbols_1332x826.png){:target="_blank"} ##### Symbol paths Symbols are searched in the locations indicated by the **Symbol Paths** list, found in the **Symbols** tab of the *Load profile trace* window. Symbol locations can be of two types: - Paths to local directories or network file shares. - Symbol server URLs. By default, the [Microsoft public symbol server](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/microsoft-public-symbols) is added to the list, with a local download cache directory at *C:\Symbols*. !!! note More info about symbol servers and the symbol path syntax is available here: [https://learn.microsoft.com/en-us/windows/win32/debug/using-symsrv](https://learn.microsoft.com/en-us/windows/win32/debug/using-symsrv) ##### Missing debug info symbols When the debug info symbols (PDB file) for a module cannot be found, the names of the functions used by the app during the trace are replaced by their *Relative virtual address* (RVA) as a hexadecimal value (*127F* for example). You can use the logs from the [Trace view report](trace-overview.md) to understand why symbols could not be found, such as using wrong local directory paths or a symbol server being unreachable. ##### Additional symbol options | Option | Description | | ------ | ------------| | Include __NT__SYMBOL__PATH environment variable | Append the environment variable's value to the list of searched symbol paths. | | Include subdirectories for local paths | Consider symbols in sub-directories up to 3 levels deep for the local directories in the *Symbols Paths* list. | | Don't load symbols for very low sample modules | Skip downloading and loading of symbols for modules with a low number of samples. This helps reduce download time for processes with many modules, where the majority have few relevant samples.

A module is skipped if it has fewer samples than a threshold. This threshold can be configured using the *Minimum samples* field as a percentage of the total number of samples. | | Don't load symbols that failed in previous sessions | Skip downloading and loading of symbols that could not be found in previous sessions (for example, due to offline symbol servers). The list of skipped symbols can be viewed and cleared. | | Cache processed symbol files | Cache the processed debug symbol files and use them to speed up loading of traces requiring the same symbols. The cache files are saved in the temporary directory and can be viewed and cleared. | #### Trace processing options [![Load profile window options screenshot](img/load-options__1332x648.png)](img/load-options__1332x648.png){:target="_blank"} | Option | Description | | ------ | ------------| | Handle Kernel profile samples | Include samples executing in the kernel context and connect the call stacks between kernel and user mode code. | | Handle CPU performance counter samples | Process CPU performance counter (PMC) events and display them in the Summary, Assembly and *Source File* views using additional columns. | | Download source files from Source Server | Automatically attempt to download source files from the location indicated by the debug info file. If the download URL requires authentication, it can be configured in the Authentication section found below. | ##### Authentication Authentication using an user/email address and Personal Autehnticaion token (PAT) can be configured for both source file servers and symbol servers. ##### Binary files Additional local directory paths for searching binary files can be configured. The binary files to process in a trace can be restricted to only the ones in the accepted list. ================================================ FILE: docs/docs/trace-overview.md ================================================ #### Overview The *Profiling Trace Report* window provides details of the current profiling session, including the loaded trace path and process name/ID, trace recording time and duration, and the machine used to record the trace. A list of modules referenced by the profiled code is also included, with the symbol search result for both binary and debug info files. The symbol search logs can help you understand why symbols could not be found, such as using wrong local directory paths or a symbol server being unreachable. To view the report, once a trace is loaded *click* *Profiling report* from the *Profiling* menu. The report is also automatically displayed if a trace fails to load. ##### Summary [![Profiling UI screenshot](img/report-general_931x507.png)](img/report-general_931x507.png){:target="_blank"} ##### Modules Once a module is selected, the *Image file* and *Debug file* tabs are updated to show the symbol info used to look up the symbols. [![Profiling UI screenshot](img/report-modules_969x815.png)](img/report-modules_969x815.png){:target="_blank"} The *Logs* section displays the list of symbol search paths used during the search and the steps taken by the algorithm. ???+ tip If a symbol file is found, but there is a timestamp/checksum mismatch, the symbol is not used and the next search path is queried. If no matching symbols are found for the module, it usually means that the symbols are from a different version of the application than the one recorded in the trace. [![Profiling UI screenshot](img/report-debug_963x428.png)](img/report-debug_963x428.png){:target="_blank"} ================================================ FILE: docs/docs/trace-recording.md ================================================ ???+ note The documentation is currently being worked on. #### Recording a trace ETW traces can be recorded directly from the app in several ways: - starting a new process. - attaching to a running process. - system-wide (default ETW recording mode). There are several ways to start a recording: - Use the **Record** button in the *Start Page* displayed on startup. - Use the **Profiling** -> **Record Profile** menu. [![Profiling UI screenshot](img/record-start-app_1332x830.png)](img/record-start-app_1332x830.png){:target="_blank"} ================================================ FILE: docs/docs/workspaces ================================================ ???+ note The documentation is currently being worked on. ================================================ FILE: docs/mkdocs.yml ================================================ site_name: Profile Explorer use_directory_urls: false nav: - Introduction: intro.md - Getting started: - About: about.md - Profiling UI overview: profiling-ui.md - Video Demos: demos.md - Trace loading and recording: - Loading a trace: trace-loading.md - Recording a trace: trace-recording.md - Profiling Trace report: trace-overview.md - Trace profile views: - Summary view: summary-panel.md - Flame Graph view: flame-graph-panel.md - Timeline view: timeline-panel.md - Call Tree view: call-tree-panel.md - Caller/Callee view: caller-panel.md - Function profile views: - Assembly view: assembly-view.md - Source File view: source-panel.md - Flow Graph view: flow-graph-panel.md - Additional functionality: - Trace profile overview: profile-overview.md - Function/module marking: profile-marking.md - Workspaces: workspaces.md - Application options: options.md - Rust support: rust.md theme: logo: img/logo.png favicon: img/favicon.png name: 'material' font: text: Roboto code: Roboto Mono palette: # Palette toggle for light mode - scheme: default primary: blue toggle: icon: material/brightness-7 name: Switch to dark mode # Palette toggle for dark mode - scheme: slate primary: black toggle: icon: material/brightness-4 name: Switch to light mode features: - navigation.expand - navigation.instant - navigation.top - header.autohide - navigation.footer extra: generator: false extra_css: - style.css markdown_extensions: - admonition - attr_list - pymdownx.details - pymdownx.superfences - pymdownx.tabbed: alternate_style: true ================================================ FILE: installer/arm64/installer.iss ================================================ ; -- Example1.iss -- ; Demonstrates copying 3 files and creating an icon. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES! #include "../environment.iss" #define MyAppName "Profile Explorer" #define MyAppExeName "ProfileExplorer.exe" [Setup] AppName=Profile Explorer AppVersion={#APP_VERSION} WizardStyle=modern DisableDirPage=no DefaultDirName={autopf}\Profile Explorer DefaultGroupName=Profile Explorer UninstallDisplayIcon={app}\ProfileExplorer.exe Compression=lzma2 SolidCompression=yes OutputDir=userdocs:ProfileExplorer ChangesAssociations = yes ChangesEnvironment = yes OutputBaseFilename=profile_explorer_installer_{#APP_VERSION}_arm64 [Registry] Root: HKCR; Subkey: "{#MyAppName}"; ValueData: "Program {#MyAppName}"; Flags: uninsdeletekey; ValueType: string; ValueName: "" Root: HKCR; Subkey: "{#MyAppName}\DefaultIcon"; ValueData: "{app}\{#MyAppExeName},0"; ValueType: string; ValueName: "" Root: HKCR; Subkey: "{#MyAppName}\shell\open\command"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; ValueType: string; ValueName: "" [Files] Source: ".\out\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs [Icons] Name: "{group}\Profile Explorer"; Filename: "{app}\ProfileExplorer.exe" [Tasks] Name: envPath; Description: "Add to PATH env. variable as ProfileExplorer.exe" [Run] Filename: "{sys}\Regsvr32.exe"; Parameters: "/s msdia140.dll"; WorkingDir: "{app}"; Flags: shellexec runhidden; [Code] procedure CurStepChanged(CurStep: TSetupStep); begin if (CurStep = ssPostInstall) and IsTaskSelected('envPath') then EnvAddPath(ExpandConstant('{app}')); end; ================================================ FILE: installer/arm64/prepare-installer.cmd ================================================ set %_VERSION="1.2.1" iscc.exe installer.iss /DAPP_VERSION=%_VERSION% /O%cd% ================================================ FILE: installer/arm64/prepare-out.cmd ================================================ set _PUBLISH_PATH="publish" set _BUILD_TARGET="..\..\src\ProfileExplorerUI\ProfileExplorerUI.csproj" set _PROFILER_PATH="..\..\src\ManagedProfiler" set _EXTERNALS_PATH="..\..\src\external" set _EXTERNALS_PATH_ARM64="..\..\src\external\arm64" set _RESOURCES_PATH="..\..\resources" set _REPO_PATH="..\.." set _OUT_PATH="out" rd %_OUT_PATH% /s /q rd %_PUBLISH_PATH% /s /q mkdir %_OUT_PATH% dotnet publish -c "Release" -r win-arm64 --self-contained true --verbosity diagnostic --output %_PUBLISH_PATH% %_BUILD_TARGET% for /f "delims=" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -all -prerelease -property installationPath') do set _VS=%%i set _VS_ENV=%_VS%\VC\Auxiliary\Build\vcvarsamd64_arm64.bat call "%_VS_ENV%" pushd %_EXTERNALS_PATH% call build-external-arm64.cmd popd msbuild %_PROFILER_PATH%\ManagedProfiler.vcxproj /t:Rebuild /p:Configuration=Release /p:Platform=arm64 copy %_PROFILER_PATH%\arm64\Release\ManagedProfiler.dll %_OUT_PATH% xcopy %_PUBLISH_PATH% %_OUT_PATH% /i /c /e /y xcopy %_RESOURCES_PATH% %_OUT_PATH% /i /c /e /y xcopy %_EXTERNALS_PATH_ARM64%\*.dll %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH_ARM64%\config6 %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH%\tree-sitter\build_arm64\*.dll %_OUT_PATH% /i /c /y copy %_EXTERNALS_PATH%\capstone\build_arm64\Release\capstone.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\cmd\dot\Release\dot.exe %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\cdt\Release\cdt.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\cgraph\Release\cgraph.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\gvc\Release\gvc.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\pathplan\Release\pathplan.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\lib\xdot\Release\xdot.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\plugin\core\Release\gvplugin_core.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build_arm64\plugin\dot_layout\Release\gvplugin_dot_layout.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\zlib1.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\libexpat.dll %_OUT_PATH% copy %_REPO_PATH%\NOTICE.md %_OUT_PATH% ================================================ FILE: installer/arm64/prepare.cmd ================================================ call prepare-out.cmd call prepare-installer.cmd ================================================ FILE: installer/environment.iss ================================================ [Code] const EnvironmentKey = 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment'; procedure EnvAddPath(Path: string); var Paths: string; begin { Retrieve current path (use empty string if entry not exists) } if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then Paths := ''; { Skip if string already found in path } if Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';') > 0 then exit; { App string to the end of the path variable } Paths := Paths + ';'+ Path +';' { Overwrite (or create if missing) path environment variable } if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then Log(Format('The [%s] added to PATH: [%s]', [Path, Paths])) else Log(Format('Error while adding the [%s] to PATH: [%s]', [Path, Paths])); end; procedure EnvRemovePath(Path: string); var Paths: string; P: Integer; begin { Skip if registry entry not exists } if not RegQueryStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then exit; { Skip if string not found in path } P := Pos(';' + Uppercase(Path) + ';', ';' + Uppercase(Paths) + ';'); if P = 0 then exit; { Update path variable } Delete(Paths, P - 1, Length(Path) + 1); { Overwrite path environment variable } if RegWriteStringValue(HKEY_LOCAL_MACHINE, EnvironmentKey, 'Path', Paths) then Log(Format('The [%s] removed from PATH: [%s]', [Path, Paths])) else Log(Format('Error while removing the [%s] from PATH: [%s]', [Path, Paths])); end; ================================================ FILE: installer/x64/installer.iss ================================================ ; -- Example1.iss -- ; Demonstrates copying 3 files and creating an icon. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES! #include "../environment.iss" #define MyAppName "Profile Explorer" #define MyAppExeName "ProfileExplorer.exe" [Setup] AppName=Profile Explorer AppVersion={#APP_VERSION} WizardStyle=modern DisableDirPage=no DefaultDirName={autopf}\Profile Explorer DefaultGroupName=Profile Explorer UninstallDisplayIcon={app}\ProfileExplorer.exe Compression=lzma2 SolidCompression=yes OutputDir=userdocs:ProfileExplorer ChangesAssociations = yes ChangesEnvironment = yes OutputBaseFilename=profile_explorer_installer_{#APP_VERSION}_x64 [Registry] Root: HKCR; Subkey: "{#MyAppName}"; ValueData: "Program {#MyAppName}"; Flags: uninsdeletekey; ValueType: string; ValueName: "" Root: HKCR; Subkey: "{#MyAppName}\DefaultIcon"; ValueData: "{app}\{#MyAppExeName},0"; ValueType: string; ValueName: "" Root: HKCR; Subkey: "{#MyAppName}\shell\open\command"; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; ValueType: string; ValueName: "" [Files] Source: ".\out\\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs [Icons] Name: "{group}\Profile Explorer"; Filename: "{app}\ProfileExplorer.exe" [Tasks] Name: envPath; Description: "Add to PATH env. variable as ProfileExplorer.exe" [Run] Filename: "{sys}\Regsvr32.exe"; Parameters: "/s msdia140.dll"; WorkingDir: "{app}"; Flags: shellexec runhidden; [Code] procedure CurStepChanged(CurStep: TSetupStep); begin if (CurStep = ssPostInstall) and IsTaskSelected('envPath') then EnvAddPath(ExpandConstant('{app}')); end; ================================================ FILE: installer/x64/prepare-installer.cmd ================================================ set %_VERSION="1.2.1" iscc.exe installer.iss /DAPP_VERSION=%_VERSION% /O%cd% ================================================ FILE: installer/x64/prepare-out.cmd ================================================ set _PUBLISH_PATH="publish" set _BUILD_TARGET="..\..\src\ProfileExplorerUI\ProfileExplorerUI.csproj" set _PROFILER_PATH="..\..\src\ManagedProfiler" set _EXTERNALS_PATH="..\..\src\external" set _RESOURCES_PATH="..\..\resources" set _REPO_PATH="..\.." set _OUT_PATH="out" rd %_OUT_PATH% /s /q rd %_PUBLISH_PATH% /s /q mkdir %_OUT_PATH% dotnet publish -c "Release" -r win-x64 --self-contained --verbosity diagnostic --output %_PUBLISH_PATH% %_BUILD_TARGET% for /f "delims=" %%i in ('"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -all -prerelease -property installationPath') do set _VS=%%i set _VS_ENV=%_VS%\VC\Auxiliary\Build\vcvars64.bat call "%_VS_ENV%" pushd %_EXTERNALS_PATH% call build-external.cmd popd msbuild %_PROFILER_PATH%\ManagedProfiler.vcxproj /t:Rebuild /p:Configuration=Release /p:Platform=x64 copy %_PROFILER_PATH%\x64\Release\ManagedProfiler.dll %_OUT_PATH% xcopy %_PUBLISH_PATH% %_OUT_PATH% /i /c /e /y xcopy %_RESOURCES_PATH% %_OUT_PATH% /i /c /e /y xcopy %_EXTERNALS_PATH%\config6 %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH%\*.dll %_OUT_PATH% /i /c /y xcopy %_EXTERNALS_PATH%\tree-sitter\build\*.dll %_OUT_PATH% /i /c /y copy %_EXTERNALS_PATH%\capstone\build\Release\capstone.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\cmd\dot\Release\dot.exe %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\cdt\Release\cdt.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\cgraph\Release\cgraph.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\gvc\Release\gvc.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\pathplan\Release\pathplan.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\lib\xdot\Release\xdot.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\plugin\core\Release\gvplugin_core.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\build\plugin\dot_layout\Release\gvplugin_dot_layout.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\zlib1.dll %_OUT_PATH% copy %_EXTERNALS_PATH%\graphviz\windows\dependencies\libraries\vcpkg\installed\x64-windows\bin\libexpat.dll %_OUT_PATH% copy %_REPO_PATH%\NOTICE.md %_OUT_PATH% ================================================ FILE: installer/x64/prepare.cmd ================================================ call prepare-out.cmd call prepare-installer.cmd ================================================ FILE: resources/asm/arm64-asm.xshd ================================================ " " define global declare bl\s+.* blr\s+.* b br cbz cbnz tbz tbnz b br beq bne blt ble bgt bge ret abs adc adclb adclt adcs add addg addha addhn addhn2 addhnb addhnt addp addpl addpt addqv adds addspl addsvl addv addva addvl adr adrp aesd aese aesimc aesmc and andqv ands andv asr asrd asrr asrv at autda autdb autdza autdzb autia autia1716 autiasp autiaz autib autib1716 autibsp autibz autiza autizb axflag b bcax bcc b.cc bcs b.cs bdep beq b.eq bext bf1cvt bf1cvtl bf1cvtl2 bf1cvtlt bf2cvt bf2cvtl bf2cvtl2 bf2cvtlt bfadd bfc bfclamp bfcvt bfcvtn bfcvtn2 bfcvtnt bfdot bfi bfm bfmax bfmaxnm bfmin bfminnm bfmla bfmlal bfmlalb bfmlalt bfmls bfmlsl bfmlslb bfmlslt bfmmla bfmopa bfmops bfmul bfsub bfvdot bfxil bge b.ge bgrp bgt b.gt bhi bhs b.hs bic bics bif bit bl ble b.le blo b.lo blr blraa blraaz blrab blrabz bls b.ls blt b.lt bmi b.mi bmopa bmops bne b.ne bpl b.pl br braa braaz brab brabz brb brk brka brkas brkb brkbs brkn brkns brkpa brkpas brkpb brkpbs bsl bsl1n bsl2n bti bvc b.vc bvs b.vs cadd cas casa casab casah casal casalb casalh casb cash casl caslb caslh casp caspa caspal caspl cbnz cbz ccmn ccmp cdot cfinv cfp chkfeat cinc cinv clasta clastb clearbhb clrbhb clrex cls clz cmeq cmge cmgt cmhi cmhs cmla cmle cmlt cmn cmp cmpeq cmpge cmpgt cmphi cmphs cmple cmplo cmpls cmplt cmpne cmpp cmtst cneg cnot cnt cntb cntd cnth cntp cntw compact cosp cpp cpy crc32b crc32cb crc32ch crc32cw crc32cx crc32h crc32w crc32x csdb csel cset csetm csinc csinv csneg ctermeq ctermne ctz dc dcps1 dcps2 dcps3 decb decd dech decp decw dfb dgh dmb drps dsb dup dupm dupq dvp eon eor eor3 eorbt eorqv eors eortb eorv eret eretaa eretab esb ext extq extr f1cvt f1cvtl f1cvtl2 f1cvtlt f2cvt f2cvtl f2cvtl2 f2cvtlt fabd fabs facge facgt facle faclt fadd fadda faddp faddqv faddv famax famin fcadd fccmp fccmpe fclamp fcmeq fcmge fcmgt fcmla fcmle fcmlt fcmne fcmp fcmpe fcmuo fcpy fcsel fcvt fcvtas fcvtau fcvtl fcvtl2 fcvtlt fcvtms fcvtmu fcvtn fcvtn2 fcvtnb fcvtns fcvtnt fcvtnu fcvtps fcvtpu fcvtx fcvtxn fcvtxn2 fcvtxnt fcvtzs fcvtzu fdiv fdivr fdot fdup fexpa fjcvtzs flogb fmad fmadd fmax fmaxnm fmaxnmp fmaxnmqv fmaxnmv fmaxp fmaxqv fmaxv fmin fminnm fminnmp fminnmqv fminnmv fminp fminqv fminv fmla fmlal fmlal2 fmlalb fmlall fmlallbb fmlallbt fmlalltb fmlalltt fmlalt fmls fmlsl fmlsl2 fmlslb fmlslt fmmla fmopa fmops fmov fmsb fmsub fmul fmulx fneg fnmad fnmadd fnmla fnmls fnmsb fnmsub fnmul frecpe frecps frecpx frint32x frint32z frint64x frint64z frinta frinti frintm frintn frintp frintx frintz frsqrte frsqrts fscale fsqrt fsub fsubr ftmad ftsmul ftssel fvdot fvdotb fvdott gcsb gcspopcx gcspopm gcspopx gcspushm gcspushx gcsss1 gcsss2 gcsstr gcssttr gmi hint histcnt histseg hlt hvc ic incb incd inch incp incw index ins insr irg isb lasta lastb ld1 ld1b ld1d ld1h ld1q ld1r ld1rb ld1rd ld1rh ld1rob ld1rod ld1roh ld1row ld1rqb ld1rqd ld1rqh ld1rqw ld1rsb ld1rsh ld1rsw ld1rw ld1sb ld1sh ld1sw ld1w ld2 ld2b ld2d ld2h ld2q ld2r ld2w ld3 ld3b ld3d ld3h ld3q ld3r ld3w ld4 ld4b ld4d ld4h ld4q ld4r ld4w ld64b ldadd ldadda ldaddab ldaddah ldaddal ldaddalb ldaddalh ldaddb ldaddh ldaddl ldaddlb ldaddlh ldap1 ldapr ldaprb ldaprh ldapur ldapurb ldapurh ldapursb ldapursh ldapursw ldar ldarb ldarh ldaxp ldaxr ldaxrb ldaxrh ldclr ldclra ldclrab ldclrah ldclral ldclralb ldclralh ldclrb ldclrh ldclrl ldclrlb ldclrlh ldclrp ldclrpa ldclrpal ldclrpl ldeor ldeora ldeorab ldeorah ldeoral ldeoralb ldeoralh ldeorb ldeorh ldeorl ldeorlb ldeorlh ldff1b ldff1d ldff1h ldff1sb ldff1sh ldff1sw ldff1w ldg ldgm ldiapp ldlar ldlarb ldlarh ldnf1b ldnf1d ldnf1h ldnf1sb ldnf1sh ldnf1sw ldnf1w ldnp ldnt1b ldnt1d ldnt1h ldnt1sb ldnt1sh ldnt1sw ldnt1w ldp ldr ldraa ldrab ldrb ldrh ldrsb ldrsh ldrsw ldset ldseta ldsetab ldsetah ldsetal ldsetalb ldsetalh ldsetb ldseth ldsetl ldsetlb ldsetlh ldsetp ldsetpa ldsetpal ldsetpl ldsmax ldsmaxa ldsmaxab ldsmaxah ldsmaxal ldsmaxalb ldsmaxalh ldsmaxb ldsmaxh ldsmaxl ldsmaxlb ldsmaxlh ldsmin ldsmina ldsminab ldsminah ldsminal ldsminalb ldsminalh ldsminb ldsminh ldsminl ldsminlb ldsminlh ldtr ldtrb ldtrh ldtrsb ldtrsh ldtrsw ldumax ldumaxa ldumaxab ldumaxah ldumaxal ldumaxalb ldumaxalh ldumaxb ldumaxh ldumaxl ldumaxlb ldumaxlh ldumin ldumina lduminab lduminah lduminal lduminalb lduminalh lduminb lduminh lduminl lduminlb lduminlh ldur ldurb ldurh ldursb ldursh ldursw ldxp ldxr ldxrb ldxrh lsl lslr lslv lsr lsrr lsrv luti2 luti4 mad madd maddpt madpt match mla mlapt mls mneg mov mova movaz movi movk movn movprfx movs movt movz mrrs mrs msb msr msrr msub msubpt mul mvn mvni nand nands nbsl neg negs ngc ngcs nmatch nop nor nors not nots orn orns orqv orr orrs orv pacda pacdb pacdza pacdzb pacga pacia pacia1716 paciasp paciaz pacib pacib1716 pacibsp pacibz paciza pacizb pext pfalse pfirst pmov pmul pmull pmull2 pmullb pmullt pnext prfb prfd prfh prfm prfum prfw psb psel pssbb ptest ptrue ptrues punpkhi punpklo raddhn raddhn2 raddhnb raddhnt rax1 rbit rcwcas rcwcasa rcwcasal rcwcasl rcwcasp rcwcaspa rcwcaspal rcwcaspl rcwclr rcwclra rcwclral rcwclrl rcwclrp rcwclrpa rcwclrpal rcwclrpl rcwscas rcwscasa rcwscasal rcwscasl rcwscasp rcwscaspa rcwscaspal rcwscaspl rcwsclr rcwsclra rcwsclral rcwsclrl rcwsclrp rcwsclrpa rcwsclrpal rcwsclrpl rcwset rcwseta rcwsetal rcwsetl rcwsetp rcwsetpa rcwsetpal rcwsetpl rcwsset rcwsseta rcwssetal rcwssetl rcwssetp rcwssetpa rcwssetpal rcwssetpl rcwsswp rcwsswpa rcwsswpal rcwsswpl rcwsswpp rcwsswppa rcwsswppal rcwsswppl rcwswp rcwswpa rcwswpal rcwswpl rcwswpp rcwswppa rcwswppal rcwswppl rdffr rdffrs rdsvl rdvl ret retaa retab rev rev16 rev32 rev64 revb revd revh revw rmif ror rorv rprfm rshrn rshrn2 rshrnb rshrnt rsubhn rsubhn2 rsubhnb rsubhnt saba sabal sabal2 sabalb sabalt sabd sabdl sabdl2 sabdlb sabdlt sadalp saddl saddl2 saddlb saddlbt saddlp saddlt saddlv saddv saddw saddw2 saddwb saddwt sb sbc sbclb sbclt sbcs sbfiz sbfm sbfx sclamp scvtf sdiv sdivr sdot sel setf16 setf8 setffr sev sevl sha1c sha1h sha1m sha1p sha1su0 sha1su1 sha256h sha256h2 sha256su0 sha256su1 sha512h sha512h2 sha512su0 sha512su1 shadd shl shll shll2 shrn shrn2 shrnb shrnt shsub shsubr sli sm3partw1 sm3partw2 sm3ss1 sm3tt1a sm3tt1b sm3tt2a sm3tt2b sm4e sm4ekey smaddl smax smaxp smaxqv smaxv smc smin sminp sminqv sminv smlal smlal2 smlalb smlall smlalt smlsl smlsl2 smlslb smlsll smlslt smmla smnegl smopa smops smov smstart smstop smsubl smulh smull smull2 smullb smullt splice sqabs sqadd sqcadd sqcvt sqcvtn sqcvtu sqcvtun sqdecb sqdecd sqdech sqdecp sqdecw sqdmlal sqdmlal2 sqdmlalb sqdmlalbt sqdmlalt sqdmlsl sqdmlsl2 sqdmlslb sqdmlslbt sqdmlslt sqdmulh sqdmull sqdmull2 sqdmullb sqdmullt sqincb sqincd sqinch sqincp sqincw sqneg sqrdcmlah sqrdmlah sqrdmlsh sqrdmulh sqrshl sqrshlr sqrshr sqrshrn sqrshrn2 sqrshrnb sqrshrnt sqrshru sqrshrun sqrshrun2 sqrshrunb sqrshrunt sqshl sqshlr sqshlu sqshrn sqshrn2 sqshrnb sqshrnt sqshrun sqshrun2 sqshrunb sqshrunt sqsub sqsubr sqxtn sqxtn2 sqxtnb sqxtnt sqxtun sqxtun2 sqxtunb sqxtunt srhadd sri srshl srshlr srshr srsra ssbb sshl sshll sshll2 sshllb sshllt sshr ssra ssubl ssubl2 ssublb ssublbt ssublt ssubltb ssubw ssubw2 ssubwb ssubwt st1 st1b st1d st1h st1q st1w st2 st2b st2d st2g st2h st2q st2w st3 st3b st3d st3h st3q st3w st4 st4b st4d st4h st4q st4w st64b st64bv st64bv0 stadd staddb staddh staddl staddlb staddlh stclr stclrb stclrh stclrl stclrlb stclrlh steor steorb steorh steorl steorlb steorlh stg stgm stgp stilp stl1 stllr stllrb stllrh stlr stlrb stlrh stlur stlurb stlurh stlxp stlxr stlxrb stlxrh stnp stnt1b stnt1d stnt1h stnt1w stp str strb strh stset stsetb stseth stsetl stsetlb stsetlh stsmax stsmaxb stsmaxh stsmaxl stsmaxlb stsmaxlh stsmin stsminb stsminh stsminl stsminlb stsminlh sttr sttrb sttrh stumax stumaxb stumaxh stumaxl stumaxlb stumaxlh stumin stuminb stuminh stuminl stuminlb stuminlh stur sturb sturh stxp stxr stxrb stxrh stz2g stzg stzgm sub subg subhn subhn2 subhnb subhnt subp subps subpt subr subs sudot sumlall sumopa sumops sunpk sunpkhi sunpklo suqadd suvdot svc svdot swp swpa swpab swpah swpal swpalb swpalh swpb swph swpl swplb swplh swpp swppa swppal swppl sxtb sxth sxtl sxtl2 sxtw sys sysl sysp tbl tblq tbnz tbx tbxq tbz tcancel tcommit tlbi tlbip trcit trn1 trn2 tsb tst tstart ttest uaba uabal uabal2 uabalb uabalt uabd uabdl uabdl2 uabdlb uabdlt uadalp uaddl uaddl2 uaddlb uaddlp uaddlt uaddlv uaddv uaddw uaddw2 uaddwb uaddwt ubfiz ubfm ubfx uclamp ucvtf udf udiv udivr udot uhadd uhsub uhsubr umaddl umax umaxp umaxqv umaxv umin uminp uminqv uminv umlal umlal2 umlalb umlall umlalt umlsl umlsl2 umlslb umlsll umlslt ummla umnegl umopa umops umov umsubl umulh umull umull2 umullb umullt uqadd uqcvt uqcvtn uqdecb uqdecd uqdech uqdecp uqdecw uqincb uqincd uqinch uqincp uqincw uqrshl uqrshlr uqrshr uqrshrn uqrshrn2 uqrshrnb uqrshrnt uqshl uqshlr uqshrn uqshrn2 uqshrnb uqshrnt uqsub uqsubr uqxtn uqxtn2 uqxtnb uqxtnt urecpe urhadd urshl urshlr urshr ursqrte ursra usdot ushl ushll ushll2 ushllb ushllt ushr usmlall usmmla usmopa usmops usqadd usra usubl usubl2 usublb usublt usubw usubw2 usubwb usubwt usvdot uunpk uunpkhi uunpklo uvdot uxtb uxth uxtl uxtl2 uxtw uzp uzp1 uzp2 uzpq1 uzpq2 wfe wfet wfi wfit whilege whilegt whilehi whilehs whilele whilelo whilels whilelt whilerw whilewr wrffr xaflag xar xpacd xpaci xpaclri xtn xtn2 yield zero zip zip1 zip2 zipq1 zipq2 byte word dword qword ptr xmmword ymmword zmmword \[ \] \{ \} %\w+(.\w+)* @\w+(.\w+)* !\w+([a-z]|[A-Z]|[0-9]|\(|\))* \b((0x)?[0-9a-fA-F]+|[0-9]+)\b true false ================================================ FILE: resources/asm/function-markings.json ================================================ { "ModuleColors": [], "FunctionColors": [ { "IsEnabled": true, "Title": "Memory Allocation", "Name": "\\b(free|malloc|calloc|aligned_alloc|operator delete|operator new|realloc|RtlAllocateHeap|RtlFreeHeap|RtlpAllocateHeap|RtlpAllocateHeapInternal|RtlpFreeHeap|RtlpFreeHeapInternal|_free_base|_malloc_base)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Memory Copy/Set/Move", "Name": "\\b(memset|memcpy|memmove|ZeroMemory|SecureZeroMemory|SecureZeroMemory2|CopyMemory|MoveMemory|FillMemory)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Page Fault", "Name": "\\b(KiPageFault|MiCompletePrivateZeroFault|MiDispatchFault|MiResolveDemandZeroFault|MiResolvePrivateZeroFault|MiUserFault|MiZeroFault|MmAccessFault)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Virtual Memory", "Name": "\\b(DiscardVirtualMemory|OfferVirtualMemory|PrefetchVirtualMemory|QueryVirtualMemoryInformation|ReclaimVirtualMemory|VirtualAlloc|VirtualAlloc2|VirtualAllocEx|VirtualAllocExNuma|VirtualFree|VirtualFreeEx|VirtualLock|VirtualProtect|VirtualProtectEx|VirtualProtectFromApp|VirtualQuery|VirtualQueryEx|VirtualUnlock)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Thread Synchronization", "Name": "\\b(AcquireSRWLockExclusive|AcquireSRWLockShared|DeleteCriticalSection|EnterCriticalSection|InitializeConditionVariable|InitializeCriticalSection|InitializeCriticalSectionAndSpinCount|InitializeCriticalSectionEx|InitializeSRWLock|KeDelayExecutionThread|KeYieldExecution|LeaveCriticalSection|ReleaseSRWLockExclusive|ReleaseSRWLockShared|RtlAcquireSRWLockExclusive|RtlAcquireSRWLockShared|RtlBackoff|RtlDelayExecution|RtlEnterCriticalSection|RtlLeaveCriticalSection|RtlpEnterCriticalSectionContended|RtlpOptimizeConditionVariableWaitList|RtlpWaitOnCriticalSection|RtlpWakeSRWLock|RtlReleaseSRWLockExclusive|RtlReleaseSRWLockShared|RtlSleepConditionVariableSRW|RtlWakeConditionVariable|SetCriticalSectionSpinCount|SleepConditionVariableCS|SleepConditionVariableSRW|TryAcquireSRWLockExclusive|TryAcquireSRWLockShared|TryEnterCriticalSection|WakeAllConditionVariable|WakeConditionVariable|NtDelayExecution)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "File I\/O", "Name": "\\b(CreateFile|CreateFile2|DeleteFile|FindClose|FindFirstFile|FindFirstFileEx|FindNextFile|FlushFileBuffers|GetFileAttributes|GetFileAttributesEx|GetFileSize|GetFileSizeEx|GetFileTime|IopCreateFile|IopReadFile|IopWriteFile|NtCreateFile|NtReadFile|NtWriteFile|ReadFile|ReadFileEx|SetFileAttributes|SetFileInformationByHandle|SetFilePointer|SetFilePointerEx|WriteFile|WriteFileEx)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "C\/C++ File I\/O", "Name": "\\b(_fgetc_nolock|_fread|_fsopen|_fwrite_nolock_internal|_read_nolock|fclose|fgetc|fread_s|fwrite|std::basic_filebuf)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Network I\/O", "Name": "\\b(WSARecv|WSASend|TcpTlConnectionSend|TcpReceive)\\b|_WSARecv|_WSASend", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "C-style Strings", "Name": "\\b(mblen|mbstowcs|mbtowc|memchr|strcat|strcat_s|strchr|strcmp|strcoll|strcpy|strcpy_s|strcspn|strlen|strncat|strncat_s|strncmp|strncpy|strncpy_s|strpbrk|strrchr|strspn|strstr|strtok|wcscat|wcscat_s|wcschr|wcscmp|wcscoll|wcscpy|wcscpy_s|wcscspn|wcslen|wcsncat|wcsncat_s|wcsncmp|wcsncpy|wcsncpy_s|wcspbrk|wcsrchr|wcsspn|wcsstr|wcstod|wcstof|wcstok|wcstol|wcstold|wcstoll|wcstombs|wcstoul|wcstoull|wcsxfrm|wctomb|_mbscat|_mbscat_s|_mbscmp|_mbscoll|_mbscoll_l|_mbscpy|_mbscpy_s|_mbsicmp|_mbsicmp_l|_mbsicoll|_mbsicoll_l|_mbsncat|_mbsncat_l|_mbsncat_s|_mbsncat_s_l|_mbsncoll|_mbsncoll_l|_mbsncpy|_mbsncpy_l|_mbsncpy_s|_mbsncpy_s_l|_mbsnicmp|_mbsnicmp_l|_mbsnicoll|_mbsnicoll_l|_mbsrchr|_mbsrchr_l|_strcoll_l|_stricmp|_stricmp_l|_stricoll|_stricoll_l|_strncat_l|_strncat_s_l|_strncoll|_strncoll_l|_strncpy_l|_strncpy_s_l|_strnicmp|_strnicmp_l|_strnicoll|_strnicoll_l|_wcscoll_l|_wcsicmp|_wcsicmp_l|_wcsicoll|_wcsicoll_l|_wcsncat_l|_wcsncat_s_l|_wcsncoll|_wcsncoll_l|_wcsncpy_l|_wcsncpy_s_l|_wcsnicmp|_wcsnicmp_l|_wcsnicoll|_wcsnicoll_l)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Wait on Objects", "Name": "\\b(MsgWaitForMultipleObjects|MsgWaitForMultipleObjectsEx|RegisterWaitForSingleObject|SignalObjectAndWait|UnregisterWait|UnregisterWaitEx|WaitForMultipleObjects|WaitForMultipleObjectsEx|WaitForSingleObject|WaitForSingleObjectEx|WaitOnAddress|WaitOrTimerCallback|WakeByAddressAll|WakeByAddressSingle)\\b", "Color": "#000000", "IsRegex": true }, { "IsEnabled": true, "Title": "Exception Handling", "Name": "\\b(RaiseException|RtlRaiseException|RtlDispatchException|RtlpExecuteHandlerForException|__CxxFrameHandler4|RtlUnwind|RtlUnwindEx|__ExceptionPtrRethrow)\\b", "Color": "#000000", "IsRegex": true } ], "Title": "Builtin" } ================================================ FILE: resources/asm/x86-asm.xshd ================================================ " " define global declare je jne jo jno jb jnb jz jnz jbe ja js jns jp jnp jmp jl jge jle jg ret retf iret int3 call\s+.* aaa aad aam aas adc adcx add addpd vaddpd addps vaddps addsd vaddsd addss vaddss addsubpd vaddsubpd addsubps vaddsubps adox aesdec vaesdec aesdeclast vaesdeclast aesenc vaesenc aesenclast vaesenclast aesimc vaesimc aeskeygenassist vaeskeygenassist and andn andnpd vandnpd andnps vandnps andpd vandpd andps vandps arpl bextr blendpd vblendpd blendps vblendps blendvpd vblendvpd blendvps vblendvps blsi blsmsk blsr bndcl bndcu bndcn bndldx bndmk bndmov bndstx bound bsf bsr bswap bt btc btr bts bzhi call cbw cwde cdqe clac clc cld cldemote clflush clflushopt cli clts clwb cmc cmova cmovae cmovb cmovbe cmovc cmove cmovg cmovge cmovl cmovle cmovna cmovnae cmovnb cmovnbe cmovnc cmovne cmovng cmovnge cmovnl cmovnle cmovno cmovnp cmovns cmovnz cmovo cmovp cmovpe cmovpo cmovs cmovz cmp cmppd vcmppd cmpps vcmpps cmps cmpsb cmpsw cmpsd cmpsq cmpsd vcmpsd cmpss vcmpss cmpxchg cmpxchg8b cmpxchg16b comisd vcomisd comiss vcomiss cpuid crc32 cvtdq2pd vcvtdq2pd cvtdq2ps vcvtdq2ps cvtpd2dq vcvtpd2dq cvtpd2pi cvtpd2ps vcvtpd2ps cvtpi2pd cvtpi2ps cvtps2dq vcvtps2dq cvtps2pd vcvtps2pd cvtps2pi cvtsd2si vcvtsd2si cvtsd2ss vcvtsd2ss cvtsi2sd vcvtsi2sd cvtsi2ss vcvtsi2ss cvtss2sd vcvtss2sd cvtss2si vcvtss2si cvttpd2dq vcvttpd2dq cvttpd2pi cvttps2dq vcvttps2dq cvttps2pi cvttsd2si vcvttsd2si cvttss2si vcvttss2si cwd cdq cqo daa das dec div divpd vdivpd divps vdivps divsd vdivsd divss vdivss dppd vdppd dpps vdpps eaccept eacceptcopy eadd eaug eblock ecreate edbgrd edbgwr edecvirtchild eenter eexit eextend egetkey eincvirtchild einit eldb eldu eldbc emms emodpe emodpr emodt encls enclu enclv enqcmd enqcmds enter epa erdinfo eremove ereport eresume esetcontext etrack etrackc ewb extractps vextractps f2xm1 fabs fadd faddp fiadd fbld fbstp fchs fclex fnclex fcmovb fcmove fcmovbe fcmovu fcmovnb fcmovne fcmovnbe fcmovnu fcom fcomp fcompp fcomi fcomip fucomi fucomip fcos fdecstp fdiv fdivp fidiv fdivr fdivrp fidivr ffree ficom ficomp fild fincstp finit fninit fist fistp fisttp fld fld1 fldl2t fldl2e fldpi fldlg2 fldln2 fldz fldcw fldenv fmul fmulp fimul fnop fpatan fprem fprem1 fptan frndint frstor fsave fnsave fscale fsin fsincos fsqrt fst fstp fstcw fnstcw fstenv fnstenv fstsw fnstsw fsub fsubp fisub fsubr fsubrp fisubr ftst fucom fucomp fucompp fxam fxch fxrstor fxrstor64 fxsave fxsave64 fxtract fyl2x fyl2xp1 exitac parameters senter sexit smctrl wakeup gf2p8affineinvqb vgf2p8affineinvqb gf2p8affineqb vgf2p8affineqb gf2p8mulb vgf2p8mulb haddpd vhaddpd haddps vhaddps hlt hsubpd vhsubpd hsubps vhsubps idiv imul in inc ins insb insw insd insertps vinsertps int3 int into int1 invd invlpg invpcid iret iretd iretq ja jae jb jbe jc jcxz jecxz jrcxz je jg jge jl jle jna jnae jnb jnbe jnc jne jng jnge jnl jnle jno jnp jns jnz jo jp jpe jpo js jz jmp kaddw kaddb kaddq kaddd kandnw kandnb kandnq kandnd kandw kandb kandq kandd kmovw kmovb kmovq kmovd knotw knotb knotq knotd kortestw kortestb kortestq kortestd korw korb korq kord kshiftlw kshiftlb kshiftlq kshiftld kshiftrw kshiftrb kshiftrq kshiftrd ktestw ktestb ktestq ktestd kunpckbw kunpckwd kunpckdq kxnorw kxnorb kxnorq kxnord kxorw kxorb kxorq kxord lahf lar lddqu vlddqu ldmxcsr vldmxcsr lds lss les lfs lgs lea leave lfence lgdt lidt lldt lmsw lock lods lodsb lodsw lodsd lodsq loop loope loopne lsl ltr lzcnt maskmovdqu vmaskmovdqu maskmovq maxpd vmaxpd maxps vmaxps maxsd vmaxsd maxss vmaxss mfence minpd vminpd minps vminps minsd vminsd minss vminss monitor mov movapd vmovapd movaps vmovaps movbe movd movq vmovd vmovq movddup vmovddup movdir64b movdiri movdq2q movdqa vmovdqa vmovdqa32 vmovdqa64 movdqu vmovdqu vmovdqu8 vmovdqu16 vmovdqu32 vmovdqu64 movhlps vmovhlps movhpd vmovhpd movhps vmovhps movlhps vmovlhps movlpd vmovlpd movlps vmovlps movmskpd vmovmskpd movmskps vmovmskps movntdq vmovntdq movntdqa vmovntdqa movnti movntpd vmovntpd movntps vmovntps movntq movq vmovq movq2dq movs movsb movsw movsd movsq movsd vmovsd movshdup vmovshdup movsldup vmovsldup movss vmovss movsx movsxd movupd vmovupd movups vmovups movzx mpsadbw vmpsadbw mul mulpd vmulpd mulps vmulps mulsd vmulsd mulss vmulss mulx mwait neg nop not or orpd vorpd orps vorps out outs outsb outsw outsd pabsb pabsw pabsd vpabsb vpabsw vpabsd vpabsq packsswb packssdw vpacksswb vpackssdw packusdw vpackusdw packuswb vpackuswb paddb paddw paddd paddq vpaddb vpaddw vpaddd vpaddq paddsb paddsw vpaddsb vpaddsw paddusb paddusw vpaddusb vpaddusw palignr vpalignr pand vpand vpandd vpandq pandn vpandn vpandnd vpandnq pause pavgb pavgw vpavgb vpavgw pblendvb vpblendvb pblendw vpblendw pclmulqdq vpclmulqdq pcmpeqb pcmpeqw pcmpeqd vpcmpeqb vpcmpeqw vpcmpeqd pcmpeqq vpcmpeqq pcmpestri vpcmpestri pcmpestrm vpcmpestrm pcmpgtb pcmpgtw pcmpgtd vpcmpgtb vpcmpgtw vpcmpgtd pcmpgtq vpcmpgtq pcmpistri vpcmpistri pcmpistrm vpcmpistrm pconfig pdep pext pextrb pextrd pextrq vpextrb vpextrd vpextrq pextrw vpextrw phaddsw vphaddsw phaddw phaddd vphaddw vphaddd phminposuw vphminposuw phsubsw vphsubsw phsubw phsubd vphsubw vphsubd pinsrb pinsrd pinsrq vpinsrb vpinsrd vpinsrq pinsrw vpinsrw pmaddubsw vpmaddubsw pmaddwd vpmaddwd pmaxsw pmaxsb pmaxsd vpmaxsb vpmaxsw vpmaxsd vpmaxsq pmaxub pmaxuw vpmaxub vpmaxuw pmaxud vpmaxud vpmaxuq pminsw pminsb vpminsb vpminsw pminsd vpminsd vpminsq pminub pminuw vpminub vpminuw pminud vpminud vpminuq pmovmskb vpmovmskb pmovsxbw pmovsxbd pmovsxbq pmovsxwd pmovsxwq pmovsxdq vpmovsxbw vpmovsxbd vpmovsxbq vpmovsxwd vpmovsxwq vpmovsxdq pmovzxbw pmovzxbd pmovzxbq pmovzxwd pmovzxwq pmovzxdq vpmovzxbw vpmovzxbd vpmovzxbq vpmovzxwd vpmovzxwq vpmovzxdq pmuldq vpmuldq pmulhrsw vpmulhrsw pmulhuw vpmulhuw pmulhw vpmulhw pmulld vpmulld vpmullq pmullw vpmullw pmuludq vpmuludq pop popa popad popcnt popf popfd popfq por vpor vpord vporq prefetcht0 prefetcht1 prefetcht2 prefetchnta prefetchw prefetchwt1 psadbw vpsadbw pshufb vpshufb pshufd vpshufd pshufhw vpshufhw pshuflw vpshuflw pshufw psignb psignw psignd vpsignb vpsignw vpsignd pslldq vpslldq psllw pslld psllq vpsllw vpslld vpsllq psraw psrad vpsraw vpsrad vpsraq psrldq vpsrldq psrlw psrld psrlq vpsrlw vpsrld vpsrlq psubb psubw psubd vpsubb vpsubw vpsubd psubq vpsubq psubsb psubsw vpsubsb vpsubsw psubusb psubusw vpsubusb vpsubusw punpckhbw punpckhwd punpckhdq punpckhqdq vpunpckhbw vpunpckhwd vpunpckhdq vpunpckhqdq punpcklbw punpcklwd punpckldq punpcklqdq vpunpcklbw vpunpcklwd vpunpckldq vpunpcklqdq push pusha pushad pushf pushfd pushfq pxor vpxor vpxord vpxorq rcl rcr rol ror rcpps vrcpps rcpss vrcpss rdfsbase rdgsbase rdmsr rdpid rdpkru rdpmc rdrand rdseed rdtsc rdtscp rep_ins rep_movs rep_outs rep_lods rep_stos repe_cmps repe_scas repne_cmps repne_scas ret rorx roundpd vroundpd roundps vroundps roundsd vroundsd roundss vroundss rsm rsqrtps vrsqrtps rsqrtss vrsqrtss sahf sal sar shl shr sarx shlx shrx sbb scas scasb scasw scasd scasq seta setae setb setbe setc sete setg setge setl setle setna setnae setnb setnbe setnc setne setng setnge setnl setnle setno setnp setns setnz seto setp setpe setpo sets setz sfence sgdt sha1msg1 sha1msg2 sha1nexte sha1rnds4 sha256msg1 sha256msg2 sha256rnds2 shld shrd shufpd vshufpd shufps vshufps sidt sldt smsw sqrtpd vsqrtpd sqrtps vsqrtps sqrtsd vsqrtsd sqrtss vsqrtss stac stc std sti stmxcsr vstmxcsr stos stosb stosw stosd stosq str sub subpd vsubpd subps vsubps subsd vsubsd subss vsubss swapgs syscall sysenter sysexit sysret test tpause tzcnt ucomisd vucomisd ucomiss vucomiss ud01 ud1 ud2 umonitor umwait unpckhpd vunpckhpd unpckhps vunpckhps unpcklpd vunpcklpd unpcklps vunpcklps v4fmaddps v4fnmaddps v4fmaddss v4fnmaddss vaesdec vaesdeclast vaesenc vaesenclast valignd valignq vblendmpd vblendmps vbroadcastss vbroadcastsd vbroadcastf128 vbroadcastf32x2 vbroadcastf32x4 vbroadcastf64x2 vbroadcastf32x8 vbroadcastf64x4 vcompresspd vcompressps vcvtne2ps2bf16 vcvtneps2bf16 vcvtpd2qq vcvtpd2udq vcvtpd2uqq vcvtph2ps vcvtps2ph vcvtps2qq vcvtps2udq vcvtps2uqq vcvtqq2pd vcvtqq2ps vcvtsd2usi vcvtss2usi vcvttpd2qq vcvttpd2udq vcvttpd2uqq vcvttps2qq vcvttps2udq vcvttps2uqq vcvttsd2usi vcvttss2usi vcvtudq2pd vcvtudq2ps vcvtuqq2pd vcvtuqq2ps vcvtusi2sd vcvtusi2ss vdbpsadbw vdpbf16ps verr verw vexp2pd vexp2ps vexpandpd vexpandps vextractf128 vextractf32x4 vextractf64x2 vextractf32x8 vextractf64x4 vextracti128 vextracti32x4 vextracti64x2 vextracti32x8 vextracti64x4 vfixupimmpd vfixupimmps vfixupimmsd vfixupimmss vfmadd132pd vfmadd213pd vfmadd231pd vfmadd132ps vfmadd213ps vfmadd231ps vfmadd132sd vfmadd213sd vfmadd231sd vfmadd132ss vfmadd213ss vfmadd231ss vfmaddsub132pd vfmaddsub213pd vfmaddsub231pd vfmaddsub132ps vfmaddsub213ps vfmaddsub231ps vfmsub132pd vfmsub213pd vfmsub231pd vfmsub132ps vfmsub213ps vfmsub231ps vfmsub132sd vfmsub213sd vfmsub231sd vfmsub132ss vfmsub213ss vfmsub231ss vfmsubadd132pd vfmsubadd213pd vfmsubadd231pd vfmsubadd132ps vfmsubadd213ps vfmsubadd231ps vfnmadd132pd vfnmadd213pd vfnmadd231pd vfnmadd132ps vfnmadd213ps vfnmadd231ps vfnmadd132sd vfnmadd213sd vfnmadd231sd vfnmadd132ss vfnmadd213ss vfnmadd231ss vfnmsub132pd vfnmsub213pd vfnmsub231pd vfnmsub132ps vfnmsub213ps vfnmsub231ps vfnmsub132sd vfnmsub213sd vfnmsub231sd vfnmsub132ss vfnmsub213ss vfnmsub231ss vfpclasspd vfpclassps vfpclasssd vfpclassss vgatherdpd vgatherqpd vgatherdps vgatherdpd vgatherdps vgatherqps vgatherpf0dps vgatherpf0qps vgatherpf0dpd vgatherpf0qpd vgatherpf1dps vgatherpf1qps vgatherpf1dpd vgatherpf1qpd vgatherqps vgatherqpd vgetexppd vgetexpps vgetexpsd vgetexpss vgetmantpd vgetmantps vgetmantsd vgetmantss vinsertf128 vinsertf32x4 vinsertf64x2 vinsertf32x8 vinsertf64x4 vinserti128 vinserti32x4 vinserti64x2 vinserti32x8 vinserti64x4 vmaskmovps vmaskmovpd vp2intersectd vp2intersectq vp4dpwssd vp4dpwssds vpblendd vpblendmb vpblendmw vpblendmd vpblendmq vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vbroadcasti32x2 vbroadcasti128 vbroadcasti32x4 vbroadcasti64x2 vbroadcasti32x8 vbroadcasti64x4 vpbroadcastb vpbroadcastw vpbroadcastd vpbroadcastq vpbroadcastmb2q vpbroadcastmw2d vpclmulqdq vpcmpb vpcmpub vpcmpd vpcmpud vpcmpq vpcmpuq vpcmpw vpcmpuw vpcompressb vpcompressw vpcompressd vpcompressq vpconflictd vpconflictq vpdpbusd vpdpbusds vpdpwssd vpdpwssds vperm2f128 vperm2i128 vpermb vpermd vpermw vpermi2b vpermi2w vpermi2d vpermi2q vpermi2ps vpermi2pd vpermilpd vpermilps vpermpd vpermps vpermq vpermt2b vpermt2w vpermt2d vpermt2q vpermt2ps vpermt2pd vpexpandb vpexpandw vpexpandd vpexpandq vpgatherdd vpgatherdq vpgatherdd vpgatherqd vpgatherdq vpgatherqq vpgatherqd vpgatherqq vplzcntd vplzcntq vpmadd52huq vpmadd52luq vpmaskmovd vpmaskmovq vpmovb2m vpmovw2m vpmovd2m vpmovq2m vpmovdb vpmovsdb vpmovusdb vpmovdw vpmovsdw vpmovusdw vpmovm2b vpmovm2w vpmovm2d vpmovm2q vpmovqb vpmovsqb vpmovusqb vpmovqd vpmovsqd vpmovusqd vpmovqw vpmovsqw vpmovusqw vpmovwb vpmovswb vpmovuswb vpmultishiftqb vpopcntb vpopcntw vpopcntd vpopcntq vprolvd vprold vprolvq vprolq vprorvd vprord vprorvq vprorq vpscatterdd vpscatterdq vpscatterqd vpscatterqq vpshldw vpshldd vpshldq vpshldvw vpshldvd vpshldvq vpshrdw vpshrdd vpshrdq vpshrdvw vpshrdvd vpshrdvq vpshufbitqmb vpsllvd vpsllvq vpsllvw vpsravd vpsravw vpsravq vpsrlvd vpsrlvq vpsrlvw vpternlogd vpternlogq vptestmb vptestmw vptestmd vptestmq vptestnmb vptestnmw vptestnmd vptestnmq vrangepd vrangeps vrangesd vrangess vrcp14pd vrcp14ps vrcp14sd vrcp14ss vrcp28pd vrcp28ps vrcp28sd vrcp28ss vreducepd vreduceps vreducesd vreducess vrndscalepd vrndscaleps vrndscalesd vrndscaless vrsqrt14pd vrsqrt14ps vrsqrt14sd vrsqrt14ss vrsqrt28pd vrsqrt28ps vrsqrt28sd vrsqrt28ss vscalefpd vscalefps vscalefsd vscalefss vscatterdps vscatterdpd vscatterqps vscatterqpd vscatterpf0dps vscatterpf0qps vscatterpf0dpd vscatterpf0qpd vscatterpf1dps vscatterpf1qps vscatterpf1dpd vscatterpf1qpd vshuff32x4 vshuff64x2 vshufi32x4 vshufi64x2 vtestps vtestpd vzeroall vzeroupper wait fwait wbinvd wbnoinvd wrfsbase wrgsbase wrmsr wrpkru xabort xacquire xrelease xadd xbegin xchg xend xgetbv xlat xlatb xor xorpd vxorpd xorps vxorps xrstor xrstor64 xrstors xrstors64 xsave xsave64 xsavec xsavec64 xsaveopt xsaveopt64 xsaves xsaves64 xsetbv xtest byte word dword qword ptr xmmword ymmword zmmword \[ \] \{ \} %\w+(.\w+)* @\w+(.\w+)* !\w+([a-z]|[A-Z]|[0-9]|\(|\))* \b((0x)?[0-9a-fA-F]+|[0-9]+)\b rep true false ================================================ FILE: resources/documentStyles.xml ================================================ ================================================ FILE: resources/ir.xshd ================================================ func block label var temp indir metadata exception other intconst floatconst address branch goto switch return int8> int16 int32 int64 uint8> uint16 uint32 uint64 float32 float64 unknown void bool mb4 mb8 mb16 \[ \] \b0[xX][0-9a-fA-F]+|(\b(?<!\$)\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? ================================================ FILE: resources/llvm/llvm.xshd ================================================ " " define global declare load store alloca icmp select bitcast add sub mul sdiv udiv fdiv urem srem frem fneg shl lshr ashr and or xor phi trunc zext sext fcmp extractelement insertelement shufflevector extractvalue insertvalue getelementptr inttoptr sitofp uitofp fptosi fptoui fpext fptrunc fmul fadd fsub br indirectbr callbr switch ret label resume catchret cleanupret unreachable call invoke va_arg type i1 i8 i16 i32 i64 float double void undef \[ \] \{ \} nsw nuw volatile align tail zeroinitializer byval zeroext signext inreg sret noalias nocapture nonnull alwaysinline noinline noreturn nounwind optnone optsize readnone readonly writeonly argmemonly external internal linkonce weak private dllimport dllexport atomic metadata inbounds %\w+(.\w+)* @\w+(.\w+)* !\w+([a-z]|[A-Z]|[0-9]|\(|\))* \b0[xX][0-9a-fA-F]+|(\b(?<!\$)\d+(\.[0-9]+)?|\.[0-9]+)([eE][+-]?[0-9]+)? true false ================================================ FILE: resources/scripts/ssa-checker.cs ================================================ using IRExplorerCore; using IRExplorerCore.IR; using IRExplorerCore.Analysis; using IRExplorerUI.Query; using IRExplorerUI; using IRExplorerUI.Scripting; using System.Collections.Generic; using System; using System.Windows.Media; using System.ComponentModel; public class Script { class Options : IFunctionTaskOptions { [DisplayName("Check value definition dominance")] [Description("Checks that the definition of each source value dominates the instruction")] public bool CheckDominance { get; set; } [DisplayName("Check live range overlap")] [Description("Checks that there is no live range overlap of multiple SSA values of the same symbol")] public bool CheckLiveRangeOverlap { get; set; } [DisplayName("Error marker color (dominance)")] [Description("Color to be used for marking dominance errors")] public Color MarkerColor { get; set; } [DisplayName("Error marker color (live range)")] [Description("Color to be used for marking live range overlap errors")] public Color LiveRangeMarkerColor { get; set; } [DisplayName("Error marker color (dominance)")] [Description("Color to be used for marking the definition operand")] public Color DefinitionMarkerColor { get; set; } public Options() { Reset(); } public void Reset() { CheckDominance = true; CheckLiveRangeOverlap = true; MarkerColor = Colors.Pink; LiveRangeMarkerColor = Colors.LightSalmon; DefinitionMarkerColor = Colors.Gold; } } public FunctionTaskInfo GetTaskInfo() { return new FunctionTaskInfo(Guid.Parse("C18CD53C-7BE6-4893-BCFC-B093DD5FD91C"), "SSA form checks", "Some description") { HasOptionsPanel = true, OptionsType = typeof(Options) }; } public bool Execute(ScriptSession s) { var func = s.CurrentFunction; var options = (Options)s.SessionObject; var domTree = s.Analysis.DominatorTree; var refs = s.Analysis.References; bool failed = false; foreach(var block in func.Blocks) { var visitedInstrs = new HashSet(); foreach(var instr in block.Instructions) { int sourceOpIndex = -1; foreach(var sourceOp in instr.Sources) { sourceOpIndex++; var defOp = ReferenceFinder.GetSSADefinition(sourceOp); if(defOp == null) continue; // No SSA info. var defInstr = defOp.ParentInstruction; if(defInstr == null) { continue; // Constants, params, etc. dominate. } var checkedBlock = block; var defBlock = defInstr.ParentBlock; bool isPhiIncomingBlock = false; if (s.IR.IsPhiInstruction(instr)) { // For a PHI, the incoming operand must dominate the corresponding predecessor. checkedBlock = s.IR.GetIncomingPhiOperandBlock(instr, sourceOpIndex); isPhiIncomingBlock = true; } if(options.CheckDominance) { if(!CheckDominance(checkedBlock, block, instr, isPhiIncomingBlock, defInstr, defBlock, visitedInstrs, domTree, options, s)) { ReportDomFailure(s, checkedBlock, instr, sourceOp, defOp, defBlock, options); failed = true; } } if (options.CheckLiveRangeOverlap) { // Walk dominator tree between def. block and current block // and check if there is any other definition of the same symbol. InstructionIR redefinitionInstr = null; if(defBlock == checkedBlock) { CheckRedefinition(instr, checkedBlock, defInstr, defBlock, refs, out redefinitionInstr); } else { BlockIR domBlock = checkedBlock; do { domBlock = domTree.GetImmediateDominator(domBlock); if(!CheckRedefinition(instr, domBlock, defInstr, defBlock, refs, out redefinitionInstr)) { break; } } while (domBlock != null && domBlock != defBlock); } if(redefinitionInstr != null) { ReportOverlapFailure(s, checkedBlock, instr, defOp, defBlock, redefinitionInstr, options); failed = true; } } } visitedInstrs.Add(instr); } } if(failed) { s.SetSessionResult(false, "SSA correctness errors found"); } else { s.SetSessionResult(true, "No problems found"); } return true; } private bool CheckDominance(BlockIR checkedBlock, BlockIR userBlock, InstructionIR userInstr, bool isPhiIncomingBlock, InstructionIR defInstr, BlockIR defBlock, HashSet visitedInstrs, DominatorAlgorithm domTree, Options options, ScriptSession s) { if (!domTree.Dominates(defBlock, checkedBlock)) { //s.WriteLine($"Dom failure for defBlock {defBlock.Number} and {checkedBlock.Number}"); return false; } else if (defBlock == userBlock) { // Check that the def is defined before the user in the same block. // If the instr. being checked is a PHI, with a loop back-edge the def. // would be found after the PHI at the top of the block, which is expected. if(isPhiIncomingBlock) { return true; } if (!visitedInstrs.Contains(defInstr)) { //s.WriteLine($"Same block failure for defBlock {defBlock.Number} and userBlock {checkedBlock.Number} and {checkedBlock.Number} "); return false; } } return true; } private bool CheckRedefinition(InstructionIR userInstr, BlockIR domBlock, InstructionIR defInstr, BlockIR defBlock, ReferenceFinder refs, out InstructionIR redefinitionInstr) { bool defInstrSeen = domBlock != defBlock; var defDestOp = defInstr.Destinations[0]; foreach(var instr in domBlock.Instructions) { if(!defInstrSeen) { defInstrSeen = instr == defInstr; } else { if(instr == userInstr) { break; } // Check if the def. operand is overwritten. foreach(var destOp in instr.Destinations) { if(refs.IsSameSymbolOperand(destOp, defDestOp, checkType:false, exactCheck:true)) { redefinitionInstr = instr; return false; // Redefinition. } } } } redefinitionInstr = null; return true; } private void ReportDomFailure(ScriptSession s, BlockIR block, InstructionIR instr, OperandIR sourceOp, IRElement defOp, BlockIR defBlock, Options options) { s.Mark(instr, options.MarkerColor); s.Mark(defOp, options.DefinitionMarkerColor); s.Write($"Dominance issue for instr in block {block.Number}: "); s.WriteLine(instr); s.Write(" for source "); s.WriteLine(sourceOp); s.Write($" defined in block {defBlock.Number}: "); s.WriteLine(defOp); } private void ReportOverlapFailure(ScriptSession s, BlockIR block, InstructionIR instr, IRElement defOp, BlockIR defBlock, InstructionIR redefinitionInstr, Options options) { s.Mark(instr, options.LiveRangeMarkerColor); s.Mark(redefinitionInstr, options.DefinitionMarkerColor); s.Write($"Live-range overlap issue for instr in block {block.Number}: "); s.WriteLine(instr); s.Write($" defined in block {defBlock.Number}: "); s.WriteLine(defOp); s.Write($" redefined in block {redefinitionInstr.ParentBlock.Number}: "); s.WriteLine(redefinitionInstr); } } ================================================ FILE: resources/workspaces/Profiling - Compact.xml ================================================ ================================================ FILE: resources/workspaces/Profiling - Source.xml ================================================ ================================================ FILE: resources/workspaces/Profiling - Wide Alt.xml ================================================ ================================================ FILE: resources/workspaces/Profiling - Wide.xml ================================================ ================================================ FILE: resources/workspaces/Profiling.xml ================================================ ================================================ FILE: scripts/Analyze-DiagnosticLog.ps1 ================================================ <# .SYNOPSIS Analyzes Profile Explorer diagnostic log files to summarize symbol loading issues. .DESCRIPTION This script parses Profile Explorer diagnostic logs (generated when PROFILE_EXPLORER_DEBUG=1) and provides a comprehensive summary of symbol loading performance, failures, and recommendations. .PARAMETER LogPath Path to the diagnostic log file. If not specified, uses the most recent log in %TEMP%. .EXAMPLE .\Analyze-DiagnosticLog.ps1 Analyzes the most recent diagnostic log. .EXAMPLE .\Analyze-DiagnosticLog.ps1 -LogPath "C:\temp\ProfileExplorer_Diagnostic_20260109.log" Analyzes a specific log file. #> param( [string]$LogPath ) # Find the most recent log if not specified if (-not $LogPath) { $logFiles = Get-ChildItem "$env:TEMP\ProfileExplorer_Diagnostic_*.log" -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending if ($logFiles.Count -eq 0) { Write-Host "No diagnostic logs found in $env:TEMP" -ForegroundColor Red Write-Host "Set PROFILE_EXPLORER_DEBUG=1 and load a trace to generate logs." -ForegroundColor Yellow exit 1 } $LogPath = $logFiles[0].FullName Write-Host "Using most recent log: $LogPath" -ForegroundColor Cyan } if (-not (Test-Path $LogPath)) { Write-Host "Log file not found: $LogPath" -ForegroundColor Red exit 1 } Write-Host "" Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host " PROFILE EXPLORER DIAGNOSTIC LOG ANALYZER" -ForegroundColor Cyan Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host "" $fileInfo = Get-Item $LogPath Write-Host "Log File: $LogPath" Write-Host "Size: $([math]::Round($fileInfo.Length / 1MB, 2)) MB" Write-Host "Created: $($fileInfo.CreationTime)" Write-Host "" # Read log file Write-Host "Reading log file..." -ForegroundColor Gray $log = Get-Content $LogPath # ============================================================================ # CRITICAL ERROR CHECK - DIA SDK Registration # ============================================================================ $diaError = $log | Where-Object { $_ -match 'DIA SDK.*is not registered|msdia140\.dll.*not registered|\[CRITICAL\].*DIA' } | Select-Object -First 1 if ($diaError) { Write-Host "" Write-Host ("!" * 80) -ForegroundColor Red Write-Host " CRITICAL ERROR: DIA SDK NOT REGISTERED" -ForegroundColor Red Write-Host ("!" * 80) -ForegroundColor Red Write-Host "" Write-Host " The DIA SDK (msdia140.dll) is not registered as a COM component." -ForegroundColor Red Write-Host " This prevents ALL symbol resolution - no function names will be displayed." -ForegroundColor Red Write-Host "" Write-Host " TO FIX (run as Administrator):" -ForegroundColor Yellow Write-Host " regsvr32 `"\msdia140.dll`"" -ForegroundColor White Write-Host "" Write-Host " Or for dev builds:" -ForegroundColor Yellow Write-Host " regsvr32 `"C:\src\profile-explorer\src\ProfileExplorerUI\bin\Release\net8.0-windows\msdia140.dll`"" -ForegroundColor White Write-Host "" Write-Host ("!" * 80) -ForegroundColor Red Write-Host "" } # Categorize lines $infoLines = $log | Where-Object { $_ -match '\[Information\]' } $warningLines = $log | Where-Object { $_ -match '\[Warning\]' } $debugLines = $log | Where-Object { $_ -match '\[Debug\]' } $errorLines = $log | Where-Object { $_ -match '\[Error\]' } # ============================================================================ # TRACE INFO & SYMBOL SERVER STATUS # ============================================================================ Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " TRACE INFO & SYMBOL SERVER STATUS" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray # Check for ImageID events $hasImageIdEvents = $log | Where-Object { $_ -match 'HasImageIdEvents=True' } | Select-Object -First 1 $noImageIdEvents = $log | Where-Object { $_ -match 'HasImageIdEvents=False|Trace has no ImageID DbgID events' } | Select-Object -First 1 $symbolServerDisabled = $log | Where-Object { $_ -match 'Symbol server disabled|Disabling symbol server|SourceServerEnabled=False' } | Select-Object -First 1 $symbolServerEnabled = $log | Where-Object { $_ -match 'SourceServerEnabled=True' } | Select-Object -First 1 # ImageID event counts - parse from log format: # "[TraceLoad] Event counts: ImageLoad=X (Y with timestamp), ImageID=Z, ImageID_DbgID=W" $imageLoadCount = 0 $imageIdCount = 0 $dbgIdCount = 0 $eventCountLine = $log | Where-Object { $_ -match '\[TraceLoad\] Event counts:' } | Select-Object -First 1 if ($eventCountLine) { if ($eventCountLine -match 'ImageLoad=(\d+)') { $imageLoadCount = [int]$Matches[1] } if ($eventCountLine -match 'ImageID=(\d+)') { $imageIdCount = [int]$Matches[1] } if ($eventCountLine -match 'ImageID_DbgID=(\d+)') { $dbgIdCount = [int]$Matches[1] } } # Parse Microsoft module info from [SymbolLoading] logs # Format: "[SymbolLoading] 1. modulename.dll: 12345 samples [Microsoft]" $microsoftModules = @{} $log | Where-Object { $_ -match '\[SymbolLoading\].*\d+\.\s+([^:]+):\s+\d+\s+samples' } | ForEach-Object { if ($_ -match '\[SymbolLoading\].*\d+\.\s+([^:]+):\s+(\d+)\s+samples(.*)$') { $moduleName = $Matches[1].Trim() $isMicrosoft = $Matches[3] -match '\[Microsoft\]' $microsoftModules[$moduleName.ToLower()] = $isMicrosoft } } Write-Host "" # Only report "MISSING" if we explicitly found evidence of missing events # (not just because we couldn't parse the count) $knownMissing = $noImageIdEvents -or ($eventCountLine -and $dbgIdCount -eq 0) $knownPresent = $hasImageIdEvents -or ($eventCountLine -and $dbgIdCount -gt 0) if ($knownMissing) { Write-Host "[!] MISSING ImageID DbgID EVENTS" -ForegroundColor Red Write-Host " This trace is missing ImageID DbgID (RSDS) events which contain PDB GUID/Age." -ForegroundColor Yellow Write-Host " Without these events, symbol server lookups are impossible because PDB matching" -ForegroundColor Yellow Write-Host " requires the exact GUID+Age from the trace (not extracted from binaries)." -ForegroundColor Yellow Write-Host "" Write-Host " Root cause: The trace was likely captured without the right ETW providers enabled." -ForegroundColor Gray Write-Host " Solution: Re-capture using Profile Explorer's built-in capture (File -> Record Profile)" -ForegroundColor Cyan Write-Host " or from command line: wpr -start CPU" -ForegroundColor Cyan Write-Host "" } elseif ($knownPresent) { Write-Host "[OK] Trace has ImageID DbgID events (PDB GUID/Age available)" -ForegroundColor Green if ($dbgIdCount -gt 0) { Write-Host " ImageID_DbgID event count: $dbgIdCount" -ForegroundColor Gray } } else { Write-Host "[?] Could not determine ImageID event status from log" -ForegroundColor Yellow } if ($symbolServerDisabled) { Write-Host "[!] SYMBOL SERVER DISABLED" -ForegroundColor Yellow Write-Host " Symbol server lookups were disabled (either by user or due to missing ImageID events)." -ForegroundColor Gray Write-Host " Only local/cached symbols will be used." -ForegroundColor Gray Write-Host "" } elseif ($symbolServerEnabled) { Write-Host "[OK] Symbol server enabled" -ForegroundColor Green } Write-Host "" # ============================================================================ # PHASE TIMING ANALYSIS # ============================================================================ Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " PHASE TIMING ANALYSIS" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray # Find phase markers $loadStart = $log | Where-Object { $_ -match 'Starting LoadBinaryAndDebugFiles' } | Select-Object -First 1 $loadComplete = $log | Where-Object { $_ -match 'LoadBinaryAndDebugFiles completed' } | Select-Object -First 1 $binaryPhaseStart = $log | Where-Object { $_ -match 'Binary download phase: Started' } | Select-Object -First 1 $binaryPhaseEnd = $log | Where-Object { $_ -match 'All binary downloads completed|Binary download complete' } | Select-Object -First 1 $pdbPhaseStart = $log | Where-Object { $_ -match 'PDB download phase: Started' } | Select-Object -First 1 $pdbPhaseEnd = $log | Where-Object { $_ -match 'All PDB downloads completed|PDB download complete' } | Select-Object -First 1 function Get-TimestampFromLine($line) { if ($line -match '^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})') { return [datetime]::ParseExact($Matches[1], "yyyy-MM-dd HH:mm:ss.fff", $null) } return $null } $startTime = Get-TimestampFromLine $loadStart $endTime = Get-TimestampFromLine $loadComplete $binStartTime = Get-TimestampFromLine $binaryPhaseStart $binEndTime = Get-TimestampFromLine $binaryPhaseEnd $pdbStartTime = Get-TimestampFromLine $pdbPhaseStart $pdbEndTime = Get-TimestampFromLine $pdbPhaseEnd # Extract embedded time from log if available: "LoadBinaryAndDebugFiles completed in X.Xs" $loadCompleteEmbeddedTime = $null if ($loadComplete -match 'completed in (\d+\.?\d*)s') { $loadCompleteEmbeddedTime = [double]$Matches[1] } # Calculate total time - use embedded time, or timestamp diff, but sanity check against PDB time later $totalTime = $null if ($loadCompleteEmbeddedTime) { $totalTime = $loadCompleteEmbeddedTime } elseif ($startTime -and $endTime) { $totalTime = ($endTime - $startTime).TotalSeconds } if ($binStartTime -and $binEndTime) { $binTime = ($binEndTime - $binStartTime).TotalSeconds Write-Host " Binary Download Phase: " -NoNewline Write-Host ("{0:F1}s" -f $binTime) -ForegroundColor $(if ($binTime -gt 60) { "Red" } elseif ($binTime -gt 30) { "Yellow" } else { "Green" }) } # Calculate PDB/Symbol loading time # Try multiple approaches since log format may vary # Approach 1: Find time from "Starting PDB/symbol file search" to last PDBDebugInfo BEFORE lazy load $pdbStartLine = $log | Where-Object { $_ -match '\[SymbolLoading\].*Starting PDB' } | Select-Object -First 1 $pdbStartTs = Get-TimestampFromLine $pdbStartLine # Find the line index where lazy load starts (if any) - we only want PDBDebugInfo before this $lazyLoadLineIndex = $null for ($i = 0; $i -lt $log.Count; $i++) { if ($log[$i] -match '\[LazyBinaryLoad\]') { $lazyLoadLineIndex = $i break } } # Get last PDBDebugInfo line BEFORE lazy load (or last overall if no lazy load) $pdbEndLine = $null if ($lazyLoadLineIndex) { $pdbEndLine = $log[0..($lazyLoadLineIndex-1)] | Where-Object { $_ -match '\[PDBDebugInfo\]' } | Select-Object -Last 1 } else { $pdbEndLine = $log | Where-Object { $_ -match '\[PDBDebugInfo\]' } | Select-Object -Last 1 } $pdbEndTs = Get-TimestampFromLine $pdbEndLine # Approach 2: Try to extract embedded time from log message $pdbTimeLine = $log | Where-Object { $_ -match 'PDB downloads? completed? in (\d+\.?\d*)s|PDB download complete:.*in (\d+\.?\d*)s' } | Select-Object -First 1 $pdbEmbeddedTime = $null if ($pdbTimeLine -match 'in (\d+\.?\d*)s') { $pdbEmbeddedTime = [double]$Matches[1] } $pdbTime = $null if ($pdbStartTs -and $pdbEndTs) { $pdbTime = ($pdbEndTs - $pdbStartTs).TotalSeconds } elseif ($pdbEmbeddedTime) { $pdbTime = $pdbEmbeddedTime } # Display timing - use PDB time as authoritative if total time seems wrong if ($pdbTime -and $pdbTime -gt 0.5) { # If total time < PDB time, use PDB time as total (old logs may have wrong embedded time) if ($totalTime -and $totalTime -lt $pdbTime) { $totalTime = $pdbTime } } if ($totalTime -and $totalTime -gt 0.5) { Write-Host "Total Symbol Loading Time: " -NoNewline Write-Host ("{0:F1}s" -f $totalTime) -ForegroundColor $(if ($totalTime -gt 120) { "Red" } elseif ($totalTime -gt 60) { "Yellow" } else { "Green" }) } if ($pdbTime -and $pdbTime -gt 0.5) { Write-Host " PDB/Symbol Loading: " -NoNewline Write-Host ("{0:F1}s" -f $pdbTime) -ForegroundColor $(if ($pdbTime -gt 60) { "Red" } elseif ($pdbTime -gt 30) { "Yellow" } else { "Green" }) } # Count timeouts vs successes $binaryTimeouts = ($log | Where-Object { $_ -match '\[BinarySearch\] TIMEOUT' }).Count $binaryFound = ($log | Where-Object { $_ -match '\[BinarySearch\] Found binary for' }).Count $binaryFailed = ($log | Where-Object { $_ -match '\[BinarySearch\] Failed to find binary' }).Count $binarySkipped = ($log | Where-Object { $_ -match '\[BinarySearch\] SKIPPED' }).Count $binarySkippedDisabled = ($log | Where-Object { $_ -match '\[SymbolLoading\] Symbol server disabled - skipping binary downloads' }).Count $pdbTimeouts = ($log | Where-Object { $_ -match '\[SymbolSearch\] TIMEOUT' }).Count $pdbFound = ($log | Where-Object { $_ -match '\[SymbolSearch\] Successfully found symbol' }).Count $pdbFailed = ($log | Where-Object { $_ -match '\[SymbolSearch\] Failed to find symbol' }).Count $pdbSkipped = ($log | Where-Object { $_ -match '\[SymbolLoading\] Skipping PDB lookup' }).Count $pdbSkippedDisabled = ($log | Where-Object { $_ -match '\[SymbolLoading\] Symbol server disabled' }).Count Write-Host "" Write-Host "Binary Search Results:" -ForegroundColor Cyan if ($binarySkippedDisabled -gt 0) { Write-Host " [Symbol server disabled - all downloads skipped]" -ForegroundColor Yellow } else { Write-Host " Found: $binaryFound" -ForegroundColor Green Write-Host " Failed: $binaryFailed" -ForegroundColor Yellow Write-Host " Timeouts: $binaryTimeouts" -ForegroundColor $(if ($binaryTimeouts -gt 10) { "Red" } else { "Yellow" }) Write-Host " Skipped: $binarySkipped" -ForegroundColor Gray } Write-Host "" Write-Host "PDB Search Results:" -ForegroundColor Cyan if ($pdbSkippedDisabled -gt 0 -and $pdbFound -eq 0) { Write-Host " [Symbol server disabled - no PDB lookups attempted]" -ForegroundColor Yellow } else { Write-Host " Found: $pdbFound" -ForegroundColor Green Write-Host " Failed: $pdbFailed" -ForegroundColor Yellow Write-Host " Timeouts: $pdbTimeouts" -ForegroundColor $(if ($pdbTimeouts -gt 10) { "Red" } else { "Yellow" }) Write-Host " Skipped (company filter): $pdbSkipped" -ForegroundColor Gray } Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " LOG STATISTICS" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "Total Lines: $($log.Count)" Write-Host " Information: $($infoLines.Count)" -ForegroundColor Green Write-Host " Warnings: $($warningLines.Count)" -ForegroundColor Yellow Write-Host " Debug: $($debugLines.Count)" -ForegroundColor Gray Write-Host " Errors: $($errorLines.Count)" -ForegroundColor Red Write-Host "" # Analyze NOT_RESOLVED failures $notResolved = $warningLines | Where-Object { $_ -match 'NOT_RESOLVED' } $failedModules = @{} $notResolved | ForEach-Object { if ($_ -match 'Module: ([^,]+),') { $module = $Matches[1] if ($failedModules.ContainsKey($module)) { $failedModules[$module]++ } else { $failedModules[$module] = 1 } } } Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " SYMBOL RESOLUTION FAILURES" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "Total unresolved symbols: $($notResolved.Count)" -ForegroundColor Red Write-Host "Unique modules with failures: $($failedModules.Count)" Write-Host "" # Top failed modules Write-Host "Top 30 Modules Missing Symbols:" -ForegroundColor Yellow Write-Host "" $sortedFailures = $failedModules.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 30 $totalFailures = ($failedModules.Values | Measure-Object -Sum).Sum foreach ($item in $sortedFailures) { $pct = [math]::Round(($item.Value / $totalFailures) * 100, 1) $bar = "#" * [math]::Min([int]($pct / 2), 40) $color = if ($item.Value -gt 500) { "Red" } elseif ($item.Value -gt 100) { "Yellow" } else { "White" } Write-Host ("{0,6} ({1,5}%) {2,-30} {3}" -f $item.Value, $pct, $item.Key, $bar) -ForegroundColor $color } # Analyze successful resolutions $resolved = $infoLines | Where-Object { $_ -match 'resolved via debug info|found in cache|found via PDB query' } $successModules = @{} $resolved | ForEach-Object { if ($_ -match 'Module: ([^,]+),') { $module = $Matches[1] if ($successModules.ContainsKey($module)) { $successModules[$module]++ } else { $successModules[$module] = 1 } } } Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " SUCCESSFUL SYMBOL RESOLUTION" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "Total resolved symbols: $($resolved.Count)" -ForegroundColor Green Write-Host "" Write-Host "Top 20 Modules With Symbols:" -ForegroundColor Green $sortedSuccess = $successModules.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 20 foreach ($item in $sortedSuccess) { Write-Host ("{0,6} - {1}" -f $item.Value, $item.Key) -ForegroundColor Green } # Analyze binary loading times $slowBinaries = $log | Where-Object { $_ -match '\[BinaryLoading\].*Duration:' } $binaryTimes = @{} $slowBinaries | ForEach-Object { if ($_ -match 'Binary: ([^,]+).*Duration: (\d+)ms') { $binary = $Matches[1] $duration = [int]$Matches[2] if (-not $binaryTimes.ContainsKey($binary) -or $binaryTimes[$binary] -lt $duration) { $binaryTimes[$binary] = $duration } } } if ($binaryTimes.Count -gt 0) { Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " SLOW BINARY LOADING (>500ms)" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray $slowest = $binaryTimes.GetEnumerator() | Where-Object { $_.Value -gt 500 } | Sort-Object Value -Descending | Select-Object -First 20 if ($slowest.Count -gt 0) { foreach ($item in $slowest) { $secs = [math]::Round($item.Value / 1000, 2) $color = if ($item.Value -gt 5000) { "Red" } elseif ($item.Value -gt 2000) { "Yellow" } else { "White" } Write-Host ("{0,8}ms ({1,5}s) - {2}" -f $item.Value, $secs, $item.Key) -ForegroundColor $color } } else { Write-Host "No slow binary loads detected." -ForegroundColor Green } } # Analyze PDB loading $pdbLoads = $log | Where-Object { $_ -match '\[PDBDebugInfo\]' } $pdbCacheHits = ($pdbLoads | Where-Object { $_ -match 'found in cache' }).Count $pdbQueries = ($pdbLoads | Where-Object { $_ -match 'found via PDB query' }).Count $pdbAlreadyLoaded = ($pdbLoads | Where-Object { $_ -match 'already loaded' }).Count Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " PDB LOADING EFFICIENCY" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "PDB Cache Hits: $pdbCacheHits" -ForegroundColor Green Write-Host "PDB Queries: $pdbQueries" -ForegroundColor Cyan Write-Host "PDB Already Loaded: $pdbAlreadyLoaded" -ForegroundColor Green $totalPdbOps = $pdbCacheHits + $pdbQueries + $pdbAlreadyLoaded if ($totalPdbOps -gt 0) { $cacheRate = [math]::Round((($pdbCacheHits + $pdbAlreadyLoaded) / $totalPdbOps) * 100, 1) Write-Host "Cache Hit Rate: $cacheRate%" -ForegroundColor $(if ($cacheRate -gt 80) { "Green" } else { "Yellow" }) } # Module initialization analysis $moduleInits = $log | Where-Object { $_ -match '\[ModuleInit\]' } $modulesWithDebugInfo = ($moduleInits | Where-Object { $_ -match 'HasDebugInfo=True' }).Count $modulesWithoutDebugInfo = ($moduleInits | Where-Object { $_ -match 'HasDebugInfo=False' }).Count Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " MODULE INITIALIZATION" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "Modules With Debug Info: $modulesWithDebugInfo" -ForegroundColor Green Write-Host "Modules Without Debug Info: $modulesWithoutDebugInfo" -ForegroundColor Yellow # Categorize failed modules Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " MODULE CATEGORIES" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray $kernelModules = @() $microsoftOtherModules = @() $driverModules = @() $thirdPartyModules = @() foreach ($module in $failedModules.Keys) { $count = $failedModules[$module] $moduleLower = $module.ToLower() # Check if module is marked as Microsoft from trace FileVersion events $isMicrosoftFromTrace = $microsoftModules.ContainsKey($moduleLower) -and $microsoftModules[$moduleLower] # Fallback to name-based heuristics if no trace info $isMicrosoftByName = $module -match '^Windows\.|^Microsoft\.|explorer\.exe|shell32|combase|ExplorerFrame|dui70|duser|thumbcache|twinui|dwm|dcomp|CoreMessaging' $isMicrosoft = $isMicrosoftFromTrace -or $isMicrosoftByName if ($module -match 'ntoskrnl|ntkrnl|hal\.dll') { $kernelModules += [PSCustomObject]@{Name=$module; Count=$count; IsMicrosoft=$true} } elseif ($module -match '\.sys$') { $driverModules += [PSCustomObject]@{Name=$module; Count=$count; IsMicrosoft=$isMicrosoft} } elseif ($isMicrosoft) { $microsoftOtherModules += [PSCustomObject]@{Name=$module; Count=$count; IsMicrosoft=$true} } else { $thirdPartyModules += [PSCustomObject]@{Name=$module; Count=$count; IsMicrosoft=$false} } } $kernelTotal = ($kernelModules | Measure-Object -Property Count -Sum).Sum $microsoftTotal = ($microsoftOtherModules | Measure-Object -Property Count -Sum).Sum $driverTotal = ($driverModules | Measure-Object -Property Count -Sum).Sum $thirdPartyTotal = ($thirdPartyModules | Measure-Object -Property Count -Sum).Sum $msDriverCount = ($driverModules | Where-Object { $_.IsMicrosoft } | Measure-Object).Count Write-Host "" Write-Host "Kernel/NT: $kernelTotal failures in $($kernelModules.Count) modules" -ForegroundColor Red Write-Host "Microsoft: $microsoftTotal failures in $($microsoftOtherModules.Count) modules" -ForegroundColor Yellow Write-Host "Drivers: $driverTotal failures in $($driverModules.Count) modules ($msDriverCount Microsoft)" -ForegroundColor Yellow Write-Host "Third-Party: $thirdPartyTotal failures in $($thirdPartyModules.Count) modules" -ForegroundColor White # Extract symbol path from log $symbolPathLine = $log | Where-Object { $_ -match '\[SymbolSearch\] Symbol search path:' } | Select-Object -First 1 $symbolPath = "" if ($symbolPathLine -match 'Symbol search path:\s*(.+)$') { $symbolPath = $Matches[1].Trim() } # Recommendations Write-Host "" Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host " SYMBOL CONFIGURATION" -ForegroundColor Cyan Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host "" if ($symbolPath) { Write-Host "Symbol Path Used:" -ForegroundColor Cyan # Split on semicolons and display each part $symbolPath -split ';' | Where-Object { $_.Trim() } | ForEach-Object { Write-Host " - $_" -ForegroundColor White } Write-Host "" } else { Write-Host "[!] Could not determine symbol path from log" -ForegroundColor Yellow Write-Host "" } Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host " RECOMMENDATIONS" -ForegroundColor Cyan Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host "" if ($failedModules.ContainsKey("ntoskrnl.exe") -and $failedModules["ntoskrnl.exe"] -gt 100) { Write-Host "[!] " -NoNewline -ForegroundColor Red Write-Host "High ntoskrnl.exe failures ($($failedModules['ntoskrnl.exe'])). Kernel symbols not resolving." Write-Host " This binary may not have public symbols, or the symbol server is timing out." Write-Host "" } if ($failedModules.ContainsKey("combase.dll") -and $failedModules["combase.dll"] -gt 100) { Write-Host "[!] " -NoNewline -ForegroundColor Red Write-Host "High combase.dll failures ($($failedModules['combase.dll'])). COM infrastructure symbols missing." Write-Host " Verify this binary version has symbols available on your configured symbol server." Write-Host "" } if ($failedModules.ContainsKey("explorer.exe") -and $failedModules["explorer.exe"] -gt 50) { Write-Host "[!] " -NoNewline -ForegroundColor Yellow Write-Host "explorer.exe symbols missing ($($failedModules['explorer.exe'])). Profile is for explorer.exe but symbols not loaded." Write-Host "" } $thirdPartyHigh = $thirdPartyModules | Where-Object { $_.Count -gt 50 } if ($thirdPartyHigh.Count -gt 0) { Write-Host "[i] " -NoNewline -ForegroundColor Cyan Write-Host "Third-party modules without symbols (PDBs not available on symbol server):" foreach ($m in $thirdPartyHigh | Sort-Object Count -Descending | Select-Object -First 5) { Write-Host " - $($m.Name) ($($m.Count) failures)" } Write-Host "" } # Also show high-failure Microsoft modules (may indicate symbol server issues) $microsoftHigh = $microsoftOtherModules | Where-Object { $_.Count -gt 50 } if ($microsoftHigh.Count -gt 0) { Write-Host "[!] " -NoNewline -ForegroundColor Yellow Write-Host "Microsoft modules without symbols (check symbol server access):" foreach ($m in $microsoftHigh | Sort-Object Count -Descending | Select-Object -First 5) { Write-Host " - $($m.Name) ($($m.Count) failures)" } Write-Host "" } # Analyze timestamp gaps (find slow operations) - OPTIMIZED Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " TIMESTAMP GAP ANALYSIS (Slow Operations)" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "Analyzing timestamps..." -ForegroundColor Gray # Optimized: Use ArrayList and only parse timestamps, track gaps inline $gaps = [System.Collections.ArrayList]::new() $lazyLoadOps = [System.Collections.ArrayList]::new() # Track lazy load operations (start to finish) $prevTimestamp = $null $prevLine = $null $prevLineNum = 0 $lineNum = 0 $totalTimestamped = 0 $loadingCompleted = $false # For tracking lazy load operations $lazyLoadStart = $null $lazyLoadStartLine = $null $lazyLoadModule = $null foreach ($line in $log) { $lineNum++ # Track when initial loading is done - gaps after this before lazy load are user think time if ($line -match 'LoadBinaryAndDebugFiles completed|=== Trace loading completed') { $loadingCompleted = $true } # Track lazy load operations (start to finish for each binary) if ($line -match '\[LazyBinaryLoad\] Loading binary on-demand for ([^\s]+)') { $lazyLoadModule = $Matches[1] # Save module name BEFORE timestamp match overwrites $Matches $lazyLoadStart = Get-TimestampFromLine $line $lazyLoadStartLine = $lineNum } if ($lazyLoadStart -and ($line -match '\[LazyBinaryLoad\] Successfully loaded|\[LazyBinaryLoad\] Could not find|\[LazyBinaryLoad\] Found binary')) { $lazyLoadEnd = Get-TimestampFromLine $line $lazyLoadSuccess = $line -match '\[LazyBinaryLoad\] (Successfully loaded|Found binary)' if ($lazyLoadEnd) { $lazyLoadMs = ($lazyLoadEnd - $lazyLoadStart).TotalMilliseconds [void]$lazyLoadOps.Add([PSCustomObject]@{ Module = $lazyLoadModule DurationMs = $lazyLoadMs Success = $lazyLoadSuccess StartLine = $lazyLoadStartLine EndLine = $lineNum StartTime = $lazyLoadStart.ToString("HH:mm:ss.fff") EndTime = $lazyLoadEnd.ToString("HH:mm:ss.fff") }) } $lazyLoadStart = $null $lazyLoadModule = $null } if ($line -match '^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3})') { $totalTimestamped++ $timestamp = [datetime]::ParseExact($Matches[1], "yyyy-MM-dd HH:mm:ss.fff", $null) if ($null -ne $prevTimestamp) { $gapMs = ($timestamp - $prevTimestamp).TotalMilliseconds if ($gapMs -gt 500) { # Only track gaps > 500ms for performance $gapObj = [PSCustomObject]@{ GapMs = $gapMs StartLine = $prevLineNum EndLine = $lineNum StartTime = $prevTimestamp.ToString("HH:mm:ss.fff") EndTime = $timestamp.ToString("HH:mm:ss.fff") BeforeLine = $prevLine AfterLine = $line } # Only track gaps during initial load (not lazy load related) # Lazy load operations are tracked separately $isLazyLoadRelated = ($line -match '\[LazyBinaryLoad\]') -or ($prevLine -match '\[LazyBinaryLoad\]') if (-not $isLazyLoadRelated) { [void]$gaps.Add($gapObj) } } } $prevTimestamp = $timestamp $prevLine = $line $prevLineNum = $lineNum } } Write-Host "Total timestamped lines: $totalTimestamped" Write-Host "Initial load gaps > 500ms: $($gaps.Count)" -ForegroundColor $(if ($gaps.Count -gt 0) { "Yellow" } else { "Green" }) if ($lazyLoadOps.Count -gt 0) { $lazyLoadTotal = ($lazyLoadOps | Measure-Object -Property DurationMs -Sum).Sum / 1000 $lazyLoadFailCount = @($lazyLoadOps | Where-Object { -not $_.Success }).Count $lazyLoadColor = if ($lazyLoadFailCount -gt 0) { "Red" } else { "Cyan" } $lazyLoadSuffix = if ($lazyLoadFailCount -gt 0) { ", $lazyLoadFailCount FAILED" } else { "" } Write-Host "Lazy load operations: $($lazyLoadOps.Count) binaries ($([math]::Round($lazyLoadTotal, 1))s total$lazyLoadSuffix)" -ForegroundColor $lazyLoadColor } Write-Host "" # Sort by gap size and show top gaps $topGaps = $gaps | Sort-Object GapMs -Descending | Select-Object -First 25 if ($topGaps.Count -gt 0) { Write-Host "Top 25 Largest Gaps (potential slow operations):" -ForegroundColor Yellow Write-Host "" $rank = 0 foreach ($gap in $topGaps) { $rank++ $secs = [math]::Round($gap.GapMs / 1000, 2) $color = if ($gap.GapMs -gt 5000) { "Red" } elseif ($gap.GapMs -gt 1000) { "Yellow" } else { "White" } Write-Host ("{0,3}. " -f $rank) -NoNewline -ForegroundColor Cyan Write-Host ("{0,8}ms ({1,6}s) " -f [int]$gap.GapMs, $secs) -NoNewline -ForegroundColor $color Write-Host "Lines $($gap.StartLine)-$($gap.EndLine) @ $($gap.StartTime)" -ForegroundColor Gray # Extract context from the lines $beforeContext = "" $afterContext = "" if ($gap.BeforeLine -match '\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.*)') { $beforeContext = "[$($Matches[2])] $($Matches[3].Substring(0, [Math]::Min(60, $Matches[3].Length)))" } if ($gap.AfterLine -match '\[([^\]]+)\]\s*\[([^\]]+)\]\s*(.*)') { $afterContext = "[$($Matches[2])] $($Matches[3].Substring(0, [Math]::Min(60, $Matches[3].Length)))" } if ($beforeContext) { Write-Host " Before: $beforeContext..." -ForegroundColor DarkGray } if ($afterContext) { Write-Host " After: $afterContext..." -ForegroundColor DarkGray } Write-Host "" } # Summary statistics $totalGapTime = ($gaps | Measure-Object -Property GapMs -Sum).Sum $avgGap = ($gaps | Measure-Object -Property GapMs -Average).Average $gapsOver1s = ($gaps | Where-Object { $_.GapMs -gt 1000 }).Count $gapsOver5s = ($gaps | Where-Object { $_.GapMs -gt 5000 }).Count Write-Host "Gap Statistics:" -ForegroundColor Cyan Write-Host " Total gaps > 100ms: $($gaps.Count)" Write-Host " Gaps > 1 second: $gapsOver1s" -ForegroundColor $(if ($gapsOver1s -gt 10) { "Yellow" } else { "White" }) Write-Host " Gaps > 5 seconds: $gapsOver5s" -ForegroundColor $(if ($gapsOver5s -gt 0) { "Red" } else { "White" }) Write-Host " Total gap time: $([math]::Round($totalGapTime / 1000, 2))s" Write-Host " Average gap: $([math]::Round($avgGap, 0))ms" # Calculate total trace time if ($timestampedLines.Count -gt 1) { $firstTime = $timestampedLines[0].Timestamp $lastTime = $timestampedLines[-1].Timestamp $totalTime = ($lastTime - $firstTime).TotalSeconds $gapPercent = [math]::Round(($totalGapTime / 1000) / $totalTime * 100, 1) Write-Host "" Write-Host " Total trace time: $([math]::Round($totalTime, 2))s" Write-Host " Time in gaps: $gapPercent%" -ForegroundColor $(if ($gapPercent -gt 50) { "Red" } elseif ($gapPercent -gt 25) { "Yellow" } else { "Green" }) } } else { Write-Host "No significant performance gaps (>500ms) detected." -ForegroundColor Green } # Show lazy load operations (on-demand binary downloads) if ($lazyLoadOps.Count -gt 0) { Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " LAZY LOAD OPERATIONS (on-demand binary downloads)" -ForegroundColor Cyan Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host "Time spent downloading binaries when user views assembly/graph." -ForegroundColor Gray Write-Host "" $lazyLoadSucceeded = @($lazyLoadOps | Where-Object { $_.Success }) $lazyLoadFailed = @($lazyLoadOps | Where-Object { -not $_.Success }) foreach ($op in $lazyLoadOps | Sort-Object DurationMs -Descending | Select-Object -First 10) { $secs = [math]::Round($op.DurationMs / 1000, 2) $status = if ($op.Success) { "OK" } else { "FAILED" } $color = if (-not $op.Success) { "Red" } elseif ($op.DurationMs -gt 5000) { "Yellow" } elseif ($op.DurationMs -gt 2000) { "Yellow" } else { "Green" } Write-Host (" {0,6}ms ({1,5}s) - {2} [{3}]" -f [int]$op.DurationMs, $secs, $op.Module, $status) -ForegroundColor $color } $lazyLoadTotal = ($lazyLoadOps | Measure-Object -Property DurationMs -Sum).Sum / 1000 Write-Host "" if ($lazyLoadFailed.Count -gt 0) { Write-Host " Succeeded: $($lazyLoadSucceeded.Count), Failed: $($lazyLoadFailed.Count)" -ForegroundColor Red Write-Host " Failed modules: $($lazyLoadFailed.Module -join ', ')" -ForegroundColor Red } else { Write-Host " All $($lazyLoadSucceeded.Count) lazy loads succeeded" -ForegroundColor Green } Write-Host " Total lazy load time: $([math]::Round($lazyLoadTotal, 1))s" -ForegroundColor Cyan } # Analyze what operations are causing the biggest gaps (excluding user think time) Write-Host "" Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " GAP CAUSE ANALYSIS" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray $gapCauses = @{} foreach ($gap in $gaps | Where-Object { $_.GapMs -gt 500 }) { $cause = "Unknown" if ($gap.AfterLine -match '\[LazyBinaryLoad\].*for ([^\s]+)') { # LazyBinaryLoad during loading (not user-triggered) is a real delay $cause = "LazyBinaryLoad: $($Matches[1])" } elseif ($gap.AfterLine -match '\[ModuleInit\].*Starting.*module: ([^\s]+)') { $cause = "ModuleInit: $($Matches[1])" } elseif ($gap.AfterLine -match '\[BinaryLoading\].*Binary: ([^\s,]+)') { $cause = "BinaryLoad: $($Matches[1])" } elseif ($gap.AfterLine -match '\[PDBDebugInfo\].*Binary: ([^\s,]+)') { $cause = "PDBLoad: $($Matches[1])" } elseif ($gap.AfterLine -match '\[SymbolSearch\].*for ([^\s]+)') { $cause = "SymbolSearch: $($Matches[1])" } elseif ($gap.AfterLine -match '\[DebugInfoInit\].*module ([^\s]+)') { $cause = "DebugInfoInit: $($Matches[1])" } elseif ($gap.AfterLine -match '\[FunctionResolution\].*Module: ([^\s,]+)') { $cause = "FuncResolve: $($Matches[1])" } elseif ($gap.BeforeLine -match '\[ModuleInit\].*module: ([^\s]+)') { $cause = "After ModuleInit: $($Matches[1])" } elseif ($gap.BeforeLine -match '\[SymbolLoading\].*PDB download') { $cause = "PDB Downloads" } if ($gapCauses.ContainsKey($cause)) { $gapCauses[$cause] += $gap.GapMs } else { $gapCauses[$cause] = $gap.GapMs } } if ($gapCauses.Count -gt 0) { Write-Host "Operations causing most delay (gaps > 500ms):" -ForegroundColor Yellow Write-Host "" $gapCauses.GetEnumerator() | Sort-Object Value -Descending | Select-Object -First 15 | ForEach-Object { $secs = [math]::Round($_.Value / 1000, 2) Write-Host ("{0,8}ms ({1,6}s) - {2}" -f [int]$_.Value, $secs, $_.Key) } } # Calculate overall resolution rate $totalAttempts = $resolved.Count + $notResolved.Count if ($totalAttempts -gt 0) { $resolutionRate = [math]::Round(($resolved.Count / $totalAttempts) * 100, 1) Write-Host "" Write-Host "Overall Symbol Resolution Rate: " -NoNewline if ($resolutionRate -gt 80) { Write-Host "$resolutionRate%" -ForegroundColor Green } elseif ($resolutionRate -gt 60) { Write-Host "$resolutionRate%" -ForegroundColor Yellow } else { Write-Host "$resolutionRate%" -ForegroundColor Red } } Write-Host "" Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host " SUMMARY DIAGNOSIS" -ForegroundColor Cyan Write-Host ("=" * 80) -ForegroundColor Cyan Write-Host "" # Determine the primary issue $primaryIssue = $null $issueDetails = @() if ($noImageIdEvents -or $dbgIdCount -eq 0) { $primaryIssue = "Missing ImageID DbgID Events" $issueDetails += "The trace is missing PDB GUID/Age information required for symbol server lookups." $issueDetails += "This typically happens when using traces from external tools that don't capture ImageID events." $issueDetails += "" $issueDetails += "FIX: Re-capture with Profile Explorer (File -> Record Profile) or 'wpr -start CPU'" } elseif ($binaryTimeouts -gt 10 -or $pdbTimeouts -gt 10) { $primaryIssue = "Symbol Server Timeouts" $issueDetails += "Multiple symbol server requests are timing out." $issueDetails += "This could indicate network issues, slow symbol server, or corporate firewall blocks." $issueDetails += "" $issueDetails += "FIX: Check network connectivity, verify symbol server URL, or increase timeout settings." } elseif ($totalAttempts -gt 0 -and $resolutionRate -lt 50) { $primaryIssue = "Low Symbol Resolution Rate" $issueDetails += "Only $resolutionRate% of symbols are resolving successfully." $issueDetails += "This may indicate missing symbols on the symbol server or version mismatch." $issueDetails += "" $issueDetails += "FIX: Ensure symbol server is correctly configured and symbols exist for your binaries." } else { $primaryIssue = "Symbol Loading Appears Normal" $issueDetails += "No major issues detected in symbol loading." if ($totalAttempts -gt 0) { $issueDetails += "Symbol resolution rate: $resolutionRate%" } } Write-Host "Primary Issue: " -NoNewline if ($primaryIssue -eq "Symbol Loading Appears Normal") { Write-Host $primaryIssue -ForegroundColor Green } else { Write-Host $primaryIssue -ForegroundColor Red } Write-Host "" foreach ($detail in $issueDetails) { if ($detail -match '^FIX:') { Write-Host $detail -ForegroundColor Cyan } else { Write-Host " $detail" -ForegroundColor Gray } } Write-Host "" # ============================================================================ # SOURCE FILE LOADING ANALYSIS # ============================================================================ Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " SOURCE FILE LOADING ANALYSIS" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray $sourceFileLines = $log | Where-Object { $_ -match '\[SourceFile\]' } $strippedPdbLines = $log | Where-Object { $_ -match 'PDB appears to be STRIPPED' } $privatePdbLines = $log | Where-Object { $_ -match 'PDB has source info\.' } $sourceServerEnabled = $log | Where-Object { $_ -match 'SourceServerEnabled=True' } | Select-Object -First 1 $sourceServerLookups = $log | Where-Object { $_ -match 'Attempting source server lookup' } $sourceFileSuccess = $log | Where-Object { $_ -match 'Downloaded and verified source file' } $sourceFileFailed = $log | Where-Object { $_ -match 'Failed to download|GetSourceFile returned: null|lineInfo is Unknown' } $pdbFileSizes = $log | Where-Object { $_ -match '\[PDBDebugInfo\] PDB file size:' } # Parse PDB file sizes and build lookup table $pdbSizeTable = @{} $pdbFileSizes | ForEach-Object { if ($_ -match 'PDB file size: ([0-9,]+) bytes \(([0-9.]+) MB\) - (.+)$') { $sizeMB = [double]$Matches[2] $path = $Matches[3] $pdbName = Split-Path $path -Leaf $pdbSizeTable[$path] = @{ Name = $pdbName; SizeMB = $sizeMB } } } # Parse stripped/private PDB lists $strippedPdbPaths = @() $strippedPdbLines | ForEach-Object { if ($_ -match 'for: (.+)$') { $strippedPdbPaths += $Matches[1] } } $privatePdbPaths = @() $privatePdbLines | ForEach-Object { # Private PDB log format: "PDB has source info. Sample source file: " # The PDB path is logged earlier, need to correlate } Write-Host "" # PDB Classification Summary $totalPdbs = $strippedPdbLines.Count + $privatePdbLines.Count if ($totalPdbs -gt 0) { Write-Host "PDB CLASSIFICATION SUMMARY:" -ForegroundColor Cyan Write-Host ("=" * 50) -ForegroundColor DarkGray $privateCount = $privatePdbLines.Count $strippedCount = $strippedPdbLines.Count $privatePercent = if ($totalPdbs -gt 0) { [math]::Round(($privateCount / $totalPdbs) * 100, 1) } else { 0 } $strippedPercent = if ($totalPdbs -gt 0) { [math]::Round(($strippedCount / $totalPdbs) * 100, 1) } else { 0 } Write-Host " Total PDBs loaded: $totalPdbs" -ForegroundColor White Write-Host " PRIVATE (has source): $privateCount ($privatePercent%)" -ForegroundColor Green Write-Host " PUBLIC/STRIPPED: $strippedCount ($strippedPercent%)" -ForegroundColor Yellow Write-Host "" if ($strippedCount -gt 0 -and $privateCount -gt 0) { Write-Host " [i] Some PDBs are private (from symweb), others are public (from msdl)." -ForegroundColor Gray Write-Host " Private PDBs support source file viewing. Public PDBs only have function names." -ForegroundColor Gray } elseif ($strippedCount -gt 0 -and $privateCount -eq 0) { Write-Host " [!] ALL PDBs are PUBLIC/STRIPPED - source file viewing will NOT work." -ForegroundColor Red Write-Host " Check if symweb auth is working. You may need to re-authenticate." -ForegroundColor Yellow } elseif ($privateCount -gt 0 -and $strippedCount -eq 0) { Write-Host " [OK] All PDBs are PRIVATE - source file viewing should work!" -ForegroundColor Green } Write-Host "" } Write-Host "Source File Lookups:" -ForegroundColor Cyan Write-Host " Total [SourceFile] log entries: $($sourceFileLines.Count)" Write-Host " Source server lookups attempted: $($sourceServerLookups.Count)" Write-Host " Successful downloads: $($sourceFileSuccess.Count)" -ForegroundColor $(if ($sourceFileSuccess.Count -gt 0) { "Green" } else { "Yellow" }) Write-Host " Failed lookups: $($sourceFileFailed.Count)" -ForegroundColor $(if ($sourceFileFailed.Count -gt 0) { "Red" } else { "Green" }) Write-Host "" if ($strippedPdbLines.Count -gt 0) { Write-Host "STRIPPED PDBs (no source info):" -ForegroundColor Yellow $strippedPdbPaths | Select-Object -First 10 | ForEach-Object { $path = $_ $pdbName = Split-Path $path -Leaf $sizeInfo = $pdbSizeTable[$path] if ($sizeInfo) { Write-Host (" {0,8:F2} MB - {1}" -f $sizeInfo.SizeMB, $pdbName) -ForegroundColor Yellow } else { Write-Host " - $pdbName" -ForegroundColor Yellow } } if ($strippedPdbPaths.Count -gt 10) { Write-Host " ... and $($strippedPdbPaths.Count - 10) more" -ForegroundColor Gray } Write-Host "" } if ($pdbFileSizes.Count -gt 0) { Write-Host "PDB File Sizes (top 10 by size):" -ForegroundColor Cyan # Sort by size descending and show top 10 $sortedPdbs = $pdbSizeTable.Values | Sort-Object -Property SizeMB -Descending | Select-Object -First 10 $sortedPdbs | ForEach-Object { $sizeMB = $_.SizeMB $pdbName = $_.Name Write-Host (" {0,8:F2} MB - {1}" -f $sizeMB, $pdbName) -ForegroundColor White } Write-Host "" } # ============================================================================ # AUTH & SYMBOL SERVER ANALYSIS # ============================================================================ Write-Host ("-" * 80) -ForegroundColor DarkGray Write-Host " AUTH & SYMBOL SERVER ANALYSIS" -ForegroundColor Yellow Write-Host ("-" * 80) -ForegroundColor DarkGray # Look for explicit auth failure/success messages from our logging $authFailed = $log | Where-Object { $_ -match 'auth FAILED|PrimaryServerAuthFailed=True' } $authVerified = $log | Where-Object { $_ -match 'auth VERIFIED|PrimaryServerVerified=True' } $symwebHits = $log | Where-Object { $_ -match 'symweb' -and $_ -match 'TraceEvent log' } $msdlHits = $log | Where-Object { $_ -match 'msdl\.microsoft\.com|download/symbols' -and $_ -match 'TraceEvent log' } Write-Host "" if ($authFailed.Count -gt 0) { Write-Host "[!] AUTH FAILURES DETECTED:" -ForegroundColor Red $authFailed | Select-Object -First 5 | ForEach-Object { Write-Host " $_" -ForegroundColor Yellow } Write-Host "" Write-Host " If you're EXTERNAL to Microsoft, symweb auth failures are expected." -ForegroundColor Gray Write-Host " The fallback to public symbols (msdl) should be automatic." -ForegroundColor Gray Write-Host "" } elseif ($authVerified.Count -gt 0) { Write-Host "[OK] Primary server (symweb) auth verified" -ForegroundColor Green Write-Host "" } else { Write-Host "[?] Could not determine auth status from logs" -ForegroundColor Yellow Write-Host " Look for 401/403 errors in TraceEvent logs below" -ForegroundColor Gray Write-Host "" } # Show TraceEvent logs for symbol downloads $traceEventLogs = $log | Where-Object { $_ -match '\[SymbolSearch\] TraceEvent log for' } if ($traceEventLogs.Count -gt 0) { Write-Host "Symbol Download Details (first 5):" -ForegroundColor Cyan $traceEventLogs | Select-Object -First 5 | ForEach-Object { if ($_ -match 'TraceEvent log for ([^:]+):') { Write-Host " - $($Matches[1])" -ForegroundColor White } } Write-Host "" } Write-Host ("=" * 80) -ForegroundColor Cyan ================================================ FILE: src/.editorconfig ================================================ root = true # Remove the line below if you want to inherit .editorconfig settings from higher directories # C# files [*.cs] #### Core EditorConfig Options #### # Indentation and spacing indent_size = 2 indent_style = space tab_width = 2 # New line preferences insert_final_newline = false #### .NET Coding Conventions #### # Organize usings dotnet_separate_import_directive_groups = false dotnet_sort_system_directives_first = true # this. and Me. preferences dotnet_style_qualification_for_event = false:suggestion dotnet_style_qualification_for_field = false:suggestion dotnet_style_qualification_for_method = false:suggestion dotnet_style_qualification_for_property = false:suggestion # Language keywords vs BCL types preferences dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion dotnet_style_predefined_type_for_member_access = true:suggestion # Parentheses preferences dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none # Modifier preferences dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion # Expression-level preferences dotnet_style_coalesce_expression = true:silent dotnet_style_collection_initializer = true:silent dotnet_style_explicit_tuple_names = true:silent dotnet_style_null_propagation = true:silent dotnet_style_object_initializer = true:silent dotnet_style_operator_placement_when_wrapping = beginning_of_line dotnet_style_prefer_auto_properties = true:silent dotnet_style_prefer_compound_assignment = true:silent dotnet_style_prefer_conditional_expression_over_assignment = true:silent dotnet_style_prefer_conditional_expression_over_return = true:silent dotnet_style_prefer_inferred_anonymous_type_member_names = true:silent dotnet_style_prefer_inferred_tuple_names = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent dotnet_style_prefer_simplified_boolean_expressions = true:silent dotnet_style_prefer_simplified_interpolation = true:suggestion # Field preferences dotnet_style_readonly_field = false:suggestion # Parameter preferences dotnet_code_quality_unused_parameters = all:suggestion #### C# Coding Conventions #### # var preferences csharp_style_var_elsewhere = true:suggestion csharp_style_var_for_built_in_types = true:suggestion csharp_style_var_when_type_is_apparent = true:suggestion # Expression-bodied members csharp_style_expression_bodied_accessors = true:silent csharp_style_expression_bodied_constructors = false:silent csharp_style_expression_bodied_indexers = when_on_single_line:silent csharp_style_expression_bodied_lambdas = true:silent csharp_style_expression_bodied_local_functions = false:silent csharp_style_expression_bodied_methods = false:silent csharp_style_expression_bodied_operators = false:silent csharp_style_expression_bodied_properties = when_on_single_line:silent # Pattern matching preferences csharp_style_pattern_matching_over_as_with_null_check = true:silent csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion csharp_style_prefer_switch_expression = true:suggestion # Null-checking preferences csharp_style_conditional_delegate_call = true:silent # Modifier preferences csharp_prefer_static_local_function = false:suggestion csharp_preferred_modifier_order = public, private, protected, internal, new, static, abstract, virtual, sealed, readonly, override, extern, unsafe, volatile, async:suggestion # Code-block preferences csharp_prefer_braces = true:silent csharp_prefer_simple_using_statement = true:suggestion # Expression-level preferences csharp_prefer_simple_default_expression = true:suggestion csharp_style_deconstructed_variable_declaration = true:suggestion csharp_style_inlined_variable_declaration = true:silent csharp_style_pattern_local_over_anonymous_function = true:suggestion csharp_style_prefer_index_operator = true:silent csharp_style_prefer_range_operator = true:suggestion csharp_style_throw_expression = true:silent csharp_style_unused_value_assignment_preference = discard_variable:suggestion csharp_style_unused_value_expression_statement_preference = discard_variable:silent # 'using' directive preferences csharp_using_directive_placement = outside_namespace:silent #### C# Formatting Rules #### # New line preferences csharp_new_line_before_catch = true csharp_new_line_before_else = true csharp_new_line_before_finally = true csharp_new_line_before_members_in_anonymous_types = true csharp_new_line_before_members_in_object_initializers = false csharp_new_line_before_open_brace = none csharp_new_line_between_query_expression_clauses = true # Indentation preferences csharp_indent_block_contents = true csharp_indent_braces = false csharp_indent_case_contents = true csharp_indent_case_contents_when_block = false csharp_indent_labels = one_less_than_current csharp_indent_switch_labels = true # Space preferences csharp_space_after_cast = false csharp_space_after_colon_in_inheritance_clause = true csharp_space_after_comma = true csharp_space_after_dot = false csharp_space_after_keywords_in_control_flow_statements = true csharp_space_after_semicolon_in_for_statement = true csharp_space_around_binary_operators = before_and_after csharp_space_around_declaration_statements = false csharp_space_before_colon_in_inheritance_clause = true csharp_space_before_comma = false csharp_space_before_dot = false csharp_space_before_open_square_brackets = false csharp_space_before_semicolon_in_for_statement = false csharp_space_between_empty_square_brackets = false csharp_space_between_method_call_empty_parameter_list_parentheses = false csharp_space_between_method_call_name_and_opening_parenthesis = false csharp_space_between_method_call_parameter_list_parentheses = false csharp_space_between_method_declaration_empty_parameter_list_parentheses = false csharp_space_between_method_declaration_name_and_open_parenthesis = false csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_parentheses = false csharp_space_between_square_brackets = false # Wrapping preferences csharp_preserve_single_line_blocks = true csharp_preserve_single_line_statements = false #### Naming styles #### # Naming rules dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion dotnet_naming_rule.types_should_be_pascal_case.symbols = types dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case # Symbol specifications dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected dotnet_naming_symbols.non_field_members.required_modifiers = # Naming styles dotnet_naming_style.pascal_case.required_prefix = dotnet_naming_style.pascal_case.required_suffix = dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_naming_style.begins_with_i.required_prefix = I dotnet_naming_style.begins_with_i.required_suffix = dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case # Microsoft .NET properties dotnet_naming_rule.event_rule.import_to_resharper = as_predefined dotnet_naming_rule.event_rule.severity = none dotnet_naming_rule.event_rule.style = pascal_case dotnet_naming_rule.event_rule.symbols = event_symbols dotnet_naming_rule.interfaces_rule.import_to_resharper = as_predefined dotnet_naming_rule.interfaces_rule.severity = none dotnet_naming_rule.interfaces_rule.style = begins_with_i dotnet_naming_rule.interfaces_rule.symbols = interfaces_symbols dotnet_naming_rule.method_rule.import_to_resharper = as_predefined dotnet_naming_rule.method_rule.severity = none dotnet_naming_rule.method_rule.style = pascal_case dotnet_naming_rule.method_rule.symbols = method_symbols dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined dotnet_naming_rule.private_constants_rule.severity = none dotnet_naming_rule.private_constants_rule.style = pascal_case dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols dotnet_naming_rule.private_instance_fields_rule.import_to_resharper = as_predefined dotnet_naming_rule.private_instance_fields_rule.severity = none dotnet_naming_rule.private_instance_fields_rule.style = lower_camel_case_underscore_tolerant_style dotnet_naming_rule.private_instance_fields_rule.symbols = private_instance_fields_symbols dotnet_naming_rule.private_static_fields_rule.import_to_resharper = as_predefined dotnet_naming_rule.private_static_fields_rule.severity = none dotnet_naming_rule.private_static_fields_rule.style = lower_camel_case_style dotnet_naming_rule.private_static_fields_rule.symbols = private_static_fields_symbols dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = as_predefined dotnet_naming_rule.private_static_readonly_rule.severity = none dotnet_naming_rule.private_static_readonly_rule.style = pascal_case dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols dotnet_naming_rule.property_rule.import_to_resharper = as_predefined dotnet_naming_rule.property_rule.severity = none dotnet_naming_rule.property_rule.style = pascal_case dotnet_naming_rule.property_rule.symbols = property_symbols dotnet_naming_rule.types_and_namespaces_rule.import_to_resharper = as_predefined dotnet_naming_rule.types_and_namespaces_rule.severity = none dotnet_naming_rule.types_and_namespaces_rule.style = pascal_case dotnet_naming_rule.types_and_namespaces_rule.symbols = types_and_namespaces_symbols dotnet_naming_style.lower_camel_case_style.capitalization = camel_case dotnet_naming_style.lower_camel_case_style.required_prefix = _ dotnet_naming_style.lower_camel_case_underscore_tolerant_style.capitalization = camel_case dotnet_naming_style.lower_camel_case_underscore_tolerant_style.word_separator = _ dotnet_naming_symbols.event_symbols.applicable_accessibilities = * dotnet_naming_symbols.event_symbols.applicable_kinds = event dotnet_naming_symbols.interfaces_symbols.applicable_accessibilities = * dotnet_naming_symbols.interfaces_symbols.applicable_kinds = interface dotnet_naming_symbols.method_symbols.applicable_accessibilities = * dotnet_naming_symbols.method_symbols.applicable_kinds = method dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field dotnet_naming_symbols.private_constants_symbols.required_modifiers = const dotnet_naming_symbols.private_instance_fields_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_instance_fields_symbols.applicable_kinds = field dotnet_naming_symbols.private_static_fields_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_static_fields_symbols.applicable_kinds = field dotnet_naming_symbols.private_static_fields_symbols.required_modifiers = static dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static, readonly dotnet_naming_symbols.property_symbols.applicable_accessibilities = * dotnet_naming_symbols.property_symbols.applicable_kinds = property dotnet_naming_symbols.types_and_namespaces_symbols.applicable_accessibilities = * dotnet_naming_symbols.types_and_namespaces_symbols.applicable_kinds = namespace, class, struct, enum, delegate # ReSharper properties resharper_braces_for_for = not_required resharper_braces_for_foreach = not_required resharper_braces_for_ifelse = not_required_for_both resharper_braces_for_while = not_required resharper_braces_redundant = true resharper_cpp_insert_final_newline = true resharper_csharp_naming_rule.event = AaBb resharper_csharp_naming_rule.interfaces = I + AaBb resharper_csharp_naming_rule.method = AaBb resharper_csharp_naming_rule.property = AaBb resharper_csharp_naming_rule.types_and_namespaces = AaBb resharper_csharp_wrap_lines = false resharper_keep_existing_declaration_block_arrangement = false resharper_keep_existing_embedded_block_arrangement = false resharper_keep_existing_enum_arrangement = false resharper_show_autodetect_configure_formatting_tip = false resharper_use_heuristics_for_body_style = true # ReSharper inspection severities resharper_arrange_accessor_owner_body_highlighting = suggestion resharper_arrange_redundant_parentheses_highlighting = hint resharper_arrange_this_qualifier_highlighting = hint resharper_arrange_type_member_modifiers_highlighting = hint resharper_arrange_type_modifiers_highlighting = hint resharper_built_in_type_reference_style_for_member_access_highlighting = hint resharper_built_in_type_reference_style_highlighting = hint resharper_inconsistent_naming_highlighting = none resharper_redundant_base_qualifier_highlighting = warning resharper_suggest_var_or_type_built_in_types_highlighting = hint resharper_suggest_var_or_type_elsewhere_highlighting = hint resharper_suggest_var_or_type_simple_types_highlighting = hint resharper_unused_member_global_highlighting = none [*.{appxmanifest,axml,build,c,c++,cc,cginc,compute,config,cp,cpp,csproj,cu,cuh,cxx,dbml,discomap,dtd,fx,fxh,h,hh,hlsl,hlsli,hlslinc,hpp,hxx,inc,inl,ino,ipp,jsproj,lsproj,mpp,mq4,mq5,mqh,njsproj,nuspec,proj,props,proto,resw,resx,StyleCop,targets,tasks,tpp,usf,ush,vbproj,xml,xsd}] indent_style = tab indent_size = tab tab_width = 4 [*.{axaml,cs,paml,vb,xaml,xamlx,xoml}] indent_style = space indent_size = 2 tab_width = 2 [*] # Microsoft .NET properties csharp_indent_braces = false csharp_new_line_before_members_in_object_initializers = false csharp_new_line_before_open_brace = none csharp_preferred_modifier_order = public, protected, override, private, volatile, file, unsafe, internal, static, async, extern, virtual, sealed, abstract, readonly, new, required:suggestion csharp_preserve_single_line_blocks = true csharp_style_namespace_declarations = file_scoped:warning csharp_style_var_elsewhere = true:suggestion csharp_style_var_for_built_in_types = false:suggestion csharp_style_var_when_type_is_apparent = true:suggestion dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:none dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none # ReSharper properties resharper_align_multiline_argument = true resharper_align_multiline_for_stmt = true resharper_align_multiline_parameter = true resharper_align_multiline_statement_conditions = false resharper_align_multline_type_parameter_constrains = true resharper_align_multline_type_parameter_list = true resharper_align_tuple_components = true resharper_allow_comment_after_lbrace = true resharper_arguments_skip_single = true resharper_blank_lines_after_block_statements = 1 resharper_blank_lines_after_multiline_statements = 0 resharper_blank_lines_after_start_comment = 0 resharper_blank_lines_around_auto_property = 0 resharper_blank_lines_around_invocable = 1 resharper_blank_lines_around_property = 1 resharper_blank_lines_around_single_line_type = 0 resharper_blank_lines_before_block_statements = 1 resharper_blank_lines_before_control_transfer_statements = 0 resharper_blank_lines_before_multiline_statements = 0 resharper_braces_for_for = required_for_multiline resharper_braces_for_foreach = required_for_multiline resharper_braces_for_ifelse = not_required resharper_braces_for_while = required_for_multiline resharper_braces_redundant = false resharper_csharp_align_multiline_argument = true resharper_csharp_allow_far_alignment = true resharper_csharp_blank_lines_around_field = 0 resharper_csharp_blank_lines_around_invocable = 1 resharper_csharp_blank_lines_around_region = 0 resharper_csharp_insert_final_newline = false resharper_csharp_keep_blank_lines_in_code = 1 resharper_csharp_keep_blank_lines_in_declarations = 0 resharper_csharp_max_line_length = 120 resharper_csharp_remove_blank_lines_near_braces_in_code = true resharper_csharp_remove_blank_lines_near_braces_in_declarations = true resharper_csharp_wrap_before_first_type_parameter_constraint = true resharper_csharp_wrap_ternary_expr_style = wrap_if_long resharper_default_internal_modifier = implicit resharper_default_value_when_type_not_evident = default_expression resharper_for_simple_types = use_var resharper_indent_pars = outside resharper_indent_preprocessor_region = do_not_change resharper_instance_members_qualify_declared_in = resharper_int_align_switch_expressions = true resharper_int_align_switch_sections = true resharper_keep_existing_attribute_arrangement = true resharper_keep_existing_enum_arrangement = false resharper_max_enum_members_on_line = 1 resharper_max_initializer_elements_on_line = 1 resharper_object_creation_when_type_evident = target_typed resharper_parentheses_non_obvious_operations = none, bitwise_and, bitwise_exclusive_or, bitwise_inclusive_or, bitwise, conditional_and, conditional_or, conditional resharper_parentheses_redundancy_style = remove resharper_parentheses_same_type_operations = true resharper_place_abstract_accessorholder_on_single_line = true resharper_place_accessorholder_attribute_on_same_line = false resharper_place_accessor_attribute_on_same_line = false resharper_place_expr_accessor_on_single_line = true resharper_place_expr_property_on_single_line = true resharper_place_field_attribute_on_same_line = false resharper_place_simple_accessor_on_single_line = true resharper_place_simple_blocks_on_single_line = false resharper_place_simple_embedded_statement_on_same_line = false resharper_place_simple_initializer_on_single_line = true resharper_remove_blank_lines_near_braces_in_code = true resharper_remove_blank_lines_near_braces_in_declarations = true resharper_space_between_attribute_sections = false resharper_space_within_single_line_array_initializer_braces = false resharper_use_roslyn_logic_for_evident_types = true resharper_wrap_after_dot_in_method_calls = true resharper_wrap_for_stmt_header_style = wrap_if_long resharper_wrap_object_and_collection_initializer_style = chop_always dotnet_style_operator_placement_when_wrapping = beginning_of_line end_of_line = crlf dotnet_style_coalesce_expression = true:silent dotnet_style_null_propagation = true:silent dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent dotnet_style_prefer_auto_properties = true:silent csharp_style_prefer_method_group_conversion = true:silent csharp_style_prefer_top_level_statements = true:silent csharp_style_prefer_primary_constructors = true:suggestion dotnet_style_object_initializer = true:silent ================================================ FILE: src/.gitattributes ================================================ *.etl filter=lfs diff=lfs merge=lfs -text ================================================ FILE: src/GrpcLib/DebugService.proto ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. syntax = "proto3"; service DebugService { rpc StartSession(StartSessionRequest) returns (StartSessionResult); rpc EndSession(EndSessionRequest) returns (Result); rpc UpdateIR(UpdateIRRequest) returns (Result); rpc MarkElement(MarkElementRequest) returns (Result); rpc SetCurrentElement(SetCurrentElementRequest) returns (Result); rpc ExecuteCommand(ElementCommandRequest) returns (Result); rpc HasActiveBreakpoint(ActiveBreakpointRequest) returns (ActiveBreakpointResult); rpc ClearTemporaryHighlighting(ClearHighlightingRequest) returns (Result); rpc SetSessionState(SessionStateRequest) returns (Result); rpc UpdateCurrentStackFrame(CurrentStackFrameRequest) returns (Result); } enum SessionState { Listening = 0; Paused = 1; } message SessionStateRequest { SessionState state = 1; } enum ClientKind { debugger = 0; runtime = 1; } message StartSessionRequest { ClientKind kind = 1; int64 processId = 2; int64 processArgs = 3; } message StartSessionResult { int32 errorCode = 1; string errorMessage = 2; int64 sessionId = 3; } message EndSessionRequest { int64 sessionId = 1; } message StackFrame { string file = 1; string function = 2; int32 lineNumber = 3; } message CurrentStackFrameRequest { StackFrame currentFrame = 1; } message UpdateIRRequest { int64 sessionId = 1; string text = 2; } message Result { bool success = 1; int32 errorCode = 2; string errorMessage = 3; } message RGBColor { int32 R = 1; int32 G = 2; int32 B = 3; } enum HighlightingType { temporary = 0; permanent = 1; } message ClearHighlightingRequest { HighlightingType highlighting = 1; } message MarkElementRequest { int64 elementAddress = 1; RGBColor color = 2; string label = 3; HighlightingType highlighting = 4; } enum IRElementKind { Instruction = 0; Operand = 1; Block = 2; User = 3; UserParent = 4; } message SetCurrentElementRequest { int32 elementId = 1; int64 elementAddress = 2; IRElementKind elementKind = 3; string label = 4; } enum ElementCommand { GoToDefinition = 0; MarkBlock = 1; ShowUses = 2; MarkUses = 3; ShowReferences = 4; MarkReferences = 5; MarkExpression = 6; ShowExpression = 7; ClearMarker = 8; } message ElementCommandRequest { ElementCommand command = 1; int64 elementAddress = 2; string label = 3; HighlightingType highlighting = 4; StackFrame stackFrame = 5; } message ActiveBreakpointRequest { int64 elementAddress = 1; } message ActiveBreakpointResult { bool success = 1; int32 errorCode = 2; string errorMessage = 3; bool hasBreakpoint = 4; } ================================================ FILE: src/GrpcLib/GrpcLib.csproj ================================================  netstandard2.1 all runtime; build; native; contentfiles; analyzers; buildtransitive ================================================ FILE: src/ManagedProfiler/CLRDataTarget.h ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef min #undef max class CLRDataTarget : public ICLRDataTarget { public: HANDLE process_; CLRDataTarget() { process_ = GetCurrentProcess(); } virtual HRESULT STDMETHODCALLTYPE QueryInterface(THIS_ IN REFIID InterfaceId, OUT PVOID* Interface) { if (InterfaceId == IID_IUnknown || InterfaceId == IID_ICLRDataTarget) { *Interface = (ICLRDataTarget*)this; // No need to refcount as this class is contained. return S_OK; } else { *Interface = nullptr; return E_NOINTERFACE; } } virtual STDMETHODIMP_(ULONG) AddRef(THIS) { return 1; } virtual STDMETHODIMP_(ULONG) Release(THIS) { return 0; } virtual HRESULT STDMETHODCALLTYPE GetMachineType( /* [out] */ ULONG32* machineType) { *machineType = IMAGE_FILE_MACHINE_AMD64; return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetPointerSize( /* [out] */ ULONG32* pointerSize) { *pointerSize = 8; return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetImageBase( /* [string][in] */ LPCWSTR imagePath, /* [out] */ CLRDATA_ADDRESS* baseAddress) { *baseAddress = (CLRDATA_ADDRESS)GetModuleBaseAddress(GetCurrentProcessId(), imagePath); return S_OK; } virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ BYTE* buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32* bytesRead) { SIZE_T read; ReadProcessMemory(process_, (LPCVOID)address, buffer, bytesRequested, &read); *bytesRead = (ULONG32)read; return S_OK; } virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ BYTE* buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32* bytesWritten) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetTLSValue( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS* value) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE SetTLSValue( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( /* [out] */ ULONG32* threadID) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE GetPlatform( /* [out] */ CorDebugPlatform* pTargetPlatform) { // CORDB_PLATFORM_WINDOWS_AMD64 // ORDB_PLATFORM_WINDOWS_ARM64 *pTargetPlatform = CORDB_PLATFORM_WINDOWS_AMD64; return S_OK; } virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE* pContext) { CorDebugPlatform platform; GetPlatform(&platform); HRESULT result = E_FAIL; HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, false, threadID); if (hThread) { if (platform == CORDB_PLATFORM_WINDOWS_X86) { WOW64_CONTEXT context; context.ContextFlags = contextFlags; if (Wow64GetThreadContext(hThread, &context)) { ZeroMemory(pContext, contextSize); CopyMemory(pContext, &context, std::min(contextSize, (ULONG32)sizeof(context))); result = S_OK; } } else if (platform == CORDB_PLATFORM_WINDOWS_AMD64) { CONTEXT context; context.ContextFlags = contextFlags; if (::GetThreadContext(hThread, &context)) { ZeroMemory(pContext, contextSize); CopyMemory(pContext, &context, std::min(contextSize, (ULONG32)sizeof(context))); result = S_OK; } } CloseHandle(hThread); } return result; } virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE* context) { return E_NOTIMPL; } virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE* inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE* outBuffer) { return E_NOTIMPL; } static uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName) { uintptr_t modBaseAddr = 0; HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId); if (hSnap != INVALID_HANDLE_VALUE) { MODULEENTRY32 modEntry; modEntry.dwSize = sizeof(modEntry); if (Module32First(hSnap, &modEntry)) { do { if (!_wcsicmp(modEntry.szModule, modName)) { modBaseAddr = (uintptr_t)modEntry.modBaseAddr; break; } } while (Module32Next(hSnap, &modEntry)); } } CloseHandle(hSnap); return modBaseAddr; } static std::wstring GetModulePath(DWORD procId, const wchar_t* modName) { uintptr_t modBaseAddr = 0; HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId); if (hSnap != INVALID_HANDLE_VALUE) { MODULEENTRY32 modEntry; modEntry.dwSize = sizeof(modEntry); if (Module32First(hSnap, &modEntry)) { do { if (!_wcsicmp(modEntry.szModule, modName)) { return modEntry.szExePath; } } while (Module32Next(hSnap, &modEntry)); } } CloseHandle(hSnap); return L""; } static std::wstring GetDirectory(const std::wstring& path) { size_t found = path.find_last_of(L"/\\"); return (path.substr(0, found)); } static std::wstring FindDacBinary(ICorProfilerInfo8* _info, int machineType) { USHORT pClrInstanceId; COR_PRF_RUNTIME_TYPE pRuntimeType; USHORT pMajorVersion; USHORT pMinorVersion; USHORT pBuildNumber; USHORT pQFEVersion; WCHAR verstr[100]; ULONG dummy; _info->GetRuntimeInformation(&pClrInstanceId, &pRuntimeType, &pMajorVersion, &pMinorVersion, &pBuildNumber, &pQFEVersion, 100, &dummy, verstr); static const wchar_t* DesktopCLRModule = L"clr.dll"; static const wchar_t* CoreCLRModule = L"coreclr.dll"; static const wchar_t* DesktopDacModule = L"mscordacwks.dll"; static const wchar_t* CoreDacModule = L"mscordaccore.dll"; const wchar_t* clrModule; const wchar_t* dacModule; if (pRuntimeType == COR_PRF_CORE_CLR) { clrModule = CoreCLRModule; dacModule = CoreDacModule; } else { clrModule = DesktopCLRModule; dacModule = DesktopDacModule; } auto clrPath = GetModulePath(GetCurrentProcessId(), clrModule); auto clrDir = std::filesystem::path(clrPath).parent_path(); auto dacPath = clrDir / std::filesystem::path(dacModule); if (std::filesystem::exists(dacPath)) { return dacPath.wstring(); } return L""; } }; ================================================ FILE: src/ManagedProfiler/CapstoneWrappers.h ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #pragma once #include #include // Minimal C++ wrappers over the Capstone C API functions. class CapstoneHandle : public std::shared_ptr { public: CapstoneHandle() : std::shared_ptr(&handle_, cs_close) {} private: csh handle_; }; class InstructionHolder { public: InstructionHolder(CapstoneHandle handle, cs_insn* instr) : handle_(handle), instr_(instr) {} cs_insn* operator->() { return instr_; } private: CapstoneHandle handle_; cs_insn* instr_; }; class InstructionListHolder { public: size_t Size; const void* Address; size_t Count; InstructionListHolder(CapstoneHandle& handle, const void* address, size_t size, size_t startAddress) : handle_(handle), Address(address), Size(size), instrs_(nullptr) { Count = cs_disasm(*handle_.get(), static_cast(address), size, startAddress, 0, &instrs_); } ~InstructionListHolder() { if (instrs_) { cs_free(instrs_, Count); } } InstructionHolder Instruction(size_t index) { return *new InstructionHolder(handle_, instrs_ + index); } private: cs_insn* instrs_; CapstoneHandle handle_; }; class CapstoneDisasm { public: CapstoneDisasm(cs_arch arch, unsigned int mode) { cs_open(arch, (cs_mode)mode, handle_.get()); } InstructionListHolder* Disassemble(const void* code, size_t size, size_t startAddress = 0) { return new InstructionListHolder(handle_, code, size, startAddress); } bool SetSyntax(cs_opt_value syntax) { return !cs_option(*handle_.get(), cs_opt_type::CS_OPT_SYNTAX, syntax); } bool SetDetail(cs_opt_value detailedInfo) { return !cs_option(*handle_.get(), cs_opt_type::CS_OPT_DETAIL, detailedInfo); } private: CapstoneHandle handle_; }; ================================================ FILE: src/ManagedProfiler/Common.h ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #pragma once #include #include #ifdef _WINDOWS #include #else typedef int32_t HRESULT; struct CAtlException { HRESULT HResult; CAtlException(HRESULT hr) : HResult(hr) {} }; #define AtlThrow(hr) throw CAtlException(hr) #if defined(_DEBUG) && !defined(ATLASSERT) #define ATLASSERT(expr) _ASSERTE(expr) #endif // ATLASSERT #include #endif ================================================ FILE: src/ManagedProfiler/CoreProfiler.cpp ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include "CoreProfiler.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "CLRDataTarget.h" static const wchar_t* ProfilerPipeName = L"\\\\.\\pipe\\PEXProfilerPipe"; CComPtr dac_; std::unordered_set recordedAddrs_; std::mutex lock_; bool sessionEnded_; HRESULT __stdcall CoreProfiler::QueryInterface(REFIID riid, void** ppvObject) { Log(L"PEX: QueryInterface"); if (ppvObject == nullptr) return E_POINTER; if (riid == __uuidof(IUnknown) || riid == __uuidof(ICorProfilerCallback) || riid == __uuidof(ICorProfilerCallback2) || riid == __uuidof(ICorProfilerCallback3) || riid == __uuidof(ICorProfilerCallback4) || riid == __uuidof(ICorProfilerCallback5) || riid == __uuidof(ICorProfilerCallback6) || riid == __uuidof(ICorProfilerCallback7) || riid == __uuidof(ICorProfilerCallback8) || riid == __uuidof(ICorProfilerCallback9) || riid == __uuidof(ICorProfilerCallback10)) { AddRef(); *ppvObject = static_cast(this); return S_OK; } return E_NOINTERFACE; } ULONG __stdcall CoreProfiler::AddRef(void) { return ++refCount_; } ULONG __stdcall CoreProfiler::Release(void) { auto count = --refCount_; if (count == 0) delete this; return count; } int64_t GetMethodHandleForIP(uint64_t ip) { uint64_t md = 0; if (FAILED(dac_->GetMethodDescPtrFromIP(ip, &md)) || md == 0) { DacpCodeHeaderData headerData; if (FAILED(dac_->GetCodeHeaderData(ip, &headerData))) { return 0; } md = headerData.MethodDescPtr; } return md; } void FindRuntimeArchitecture() { HRESULT hr; ICLRMetaHost* metaHost = nullptr; if ((hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, (LPVOID*)&metaHost)) != S_OK) { return; } CComPtr runtime; if ((hr = metaHost->EnumerateInstalledRuntimes(&runtime)) != S_OK) { return; } auto frameworkName = (LPWSTR)LocalAlloc(LPTR, 2048); IUnknown* enumRuntime; while (runtime->Next(1, &enumRuntime, 0) == S_OK) { CComPtr runtimeInfo; if (enumRuntime->QueryInterface(&runtimeInfo) == S_OK) { if (runtimeInfo != nullptr) { DWORD bytes; runtimeInfo->GetVersionString(frameworkName, &bytes); } } } } bool IsWindowsVersionOrGreater(WORD wMajorVersion, WORD wMinorVersion = 0, WORD wBuildNumber = 0) { OSVERSIONINFOEXW osvi = {}; osvi.dwOSVersionInfoSize = sizeof(osvi); auto dwlConditionMask = VerSetConditionMask( VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL), VER_MINORVERSION, VER_GREATER_EQUAL); if (wBuildNumber != 0) { VerSetConditionMask(dwlConditionMask, VER_BUILDNUMBER, VER_GREATER_EQUAL); } osvi.dwMajorVersion = wMajorVersion; osvi.dwMinorVersion = wMinorVersion; osvi.wServicePackMajor = wBuildNumber; return VerifyVersionInfoW( &osvi, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR, dwlConditionMask) != FALSE; } bool TryGetWow64(HANDLE proc, bool& result) { if (IsWindowsVersionOrGreater(5, 1)) { BOOL value; return IsWow64Process(proc, &value); } return false; } bool TryGetWow64_2(HANDLE proc, USHORT& processMachine, USHORT& nativeMachine) { if (IsWindowsVersionOrGreater(11) || IsWindowsVersionOrGreater(10, 0, 10586)) { return IsWow64Process2(proc, &processMachine, &nativeMachine); } return false; } USHORT GetMachineType() { SYSTEM_INFO sysInfo; GetSystemInfo(&sysInfo); switch (sysInfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_AMD64: return IMAGE_FILE_MACHINE_AMD64; case PROCESSOR_ARCHITECTURE_ARM: return IMAGE_FILE_MACHINE_ARM; case PROCESSOR_ARCHITECTURE_ARM64: return IMAGE_FILE_MACHINE_ARM64; default: return IMAGE_FILE_MACHINE_I386; } } USHORT GetTargetMachine() { auto handle = GetCurrentProcess(); USHORT processMachine = IMAGE_FILE_MACHINE_UNKNOWN; USHORT nativeMachine = IMAGE_FILE_MACHINE_UNKNOWN; USHORT targetMachine = IMAGE_FILE_MACHINE_UNKNOWN; if (TryGetWow64_2(handle, processMachine, nativeMachine)) { targetMachine = processMachine != IMAGE_FILE_MACHINE_UNKNOWN ? processMachine : nativeMachine; } else { bool isWow64 = false; TryGetWow64(handle, isWow64); targetMachine = isWow64 ? IMAGE_FILE_MACHINE_I386 : GetMachineType(); } return targetMachine; } HRESULT CoreProfiler::Initialize(IUnknown* pICorProfilerInfoUnk) { Log("PEX: Initialize"); pICorProfilerInfoUnk->QueryInterface(&profilerInfo_); profilerInfo_->SetEventMask2( // COR_PRF_MONITOR_MODULE_LOADS | // COR_PRF_MONITOR_ASSEMBLY_LOADS | // COR_PRF_MONITOR_GC | // COR_PRF_MONITOR_CLASS_LOADS | // COR_PRF_MONITOR_THREADS | // COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_MONITOR_JIT_COMPILATION, COR_PRF_HIGH_MONITOR_EVENT_PIPE); /*while (!::IsDebuggerPresent()) { Log(L"PEX: waiting"); ::Sleep(1000); }*/ sessionEnded_.store(false); recordedAddrs_.clear(); machineType_ = GetTargetMachine(); processId_ = GetCurrentProcessId(); pipeClient_ = new NamedPipeClient(); if (!pipeClient_->Initialize(ProfilerPipeName)) { Log("PEX: Failed to connect to pipe\n"); return S_OK; } Log("PEX: Connected to pipe for proc %d\n", processId_); pipeClientThread_ = new std::thread([this]() { Log("PEX: Started pipe thread\n"); bool canceled = false; pipeClient_->ReceiveMessages( [&](PipeMessageHeader header, std::shared_ptr messageBody) { Log("PEX: Message %d, size %d\n", header.Kind, header.Size); switch (header.Kind) { case PipeMessageKind::RequestFunctionCode: { auto request = (RequestFunctionCodeMessage*)messageBody.get(); Log("PEX: Request %lld id %lld\n", request->Address, request->FunctionId); if (request->ProcessId == processId_) { SendRequestedFunctionCode(*request); } break; } case PipeMessageKind::EndSession: { sessionEnded_.store(true); pipeClient_->Disconnect(); Log("PEX: Detaching profiler for proc %d\n", processId_); /*if (FAILED(profilerInfo_->RequestProfilerDetach(10000))) { Log("PEX: Failed to detach proc %d\n", processId_); } else { Log("PEX: Profiler detached for proc %d\n", processId_); }*/ return; // Exit thread. } } }, canceled); Log(">PEX: Stop pipe thread\n"); }); // Load DAC, used mostly to get JIT helper function names. auto dacPath = CLRDataTarget::FindDacBinary(profilerInfo_, machineType_); auto dacModule = LoadLibrary(dacPath.c_str()); if (dacModule) { auto createProc = GetProcAddress(dacModule, "CLRDataCreateInstance"); auto createFunc = (PFN_CLRDataCreateInstance)createProc; auto clrDataTarget = new CLRDataTarget(); IXCLRDataProcess* dataProc; auto result = createFunc(__uuidof(IXCLRDataProcess), clrDataTarget, (void**)&dataProc); if (SUCCEEDED(result)) { auto result = dataProc->QueryInterface(&dac_); if (SUCCEEDED(result)) { Log("PEX: DAC initialized"); } else { Log("PEX: DAC initialization failed: %d", result); } } } return S_OK; } bool CoreProfiler::SendRequestedFunctionCode( RequestFunctionCodeMessage& request) { if (sessionEnded_.load()) { return true; } Log("PEX: SendRequestedFunctionCode: %s", GetMethodName(request.FunctionId).c_str()); ModuleID module; mdToken token; mdTypeDef type; ClassID classId; if (FAILED(profilerInfo_->GetFunctionInfo(request.FunctionId, &classId, &module, &token))) { Log("PEX: Failed GetFunctionInfo\n"); return false; } ULONG rejitCount; if (FAILED(profilerInfo_->GetReJITIDs(request.FunctionId, 0, &rejitCount, nullptr))) { Log("PEX: Failed GetReJITIDs\n"); return false; } std::vector rejitIds(rejitCount); //? TODO: Use pre-allocated array if (FAILED(profilerInfo_->GetReJITIDs(request.FunctionId, rejitCount, &rejitCount, rejitIds.data()))) { Log("PEX: Failed GetReJITIDs\n"); return false; } for (auto&& rejit : rejitIds) { if (rejit != request.ReJITId) { continue; } // Log("PEX: Handle RejitID %d\n", rejit); ULONG32 addrs = 0; profilerInfo_->GetNativeCodeStartAddresses(request.FunctionId, rejit, 0, &addrs, nullptr); std::vector addr(addrs); profilerInfo_->GetNativeCodeStartAddresses(request.FunctionId, rejit, addrs, &addrs, addr.data()); for (int rejit = 0; rejit < addrs; rejit++) { ULONG32 cCodeInfos2; profilerInfo_->GetCodeInfo4(addr[rejit], 0, &cCodeInfos2, nullptr); std::vector codeInfos2(cCodeInfos2); profilerInfo_->GetCodeInfo4(addr[rejit], cCodeInfos2, &cCodeInfos2, codeInfos2.data()); for (auto&& codeInfo : codeInfos2) { //? TODO: Lock could be moved down if R/W //? also not needed after adding std::lock_guard lock(lock_); if (recordedAddrs_.find(codeInfo.startAddress) != recordedAddrs_.end()) { continue; } recordedAddrs_.insert(codeInfo.startAddress); SendLoadedFunctionCode(request.FunctionId, codeInfo.startAddress, rejit, (uint32_t)codeInfo.size, (char*)codeInfo.startAddress); SendCallTargets(request.FunctionId, rejit, (uint32_t)codeInfo.size, (char*)codeInfo.startAddress); } } } return true; } bool CoreProfiler::SendLoadedFunctionCode(uint64_t funcId, uint64_t address, uint32_t rejitId, uint32_t codeSize, char* codeByes) { if (pipeClient_ != nullptr) { Log("PEX: Sending code for funcId %llu, IP %llu, code size %d\n", funcId, address, codeSize); SendFunctionCode(*pipeClient_, funcId, address, rejitId, processId_, codeSize, codeByes); Log("PEX: Sent code for funcId %llu, IP %llu, code size %d\n", funcId, address, codeSize); } return true; } HRESULT CoreProfiler::Shutdown() { Log("PEX: Shutdown"); profilerInfo_.Release(); return S_OK; } HRESULT CoreProfiler::AppDomainCreationStarted(AppDomainID appDomainId) { return S_OK; } HRESULT CoreProfiler::AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::AppDomainShutdownStarted(AppDomainID appDomainId) { return S_OK; } HRESULT CoreProfiler::AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::AssemblyLoadStarted(AssemblyID assemblyId) { return S_OK; } HRESULT CoreProfiler::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) { WCHAR name[512]; ULONG size; AppDomainID ad; return S_OK; } HRESULT CoreProfiler::AssemblyUnloadStarted(AssemblyID assemblyId) { return S_OK; } HRESULT CoreProfiler::AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::ModuleLoadStarted(ModuleID moduleId) { return S_OK; } HRESULT CoreProfiler::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::ModuleUnloadStarted(ModuleID moduleId) { return S_OK; } HRESULT CoreProfiler::ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) { return S_OK; } HRESULT CoreProfiler::ClassLoadStarted(ClassID classId) { return S_OK; } HRESULT CoreProfiler::ClassLoadFinished(ClassID classId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::ClassUnloadStarted(ClassID classId) { return S_OK; } HRESULT CoreProfiler::ClassUnloadFinished(ClassID classId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::FunctionUnloadStarted(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock) { // Logger::Debug("JIT compilation started: %s", // GetMethodName(functionId).c_str()); return S_OK; } HRESULT CoreProfiler::JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { Log("PEX: JITCompilationFinished: %s", GetMethodName(functionId).c_str()); if (fIsSafeToBlock) { profilerInfo_->SuspendRuntime(); } HandleLoadedFunction(functionId); if (fIsSafeToBlock) { profilerInfo_->ResumeRuntime(); } return S_OK; } bool CoreProfiler::SendCallTargetName(uint64_t ip, uint64_t funcId, uint32_t rejitId) { auto md = GetMethodHandleForIP(ip); if (md != 0) { unsigned needed; if (SUCCEEDED(dac_->GetMethodDescName(md, 0, nullptr, &needed))) { auto buffer = std::make_unique(needed - 1, 0); if (SUCCEEDED(dac_->GetMethodDescName( md, needed, (wchar_t*)buffer->c_str(), &needed))) { //? Hacky conversion to UTF8. auto result = std::make_unique(needed - 1, 0); for (size_t i = 0; i < needed; i++) { (*result)[i] = (char)(*buffer)[i]; } SendFunctionCallTarget(*pipeClient_, funcId, ip, rejitId, processId_, result->size() + 1, result->c_str()); } } } else { unsigned needed; if (SUCCEEDED(dac_->GetJitHelperFunctionName(ip, 0, nullptr, &needed))) { char buffer[1024]; if (SUCCEEDED( dac_->GetJitHelperFunctionName(ip, needed, buffer, &needed))) { SendFunctionCallTarget(*pipeClient_, funcId, ip, rejitId, processId_, needed, buffer); } } } return true; } bool CoreProfiler::HandleLoadedFunction(uint64_t functionId) { if (sessionEnded_.load()) { return true; } Log("PEX: JITCompilationFinished: %s", GetMethodName(functionId).c_str()); ModuleID module; mdToken token; mdTypeDef type; ClassID classId; if (FAILED(profilerInfo_->GetFunctionInfo(functionId, &classId, &module, &token))) { Log("PEX: Failed GetFunctionInfo\n"); return false; } ULONG rejitCount; if (FAILED(profilerInfo_->GetReJITIDs(functionId, 0, &rejitCount, nullptr))) { Log("PEX: Failed GetReJITIDs\n"); return false; } std::vector rejitIds(rejitCount); //? TODO: Use pre-allocated array if (FAILED(profilerInfo_->GetReJITIDs(functionId, rejitCount, &rejitCount, rejitIds.data()))) { Log("PEX: Failed GetReJITIDs\n"); return false; } for (auto&& rejit : rejitIds) { ULONG32 addrs = 0; profilerInfo_->GetNativeCodeStartAddresses(functionId, rejit, 0, &addrs, nullptr); std::vector addr(addrs); profilerInfo_->GetNativeCodeStartAddresses(functionId, rejit, addrs, &addrs, addr.data()); for (int rejit = 0; rejit < addrs; rejit++) { ULONG32 cCodeInfos2; profilerInfo_->GetCodeInfo4(addr[rejit], 0, &cCodeInfos2, nullptr); std::vector codeInfos2(cCodeInfos2); profilerInfo_->GetCodeInfo4(addr[rejit], cCodeInfos2, &cCodeInfos2, codeInfos2.data()); for (auto&& codeInfo : codeInfos2) { //? TODO: Lock could be moved down if R/W //? also not needed after adding std::lock_guard lock(lock_); if (recordedAddrs_.find(codeInfo.startAddress) != recordedAddrs_.end()) { continue; } recordedAddrs_.insert(codeInfo.startAddress); SendLoadedFunctionCode(functionId, codeInfo.startAddress, rejit, (uint32_t)codeInfo.size, (char*)codeInfo.startAddress); SendCallTargets(functionId, rejit, (uint32_t)codeInfo.size, (char*)codeInfo.startAddress); } } } return true; } bool CoreProfiler::SendCallTargets(uint64_t funcId, uint32_t rejitId, uint32_t codeSize, char* codeBytes) { if (sessionEnded_.load()) { return true; } __try { switch (machineType_) { case IMAGE_FILE_MACHINE_AMD64: { CollectCallTargets(true, funcId, rejitId, codeBytes, codeSize); break; } case IMAGE_FILE_MACHINE_ARM64: { CollectCallTargetsArm64(funcId, rejitId, codeBytes, codeSize); break; } case IMAGE_FILE_MACHINE_I386: { CollectCallTargets(false, funcId, rejitId, codeBytes, codeSize); break; } } } __except (EXCEPTION_EXECUTE_HANDLER) { // Log("Exception disassembling: %llx, size %d\n", codeInfo.startAddress, // codeSize); return false; } return true; } HRESULT CoreProfiler::JITCachedFunctionSearchStarted( FunctionID functionId, BOOL* pbUseCachedFunction) { return S_OK; } HRESULT CoreProfiler::JITCachedFunctionSearchFinished( FunctionID functionId, COR_PRF_JIT_CACHE result) { return S_OK; } HRESULT CoreProfiler::JITFunctionPitched(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::JITInlining(FunctionID callerId, FunctionID calleeId, BOOL* pfShouldInline) { return S_OK; } HRESULT CoreProfiler::ThreadCreated(ThreadID threadId) { return S_OK; } HRESULT CoreProfiler::ThreadDestroyed(ThreadID threadId) { return S_OK; } HRESULT CoreProfiler::ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId) { return S_OK; } HRESULT CoreProfiler::RemotingClientInvocationStarted() { return S_OK; } HRESULT CoreProfiler::RemotingClientSendingMessage(GUID* pCookie, BOOL fIsAsync) { return S_OK; } HRESULT CoreProfiler::RemotingClientReceivingReply(GUID* pCookie, BOOL fIsAsync) { return S_OK; } HRESULT CoreProfiler::RemotingClientInvocationFinished() { return S_OK; } HRESULT CoreProfiler::RemotingServerReceivingMessage(GUID* pCookie, BOOL fIsAsync) { return S_OK; } HRESULT CoreProfiler::RemotingServerInvocationStarted() { return S_OK; } HRESULT CoreProfiler::RemotingServerInvocationReturned() { return S_OK; } HRESULT CoreProfiler::RemotingServerSendingReply(GUID* pCookie, BOOL fIsAsync) { return S_OK; } HRESULT CoreProfiler::UnmanagedToManagedTransition( FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { return S_OK; } HRESULT CoreProfiler::ManagedToUnmanagedTransition( FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { return S_OK; } HRESULT CoreProfiler::RuntimeSuspendStarted( COR_PRF_SUSPEND_REASON suspendReason) { return S_OK; } HRESULT CoreProfiler::RuntimeSuspendFinished() { return S_OK; } HRESULT CoreProfiler::RuntimeSuspendAborted() { return S_OK; } HRESULT CoreProfiler::RuntimeResumeStarted() { return S_OK; } HRESULT CoreProfiler::RuntimeResumeFinished() { return S_OK; } HRESULT CoreProfiler::RuntimeThreadSuspended(ThreadID threadId) { return S_OK; } HRESULT CoreProfiler::RuntimeThreadResumed(ThreadID threadId) { return S_OK; } HRESULT CoreProfiler::MovedReferences(ULONG cMovedObjectIDRanges, ObjectID* oldObjectIDRangeStart, ObjectID* newObjectIDRangeStart, ULONG* cObjectIDRangeLength) { return S_OK; } HRESULT CoreProfiler::ObjectAllocated(ObjectID objectId, ClassID classId) { /*ModuleID module; mdTypeDef type; if (SUCCEEDED(_info->GetClassIDInfo(classId, &module, &type))) { auto name = GetTypeName(type, module); }*/ return S_OK; } HRESULT CoreProfiler::ObjectsAllocatedByClass(ULONG cClassCount, ClassID* classIds, ULONG* cObjects) { return S_OK; } HRESULT CoreProfiler::ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID* objectRefIds) { return S_OK; } HRESULT CoreProfiler::RootReferences(ULONG cRootRefs, ObjectID* rootRefIds) { return S_OK; } HRESULT CoreProfiler::ExceptionThrown(ObjectID thrownObjectId) { return S_OK; } HRESULT CoreProfiler::ExceptionSearchFunctionEnter(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::ExceptionSearchFunctionLeave() { return S_OK; } HRESULT CoreProfiler::ExceptionSearchFilterEnter(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::ExceptionSearchFilterLeave() { return S_OK; } HRESULT CoreProfiler::ExceptionSearchCatcherFound(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::ExceptionOSHandlerEnter(UINT_PTR __unused) { return S_OK; } HRESULT CoreProfiler::ExceptionOSHandlerLeave(UINT_PTR __unused) { return S_OK; } HRESULT CoreProfiler::ExceptionUnwindFunctionEnter(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::ExceptionUnwindFunctionLeave() { return S_OK; } HRESULT CoreProfiler::ExceptionUnwindFinallyEnter(FunctionID functionId) { return S_OK; } HRESULT CoreProfiler::ExceptionUnwindFinallyLeave() { return S_OK; } HRESULT CoreProfiler::ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) { return S_OK; } HRESULT CoreProfiler::ExceptionCatcherLeave() { return S_OK; } HRESULT CoreProfiler::COMClassicVTableCreated(ClassID wrappedClassId, const GUID& implementedIID, void* pVTable, ULONG cSlots) { return S_OK; } HRESULT CoreProfiler::COMClassicVTableDestroyed(ClassID wrappedClassId, const GUID& implementedIID, void* pVTable) { return S_OK; } HRESULT CoreProfiler::ExceptionCLRCatcherFound() { return S_OK; } HRESULT CoreProfiler::ExceptionCLRCatcherExecute() { return S_OK; } HRESULT CoreProfiler::ThreadNameChanged(ThreadID threadId, ULONG cchName, WCHAR* name) { return S_OK; } HRESULT CoreProfiler::GarbageCollectionStarted(int cGenerations, BOOL* generationCollected, COR_PRF_GC_REASON reason) { return S_OK; } HRESULT CoreProfiler::SurvivingReferences(ULONG cSurvivingObjectIDRanges, ObjectID* objectIDRangeStart, ULONG* cObjectIDRangeLength) { return S_OK; } HRESULT CoreProfiler::GarbageCollectionFinished() { return S_OK; } HRESULT CoreProfiler::FinalizeableObjectQueued(DWORD finalizerFlags, ObjectID objectID) { return S_OK; } HRESULT CoreProfiler::RootReferences2(ULONG cRootRefs, ObjectID* rootRefIds, COR_PRF_GC_ROOT_KIND* rootKinds, COR_PRF_GC_ROOT_FLAGS* rootFlags, UINT_PTR* rootIds) { return S_OK; } HRESULT CoreProfiler::HandleCreated(GCHandleID handleId, ObjectID initialObjectId) { return S_OK; } HRESULT CoreProfiler::HandleDestroyed(GCHandleID handleId) { return S_OK; } HRESULT CoreProfiler::InitializeForAttach(IUnknown* pCorProfilerInfoUnk, void* pvClientData, UINT cbClientData) { Log("PEX: InitializeForAttach, data %d\n", cbClientData); return Initialize(pCorProfilerInfoUnk); } HRESULT CoreProfiler::ProfilerAttachComplete() { Log("PEX: ProfilerAttachComplete\n"); return S_OK; } HRESULT CoreProfiler::ProfilerDetachSucceeded() { Log("PEX: ProfilerDetachSucceeded"); return S_OK; } HRESULT CoreProfiler::ReJITCompilationStarted(FunctionID functionId, ReJITID rejitId, BOOL fIsSafeToBlock) { return S_OK; } HRESULT CoreProfiler::GetReJITParameters( ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl* pFunctionControl) { return S_OK; } HRESULT CoreProfiler::ReJITCompilationFinished(FunctionID functionId, ReJITID rejitId, HRESULT hrStatus, BOOL fIsSafeToBlock) { return S_OK; } HRESULT CoreProfiler::ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) { return S_OK; } HRESULT CoreProfiler::MovedReferences2(ULONG cMovedObjectIDRanges, ObjectID* oldObjectIDRangeStart, ObjectID* newObjectIDRangeStart, SIZE_T* cObjectIDRangeLength) { return S_OK; } HRESULT CoreProfiler::SurvivingReferences2(ULONG cSurvivingObjectIDRanges, ObjectID* objectIDRangeStart, SIZE_T* cObjectIDRangeLength) { return S_OK; } HRESULT CoreProfiler::ConditionalWeakTableElementReferences( ULONG cRootRefs, ObjectID* keyRefIds, ObjectID* valueRefIds, GCHandleID* rootIds) { return S_OK; } HRESULT CoreProfiler::GetAssemblyReferences( const WCHAR* wszAssemblyPath, ICorProfilerAssemblyReferenceProvider* pAsmRefProvider) { return S_OK; } HRESULT CoreProfiler::ModuleInMemorySymbolsUpdated(ModuleID moduleId) { return S_OK; } HRESULT CoreProfiler::DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) { return S_OK; } HRESULT CoreProfiler::DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { return S_OK; } HRESULT STDMETHODCALLTYPE CoreProfiler::EventPipeEventDelivered(EVENTPIPE_PROVIDER provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, ThreadID eventThread, ULONG numStackFrames, UINT_PTR stackFrames[]) { return S_OK; } HRESULT CoreProfiler::EventPipeProviderCreated(EVENTPIPE_PROVIDER provider) { Log("PEX: Created provider %llu\n", provider); return S_OK; } std::string UnicodeToAnsi(const WCHAR* str) { #ifdef _WINDOWS std::wstring ws(str); #else std::basic_string ws(str); #endif return std::string(ws.begin(), ws.end()); } std::string CoreProfiler::GetTypeName(mdTypeDef type, ModuleID module) const { CComPtr spMetadata; if (SUCCEEDED(profilerInfo_->GetModuleMetaData( module, ofRead, IID_IMetaDataImport, reinterpret_cast(&spMetadata)))) { WCHAR name[256]; ULONG nameSize = 256; DWORD flags; mdTypeDef baseType; if (SUCCEEDED(spMetadata->GetTypeDefProps(type, name, 256, &nameSize, &flags, &baseType))) { return UnicodeToAnsi(name); } } return ""; } std::string CoreProfiler::GetMethodName(FunctionID function) const { ModuleID module; mdToken token; mdTypeDef type; ClassID classId; if (FAILED( profilerInfo_->GetFunctionInfo(function, &classId, &module, &token))) return ""; CComPtr spMetadata; if (FAILED(profilerInfo_->GetModuleMetaData( module, ofRead, IID_IMetaDataImport, reinterpret_cast(&spMetadata)))) return ""; PCCOR_SIGNATURE sig; ULONG blobSize, size, attributes; WCHAR name[256]; DWORD flags; ULONG codeRva; if (FAILED(spMetadata->GetMethodProps(token, &type, name, 256, &size, &attributes, &sig, &blobSize, &codeRva, &flags))) return ""; return GetTypeName(type, module) + "::" + UnicodeToAnsi(name); } ================================================ FILE: src/ManagedProfiler/CoreProfiler.h ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #pragma once #include #include #include #include #include #include #include #include #include "CapstoneWrappers.h" #include "Common.h" #include "NamedPipeClient.h" #undef min #undef max inline void Log(const std::wstring format, ...) { const int TRACE_BUFFER_SIZE = 4096; wchar_t buffer[TRACE_BUFFER_SIZE]; va_list args; va_start(args, format); _vsnwprintf_s( buffer, TRACE_BUFFER_SIZE - 2, format.c_str(), args); // Truncates if buffer is not big enough. va_end(args); ::OutputDebugStringW(buffer); } #ifdef DEBUG inline void Log(const std::string format, ...) { const int TRACE_BUFFER_SIZE = 4096; char buffer[TRACE_BUFFER_SIZE]; va_list args; va_start(args, format); _vsnprintf_s( buffer, TRACE_BUFFER_SIZE - 2, format.c_str(), args); // Truncates if buffer is not big enough. va_end(args); ::OutputDebugStringA(buffer); } #else #define Log #endif #pragma region ClassInfo struct ClassInfo { ClassInfo(mdTypeDef type, ModuleID module) : Type(type), Module(module) {} bool operator==(const ClassInfo& other) const { return Type == other.Type && Module == other.Module; } mdTypeDef Type; ModuleID Module; }; template <> struct std::hash { size_t operator()(const ClassInfo& ci) const { return ci.Module ^ ci.Type; } }; #pragma endregion class CoreProfiler : public ICorProfilerCallback10 { public: // Inherited via ICorProfilerCallback8 HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override; ULONG __stdcall AddRef(void) override; ULONG __stdcall Release(void) override; HRESULT __stdcall Initialize(IUnknown* pICorProfilerInfoUnk) override; HRESULT __stdcall Shutdown(void) override; HRESULT __stdcall AppDomainCreationStarted(AppDomainID appDomainId) override; HRESULT __stdcall AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) override; HRESULT __stdcall AppDomainShutdownStarted(AppDomainID appDomainId) override; HRESULT __stdcall AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) override; HRESULT __stdcall AssemblyLoadStarted(AssemblyID assemblyId) override; HRESULT __stdcall AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) override; HRESULT __stdcall AssemblyUnloadStarted(AssemblyID assemblyId) override; HRESULT __stdcall AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus) override; HRESULT __stdcall ModuleLoadStarted(ModuleID moduleId) override; HRESULT __stdcall ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) override; HRESULT __stdcall ModuleUnloadStarted(ModuleID moduleId) override; HRESULT __stdcall ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) override; HRESULT __stdcall ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) override; HRESULT __stdcall ClassLoadStarted(ClassID classId) override; HRESULT __stdcall ClassLoadFinished(ClassID classId, HRESULT hrStatus) override; HRESULT __stdcall ClassUnloadStarted(ClassID classId) override; HRESULT __stdcall ClassUnloadFinished(ClassID classId, HRESULT hrStatus) override; HRESULT __stdcall FunctionUnloadStarted(FunctionID functionId) override; HRESULT __stdcall JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock) override; HRESULT __stdcall JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override; HRESULT __stdcall JITCachedFunctionSearchStarted( FunctionID functionId, BOOL* pbUseCachedFunction) override; HRESULT __stdcall JITCachedFunctionSearchFinished( FunctionID functionId, COR_PRF_JIT_CACHE result) override; HRESULT __stdcall JITFunctionPitched(FunctionID functionId) override; HRESULT __stdcall JITInlining(FunctionID callerId, FunctionID calleeId, BOOL* pfShouldInline) override; HRESULT __stdcall ThreadCreated(ThreadID threadId) override; HRESULT __stdcall ThreadDestroyed(ThreadID threadId) override; HRESULT __stdcall ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId) override; HRESULT __stdcall RemotingClientInvocationStarted(void) override; HRESULT __stdcall RemotingClientSendingMessage(GUID* pCookie, BOOL fIsAsync) override; HRESULT __stdcall RemotingClientReceivingReply(GUID* pCookie, BOOL fIsAsync) override; HRESULT __stdcall RemotingClientInvocationFinished(void) override; HRESULT __stdcall RemotingServerReceivingMessage(GUID* pCookie, BOOL fIsAsync) override; HRESULT __stdcall RemotingServerInvocationStarted(void) override; HRESULT __stdcall RemotingServerInvocationReturned(void) override; HRESULT __stdcall RemotingServerSendingReply(GUID* pCookie, BOOL fIsAsync) override; HRESULT __stdcall UnmanagedToManagedTransition( FunctionID functionId, COR_PRF_TRANSITION_REASON reason) override; HRESULT __stdcall ManagedToUnmanagedTransition( FunctionID functionId, COR_PRF_TRANSITION_REASON reason) override; HRESULT __stdcall RuntimeSuspendStarted( COR_PRF_SUSPEND_REASON suspendReason) override; HRESULT __stdcall RuntimeSuspendFinished(void) override; HRESULT __stdcall RuntimeSuspendAborted(void) override; HRESULT __stdcall RuntimeResumeStarted(void) override; HRESULT __stdcall RuntimeResumeFinished(void) override; HRESULT __stdcall RuntimeThreadSuspended(ThreadID threadId) override; HRESULT __stdcall RuntimeThreadResumed(ThreadID threadId) override; HRESULT __stdcall MovedReferences(ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], ObjectID newObjectIDRangeStart[], ULONG cObjectIDRangeLength[]) override; HRESULT __stdcall ObjectAllocated(ObjectID objectId, ClassID classId) override; HRESULT __stdcall ObjectsAllocatedByClass(ULONG cClassCount, ClassID classIds[], ULONG cObjects[]) override; HRESULT __stdcall ObjectReferences(ObjectID objectId, ClassID classId, ULONG cObjectRefs, ObjectID objectRefIds[]) override; HRESULT __stdcall RootReferences(ULONG cRootRefs, ObjectID rootRefIds[]) override; HRESULT __stdcall ExceptionThrown(ObjectID thrownObjectId) override; HRESULT __stdcall ExceptionSearchFunctionEnter( FunctionID functionId) override; HRESULT __stdcall ExceptionSearchFunctionLeave(void) override; HRESULT __stdcall ExceptionSearchFilterEnter(FunctionID functionId) override; HRESULT __stdcall ExceptionSearchFilterLeave(void) override; HRESULT __stdcall ExceptionSearchCatcherFound(FunctionID functionId) override; HRESULT __stdcall ExceptionOSHandlerEnter(UINT_PTR __unused) override; HRESULT __stdcall ExceptionOSHandlerLeave(UINT_PTR __unused) override; HRESULT __stdcall ExceptionUnwindFunctionEnter( FunctionID functionId) override; HRESULT __stdcall ExceptionUnwindFunctionLeave(void) override; HRESULT __stdcall ExceptionUnwindFinallyEnter(FunctionID functionId) override; HRESULT __stdcall ExceptionUnwindFinallyLeave(void) override; HRESULT __stdcall ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) override; HRESULT __stdcall ExceptionCatcherLeave(void) override; HRESULT __stdcall COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void* pVTable, ULONG cSlots) override; HRESULT __stdcall COMClassicVTableDestroyed(ClassID wrappedClassId, REFGUID implementedIID, void* pVTable) override; HRESULT __stdcall ExceptionCLRCatcherFound(void) override; HRESULT __stdcall ExceptionCLRCatcherExecute(void) override; HRESULT __stdcall ThreadNameChanged(ThreadID threadId, ULONG cchName, WCHAR name[]) override; HRESULT __stdcall GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) override; HRESULT __stdcall SurvivingReferences(ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], ULONG cObjectIDRangeLength[]) override; HRESULT __stdcall GarbageCollectionFinished(void) override; HRESULT __stdcall FinalizeableObjectQueued(DWORD finalizerFlags, ObjectID objectID) override; HRESULT __stdcall RootReferences2(ULONG cRootRefs, ObjectID rootRefIds[], COR_PRF_GC_ROOT_KIND rootKinds[], COR_PRF_GC_ROOT_FLAGS rootFlags[], UINT_PTR rootIds[]) override; HRESULT __stdcall HandleCreated(GCHandleID handleId, ObjectID initialObjectId) override; HRESULT __stdcall HandleDestroyed(GCHandleID handleId) override; HRESULT __stdcall InitializeForAttach(IUnknown* pCorProfilerInfoUnk, void* pvClientData, UINT cbClientData) override; HRESULT __stdcall ProfilerAttachComplete(void) override; HRESULT __stdcall ProfilerDetachSucceeded(void) override; HRESULT __stdcall ReJITCompilationStarted(FunctionID functionId, ReJITID rejitId, BOOL fIsSafeToBlock) override; HRESULT __stdcall GetReJITParameters( ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl* pFunctionControl) override; HRESULT __stdcall ReJITCompilationFinished(FunctionID functionId, ReJITID rejitId, HRESULT hrStatus, BOOL fIsSafeToBlock) override; HRESULT __stdcall ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) override; HRESULT __stdcall MovedReferences2(ULONG cMovedObjectIDRanges, ObjectID oldObjectIDRangeStart[], ObjectID newObjectIDRangeStart[], SIZE_T cObjectIDRangeLength[]) override; HRESULT __stdcall SurvivingReferences2( ULONG cSurvivingObjectIDRanges, ObjectID objectIDRangeStart[], SIZE_T cObjectIDRangeLength[]) override; HRESULT __stdcall ConditionalWeakTableElementReferences( ULONG cRootRefs, ObjectID keyRefIds[], ObjectID valueRefIds[], GCHandleID rootIds[]) override; HRESULT __stdcall GetAssemblyReferences( const WCHAR* wszAssemblyPath, ICorProfilerAssemblyReferenceProvider* pAsmRefProvider) override; HRESULT __stdcall ModuleInMemorySymbolsUpdated(ModuleID moduleId) override; HRESULT __stdcall DynamicMethodJITCompilationStarted( FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) override; HRESULT __stdcall DynamicMethodJITCompilationFinished( FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) override; HRESULT STDMETHODCALLTYPE DynamicMethodUnloaded(FunctionID functionId) override { return S_OK; } HRESULT STDMETHODCALLTYPE EventPipeEventDelivered(EVENTPIPE_PROVIDER provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, ThreadID eventThread, ULONG numStackFrames, UINT_PTR stackFrames[]) override; HRESULT STDMETHODCALLTYPE EventPipeProviderCreated(EVENTPIPE_PROVIDER provider) override; private: CComPtr profilerInfo_; std::atomic refCount_{1}; int machineType_; int processId_; NamedPipeClient* pipeClient_; std::thread* pipeClientThread_; std::atomic sessionEnded_; std::string GetTypeName(mdTypeDef type, ModuleID module) const; std::string GetMethodName(FunctionID function) const; bool HandleLoadedFunction(uint64_t functionId); bool SendLoadedFunctionCode(uint64_t funcId, uint64_t address, uint32_t rejitId, uint32_t codeSize, char* codeByes); bool SendCallTargets(uint64_t funcId, uint32_t rejitId, uint32_t codeSize, char* codeByes); bool SendCallTargetName(uint64_t ip, uint64_t funcId, uint32_t rejitId); bool SendRequestedFunctionCode(RequestFunctionCodeMessage& request); void CollectCallTargets(bool is64BitCode, uint64_t funcId, uint32_t rejitId, void* buffer, size_t size) { auto mode = cs_mode::CS_MODE_LITTLE_ENDIAN | (is64BitCode ? cs_mode::CS_MODE_64 : cs_mode::CS_MODE_32); auto dis = CapstoneDisasm(cs_arch::CS_ARCH_X86, mode); dis.SetDetail(cs_opt_value::CS_OPT_ON); dis.SetSyntax(cs_opt_value::CS_OPT_SYNTAX_INTEL); int64_t startRva = (int64_t)buffer; std::unique_ptr instrs( dis.Disassemble(buffer, size, startRva)); if (instrs->Count == 0) { return; } std::unique_ptr> sentTargets; for (size_t i = 0; i < instrs->Count; i++) { auto instr = instrs->Instruction(i); // Log("%s %s\n", instr->mnemonic, instr->op_str); if (!instr->detail) continue; for (int i = 0; i < instr->detail->x86.op_count; i++) { if (instr->detail->x86.operands[i].type == X86_OP_IMM) { auto targetAddr = instr->detail->x86.operands[i].imm; // Sent each unique call target only once. if (sentTargets == nullptr) { sentTargets = std::make_unique>(); } if (sentTargets->find(targetAddr) == sentTargets->end()) { SendCallTargetName(targetAddr, funcId, rejitId); sentTargets->insert(targetAddr); } } } } } void CollectCallTargetsArm64(uint64_t funcId, uint32_t rejitId, void* buffer, size_t size) { auto mode = cs_mode::CS_MODE_THUMB | cs_mode::CS_MODE_LITTLE_ENDIAN; auto dis = CapstoneDisasm(cs_arch::CS_ARCH_AARCH64, mode); dis.SetDetail(cs_opt_value::CS_OPT_ON); dis.SetSyntax(cs_opt_value::CS_OPT_SYNTAX_INTEL); int64_t startRva = (int64_t)buffer; std::unique_ptr instrs( dis.Disassemble(buffer, size, startRva)); if (instrs->Count == 0) { return; } std::unique_ptr> sentTargets; for (size_t i = 0; i < instrs->Count; i++) { auto instr = instrs->Instruction(i); // Log("%s %s\n", instr->mnemonic, instr->op_str); if (!instr->detail) continue; // Sent each unique call target only once. if (sentTargets == nullptr) { sentTargets = std::make_unique>(); } for (int i = 0; i < instr->detail->aarch64.op_count; i++) { if (instr->detail->aarch64.operands[i].type == AArch64_OP_IMM) { auto targetAddr = instr->detail->aarch64.operands[i].imm; if (sentTargets->find(targetAddr) == sentTargets->end()) { SendCallTargetName(targetAddr, funcId, rejitId); sentTargets->insert(targetAddr); } } } } } }; ================================================ FILE: src/ManagedProfiler/CoreProfilerFactory.cpp ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include "Common.h" #include "CoreProfilerFactory.h" #include "CoreProfiler.h" #include HRESULT __stdcall CoreProfilerFactory::QueryInterface(REFIID riid, void** ppvObject) { if (ppvObject == nullptr) return E_POINTER; if (riid == __uuidof(IUnknown) || riid == __uuidof(IClassFactory)) { *ppvObject = static_cast(this); return S_OK; } return E_NOINTERFACE; } ULONG __stdcall CoreProfilerFactory::AddRef(void) { return 2; } ULONG __stdcall CoreProfilerFactory::Release(void) { return 1; } HRESULT __stdcall CoreProfilerFactory::CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject) { auto profiler = new (std::nothrow) CoreProfiler; if (profiler == nullptr) return E_OUTOFMEMORY; auto hr = profiler->QueryInterface(riid, ppvObject); profiler->Release(); return hr; } ================================================ FILE: src/ManagedProfiler/CoreProfilerFactory.h ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #pragma once class CoreProfilerFactory : public IClassFactory { public: // Inherited via IClassFactory HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override; ULONG __stdcall AddRef(void) override; ULONG __stdcall Release(void) override; HRESULT __stdcall CreateInstance(IUnknown* pUnkOuter, REFIID riid, void** ppvObject) override; HRESULT __stdcall LockServer(BOOL fLock) override { return E_NOTIMPL; } }; ================================================ FILE: src/ManagedProfiler/IRExplorerProfiler.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Resource Files ================================================ FILE: src/ManagedProfiler/ManagedProfiler.def ================================================ LIBRARY EXPORTS DllGetClassObject PRIVATE ================================================ FILE: src/ManagedProfiler/ManagedProfiler.vcxproj ================================================ Debug ARM64 Debug Win32 Release ARM64 Release Win32 Debug x64 Release x64 17.0 Win32Proj {08ded710-2048-45c3-90f9-0d585263796d} ManagedProfiler 10.0 DynamicLibrary true v143 Unicode DynamicLibrary false v143 true Unicode DynamicLibrary true v143 Unicode DynamicLibrary true v143 Unicode DynamicLibrary false v143 true Unicode DynamicLibrary false v143 true Unicode $(ProjectDir)\..\external\capstone\include;$(ProjectDir)\external\coreclr\inc;$(ProjectDir)\external\coreclr\pal\prebuilt\inc;$(IncludePath) $(ProjectDir)\..\external\capstone\include;$(ProjectDir)\external\coreclr\inc;$(ProjectDir)\external\coreclr\pal\prebuilt\inc;$(IncludePath) $(ProjectDir)\..\external\capstone\include;$(ProjectDir)\external\coreclr\inc;$(ProjectDir)\external\coreclr\pal\prebuilt\inc;$(IncludePath) $(ProjectDir)\..\external\capstone\include;$(ProjectDir)\external\coreclr\inc;$(ProjectDir)\external\coreclr\pal\prebuilt\inc;$(IncludePath) Level3 true WIN32;_DEBUG;MANAGEDPROFILER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true false Level3 true true true WIN32;NDEBUG;MANAGEDPROFILER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 Windows true true true false Level3 true _DEBUG;MANAGEDPROFILER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 /D_CRT_SECURE_NO_WARNINGS %(AdditionalOptions) Windows true false $(ProjectDir)\..\external\capstone\build_static\Release\;%(AdditionalLibraryDirectories) capstone.lib;corguids.lib;mscoree.lib;%(AdditionalDependencies) Level3 true _DEBUG;MANAGEDPROFILER_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) true NotUsing pch.h stdcpp20 /D_CRT_SECURE_NO_WARNINGS %(AdditionalOptions) Windows true false $(ProjectDir)\..\external\capstone\build_arm64_static\Release\;%(AdditionalLibraryDirectories) capstone.lib;corguids.lib;mscoree.lib;%(AdditionalDependencies) Level3 true true false NDEBUG;MANAGEDPROFILER_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true NotUsing stdcpp20 true MultiThreaded SyncCThrow /D_CRT_SECURE_NO_WARNINGS %(AdditionalOptions) Windows true true true false $(ProjectDir)\..\external\capstone\build_static\Release\;%(AdditionalLibraryDirectories) capstone.lib;corguids.lib;mscoree.lib;%(AdditionalDependencies) ManagedProfiler.def Level3 true true false NDEBUG;MANAGEDPROFILER_EXPORTS;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true NotUsing pch.h false MultiThreaded stdcpp20 /D_CRT_SECURE_NO_WARNINGS %(AdditionalOptions) Windows true true true false $(ProjectDir)\..\external\capstone\build_arm64_static\Release\;%(AdditionalLibraryDirectories) capstone.lib;corguids.lib;mscoree.lib;%(AdditionalDependencies) ManagedProfiler.def ================================================ FILE: src/ManagedProfiler/NamedPipeClient.h ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include #include #include #include #pragma once enum class PipeMessageKind : int32_t { StartSession, EndSession, FunctionCode, FunctionCallTarget, RequestFunctionCode, }; #pragma pack(push, 1) struct PipeMessageHeader { PipeMessageKind Kind; int32_t Size; }; #pragma pack(pop) #pragma pack(push, 1) struct FunctionCodeMessage { int64_t FunctionId; int64_t Address; int32_t ReJITId; int32_t ProcessId; int32_t CodeSize; int8_t CodeBytes[]; }; #pragma pack(pop) #pragma pack(push, 1) struct FunctionCallTargetMessage { int64_t FunctionId; int64_t Address; int32_t ReJITId; int32_t ProcessId; int32_t NameLength; char Name[]; }; #pragma pack(pop) #pragma pack(push, 1) struct RequestFunctionCodeMessage { int64_t FunctionId; int64_t Address; int32_t ReJITId; int32_t ProcessId; }; #pragma pack(pop) class NamedPipeClient { HANDLE handle_; HANDLE readEvent_; HANDLE writeEvent_; std::mutex lock_; public: NamedPipeClient() { handle_ = INVALID_HANDLE_VALUE; } ~NamedPipeClient() { Disconnect(); } bool Initialize(const wchar_t* pipeName) { readEvent_ = CreateEvent(nullptr, TRUE, TRUE, nullptr); writeEvent_ = CreateEvent(nullptr, TRUE, TRUE, nullptr); handle_ = CreateFile(pipeName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); return handle_ != INVALID_HANDLE_VALUE && readEvent_ != INVALID_HANDLE_VALUE && writeEvent_ != INVALID_HANDLE_VALUE; } void Disconnect() { if (handle_ != INVALID_HANDLE_VALUE) { CloseHandle(handle_); CloseHandle(readEvent_); CloseHandle(writeEvent_); handle_ = readEvent_ = writeEvent_ = INVALID_HANDLE_VALUE; } } bool ReadMessage(PipeMessageHeader* header, std::shared_ptr& messageBody) { if (!ReadOverlapped(sizeof(PipeMessageHeader), header)) { return false; } if (header->Size > sizeof(PipeMessageHeader)) { int messageSize = header->Size - sizeof(PipeMessageHeader); messageBody.reset(new char[messageSize]); if (!ReadOverlapped(messageSize, messageBody.get())) { return false; } } return true; } template void ReceiveMessages(Action handleMessage, bool& canceled) { while (!canceled) { PipeMessageHeader header; std::shared_ptr messageBody; if (!ReadMessage(&header, messageBody)) { break; } // printf("Received %d, size %d\n", header.Kind, header.Size); handleMessage(header, messageBody); } } bool SendMessage(PipeMessageKind kind) { return WriteMessageHeader(kind, 0); } template bool SendMessage(PipeMessageKind kind, const T& data) { std::unique_lock lock(lock_); if (!WriteMessageHeader(kind, sizeof(T))) return false; return WriteOverlapped(data, sizeof(T)); } bool SendMessage(PipeMessageKind kind, void* data, size_t dataSize) { std::unique_lock lock(lock_); if (!WriteMessageHeader(kind, dataSize)) return false; return WriteOverlapped(data, dataSize); } bool WriteMessageHeader(PipeMessageKind kind, size_t dataSize) { PipeMessageHeader header; header.Kind = kind; header.Size = (int32_t)dataSize + sizeof(header); return WriteOverlapped(&header, sizeof(header)); } bool WriteOverlapped(void* data, size_t dataSize) { DWORD bytesWritten; OVERLAPPED overlapped; overlapped.hEvent = writeEvent_; overlapped.Offset = 0; overlapped.OffsetHigh = 0; if (!WriteFile(handle_, data, dataSize, &bytesWritten, &overlapped)) { if (GetLastError() != ERROR_IO_PENDING) { return false; } WaitForSingleObject(writeEvent_, INFINITE); if (!GetOverlappedResult(handle_, &overlapped, &bytesWritten, false)) { return false; } } return bytesWritten == dataSize; } bool ReadOverlapped(size_t dataSize, void* dataOut) { DWORD bytesRead; OVERLAPPED overlapped; overlapped.hEvent = readEvent_; overlapped.Offset = 0; overlapped.OffsetHigh = 0; if (!ReadFile(handle_, dataOut, dataSize, &bytesRead, &overlapped)) { if (GetLastError() != ERROR_IO_PENDING) { return false; } WaitForSingleObject(readEvent_, INFINITE); if (!GetOverlappedResult(handle_, &overlapped, &bytesRead, false)) { return false; } } return bytesRead == dataSize; } }; static bool SendFunctionCode(NamedPipeClient& client, int64_t functionId, int64_t address, int32_t reJITId, int32_t processId, int32_t codeSize, void* codeBytes) { const size_t BUFFER_SIZE = 4 * 1024; char stackBuffer[BUFFER_SIZE]; std::unique_ptr dynamicBuffer; FunctionCodeMessage* message; size_t messageSize = sizeof(FunctionCodeMessage) + codeSize; if (messageSize < BUFFER_SIZE) { message = (FunctionCodeMessage*)stackBuffer; } else { dynamicBuffer = std::make_unique(sizeof(FunctionCodeMessage) + codeSize); message = (FunctionCodeMessage*)dynamicBuffer.get(); } message->FunctionId = functionId; message->Address = address; message->ReJITId = reJITId; message->ProcessId = processId; message->CodeSize = codeSize; memcpy(message->CodeBytes, codeBytes, codeSize); return client.SendMessage(PipeMessageKind::FunctionCode, message, messageSize); } static bool SendFunctionCallTarget(NamedPipeClient& client, int64_t functionId, int64_t address, int32_t reJITId, int32_t processId, int32_t nameLength, const char* name) { const size_t BUFFER_SIZE = 4 * 1024; char stackBuffer[BUFFER_SIZE]; std::unique_ptr dynamicBuffer; FunctionCallTargetMessage* message; size_t messageSize = sizeof(FunctionCallTargetMessage) + nameLength; if (messageSize < BUFFER_SIZE) { message = (FunctionCallTargetMessage*)stackBuffer; } else { dynamicBuffer = std::make_unique(sizeof(FunctionCallTargetMessage) + nameLength); message = (FunctionCallTargetMessage*)dynamicBuffer.get(); } message->FunctionId = functionId; message->Address = address; message->ReJITId = reJITId; message->ProcessId = processId; message->NameLength = nameLength; memcpy(message->Name, name, nameLength); return client.SendMessage(PipeMessageKind::FunctionCallTarget, message, messageSize); } static bool SendFunctionCallTarget(NamedPipeClient& client, int64_t functionId, int64_t address, int32_t reJITId, int32_t processId, const char* name) { return SendFunctionCallTarget(client, functionId, address, reJITId, processId, (int32_t)strlen(name) + 1, name); } ================================================ FILE: src/ManagedProfiler/dllmain.cpp ================================================ // Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #include #include "Common.h" #include "CoreProfilerFactory.h" #include "CoreProfiler.h" // COM ID required when loading the profiler DLL in the .NET runtime. class __declspec(uuid("805A308B-061C-47F3-9B30-F785C3186E81")) CoreProfiler; extern "C" BOOL __stdcall DllMain(HINSTANCE hInstDll, DWORD reason, PVOID) { switch (reason) { case DLL_PROCESS_ATTACH: Log(L"IRX: Profiler connected\n"); break; case DLL_PROCESS_DETACH: break; } return TRUE; } extern "C" HRESULT __stdcall DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv) { if (rclsid == __uuidof(CoreProfiler)) { static CoreProfilerFactory factory; return factory.QueryInterface(riid, ppv); } return CLASS_E_CLASSNOTAVAILABLE; } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/CrstTypeTool.cs ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // This tool exists to transform a high level description of Crst dependencies (i.e. which Crst type may be // acquired before or after other Crst types) into a header file that defines a enum to describe each Crst // type and tables that map type to numerical ranking and a string based name. // // To use the tool, run "csc.exe CrstTypeTool.cs" and run the resulting executable. // // The Crst type definition file is written in a very simple language. Comments begin with '//' and continue // to the end of the line. All remaining tokens after comment removal are simply sequences of non-whitespace // characters separated by whitespace. Keywords are case-insensitive and identifiers (which are always Crst // type names) are case sensitive. The language grammar is given below in EBNF-like form: // // TopLevel ::= CrstDefinition* // // CrstDefinition ::= 'Crst' CrstDependency* 'End' // // CrstDependency ::= 'AcquiredBefore' * // | 'AcquiredAfter' * // | 'SameLevelAs' * // | 'Unordered' // // Crst type names match the CrstType enums used in the source code minus the 'Crst' prefix. For example // CrstAppDomainCache is written as 'AppDomainCache' in the .def file. // // The dependency "A 'AcquiredBefore' B" indicates that CrstA may be legally held while CrstB is acquired. // Similarly "A 'AcquiredAfter' B" indicates that CrstA may be legally acquired while CrstB is held. "A // 'AcquiredBefore' B" is logically equivalent to "B 'AcquiredAfter' A" and authors may enter the dependency // is whichever seems to make the most sense to them (or add both rules if they so desire). // // 'Unordered' indicates that the Crst type does not participate in ranking (there should be very few Crsts // like this and those that are know how to avoid or deal with deadlocks manually). // // 'SameLevelAs' indicates the given Crst type may be acquired alongside any number of instances of the Crst // types indicated. "A 'SameLevel' B" automatically implies "B 'SameLevel' A" so it's not necessary to specify // the dependency both ways though authors can do so if they wish. // // Simple validation of the .def file (over and above syntax checking) is performed by this tool prior to // emitting the header file. This will catch logic errors such as referencing a Crst type that is not // defined or using the 'Unordered' attribute along with any other attribute within a single definition. It // will also catch cycles in the dependency graph (i.e. definitions that logically describe a system where the // Crst types can't be ranked). // using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Text.RegularExpressions; // The main application class containing the program entry point. class CrstTypeTool { // A hash containing every Crst type defined by the input .def file along with its attributes. Keyed by // Crst type name (which is case sensitive and doesn't include the 'Crst' enum prefix). Dictionary m_crsts = new Dictionary(); // The program entry point. public static int Main() { try { // Calculate the filenames of the input and output files. string inputFile = "CrstTypes.def"; string outputFile = "crsttypes_generated.h"; // A common error is to forget to check out the crsttypes_generated.h file first. Handle this case specially // so we can give a good error message. if (File.Exists(outputFile) && (File.GetAttributes(outputFile) & FileAttributes.ReadOnly) != 0) { Console.WriteLine(outputFile + " is read-only, you must check it out of TFS/SD first"); return 2; } // Create an instance of our application class to store state in (specifically the collection of // Crst type definitions). CrstTypeTool app = new CrstTypeTool(); // Create a parser for the CrstTypes.def file and run it over the input file (errors are signalled // via exception, in common with all the following steps except validation). new TypeFileParser().ParseFile(inputFile, app.m_crsts); // Validate the collection of Crst type definitions we built up during parsing for common logic // errors and the presence of dependency cycles. False is returned from ValidateCrsts if an error // was detected (an error message will have already been output to the console at this point). if (!app.ValidateCrsts()) return 3; // Perform a topological sort to map each Crst type to a numeric ranking. app.LevelCrsts(); // Emit the new header file containing Crst type definitions and ranking information. app.WriteHeaderFile(outputFile); // If we get here the transformation was successful; inform the user and we're done. Console.WriteLine(outputFile + " successfully updated"); return 0; } catch (TypeFileParser.ParseError pe) { // Syntax errors specific to parsing the input file. Console.WriteLine("ParseError: " + pe.Message); return 4; } catch (Exception e) { // Any other general errors (file I/O problems, out of memory etc.). Console.WriteLine("Unexpected exception:"); Console.WriteLine(e); return 5; } } // Emit the crsttypes_generated.h output file. void WriteHeaderFile(string fileName) { FileStream stream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None); StreamWriter writer = new StreamWriter(stream); // Create a collection based on all the Crst types we've stored in the hash. We do this so we can sort // the Crst types we emit (lexically, based on type name). Dictionary.ValueCollection crstCollection = m_crsts.Values; CrstType[] crsts = new CrstType[crstCollection.Count]; crstCollection.CopyTo(crsts, 0); Array.Sort(crsts); // Emit the header. Contains copyright information, the usual goop to avoid multiple inclusion and a // header comment to discourage direct editing and point the user at the CrstTypes.def file instead // (where all will be explained in greater detail). writer.WriteLine("//"); writer.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); writer.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); writer.WriteLine("//"); writer.WriteLine(); writer.WriteLine("#ifndef __CRST_TYPES_INCLUDED"); writer.WriteLine("#define __CRST_TYPES_INCLUDED"); writer.WriteLine(); writer.WriteLine("// **** THIS IS AN AUTOMATICALLY GENERATED HEADER FILE -- DO NOT EDIT!!! ****"); writer.WriteLine(); writer.WriteLine("// This file describes the range of Crst types available and their mapping to a numeric level (used by the"); writer.WriteLine("// runtime in debug mode to validate we're deadlock free). To modify these settings edit the"); writer.WriteLine("// file:CrstTypes.def file and run the clr\\artifacts\\CrstTypeTool utility to generate a new version of this file."); writer.WriteLine(); // Emit the CrstType enum to define a value for each crst type (along with the kNumberOfCrstTypes // constant). writer.WriteLine("// Each Crst type is declared as a value in the following CrstType enum."); writer.WriteLine("enum CrstType"); writer.WriteLine("{"); for (int i = 0; i < crsts.Length; i++) writer.WriteLine(" Crst" + crsts[i].Name + " = " + i.ToString() + ","); writer.WriteLine(" kNumberOfCrstTypes = " + crsts.Length.ToString()); writer.WriteLine("};"); writer.WriteLine(); // This is the end of the regular part of the header included by most files. writer.WriteLine("#endif // __CRST_TYPES_INCLUDED"); writer.WriteLine(); // There is a second section of the header intended for inclusion only by vm\Crst.cpp. This contains // some data tables used to map crst type to rank or name. We could instead define two separate // headers, but on the whole it seems simpler to do it this way. writer.WriteLine("// Define some debug data in one module only -- vm\\crst.cpp."); writer.WriteLine("#if defined(__IN_CRST_CPP) && defined(_DEBUG)"); writer.WriteLine(); // Emit the crst type to rank mapping table. writer.WriteLine("// An array mapping CrstType to level."); writer.WriteLine("int g_rgCrstLevelMap[] ="); writer.WriteLine("{"); foreach (CrstType crst in crsts) { string crstLine = " " + crst.Level + ","; crstLine = crstLine + new string(' ', 16 - crstLine.Length); writer.WriteLine(crstLine + "// Crst" + crst.Name); } writer.WriteLine("};"); writer.WriteLine(); // Emit the crst type to name mapping table. writer.WriteLine("// An array mapping CrstType to a stringized name."); writer.WriteLine("LPCSTR g_rgCrstNameMap[] ="); writer.WriteLine("{"); foreach (CrstType crst in crsts) writer.WriteLine(" \"Crst" + crst.Name + "\","); writer.WriteLine("};"); writer.WriteLine(); // Emit the constant Crst.cpp uses to record an unordered rank. writer.WriteLine("// Define a special level constant for unordered locks."); writer.WriteLine("#define CRSTUNORDERED (-1)"); writer.WriteLine(); // Emit a couple of inline helpers to map type to rank or name (and validate the type while they're at // it). writer.WriteLine("// Define inline helpers to map Crst types to names and levels."); writer.WriteLine("inline static int GetCrstLevel(CrstType crstType)"); writer.WriteLine("{"); writer.WriteLine(" LIMITED_METHOD_CONTRACT;"); writer.WriteLine(" _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes);"); writer.WriteLine(" return g_rgCrstLevelMap[crstType];"); writer.WriteLine("}"); writer.WriteLine("inline static LPCSTR GetCrstName(CrstType crstType)"); writer.WriteLine("{"); writer.WriteLine(" LIMITED_METHOD_CONTRACT;"); writer.WriteLine(" _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes);"); writer.WriteLine(" return g_rgCrstNameMap[crstType];"); writer.WriteLine("}"); writer.WriteLine(); // And that's the end of the second section of the header file. writer.WriteLine("#endif // defined(__IN_CRST_CPP) && defined(_DEBUG)"); writer.Close(); stream.Close(); } // Perform checking of the Crst type definitions we've read just read. Various forms of logic error are // scanned for including cycles in the dependency graph. Returns true if no errors are found. If false is // returned a descriptive error message will have already been written to the console. bool ValidateCrsts() { // Look at each Crst type definition in turn. foreach (CrstType crst in m_crsts.Values) { // Catch Crst types that are referenced but never defined. if (!crst.Defined) { Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is referenced without being defined", crst.Name)); return false; } // Catch the use of the 'Unordered' attribute alongside the 'AcquiredBefore' attribute (which // indicates an ordering). if (crst.Level == CrstType.CrstUnordered && (crst.AcquiredBeforeList.Count > 0 || crst.Group != null)) { Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as both unordered and acquired before 'Crst{1}'", crst.Name, crst.AcquiredBeforeList[0].Name)); return false; } // Catch the use of the 'Unordered' attribute alongside the 'SameLevelAs' attribute (which // indicates an ordering). if (crst.Level == CrstType.CrstUnordered && crst.Group != null) { Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as both unordered and in the same level as another CrstType", crst.Name)); return false; } // Catch the simple cycle where the Crst type depends on itself. if (crst.AcquiredBeforeList.Contains(crst)) { Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is declared as being acquired before itself", crst.Name)); return false; } // Look for deeper cycles using a recursive algorithm in 'FindCycle()'. List cycleList = new List(); if (FindCycle(crst, crst, cycleList)) { Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", crst.Name)); foreach (CrstType cycleCrst in cycleList) Console.WriteLine(String.Format(" Crst{0}", cycleCrst.Name)); return false; } } // Perform normalization of each set of Crst types that are included in the same group (i.e. have a // 'SameLevelAs' relationship). Normalization means that each Crst type in a group will have exactly // the same set of dependency rules as all the others. CrstTypeGroup.NormalizeAllRules(); // The normalization process could have introduced cycles in the dependency graph so run the cycle // detection pass again. We do separate passes like this since normalizing can lead to less intuitive // error messages if a cycle is found: so if the cycle exists before normalization takes place we want // to generate an error message then. foreach (CrstType crst in m_crsts.Values) { List cycleList = new List(); if (FindCycle(crst, crst, cycleList)) { Console.WriteLine(String.Format("Error: CrstType 'Crst{0}' is involved in a dependency cycle with the following CrstTypes:", crst.Name)); foreach (CrstType cycleCrst in cycleList) Console.WriteLine(String.Format(" Crst{0}", cycleCrst)); Console.WriteLine("Note that the cycle was detected only after 'SameLevelAs' processing was performed so some CrstType dependencies are implied by peer CrstTypes"); return false; } } return true; } // Recursively determine if a cycle exists in the Crst type dependency graph rooted at the 'rootCrst' // type. The 'currCrst' indicates the next dependency to be examined (it will be the same as the // 'rootCrst' when we're first called). The 'cycleList' argument contains a list of Crst types we've // already examined in this branch of the algorithm and serves both to avoid checking the same node twice // and to provide a list of the involved Crst types should a cycle be detected. // Note that this algorithm is not designed to detect general cycles in the graph, only those that involve // the 'rootCrst' directly. This is somewhat inefficient but gives us a simple way to generate clear error // messages. bool FindCycle(CrstType rootCrst, CrstType currCrst, List cycleList) { // Add the current Crst type to the list of those we've seen. cycleList.Add(currCrst); // Look through all the dependencies of the current Crst type. foreach (CrstType childCrst in currCrst.AcquiredBeforeList) { // If we find a reference back to the root Crst type then we've found a cycle. Start backing out // from the recursion (keeping the list of nodes we visited intact) by returning true. if (childCrst == rootCrst) return true; // Otherwise iterate over the dependencies of the current node and for each one that we haven't // already seen and recursively extend the search. if (!cycleList.Contains(childCrst)) if (FindCycle(rootCrst, childCrst, cycleList)) return true; } // Didn't find any cycles involving the root and this node; remove this node from the potential cycle // list and return up to our caller indicating such. cycleList.RemoveAt(cycleList.Count - 1); return false; } // Topologically sort all the Crsts so we can assign a total ordering to them (in the form of a numeric // ranking). Ranks start from 0 (Crst types that may be acquired at any time) and increment from there // (Crst types that may only be acquired if a lower type is not already held). // **** NOTE: The leveling process is destructive in that we will lose all dependency information from the // Crst type definitions during the course of the algorithm. void LevelCrsts() { // Note that Crst type dependency rules have been normalized (by the input parser) so that all // AcquiredBefore/AcquiredAfter relationships have been reduced to AcquiredBefore relationships (i.e. // any rule of the form "A AcquiredAfter B" has been converted to "B AcquiredBefore A". Any // normalization makes the algorithm easier to program, but a normaliztion to AcquiredBefore // relationships was chosen since it makes it particularly easy to implement an algorithm that assigns // ranks beginning with zero and moving up to an arbitrary level. Any type that doesn't have any // AcquiredBefore dependencies can always be ranked at a lower level than any remaining unranked types // by definition and from this we can derive a simple iterative process to rank all the crst types. // Calculate how many Crst types we have left to rank (some are not included in this step because // they've been marked as 'Unordered' in the input file). int unsorted = 0; foreach (CrstType crst in m_crsts.Values) if (crst.Level == CrstType.CrstUnassigned) unsorted++; // The ranking level we're going to assign to Crst types on the next pass of the algorithm. int currLevel = 0; // Iterate while we still have Crst types left to rank. On each pass we'll assign a rank to those // types that no longer have any dependencies forcing them to have a higher rank and then remove // dependency rules involving those newly ranked types from the remaining types. while (unsorted > 0) { // Record a flag indicating whether we manage to assign a rank to at least one Crst type on this // pass. If we ever fail to do this we've hit a cycle (this is just paranoia, the Crst declaration // validation performed in ValidateCrsts() should have detected such a cycle first). bool madeProgress = false; // If we spot any types that are in a group (SameLevelAs relationship) then we defer assigning a // rank till we've dealt with any non-group types (we wish to always place type groups in their // very own rank else the Crst rank violation detection code won't detect violations between // members of the group and singleton types that happened to be assigned rank on the same pass). List deferredGroups = new List(); // Scan through all the Crst types. foreach (CrstType crst in m_crsts.Values) { // Skip those types that already have a rank assigned. if (crst.Level != CrstType.CrstUnassigned) continue; // We're looking for Crst types that no longer have any types that can be acquired while they // are already held. This indicates that it's safe to assign the current rank to them (since // there are no remaining dependencies that need to be ranked first (i.e. with a lower rank // value than this type). if (crst.AcquiredBeforeList.Count == 0) { if (crst.Group == null) { // If this type is not part of the group we can go and assign the rank right away. crst.Level = currLevel; madeProgress = true; unsorted--; } else if (!deferredGroups.Contains(crst.Group)) // Otherwise we'll defer ranking this group member until all the singletons are // processed. deferredGroups.Add(crst.Group); } } // We've gone through the entire collection of Crst types and assigned the current rank level to // any singleton Crst types that qualify. Now deal with any group members we detected (it's // possible that more than one group qualifies for ranking at this level but we need to be careful // to assign distinct rank values to each group to avoid hiding lock rank violations (since group // members are always allowed to be acquired alongside any other type with the same rank value). // Iterate over each distinct group that we found in this pass. foreach (CrstTypeGroup group in deferredGroups) { // Look at our progress flag here. If it is false then we didn't have any singleton Crst types // ranked at this level and we haven't processed any other groups at this level either. Thus // we can rank this group at the current level. Otherwise at least one type was already ranked // with this level so we need to increment to a new, distinct level to avoid ranking // ambiguity. if (madeProgress) currLevel++; // Iterate through each Crst type that is a member of this group assigning them the (same) // current rank. foreach (CrstType crst in group.Members) { // Double check that each member has the same dependencies (i.e. they should all be empty // by now). There should be no way that this error should ever occur, it's just paranoia // on my part. if (crst.AcquiredBeforeList.Count != 0) throw new Exception("Internal error: SameLevel CrstTypes with differing rulesets"); crst.Level = currLevel; unsorted--; } // Once we've processed at least one group we've made progress this iteration. madeProgress = true; } // If we didn't manage to assign rank to at least one Crst type then we're not going to do any // better next iteration either (because no state was updated in this iteration). This should only // occur in the presence of a dependency cycle and we shouldn't get that here after a successful // call to ValidateCrsts(), so this check is pure paranoia. if (!madeProgress) { Console.WriteLine(String.Format("{0} unsorted remain", unsorted)); throw new Exception("Cycle detected trying to assign level " + currLevel.ToString()); } // Loop through all the unranked Crsts types and remove any AcquiredBefore relationships that // involve types we've already leveled (since those types, by definition, have already been // assigned a lower rank). foreach (CrstType crst in m_crsts.Values) { if (crst.Level != CrstType.CrstUnassigned) continue; List prunedCrsts = crst.AcquiredBeforeList.FindAll(Unleveled); crst.AcquiredBeforeList = prunedCrsts; } // Done with this rank level, move to the next. currLevel++; } } // Predicate method used with List.FindAll() to locate Crst types that haven't had their rank assigned // yet. static bool Unleveled(CrstType crst) { return crst.Level == CrstType.CrstUnassigned; } } // Class used to parse a CrstTypes.def file into a dictionary of Crst type definitions. It uses a simple lexer // that removes comments then forms tokens out of any consecutive non-whitespace characters. An equally simple // recursive descent parser forms Crst instances by parsing the token stream. class TypeFileParser { // Remember the input file name and the dictionary we're meant to populate. string m_typeFileName; Dictionary m_crsts; // Compile regular expressions for detecting comments and tokens in the parser input. Regex m_commentRegex = new Regex(@"//.*"); Regex m_tokenRegex = new Regex(@"^(\s*(\S+)\s*)*"); // Input is lexed into an array of tokens. We record the index of the token being currently parsed. Token[] m_tokens; int m_currToken; // Parse the given file into Crst type definitions and place these definitions in the dictionary provided. // Syntax errors are signalled via ParseError derived exceptions. public void ParseFile(string typeFileName, Dictionary crsts) { m_typeFileName = typeFileName; m_crsts = crsts; // Lex the file into tokens. InitTokenStream(); // Parse the tokens according to the grammar set out at the top of this file. // Loop until we have no further tokens to process. while (!IsEof()) { // Grab the next token. Token token = NextToken(); // We're at the top level, so the token had better be 'Crst'. if (token.Id != KeywordId.Crst) throw new UnexpectedTokenError(token, KeywordId.Crst); // OK, parse the rest of this single Crst type definition. ParseCrst(); } } // Parse a single Crst type definition. void ParseCrst() { // The next token had better be an identifier (the Crst type name). Token token = NextToken(); if (token.Id != KeywordId.Id) throw new UnexpectedTokenError(token, KeywordId.Id); // The Crst instance might already exist in the dictionary (forward references to a Crst type cause // these entries to auto-vivify). But in that case the entry better not be marked as 'Defined' which // would indicate a double declaration. CrstType crst; if (m_crsts.ContainsKey(token.Text)) { crst = m_crsts[token.Text]; if (crst.Defined) throw new ParseError(String.Format("Duplicate definition for CrstType '{0}'", token.Text), token); } else { // Otherwise this Crst type hasn't been seen thus far so we allocate a new instance and add it to // the dictionary. crst = new CrstType(token.Text); m_crsts.Add(crst.Name, crst); } // We're defining, not just referencing this type. crst.Defined = true; // Parse any attributes inside this definition (until we see an 'End' token). bool parsingCrst = true; while (parsingCrst) { // Get the next token. Either some attribute keyword or 'End'. token = NextToken(); List list; switch (token.Id) { case KeywordId.AcquiredBefore: // Simply parse the following list of Crst types into the current type's AcquiredBefore list. ParseList(crst.AcquiredBeforeList); break; case KeywordId.AcquiredAfter: // AcquiredAfter is trickier. To make the ranking algorithm's life easier we actually // normalize all rules to the AcquiredBefore form (see LevelCrsts() for the reasoning). So we // capture the list of Crst types that follow the AcquiredAfter keyword and then append the // current type to the AcquiredBefore list of each type found. list = new List(); ParseList(list); foreach (CrstType priorCrst in list) priorCrst.AcquiredBeforeList.Add(crst); break; case KeywordId.SameLevelAs: // Parse the following list of Crst types them let the CrstTypeGroup class handle the // resulting updates to the type groups we're currently maintaining. See the comments for the // CrstTypeGroup class for more details. list = new List(); ParseList(list); foreach (CrstType sameLevelCrst in list) CrstTypeGroup.Join(crst, sameLevelCrst); break; case KeywordId.Unordered: crst.Level = CrstType.CrstUnordered; break; case KeywordId.End: parsingCrst = false; break; default: throw new UnexpectedTokenError(token, KeywordId.AcquiredBefore, KeywordId.AcquiredAfter, KeywordId.SameLevelAs, KeywordId.Unordered); } } } // Parse a list of Crst type names. Any other token terminates the list (without error and without // consuming that token from the stream). The list of tokens is returned as a list of corresponding // CrstTypes (which are auto-vivified in the output dictionary if they haven't been declared yet). void ParseList(List list) { // Parse tokens until we find a non-identifier. while (true) { Token token = NextToken(); if (token.Id != KeywordId.Id) { // We found the list terminator. Push the non-identifier token back into the stream for our // caller to parse correctly. UnwindToken(); return; } // Look up or add a new CrstType corresponding to this type name. CrstType crst; if (m_crsts.ContainsKey(token.Text)) crst = m_crsts[token.Text]; else { crst = new CrstType(token.Text); m_crsts[crst.Name] = crst; } // Add the type to the output list we're building. list.Add(crst); } } // Lex the input file into an array of tokens. void InitTokenStream() { StreamReader file = new StreamReader(m_typeFileName); int lineNumber = 1; List tokenList = new List(); // Read the file a line at a time. string line; while ((line = file.ReadLine()) != null) { // Remove comments from the current line. line = m_commentRegex.Replace(line, ""); // Match all contiguous non-whitespace characters as individual tokens. Match match = m_tokenRegex.Match(line); if (match.Success) { // For each token captured build a token instance and record the token text and the file, line // and column at which it was encountered (these latter in order to produce useful syntax // error messages). CaptureCollection cap = match.Groups[2].Captures; for (int i = 0; i < cap.Count; i++) tokenList.Add(new Token(m_typeFileName, cap[i].Value, lineNumber, cap[i].Index)); } lineNumber++; } // Record the list of tokens we captured as an array and reset the index of the next token to be // handled by the parser. m_tokens = tokenList.ToArray(); m_currToken = 0; } // Have we run out of tokens to parse? bool IsEof() { return m_currToken >= m_tokens.Length; } // Get the next token and throw an exception if we ran out. Token NextToken() { if (m_currToken >= m_tokens.Length) throw new UnexpectedEofError(); return m_tokens[m_currToken++]; } // Push the last token parsed back into the stream. void UnwindToken() { if (m_currToken <= 0) throw new InvalidOperationException(); m_currToken--; } // The various keywords we can encounter (plus Id for identifiers, which are currently always Crst type // names). internal enum KeywordId { Id, Crst, End, AcquiredBefore, AcquiredAfter, Unordered, SameLevelAs, } // Class encapsulating a single token captured from the input file. internal class Token { // Hash of keyword text to enum values. static Dictionary s_keywords; // The characters comprising the text of the token from the input file. string m_text; // Where the token was found (for error messages). string m_file; int m_line; int m_column; // The ID of the keyword this token represents (or KeywordId.Id). KeywordId m_id; // Static class initialization. static Token() { // Populate the keyword hash. No sense building complex finite state machines to improve the // efficiency of keyword lexing here since the input file (and keyword set) is never going to be // big enough to justify the extra work. s_keywords = new Dictionary(); s_keywords.Add("crst", KeywordId.Crst); s_keywords.Add("end", KeywordId.End); s_keywords.Add("acquiredbefore", KeywordId.AcquiredBefore); s_keywords.Add("acquiredafter", KeywordId.AcquiredAfter); s_keywords.Add("unordered", KeywordId.Unordered); s_keywords.Add("samelevelas", KeywordId.SameLevelAs); } public Token(string file, string text, int line, int column) { m_file = file; m_text = text; m_line = line; m_column = column; // Map token text to keyword ID. True keywords (not identifiers) are case insensitive so normalize // the text to lower case before performing the keyword hash lookup. string canonName = m_text.ToLower(); if (s_keywords.ContainsKey(canonName)) m_id = s_keywords[canonName]; else m_id = KeywordId.Id; } public string Text {get { return m_text; }} public string Location {get { return String.Format("{0} line {1}, column {2}", m_file, m_line, m_column); }} public KeywordId Id {get { return m_id; }} } // Base class for all syntax errors reported by the parser. internal class ParseError : Exception { // A raw error message. public ParseError(string message) : base(message) {} // An error message tagged with a file, line and column (coming from an error token). public ParseError(string message, Token errorToken) : base(String.Format("{0}: {1}", errorToken.Location, message)) {} // Produce a textual name for the given keyword type. protected static string IdToName(KeywordId id) { if (id == KeywordId.Id) return "a CrstType name"; return String.Format("'{0}'", id.ToString()); } } // Syntax error used when an unexpected token is encountered which further lists the valid tokens that // would otherwise have been accepted. internal class UnexpectedTokenError : ParseError { // Produce an unexpected token message with a file, line and column coming from an error token and // optionally the names of zero or more tokens that would have been accepted. public UnexpectedTokenError(Token errorToken, params KeywordId[] expected) : base(FormatErrorMessage(errorToken, expected)) {} static string FormatErrorMessage(Token errorToken, KeywordId[] expected) { StringBuilder message = new StringBuilder(String.Format("Unexpected token '{0}' at {1}", errorToken.Text, errorToken.Location)); if (expected.Length == 0) { } else if (expected.Length == 1) { message.Append(String.Format("; expected {0}", IdToName(expected[0]))); } else { message.Append("; expected one of "); for (int i = 0; i < expected.Length - 1; i++) message.Append(String.Format("{0}, ", IdToName(expected[i]))); message.Append(IdToName(expected[expected.Length - 1])); } return message.ToString(); } } // Syntax error used when we unexpectedly ran out of tokens. internal class UnexpectedEofError : ParseError { public UnexpectedEofError() : base("Unexpected end of file") {} } } // This class represents an instance of a Crst type. These are unqiuely identified by case-sensitive name (the // same as the enum name used in vm code, minus the 'Crst' prefix). class CrstType : IComparable { // Special level constants used to indicate unordered Crst types or those types we haven't gotten around // to ranking yet. public static readonly int CrstUnordered = -1; public static readonly int CrstUnassigned = -2; // Name of the type, e.g. "AppDomainCache" for the CrstAppDomainCache type. string m_name; // The numeric ranking assigned to this type. Starts as CrstUnassigned and then becomes either // CrstUnordered (while parsing the input file) or a number >= 0 (during LevelCrsts()). int m_level; // List of Crst types that can be legally acquired while this one is held. (AcquiredAfter relationships // are by switching the terms and adding to the second type's AcquiredBefore list). List m_acquiredBeforeCrsts; // Either null if this Crst type is not in (or has not yet been determined to be in) a SameLevelAs // relationship or points to a CrstTypeGroup that records all the sibling types at the same level (that // have been discovered thus far during parsing). CrstTypeGroup m_group; // Set once a definition for this type has been discovered. Used to detect double definitions and types // referenced without definitions. bool m_defined; public CrstType(string name) { m_name = name; m_level = CrstUnassigned; m_acquiredBeforeCrsts = new List(); m_group = null; m_defined = false; } public string Name {get { return m_name; }} public int Level {get { return m_level; } set { m_level = value; }} public List AcquiredBeforeList {get { return m_acquiredBeforeCrsts; } set { m_acquiredBeforeCrsts = value; }} public CrstTypeGroup Group {get { return m_group; } set { m_group = value; }} public bool Defined {get {return m_defined; } set { m_defined = value; }} // Helper used to sort CrstTypes. The sort order is lexical based on the type name. public int CompareTo(object other) { return m_name.CompareTo(((CrstType)other).m_name); } } // Every time a SameLevelAs relationship is used we need to be careful to keep track of the transitive closure // of all types bound in the relationship. That's because such a relationship impacts the other dependency // rules (each member of a SameLevelAs group must behave as though it has exactly the same dependency rules as // all the others). Identifying all the members is tricky because "A SameLevelAs B" and "B SameLevelAs C" // implies "A SameLevelAs C". So we use a separate tracking structure, instances of the CrstTypeGroup type, to // do the bookkeeping for us. Each Crst type belongs to either zero or one CrstTypeGroups. As we find new // SameLevelAs relationships we create new groups, add types to existing groups or merge groups (as previous // distinct groups are merged by the discovery of a SameLevelAs relationship that links them). By the time // parsing has finished we are guaranteed to have discovered all the distinct, disjoint groups and to have // fully populated them with the transitive closure of all related types. We can them normalize all groups // members so they share the same AcquiredBefore relationships. class CrstTypeGroup { // We record every group that has been formed so far. This makes normalizing all groups easier. static List s_groups = new List(); // Crst types that are members of the current group. There are no duplicates in this list. List m_members = new List(); // Declare a SameLevelAs relationship between the two Crst types given. Groups will be assigned, created // or merged as required to maintain our guarantees (each CrstType is a member of at most one group and // all CrstTypes involved in the same transitive closure of a SameLevelAs relationship are members of one // group). public static void Join(CrstType crst1, CrstType crst2) { CrstTypeGroup group; if (crst1 == crst2) { // In this case the type refers to itself. Create a singleton group for this type if it doesn't // already exist. if (crst1.Group == null) { group = new CrstTypeGroup(); group.m_members.Add(crst1); s_groups.Add(group); crst1.Group = group; } } else if (crst1.Group == null && crst2.Group == null) { // Neither types belong to a group already. So we can create a new one and add both types to it. group = new CrstTypeGroup(); group.m_members.Add(crst1); group.m_members.Add(crst2); s_groups.Add(group); crst1.Group = group; crst2.Group = group; } else if (crst1.Group == null) { // The first type doesn't belong to a group yet but the second does. So we can simply add the // first type to the second group. group = crst2.Group; group.m_members.Add(crst1); crst1.Group = group; } else if (crst2.Group == null) { // As for the case above but the group/no-group positions are reversed. group = crst1.Group; group.m_members.Add(crst2); crst2.Group = group; } else if (crst1.Group != crst2.Group) { // Both types belong to different groups so we'll have to merge them. Add the members of group 2 // to group 1 and throw away group 2. group = crst1.Group; CrstTypeGroup absorbGroup = crst2.Group; foreach (CrstType crst in absorbGroup.m_members) { group.m_members.Add(crst); crst.Group = group; } s_groups.Remove(absorbGroup); } // The only case left is when both types are already in the same group and there's no work needed in // this case. } // Normalize all the groups we created during parsing. See below for the definition of normalization. public static void NormalizeAllRules() { foreach (CrstTypeGroup group in s_groups) group.NormalizeRules(); } // Normalize this group. This involves adjusting the AcquiredBefore list of each member to be the union of // all such rules within the group. This step allows us to detect cycles in the dependency graph that // would otherwise remain hidden if we only examined the unnormalized AcquiredBefore rules. void NormalizeRules() { // This local will contain the union of all AcquiredBefore rules. List acquiredBeforeList = new List(); // Iterate through each member of the group. foreach (CrstType crst in m_members) { // Add each AcquiredBefore rule we haven't already seen to the union. foreach (CrstType afterCrst in crst.AcquiredBeforeList) if (!acquiredBeforeList.Contains(afterCrst)) acquiredBeforeList.Add(afterCrst); } // Reset each member's AcquiredBefore list to a copy of the union we calculated. Note it's important // to make a (shallow) copy because the ranking process modifies this list and so a shared copy would // cause unexpected results. foreach (CrstType crst in m_members) crst.AcquiredBeforeList = acquiredBeforeList.GetRange(0, acquiredBeforeList.Count); } public List Members {get { return m_members; }} } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/CrstTypes.def ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // This file is used to describe the different types of Crst and their dependencies on other Crst types (in // terms of which types may be legally held while others are acquired). // // The CrstTypeTool utility is used to parse this file, verify that there are no logical inconsistencies (such // as a cycle in the dependencies) and generate an enum value and numerical ranking for each type. This // ranking is used by the runtime (in checked builds) to verify that none of the rules described below are // violated (which could lead to a deadlock). // // When you add a new Crst type you need to be aware of which Crst types may be already held when your Crst is // acquired and which other types may be subsequently acquired. You can then add a Crst definition to this // file and annotate it with those dependencies. Running CrstTypeTool will check to see if this introduces a // potential deadlock problem and if everything checks out will generate a new version of // file:crsttypes_generated.h. // // The format of this file is a very simple language. Comments are introduced with '//' and continue to the // end of the line. Keywords are case insensitive (Crst type names, however, are case sensitive since they'll // be translated directly to C++ enum values). Crst type names are used without the 'Crst' prefix used in C++ // code (e.g. CrstAppDomainCache is referred to as AppDomainCache). The following words are reserved keywords // and may not be used as the names of Crst types: // Crst // End // AcquiredBefore // AcquiredAfter // Unordered // SameLevelAs // // Each Crst type definition has the following format (where [] indicates optional and ... indicates zero or // more repetitions): // Crst // [AcquiredBefore ...] // [AcquiredAfter ...] // [SameLevelAs ...] // [Unordered] // End // // For example: // Crst Foo // AcquiredBefore Bar // AcquiredAfter Zob Baz // SameLevelAs Foo // End // // This introduces a new Crst type Foo (CrstFoo inside the runtime). This type may be legally acquired when // the current thread holds Crst instances of type Zob, Bar or even other instances of Foo. While Foo is held // it is legal to acquire Crsts of type Bar. Assuming that this definition does not introduce any dependency // cycles, CrstTypeTool will assign a numeric rank to CrstFoo that maximizes the chance that any other Crst // type interaction you didn't explicitly specify (e.g. holding Foo while taking a Crst of type Wibble) will // generate a ranking violation assert in the checked build. // // Note that the following set of definitions: // Crst A AcquiredBefore B End // Crst B End // // Crst A End // Crst B AcquiredAfter A End // // Crst A AcquiredBefore B End // Crst B AcquiredAfter A End // // are all equivalent. You are free to use whichever variant seems clearest to you (CrstTypeTool will tell you // if you introduce conflicting rules). Similarly "A SameLevelAs B" implies "B SameLevelAs A". The initial // contents of this file uses AcquiredBefore in preference to AcquiredAfter purely because it was generated // automatically by a profiling mechanism (the initial rules were seeded from observations of Crst usage while // running our test suites). Feel free to add meaningful comments to existing rules if you feel they can // usefully clarify the reasons for particular dependencies. // // See CrstTypeTool.cs for how to consume this file. // // Each Crst type definition is currently in alphabetical order. Please maintain this convention. // Crst AppDomainCache AcquiredBefore UniqueStack UnresolvedClassLock End Crst PinnedHeapHandleTable AcquiredBefore AvailableParamTypes HandleTable IbcProfile SyncBlockCache SystemDomainDelayedUnloadList SystemDomain End Crst ArgBasedStubCache End Crst AssemblyLoader AcquiredBefore DeadlockDetection UniqueStack DebuggerMutex End Crst AvailableClass AcquiredBefore LoaderHeap End Crst AvailableParamTypes AcquiredBefore ModuleLookupTable IbcProfile LoaderHeap End Crst BaseDomain AcquiredBefore LoaderHeap UniqueStack End Crst CCompRC Unordered End Crst ClassFactInfoHash AcquiredBefore SyncBlockCache ThreadStore End Crst ClassInit AcquiredBefore DeadlockDetection IbcProfile SameLevelAs Jit End Crst ClrNotification Unordered End Crst COMWrapperCache AcquiredBefore HandleTable UniqueStack End Crst DeadlockDetection End Crst DebuggerController // AcquiredBefore DebuggerHeapLock DebuggerJitInfo LoaderHeap // See bug: 581892. This has a conflict with CrstInstMethodHashTableRanking. // The controller logic will be moved to OOP in V3, and so this lock will no longer be necessary. // Fixing this in-proc would be difficult, and it would all be throwaway as we go oop. Unordered End // This is a leaf debugger lock. Crst DebuggerFavorLock AcquiredAfter DebuggerJitInfo DebuggerMutex End // This is the lock used by the DebuggerHeapExecutableMemoryAllocator for allocating/freeing memory. Crst DebuggerHeapExecMemLock End // Debugger Heap lock is the smallest of the debugger locks. Crst DebuggerHeapLock AcquiredAfter DebuggerFavorLock DebuggerJitInfo DebuggerMutex // Disabled per bug 581892 // AcquiredAfter DebuggerController End Crst DebuggerJitInfo AcquiredBefore DebuggerHeapLock End // This is the major debugger lock. // It's the largest of the debugger locks. Crst DebuggerMutex AcquiredBefore AvailableParamTypes DynamicIL LoaderHeap ModuleLookupTable // Disabled per bug 581892 // AcquiredBefore DebuggerController AcquiredBefore DebuggerHeapLock DebuggerJitInfo End // This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) // and is released before taking any other lock except for CrstDataTest2 Crst DataTest1 AcquiredAfter DebuggerMutex End // This lock is used only for testing data consistency (see code:DataTest::TestDataSafety) // and is released before taking any other lockCrst DataTest2 Crst DataTest2 AcquiredAfter DataTest1 End Crst DbgTransport End Crst DelegateToFPtrHash End Crst DomainLocalBlock AcquiredBefore PinnedHeapHandleTable IbcProfile LoaderHeap SystemDomainDelayedUnloadList UniqueStack End Crst DynamicIL End Crst DynamicMT AcquiredBefore IbcProfile End Crst EventStore End Crst Exception End Crst ExecutableAllocatorLock AcquiredAfter LoaderHeap ArgBasedStubCache UMEntryThunkFreeListLock COMCallWrapper End Crst ExecuteManRangeLock AcquiredAfter NativeImageEagerFixups End Crst FCall AcquiredBefore LoaderHeap End Crst FrozenObjectHeap Unordered End Crst MethodTableExposedObject Unordered End Crst RetThunkCache AcquiredBefore LoaderHeap End Crst FuncPtrStubs AcquiredBefore IbcProfile LoaderHeap UniqueStack CodeFragmentHeap JumpStubCache End Crst FusionAppCtx AcquiredBefore PEImage End Crst GCCover AcquiredBefore LoaderHeap CodeVersioning End Crst GlobalStrLiteralMap AcquiredBefore PinnedHeapHandleTable HandleTable IbcProfile SyncBlockCache SystemDomainDelayedUnloadList ThreadStore UniqueStack End Crst HandleTable SameLevelAs HandleTable End Crst IbcProfile End Crst IJWFixupData AcquiredBefore FuncPtrStubs IJWHash LoaderHeap End Crst IJWHash End Crst ILStubGen AcquiredBefore DeadlockDetection UniqueStack End Crst InstMethodHashTable AcquiredBefore LoaderHeap UniqueStack JumpStubCache End Crst Interop AcquiredBefore PinnedHeapHandleTable AvailableParamTypes ClassInit DeadlockDetection DomainLocalBlock HandleTable InstMethodHashTable InteropData JitGenericHandleCache LoaderHeap SigConvert StubDispatchCache StubUnwindInfoHeapSegments SyncBlockCache TypeIDMap UnresolvedClassLock PendingTypeLoadEntry End Crst InteropData AcquiredBefore LoaderHeap UniqueStack End Crst IsJMCMethod End Crst ISymUnmanagedReader AcquiredBefore UniqueStack JumpStubCache End Crst Jit AcquiredBefore DeadlockDetection JumpStubCache SameLevelAs ClassInit End Crst JitGenericHandleCache End Crst JitPatchpoint AcquiredBefore LoaderHeap End Crst JitPerf Unordered End Crst JumpStubCache AcquiredBefore ExecuteManRangeLock LoaderHeap SingleUseLock AcquiredAfter AppDomainCache ILStubGen TypeIDMap BaseDomain AssemblyLoader End Crst ListLock Unordered End // Leaflock leveling, used for crsts that explicitly want to be a leaf lock Crst LeafLock End Crst LoaderAllocator AcquiredBefore PinnedHeapHandleTable HandleTable UniqueStack ThreadStore AcquiredAfter DomainLocalBlock End Crst LoaderAllocatorReferences AcquiredBefore LoaderAllocator AcquiredAfter PendingTypeLoadEntry InstMethodHashTable End Crst AssemblyList AcquiredAfter LoaderAllocatorReferences ThreadStore AssemblyLoader End Crst LoaderHeap End Crst StubCache AcquiredBefore LoaderHeap End Crst ManagedObjectWrapperMap AcquiredBefore HandleTable End Crst Module AcquiredBefore LoaderHeap UniqueStack End Crst ModuleFixup AcquiredBefore PinnedHeapHandleTable GlobalStrLiteralMap IbcProfile SyncBlockCache End Crst ModuleLookupTable AcquiredBefore LoaderHeap End Crst Nls End Crst ObjectList SameLevelAs ObjectList End Crst PEImage AcquiredBefore UniqueStack End Crst PendingTypeLoadEntry AcquiredBefore AppDomainCache PinnedHeapHandleTable AssemblyLoader AvailableClass AvailableParamTypes BaseDomain ClassInit DeadlockDetection DebuggerController DebuggerJitInfo DebuggerMutex DomainLocalBlock Exception ExecuteManRangeLock FuncPtrStubs FusionAppCtx GlobalStrLiteralMap HandleTable IbcProfile IJWFixupData IJWHash ISymUnmanagedReader Jit JumpStubCache LoaderHeap Module ModuleLookupTable PEImage SecurityStackwalkCache SigConvert SingleUseLock StubDispatchCache StubUnwindInfoHeapSegments SyncBlockCache SystemDomain ThreadIdDispenser ThreadStore TypeIDMap UnresolvedClassLock SameLevelAs PendingTypeLoadEntry End // ProfilerGCRefDataFreeList synchronizes access to the profiler API's list of // free, previously allocated structures that track moved references and // root references during a GC. Crst ProfilerGCRefDataFreeList End // ProfilingAPIStatus serializes attempts to transition the global status // from state to state, and access to the ProfilerDetachInfo structure // between the thread executing DetachProfiler(), and the DetachThread // carrying out the evacuation order. Crst ProfilingAPIStatus AcquiredBefore ThreadStore End Crst RCWCache AcquiredBefore IbcProfile LoaderHeap RCWCleanupList End Crst RCWCleanupList End Crst ExternalObjectContextCache End Crst Reflection AcquiredBefore LoaderHeap UnresolvedClassLock End // Used to synchronize all rejit information stored in a given AppDomain. Crst CodeVersioning AcquiredBefore LoaderHeap SingleUseLock DeadlockDetection JumpStubCache DebuggerController FuncPtrStubs AcquiredAfter ReJITGlobalRequest ThreadStore GlobalStrLiteralMap SystemDomain DebuggerMutex MethodDescBackpatchInfoTracker ReadyToRunEntryPointToMethodDescMap ClassInit AppDomainCache TypeIDMap FusionAppCtx COMWrapperCache End // Used to synchronize all global requests (which may span multiple AppDomains) which add // new functions to rejit tables, or request Reverts on existing functions in the rejit // tables. One of these crsts exist per runtime. Crst ReJITGlobalRequest AcquiredBefore ThreadStore CodeVersioning SystemDomain JitInlineTrackingMap End // ETW infrastructure uses this crst to protect a hash table of TypeHandles which is // used to remember which types have been logged (to avoid duplicate logging of the // same type). Crst EtwTypeLogHash AcquiredAfter SingleUseLock End Crst SavedExceptionInfo AcquiredBefore DebuggerController End Crst SaveModuleProfileData End Crst SecurityStackwalkCache End Crst SigConvert AcquiredBefore LoaderHeap End Crst SingleUseLock AcquiredBefore ExecuteManRangeLock LoaderHeap UniqueStack DebuggerJitInfo End Crst UnwindInfoTableLock AcquiredAfter StubUnwindInfoHeapSegments SingleUseLock AcquiredBefore StressLog End Crst SpecialStatics End Crst StressLog Unordered End Crst CodeFragmentHeap AcquiredBefore SingleUseLock End Crst StubDispatchCache End Crst StubUnwindInfoHeapSegments AcquiredAfter StubCache End Crst SyncBlockCache AcquiredBefore ThreadIdDispenser End Crst SyncHashLock End Crst SystemBaseDomain AcquiredBefore LoaderHeap UniqueStack End Crst SystemDomain AcquiredBefore DebuggerMutex HandleTable IbcProfile SaveModuleProfileData ThreadIdDispenser ThreadStore End Crst SystemDomainDelayedUnloadList End Crst ThreadIdDispenser End Crst ThreadStore AcquiredBefore AvailableParamTypes DeadlockDetection DebuggerController DebuggerHeapLock DebuggerJitInfo DynamicIL ExecuteManRangeLock HandleTable IbcProfile JitGenericHandleCache JumpStubCache LoaderHeap ModuleLookupTable ProfilerGCRefDataFreeList SingleUseLock SyncBlockCache SystemDomainDelayedUnloadList ThreadIdDispenser DebuggerMutex End Crst TypeIDMap AcquiredBefore UniqueStack End Crst TypeEquivalenceMap AcquiredBefore LoaderHeap End Crst UMEntryThunkFreeListLock End Crst UniqueStack AcquiredBefore LoaderHeap End Crst UnresolvedClassLock AcquiredBefore AvailableParamTypes IbcProfile JumpStubCache End Crst WrapperTemplate AcquiredBefore IbcProfile End Crst UMEntryThunkCache AcquiredBefore LoaderHeap End Crst PinnedByrefValidation End Crst VSDIndirectionCellLock AcquiredBefore LoaderHeap End Crst MulticoreJitHash End Crst MulticoreJitManager AcquiredBefore MulticoreJitHash ThreadStore End Crst StackSampler End Crst InlineTrackingMap AcquiredBefore IbcProfile End Crst JitInlineTrackingMap AcquiredBefore CodeVersioning ThreadStore MethodDescBackpatchInfoTracker End Crst EventPipe AcquiredAfter PendingTypeLoadEntry AcquiredBefore ThreadIdDispenser ThreadStore DomainLocalBlock InstMethodHashTable End Crst NotifyGdb End Crst ReadyToRunEntryPointToMethodDescMap AcquiredBefore ExecuteManRangeLock UniqueStack End Crst TieredCompilation AcquiredAfter CodeVersioning AcquiredBefore FuncPtrStubs End Crst COMCallWrapper End Crst MethodDescBackpatchInfoTracker AcquiredBefore FuncPtrStubs AcquiredAfter ReJITGlobalRequest ThreadStore SystemDomain End Crst NativeImageEagerFixups End Crst NativeImageLoad End Crst PgoData AcquiredBefore LoaderHeap End ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/OpCodeGen.pl ================================================ # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. # # OpCodeGen.pl # # PERL script used to generate the numbering of the reference opcodes # #use strict 'vars'; #use strict 'subs'; #use strict 'refs'; my $ret = 0; my %opcodeEnum; my %oneByte; my %twoByte; my %controlFlow; my @singleByteArg; my %stackbehav; my %opcodetype; my %operandtype; my %opcodes; my $popstate; my $pushstate; $ctrlflowcount = 0; $count = 0; my @lowercaseAlphabet = ('a'..'z','0'..'9'); my %upcaseAlphabet = (); foreach $letter (@lowercaseAlphabet) { $j = $letter; $j=~tr/a-z/A-Z/; $upcaseAlphabet{$letter}=$j; } $license = "// Licensed to the .NET Foundation under one or more agreements.\n"; $license .= "// The .NET Foundation licenses this file to you under the MIT license.\n"; $startHeaderComment = "/*============================================================\n**\n"; $endHeaderComment = "**\n** THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT BY HAND!\n"; $endHeaderComment .= "** See \$(RepoRoot)\\src\\inc\\OpCodeGen.pl for more information.**\n"; $endHeaderComment .= "==============================================================*/\n\n"; $usingAndRefEmitNmsp = "namespace System.Reflection.Emit\n{\n\n"; $obsoleteAttr = " [Obsolete(\"This API has been deprecated. https://go.microsoft.com/fwlink/?linkid=14202\")]\n"; # Open source file and target files open (OPCODE, "opcode.def") or die "Couldn't open opcode.def: $!\n"; open (OUTPUT, ">OpCodes.cs") or die "Couldn't open OpCodes.cs: $!\n"; open (FCOUTPUT, ">FlowControl.cs") or die "Couldn't open FlowControl.cs: $!\n"; open (SOUTPUT, ">StackBehaviour.cs") or die "Couldn't open StackBehaviour.cs: $!\n"; open (OCOUTPUT, ">OpCodeType.cs") or die "Couldn't open OpCodeType.cs: $!\n"; open (OPOUTPUT, ">OperandType.cs") or die "Couldn't open OperandType.cs: $!\n"; print OUTPUT $license; print OUTPUT $startHeaderComment; print OUTPUT "** Class: OpCodes\n"; print OUTPUT "**\n"; print OUTPUT "** Purpose: Exposes all of the IL instructions supported by the runtime.\n"; print OUTPUT $endHeaderComment; print OUTPUT $usingAndRefEmitNmsp; print FCOUTPUT $license; print FCOUTPUT $startHeaderComment; print FCOUTPUT "** Enumeration: FlowControl\n"; print FCOUTPUT "**\n"; print FCOUTPUT "** Purpose: Exposes FlowControl Attribute of IL.\n"; print FCOUTPUT $endHeaderComment; print FCOUTPUT $usingAndRefEmitNmsp; print FCOUTPUT " public enum FlowControl\n {\n"; print SOUTPUT $license; print SOUTPUT $startHeaderComment; print SOUTPUT "** Enumeration: StackBehaviour\n"; print SOUTPUT "**\n"; print SOUTPUT "** Purpose: Exposes StackBehaviour Attribute of IL.\n"; print SOUTPUT $endHeaderComment; print SOUTPUT $usingAndRefEmitNmsp; print SOUTPUT " public enum StackBehaviour\n {\n"; print OCOUTPUT $license; print OCOUTPUT $startHeaderComment; print OCOUTPUT "** Enumeration: OpCodeType\n"; print OCOUTPUT "**\n"; print OCOUTPUT "** Purpose: Exposes OpCodeType Attribute of IL.\n"; print OCOUTPUT $endHeaderComment; print OCOUTPUT $usingAndRefEmitNmsp; print OCOUTPUT " public enum OpCodeType\n {\n"; print OPOUTPUT $license; print OPOUTPUT $startHeaderComment; print OPOUTPUT "** Enumeration: OperandType\n"; print OPOUTPUT "**\n"; print OPOUTPUT "** Purpose: Exposes OperandType Attribute of IL.\n"; print OPOUTPUT $endHeaderComment; print OPOUTPUT $usingAndRefEmitNmsp; print OPOUTPUT " public enum OperandType\n {\n"; while () { # Process only OPDEF(....) lines if (/OPDEF\(\s*/) { chop; # Strip off trailing CR s/^OPDEF\(\s*//; # Strip off "OP(" s/,\s*/,/g; # Remove whitespace s/\).*$//; # Strip off ")" and everything behind it at end # Split the line up into its basic parts ($enumname, $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl) = split(/,/); $s1 =~ s/0x//; $s1 = hex($s1); $s2 =~ s/0x//; $s2 = hex($s2); if ($size == 0) { next; } next if ($enumname =~ /UNUSED/); #Remove the prefix $enumname=~s/CEE_//g; #Convert name to our casing convention $enumname=~tr/A-Z/a-z/; $enumname=~s/^(.)/\u$1/g; $enumname=~s/_(.)/_\u$1/g; #Convert pop to our casing convention $pop=~tr/A-Z/a-z/; $pop=~s/^(.)/\u$1/g; $pop=~s/_(.)/_\u$1/g; #Convert push to our casing convention $push=~tr/A-Z/a-z/; $push=~s/^(.)/\u$1/g; $push=~s/_(.)/_\u$1/g; #Convert operand to our casing convention #$operand=~tr/A-Z/a-z/; #$operand=~s/^(.)/\u$1/g; #$operand=~s/_(.)/_\u$1/g; #Remove the I prefix on type $type=~s/I//g; #Convert Type to our casing convention $type=~tr/A-Z/a-z/; $type=~s/^(.)/\u$1/g; $type=~s/_(.)/_\u$1/g; #Convert ctrl to our casing convention $ctrl=~tr/A-Z/a-z/; $ctrl=~s/^(.)/\u$1/g; $ctrl=~s/_(.)/_\u$1/g; # Make a list of the flow Control type # Make a list of the opcodes and their values if ($opcodes{$enumname}) { } elsif ($size == 1) { $opcodes{$enumname} = $s2; } elsif ($size == 2) { $opcodes{$enumname} = ($s2 + 256 * $s1); } #Make a list of the instructions which only take one-byte arguments if ($enumname =~ /^.*_S$/) { #but exclude the deprecated expressions (sometimes spelled "depricated") if (!($enumname=~/^Depr.cated.*/)) { my $caseStatement = sprintf(" case %-20s: \n", $enumname); push(@singleByteArg, $caseStatement); } } #make a list of the control Flow Types if ($controlFlow{$ctrl}) { #printf("DUPE Control Flow\n"); } else { $controlFlow{$ctrl} = $ctrlflowcount; $ctrlflowcount++; } $ctrlflowcount = 0; #make a list of the StackBehaviour Types $pop=~s/\+/_/g; if ($stackbehav{$pop}) { #printf("DUPE stack behaviour pop\n"); } else { $stackbehav{$pop} = $ctrlflowcount; $ctrlflowcount++; } #make a list of the StackBehaviour Types $push=~s/\+/_/g; if ($stackbehav{$push}) { #printf("DUPE stack behaviour push\n"); } else { $stackbehav{$push} = $ctrlflowcount; $ctrlflowcount++; } #make a list of operand types if ($operandtype{$operand}) { #printf("DUPE operand type\n"); } else { $operandtype{$operand} = $ctrlflowcount; $ctrlflowcount++; } #make a list of opcode types if ($opcodetype{$type}) { #printf("DUPE opcode type\n"); } else { $opcodetype{$type} = $ctrlflowcount; $ctrlflowcount++; } my $opcodeName = $enumname; # Tailcall OpCode enum name does not comply with convention # that all enum names are exactly the same as names in opcode.def # file less leading CEE_ and changed casing convention $enumname = substr $enumname, 0, 4 unless $enumname !~ m/Tailcall$/; # If string name ends with dot OpCode enum name ends with underscore $enumname .= "_" unless $stringname !~ m/\."$/; printf(" OpCode name:%20s,\t\tEnum label:%20s,\t\tString name:%20s\n", $opcodeName, $enumname, $stringname); if ($stringname eq "arglist") { print "This is arglist----------\n"; } my $lineEnum; if ($size == 1) { $lineEnum = sprintf(" %s = 0x%.2x,\n", $enumname, $s2); $opcodeEnum{$s2} = $lineEnum; } elsif ($size == 2) { $lineEnum = sprintf(" %s = 0x%.4x,\n", $enumname, $s2 + 256 * $s1); $opcodeEnum{$s2 + 256 * $s1} = $lineEnum; } my $line; $line = sprintf(" public static readonly OpCode %s = new OpCode(OpCodeValues.%s,\n", $opcodeName, $enumname); $line .= sprintf(" ((int)OperandType.%s) |\n", $operand); $line .= sprintf(" ((int)FlowControl.%s << OpCode.FlowControlShift) |\n", $ctrl); $line .= sprintf(" ((int)OpCodeType.%s << OpCode.OpCodeTypeShift) |\n", $type); $line .= sprintf(" ((int)StackBehaviour.%s << OpCode.StackBehaviourPopShift) |\n", $pop); $line .= sprintf(" ((int)StackBehaviour.%s << OpCode.StackBehaviourPushShift) |\n", $push); $popstate = 0; if($pop eq "Pop0" || $pop eq "Varpop") { $popstate = 0; } elsif ($pop eq "Pop1" || $pop eq "Popi" || $pop eq "Popref") { $popstate = $popstate -1; } elsif ($pop eq "Pop1_pop1" || $pop eq "Popi_pop1" || $pop eq "Popi_popi" || $pop eq "Popi_popi8" || $pop eq "Popi_popr4" || $pop eq "Popi_popr8" || $pop eq "Popref_pop1" || $pop eq "Popref_popi") { $popstate = $popstate -2; } elsif ($pop eq "Popi_popi_popi" || $pop eq "Popref_popi_popi" || $pop eq "Popref_popi_popi8" || $pop eq "Popref_popi_popr4" || $pop eq "Popref_popi_popr8" || $pop eq "Popref_popi_popref" || $pop eq "Popref_popi_pop1") { $popstate = $popstate -3; } if ($push eq "Push1" || $push eq "Pushi" ||$push eq "Pushi8" ||$push eq "Pushr4" ||$push eq "Pushr8" ||$push eq "Pushref") { $popstate = $popstate + 1; } elsif($push eq "Push1_push1") { $popstate = $popstate + 2; } $line .= sprintf(" (%s << OpCode.SizeShift) |\n", $size); if ($ctrl =~ m/Return/ || $ctrl =~ m/^Branch/ || $ctrl =~ m/^Throw/ || $enumname =~ m/Jmp/){ $line .= sprintf(" OpCode.EndsUncondJmpBlkFlag |\n", $size); } $line .= sprintf(" (%d << OpCode.StackChangeShift)\n", $popstate); $line .= sprintf(" );\n\n"); if ($size == 1) { if ($oneByte{$s2}) { printf("Error opcode 0x%x already defined!\n", $s2); print " Old = $oneByte{$s2}"; print " New = $line"; $ret = -1; } $oneByte{$s2} = $line; } elsif ($size == 2) { if ($twoByte{$s2}) { printf("Error opcode 0x%x%x already defined!\n", $s1, $s2); print " Old = $oneByte{$s2}"; print " New = $line"; $ret = -1; } $twoByte{$s2 + 256 * $s1} = $line; } else { $line .= "\n"; push(@deprecated, $line); printf("deprecated code!\n"); } $count++; } } # Generate the Flow Control enum $ctrlflowcount = 0; foreach $key (sort {$a cmp $b} keys (%controlFlow)) { print FCOUTPUT " $key"; print FCOUTPUT " = $ctrlflowcount,\n"; $ctrlflowcount++; if ($key =~ m/Next/){ print FCOUTPUT $obsoleteAttr; print FCOUTPUT " Phi"; print FCOUTPUT " = $ctrlflowcount,\n"; $ctrlflowcount++; } } #end the flowcontrol enum print FCOUTPUT " }\n}\n"; # Generate the StackBehaviour enum $ctrlflowcount = 0; foreach $key (sort {$a cmp $b} keys (%stackbehav)) { if ($key !~ m/Popref_popi_pop1/){ print SOUTPUT " $key"; print SOUTPUT " = $ctrlflowcount,\n"; $ctrlflowcount++; } } print SOUTPUT " Popref_popi_pop1 = $ctrlflowcount,\n"; #end the StackBehaviour enum print SOUTPUT " }\n}\n"; # Generate OpCodeType enum $ctrlflowcount = 0; foreach $key (sort {$a cmp $b} keys (%opcodetype)) { if ($ctrlflowcount == 0){ print OCOUTPUT $obsoleteAttr; print OCOUTPUT " Annotation = 0,\n"; $ctrlflowcount++; } print OCOUTPUT " $key"; print OCOUTPUT " = $ctrlflowcount,\n"; $ctrlflowcount++; } # end the OpCodeType enum print OCOUTPUT " }\n}\n"; # Generate OperandType enum $ctrlflowcount = 0; foreach $key (sort {$a cmp $b} keys (%operandtype)) { print OPOUTPUT " $key"; print OPOUTPUT " = $ctrlflowcount,\n"; $ctrlflowcount++; if ($key =~ m/InlineNone/){ print OPOUTPUT $obsoleteAttr; print OPOUTPUT " InlinePhi = 6,\n"; $ctrlflowcount++; } if ($key =~ m/^InlineR$/){ $ctrlflowcount++; } } #end the OperandType enum print OPOUTPUT " }\n}\n"; # Generate OpCodeValues internal enum print OUTPUT " ///\n"; print OUTPUT " /// Internal enum OpCodeValues for opcode values.\n"; print OUTPUT " ///\n"; print OUTPUT " ///\n"; print OUTPUT " /// Note that the value names are used to construct publicly visible\n"; print OUTPUT " /// ilasm-compatible opcode names, so their exact form is important!\n"; print OUTPUT " ///\n"; print OUTPUT " internal enum OpCodeValues\n"; print OUTPUT " {\n"; foreach $opcodeValue (sort {$a <=> $b} keys(%opcodeEnum)) { print OUTPUT $opcodeEnum{$opcodeValue}; } # End generating OpCodeValues internal enum print OUTPUT " }\n\n"; # Generate public OpCodes class print OUTPUT " /// \n"; print OUTPUT " /// \n"; print OUTPUT " /// The IL instruction opcodes supported by the runtime.\n"; print OUTPUT " /// The Specification of IL Instruction describes each Opcode.\n"; print OUTPUT " /// \n"; print OUTPUT " /// \n"; print OUTPUT " /// \n"; print OUTPUT " public class OpCodes\n"; print OUTPUT " {\n\n";; print OUTPUT " private OpCodes()\n {\n }\n\n"; my $opcode; my $lastOp = -1; foreach $opcode (sort {$a <=> $b} keys(%oneByte)) { printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); print OUTPUT $oneByte{$opcode}; $lastOp = $opcode; } $lastOp = -1; foreach $opcode (sort {$a <=> $b} keys(%twoByte)) { printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); print OUTPUT $twoByte{$opcode}; $lastOp = $opcode; } print OUTPUT "\n";; print OUTPUT " public static bool TakesSingleByteArgument(OpCode inst)\n"; print OUTPUT " {\n"; print OUTPUT " switch (inst.OperandType)\n"; print OUTPUT " {\n"; print OUTPUT " case OperandType.ShortInlineBrTarget:\n"; print OUTPUT " case OperandType.ShortInlineI:\n"; print OUTPUT " case OperandType.ShortInlineVar:\n"; print OUTPUT " return true;\n"; print OUTPUT " }\n"; print OUTPUT " return false;\n"; print OUTPUT " }\n"; # End Generate public OpCodes class and close namespace print OUTPUT " }\n}\n"; exit($ret); ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/allocacheck.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*********************************************************************/ /* AllocaCheck */ /*********************************************************************/ /* check for alloca overruns (which otherwise are hard to track down and often only repro on optimized builds). USAGE: void foo() { ALLOCA_CHECK(); // Declare at function level scope .... void* mem = ALLOCA(size); // does an alloca, } // destructor of ALLOCA_CHECK for buffer overruns. */ /* */ /*********************************************************************/ #ifndef AllocaCheck_h #define AllocaCheck_h #include // for alloca itself #if defined(assert) && !defined(_ASSERTE) #define _ASSERTE assert #endif #if defined(_DEBUG) || defined(DEBUG) /*********************************************************************/ class AllocaCheck { public: enum { CheckBytes = 0xCCCDCECF, }; struct AllocaSentinel { int check; AllocaSentinel* next; }; public: /***************************************************/ AllocaCheck() { sentinels = 0; } ~AllocaCheck() { AllocaSentinel* ptr = sentinels; while (ptr != 0) { if (ptr->check != (int)CheckBytes) _ASSERTE(!"alloca buffer overrun"); ptr = ptr->next; } } void* add(void* allocaBuff, unsigned size) { AllocaSentinel* newSentinel = (AllocaSentinel*) ((char*) allocaBuff + size); newSentinel->check = CheckBytes; newSentinel->next = sentinels; sentinels = newSentinel; memset(allocaBuff, 0xDD, size); return allocaBuff; } private: AllocaSentinel* sentinels; }; #define ALLOCA_CHECK() AllocaCheck __allocaChecker #define ALLOCA(size) __allocaChecker.add(_alloca(size+sizeof(AllocaCheck::AllocaSentinel)), size); #else #define ALLOCA_CHECK() #define ALLOCA(size) _alloca(size) #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/arrayholder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. template class ArrayHolder { public: ArrayHolder(T *ptr) : m_ptr(ptr) { } ~ArrayHolder() { Clear(); } ArrayHolder(const ArrayHolder &rhs) { m_ptr = const_cast(&rhs)->Detach(); } ArrayHolder &operator=(T *ptr) { Clear(); m_ptr = ptr; return *this; } const T &operator[](int i) const { return m_ptr[i]; } T &operator[](int i) { return m_ptr[i]; } operator const T *() const { return m_ptr; } operator T *() { return m_ptr; } T **operator&() { return &m_ptr; } T *GetPtr() { return m_ptr; } T *Detach() { T *ret = m_ptr; m_ptr = NULL; return ret; } private: void Clear() { if (m_ptr) { delete [] m_ptr; m_ptr = NULL; } } private: T *m_ptr; }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/arraylist.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef ARRAYLIST_H_ #define ARRAYLIST_H_ #include #include #include // offsetof // // ArrayList is a simple class which is used to contain a growable // list of pointers, stored in chunks. Modification is by appending // only currently. Access is by index (efficient if the number of // elements stays small) and iteration (efficient in all cases). // // An important property of an ArrayList is that the list remains // coherent while it is being modified. This means that readers // never need to lock when accessing it. // #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4200) // Disable zero-sized array warning #endif class ArrayListBase { public: enum { ARRAY_BLOCK_SIZE_START = 5, }; private: struct ArrayListBlock { SPTR(ArrayListBlock) m_next; DWORD m_blockSize; #ifdef HOST_64BIT DWORD m_padding; #endif PTR_VOID m_array[0]; #ifdef DACCESS_COMPILE static ULONG32 DacSize(TADDR addr) { LIMITED_METHOD_CONTRACT; return offsetof(ArrayListBlock, m_array) + (*PTR_DWORD(addr + offsetof(ArrayListBlock, m_blockSize)) * sizeof(void*)); } #endif }; typedef SPTR(ArrayListBlock) PTR_ArrayListBlock; struct FirstArrayListBlock { PTR_ArrayListBlock m_next; DWORD m_blockSize; #ifdef HOST_64BIT DWORD m_padding; #endif void * m_array[ARRAY_BLOCK_SIZE_START]; }; typedef DPTR(FirstArrayListBlock) PTR_FirstArrayListBlock; DWORD m_count; FirstArrayListBlock m_firstBlock; public: PTR_VOID *GetPtr(DWORD index) const; PTR_VOID Get(DWORD index) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return *GetPtr(index); } void Set(DWORD index, PTR_VOID element) { WRAPPER_NO_CONTRACT; *GetPtr(index) = element; } DWORD GetCount() const { LIMITED_METHOD_DAC_CONTRACT; return m_count; } HRESULT Append(void *element); enum { NOT_FOUND = -1 }; DWORD FindElement(DWORD start, PTR_VOID element) const; void Clear(); void Init() { LIMITED_METHOD_CONTRACT; m_count = 0; m_firstBlock.m_next = NULL; m_firstBlock.m_blockSize = ARRAY_BLOCK_SIZE_START; } void Destroy() { WRAPPER_NO_CONTRACT; Clear(); } #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif class ConstIterator; class Iterator { friend class ArrayListBase; friend class ConstIterator; public: BOOL Next(); void SetEmpty() { LIMITED_METHOD_CONTRACT; m_block = NULL; m_index = (DWORD)-1; m_remaining = 0; m_total = 0; } PTR_VOID GetElement() {LIMITED_METHOD_DAC_CONTRACT; return m_block->m_array[m_index]; } PTR_VOID * GetElementPtr() {LIMITED_METHOD_CONTRACT; return m_block->m_array + m_index; } DWORD GetIndex() {LIMITED_METHOD_CONTRACT; return m_index + m_total; } void *GetBlock() { return m_block; } private: ArrayListBlock* m_block; DWORD m_index; DWORD m_remaining; DWORD m_total; static Iterator Create(ArrayListBlock* block, DWORD remaining) { LIMITED_METHOD_DAC_CONTRACT; Iterator i; i.m_block = block; i.m_index = (DWORD) -1; i.m_remaining = remaining; i.m_total = 0; return i; } }; class ConstIterator { public: ConstIterator(ArrayListBlock *pBlock, DWORD dwRemaining) : m_iterator(Iterator::Create(pBlock, dwRemaining)) { } BOOL Next() { WRAPPER_NO_CONTRACT; return m_iterator.Next(); } PTR_VOID GetElement() { WRAPPER_NO_CONTRACT; return m_iterator.GetElement(); } private: Iterator m_iterator; }; Iterator Iterate() { WRAPPER_NO_CONTRACT; return Iterator::Create((ArrayListBlock*)&m_firstBlock, m_count); } ConstIterator Iterate() const { // Const cast is safe because ConstIterator does not expose any way to modify the block ArrayListBlock *pFirstBlock = const_cast(reinterpret_cast(&m_firstBlock)); return ConstIterator(pFirstBlock, m_count); } // BlockIterator is used for only memory walking, such as prejit save/fixup. // It is not appropriate for other more typical ArrayList use. class BlockIterator { private: ArrayListBlock *m_block; DWORD m_remaining; friend class ArrayListBase; BlockIterator(ArrayListBlock *block, DWORD remaining) : m_block(block), m_remaining(remaining) { } public: BOOL Next() { if (m_block != NULL) { // Prevent m_remaining from underflowing - we can have completely empty block at the end. if (m_remaining > m_block->m_blockSize) m_remaining -= m_block->m_blockSize; else m_remaining = 0; m_block = m_block->m_next; } return m_block != NULL; } #ifndef DACCESS_COMPILE void ClearUnusedMemory() { if (m_remaining < m_block->m_blockSize) ZeroMemory(m_block->m_array + m_remaining, (m_block->m_blockSize - m_remaining) * sizeof(void*)); #ifdef HOST_64BIT m_block->m_padding = 0; #endif // HOST_64BIT } #endif // DACCESS_COMPILE void **GetNextPtr() { return (void **) &m_block->m_next; } void *GetBlock() { return m_block; } SIZE_T GetBlockSize() { return offsetof(ArrayListBlock, m_array) + (m_block->m_blockSize * sizeof(void*)); } }; void **GetInitialNextPtr() { return (void **) &m_firstBlock.m_next; } BlockIterator IterateBlocks() { return BlockIterator((ArrayListBlock *) &m_firstBlock, m_count); } }; class ArrayList : public ArrayListBase { public: #ifndef DACCESS_COMPILE ArrayList() { WRAPPER_NO_CONTRACT; Init(); } ~ArrayList() { WRAPPER_NO_CONTRACT; Destroy(); } #endif }; /* to be used as static variable - no constructor/destructor, assumes zero initialized memory */ class ArrayListStatic : public ArrayListBase { }; typedef DPTR(ArrayListStatic) PTR_ArrayListStatic; #ifdef _MSC_VER #pragma warning(pop) #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/assemblybinderutil.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // Contains helper types for assembly binding host infrastructure. #ifndef __ASSEMBLY_BINDER_UTIL_H__ #define __ASSEMBLY_BINDER_UTIL_H__ //===================================================================================================================== // Forward declarations typedef DPTR(BINDER_SPACE::Assembly) PTR_BINDER_SPACE_Assembly; typedef DPTR(AssemblyBinder) PTR_AssemblyBinder; //===================================================================================================================== #define VALIDATE_CONDITION(condition, fail_op) \ do { \ _ASSERTE((condition)); \ if (!(condition)) \ fail_op; \ } while (false) #define VALIDATE_ARG_RET(condition) VALIDATE_CONDITION(condition, return E_INVALIDARG) #endif // __ASSEMBLY_BINDER_UTIL_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/bitmask.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // -------------------------------------------------------------------------------- // BitMask.h // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // BitMask is an arbitrarily large sized bitfield which has optimal storage // for 32 bits or less. // Storage is proportional to the highest index which is set. // -------------------------------------------------------------------------------- #include #ifndef _BITMASK_H_ #define _BITMASK_H_ class BitMask { public: BitMask(); ~BitMask(); BOOL TestBit(int bit); void SetBit(int bit); void ClearBit(int bit); // returns true if any bit is set BOOL TestAnyBit(); void ClearAllBits(); // Allocation exposed for ngen save/fixup size_t GetAllocatedBlockOffset(); void *GetAllocatedBlock(); COUNT_T GetAllocatedBlockSize(); private: static const int BIT_SIZE_SHIFT = 5; static const int BIT_SIZE = (1<writer so be very careful // when taking this lock else you might deadlock your own thread! SimpleRWLock m_bitMaskLock; }; #include #endif // _BITMASK_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/bitmask.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // -------------------------------------------------------------------------------- // BitMask.inl // -------------------------------------------------------------------------------- #include #ifndef _BITMASK_INL_ #define _BITMASK_INL_ inline BOOL BitMask::IsArray() { LIMITED_METHOD_CONTRACT; return (m_mask&1) == 0; } // Indexing computations inline COUNT_T BitMask::BitToIndex(int bit) { LIMITED_METHOD_CONTRACT; // First word has one less bit due to tag return (bit+1) >> BIT_SIZE_SHIFT; } inline COUNT_T BitMask::BitToShift(int bit) { LIMITED_METHOD_CONTRACT; // First word has one less bit due to tag return (bit+1) & BIT_SIZE_MASK; } // Array access. Note the first array element is the count of the // rest of the elements inline COUNT_T *BitMask::GetMaskArray() { LIMITED_METHOD_CONTRACT; if (IsArray()) { CONSISTENCY_CHECK(CheckPointer(m_maskArray)); return m_maskArray+1; } else return &m_mask; } inline COUNT_T BitMask::GetMaskArraySize() { LIMITED_METHOD_CONTRACT; if (IsArray()) return *m_maskArray; else return 1; } inline void BitMask::GrowArray(COUNT_T newSize) { CONTRACTL { THROWS; } CONTRACTL_END; // Ensure we don't grow too often COUNT_T oldSize = GetMaskArraySize(); if (newSize <= oldSize) return; if (newSize < oldSize*2) newSize = oldSize*2; if (newSize < MIN_ARRAY_ALLOCATION) newSize = MIN_ARRAY_ALLOCATION; // Allocate new array COUNT_T *newArray = new COUNT_T [newSize+1]; *newArray = newSize; CopyMemory(newArray+1, GetMaskArray(), oldSize * sizeof(COUNT_T)); ZeroMemory(newArray+oldSize+1, (newSize - oldSize) * sizeof(COUNT_T)); if (IsArray()) delete [] m_maskArray; m_maskArray = newArray; } inline BitMask::BitMask() : m_mask(1) { LIMITED_METHOD_CONTRACT; } inline BitMask::~BitMask() { LIMITED_METHOD_CONTRACT; if (IsArray()) delete [] m_maskArray; } inline BOOL BitMask::TestBit(int bit) { LIMITED_METHOD_CONTRACT; COUNT_T index = BitToIndex(bit); if (index >= GetMaskArraySize()) return FALSE; return ( GetMaskArray()[index] >> BitToShift(bit) ) & 1; } inline void BitMask::SetBit(int bit) { CONTRACTL { THROWS; } CONTRACTL_END; COUNT_T index = BitToIndex(bit); if (index >= GetMaskArraySize()) GrowArray(index+1); GetMaskArray()[index] |= (1 << BitToShift(bit)); } inline void BitMask::ClearBit(int bit) { LIMITED_METHOD_CONTRACT; COUNT_T index = BitToIndex(bit); if (index >= GetMaskArraySize()) return; GetMaskArray()[index] &= ~(1 << BitToShift(bit)); } inline BOOL BitMask::TestAnyBit() { LIMITED_METHOD_CONTRACT; if (IsArray()) { COUNT_T *mask = m_maskArray+1; COUNT_T *maskEnd = mask + m_maskArray[0]; while (mask < maskEnd) { if (*mask != 0) return TRUE; mask++; } return FALSE; } else return m_mask != (COUNT_T) 1; } inline void BitMask::ClearAllBits() { LIMITED_METHOD_CONTRACT; if (IsArray()) delete [] m_maskArray; m_mask = 1; } inline size_t BitMask::GetAllocatedBlockOffset() { LIMITED_METHOD_CONTRACT; return offsetof(BitMask, m_maskArray); } inline void *BitMask::GetAllocatedBlock() { LIMITED_METHOD_CONTRACT; if (IsArray()) return m_maskArray; else return NULL; } inline COUNT_T BitMask::GetAllocatedBlockSize() { LIMITED_METHOD_CONTRACT; if (IsArray()) return (GetMaskArraySize()+1) * sizeof(COUNT_T); else return 0; } ///////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////// inline SynchronizedBitMask::SynchronizedBitMask() : m_bitMaskLock(PREEMPTIVE, LOCK_TYPE_DEFAULT) { LIMITED_METHOD_CONTRACT; } inline BOOL SynchronizedBitMask::TestBit(int bit) { CONTRACTL { NOTHROW; MODE_ANY; CAN_TAKE_LOCK; } CONTRACTL_END; SimpleReadLockHolder holder(&m_bitMaskLock); return m_bitMask.TestBit(bit); } inline void SynchronizedBitMask::SetBit(int bit) { CONTRACTL { THROWS; MODE_ANY; CAN_TAKE_LOCK; } CONTRACTL_END; SimpleWriteLockHolder holder(&m_bitMaskLock); m_bitMask.SetBit(bit); } inline void SynchronizedBitMask::ClearBit(int bit) { CONTRACTL { NOTHROW; MODE_ANY; CAN_TAKE_LOCK; } CONTRACTL_END; SimpleWriteLockHolder holder(&m_bitMaskLock); m_bitMask.ClearBit(bit); } inline BOOL SynchronizedBitMask::TestAnyBit() { CONTRACTL { NOTHROW; MODE_ANY; CAN_TAKE_LOCK; } CONTRACTL_END; SimpleReadLockHolder holder(&m_bitMaskLock); return m_bitMask.TestAnyBit(); } inline void SynchronizedBitMask::ClearAllBits() { CONTRACTL { NOTHROW; MODE_ANY; CAN_TAKE_LOCK; } CONTRACTL_END; SimpleWriteLockHolder holder(&m_bitMaskLock); m_bitMask.ClearAllBits(); } #endif // _BITMASK_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/bitposition.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _BITPOSITION_H_ #define _BITPOSITION_H_ //------------------------------------------------------------------------ // BitPosition: Return the position of the single bit that is set in 'value'. // // Return Value: // The position (0 is LSB) of bit that is set in 'value' // // Notes: // 'value' must have exactly one bit set. // It performs the "TrailingZeroCount" operation using intrinsics. // inline unsigned BitPosition(unsigned value) { _ASSERTE((value != 0) && ((value & (value-1)) == 0)); DWORD index; BitScanForward(&index, value); return index; } #ifdef HOST_64BIT //------------------------------------------------------------------------ // BitPosition: Return the position of the single bit that is set in 'value'. // // Return Value: // The position (0 is LSB) of bit that is set in 'value' // // Notes: // 'value' must have exactly one bit set. // It performs the "TrailingZeroCount" operation using intrinsics. // inline unsigned BitPosition(unsigned __int64 value) { _ASSERTE((value != 0) && ((value & (value-1)) == 0)); DWORD index; BitScanForward64(&index, value); return index; } #endif // HOST_64BIT #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/bitvector.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************/ /* BitVector.h */ /***************************************************************************/ // Routines to support a growable bitvector /***************************************************************************/ #ifndef BITVECTOR_H #define BITVECTOR_H 1 #ifndef LIMITED_METHOD_CONTRACT #define LIMITED_METHOD_CONTRACT #define UNDEF_LIMITED_METHOD_CONTRACT #endif #ifndef WRAPPER_NO_CONTRACT #define WRAPPER_NO_CONTRACT #define UNDEF_WRAPPER_NO_CONTRACT #endif #ifndef SUPPORTS_DAC #define SUPPORTS_DAC #define UNDEF_SUPPORTS_DAC #endif #ifndef _ASSERTE #define _ASSERTE(x) #define UNDEF_ASSERTE #endif #define USE_BITVECTOR 1 #if USE_BITVECTOR /* The bitvector class is meant to be a drop in replacement for an integer (that is you use it like an integer), however it grows as needed. Features: plug compatible with normal integers; grows as needed Optimized for the small case when the vector fits in machine word Uses one machine word if vector fits in machine word (minus a bit) Some caveates: You should use mutator operators &=, |= ... instead of the non-mutators whenever possible to avoid creating a temps Specifically did NOT supply automatic coercions to and from short types so that the programmer is aware of when code was being injected on their behalf. The upshot of this is that you have to use the BitVector() toUnsigned() to convert */ /***************************************************************************/ class BitVector { // Set this to be unsigned char to do testing, should be UINT_PTR for real life typedef UINT_PTR ChunkType; // The size of integer type that the machine can operate on directly // typedef BYTE ChunkType; // Use for testing // Maximum number of bits in our bitvector #define MAX_PTRARG_OFS 1024 enum { IS_BIG = 1, // The low bit is used to discrimate m_val and m_vals CHUNK_BITS = sizeof(ChunkType)*8, // The number of bits that we can manipuate as a chunk SMALL_BITS = CHUNK_BITS - 1, // The number of bits we can fit in the small representation // SMALL_BITS = 5, // TESTING ONLY: The number of bits we can fit in the small representation VALS_COUNT = MAX_PTRARG_OFS / CHUNK_BITS, // The number of ChunkType elements in the Vals array }; public: BitVector() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; m_val = 0; } BOOL isBig() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return ((m_val & IS_BIG) != 0); } void toBig() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; if (!isBig()) { doBigInit(smallBits()); } } explicit BitVector(ChunkType arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (arg > MaxVal) { doBigInit(arg); } else { m_val = ChunkType(arg << 1); } } BitVector(ChunkType arg, UINT shift) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if ((arg > MaxVal) || (shift >= SMALL_BITS) || (arg > (MaxVal >> shift))) { doBigInit(arg); doBigLeftShiftAssign(shift); } else { m_val = ChunkType(arg << (shift+1)); } } #define CONSTRUCT_ptrArgTP(arg,shift) BitVector((arg), (shift)) BitVector(const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (arg.isBig()) { doBigInit(arg); } else { m_val = arg.m_val; } } void operator <<=(unsigned shift) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if ((m_val == 0) || (shift == 0)) // Zero is a special case, don't need to do anything return; if (isBig() || (shift >= SMALL_BITS) || (m_val > (MaxVal >> (shift-1)))) { doBigLeftShiftAssign(shift); } else { m_val <<= shift; } } void operator >>=(unsigned shift) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (isBig()) { doBigRightShiftAssign(shift); } else { m_val >>= shift; m_val &= ~IS_BIG; // clear the isBig bit if it got set } } void operator |=(const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (((m_val | arg.m_val) & IS_BIG) != 0) { doBigOrAssign(arg); } else { m_val |= arg.m_val; } } // Note that this is set difference, not subtration void operator -=(const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (((m_val | arg.m_val) & IS_BIG) != 0) { doBigDiffAssign(arg); } else { m_val &= ~arg.m_val; } } void operator &=(const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (((m_val | arg.m_val) & IS_BIG) != 0) { doBigAndAssign(arg); } else { m_val &= arg.m_val; } } friend void setDiff(BitVector& target, const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; target -= arg; } friend BOOL intersect(const BitVector& arg1, const BitVector& arg2) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (((arg1.m_val | arg2.m_val) & IS_BIG) != 0) { return arg1.doBigIntersect(arg2); } else { return ((arg1.m_val & arg2.m_val) != 0); } } BOOL operator ==(const BitVector& arg) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if ((m_val | arg.m_val) & IS_BIG) { return doBigEquals(arg); } else { return m_val == arg.m_val; } } BOOL operator !=(const BitVector& arg) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return !(*this == arg); } friend ChunkType toUnsigned(const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (arg.isBig()) { return arg.m_vals.m_chunks[0]; // Note truncation } else { return arg.smallBits(); } } // Note that we require the invariant that zero is always stored in the // small form so that this works bitvector is zero iff (m_val == 0) friend BOOL isZero(const BitVector& arg) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return arg.m_val == 0; } /* currently only used in asserts */ BitVector operator &(const BitVector& arg) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; BitVector ret = *this; ret &= arg; return ret; } int NumBits() const; private: static const ChunkType MaxVal = ((ChunkType)1 << SMALL_BITS) - 1; // Maximum value that can be stored in m_val // This is the structure that we use when the bit vector overflows. // It is a simple vector. struct Vals { unsigned m_encodedLength; // An encoding of the current length of the 'm_chunks' array ChunkType m_chunks[VALS_COUNT]; BOOL isBig() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return ((m_encodedLength & IS_BIG) != 0); } unsigned GetLength() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; if (isBig()) { unsigned length = (m_encodedLength >> 1); _ASSERTE(length > 0); return length; } else { return 0; } } void SetLength(unsigned length) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; _ASSERTE(length > 0); _ASSERTE(length <= VALS_COUNT); m_encodedLength = (ChunkType) (length << 1); m_encodedLength |= (ChunkType) IS_BIG; } }; // // This is the instance data for the bitvector // // We discrimininate on this union { ChunkType m_val; // if m_val bit 0 is false, then bits 1-N are the bit vector Vals m_vals; // if m_val bit 1 is true, then use Vals }; ChunkType smallBits() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; _ASSERTE(!isBig()); return (m_val >> 1); } #ifdef STRIKE void doBigInit(ChunkType arg) {} #else void doBigInit(ChunkType arg); #endif void doBigInit(const BitVector& arg); void doBigLeftShiftAssign(unsigned arg); void doBigRightShiftAssign(unsigned arg); void doBigDiffAssign(const BitVector&); void doBigAndAssign(const BitVector&); void doBigOrAssign(const BitVector& arg); BOOL doBigEquals(const BitVector&) const; BOOL doBigIntersect(const BitVector&) const; }; typedef BitVector ptrArgTP; #else // !USE_BITVECTOR typedef unsigned __int64 ptrArgTP; // Maximum number of bits in our bitvector #define MAX_PTRARG_OFS (sizeof(ptrArgTP) * 8) #define CONSTRUCT_ptrArgTP(arg,shift) (((ptrArgTP) (arg)) << (shift)) inline BOOL isZero(const ptrArgTP& arg) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return (arg == 0); } inline ptrArgTP toUnsigned(const ptrArgTP& arg) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return arg; } inline void setDiff(ptrArgTP& target, const ptrArgTP& arg) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; target &= ~arg; } inline BOOL intersect(const ptrArgTP arg1, const ptrArgTP arg2) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return ((arg1 & arg2) != 0); } #endif // !USE_BITVECTOR #ifdef UNDEF_LIMITED_METHOD_CONTRACT #undef LIMITED_METHOD_CONTRACT #undef UNDEF_LIMITED_METHOD_CONTRACT #endif #ifdef UNDEF_WRAPPER_NO_CONTRACT #undef WRAPPER_NO_CONTRACT #undef UNDEF_WRAPPER_NO_CONTRACT #endif #ifdef UNDEF_SUPPORTS_DAC #undef SUPPORTS_DAC #undef UNDEF_SUPPORTS_DAC #endif #ifdef UNDEF_ASSERTE #undef _ASSERTE #undef UNDEF_ASSERTE #endif #endif // BITVECTOR_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/blobfetcher.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // CBlobFetcher - it fetches binary chunks, similar to new, but more controlled // // Fast, dynamic, memory management which doesn't relocate blocks // m_pIndex has array of pillars, where each pillar starts off empty and has // just-in-time allocation. As each pillar fills up, we move to the next pillar // If the entire array of pillars fill up, we need to allocate a new array and // copy the pillars over. But the actual data returned from GetBlock() never // gets moved. So everyone's happy. // //***************************************************************************** #ifndef __BLOB_FETCHER_H_ #define __BLOB_FETCHER_H_ #include class CBlobFetcher { protected: class CPillar { public: CPillar(); ~CPillar(); void SetAllocateSize(unsigned nSize); unsigned GetAllocateSize() const; char* MakeNewBlock(unsigned len, unsigned pad); void StealDataFrom(CPillar & src); unsigned GetDataLen() const; char* GetRawDataStart(); BOOL Contains(_In_ char *ptr); ULONG32 GetOffset(_In_ char *ptr); protected: unsigned m_nTargetSize; // when we allocate, make it this large // Make these public so CBlobFetcher can do easy manipulation public: char* m_dataAlloc; char* m_dataStart; char* m_dataCur; char* m_dataEnd; }; CPillar * m_pIndex; // array of pillars unsigned m_nIndexMax; // actual size of m_ppIndex unsigned m_nIndexUsed; // current pillar, so start at 0 unsigned m_nDataLen; // sum of all pillars' lengths // Don't allow these because they'll mess up the ownership CBlobFetcher(const CBlobFetcher & src); CBlobFetcher& operator=(const CBlobFetcher & src); public: #if defined(HOST_64BIT) // needs to be 64 so that we can purposefully cache align code in ngen'd images enum { maxAlign = 64 }; // maximum alignment we support #else enum { maxAlign = 32 }; // maximum alignment we support #endif CBlobFetcher(); ~CBlobFetcher(); // get a block to write on (use instead of write to avoid copy) char * MakeNewBlock(unsigned int nSize, unsigned align=1); // Index segment as if this were linear char * ComputePointer(unsigned offset) const; // Determine if pointer came from this fetcher BOOL ContainsPointer(_In_ char *ptr) const; // Find an offset as if this were linear unsigned ComputeOffset(_In_ char *ptr) const; // Write out the section to the stream HRESULT Write(HANDLE file); // Write out the section to memory HRESULT WriteMem(void ** pMem); // Get the total length of all our data (sum of all the pillar's data length's) // cached value, so light weight & no computations unsigned GetDataLen() const; HRESULT Merge(CBlobFetcher *destination); // Set the blob fetcher to slow growth mode. This should be done before any allocations void SetInitialGrowth(unsigned growth); }; //***************************************************************************** // Inlines //***************************************************************************** // Set the size that the Pillar will allocate if we call getBlock() inline void CBlobFetcher::CPillar::SetAllocateSize(unsigned nSize) { LIMITED_METHOD_CONTRACT; m_nTargetSize = nSize; } // Get the size we will allocate so we can decide if we need to change it // This is not the same as the GetDataLen() and is only useful // before we do the allocation inline unsigned CBlobFetcher::CPillar::GetAllocateSize() const { LIMITED_METHOD_CONTRACT; return m_nTargetSize; } inline char* CBlobFetcher::CPillar::GetRawDataStart() { LIMITED_METHOD_CONTRACT; return m_dataStart; } inline BOOL CBlobFetcher::CPillar::Contains(_In_ char *ptr) { LIMITED_METHOD_CONTRACT; return ptr >= m_dataStart && ptr < m_dataCur; } inline ULONG32 CBlobFetcher::CPillar::GetOffset(_In_ char *ptr) { LIMITED_METHOD_CONTRACT; _ASSERTE(Contains(ptr)); return (ULONG32)(ptr - m_dataStart); } //----------------------------------------------------------------------------- // Calculate the length of data being used, (not the length allocated) //----------------------------------------------------------------------------- inline unsigned CBlobFetcher::CPillar::GetDataLen() const { LIMITED_METHOD_CONTRACT; _ASSERTE((m_dataCur >= m_dataStart) && (m_dataCur <= m_dataEnd)); return (unsigned)(m_dataCur - m_dataStart); } inline unsigned CBlobFetcher::GetDataLen() const { LIMITED_METHOD_CONTRACT; return m_nDataLen; } // Set the blob fetcher to slow growth mode. This should be done before any allocations inline void CBlobFetcher::SetInitialGrowth(unsigned growth) { _ASSERTE(GetDataLen() == 0); if (GetDataLen() == 0) { m_pIndex[0].SetAllocateSize(growth); } } #endif // __BLOB_FETCHER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/bundle.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** bundle.h - Information about applications bundled as a single-file ** ** ** *****************************************************************************/ #ifndef _BUNDLE_H_ #define _BUNDLE_H_ #include #include "coreclrhost.h" class Bundle; struct BundleFileLocation { INT64 Size; INT64 Offset; INT64 UncompresedSize; BundleFileLocation() { LIMITED_METHOD_CONTRACT; Size = 0; Offset = 0; UncompresedSize = 0; } static BundleFileLocation Invalid() { LIMITED_METHOD_CONTRACT; return BundleFileLocation(); } const SString &Path() const; bool IsValid() const { LIMITED_METHOD_CONTRACT; return Offset != 0; } }; class Bundle { public: Bundle(LPCSTR bundlePath, BundleProbeFn *probe); BundleFileLocation Probe(const SString& path, bool pathIsBundleRelative = false) const; const SString &Path() const { LIMITED_METHOD_CONTRACT; return m_path; } const SString &BasePath() const { LIMITED_METHOD_CONTRACT; return m_basePath; } static Bundle* AppBundle; // The BundleInfo for the current app, initialized by coreclr_initialize. static bool AppIsBundle() { LIMITED_METHOD_CONTRACT; return AppBundle != nullptr; } static BundleFileLocation ProbeAppBundle(const SString& path, bool pathIsBundleRelative = false); private: SString m_path; // The path to single-file executable BundleProbeFn *m_probe; SString m_basePath; // The prefix to denote a path within the bundle COUNT_T m_basePathLength; }; #endif // _BUNDLE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cahlpr.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // File: CAHLPR.H // // // //***************************************************************************** #ifndef __CAHLPR_H__ #define __CAHLPR_H__ #include "caparser.h" //***************************************************************************** // This class assists in the parsing of CustomAttribute blobs. //***************************************************************************** struct CaValue { union { signed __int8 i1; unsigned __int8 u1; signed __int16 i2; unsigned __int16 u2; signed __int32 i4; unsigned __int32 u4; signed __int64 i8; unsigned __int64 u8; float r4; double r8; struct { LPCUTF8 pStr; ULONG cbStr; } str; }; unsigned __int8 tag; }; #endif // __CAHLPR_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/caparser.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // File: caparser.h // // // // ============================================================================ #ifndef __CAPARSER_H__ #define __CAPARSER_H__ #include "stgpooli.h" class CustomAttributeParser { public: CustomAttributeParser( // Constructor for CustomAttributeParser. const void *pvBlob, // Pointer to the CustomAttribute blob. ULONG cbBlob) // Size of the CustomAttribute blob. : m_pbCur(reinterpret_cast(pvBlob)), m_pbBlob(reinterpret_cast(pvBlob)), m_cbBlob(cbBlob) { LIMITED_METHOD_CONTRACT; } private: signed __int8 GetI1() { LIMITED_METHOD_CONTRACT; signed __int8 tmp = *reinterpret_cast(m_pbCur); m_pbCur += sizeof(signed __int8); return tmp; } unsigned __int8 GetU1() { LIMITED_METHOD_CONTRACT; unsigned __int8 tmp = *reinterpret_cast(m_pbCur); m_pbCur += sizeof(unsigned __int8); return tmp; } signed __int16 GetI2() { LIMITED_METHOD_CONTRACT; signed __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur); m_pbCur += sizeof(signed __int16); return tmp; } unsigned __int16 GetU2() { LIMITED_METHOD_CONTRACT; unsigned __int16 tmp = GET_UNALIGNED_VAL16(m_pbCur); m_pbCur += sizeof(unsigned __int16 ); return tmp; } signed __int32 GetI4() { LIMITED_METHOD_CONTRACT; signed __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); m_pbCur += sizeof(signed __int32 ); return tmp; } unsigned __int32 GetU4() { LIMITED_METHOD_CONTRACT; unsigned __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); m_pbCur += sizeof(unsigned __int32 ); return tmp; } signed __int64 GetI8() { LIMITED_METHOD_CONTRACT; signed __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); m_pbCur += sizeof(signed __int64 ); return tmp; } unsigned __int64 GetU8() { LIMITED_METHOD_CONTRACT; unsigned __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); m_pbCur += sizeof(unsigned __int64 ); return tmp; } public: float GetR4() { LIMITED_METHOD_CONTRACT; __int32 tmp = GET_UNALIGNED_VAL32(m_pbCur); _ASSERTE(sizeof(__int32) == sizeof(float)); m_pbCur += sizeof(float); return (float &)tmp; } double GetR8() { LIMITED_METHOD_CONTRACT; __int64 tmp = GET_UNALIGNED_VAL64(m_pbCur); _ASSERTE(sizeof(__int64) == sizeof(double)); m_pbCur += sizeof(double); return (double &)tmp; } private: unsigned __int16 GetProlog() { WRAPPER_NO_CONTRACT; unsigned __int16 val; VERIFY(SUCCEEDED(GetProlog(&val))); return val; } LPCUTF8 GetString(ULONG *pcbString) { WRAPPER_NO_CONTRACT; LPCUTF8 val; VERIFY(SUCCEEDED(GetString(&val, pcbString))); return val; } public: HRESULT GetI1(signed __int8 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(signed __int8)) return META_E_CA_INVALID_BLOB; *pVal = GetI1(); return S_OK; } HRESULT GetTag(CorSerializationType *pVal) { WRAPPER_NO_CONTRACT; HRESULT hr; signed __int8 tmp; IfFailRet(GetI1(&tmp)); *pVal = (CorSerializationType)((unsigned __int8)tmp); return hr; } HRESULT GetU1(unsigned __int8 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(unsigned __int8)) return META_E_CA_INVALID_BLOB; *pVal = GetU1(); return S_OK; } HRESULT GetI2(signed __int16 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(signed __int16)) return META_E_CA_INVALID_BLOB; *pVal = GetI2(); return S_OK; } HRESULT GetU2(unsigned __int16 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(unsigned __int16)) return META_E_CA_INVALID_BLOB; *pVal = GetU2(); return S_OK; } HRESULT GetI4(signed __int32 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(signed __int32)) return META_E_CA_INVALID_BLOB; *pVal = GetI4(); return S_OK; } HRESULT GetU4(unsigned __int32 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(unsigned __int32)) return META_E_CA_INVALID_BLOB; *pVal = GetU4(); return S_OK; } HRESULT GetI8(signed __int64 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(signed __int64)) return META_E_CA_INVALID_BLOB; *pVal = GetI8(); return S_OK; } HRESULT GetU8(unsigned __int64 *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(unsigned __int64)) return META_E_CA_INVALID_BLOB; *pVal = GetU8(); return S_OK; } HRESULT GetR4(float *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(float)) return META_E_CA_INVALID_BLOB; *pVal = GetR4(); return S_OK; } HRESULT GetR8(double *pVal) { WRAPPER_NO_CONTRACT; if (BytesLeft() < (int) sizeof(double)) return META_E_CA_INVALID_BLOB; *pVal = GetR8(); return S_OK; } HRESULT GetProlog(unsigned __int16 *pVal) { WRAPPER_NO_CONTRACT; m_pbCur = m_pbBlob; if (BytesLeft() < (int)(sizeof(BYTE) * 2)) return META_E_CA_INVALID_BLOB; return GetU2(pVal); } // Added for compatibility with anyone that may emit // blobs where the prolog is the only incorrect data. HRESULT SkipProlog() { unsigned __int16 val; return GetProlog(&val); } HRESULT ValidateProlog() { HRESULT hr; unsigned __int16 val; IfFailRet(GetProlog(&val)); if (val != 0x0001) return META_E_CA_INVALID_BLOB; return hr; } // // IMPORTANT: the returned string is typically not null-terminated. // // This can return any of three distinct valid results: // - NULL string, indicated by *pszString==NULL, *pcbString==0 // - empty string, indicated by *pszString!=NULL, *pcbString==0 // - non-empty string, indicated by *pdzString!=NULL, *pcbString!=0 // If you expect non-null or non-empty strings in your usage scenario, // call the GetNonNullString and GetNonEmptyString helpers below. // HRESULT GetString(LPCUTF8 *pszString, ULONG *pcbString) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; HRESULT hr; if (BytesLeft() == 0) { // Need to check for NULL string sentinel (see below), // so need to have at least one byte to read. IfFailRet(META_E_CA_INVALID_BLOB); } if (*m_pbCur == 0xFF) { // 0xFF indicates the NULL string, which is semantically // different than the empty string. *pszString = NULL; *pcbString = 0; m_pbCur++; return S_OK; } // Get the length, pointer to data following the length. return GetData((BYTE const **)pszString, pcbString); } // // This can return any of two distinct valid results: // - empty string, indicated by *pszString!=NULL, *pcbString==0 // - non-empty string, indicated by *pszString!=NULL, *pcbString!=0 // If you expect non-null or non-empty strings in your usage scenario, // call the GetNonNullString and GetNonEmptyString helpers below. // HRESULT GetNonNullString(LPCUTF8 *pszString, ULONG *pcbString) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; HRESULT hr; IfFailRet(GetString(pszString, pcbString)); if (*pszString == NULL) { return META_E_CA_INVALID_BLOB; } return S_OK; } // // This function will only return success if the string is valid, // non-NULL and non-empty; i.e., *pszString!=NULL, *pcbString!=0 // HRESULT GetNonEmptyString(LPCUTF8 *pszString, ULONG *pcbString) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; HRESULT hr; IfFailRet(GetNonNullString(pszString, pcbString)); if (*pcbString == 0) { return META_E_CA_INVALID_BLOB; } return S_OK; } // IMPORTANT: do not use with string fetching - use GetString instead. HRESULT GetData(BYTE const **ppbData, ULONG *pcbData) { HRESULT hr; IfFailRet(CPackedLen::SafeGetData(m_pbCur, m_pbBlob + m_cbBlob, pcbData, ppbData)); // Move past the data we just recovered m_pbCur = *ppbData + *pcbData; return S_OK; } // IMPORTANT: do not use with string fetching - use GetString instead. HRESULT GetPackedValue(ULONG *pcbData) { return CPackedLen::SafeGetLength(m_pbCur, m_pbBlob + m_cbBlob, pcbData, &m_pbCur); } int BytesLeft() { LIMITED_METHOD_CONTRACT; return (int)(m_cbBlob - (m_pbCur - m_pbBlob)); } private: const BYTE *m_pbCur; const BYTE *m_pbBlob; ULONG m_cbBlob; }; #endif // __CAPARSER_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ceefilegenwriter.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== // File: CeeFileGenWriter.h // // =========================================================================== #ifndef _CEEFILEGENWRITER_H_ #define _CEEFILEGENWRITER_H_ // // CeeFileGenWriter contains all the code necessary to actually write an exe // while CCeeGen contains everything else. This lets CeeGen.exe and the VM // share more code without forcing the VM to carry the extra code to write an // exe. #include #include "ceegen.h" #include "iceefilegen.h" class PEWriter; class CeeFileGenWriter; // default setting for PE file const UINT32 CEE_IMAGE_BASE_32 = 0x00400000; const UINT64 CEE_IMAGE_BASE_64 = UI64(0x0000000140000000); const int CEE_IMAGE_SUBSYSTEM_MAJOR_VERSION = 4; const int CEE_IMAGE_SUBSYSTEM_MINOR_VERSION = 0; class CeeFileGenWriter : public CCeeGen { mdToken m_entryPoint; // token for entry point DWORD m_comImageFlags; LPWSTR m_outputFileName; LPWSTR m_resourceFileName; bool m_dllSwitch; ULONG m_iatOffset; DWORD m_dwManifestRVA; DWORD m_dwManifestSize; DWORD m_dwStrongNameRVA; DWORD m_dwStrongNameSize; DWORD m_dwVTableRVA; DWORD m_dwVTableSize; bool m_linked; bool m_fixed; HRESULT checkForErrors(); struct IDataDllInfo { const char *m_name; int m_numMethods; const char **m_methodName; int m_iltOffset; int m_ibnOffset; int m_iatOffset; int m_nameOffset; } *m_iDataDlls; int m_dllCount; CeeSection *m_iDataSectionIAT; int m_iDataOffsetIAT; char *m_iDataIAT; HRESULT allocateIAT(); public: // Create with one of these two methods, not operator new static HRESULT CreateNewInstance(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); // See ICeeFileGen.h for the definition of the bits used in createFlags static HRESULT CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, DWORD createFlags, LPCWSTR seedFileName = NULL); virtual HRESULT Cleanup(); PEWriter &getPEWriter(); HRESULT link(); // Layout the sections and assign their starting addresses HRESULT fixup(); // Apply relocations to any pointer data. Also generate PE base relocs HRESULT generateImage(void **ppImage); HRESULT setImageBase(size_t imageBase); HRESULT setImageBase64(ULONGLONG imageBase); HRESULT setFileAlignment(ULONG fileAlignment); HRESULT setSubsystem(DWORD subsystem, DWORD major, DWORD minor); HRESULT getMethodRVA(ULONG codeOffset, ULONG *codeRVA); HRESULT setEntryPoint(mdMethodDef method); mdMethodDef getEntryPoint(); HRESULT setComImageFlags(DWORD mask); HRESULT clearComImageFlags(DWORD mask); DWORD getComImageFlags(); HRESULT setOutputFileName(_In_ LPWSTR outputFileName); LPWSTR getOutputFileName(); HRESULT setResourceFileName(_In_ LPWSTR resourceFileName); LPWSTR getResourceFileName(); HRESULT setDirectoryEntry(CeeSection §ion, ULONG entry, ULONG size, ULONG offset=0); HRESULT computeSectionOffset(CeeSection §ion, _In_ char *ptr, unsigned *offset); HRESULT computeOffset(_In_ char *ptr, CeeSection **pSection, unsigned *offset); HRESULT getCorHeader(IMAGE_COR20_HEADER **ppHeader); HRESULT getFileTimeStamp(DWORD *pTimeStamp); HRESULT setLibraryGuid(_In_ LPWSTR libraryGuid); HRESULT setDllSwitch(bool dllSwitch); bool getDllSwitch(); HRESULT setManifestEntry(ULONG size, ULONG offset); HRESULT setStrongNameEntry(ULONG size, ULONG offset); HRESULT setVTableEntry(ULONG size, ULONG offset); HRESULT setVTableEntry64(ULONG size, void* ptr); protected: CeeFileGenWriter(); // ctor is protected HRESULT emitResourceSection(); HRESULT emitExeMain(); HRESULT setAddrReloc(UCHAR *instrAddr, DWORD value); HRESULT addAddrReloc(CeeSection &thisSection, UCHAR *instrAddr, DWORD offset, CeeSection *targetSection); HRESULT MapTokens(CeeGenTokenMapper *pMapper, IMetaDataImport *pImport); HRESULT MapTokensForMethod(CeeGenTokenMapper *pMapper,BYTE *pCode, LPCWSTR szMethodName); }; inline PEWriter &CeeFileGenWriter::getPEWriter() { return (PEWriter &) *m_peSectionMan; } inline LPWSTR CeeFileGenWriter::getOutputFileName() { return m_outputFileName; } inline LPWSTR CeeFileGenWriter::getResourceFileName() { return m_resourceFileName; } inline HRESULT CeeFileGenWriter::setDllSwitch(bool dllSwitch) { m_dllSwitch = dllSwitch; return S_OK; } inline bool CeeFileGenWriter::getDllSwitch() { return m_dllSwitch; } inline mdMethodDef CeeFileGenWriter::getEntryPoint() { return m_entryPoint; } inline HRESULT CeeFileGenWriter::setEntryPoint(mdMethodDef method) { m_entryPoint = method; return S_OK; } inline HRESULT CeeFileGenWriter::setComImageFlags(DWORD mask) { m_comImageFlags |= mask; return S_OK; } inline HRESULT CeeFileGenWriter::clearComImageFlags(DWORD mask) { m_comImageFlags &= ~mask; return S_OK; } inline DWORD CeeFileGenWriter::getComImageFlags() { return m_comImageFlags; } // #if defined(_IMAGE_FILE_4K_SECTION_ALIGNMENT_) #define IMAGE_NT_OPTIONAL_HDR_SECTION_ALIGNMENT 0x1000 #else #define IMAGE_NT_OPTIONAL_HDR_SECTION_ALIGNMENT 0x2000 #endif // The stub is always x86 so we always mark the image as x86 #define IMAGE_FILE_MACHINE IMAGE_FILE_MACHINE_I386 #endif // _CEEFILEGENWRITER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ceegen.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== // File: CEEGEN.H // // =========================================================================== #ifndef _CEEGEN_H_ #define _CEEGEN_H_ #include "cor.h" #include "iceefilegen.h" #include "ceegentokenmapper.h" class CeeSection; class CeeSectionString; class CCeeGen; class PESectionMan; class PESection; typedef DWORD StringRef; #if 0 This is a description of the current implementation of these types for generating CLR modules. ICeeGenInternal - interface to generate in-memory CLR module. CCeeGen - implementation of ICeeGen. Currently it uses both CeeSections as well as PESections (inside PESectionMan), and maintains a 1:1 relation between them. This is ugly. CeeFileGenWriter - Provides functionality to write in-memory module to PE format file. Uses PEWriter (m_pSectionMan) for file-writing functionality PEWriter - It can generate a PE format file. It also knows to apply pointer relocs when it lays out the PESections. ICeeFileGen - Interface used by compilers, ngen, etc, to generate a CLR file. Has a bunch of methods to emit signatures, tokens, methods, etc which are not implemented. These are left over from before +----------------------------+ | ICeeGenInternal | | | | COM-style version of | | ICeeFileGen. HCEEFILE is | | replaced with "this" | +-------------------------+ | | | CeeSectionImpl | +----------------------------+ +-------------------------+ | | | | | | v | v +---------------------------+ | +------------+ | CCeeGen | | | | +---------------------------+ | | CeeSection | contains | | | | |<-------------| CeeSection* m_sections | | +------------+ | | | /| PESectionMan m_pSectionMan| | / | | | +-----------------+ / +---------------------------+ v | PESectionMan |<----+ | +-----------+ | | contains | | PESection | +-----------------+ | | | contains | PESection * | v | |<----------| sectStart, | +------------------------------+ +-----------+ | sectCur, | | CeeFileGenWriter | | sectEnd | +------------------------------+ +-----------------+ | Does meta-data specific | | | stuff and then dispatches to | | | m_pSectionMan.PEWriter::***()| | | | v +------------------------------+ +------------------------+ ^ | PEWriter | |wraps +------------------------+ | | Low -level file writer | +----------------------------+ | Knows how to do | | ICeeFileGen | | pointer relocs | | | | | | C-style interface. Deals | +------------------------+ | with HCEEFILE, HCEESECTION | | etc. It is mostly just a | | thin wrapper for a | | CeeFileGenWriter | +----------------------------+ #endif // 0 // ***** CeeSection classes class CeeSectionImpl { public: virtual unsigned dataLen() = 0; virtual char * getBlock( unsigned len, unsigned align = 1) = 0; virtual HRESULT addSectReloc( unsigned offset, CeeSection & relativeTo, CeeSectionRelocType reloc = srRelocAbsolute, CeeSectionRelocExtra * extra = NULL) = 0; virtual HRESULT addBaseReloc( unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra * extra = NULL) = 0; virtual HRESULT directoryEntry(unsigned num) = 0; virtual unsigned char * name() = 0; virtual char * computePointer(unsigned offset) const = 0; virtual BOOL containsPointer(_In_ char * ptr) const = 0; virtual unsigned computeOffset(_In_ char * ptr) const = 0; virtual unsigned getBaseRVA() = 0; virtual void SetInitialGrowth(unsigned growth) = 0; }; class CeeSection { // m_ceeFile allows inter-section communication CCeeGen &m_ceeFile; // abstract away implementation to allow inheritance from CeeSection CeeSectionImpl &m_impl; public: enum RelocFlags { RELOC_NONE = 0, // address should be fixed up to be a RVA not a normal address RELOC_RVA = 1 }; CeeSection(CCeeGen &ceeFile, CeeSectionImpl &impl) : m_ceeFile(ceeFile), m_impl(impl) { LIMITED_METHOD_CONTRACT; } virtual ~CeeSection() {LIMITED_METHOD_CONTRACT; } // bytes in this section at present unsigned dataLen(); // section base, after linking unsigned getBaseRVA(); // get a block to write on (use instead of write to avoid copy) char* getBlock(unsigned len, unsigned align=1); // Indicates that the DWORD at 'offset' in the current section should // have the base of section 'relativeTo added to it HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, CeeSectionRelocType = srRelocAbsolute, CeeSectionRelocExtra *extra = 0); // Add a base reloc for the given offset in the current section virtual HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra = 0); // this section will be directory entry 'num' HRESULT directoryEntry(unsigned num); // return section name unsigned char *name(); // simulate the base + offset with a more complex data storage char * computePointer(unsigned offset) const; BOOL containsPointer(_In_ char *ptr) const; unsigned computeOffset(_In_ char *ptr) const; CeeSectionImpl &getImpl(); CCeeGen &ceeFile(); void SetInitialGrowth(unsigned growth); }; // ***** CCeeGen class // Only handles in memory stuff // Base class for CeeFileGenWriter (which actually generates PEFiles) class CCeeGen : public ICeeGenInternal { LONG m_cRefs; protected: short m_textIdx; // m_sections[] index for the .text section short m_metaIdx; // m_sections[] index for metadata (.text, or .cormeta for obj files) short m_corHdrIdx; // m_sections[] index for the COM+ header (.text0) short m_stringIdx; // m_sections[] index for strings (.text, or .rdata for EnC) short m_ilIdx; // m_sections[] index for IL (.text) CeeGenTokenMapper *m_pTokenMap; BOOLEAN m_fTokenMapSupported; // temporary to support both models IMapToken *m_pRemapHandler; CeeSection **m_sections; short m_numSections; short m_allocSections; PESectionMan * m_peSectionMan; IMAGE_COR20_HEADER *m_corHeader; DWORD m_corHeaderOffset; HRESULT allocateCorHeader(); HRESULT addSection(CeeSection *section, short *sectionIdx); // Init process: Call static CreateNewInstance() , not operator new protected: HRESULT Init(); CCeeGen(); public: virtual ~CCeeGen() {} static HRESULT CreateNewInstance(CCeeGen* & pCeeFileGen); // call this to instantiate virtual HRESULT Cleanup(); // ICeeGenInternal interfaces ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release(); STDMETHODIMP QueryInterface( REFIID riid, void **ppInterface); STDMETHODIMP EmitString ( _In_ LPWSTR lpString, // [IN] String to emit ULONG *RVA); STDMETHODIMP GetString ( ULONG RVA, __inout LPWSTR *lpString); STDMETHODIMP AllocateMethodBuffer ( ULONG cchBuffer, // [IN] Length of string to emit UCHAR **lpBuffer, // [OUT] Returned buffer ULONG *RVA); STDMETHODIMP GetMethodBuffer ( ULONG RVA, UCHAR **lpBuffer); STDMETHODIMP GetIMapTokenIface ( IUnknown **pIMapToken); STDMETHODIMP GenerateCeeFile (); STDMETHODIMP GetIlSection ( HCEESECTION *section); STDMETHODIMP GetStringSection ( HCEESECTION *section); STDMETHODIMP AddSectionReloc ( HCEESECTION section, ULONG offset, HCEESECTION relativeTo, CeeSectionRelocType relocType); STDMETHODIMP GetSectionCreate ( const char *name, DWORD flags, HCEESECTION *section); STDMETHODIMP GetSectionDataLen ( HCEESECTION section, ULONG *dataLen); STDMETHODIMP GetSectionBlock ( HCEESECTION section, ULONG len, ULONG align=1, void **ppBytes=0); STDMETHODIMP ComputePointer ( HCEESECTION section, ULONG RVA, // [IN] RVA for method to return UCHAR **lpBuffer); // [OUT] Returned buffer STDMETHODIMP AddNotificationHandler(IUnknown *pHandler); // Write the metadata in "emitter" to the default metadata section is "section" is 0 // If 'section != 0, it will put the data in 'buffer'. This // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen' // (should use GetSaveSize to insure that buffer is big enough virtual HRESULT emitMetaData(IMetaDataEmit *emitter, CeeSection* section=0, DWORD offset=0, BYTE* buffer=0, unsigned buffLen=0); virtual HRESULT getMethodRVA(ULONG codeOffset, ULONG *codeRVA); STDMETHODIMP SetInitialGrowth(DWORD growth); CeeSection &getTextSection(); CeeSection &getMetaSection(); CeeSection &getCorHeaderSection(); CeeSectionString &getStringSection(); CeeSection &getIlSection(); virtual HRESULT getSectionCreate (const char *name, DWORD flags, CeeSection **section=NULL, short *sectionIdx = NULL); PESectionMan* getPESectionMan() { LIMITED_METHOD_CONTRACT; return m_peSectionMan; } virtual HRESULT getMapTokenIface(IUnknown **pIMapToken, IMetaDataEmit *emitter=0); CeeGenTokenMapper *getTokenMapper() { LIMITED_METHOD_CONTRACT; return m_pTokenMap; } virtual HRESULT addNotificationHandler(IUnknown *pHandler); //Clone is actually a misnomer here. This method will copy all of the //instance variables and then do a deep copy (as necessary) of the sections. //Section data will be appended onto any information already in the section. //This is done to support the DynamicIL -> PersistedIL transform. virtual HRESULT cloneInstance(CCeeGen *destination); }; // ***** CeeSection inline methods inline unsigned CeeSection::dataLen() { WRAPPER_NO_CONTRACT; return m_impl.dataLen(); } inline unsigned CeeSection::getBaseRVA() { WRAPPER_NO_CONTRACT; return m_impl.getBaseRVA(); } inline char *CeeSection::getBlock(unsigned len, unsigned align) { WRAPPER_NO_CONTRACT; return m_impl.getBlock(len, align); } inline HRESULT CeeSection::addSectReloc( unsigned offset, CeeSection& relativeTo, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) { WRAPPER_NO_CONTRACT; return(m_impl.addSectReloc(offset, relativeTo, reloc, extra)); } inline HRESULT CeeSection::addBaseReloc(unsigned offset, CeeSectionRelocType reloc, CeeSectionRelocExtra *extra) { WRAPPER_NO_CONTRACT; return(m_impl.addBaseReloc(offset, reloc, extra)); } inline HRESULT CeeSection::directoryEntry(unsigned num) { WRAPPER_NO_CONTRACT; TESTANDRETURN(num < IMAGE_NUMBEROF_DIRECTORY_ENTRIES, E_INVALIDARG); m_impl.directoryEntry(num); return S_OK; } inline CCeeGen &CeeSection::ceeFile() { LIMITED_METHOD_CONTRACT; return m_ceeFile; } inline CeeSectionImpl &CeeSection::getImpl() { LIMITED_METHOD_CONTRACT; return m_impl; } inline unsigned char *CeeSection::name() { WRAPPER_NO_CONTRACT; return m_impl.name(); } inline char * CeeSection::computePointer(unsigned offset) const { WRAPPER_NO_CONTRACT; return m_impl.computePointer(offset); } inline BOOL CeeSection::containsPointer(_In_ char *ptr) const { WRAPPER_NO_CONTRACT; return m_impl.containsPointer(ptr); } inline unsigned CeeSection::computeOffset(_In_ char *ptr) const { WRAPPER_NO_CONTRACT; return m_impl.computeOffset(ptr); } inline void CeeSection::SetInitialGrowth(unsigned growth) { WRAPPER_NO_CONTRACT; m_impl.SetInitialGrowth(growth); } // ***** CCeeGen inline methods inline CeeSection &CCeeGen::getTextSection() { LIMITED_METHOD_CONTRACT; return *m_sections[m_textIdx]; } inline CeeSection &CCeeGen::getMetaSection() { LIMITED_METHOD_CONTRACT; return *m_sections[m_metaIdx]; } inline CeeSection &CCeeGen::getCorHeaderSection() { LIMITED_METHOD_CONTRACT; _ASSERTE(m_corHdrIdx >= 0); return *m_sections[m_corHdrIdx]; } inline CeeSectionString &CCeeGen::getStringSection() { LIMITED_METHOD_CONTRACT; return *(CeeSectionString*)m_sections[m_stringIdx]; } inline CeeSection &CCeeGen::getIlSection() { LIMITED_METHOD_CONTRACT; return *m_sections[m_ilIdx]; } #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ceegentokenmapper.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // CeeGenTokenMapper.h // // This helper class tracks mapped tokens from their old value to the new value // which can happen when the data is optimized on save. // //***************************************************************************** #ifndef __CeeGenTokenMapper_h__ #define __CeeGenTokenMapper_h__ #include "utilcode.h" typedef CDynArray TOKENMAP; #define INDEX_OF_TYPE(type) ((type) >> 24) //r#define INDEX_FROM_TYPE(type) case INDEX_OF_TYPE(mdt ## type): return (tkix ## type) // Define the list of CeeGen tracked tokens #define CEEGEN_TRACKED_TOKENS() \ CEEGEN_TRACKED_TOKEN(TypeDef) \ CEEGEN_TRACKED_TOKEN(InterfaceImpl) \ CEEGEN_TRACKED_TOKEN(MethodDef) \ CEEGEN_TRACKED_TOKEN(TypeRef) \ CEEGEN_TRACKED_TOKEN(MemberRef) \ CEEGEN_TRACKED_TOKEN(CustomAttribute) \ CEEGEN_TRACKED_TOKEN(FieldDef) \ CEEGEN_TRACKED_TOKEN(ParamDef) \ CEEGEN_TRACKED_TOKEN(File) \ CEEGEN_TRACKED_TOKEN(GenericParam) \ class CCeeGen; #define CEEGEN_TRACKED_TOKEN(x) tkix ## x, class CeeGenTokenMapper : public IMapToken { friend class CCeeGen; friend class PESectionMan; public: enum { CEEGEN_TRACKED_TOKENS() MAX_TOKENMAP }; static int IndexForType(mdToken tk); CeeGenTokenMapper() : m_pIImport(0), m_cRefs(1), m_pIMapToken(NULL) { LIMITED_METHOD_CONTRACT; } virtual ~CeeGenTokenMapper() {} //***************************************************************************** // IUnknown implementation. //***************************************************************************** virtual ULONG STDMETHODCALLTYPE AddRef() {LIMITED_METHOD_CONTRACT; return ++m_cRefs; } virtual ULONG STDMETHODCALLTYPE Release() { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; SUPPORTS_DAC_HOST_ONLY; ULONG cRefs = --m_cRefs; if (cRefs == 0) { if (m_pIMapToken) { m_pIMapToken->Release(); m_pIMapToken = NULL; } delete this; } return cRefs; } virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, PVOID *ppIUnk); //***************************************************************************** // Called by the meta data engine when a token is remapped to a new location. // This value is recorded in the m_rgMap array based on type and rid of the // from token value. //***************************************************************************** virtual HRESULT STDMETHODCALLTYPE Map(mdToken tkImp, mdToken tkEmit); //***************************************************************************** // Check the given token to see if it has moved to a new location. If so, // return true and give back the new token. //***************************************************************************** virtual int HasTokenMoved(mdToken tkFrom, mdToken &tkTo); int GetMaxMapSize() const { LIMITED_METHOD_CONTRACT; return (MAX_TOKENMAP); } IUnknown *GetMapTokenIface() const { LIMITED_METHOD_CONTRACT; return ((IUnknown *) this); } //***************************************************************************** // Hand out a copy of the meta data information. //***************************************************************************** virtual HRESULT GetMetaData(IMetaDataImport **ppIImport); //***************************************************************************** // Add another token mapper. //***************************************************************************** virtual HRESULT AddTokenMapper(IMapToken *pIMapToken) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; // Add the token mapper, if there isn't already one. if (m_pIMapToken == NULL) { m_pIMapToken = pIMapToken; m_pIMapToken->AddRef(); return S_OK; } else { _ASSERTE(!"Token mapper already set!"); return E_FAIL; } } protected: // m_rgMap is an array indexed by token type. For each type, an array of // tokens is kept, indexed by from rid. To see if a token has been moved, // do a lookup by type to get the right array, then use the from rid to // find the to rid. TOKENMAP m_rgMap[MAX_TOKENMAP]; IMetaDataImport *m_pIImport; ULONG m_cRefs; // Ref count. IMapToken *m_pIMapToken; }; #endif // __CeeGenTokenMapper_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ceesectionstring.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== // File: CeeSectionString.h // // =========================================================================== #ifndef CeeSectionString_H #define CeeSectionString_H #include #include "ceegen.h" // This class is responsible for managing all the strings that have // been emitted for the PE file. // This class manages the strings that are added to the .rdata section. // It keeps track of each string that has been added using a hashtable. // The hash table is effectively 2-dimensional. There is a large "virtual // hash space" that is used to get a wide hash code distribution. The // virtual hash space is mapped into a real hash table where each n // hash values in the virtual space fall into a given hash bucket for // real hash table size n. Within the bucket, elements are stored in a linked // list in-order. When an virtual hash entry corresponds to a given bucket, // that bucket is searched for the matching hash id. If not found, it is // inserted, otherwise, the value is returned. The idea is that for smaller // apps, there won't be a large number of strings, so that collisions are // minimal and the length of each bucket's chain is small. For larger // numbers of strings, having a large hash space also reduces numbers // of collisions, avoiding string compares unless the hash codes match. struct StringTableEntry; class CeeSectionString : public CeeSection { enum { MaxRealEntries = 100, MaxVirtualEntries = 10000 }; StringTableEntry *stringTable[MaxRealEntries]; StringTableEntry *createEntry(_In_z_ LPWSTR target, ULONG hashId); StringTableEntry *findStringInsert( StringTableEntry *&entry, _In_z_ LPWSTR targetValue, ULONG hashId); void deleteEntries(StringTableEntry *e); #ifdef RDATA_STATS int dumpEntries(StringTableEntry *e); void dumpTable(); #endif public: ~CeeSectionString(); CeeSectionString(CCeeGen &ceeFile, CeeSectionImpl &impl); virtual HRESULT getEmittedStringRef(_In_z_ LPWSTR targetValue, StringRef *ref); }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cfi.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef CFI_H_ #define CFI_H_ #define DWARF_REG_ILLEGAL -1 enum CFI_OPCODE { CFI_ADJUST_CFA_OFFSET, // Offset is adjusted relative to the current one. CFI_DEF_CFA_REGISTER, // New register is used to compute CFA CFI_REL_OFFSET // Register is saved at offset from the current CFA }; struct CFI_CODE { unsigned char CodeOffset;// Offset from the start of code the frame covers. unsigned char CfiOpCode; short DwarfReg; // Dwarf register number. 0~32 for x64. int Offset; CFI_CODE(unsigned char codeOffset, unsigned char cfiOpcode, short dwarfReg, int offset) : CodeOffset(codeOffset) , CfiOpCode(cfiOpcode) , DwarfReg(dwarfReg) , Offset(offset) {} }; typedef CFI_CODE* PCFI_CODE; #endif // CFI_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/check.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // Check.h // // // Assertion checking infrastructure // --------------------------------------------------------------------------- #ifndef CHECK_H_ #define CHECK_H_ #include "static_assert.h" #include "daccess.h" #include "unreachable.h" #ifdef _DEBUG #ifdef _MSC_VER // Make sure we can recurse deep enough for FORCEINLINE #pragma inline_recursion(on) #pragma inline_depth(16) #pragma warning(disable:4714) #endif // _MSC_VER #if !defined(DISABLE_CONTRACTS) #define CHECK_INVARIANTS 1 #define VALIDATE_OBJECTS 1 #endif #endif // _DEBUG #if defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif #ifdef _DEBUG #define DEBUG_ARG(x) , x #else #define DEBUG_ARG(x) #endif #define CHECK_STRESS 1 //-------------------------------------------------------------------------------- // A CHECK is an object which encapsulates a potential assertion // failure. It not only contains the result of the check, but if the check fails, // also records information about the condition and call site. // // CHECK also serves as a holder to prevent recursive CHECKS. These can be // particularly common when putting preconditions inside predicates, especially // routines called by an invariant. // // Note that using CHECK is perfectly efficient in a free build - the CHECK becomes // a simple string constant pointer (typically either NULL or (LPCSTR)1, although some // check failures may include messages) // // NOTE: you should NEVER use the CHECK class API directly - use the macros below. //-------------------------------------------------------------------------------- class SString; class CHECK { protected: // On retail, this is a pointer to a string literal, null or (LPCSTR)1. // On debug, this is a pointer to dynamically allocated memory - that // lets us have formatted strings in debug builds. LPCSTR m_message; #ifdef _DEBUG LPCSTR m_condition; LPCSTR m_file; INT m_line; LONG *m_pCount; // Keep leakage counters. static size_t s_cLeakedBytes; static size_t s_cNumFailures; static thread_local LONG t_count; #endif static BOOL s_neverEnforceAsserts; public: // !!! NOTE: Called from macros only!!! // If we are not in a check, return TRUE and PushCheck; otherwise return FALSE BOOL EnterAssert(); // Pops check count void LeaveAssert(); // Just return if we are in a check BOOL IsInAssert(); // Should we skip enforcing asserts static BOOL EnforceAssert(); static BOOL EnforceAssert_StaticCheckOnly(); static void ResetAssert(); #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4702) // Disable bogus unreachable code warning #endif // _MSC_VER CHECK() : m_message(NULL) #ifdef _DEBUG , m_condition (NULL) , m_file(NULL) , m_line(NULL) , m_pCount(NULL) #endif {} #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER // Fail records the result of a condition check. Can take either a // boolean value or another check result BOOL Fail(BOOL condition); BOOL Fail(const CHECK &check); // Setup records context info after a failure. void Setup(LPCSTR message DEBUG_ARG(LPCSTR condition) DEBUG_ARG(LPCSTR file) DEBUG_ARG(INT line)); static LPCSTR FormatMessage(LPCSTR messageFormat, ...); // Trigger triggers the actual check failure. The trigger may provide a reason // to include in the failure message. void Trigger(LPCSTR reason); // Finally, convert to a BOOL to allow just testing the result of a Check function operator BOOL(); BOOL operator!(); CHECK &operator()() { return *this; } static inline const CHECK OK() { return CHECK(); } static void SetAssertEnforcement(BOOL value); private: #ifdef _DEBUG static LPCSTR AllocateDynamicMessage(const SString &s); #endif }; //-------------------------------------------------------------------------------- // These CHECK macros are the correct way to propagate an assertion. These // routines are designed for use inside "Check" routines. Such routines may // be Invariants, Validate routines, or any other assertional predicates. // // A Check routine should return a value of type CHECK. // // It should consist of multiple CHECK or CHECK_MSG statements (along with appropritate // control flow) and should end with CHECK_OK() if all other checks pass. // // It may contain a CONTRACT_CHECK contract, but this is only appropriate if the // check is used for non-assertional purposes (otherwise the contract will never execute). // Note that CONTRACT_CHECK contracts do not support postconditions. // // CHECK: Check the given condition, return a CHECK failure if FALSE // CHECK_MSG: Same, but include a message parameter if the check fails // CHECK_OK: Return a successful check value; //-------------------------------------------------------------------------------- #ifdef _DEBUG #define DEBUG_ONLY_MESSAGE(msg) msg #else // On retail, we don't want to add a bunch of string literals to the image, // so we just use the same one everywhere. #define DEBUG_ONLY_MESSAGE(msg) ((LPCSTR)1) #endif #define CHECK_MSG_EX(_condition, _message, _RESULT) \ do \ { \ CHECK _check; \ if (_check.Fail(_condition)) \ { \ ENTER_DEBUG_ONLY_CODE; \ _check.Setup(DEBUG_ONLY_MESSAGE(_message) \ DEBUG_ARG(#_condition) \ DEBUG_ARG(__FILE__) \ DEBUG_ARG(__LINE__)); \ _RESULT(_check); \ LEAVE_DEBUG_ONLY_CODE; \ } \ } while (0) #define RETURN_RESULT(r) return r #define CHECK_MSG(_condition, _message) \ CHECK_MSG_EX(_condition, _message, RETURN_RESULT) #define CHECK(_condition) \ CHECK_MSG(_condition, "") #define CHECK_MSGF(_condition, _args) \ CHECK_MSG(_condition, CHECK::FormatMessage _args) #define CHECK_FAIL(_message) \ CHECK_MSG(FALSE, _message); UNREACHABLE() #define CHECK_FAILF(_args) \ CHECK_MSGF(FALSE, _args); UNREACHABLE() #define CHECK_OK \ return CHECK::OK() //-------------------------------------------------------------------------------- // ASSERT_CHECK is the proper way to trigger a check result. If the CHECK // has failed, the diagnostic assertion routines will fire with appropriate // context information. // // Note that the condition may either be a raw boolean expression or a CHECK result // returned from a Check routine. // // Recursion note: ASSERT_CHECKs are only performed if there is no current check in // progress. //-------------------------------------------------------------------------------- #ifndef ENTER_DEBUG_ONLY_CODE #define ENTER_DEBUG_ONLY_CODE #endif #ifndef LEAVE_DEBUG_ONLY_CODE #define LEAVE_DEBUG_ONLY_CODE #endif #define ASSERT_CHECK(_condition, _message, _reason) \ do \ { \ CHECK _check; \ if (_check.EnterAssert()) \ { \ ENTER_DEBUG_ONLY_CODE; \ if (_check.Fail(_condition)) \ { \ _check.Setup(_message \ DEBUG_ARG(#_condition) \ DEBUG_ARG(__FILE__) \ DEBUG_ARG(__LINE__)); \ _check.Trigger(_reason); \ } \ LEAVE_DEBUG_ONLY_CODE; \ _check.LeaveAssert(); \ } \ } while (0) // ex: ASSERT_CHECKF(1+2==4, "my reason", ("Woah %d", 1+3)); // note that the double parenthesis, the 'args' param below will include one pair of parens. #define ASSERT_CHECKF(_condition, _reason, _args) \ ASSERT_CHECK(_condition, CHECK::FormatMessage _args, _reason) //-------------------------------------------------------------------------------- // INVARIANTS are descriptions of conditions which are always true at well defined // points of execution. Invariants may be checked by the caller or callee at any // time as paranoia requires. // // There are really two flavors of invariant. The "public invariant" describes // to the caller invariant behavior about the abstraction which is visible from // the public API (and of course it should be expressible in that public API). // // The "internal invariant" (or representation invariant), on the other hand, is // a description of the private implementation of the abstraction, which may examine // internal state of the abstraction or use private entry points. // // Classes with invariants should introduce methods called // void Invariant(); // and // void InternalInvariant(); // to allow invariant checks. //-------------------------------------------------------------------------------- #if CHECK_INVARIANTS template CHECK CheckInvariant(TYPENAME &obj) { #if defined(_MSC_VER) || defined(__llvm__) __if_exists(TYPENAME::Invariant) { CHECK(obj.Invariant()); } __if_exists(TYPENAME::InternalInvariant) { CHECK(obj.InternalInvariant()); } #endif CHECK_OK; } #define CHECK_INVARIANT(o) \ ASSERT_CHECK(CheckInvariant(o), NULL, "Invariant failure") #else #define CHECK_INVARIANT(o) do { } while (0) #endif //-------------------------------------------------------------------------------- // VALIDATE is a check to be made on an object type which identifies a pointer as // a valid instance of the object, by calling CheckPointer on it. Normally a null // pointer is treated as an error; VALIDATE_NULL (or CheckPointer(o, NULL_OK)) // may be used when a null pointer is acceptible. // // In addition to the null/non-null check, a type may provide a specific Check method // for more sophisticated identification. In general, the Check method // should answer the question // "Is this a valid instance of its declared compile-time type?". For instance, if // runtype type identification were supported for the type, it should be invoked here. // // Note that CheckPointer will also check the invariant(s) if appropriate, so the // invariants should NOT be explicitly invoked from the Check method. //-------------------------------------------------------------------------------- enum IsNullOK { NULL_NOT_OK = 0, NULL_OK = 1 }; #if CHECK_INVARIANTS template CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK) { if (o == NULL) { CHECK_MSG(ok, "Illegal null pointer"); } else { #if defined(_MSC_VER) || defined(__llvm__) __if_exists(TYPENAME::Check) { CHECK(o->Check()); } #endif } CHECK_OK; } template CHECK CheckValue(TYPENAME &val) { #if defined(_MSC_VER) || defined(__llvm__) __if_exists(TYPENAME::Check) { CHECK(val.Check()); } #endif CHECK(CheckInvariant(val)); CHECK_OK; } #else // CHECK_INVARIANTS #ifdef _DEBUG_IMPL // Don't defined these functions to be nops for the non-debug // build as it may hide important checks template CHECK CheckPointer(TYPENAME *o, IsNullOK ok = NULL_NOT_OK) { if (o == NULL) { CHECK_MSG(ok, "Illegal null pointer"); } CHECK_OK; } template CHECK CheckValue(TYPENAME &val) { CHECK_OK; } #endif #endif // CHECK_INVARIANTS #if VALIDATE_OBJECTS #define VALIDATE(o) \ ASSERT_CHECK(CheckPointer(o), "Validation failure") #define VALIDATE_NULL(o) \ ASSERT_CHECK(CheckPointer(o, NULL_OK), "Validation failure") #else #define VALIDATE(o) do { } while (0) #define VALIDATE_NULL(o) do { } while (0) #endif //-------------------------------------------------------------------------------- // CONSISTENCY_CHECKS are ad-hoc assertions about the expected state of the program // at a given time. A failure in one of these indicates a bug in the code. // // Note that the condition may either be a raw boolean expression or a CHECK result // returned from a Check routine. //-------------------------------------------------------------------------------- #define CONSISTENCY_CHECK(_condition) \ CONSISTENCY_CHECK_MSG(_condition, "") #ifdef _DEBUG_IMPL #define CONSISTENCY_CHECK_MSG(_condition, _message) \ ASSERT_CHECK(_condition, _message, "Consistency check failed") #define CONSISTENCY_CHECK_MSGF(_condition, args) \ ASSERT_CHECKF(_condition, "Consistency check failed", args) #else #define CONSISTENCY_CHECK_MSG(_condition, _message) do { } while (0) #define CONSISTENCY_CHECK_MSGF(_condition, args) do { } while (0) #endif //-------------------------------------------------------------------------------- // SIMPLIFYING_ASSUMPTIONS are workarounds which are placed in the code to allow progress // to be made in the case of difficult corner cases. These should NOT be left in the // code; they are really just markers of things which need to be fixed. // // Note that the condition may either be a raw boolean expression or a CHECK result // returned from a Check routine. //-------------------------------------------------------------------------------- // Ex usage: // SIMPLIFYING_ASSUMPTION(SomeExpression()); #define SIMPLIFYING_ASSUMPTION(_condition) \ SIMPLIFYING_ASSUMPTION_MSG(_condition, "") // Helper for HRs. Will provide formatted message showing the failure code. #define SIMPLIFYING_ASSUMPTION_SUCCEEDED(__hr) \ { \ HRESULT __hr2 = (__hr); \ (void)__hr2; \ SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(__hr2), ("HRESULT failed.\n Expected success.\n Actual=0x%x\n", __hr2)); \ } #ifdef _DEBUG_IMPL // Ex usage: // SIMPLIFYING_ASSUMPTION_MSG(SUCCEEDED(hr), "It failed!"); #define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) \ ASSERT_CHECK(_condition, _message, "Unhandled special case detected") // use a formatted string. Ex usage: // SIMPLIFYING_ASSUMPTION_MSGF(SUCCEEDED(hr), ("Woah it failed! 0x%08x", hr)); #define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) \ ASSERT_CHECKF(_condition, "Unhandled special case detected", args) #else // !_DEBUG_IMPL #define SIMPLIFYING_ASSUMPTION_MSG(_condition, _message) do { } while (0) #define SIMPLIFYING_ASSUMPTION_MSGF(_condition, args) do { } while (0) #endif // !_DEBUG_IMPL //-------------------------------------------------------------------------------- // COMPILER_ASSUME_MSG is a statement that tells the compiler to assume the // condition is true. In a checked build these turn into asserts; // in a free build they are passed through to the compiler to use in optimization. //-------------------------------------------------------------------------------- #if defined(_PREFAST_) || defined(_PREFIX_) || defined(__clang_analyzer__) #define COMPILER_ASSUME_MSG(_condition, _message) if (!(_condition)) __UNREACHABLE(); #define COMPILER_ASSUME_MSGF(_condition, args) if (!(_condition)) __UNREACHABLE(); #else #if defined(DACCESS_COMPILE) #define COMPILER_ASSUME_MSG(_condition, _message) do { } while (0) #define COMPILER_ASSUME_MSGF(_condition, args) do { } while (0) #else #if defined(_DEBUG) #define COMPILER_ASSUME_MSG(_condition, _message) \ ASSERT_CHECK(_condition, _message, "Compiler optimization assumption invalid") #define COMPILER_ASSUME_MSGF(_condition, args) \ ASSERT_CHECKF(_condition, "Compiler optimization assumption invalid", args) #else #define COMPILER_ASSUME_MSG(_condition, _message) __assume(_condition) #define COMPILER_ASSUME_MSGF(_condition, args) __assume(_condition) #endif // _DEBUG #endif // DACCESS_COMPILE #endif // _PREFAST_ || _PREFIX_ #define COMPILER_ASSUME(_condition) \ COMPILER_ASSUME_MSG(_condition, "") //-------------------------------------------------------------------------------- // PREFIX_ASSUME_MSG and PREFAST_ASSUME_MSG are just another name // for COMPILER_ASSUME_MSG // In a checked build these turn into asserts; in a free build // they are passed through to the compiler to use in optimization; // via an __assume(_condition) optimization hint. //-------------------------------------------------------------------------------- #define PREFIX_ASSUME_MSG(_condition, _message) \ COMPILER_ASSUME_MSG(_condition, _message) #define PREFIX_ASSUME_MSGF(_condition, args) \ COMPILER_ASSUME_MSGF(_condition, args) #define PREFIX_ASSUME(_condition) \ COMPILER_ASSUME_MSG(_condition, "") #define PREFAST_ASSUME_MSG(_condition, _message) \ COMPILER_ASSUME_MSG(_condition, _message) #define PREFAST_ASSUME_MSGF(_condition, args) \ COMPILER_ASSUME_MSGF(_condition, args) #define PREFAST_ASSUME(_condition) \ COMPILER_ASSUME_MSG(_condition, "") //-------------------------------------------------------------------------------- // UNREACHABLE points are locations in the code which should not be able to be // reached under any circumstances (e.g. a default in a switch which is supposed to // cover all cases.). This macro tells the compiler this, and also embeds a check // to make sure it is always true. //-------------------------------------------------------------------------------- #define UNREACHABLE() \ UNREACHABLE_MSG("") #ifdef __llvm__ // LLVM complains if a function does not return what it says. #define UNREACHABLE_RET() do { UNREACHABLE(); return 0; } while (0) #define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message); return 0; #else // __llvm__ #define UNREACHABLE_RET() UNREACHABLE() #define UNREACHABLE_MSG_RET(_message) UNREACHABLE_MSG(_message) #endif // __llvm__ else #ifdef _DEBUG_IMPL // Note that the "do { } while (0)" syntax trick here doesn't work, as the compiler // gives an error that the while(0) is unreachable code #define UNREACHABLE_MSG(_message) \ { \ CHECK _check; \ _check.Setup(_message, "", __FILE__, __LINE__); \ _check.Trigger("Reached the \"unreachable\""); \ } __UNREACHABLE() #else #define UNREACHABLE_MSG(_message) __UNREACHABLE() #endif //-------------------------------------------------------------------------------- // STRESS_CHECK represents a check which is included in a free build // @todo: behavior on trigger // // Note that the condition may either be a raw boolean expression or a CHECK result // returned from a Check routine. // // Since Retail builds don't allow formatted checks, there's no STRESS_CHECK_MSGF. //-------------------------------------------------------------------------------- #if CHECK_STRESS #define STRESS_CHECK(_condition, _message) \ ASSERT_CHECK(_condition, _message, "Stress Assertion Failure") #else #define STRESS_CHECK(_condition, _message) do { } while (0) #endif //-------------------------------------------------------------------------------- // CONTRACT_CHECK is used to put contracts on Check function. Note that it does // not support postconditions. //-------------------------------------------------------------------------------- #define CONTRACT_CHECK CONTRACTL #define CONTRACT_CHECK_END CONTRACTL_END //-------------------------------------------------------------------------------- // CCHECK is used for Check functions which may fail due to out of memory // or other transient failures. These failures should be ignored when doing // assertions, but they cannot be ignored when the Check function is used in // normal code. // @todo: really crufty to have 2 sets of CHECK macros //-------------------------------------------------------------------------------- #ifdef _DEBUG #define CCHECK_START \ { \ BOOL ___exception = FALSE; \ BOOL ___transient = FALSE; \ CHECK ___result = CHECK::OK(); \ EX_TRY { #define CCHECK_END \ } EX_CATCH { \ if (___result.IsInAssert()) \ { \ ___exception = TRUE; \ ___transient = GET_EXCEPTION()->IsTransient(); \ } \ else \ EX_RETHROW; \ } EX_END_CATCH(RethrowTerminalExceptions); \ \ if (___exception) \ { \ if (___transient) \ CHECK_OK; \ else \ CHECK_FAIL("Nontransient exception occurred during check"); \ } \ CHECK(___result); \ } #define CRETURN_RESULT(r) ___result = r #define CCHECK_MSG(_condition, _message) \ CHECK_MSG_EX(_condition, _message, CRETURN_RESULT) #define CCHECK(_condition) \ CCHECK_MSG(_condition, "") #define CCHECK_MSGF(_condition, _args) \ CCHECK_MSG(_condition, CHECK::FormatMessage _args) #define CCHECK_FAIL(_message) \ CCHECK_MSG(FALSE, _message); UNREACHABLE() #define CCHECK_FAILF(_args) \ CCHECK_MSGF(FALSE, _args); UNREACHABLE() #else // _DEBUG #define CCHECK_START #define CCHECK_END #define CCHECK CHECK #define CCHECK_MSG CHECK_MSG #define CCHECK_MSGF CHECK_MSGF #define CCHECK_FAIL CHECK_FAIL #define CCHECK_FAILF CHECK_FAILF #endif //-------------------------------------------------------------------------------- // Common base level checks //-------------------------------------------------------------------------------- CHECK CheckAlignment(UINT alignment); CHECK CheckAligned(UINT value, UINT alignment); #if defined(_MSC_VER) CHECK CheckAligned(ULONG value, UINT alignment); #endif CHECK CheckAligned(UINT64 value, UINT alignment); CHECK CheckAligned(const void *address, UINT alignment); CHECK CheckOverflow(UINT value1, UINT value2); #if defined(_MSC_VER) CHECK CheckOverflow(ULONG value1, ULONG value2); #endif CHECK CheckOverflow(UINT64 value1, UINT64 value2); CHECK CheckOverflow(PTR_CVOID address, UINT offset); #if defined(_MSC_VER) CHECK CheckOverflow(const void *address, ULONG offset); #endif CHECK CheckOverflow(const void *address, UINT64 offset); CHECK CheckUnderflow(UINT value1, UINT value2); #if defined(_MSC_VER) CHECK CheckUnderflow(ULONG value1, ULONG value2); #endif CHECK CheckUnderflow(UINT64 value1, UINT64 value2); CHECK CheckUnderflow(const void *address, UINT offset); #if defined(_MSC_VER) CHECK CheckUnderflow(const void *address, ULONG offset); #endif CHECK CheckUnderflow(const void *address, UINT64 offset); CHECK CheckUnderflow(const void *address, void *address2); CHECK CheckZeroedMemory(const void *memory, SIZE_T size); // These include overflow checks CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset); CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size); void WINAPI ReleaseCheckTls(LPVOID pTlsData); // ================================================================================ // Inline definitions // ================================================================================ #include "check.inl" #endif // CHECK_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/check.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef CHECK_INL_ #define CHECK_INL_ #include "check.h" #include "clrhost.h" #include "debugmacros.h" #include "clrtypes.h" FORCEINLINE BOOL CHECK::EnterAssert() { if (s_neverEnforceAsserts) return FALSE; #ifdef _DEBUG_IMPL m_pCount = &t_count; if (!*m_pCount) { *m_pCount = 1; return TRUE; } else return FALSE; #else // Don't bother doing recursive checks on a free build, since checks should // be extremely isolated return TRUE; #endif } FORCEINLINE void CHECK::LeaveAssert() { #ifdef _DEBUG_IMPL *m_pCount = 0; #endif } FORCEINLINE BOOL CHECK::IsInAssert() { #ifdef _DEBUG_IMPL if (!m_pCount) m_pCount = &t_count; return *m_pCount; #else return FALSE; #endif } FORCEINLINE BOOL CHECK::EnforceAssert() { if (s_neverEnforceAsserts) return FALSE; else { CHECK chk; return !chk.IsInAssert(); } } FORCEINLINE void CHECK::ResetAssert() { CHECK chk; if (chk.IsInAssert()) chk.LeaveAssert(); } inline void CHECK::SetAssertEnforcement(BOOL value) { s_neverEnforceAsserts = !value; } // Fail records the result of a condition check. Can take either a // boolean value or another check result FORCEINLINE BOOL CHECK::Fail(BOOL condition) { #ifdef _DEBUG if (!condition) { m_condition = NULL; m_file = NULL; m_line = 0; } #endif return !condition; } FORCEINLINE BOOL CHECK::Fail(const CHECK &check) { m_message = check.m_message; #ifdef _DEBUG if (m_message != NULL) { m_condition = check.m_condition; m_file = check.m_file; m_line = check.m_line; } #endif return m_message != NULL; } #ifndef _DEBUG FORCEINLINE void CHECK::Setup(LPCSTR message) { m_message = message; } FORCEINLINE LPCSTR CHECK::FormatMessage(LPCSTR messageFormat, ...) { return messageFormat; } #endif FORCEINLINE CHECK::operator BOOL () { return m_message == NULL; } FORCEINLINE BOOL CHECK::operator!() { return m_message != NULL; } inline CHECK CheckAlignment(UINT alignment) { STATIC_CONTRACT_WRAPPER; CHECK((alignment & (alignment-1)) == 0); CHECK_OK; } inline CHECK CheckAligned(UINT value, UINT alignment) { STATIC_CONTRACT_WRAPPER; CHECK(AlignmentTrim(value, alignment) == 0); CHECK_OK; } #ifndef HOST_UNIX // For Unix this and the previous function get the same types. // So, exclude this one. inline CHECK CheckAligned(ULONG value, UINT alignment) { STATIC_CONTRACT_WRAPPER; CHECK(AlignmentTrim(value, alignment) == 0); CHECK_OK; } #endif // HOST_UNIX inline CHECK CheckAligned(UINT64 value, UINT alignment) { STATIC_CONTRACT_WRAPPER; CHECK(AlignmentTrim(value, alignment) == 0); CHECK_OK; } inline CHECK CheckAligned(const void *address, UINT alignment) { STATIC_CONTRACT_WRAPPER; CHECK(AlignmentTrim((SIZE_T)address, alignment) == 0); CHECK_OK; } inline CHECK CheckOverflow(UINT value1, UINT value2) { CHECK(value1 + value2 >= value1); CHECK_OK; } #if defined(_MSC_VER) inline CHECK CheckOverflow(ULONG value1, ULONG value2) { CHECK(value1 + value2 >= value1); CHECK_OK; } #endif inline CHECK CheckOverflow(UINT64 value1, UINT64 value2) { CHECK(value1 + value2 >= value1); CHECK_OK; } inline CHECK CheckOverflow(PTR_CVOID address, UINT offset) { TADDR targetAddr = dac_cast(address); #if POINTER_BITS == 32 CHECK((UINT) (SIZE_T)(targetAddr) + offset >= (UINT) (SIZE_T) (targetAddr)); #else CHECK((UINT64) targetAddr + offset >= (UINT64) targetAddr); #endif CHECK_OK; } #if defined(_MSC_VER) inline CHECK CheckOverflow(const void *address, ULONG offset) { #if POINTER_BITS == 32 CHECK((ULONG) (SIZE_T) address + offset >= (ULONG) (SIZE_T) address); #else CHECK((UINT64) address + offset >= (UINT64) address); #endif CHECK_OK; } #endif inline CHECK CheckOverflow(const void *address, UINT64 offset) { #if POINTER_BITS == 32 CHECK(offset >> 32 == 0); CHECK((UINT) (SIZE_T) address + (UINT) offset >= (UINT) (SIZE_T) address); #else CHECK((UINT64) address + offset >= (UINT64) address); #endif CHECK_OK; } #ifdef __APPLE__ inline CHECK CheckOverflow(const void *address, SIZE_T offset) { CHECK((UINT64) address + offset >= (UINT64) address); CHECK_OK; } #endif // __APPLE__ inline CHECK CheckUnderflow(UINT value1, UINT value2) { CHECK(value1 - value2 <= value1); CHECK_OK; } #ifndef HOST_UNIX // For Unix this and the previous function get the same types. // So, exclude this one. inline CHECK CheckUnderflow(ULONG value1, ULONG value2) { CHECK(value1 - value2 <= value1); CHECK_OK; } #endif // HOST_UNIX inline CHECK CheckUnderflow(UINT64 value1, UINT64 value2) { CHECK(value1 - value2 <= value1); CHECK_OK; } inline CHECK CheckUnderflow(const void *address, UINT offset) { #if POINTER_BITS == 32 CHECK((UINT) (SIZE_T) address - offset <= (UINT) (SIZE_T) address); #else CHECK((UINT64) address - offset <= (UINT64) address); #endif CHECK_OK; } #if defined(_MSC_VER) inline CHECK CheckUnderflow(const void *address, ULONG offset) { #if POINTER_BITS == 32 CHECK((ULONG) (SIZE_T) address - offset <= (ULONG) (SIZE_T) address); #else CHECK((UINT64) address - offset <= (UINT64) address); #endif CHECK_OK; } #endif inline CHECK CheckUnderflow(const void *address, UINT64 offset) { #if POINTER_BITS == 32 CHECK(offset >> 32 == 0); CHECK((UINT) (SIZE_T) address - (UINT) offset <= (UINT) (SIZE_T) address); #else CHECK((UINT64) address - offset <= (UINT64) address); #endif CHECK_OK; } inline CHECK CheckUnderflow(const void *address, void *address2) { #if POINTER_BITS == 32 CHECK((UINT) (SIZE_T) address - (UINT) (SIZE_T) address2 <= (UINT) (SIZE_T) address); #else CHECK((UINT64) address - (UINT64) address2 <= (UINT64) address); #endif CHECK_OK; } inline CHECK CheckZeroedMemory(const void *memory, SIZE_T size) { CHECK(CheckOverflow(memory, size)); BYTE *p = (BYTE *) memory; BYTE *pEnd = p + size; while (p < pEnd) CHECK(*p++ == 0); CHECK_OK; } inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset) { CHECK(CheckOverflow(dac_cast(rangeBase), rangeSize)); CHECK(offset <= rangeSize); CHECK_OK; } inline CHECK CheckBounds(const void *rangeBase, UINT32 rangeSize, UINT32 offset, UINT32 size) { CHECK(CheckOverflow(dac_cast(rangeBase), rangeSize)); CHECK(CheckOverflow(offset, size)); CHECK(offset + size <= rangeSize); CHECK_OK; } #endif // CHECK_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr/fs/path.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // This header provides general path-related file system services. #ifndef _clr_fs_Path_h_ #define _clr_fs_Path_h_ #include "clrtypes.h" #include "strsafe.h" #include "clr/str.h" namespace clr { namespace fs { class Path { public: //----------------------------------------------------------------------------------------- // Returns true if wzPath represents a relative path. static inline bool IsRelative(LPCWSTR wzPath) { _ASSERTE(wzPath != nullptr); // Similar to System.IO.Path.IsRelative() #if TARGET_UNIX if(wzPath[0] == VOLUME_SEPARATOR_CHAR_W) { return false; } #else // Check for a paths like "C:\..." or "\\...". Additional notes: // - "\\?\..." - long format paths are considered as absolute paths due to the "\\" prefix // - "\..." - these paths are relative, as they depend on the current drive // - "C:..." and not "C:\..." - these paths are relative, as they depend on the current directory for drive C if (wzPath[0] != W('\0') && wzPath[1] == VOLUME_SEPARATOR_CHAR_W && wzPath[2] == DIRECTORY_SEPARATOR_CHAR_W && ( (wzPath[0] >= W('A') && wzPath[0] <= W('Z')) || (wzPath[0] >= W('a') && wzPath[0] <= W('z')) )) { return false; } if (wzPath[0] == DIRECTORY_SEPARATOR_CHAR_W && wzPath[1] == DIRECTORY_SEPARATOR_CHAR_W) { return false; } #endif return true; } }; } } #endif // _clr_fs_Path_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr/fs.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // This header will include all headers relating to file system functionality. #ifndef _clr_fs_h_ #define _clr_fs_h_ #include "fs/path.h" #endif // _clr_fs_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr/stack.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // This header provides a basic stack implementation #ifndef _clr_Stack_h_ #define _clr_Stack_h_ namespace clr { //------------------------------------------------------------------------------------------------- // A basic stack class. // template < typename T > class Stack { private: //--------------------------------------------------------------------------------------------- struct Link { template < typename A1 > Link(A1 && a1, Link * next = nullptr) : _value(std::forward(a1)) , _next(next) {} T _value; Link * _next; }; public: //--------------------------------------------------------------------------------------------- // Empty stack constructor. Stack() : _top(nullptr) , _size(0) {} //--------------------------------------------------------------------------------------------- // Move constructor. Stack(Stack && stack) : _top(nullptr) , _size(0) { *this = std::move(stack); } //--------------------------------------------------------------------------------------------- ~Stack() { while (!empty()) { pop(); } } //--------------------------------------------------------------------------------------------- // Move assignment. Stack& operator=(Stack && stack) { std::swap(_top, stack._top); std::swap(_size, stack._size); } //--------------------------------------------------------------------------------------------- bool empty() const { return _top == nullptr; } //--------------------------------------------------------------------------------------------- size_t size() const { return _size; } //--------------------------------------------------------------------------------------------- T & top() { return _top->_value; } //--------------------------------------------------------------------------------------------- T const & top() const { return _top->_value; } //--------------------------------------------------------------------------------------------- template < typename A1 > inline void push(A1 && value) { STATIC_CONTRACT_THROWS; _top = new Link(std::forward(value), _top); ++_size; } //--------------------------------------------------------------------------------------------- void pop() { Link * del = _top; _top = _top->_next; --_size; delete del; } private: //--------------------------------------------------------------------------------------------- Link * _top; size_t _size; }; } // namespace clr #endif // _clr_Stack_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr/str.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // This header provides general standard string services. // #ifndef _clr_str_h_ #define _clr_str_h_ namespace clr { namespace str { //----------------------------------------------------------------------------------------- // Returns true if the provided string is a null pointer or the empty string. static inline bool IsNullOrEmpty(LPCWSTR wzStr) { return wzStr == nullptr || *wzStr == W('\0'); } } } #endif // _clr_str_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr/win32.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // clr/win32.h // // Provides Win32-specific utility functionality. // // #ifndef clr_win32_h #define clr_win32_h #include "winwrap.h" namespace clr { namespace win32 { // Prevents an HMODULE from being unloaded until process termination. inline HRESULT PreventModuleUnload(HMODULE hMod) { if (!WszGetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_PIN, reinterpret_cast(hMod), &hMod)) { return HRESULT_FROM_GetLastError(); } return S_OK; } } // namespace win } // namespace clr #endif // clr_win32_h ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr_std/algorithm ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // clr_std/algorithm // // Copy of some key Standard Template Library functionality #ifdef _MSC_VER #pragma once #endif #ifdef USE_STL #include #else #ifndef __clr_std_algorithm_h__ #define __clr_std_algorithm_h__ namespace std { template iter find_if ( iter first, iter last, CompareFunc comp ) { for ( ; first!=last ; first++ ) if ( comp(*first) ) break; return first; } template iter find(iter first, iter last, const T& val) { for (;first != last; first++) { if (*first == val) break; } return first; } template iter qsort_partition( iter first, iter last, iter pivot, comp compare ) { iter lastMinusOne = last - 1; swap(pivot, lastMinusOne); // Pivot is at end pivot = last - 1; iter partitionLoc = first; for (iter partitionWalk = first; partitionWalk != pivot; ++partitionWalk) { if (compare(*partitionWalk, *pivot)) { swap(*partitionWalk, *partitionLoc); partitionLoc++; } } swap(*pivot, *partitionLoc); return partitionLoc; } template void sort_worker ( iter first, iter last, comp compare ) { typename iter::difference_type RangeSize = last - first; // When down to a list of size 1, be done if (RangeSize < 2) return; // Pick pivot // Use simple pick middle algorithm iter pivotLoc = first + (RangeSize / 2); // Partition pivotLoc = qsort_partition(first, last, pivotLoc, compare); // Sort first array sort_worker(first, pivotLoc, compare); // Sort second array sort_worker(pivotLoc + 1, last, compare); } template void sort ( iter first, iter last, comp compare ) { sort_worker(first, last, compare); if (first != last) { for (iter i = first; i < (last - 1); i++) { // Assert that the sort function works. assert(!compare(*(i+1), *i)); } } } template OutIter transform( InIter first, InIter last, OutIter dest, Fn1 func ) { for ( ; first!=last ; ++first, ++dest ) *dest = func(*first); return dest; } } // namespace std #endif /* __clr_std_algorithm_h__ */ #endif // !USE_STL // Help the VIM editor figure out what kind of file this no-extension file is. // vim: filetype=cpp ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr_std/string ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // clr_std/string // // Copy of some key Standard Template Library functionality // // This was created for use with SuperPMI. It has the minimal functionality needed by SuperPMI. It hasn't // been tested elsewhere. #ifdef _MSC_VER #pragma once #endif #ifdef USE_STL #include #else #ifndef __clr_std_string_h__ #define __clr_std_string_h__ #include "clr_std/vector" namespace std { template class basic_string { public: typedef T value_type; typedef size_t size_type; typedef typename vector::iterator iterator; typedef typename vector::const_iterator const_iterator; basic_string() : m_string(1) // start with a string of length 1 for null terminator { m_string[0] = T(); } basic_string(const basic_string& _Right) { assign(_Right); } // Initialize a string with _Count characters from the string pointed at by _Ptr. // If you want to include the trailing null character, _Count needs to include that. basic_string(const value_type* _Ptr, size_type _Count) : m_string(_Count + 1) // add 1 for a null terminator { copy(_Ptr, _Count); } basic_string(const value_type* _Ptr) : basic_string(_Ptr, c_len(_Ptr)) { } void reserve(size_t newcapacity) { m_string.reserve(newcapacity + 1); // add 1 for the null terminator } // // Assignment // basic_string& operator=(const basic_string& _Right) { if (this != &_Right) { assign(_Right); } return (*this); } basic_string& assign(const basic_string& _Right) { m_string.resize(_Right.size() + 1); // +1 for null terminator copy(_Right); return (*this); } // // Basic data copying // void copy(const basic_string& _Right) { assert(size() >= _Right.size()); size_type i; for (i = 0; i < _Right.size(); i++) { m_string[i] = _Right.m_string[i]; } m_string[i] = T(); } void copy(const value_type* _Ptr, size_type _Count) { assert(size() >= _Count); size_type i; for (i = 0; i < _Count; i++) { m_string[i] = _Ptr[i]; } m_string[i] = T(); } // // Appending // // Append a C-style string to the string. basic_string& operator+=(const value_type* _Ptr) { size_type oldsize = size(); // doesn't include null terminator size_type addsize = c_len(_Ptr); // doesn't include null terminator size_type newsize = oldsize + addsize + 1; m_string.resize(newsize); size_type i; for (i = oldsize; i < newsize - 1; i++) { m_string[i] = *_Ptr++; } m_string[i] = T(); return (*this); } basic_string& operator+=(const basic_string& _Right) { size_type oldsize = size(); // doesn't include null terminator size_type addsize = _Right.size(); // doesn't include null terminator size_type newsize = oldsize + addsize + 1; m_string.resize(newsize); size_type new_index = oldsize, right_index = 0; while (right_index < addsize) { m_string[new_index] = _Right.m_string[right_index]; ++new_index; ++right_index; } m_string[new_index] = T(); return (*this); } basic_string& operator+=(value_type _Ch) { size_type oldsize = size(); // doesn't include null terminator m_string[oldsize] = _Ch; // Replace the null terminator with the new symbol. m_string.push_back(T()); // Return the replaced terminator again. return (*this); } ~basic_string() { // vector destructor does all the work } size_t size() const { assert(m_string.size() > 0); return m_string.size() - 1; // Don't report the null terminator. } size_t length() const { return size(); } T& operator[](size_t iIndex) { assert(iIndex < size() + 1); // allow looking at the null terminator return m_string[iIndex]; } const T* c_str() const { return m_string.data(); } iterator begin() { return m_string.begin(); } iterator end() { return m_string.end(); } const_iterator cbegin() const { return m_string.cbegin(); } const_iterator cend() const { return m_string.cend(); } basic_string substr(size_type _Off = 0, size_type _Count = npos) const { size_type cursize = size(); if (_Off >= cursize) { // result will be empty return basic_string(); } else { if ((_Count == npos) || // No count specified; take the whole string suffix (_Off + _Count > cursize)) // Count specified is too many characters; just take the whole suffix { _Count = cursize - _Off; } return basic_string(m_string.data() + _Off, _Count); } } size_type find_last_of(value_type _Ch) const { for (size_type _Off = size(); _Off != 0; _Off--) { if (m_string[_Off - 1] == _Ch) { return _Off - 1; } } return npos; } bool empty() const { return size() == 0; } int compare(const basic_string& _Str) const { size_type i; size_type compareSize = size(); if (_Str.size() < compareSize) { // This string is longer; compare character-by-character only as many characters as we have. compareSize = _Str.size(); } for (i = 0; i < compareSize; i++) { if (m_string[i] != _Str.m_string[i]) { if (m_string[i] < _Str.m_string[i]) { return -1; } else { return 1; } } } // All the characters we compared were identical, but one string might be longer than the other. if (size() == _Str.size()) { // We compared everything. return 0; } else if (size() < _Str.size()) { // _Str has more characters than this. return -1; } else { // this has more characters than _Str return 1; } } static const size_type npos = size_type(-1); private: // Compute the length in characters of a null-terminated C-style string, not including the trailing null character. // _Ptr must not be nullptr. size_type c_len(const value_type* _Ptr) { size_type count; for (count = 0; *_Ptr != T(); _Ptr++) { count++; } return count; } vector m_string; // use a vector<> to represent the string, to avoid reimplementing similar functionality }; // class basic_string // // String class instantiations // typedef basic_string string; // // Numeric conversions // // convert integer T to string template inline string _IntToString(const char *_Fmt, T _Val) { const size_t MaxIntBufSize = 21; /* can hold -2^63 and 2^64 - 1, plus NUL */ char buf[MaxIntBufSize]; int len = sprintf_s(buf, MaxIntBufSize, _Fmt, _Val); return (string(buf, len)); } inline string to_string(int _Val) { return (_IntToString("%d", _Val)); } inline string to_string(unsigned int _Val) { return (_IntToString("%u", _Val)); } inline string to_string(long _Val) { return (_IntToString("%ld", _Val)); } inline string to_string(unsigned long _Val) { return (_IntToString("%lu", _Val)); } inline string to_string(long long _Val) { return (_IntToString("%lld", _Val)); } inline string to_string(unsigned long long _Val) { return (_IntToString("%llu", _Val)); } // // Comparisons // template inline bool operator==( const basic_string& _Left, const basic_string& _Right) { return (_Left.compare(_Right) == 0); } template inline bool operator!=( const basic_string& _Left, const basic_string& _Right) { return (!(_Left == _Right)); } template inline bool operator<( const basic_string& _Left, const basic_string& _Right) { return (_Left.compare(_Right) < 0); } template inline bool operator>( const basic_string& _Left, const basic_string& _Right) { return (_Right < _Left); } template inline bool operator<=( const basic_string& _Left, const basic_string& _Right) { return (!(_Right < _Left)); } template inline bool operator>=( const basic_string& _Left, const basic_string& _Right) { return (!(_Left < _Right)); } // // String concatenation and other string operations // template inline basic_string operator+( const basic_string& _Left, const basic_string& _Right) { basic_string ret; ret.reserve(_Left.size() + _Right.size()); ret += _Left; ret += _Right; return ret; } }; // namespace std #endif /* __clr_std_string_h__ */ #endif // !USE_STL // Help the VIM editor figure out what kind of file this no-extension file is. // vim: filetype=cpp ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr_std/type_traits ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // clr_std/utility // // Copy of some key Standard Template Library functionality. // See http://msdn.microsoft.com/en-us/library/bb982077.aspx for documentation. // #ifdef _MSC_VER #pragma once #endif #ifndef __clr_std_type_traits_h__ #define __clr_std_type_traits_h__ #ifdef USE_STL #include #else namespace std { //----------------------------------------------------------------------------------------- // TEMPLATE CLASS remove_const template struct remove_const { // remove top level const qualifier typedef _Ty type; }; template struct remove_const { // remove top level const qualifier typedef _Ty type; }; template struct remove_const { // remove top level const qualifier typedef _Ty type[]; }; template struct remove_const { // remove top level const qualifier typedef _Ty type[_Nx]; }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS remove_volatile template struct remove_volatile { // remove top level volatile qualifier typedef _Ty type; }; template struct remove_volatile { // remove top level volatile qualifier typedef _Ty type; }; template struct remove_volatile { // remove top level volatile qualifier typedef _Ty type[]; }; template struct remove_volatile { // remove top level volatile qualifier typedef _Ty type[_Nx]; }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS remove_cv template struct remove_cv { // remove top level const and volatile qualifiers typedef typename remove_const::type>::type type; }; //----------------------------------------------------------------------------------------- // TEMPLATE remove_reference template struct remove_reference { // remove reference typedef T type; }; template struct remove_reference { // remove reference typedef T type; }; template struct remove_reference { // remove rvalue reference typedef T type; }; //----------------------------------------------------------------------------------------- // TEMPLATE remove_pointer template struct remove_pointer { // remove pointer typedef T type; }; template struct remove_pointer { // remove pointer typedef T type; }; //----------------------------------------------------------------------------------------- // TEMPLATE FUNCTION identity template struct identity { // map T to type unchanged typedef T type; inline const T& operator()(const T& left) const { // apply identity operator to operand return (left); } }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS integral_constant template struct integral_constant { // convenient template for integral constant types static const _Ty value = _Val; typedef _Ty value_type; typedef integral_constant<_Ty, _Val> type; }; typedef integral_constant true_type; typedef integral_constant false_type; // TEMPLATE CLASS _Cat_base template struct _Cat_base : false_type { // base class for type predicates }; template<> struct _Cat_base : true_type { // base class for type predicates }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS enable_if template struct enable_if { // type is undefined for assumed !_Test }; template struct enable_if { // type is _Type for _Test typedef _Type type; }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS conditional template struct conditional { // type is _Ty2 for assumed !_Test typedef _Ty2 type; }; template struct conditional { // type is _Ty1 for _Test typedef _Ty1 type; }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS make_unsigned template struct make_unsigned { }; template<> struct make_unsigned { typedef unsigned int type; }; #ifndef HOST_UNIX template<> struct make_unsigned { typedef unsigned long type; }; #endif // !HOST_UNIX template<> struct make_unsigned<__int64> { typedef unsigned __int64 type; }; template<> struct make_unsigned { typedef size_t type; }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS make_signed template struct make_signed { }; template<> struct make_signed { typedef signed int type; }; #ifndef HOST_UNIX template<> struct make_signed { typedef signed long type; }; #endif // !HOST_UNIX template<> struct make_signed { typedef signed __int64 type; }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_lvalue_reference template struct is_lvalue_reference : false_type { // determine whether _Ty is an lvalue reference }; template struct is_lvalue_reference<_Ty&> : true_type { // determine whether _Ty is an lvalue reference }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_rvalue_reference template struct is_rvalue_reference : false_type { // determine whether _Ty is an rvalue reference }; template struct is_rvalue_reference<_Ty&&> : true_type { // determine whether _Ty is an rvalue reference }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_reference template struct is_reference : conditional< is_lvalue_reference<_Ty>::value || is_rvalue_reference<_Ty>::value, true_type, false_type>::type { // determine whether _Ty is a reference }; // TEMPLATE CLASS is_pointer template struct is_pointer : false_type { // determine whether _Ty is a pointer }; template struct is_pointer<_Ty *> : true_type { // determine whether _Ty is a pointer }; // TEMPLATE CLASS _Is_integral template struct _Is_integral : false_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; // On Unix 'long' is a 64-bit type (same as __int64) and the following two definitions // conflict with _Is_integral and _Is_integral. #ifndef HOST_UNIX template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; #endif /* HOST_UNIX */ #if _HAS_CHAR16_T_LANGUAGE_SUPPORT template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; #endif /* _HAS_CHAR16_T_LANGUAGE_SUPPORT */ template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; template<> struct _Is_integral : true_type { // determine whether _Ty is integral }; // TEMPLATE CLASS is_integral template struct is_integral : _Is_integral::type> { // determine whether _Ty is integral }; // TEMPLATE CLASS _Is_floating_point template struct _Is_floating_point : false_type { // determine whether _Ty is floating point }; template<> struct _Is_floating_point : true_type { // determine whether _Ty is floating point }; template<> struct _Is_floating_point : true_type { // determine whether _Ty is floating point }; // In PAL, we define long as int and so this becomes int double, // which is a nonsense #ifndef HOST_UNIX template<> struct _Is_floating_point : true_type { // determine whether _Ty is floating point }; #endif // TEMPLATE CLASS is_floating_point template struct is_floating_point : _Is_floating_point::type> { // determine whether _Ty is floating point }; // TEMPLATE CLASS is_arithmetic template struct is_arithmetic : _Cat_base::value || is_floating_point<_Ty>::value> { // determine whether _Ty is an arithmetic type }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_signed template struct is_signed : conditional< static_cast::type>(-1) < 0, true_type, false_type>::type {}; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_same template struct is_same : false_type { }; //----------------------------------------------------------------------------------------- template struct is_same : true_type { }; //----------------------------------------------------------------------------------------- // TEMPLATE CLASS is_base_of #ifdef _MSC_VER template struct is_base_of : conditional<__is_base_of( TBase, TDerived), true_type, false_type>::type {}; #else namespace detail { //------------------------------------------------------------------------------------- // Helper types Small and Big - guarantee that sizeof(Small) < sizeof(Big) // template struct conversion_helper { typedef char Small; struct Big { char dummy[2]; }; static Big Test(...); static Small Test(U); static T MakeT(); }; //------------------------------------------------------------------------------------- // class template conversion // Figures out the conversion relationships between two types // Invocations (T and U are types): // a) conversion::exists // returns (at compile time) true if there is an implicit conversion from T // to U (example: Derived to Base) // b) conversion::exists2Way // returns (at compile time) true if there are both conversions from T // to U and from U to T (example: int to char and back) // c) conversion::sameType // returns (at compile time) true if T and U represent the same type // // NOTE: might not work if T and U are in a private inheritance hierarchy. // template struct conversion { typedef detail::conversion_helper H; static const bool exists = sizeof(typename H::Small) == sizeof((H::Test(H::MakeT()))); static const bool exists2Way = exists && conversion::exists; static const bool sameType = false; }; template struct conversion { static const bool exists = true; static const bool exists2Way = true; static const bool sameType = true; }; template struct conversion { static const bool exists = false; static const bool exists2Way = false; static const bool sameType = false; }; template struct conversion { static const bool exists = false; static const bool exists2Way = false; static const bool sameType = false; }; template <> struct conversion { static const bool exists = true; static const bool exists2Way = true; static const bool sameType = true; }; } // detail // Note that we need to compare pointer types here, since conversion of types by-value // just tells us whether or not an implicit conversion constructor exists. We handle // type parameters that are already pointers specially; see below. template struct is_base_of : conditional::exists, true_type, false_type>::type {}; // Specialization to handle type parameters that are already pointers. template struct is_base_of : conditional::exists, true_type, false_type>::type {}; // Specialization to handle invalid mixing of pointer types. template struct is_base_of : false_type {}; // Specialization to handle invalid mixing of pointer types. template struct is_base_of : false_type {}; #endif namespace detail { template using void_t = void; } // Always false dependent-value for static_asserts. template struct _Always_false { const bool value = false; }; template struct _Add_reference { // add reference (non-referenceable type) using _Lvalue = _Ty; using _Rvalue = _Ty; }; template struct _Add_reference<_Ty, detail::void_t<_Ty&>> { // (referenceable type) using _Lvalue = _Ty&; using _Rvalue = _Ty&&; }; template struct add_lvalue_reference { using type = typename _Add_reference<_Ty>::_Lvalue; }; template struct add_rvalue_reference { using type = typename _Add_reference<_Ty>::_Rvalue; }; template typename add_rvalue_reference<_Ty>::type declval() noexcept { static_assert(_Always_false<_Ty>::value, "Calling declval is ill-formed, see N4892 [declval]/2."); } } // namespace std #endif // !USE_STL #define REM_CONST(T) typename std::remove_const< T >::type #define REM_CV(T) typename std::remove_cv< T >::type #define REM_REF(T) typename std::remove_reference< T >::type #define REF_T(T) REM_REF(T) & #define REF_CT(T) REM_REF(REM_CONST(T)) const & #endif // __clr_std_type_traits_h__ // Help the VIM editor figure out what kind of file this no-extension file is. // vim: filetype=cpp ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr_std/utility ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // clr_std/utility // // Copy of some key Standard Template Library functionality // See http://msdn.microsoft.com/en-us/library/bb982077.aspx for documentation. // #ifdef _MSC_VER #pragma once #endif #ifdef USE_STL #include #else #ifndef __clr_std_utility_h__ #define __clr_std_utility_h__ #include "clr_std/type_traits" namespace std { //----------------------------------------------------------------------------------------- // TEMPLATE FUNCTION move template inline typename remove_reference::type&& move(T&& arg) { // forward _Arg as movable return ((typename remove_reference::type&&)arg); } //----------------------------------------------------------------------------------------- // TEMPLATE FUNCTION swap (from ) template inline void swap(T& left, T& right) { // exchange values stored at left and right T tmp = std::move(left); left = std::move(right); right = std::move(tmp); } //----------------------------------------------------------------------------------------- // TEMPLATE FUNCTION forward template inline T&& forward(typename identity::type& _Arg) { // forward _Arg, given explicitly specified type parameter return ((T&&)_Arg); } } namespace std { //----------------------------------------------------------------------------------------- // TEMPLATE STRUCT pair template struct pair { // store a pair of values typedef pair<_Ty1, _Ty2> _Myt; typedef _Ty1 first_type; typedef _Ty2 second_type; pair() : first(_Ty1()), second(_Ty2()) { // construct from defaults } pair(const _Ty1& _Val1, const _Ty2& _Val2) : first(_Val1.first), second(_Val2.second) { // construct from specified values } template pair(pair<_Other1, _Other2>& _Right) : first(_Right.first), second(_Right.second) { // construct from compatible pair } template pair(const pair<_Other1, _Other2>& _Right) : first(_Right.first), second(_Right.second) { // construct from compatible pair } void swap(_Myt& _Right) { // exchange contents with _Right if (this != &_Right) { // different, worth swapping swap(this->first, _Right.first); swap(this->second, _Right.second); } } _Myt& operator=(const _Myt& _Right) { // assign from copied pair this->first = _Right.first; this->second = _Right.second; return (*this); } typedef typename remove_reference<_Ty1>::type _Ty1x; typedef typename remove_reference<_Ty2>::type _Ty2x; pair(_Ty1x&& _Val1, _Ty2x&& _Val2) : first(std::move(_Val1)), second(std::move(_Val2)) { // construct from specified values } pair(const _Ty1x& _Val1, _Ty2x&& _Val2) : first(_Val1), second(std::move(_Val2)) { // construct from specified values } pair(_Ty1x&& _Val1, const _Ty2x& _Val2) : first(std::move(_Val1)), second(_Val2) { // construct from specified values } template pair(_Other1&& _Val1, _Other2&& _Val2) : first(std::move(_Val1)), second(std::move(_Val2)) { // construct from moved values } template pair(pair<_Other1, _Other2>&& _Right) : first(std::move(_Right.first)), second(std::move(_Right.second)) { // construct from moved compatible pair } pair& operator=(pair<_Ty1, _Ty2>&& _Right) { // assign from moved pair this->first = std::move(_Right.first); this->second = std::move(_Right.second); return (*this); } void swap(_Myt&& _Right) { // exchange contents with _Right if (this != &_Right) { // different, worth swapping this->first = std::move(_Right.first); this->second = std::move(_Right.second); } } _Ty1 first; // the first stored value _Ty2 second; // the second stored value }; // struct pair //----------------------------------------------------------------------------------------- // pair TEMPLATE FUNCTIONS template inline void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>& _Right) { // swap _Left and _Right pairs _Left.swap(_Right); } template inline void swap(pair<_Ty1, _Ty2>& _Left, pair<_Ty1, _Ty2>&& _Right) { // swap _Left and _Right pairs typedef pair<_Ty1, _Ty2> _Myt; _Left.swap(std::forward<_Myt>(_Right)); } template inline void swap( pair<_Ty1, _Ty2>&& _Left, pair<_Ty1, _Ty2>& _Right) { // swap _Left and _Right pairs typedef pair<_Ty1, _Ty2> _Myt; _Right.swap(std::forward<_Myt>(_Left)); } template inline bool operator==( const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test for pair equality return (_Left.first == _Right.first && _Left.second == _Right.second); } template inline bool operator!=( const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test for pair inequality return (!(_Left == _Right)); } template inline bool operator<( const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test if _Left < _Right for pairs return (_Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second)); } template inline bool operator>( const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test if _Left > _Right for pairs return (_Right < _Left); } template inline bool operator<=( const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test if _Left <= _Right for pairs return (!(_Right < _Left)); } template inline bool operator>=( const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test if _Left >= _Right for pairs return (!(_Left < _Right)); } template inline _InIt begin( const pair<_InIt, _InIt>& _Pair) { // return first element of pair return (_Pair.first); } template inline _InIt end( const pair<_InIt, _InIt>& _Pair) { // return second element of pair return (_Pair.second); } } // namespace std #endif /* __clr_std_utility_h__ */ #endif // !USE_STL // Help the VIM editor figure out what kind of file this no-extension file is. // vim: filetype=cpp ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clr_std/vector ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // clr_std/vector // // Copy of some key Standard Template Library functionality // #ifdef _MSC_VER #pragma once #endif #ifdef USE_STL #include #else #ifndef __clr_std_vector_h__ #define __clr_std_vector_h__ // This is defined in the debugmacrosext.h header, but don't take a dependency on that. #ifndef INDEBUG #ifdef _DEBUG #define INDEBUG(x) x #else #define INDEBUG(x) #endif #endif // !def INDEBUG namespace std { template class vector { public: class const_iterator; class iterator { friend class std::vector::const_iterator; public: typedef T value_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef T& reference; typedef class vector::iterator _MyIter; _MyIter &operator++() { m_ptr++; return *this; } _MyIter operator++(int) { // post-increment ++ _MyIter myiter(m_ptr); m_ptr++; return myiter; } _MyIter &operator--() { m_ptr--; return *this; } _MyIter operator--(int) { // post-decrement -- _MyIter myiter(m_ptr); m_ptr--; return myiter; } _MyIter operator- (ptrdiff_t n) { _MyIter myiter(m_ptr); myiter.m_ptr -= n; return myiter; } ptrdiff_t operator- (_MyIter right) { _MyIter myiter(m_ptr); return myiter.m_ptr - right.m_ptr; } _MyIter operator+ (ptrdiff_t n) { _MyIter myiter(m_ptr); myiter.m_ptr += n; return myiter; } T* operator->() const { return m_ptr; } T & operator*() const { return *m_ptr; } bool operator==(const _MyIter& _Right) const { bool equals = this->m_ptr == _Right.m_ptr; return equals; } bool operator!=(const _MyIter& _Right) const { bool equals = this->m_ptr == _Right.m_ptr; return !equals; } bool operator<(const _MyIter& _Right) const { return this->m_ptr < _Right.m_ptr; } bool operator>(const _MyIter& _Right) const { return this->m_ptr > _Right.m_ptr; } public: explicit iterator(T* ptr) { m_ptr = ptr; } private: T* m_ptr; }; // class iterator class const_iterator { public: typedef class vector::const_iterator _MyIter; typedef class vector::iterator _MyNonConstIter; _MyIter &operator++() { m_ptr++; return *this; } _MyIter operator++(int) { // post-increment ++ _MyIter myiter(m_ptr); m_ptr++; return myiter; } const T* operator->() const { return m_ptr; } const T & operator*() const { return *m_ptr; } bool operator==(const _MyIter& _Right) const { bool equals = this->m_ptr == _Right.m_ptr; return equals; } bool operator!=(const _MyIter& _Right) const { bool equals = this->m_ptr == _Right.m_ptr; return !equals; } public: explicit const_iterator(T* ptr) { m_ptr = ptr; } const_iterator(const _MyNonConstIter &nonConstIterator) { m_ptr = nonConstIterator.m_ptr; } private: T* m_ptr; }; // class const iterator public: explicit vector(size_t n = 0) { m_size = 0; m_capacity = 0; m_pelements = NULL; m_isBufferOwner = true; resize(n); } ~vector() { if (m_isBufferOwner) { erase(m_pelements, 0, m_size); delete [] (BYTE*)m_pelements; // cast to BYTE* as we don't want this delete to invoke T's dtor } else { m_size = 0; m_capacity = 0; } } vector(const vector&) = delete; vector& operator=(const vector&) = delete; vector(vector&& v) noexcept : m_size(v.m_size) , m_capacity(v.m_capacity) , m_pelements(v.m_pelements) , m_isBufferOwner(v.m_isBufferOwner) { v.m_isBufferOwner = false; } vector& operator=(vector&& v) noexcept { if (m_isBufferOwner) { erase(m_pelements, 0, m_size); delete [] (BYTE*)m_pelements; } m_size = v.m_size; m_capacity = v.m_capacity; m_pelements = v.m_pelements; m_isBufferOwner = v.m_isBufferOwner; v.m_isBufferOwner = false; return *this; } size_t size() const { return m_size; } T & operator[](size_t iIndex) { assert(iIndex < m_size); return m_pelements[iIndex]; } T & operator[](size_t iIndex) const { assert(iIndex < m_size); return m_pelements[iIndex]; } void resize(size_t newsize) { assert(m_isBufferOwner); size_t oldsize = this->size(); resize_noinit(newsize); if (newsize > oldsize) { fill_uninitialized_with_default_value(m_pelements, oldsize, newsize); } } void clear() { assert(m_isBufferOwner); resize(0); } void resize(size_t newsize, T c) { assert(m_isBufferOwner); size_t oldsize = this->size(); resize_noinit(newsize); if (newsize > oldsize) { for (size_t i = oldsize; i < newsize; i++) { m_pelements[i] = c; } } } void wrap(size_t numElements, T* pElements) { m_size = numElements; m_pelements = pElements; m_isBufferOwner = false; } void resize_noinit(size_t newsize) { assert(m_isBufferOwner); size_t oldsize = this->size(); if (newsize < oldsize) { // Shrink erase(m_pelements, newsize, oldsize); } else if (newsize > oldsize) { // Grow reserve(newsize); } m_size = newsize; } void push_back(const T & val) { assert(m_isBufferOwner); if (m_size + 1 < m_size) { assert("push_back: overflow"); // @todo: how to throw. } resize(m_size + 1, val); } void reserve(size_t newcapacity) { assert(m_isBufferOwner); if (newcapacity > m_capacity) { // To avoid resizing for every element that gets added to a vector, we // allocate at least twice the old capacity, or 16 elements, whichever is greater. newcapacity = max(newcapacity, max(m_capacity * 2, 16)); size_t bytesNeeded = newcapacity * sizeof(T); if (bytesNeeded / sizeof(T) != newcapacity) { assert("resize: overflow"); // @todo: how to throw something here? } T *pelements = (T*)(new BYTE[bytesNeeded]); // Allocate as BYTE array to avoid automatic construction INDEBUG(memset(pelements, 0xcc, bytesNeeded)); for (size_t i = 0; i < m_size; i++) { pelements[i] = m_pelements[i]; } erase(m_pelements, 0, m_size); delete [] (BYTE*)m_pelements; // cast to BYTE* as we don't want this delete to invoke T's dtor m_pelements = pelements; m_capacity = newcapacity; } } iterator begin() { return iterator(m_pelements); } iterator end() { return iterator(m_pelements + m_size); } const_iterator cbegin() const { return const_iterator(m_pelements); } const_iterator cend() const { return const_iterator(m_pelements + m_size); } iterator erase(iterator position) { assert(m_isBufferOwner); assert((position > begin() || position == begin()) && position < end()); ptrdiff_t index = position - begin(); erase(m_pelements, index, index + 1); memcpy(&m_pelements[index], &m_pelements[index + 1], sizeof(T) * (m_size - index - 1)); --m_size; return iterator(m_pelements + (position - begin())); } iterator erase(iterator position, iterator positionEnd) { assert(m_isBufferOwner); assert((position > begin() || position == begin()) && position < end()); ptrdiff_t index = position - begin(); ptrdiff_t elements = positionEnd - position; erase(m_pelements, index, index + elements); memcpy(&m_pelements[index], &m_pelements[index + elements], sizeof(T) * (m_size - index - elements)); m_size -= elements; return iterator(m_pelements + (position - begin())); } T* data() { return m_pelements; } const T* data() const { return m_pelements; } private: // Transition a subset of the array from uninitialized to initialized with default value for T. static void fill_uninitialized_with_default_value(T* pelements, size_t startIdx, size_t endIdx) { assert(startIdx <= endIdx); assert(pelements != NULL || startIdx == endIdx); for (size_t i = startIdx; i < endIdx; i++) { INDEBUG(assert(0xcc == *((BYTE*)&pelements[i]))); pelements[i] = T(); } } // Transition a subset of the array from a valid value of T to uninitialized. static void erase(T* pelements, size_t startIdx, size_t endIdx) { assert(startIdx <= endIdx); assert(pelements != NULL || startIdx == endIdx); for (size_t i = startIdx; i < endIdx; i++) { pelements[i].~T(); } INDEBUG(memset(&pelements[startIdx], 0xcc, (endIdx - startIdx) * sizeof(T))); } private: size_t m_size; //# of elements size_t m_capacity; //# of elements allocated T *m_pelements; //actual array // invariants: // dimensions == m_capacity // elements 0 thru m_size-1 always contain constructed T values. // elements from m_size thru m_capacity - 1 contain memory garbage (0xcc in DEBUG). bool m_isBufferOwner; // indicate if this vector creates its own buffer, or wraps an existing buffer. }; // class vector }; // namespace std #endif /* __clr_std_vector_h__ */ #endif // !USE_STL // Help the VIM editor figure out what kind of file this no-extension file is. // vim: filetype=cpp ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrconfig.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // -------------------------------------------------------------------------------------------------- // CLRConfig.h // // // Unified method of accessing configuration values. // To define a flag, add an entry in the table in file:CLRConfigValues.h. // -------------------------------------------------------------------------------------------------- #include "utilcode.h" #include "holder.h" #ifndef __CLRConfig_h__ #define __CLRConfig_h__ class CLRConfig { public: // Setting each option results in some change to the config value. enum class LookupOptions { // Default options. Default = 0, // If set, do not prepend prefix when doing environment variable lookup. DontPrependPrefix = 0x1, // Remove any whitespace at beginning and end of value. (Only applicable for // *string* configuration values.) TrimWhiteSpaceFromStringValue = 0x2, // The configuration should be parsed using a 10 radix as opposed to the // default of 16. ParseIntegerAsBase10 = 0x4, }; // Struct used to store information about where/how to find a Config DWORD. // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead. typedef struct ConfigDWORDInfo { LPCWSTR name; DWORD defaultValue; LookupOptions options; } ConfigDWORDInfo; // Struct used to store information about where/how to find a Config String. // NOTE: Please do NOT create instances of this struct. Use the macros in file:CLRConfigValues.h instead. typedef struct ConfigStringInfo { LPCWSTR name; LookupOptions options; } ConfigStringInfo; // // Declaring structs using the macro table in CLRConfigValues.h // // These macros declare ConfigDWORDInfo structs. #define RETAIL_CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \ static const ConfigDWORDInfo symbol; #define RETAIL_CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \ static const ConfigDWORDInfo symbol; // These macros declare ConfigStringInfo structs. #define RETAIL_CONFIG_STRING_INFO(symbol, name, description) \ static const ConfigStringInfo symbol; #define RETAIL_CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \ static const ConfigStringInfo symbol; // // Debug versions of the macros // #ifdef _DEBUG #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) \ static const ConfigDWORDInfo symbol; #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) \ static const ConfigDWORDInfo symbol; #define CONFIG_STRING_INFO(symbol, name, description) \ static const ConfigStringInfo symbol; #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) \ static const ConfigStringInfo symbol; #else #define CONFIG_DWORD_INFO(symbol, name, defaultValue, description) #define CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) #define CONFIG_STRING_INFO(symbol, name, description) #define CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) #endif // _DEBUG // Now that we have defined what what the macros in file:CLRConfigValues.h mean, include it to generate the code. #include "clrconfigvalues.h" #undef RETAIL_CONFIG_DWORD_INFO #undef RETAIL_CONFIG_STRING_INFO #undef RETAIL_CONFIG_DWORD_INFO_EX #undef RETAIL_CONFIG_STRING_INFO_EX #undef CONFIG_DWORD_INFO #undef CONFIG_STRING_INFO #undef CONFIG_DWORD_INFO_EX #undef CONFIG_STRING_INFO_EX // // Methods to do config value (DWORD and String) lookups. // static BOOL IsConfigEnabled(const ConfigDWORDInfo & info); // Look up a DWORD config value. static DWORD GetConfigValue(const ConfigDWORDInfo & info); // Look up a DWORD config value. static DWORD GetConfigValue(const ConfigDWORDInfo & info, /* [Out] */ bool *isDefault); // Look up a DWORD config value. static DWORD GetConfigValue(const ConfigDWORDInfo & info, DWORD defaultValue); // Look up a string config value. // You own the string that's returned. static LPWSTR GetConfigValue(const ConfigStringInfo & info); // Look up a string config value, passing it out through a pointer reference. Reports out of memory // errors (HRESULT E_OUTOFMEMORY). // You own the string that's returned. static HRESULT GetConfigValue(const ConfigStringInfo & info, _Outptr_result_z_ LPWSTR * outVal); // // Check whether an option is specified (e.g. explicitly listed) in the CLRConfig. // static BOOL IsConfigOptionSpecified(LPCWSTR name); // Free a string returned by GetConfigValue static void FreeConfigString(_In_ _In_z_ LPWSTR name); // Initialize the configuration. static void Initialize(); }; inline CLRConfig::LookupOptions operator|(CLRConfig::LookupOptions lhs, CLRConfig::LookupOptions rhs) { return static_cast(static_cast(lhs) | static_cast(rhs)); } inline CLRConfig::LookupOptions operator&(CLRConfig::LookupOptions lhs, CLRConfig::LookupOptions rhs) { return static_cast(static_cast(lhs) & static_cast(rhs)); } typedef Wrapper CLRConfigStringHolder; #endif //__CLRConfig_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrconfignocache.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // -------------------------------------------------------------------------------------------------- // clrconfignocache.h // // Logic for resolving configuration names. // #include // Config prefixes #define COMPLUS_PREFIX_A "COMPlus_" #define COMPLUS_PREFIX W("COMPlus_") #define LEN_OF_COMPLUS_PREFIX STRING_LENGTH(COMPLUS_PREFIX_A) #define DOTNET_PREFIX_A "DOTNET_" #define DOTNET_PREFIX W("DOTNET_") #define LEN_OF_DOTNET_PREFIX STRING_LENGTH(DOTNET_PREFIX_A) class CLRConfigNoCache { const char* _value; CLRConfigNoCache() = default; CLRConfigNoCache(LPCSTR cfg) : _value { cfg } { } public: bool IsSet() const { return _value != NULL; } LPCSTR AsString() const { _ASSERTE(IsSet()); return _value; } bool TryAsInteger(int radix, DWORD& result) const { _ASSERTE(IsSet()); errno = 0; LPSTR endPtr; result = strtoul(_value, &endPtr, radix); bool fSuccess = (errno != ERANGE) && (endPtr != _value); return fSuccess; } static CLRConfigNoCache Get(LPCSTR cfg, bool noPrefix = false, char*(*getEnvFptr)(const char*) = nullptr) { char nameBuffer[64]; const char* fallbackPrefix = NULL; const size_t namelen = strlen(cfg); if (noPrefix) { if (namelen >= ARRAY_SIZE(nameBuffer)) { _ASSERTE(!"Environment variable name too long."); return {}; } *nameBuffer = '\0'; } else { bool dotnetValid = namelen < (size_t)(STRING_LENGTH(nameBuffer) - LEN_OF_DOTNET_PREFIX); bool complusValid = namelen < (size_t)(STRING_LENGTH(nameBuffer) - LEN_OF_COMPLUS_PREFIX); if (!dotnetValid || !complusValid) { _ASSERTE(!"Environment variable name too long."); return {}; } // Priority order is DOTNET_ and then COMPlus_. strcpy_s(nameBuffer, ARRAY_SIZE(nameBuffer), DOTNET_PREFIX_A); fallbackPrefix = COMPLUS_PREFIX_A; } strcat_s(nameBuffer, ARRAY_SIZE(nameBuffer), cfg); LPCSTR val = getEnvFptr != NULL ? getEnvFptr(nameBuffer) : getenv(nameBuffer); if (val == NULL && fallbackPrefix != NULL) { strcpy_s(nameBuffer, ARRAY_SIZE(nameBuffer), fallbackPrefix); strcat_s(nameBuffer, ARRAY_SIZE(nameBuffer), cfg); val = getEnvFptr != NULL ? getEnvFptr(nameBuffer) : getenv(nameBuffer); } return { val }; } }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrconfigvalues.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // CLRConfigValues.h // // // Unified method of accessing configuration values from environment variables, // registry and config file. // // Given any config knob below that looks like this example: // RETAIL_CONFIG_DWORD_INFO(INTERNAL_LogEnable, W("LogEnable"), 0, "Turns on the traditional CLR log.") // --------- // | // -------------------- // | // V // You can set an environment variable DOTNET_LogEnable=1 to enable it. // // See below for more details // //***************************************************************************** // IMPORTANT: Before adding a new config value, please read up on naming conventions (see // code:#NamingConventions) // // ========== // CONTENTS // ========== // * How to define config values (see code:#Define) // * How to access config values (see code:#Access) // * Naming conventions (see code:#NamingConventions) // // // ===================================== // #Define - Use one of the following macros to define config values. (See code:#DWORDs and code:#Strings) // ===================================== // // By default, all macros are DEBUG ONLY. Add the "RETAIL_" prefix to make the config value available in retail builds. // // #DWORDs: // -------------------------------------------------------------------------- // CONFIG_DWORD_INFO(symbol, name, defaultValue, description) // -------------------------------------------------------------------------- // Use this macro to define a basic DWORD value. CLRConfig will look in environment variables (adding // DOTNET_ to the name) for this value. To customize // where CLRConfig looks, use the extended version of the macro below. IMPORTANT: please follow the // code:#NamingConventions for the symbol and the name! // // Example: CONFIG_DWORD_INFO(INTERNAL_AllowCrossModuleInlining, W("AllowCrossModuleInlining"), 0, "") // // -------------------------------------------------------------------------- // CONFIG_DWORD_INFO_EX(symbol, name, defaultValue, description, lookupOptions) // -------------------------------------------------------------------------- // To customize where CLRConfig looks to get a DWORD, use the extended (_EX) version of the macro. For a list // of options and their descriptions, see code:CLRConfig.LookupOptions // // Example: CONFIG_DWORD_INFO_EX(INTERNAL_EnableInternetHREFexes, W("EnableInternetHREFexes"), 0, "", // (CLRConfig::LookupOptions) (CLRConfig::LookupOptions::DontPrependPrefix)) // // #Strings: // -------------------------------------------------------------------------- // CONFIG_STRING_INFO(symbol, name, description) // -------------------------------------------------------------------------- // Defines a string value. Same rules apply as DWORDs. // // -------------------------------------------------------------------------- // CONFIG_STRING_INFO_EX(symbol, name, description, lookupOptions) // -------------------------------------------------------------------------- // Extended version of the String macro. Again, similar to the DWORD extended macro. // // // =============================================================== // #Access - Use the following overloaded method to access config values. // =============================================================== // From anywhere, use CLRConfig::GetConfigValue(CLRConfig::) to access any value defined in this // file. // // // =============================================================== // #NamingConventions // =============================================================== // ---------------- // #Symbol - used to access values from the source. (using CLRConfig::) // ---------------- // The symbol for each config value is named as such: // ### __ ### // // indicates which of the following buckets the value is in: // * INTERNAL ? this value is for internal (CLR team) use only // * UNSUPPORTED ? this value is available to partners/developers, but is not officially supported // * EXTERNAL ? this value is available for anyone to use and is publicly documented // // Examples: // * INTERNAL_Security_FullAccessChecks // * UNSUPPORTED_Security_DisableTransparency // * EXTERNAL_Security_LegacyHMACMode // // ---------------- // #Name - the name of the registry value or environment variable that CLRConfig looks up. // ---------------- // The name of each value is the same as the symbol, with one exception. Names of external values do NOT // contain the EXTERNAL prefix. // // For compatibility reasons, current names do not follow the convention. // // Examples: // * W("INTERNAL_Security_FullAccessChecks") // * W("UNSUPPORTED_Security_DisableTransparency") // * W("Security_LegacyHMACMode") <---------------------- (No EXTERNAL prefix) /// /// AppDomain /// CONFIG_DWORD_INFO(INTERNAL_EnableFullDebug, W("EnableFullDebug"), 0, "Heavy-weight checking for AD boundary violations (AD leaks)") /// /// Jit Pitching /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchEnabled, W("JitPitchEnabled"), (DWORD)0, "Set it to 1 to enable Jit Pitching") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMemThreshold, W("JitPitchMemThreshold"), (DWORD)0, "Do Jit Pitching when code heap usage is larger than this (in bytes)") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMethodSizeThreshold, W("JitPitchMethodSizeThreshold"), (DWORD)0, "Do Jit Pitching for methods whose native code size larger than this (in bytes)") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchTimeInterval, W("JitPitchTimeInterval"), (DWORD)0, "Time interval between Jit Pitchings in ms") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchPrintStat, W("JitPitchPrintStat"), (DWORD)0, "Print statistics about Jit Pitching") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMinVal, W("JitPitchMinVal"), (DWORD)0, "Do Jit Pitching if the value of the inner counter greater than this value (for debugging purpose only)") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitPitchMaxVal, W("JitPitchMaxVal"), (DWORD)0xffffffff, "Do Jit Pitching the value of the inner counter less then this value (for debuggin purpose only)") /// /// Assembly Loader /// CONFIG_DWORD_INFO(INTERNAL_GetAssemblyIfLoadedIgnoreRidMap, W("GetAssemblyIfLoadedIgnoreRidMap"), 0, "Used to force loader to ignore assemblies cached in the rid-map") /// /// Conditional breakpoints /// RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BreakOnBadExit, W("BreakOnBadExit"), 0, "") CONFIG_STRING_INFO(INTERNAL_BreakOnClassBuild, W("BreakOnClassBuild"), "Very useful for debugging class layout code.") CONFIG_STRING_INFO(INTERNAL_BreakOnClassLoad, W("BreakOnClassLoad"), "Very useful for debugging class loading code.") CONFIG_STRING_INFO(INTERNAL_BreakOnComToClrNativeInfoInit, W("BreakOnComToClrNativeInfoInit"), "Throws an assert when native information about a COM -> CLR call are about to be gathered.") CONFIG_DWORD_INFO(INTERNAL_BreakOnDebugBreak, W("BreakOnDebugBreak"), 0, "Allows an assert in debug builds when a user break is hit") CONFIG_DWORD_INFO(INTERNAL_BreakOnDILoad, W("BreakOnDILoad"), 0, "Allows an assert when the DI is loaded") CONFIG_DWORD_INFO(INTERNAL_BreakOnDumpToken, W("BreakOnDumpToken"), 0xffffffff, "Breaks when using internal logging on a particular token value.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BreakOnEELoad, W("BreakOnEELoad"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnEEShutdown, W("BreakOnEEShutdown"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnExceptionInGetThrowable, W("BreakOnExceptionInGetThrowable"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnFindMethod, W("BreakOnFindMethod"), 0, "Breaks in findMethodInternal when it searches for the specified token.") CONFIG_DWORD_INFO(INTERNAL_BreakOnFirstPass, W("BreakOnFirstPass"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnHR, W("BreakOnHR"), 0, "Debug.cpp, IfFailxxx use this macro to stop if hr matches ") CONFIG_STRING_INFO(INTERNAL_BreakOnInstantiation, W("BreakOnInstantiation"), "Very useful for debugging generic class instantiation.") CONFIG_STRING_INFO(INTERNAL_BreakOnInteropStubSetup, W("BreakOnInteropStubSetup"), "Throws an assert when marshaling stub for the given method is about to be built.") CONFIG_STRING_INFO(INTERNAL_BreakOnInteropVTableBuild, W("BreakOnInteropVTableBuild"), "Specifies a type name for which an assert should be thrown when building interop v-table.") CONFIG_STRING_INFO(INTERNAL_BreakOnMethodName, W("BreakOnMethodName"), "Very useful for debugging method override placement code.") CONFIG_DWORD_INFO(INTERNAL_BreakOnNotify, W("BreakOnNotify"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnSecondPass, W("BreakOnSecondPass"), 0, "") CONFIG_STRING_INFO(INTERNAL_BreakOnStructMarshalSetup, W("BreakOnStructMarshalSetup"), "Throws an assert when field marshalers for the given type with layout are about to be created.") CONFIG_DWORD_INFO(INTERNAL_BreakOnUEF, W("BreakOnUEF"), 0, "") CONFIG_DWORD_INFO(INTERNAL_BreakOnUncaughtException, W("BreakOnUncaughtException"), 0, "") /// /// Debugger /// RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableDiagnostics, W("EnableDiagnostics"), 1, "Allows the debugger, profiler, and EventPipe diagnostics to be disabled") CONFIG_DWORD_INFO(INTERNAL_D__FCE, W("D::FCE"), 0, "Allows an assert when crawling the managed stack for an exception handler") CONFIG_DWORD_INFO(INTERNAL_DbgBreakIfLocksUnavailable, W("DbgBreakIfLocksUnavailable"), 0, "Allows an assert when the debugger can't take a lock ") CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnErr, W("DbgBreakOnErr"), 0, "Allows an assert when we get a failing hresult") CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnMapPatchToDJI, W("DbgBreakOnMapPatchToDJI"), 0, "Allows an assert when mapping a patch to an address") CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnRawInt3, W("DbgBreakOnRawInt3"), 0, "Allows an assert for test coverage for debug break or other int3 breaks") CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnSendBreakpoint, W("DbgBreakOnSendBreakpoint"), 0, "Allows an assert when sending a breakpoint to the right side") CONFIG_DWORD_INFO(INTERNAL_DbgBreakOnSetIP, W("DbgBreakOnSetIP"), 0, "Allows an assert when setting the IP") CONFIG_DWORD_INFO(INTERNAL_DbgCheckInt3, W("DbgCheckInt3"), 0, "Asserts if the debugger explicitly writes int3 instead of calling SetUnmanagedBreakpoint") CONFIG_DWORD_INFO(INTERNAL_DbgDACAssertOnMismatch, W("DbgDACAssertOnMismatch"), 0, "Allows an assert when the mscordacwks and mscorwks dll versions don't match") CONFIG_DWORD_INFO(INTERNAL_DbgDACEnableAssert, W("DbgDACEnableAssert"), 0, "Enables extra validity checking in DAC - assumes target isn't corrupt") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDACSkipVerifyDlls, W("DbgDACSkipVerifyDlls"), 0, "Allows disabling the check to ensure mscordacwks and mscorwks dll versions match") CONFIG_DWORD_INFO(INTERNAL_DbgDelayHelper, W("DbgDelayHelper"), 0, "Varies the wait in the helper thread startup for testing race between threads") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgDisableDynamicSymsCompat, W("DbgDisableDynamicSymsCompat"), 0, "") CONFIG_DWORD_INFO(INTERNAL_DbgDisableTargetConsistencyAsserts, W("DbgDisableTargetConsistencyAsserts"), 0, "Allows explicitly testing with corrupt targets") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreads, W("DbgExtraThreads"), 0, "Allows extra unmanaged threads to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsCantStop, W("DbgExtraThreadsCantStop"), 0, "Allows extra unmanaged threads in can't stop region to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsIB, W("DbgExtraThreadsIB"), 0, "Allows extra in-band unmanaged threads to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgExtraThreadsOOB, W("DbgExtraThreadsOOB"), 0, "Allows extra out of band unmanaged threads to run and throw debug events for stress testing") CONFIG_DWORD_INFO(INTERNAL_DbgFaultInHandleIPCEvent, W("DbgFaultInHandleIPCEvent"), 0, "Allows testing the unhandled event filter") CONFIG_DWORD_INFO(INTERNAL_DbgInjectFEE, W("DbgInjectFEE"), 0, "Allows injecting a fatal execution error for testing Watson") CONFIG_DWORD_INFO(INTERNAL_DbgLeakCheck, W("DbgLeakCheck"), 0, "Allows checking for leaked Cordb objects") CONFIG_DWORD_INFO(INTERNAL_DbgNo2ndChance, W("DbgNo2ndChance"), 0, "Allows breaking on (and catching bogus) 2nd chance exceptions") CONFIG_DWORD_INFO(INTERNAL_DbgNoDebugger, W("DbgNoDebugger"), 0, "Allows breaking if we don't want to lazily initialize the debugger") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgNoForceContinue, W("DbgNoForceContinue"), 1, "Used to force a continue on longhorn") CONFIG_DWORD_INFO(INTERNAL_DbgNoOpenMDByFile, W("DbgNoOpenMDByFile"), 0, "Allows opening MD by memory for perf testing") CONFIG_DWORD_INFO(INTERNAL_DbgOOBinFEEE, W("DbgOOBinFEEE"), 0, "Allows forcing oob breakpoints when a fatal error occurs") CONFIG_DWORD_INFO(INTERNAL_DbgPingInterop, W("DbgPingInterop"), 0, "Allows checking for deadlocks in interop debugging") CONFIG_DWORD_INFO(INTERNAL_DbgRace, W("DbgRace"), 0, "Allows pausing for native debug events to get hijicked") CONFIG_DWORD_INFO(INTERNAL_DbgShortcutCanary, W("DbgShortcutCanary"), 0, "Allows a way to force canary to fail to be able to test failure paths") CONFIG_DWORD_INFO(INTERNAL_DbgSkipMEOnStep, W("DbgSkipMEOnStep"), 0, "Turns off MethodEnter checks") CONFIG_DWORD_INFO(INTERNAL_DbgSkipVerCheck, W("DbgSkipVerCheck"), 0, "Allows different RS and LS versions (for servicing work)") CONFIG_DWORD_INFO(INTERNAL_DbgTC, W("DbgTC"), 0, "Allows checking boundary compression for offset mappings") CONFIG_DWORD_INFO(INTERNAL_DbgTransportFaultInject, W("DbgTransportFaultInject"), 0, "Allows injecting a fault for testing the debug transport") CONFIG_DWORD_INFO(INTERNAL_DbgTransportLog, W("DbgTransportLog"), 0 /* LE_None */, "Turns on logging for the debug transport") CONFIG_DWORD_INFO(INTERNAL_DbgTransportLogClass, W("DbgTransportLogClass"), (DWORD)-1 /* LC_All */, "Mask to control what is logged in DbgTransportLog") RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_DbgTransportProxyAddress, W("DbgTransportProxyAddress"), "Allows specifying the transport proxy address") CONFIG_DWORD_INFO(INTERNAL_DbgTrapOnSkip, W("DbgTrapOnSkip"), 0, "Allows breaking when we skip a breakpoint") CONFIG_DWORD_INFO(INTERNAL_DbgWaitTimeout, W("DbgWaitTimeout"), 1, "Specifies the timeout value for waits") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgWFDETimeout, W("DbgWFDETimeout"), 25, "Specifies the timeout value for wait when waiting for a debug event") CONFIG_DWORD_INFO(INTERNAL_RaiseExceptionOnAssert, W("RaiseExceptionOnAssert"), 0, "Raise a first chance (if set to 1) or second chance (if set to 2) exception on asserts.") CONFIG_DWORD_INFO(INTERNAL_DebugBreakOnVerificationFailure, W("DebugBreakOnVerificationFailure"), 0, "Halts the jit on verification failure") CONFIG_STRING_INFO(INTERNAL_DebuggerBreakPoint, W("DebuggerBreakPoint"), "Allows counting various debug events") CONFIG_STRING_INFO(INTERNAL_DebugVerify, W("DebugVerify"), "Control for tracing in peverify") CONFIG_DWORD_INFO(INTERNAL_EncApplyChanges, W("EncApplyChanges"), 0, "Allows breaking when ApplyEditAndContinue is called") CONFIG_DWORD_INFO(INTERNAL_EnCBreakOnRemapComplete, W("EnCBreakOnRemapComplete"), 0, "Allows breaking after N RemapCompletes") CONFIG_DWORD_INFO(INTERNAL_EnCBreakOnRemapOpportunity, W("EnCBreakOnRemapOpportunity"), 0, "Allows breaking after N RemapOpportunities") CONFIG_DWORD_INFO(INTERNAL_EncDumpApplyChanges, W("EncDumpApplyChanges"), 0, "Allows dumping edits in delta metadata and il files") CONFIG_DWORD_INFO(INTERNAL_EncFixupFieldBreak, W("EncFixupFieldBreak"), 0, "Unlikely that this is used anymore.") CONFIG_DWORD_INFO(INTERNAL_EncJitUpdatedFunction, W("EncJitUpdatedFunction"), 0, "Allows breaking when an updated function is jitted") CONFIG_DWORD_INFO(INTERNAL_EnCResolveField, W("EnCResolveField"), 0, "Allows breaking when computing the address of an EnC-added field") CONFIG_DWORD_INFO(INTERNAL_EncResumeInUpdatedFunction, W("EncResumeInUpdatedFunction"), 0, "Allows breaking when execution resumes in a new EnC version of a function") CONFIG_DWORD_INFO(INTERNAL_DbgAssertOnDebuggeeDebugBreak, W("DbgAssertOnDebuggeeDebugBreak"), 0, "If non-zero causes the managed-only debugger to assert on unhandled breakpoints in the debuggee") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgDontResumeThreadsOnUnhandledException, W("UNSUPPORTED_DbgDontResumeThreadsOnUnhandledException"), 0, "If non-zero, then don't try to unsuspend threads after continuing a 2nd-chance native exception") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DbgSkipStackCheck, W("DbgSkipStackCheck"), 0, "Skip the stack pointer check during stackwalking") #ifdef DACCESS_COMPILE CONFIG_DWORD_INFO(INTERNAL_DumpGeneration_IntentionallyCorruptDataFromTarget, W("IntentionallyCorruptDataFromTarget"), 0, "Intentionally fakes bad data retrieved from target to try and break dump generation.") #endif // Note that Debugging_RequiredVersion is sometimes an 'INTERNAL' knob and sometimes an 'UNSUPPORTED' knob, but we don't change it's name. CONFIG_DWORD_INFO(UNSUPPORTED_Debugging_RequiredVersion, W("UNSUPPORTED_Debugging_RequiredVersion"), 0, "The lowest ICorDebug version we should attempt to emulate, or 0 for default policy. Use 2 for CLRv2, 4 for CLRv4, etc.") #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS RETAIL_CONFIG_DWORD_INFO(INTERNAL_MiniMdBufferCapacity, W("MiniMdBufferCapacity"), 64 * 1024, "The max size of the buffer to store mini metadata information for triage- and mini-dumps.") #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS CONFIG_DWORD_INFO(INTERNAL_DbgNativeCodeBpBindsAcrossVersions, W("DbgNativeCodeBpBindsAcrossVersions"), 0, "If non-zero causes native breakpoints at offset 0 to bind in all tiered compilation versions of the given method") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RichDebugInfo, W("RichDebugInfo"), 0, "If non-zero store some additional debug information for each jitted method") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_OutOfProcessSetContext, W("OutOfProcessSetContext"), 0, "If enabled the debugger will not modify thread contexts in-process. Enabled by default when CET is enabled for the process.") /// /// Diagnostics (internal general-purpose) /// CONFIG_DWORD_INFO(INTERNAL_ConditionalContracts, W("ConditionalContracts"), 0, "If ENABLE_CONTRACTS_IMPL is defined, sets whether contracts are conditional. (?)") CONFIG_DWORD_INFO(INTERNAL_ConsistencyCheck, W("ConsistencyCheck"), 0, "") CONFIG_DWORD_INFO(INTERNAL_ContinueOnAssert, W("ContinueOnAssert"), 0, "If set, doesn't break on asserts.") CONFIG_DWORD_INFO(INTERNAL_InjectFatalError, W("InjectFatalError"), 0, "") CONFIG_DWORD_INFO(INTERNAL_InjectFault, W("InjectFault"), 0, "") CONFIG_DWORD_INFO(INTERNAL_SuppressChecks, W("SuppressChecks"),0, "") #ifdef FEATURE_EH_FUNCLETS CONFIG_DWORD_INFO(INTERNAL_SuppressLockViolationsOnReentryFromOS, W("SuppressLockViolationsOnReentryFromOS"), 0, "64 bit OOM tests re-enter the CLR via RtlVirtualUnwind. This indicates whether to suppress resulting locking violations.") #endif // FEATURE_EH_FUNCLETS /// /// Exception Handling /// CONFIG_DWORD_INFO(INTERNAL_AssertOnFailFast, W("AssertOnFailFast"), 1, "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_legacyCorruptedStateExceptionsPolicy, W("legacyCorruptedStateExceptionsPolicy"), 0, "Enabled Pre-V4 CSE behavior") CONFIG_DWORD_INFO(INTERNAL_SuppressLostExceptionTypeAssert, W("SuppressLostExceptionTypeAssert"), 0, "") RETAIL_CONFIG_DWORD_INFO(INTERNAL_UseEntryPointFilter, W("UseEntryPointFilter"), 0, "") RETAIL_CONFIG_DWORD_INFO(INTERNAL_Corhost_Swallow_Uncaught_Exceptions, W("Corhost_Swallow_Uncaught_Exceptions"), 0, "") /// /// Garbage collector /// CONFIG_DWORD_INFO(INTERNAL_FastGCCheckStack, W("FastGCCheckStack"), 0, "") CONFIG_DWORD_INFO(INTERNAL_FastGCStress, W("FastGCStress"), 0, "Reduce the number of GCs done by enabling GCStress") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCBreakOnOOM, W("GCBreakOnOOM"), 0, "Does a DebugBreak at the soonest time we detect an OOM") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcConcurrent, W("gcConcurrent"), (DWORD)-1, "Enables/Disables concurrent GC") #ifdef FEATURE_CONSERVATIVE_GC RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcConservative, W("gcConservative"), 0, "Enables/Disables conservative GC") #endif RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_gcServer, W("gcServer"), 0, "Enables server GC") CONFIG_STRING_INFO(INTERNAL_GcCoverage, W("GcCoverage"), "Specify a method or regular expression of method names to run with GCStress") CONFIG_STRING_INFO(INTERNAL_SkipGCCoverage, W("SkipGcCoverage"), "Specify a list of assembly names to skip with GC Coverage") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StatsUpdatePeriod, W("StatsUpdatePeriod"), 60, "Specifies the interval, in seconds, at which to update the statistics") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCRetainVM, W("GCRetainVM"), 0, "When set we put the segments that should be deleted on a standby list (instead of releasing them back to the OS) which will be considered to satisfy new segment requests (note that the same thing can be specified via API which is the supported way)") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCLOHThreshold, W("GCLOHThreshold"), 0, "Specifies the size that will make objects go on LOH") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_gcAllowVeryLargeObjects, W("gcAllowVeryLargeObjects"), 1, "Allow allocation of 2GB+ objects on GC heap") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCStress, W("GCStress"), 0, "Trigger GCs at regular intervals") CONFIG_DWORD_INFO(INTERNAL_GcStressOnDirectCalls, W("GcStressOnDirectCalls"), 0, "Whether to trigger a GC on direct calls") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_HeapVerify, W("HeapVerify"), 0, "When set verifies the integrity of the managed heap on entry and exit of each GC") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCCpuGroup, W("GCCpuGroup"), 0, "Specifies if to enable GC to support CPU groups") RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCName, W("GCName"), "") /** * This flag allows us to force the runtime to use global allocation context on Windows x86/amd64 instead of thread allocation context just for testing purpose. * The flag is unsafe for a subtle reason. Although the access to the g_global_alloc_context is protected under a lock. The implementation of * that lock in the JIT helpers are not multi-core safe (in particular, it used and inc instruction without using the LOCK prefix). This is * only useful for ad-hoc testing. */ CONFIG_DWORD_INFO(INTERNAL_GCUseGlobalAllocationContext, W("GCUseGlobalAllocationContext"), 0, "Force using the global allocation context for testing only") /// /// JIT /// CONFIG_DWORD_INFO(INTERNAL_JitBreakEmit, W("JitBreakEmit"), (DWORD)-1, "") CONFIG_DWORD_INFO(INTERNAL_JitDebuggable, W("JitDebuggable"), 0, "") #if !defined(DEBUG) && !defined(_DEBUG) #define INTERNAL_JitEnableNoWayAssert_Default 0 #else #define INTERNAL_JitEnableNoWayAssert_Default 1 #endif RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitEnableNoWayAssert, W("JitEnableNoWayAssert"), INTERNAL_JitEnableNoWayAssert_Default, "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_JitFramed, W("JitFramed"), 0, "Forces EBP frames") CONFIG_DWORD_INFO(INTERNAL_JitThrowOnAssertionFailure, W("JitThrowOnAssertionFailure"), 0, "Throw managed exception on assertion failures during JIT instead of failfast") CONFIG_DWORD_INFO(INTERNAL_JitGCStress, W("JitGCStress"), 0, "GC stress mode for jit") CONFIG_DWORD_INFO(INTERNAL_JitHeartbeat, W("JitHeartbeat"), 0, "") CONFIG_DWORD_INFO(INTERNAL_JitHelperLogging, W("JitHelperLogging"), 0, "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_JITMinOpts, W("JITMinOpts"), 0, "Forces MinOpts") RETAIL_CONFIG_STRING_INFO(EXTERNAL_JitName, W("JitName"), "Primary jit to use") CONFIG_STRING_INFO(INTERNAL_JitPath, W("JitPath"), "Full path to primary jit to use") #if defined(ALLOW_SXS_JIT) RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitName, W("AltJitName"), "Alternative jit to use, will fall back to primary jit.") CONFIG_STRING_INFO(INTERNAL_AltJitPath, W("AltJitPath"), "Full path to alternative jit to use") RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJit, W("AltJit"), "Enables AltJit and selectively limits it to the specified methods.") RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitOs, W("AltJitOS"), "Sets target OS for AltJit or uses native one by default. Only applicable for ARM/AMR64 at the moment.") RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitExcludeAssemblies, W("AltJitExcludeAssemblies"), "Do not use AltJit on this semicolon-delimited list of assemblies.") #endif // defined(ALLOW_SXS_JIT) #if defined(FEATURE_STACK_SAMPLING) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingEnabled, W("StackSamplingEnabled"), 0, "Is stack sampling based tracking of evolving hot methods enabled.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingAfter, W("StackSamplingAfter"), 0, "When to start sampling (for some sort of app steady state), i.e., initial delay for sampling start in milliseconds.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingEvery, W("StackSamplingEvery"), 100, "How frequent should thread stacks be sampled in milliseconds.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingNumMethods, W("StackSamplingNumMethods"), 32, "Number of evolving methods to track as hot and JIT them in the background at a given point of execution.") #endif // defined(FEATURE_JIT_SAMPLING) #if defined(ALLOW_SXS_JIT_NGEN) RETAIL_CONFIG_STRING_INFO(INTERNAL_AltJitNgen, W("AltJitNgen"), "Enables AltJit for NGEN and selectively limits it to the specified methods.") #endif // defined(ALLOW_SXS_JIT_NGEN) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitHostMaxSlabCache, W("JitHostMaxSlabCache"), 0x1000000, "Sets jit host max slab cache size, 16MB default") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitOptimizeType, W("JitOptimizeType"), 0 /* OPT_DEFAULT */, "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitPrintInlinedMethods, W("JitPrintInlinedMethods"), 0, "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitTelemetry, W("JitTelemetry"), 1, "If non-zero, gather JIT telemetry data") RETAIL_CONFIG_STRING_INFO(INTERNAL_JitTimeLogFile, W("JitTimeLogFile"), "If set, gather JIT throughput data and write to this file.") RETAIL_CONFIG_STRING_INFO(INTERNAL_JitTimeLogCsv, W("JitTimeLogCsv"), "If set, gather JIT throughput data and write to a CSV file. This mode must be used in internal retail builds.") RETAIL_CONFIG_STRING_INFO(INTERNAL_JitFuncInfoLogFile, W("JitFuncInfoLogFile"), "If set, gather JIT function info and write to this file.") CONFIG_DWORD_INFO(INTERNAL_JitVerificationDisable, W("JitVerificationDisable"), 0, "") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitLockWrite, W("JitLockWrite"), 0, "Force all volatile writes to be 'locked'") CONFIG_STRING_INFO(INTERNAL_TailCallMax, W("TailCallMax"), "") RETAIL_CONFIG_STRING_INFO(EXTERNAL_TailCallOpt, W("TailCallOpt"), "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TailCallLoopOpt, W("TailCallLoopOpt"), 1, "Convert recursive tail calls to loops") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Jit_NetFx40PInvokeStackResilience, W("NetFx40_PInvokeStackResilience"), (DWORD)-1, "Makes P/Invoke resilient against mismatched signature and calling convention (significant perf penalty).") // AltJitAssertOnNYI should be 0 on targets where JIT is under development or bring up stage, so as to facilitate fallback to main JIT on hitting a NYI. #if defined(TARGET_X86) RETAIL_CONFIG_DWORD_INFO(INTERNAL_AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 0, "Controls the AltJit behavior of NYI stuff") #else RETAIL_CONFIG_DWORD_INFO(INTERNAL_AltJitAssertOnNYI, W("AltJitAssertOnNYI"), 1, "Controls the AltJit behavior of NYI stuff") #endif CONFIG_DWORD_INFO(INTERNAL_JitLargeBranches, W("JitLargeBranches"), 0, "Force using the largest conditional branch format") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitRegisterFP, W("JitRegisterFP"), 3, "Control FP enregistration") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitELTHookEnabled, W("JitELTHookEnabled"), 0, "On ARM, setting this will emit Enter/Leave/TailCall callbacks") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitVNMapSelBudget, W("JitVNMapSelBudget"), 100, "Max # of MapSelect's considered for a particular top-level invocation.") #if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64) #define EXTERNAL_FeatureSIMD_Default 1 #else // !(defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64)) #define EXTERNAL_FeatureSIMD_Default 0 #endif // !(defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64)) RETAIL_CONFIG_DWORD_INFO(INTERNAL_SIMD16ByteOnly, W("SIMD16ByteOnly"), 0, "Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit)") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TrackDynamicMethodDebugInfo, W("TrackDynamicMethodDebugInfo"), 0, "Specifies whether debug info should be generated and tracked for dynamic methods") #ifdef FEATURE_MULTICOREJIT RETAIL_CONFIG_STRING_INFO(INTERNAL_MultiCoreJitProfile, W("MultiCoreJitProfile"), "If set, use the file to store/control multi-core JIT.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_MultiCoreJitProfileWriteDelay, W("MultiCoreJitProfileWriteDelay"), 12, "Set the delay after which the multi-core JIT profile will be written to disk.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_MultiCoreJitMinNumCpus, W("MultiCoreJitMinNumCpus"), 2, "Minimum number of cpus that must be present to allow MultiCoreJit usage.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_MultiCoreJitNoProfileGather, W("MultiCoreJitNoProfileGather"), 0, "Set to 1 to disable profile gathering (but leave possibly enabled profile usage).") #endif #ifdef FEATURE_INTERPRETER /// /// Interpreter /// RETAIL_CONFIG_STRING_INFO(INTERNAL_Interpret, W("Interpret"), "Selectively uses the interpreter to execute the specified methods") RETAIL_CONFIG_STRING_INFO(INTERNAL_InterpretExclude, W("InterpretExclude"), "Excludes the specified methods from the set selected by 'Interpret'") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterMethHashMin, W("InterpreterMethHashMin"), 0, "Only interpret methods selected by 'Interpret' whose hash is at least this value. or after nth") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterMethHashMax, W("InterpreterMethHashMax"), UINT32_MAX, "If non-zero, only interpret methods selected by 'Interpret' whose hash is at most this value") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterStubMin, W("InterpreterStubMin"), 0, "Only interpret methods selected by 'Interpret' whose stub num is at least this value.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterStubMax, W("InterpreterStubMax"), UINT32_MAX, "If non-zero, only interpret methods selected by 'Interpret' whose stub number is at most this value.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterJITThreshold, W("InterpreterJITThreshold"), 10, "The number of times a method should be interpreted before being JITted") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterDoLoopMethods, W("InterpreterDoLoopMethods"), 0, "If set, don't check for loops, start by interpreting *all* methods") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterUseCaching, W("InterpreterUseCaching"), 1, "If non-zero, use the caching mechanism.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterLooseRules, W("InterpreterLooseRules"), 1, "If non-zero, allow ECMA spec violations required by managed C++.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterPrintPostMortem, W("InterpreterPrintPostMortem"), 0, "Prints summary information about the execution to the console") RETAIL_CONFIG_STRING_INFO(INTERNAL_InterpreterLogFile, W("InterpreterLogFile"), "If non-null, append interpreter logging to this file, else use stdout") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DumpInterpreterStubs, W("DumpInterpreterStubs"), 0, "Prints all interpreter stubs that are created to the console") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterEntries, W("TraceInterpreterEntries"), 0, "Logs entries to interpreted methods to the console") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterIL, W("TraceInterpreterIL"), 0, "Logs individual instructions of interpreted methods to the console") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterOstack, W("TraceInterpreterOstack"), 0, "Logs operand stack after each IL instruction of interpreted methods to the console") CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterVerbose, W("TraceInterpreterVerbose"), 0, "Logs interpreter progress with detailed messages to the console") CONFIG_DWORD_INFO(INTERNAL_TraceInterpreterJITTransition, W("TraceInterpreterJITTransition"), 0, "Logs when the interpreter determines a method should be JITted") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ForceInterpreter, W("ForceInterpreter"), 0, "If non-zero, force the interpreter to be used") RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterHWIntrinsicsIsSupportedFalse, W("InterpreterHWIntrinsicsIsSupportedFalse"), 0, "If non-zero, force get_IsSupported to return false for hardware intrinsics") // for internal testing purposes #endif // The JIT queries this ConfigDWORD but it doesn't know if FEATURE_INTERPRETER is enabled RETAIL_CONFIG_DWORD_INFO(INTERNAL_InterpreterFallback, W("InterpreterFallback"), 0, "Fallback to the interpreter when the JIT compiler fails") /// /// Loader heap /// CONFIG_DWORD_INFO(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0, "Loader heap troubleshooting") RETAIL_CONFIG_DWORD_INFO(INTERNAL_CodeHeapReserveForJumpStubs, W("CodeHeapReserveForJumpStubs"), 1, "Percentage of code heap to reserve for jump stubs") RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnOutOfMemoryWithinRange, W("BreakOnOutOfMemoryWithinRange"), 0, "Break before out of memory within range exception is thrown") /// /// Log /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_LogEnable, W("LogEnable"), 0, "Turns on the traditional CLR log.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_LogFacility, W("LogFacility"), 0, "Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_LogFacility2, W("LogFacility2"), 0, "Specifies a facility mask for CLR log. (See 'loglf.h'; VM interprets string value as hex number.) Also used by stresslog.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_logFatalError, W("logFatalError"), 1, "Specifies whether EventReporter logs fatal errors in the Windows event log.") CONFIG_STRING_INFO(INTERNAL_LogFile, W("LogFile"), "Specifies a file name for the CLR log.") CONFIG_DWORD_INFO(INTERNAL_LogFileAppend, W("LogFileAppend"), 0 , "Specifies whether to append to or replace the CLR log file.") CONFIG_DWORD_INFO(INTERNAL_LogFlushFile, W("LogFlushFile"), 0 , "Specifies whether to flush the CLR log file on each write.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_LogLevel, W("LogLevel"), 0 , "4=10 msgs, 9=1000000, 10=everything") RETAIL_CONFIG_DWORD_INFO(INTERNAL_LogToConsole, W("LogToConsole"), 0 , "Writes the CLR log to console.") CONFIG_DWORD_INFO(INTERNAL_LogToDebugger, W("LogToDebugger"), 0 , "Writes the CLR log to debugger (OutputDebugStringA).") CONFIG_DWORD_INFO(INTERNAL_LogToFile, W("LogToFile"), 0 , "Writes the CLR log to a file.") CONFIG_DWORD_INFO(INTERNAL_LogWithPid, W("LogWithPid"), FALSE, "Appends pid to filename for the CLR log.") /// /// MetaData /// CONFIG_DWORD_INFO(INTERNAL_MD_ApplyDeltaBreak, W("MD_ApplyDeltaBreak"), 0, "ASSERT when applying EnC") RETAIL_CONFIG_DWORD_INFO(INTERNAL_AssertOnBadImageFormat, W("AssertOnBadImageFormat"), 0, "ASSERT when invalid MD read") RETAIL_CONFIG_DWORD_INFO(INTERNAL_MD_DeltaCheck, W("MD_DeltaCheck"), 1, "Some checks of GUID when applying EnC (?)") CONFIG_DWORD_INFO(INTERNAL_MD_EncDelta, W("MD_EncDelta"), 0, "Forces EnC Delta format in MD (?)") RETAIL_CONFIG_DWORD_INFO(INTERNAL_MD_ForceNoColDesSharing, W("MD_ForceNoColDesSharing"), 0, "Don't know - the only usage I could find is #if 0 (?)") CONFIG_DWORD_INFO(INTERNAL_MD_KeepKnownCA, W("MD_KeepKnownCA"), 0, "Something with known CAs (?)") CONFIG_DWORD_INFO(INTERNAL_MD_MiniMDBreak, W("MD_MiniMDBreak"), 0, "ASSERT when creating CMiniMdRw class") CONFIG_DWORD_INFO(INTERNAL_MD_PreSaveBreak, W("MD_PreSaveBreak"), 0, "ASSERT when calling CMiniMdRw::PreSave") CONFIG_DWORD_INFO(INTERNAL_MD_RegMetaBreak, W("MD_RegMetaBreak"), 0, "ASSERT when creating RegMeta class") CONFIG_DWORD_INFO(INTERNAL_MD_RegMetaDump, W("MD_RegMetaDump"), 0, "Dump MD in 4 functions (?)") RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_MODIFIABLE_ASSEMBLIES, W("MODIFIABLE_ASSEMBLIES"), "Enables hot reload on debug built assemblies with the 'debug' keyword", CLRConfig::LookupOptions::TrimWhiteSpaceFromStringValue); // Metadata - mscordbi only - this flag is only intended to mitigate potential issues in bug fix 458597. RETAIL_CONFIG_DWORD_INFO(EXTERNAL_MD_PreserveDebuggerMetadataMemory, W("MD_PreserveDebuggerMetadataMemory"), 0, "Save all versions of metadata memory in the debugger when debuggee metadata is updated") /// /// Spinning heuristics /// // Note that these only take effect once the runtime has been started; prior to that the values hardcoded in g_SpinConstants (vars.cpp) are used RETAIL_CONFIG_DWORD_INFO(EXTERNAL_SpinInitialDuration, W("SpinInitialDuration"), 0x32, "Hex value specifying the first spin duration") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_SpinBackoffFactor, W("SpinBackoffFactor"), 0x3, "Hex value specifying the growth of each successive spin duration") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_SpinLimitProcCap, W("SpinLimitProcCap"), 0xFFFFFFFF, "Hex value specifying the largest value of NumProcs to use when calculating the maximum spin duration") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_SpinLimitProcFactor, W("SpinLimitProcFactor"), 0x4E20, "Hex value specifying the multiplier on NumProcs to use when calculating the maximum spin duration") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_SpinLimitConstant, W("SpinLimitConstant"), 0x0, "Hex value specifying the constant to add when calculating the maximum spin duration") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_SpinRetryCount, W("SpinRetryCount"), 0xA, "Hex value specifying the number of times the entire spin process is repeated (when applicable)") RETAIL_CONFIG_DWORD_INFO(INTERNAL_Monitor_SpinCount, W("Monitor_SpinCount"), 0x1e, "Hex value specifying the maximum number of spin iterations Monitor may perform upon contention on acquiring the lock before waiting.") /// /// Native Binder /// CONFIG_DWORD_INFO(INTERNAL_SymDiffDump, W("SymDiffDump"), 0, "Used to create the map file while binding the assembly. Used by SemanticDiffer") /// /// Profiling API / ETW /// RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_PROFILING, W("CORECLR_ENABLE_PROFILING"), 0, "CoreCLR only: Flag to indicate whether profiling should be enabled for the currently running process.", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER, W("CORECLR_PROFILER"), "CoreCLR only: Specifies GUID of profiler to load into currently running process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH, W("CORECLR_PROFILER_PATH"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_32, W("CORECLR_PROFILER_PATH_32"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 32 process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_64, W("CORECLR_PROFILER_PATH_64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running 64 process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_ARM32, W("CORECLR_PROFILER_PATH_ARM32"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running ARM32 process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_PROFILER_PATH_ARM64, W("CORECLR_PROFILER_PATH_ARM64"), "CoreCLR only: Specifies the path to the DLL of profiler to load into currently running ARM64 process", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_CORECLR_ENABLE_NOTIFICATION_PROFILERS, W("CORECLR_ENABLE_NOTIFICATION_PROFILERS"), 0, "Set to 0 to disable loading notification profilers.", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS, W("CORECLR_NOTIFICATION_PROFILERS"), "A semi-colon separated list of notification profilers to load into currently running process in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_32, W("CORECLR_NOTIFICATION_PROFILERS_32"), "A semi-colon separated list of notification profilers to load into currently running 32 process in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_64, W("CORECLR_NOTIFICATION_PROFILERS_64"), "A semi-colon separated list of notification profilers to load into currently running 64 process in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_ARM32, W("CORECLR_NOTIFICATION_PROFILERS_ARM32"), "A semi-colon separated list of notification profilers to load into currently running ARM32 process in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_CORECLR_NOTIFICATION_PROFILERS_ARM64, W("CORECLR_NOTIFICATION_PROFILERS_ARM64"), "A semi-colon separated list of notification profilers to load into currently running ARM64 process in the form \"path={guid}\"", CLRConfig::LookupOptions::DontPrependPrefix) RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_ProfAPI_ProfilerCompatibilitySetting, W("ProfAPI_ProfilerCompatibilitySetting"), "Specifies the profiler loading policy (the default is not to load a V2 profiler in V4)", CLRConfig::LookupOptions::TrimWhiteSpaceFromStringValue) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMinSleepMs, W("ProfAPI_DetachMinSleepMs"), 0, "The minimum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_DetachMaxSleepMs, W("ProfAPI_DetachMaxSleepMs"), 0, "The maximum time, in milliseconds, the CLR will wait before checking whether a profiler that is in the process of detaching is ready to be unloaded.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_RejitOnAttach, W("ProfApi_RejitOnAttach"), 1, "Enables the ability for profilers to rejit methods on attach.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ProfAPI_InliningTracking, W("ProfApi_InliningTracking"), 1, "Enables the runtime's tracking of inlining for profiler ReJIT.") CONFIG_DWORD_INFO(INTERNAL_ProfAPI_EnableRejitDiagnostics, W("ProfAPI_EnableRejitDiagnostics"), 0, "Enable extra dumping to stdout of rejit structures") CONFIG_DWORD_INFO(INTERNAL_ProfAPIFault, W("ProfAPIFault"), 0, "Test-only bitmask to inject various types of faults in the profapi code") CONFIG_DWORD_INFO(INTERNAL_TestOnlyAllowedEventMask, W("TestOnlyAllowedEventMask"), 0, "Test-only bitmask to allow profiler tests to override CLR enforcement of COR_PRF_ALLOWABLE_AFTER_ATTACH and COR_PRF_MONITOR_IMMUTABLE") CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableICorProfilerInfo, W("ProfAPI_TestOnlyEnableICorProfilerInfo"), 0, "Test-only flag to allow attaching profiler tests to call ICorProfilerInfo interface, which would otherwise be disallowed for attaching profilers") CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableObjectAllocatedHook, W("TestOnlyEnableObjectAllocatedHook"), 0, "Test-only flag that forces CLR to initialize on startup as if ObjectAllocated callback were requested, to enable post-attach ObjectAllocated functionality.") CONFIG_DWORD_INFO(INTERNAL_TestOnlyEnableSlowELTHooks, W("TestOnlyEnableSlowELTHooks"), 0, "Test-only flag that forces CLR to initialize on startup as if slow-ELT were requested, to enable post-attach ELT functionality.") RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec, W("ETW_ObjectAllocationEventsPerTypePerSec"), "Desired number of GCSampledObjectAllocation ETW events to be logged per type per second. If 0, then the default built in to the implementation for the enabled event (e.g., High, Low), will be used.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("ProfAPI_ValidateNGENInstrumentation"), 0, "This flag enables additional validations when using the IMetaDataEmit APIs for NGEN'ed images to ensure only supported edits are made.") #ifdef FEATURE_PERFMAP RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default") RETAIL_CONFIG_STRING_INFO(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to GetTempPathA()") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.") RETAIL_CONFIG_STRING_INFO(EXTERNAL_NativeImagePerfMapFormat, W("NativeImagePerfMapFormat"), "Specifies the format of native image perfmap files generated by crossgen. Valid options are RVA or OFFSET.") #endif RETAIL_CONFIG_STRING_INFO(EXTERNAL_StartupDelayMS, W("StartupDelayMS"), "") /// /// Stress /// RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StressLog, W("StressLog"), 0, "Turns on the stress log.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ForceEnc, W("ForceEnc"), 0, "Forces Edit and Continue to be on for all eligible modules.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StressLogSize, W("StressLogSize"), 0, "Stress log size in bytes per thread.") RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_StressLogFilename, W("StressLogFilename"), "Stress log filename for memory mapped stress log.") CONFIG_DWORD_INFO(INTERNAL_stressSynchronized, W("stressSynchronized"), 0, "Unknown if or where this is used; unless a test is specifically depending on this, it can be removed.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TotalStressLogSize, W("TotalStressLogSize"), 0, "Total stress log size in bytes.") /// /// Thread Suspend /// CONFIG_DWORD_INFO(INTERNAL_DiagnosticSuspend, W("DiagnosticSuspend"), 0, "") CONFIG_DWORD_INFO(INTERNAL_SuspendDeadlockTimeout, W("SuspendDeadlockTimeout"), 40000, "") CONFIG_DWORD_INFO(INTERNAL_SuspendThreadDeadlockTimeoutMs, W("SuspendThreadDeadlockTimeoutMs"), 2000, "") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadSuspendInjection, W("INTERNAL_ThreadSuspendInjection"), 1, "Specifies whether to inject activations for thread suspension on Unix") /// /// Thread (miscellaneous) /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_DefaultStackSize, W("DefaultStackSize"), 0, "Stack size to use for new VM threads when thread is created with default stack size (dwStackSize == 0).") RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadCountThresholdForGCTrigger, W("Thread_DeadThreadCountThresholdForGCTrigger"), 75, "In the heuristics to clean up dead threads, this threshold must be reached before triggering a GC will be considered. Set to 0 to disable triggering a GC based on dead threads.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_Thread_DeadThreadGCTriggerPeriodMilliseconds, W("Thread_DeadThreadGCTriggerPeriodMilliseconds"), 1000 * 60 * 30, "In the heuristics to clean up dead threads, this much time must have elapsed since the previous max-generation GC before triggering another GC will be considered") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_UseAllCpuGroups, W("Thread_UseAllCpuGroups"), 0, "Specifies whether to query and use CPU group information for determining the processor count.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Thread_AssignCpuGroups, W("Thread_AssignCpuGroups"), 1, "Specifies whether to automatically distribute threads created by the CLR across CPU Groups. Effective only when Thread_UseAllCpuGroups and GCCpuGroup are enabled.") RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_ProcessorCount, W("PROCESSOR_COUNT"), 0, "Specifies the number of processors available for the process, which is returned by Environment.ProcessorCount", CLRConfig::LookupOptions::ParseIntegerAsBase10) /// /// Threadpool /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_ForceMinWorkerThreads, W("ThreadPool_ForceMinWorkerThreads"), 0, "Overrides the MinThreads setting for the ThreadPool worker pool") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_ForceMaxWorkerThreads, W("ThreadPool_ForceMaxWorkerThreads"), 0, "Overrides the MaxThreads setting for the ThreadPool worker pool") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_DisableStarvationDetection, W("ThreadPool_DisableStarvationDetection"), 0, "Disables the ThreadPool feature that forces new threads to be added when workitems run for too long") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_DebugBreakOnWorkerStarvation, W("ThreadPool_DebugBreakOnWorkerStarvation"), 0, "Breaks into the debugger if the ThreadPool detects work queue starvation") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_EnableWorkerTracking, W("ThreadPool_EnableWorkerTracking"), 0, "Enables extra expensive tracking of how many workers threads are working simultaneously") #ifdef TARGET_ARM64 // Spinning scheme is currently different on ARM64 RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_UnfairSemaphoreSpinLimit, W("ThreadPool_UnfairSemaphoreSpinLimit"), 0x32, "Maximum number of spins per processor a thread pool worker thread performs before waiting for work") #else // !TARGET_ARM64 RETAIL_CONFIG_DWORD_INFO(INTERNAL_ThreadPool_UnfairSemaphoreSpinLimit, W("ThreadPool_UnfairSemaphoreSpinLimit"), 0x46, "Maximum number of spins a thread pool worker thread performs before waiting for work") #endif // TARGET_ARM64 RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_Disable, W("HillClimbing_Disable"), 0, "Disables hill climbing for thread adjustments in the thread pool"); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_WavePeriod, W("HillClimbing_WavePeriod"), 4, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_TargetSignalToNoiseRatio, W("HillClimbing_TargetSignalToNoiseRatio"), 300, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_ErrorSmoothingFactor, W("HillClimbing_ErrorSmoothingFactor"), 1, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_WaveMagnitudeMultiplier, W("HillClimbing_WaveMagnitudeMultiplier"), 100, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxWaveMagnitude, W("HillClimbing_MaxWaveMagnitude"), 20, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_WaveHistorySize, W("HillClimbing_WaveHistorySize"), 8, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_Bias, W("HillClimbing_Bias"), 15, "The 'cost' of a thread. 0 means drive for increased throughput regardless of thread count; higher values bias more against higher thread counts."); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxChangePerSecond, W("HillClimbing_MaxChangePerSecond"), 4, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxChangePerSample, W("HillClimbing_MaxChangePerSample"), 20, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_MaxSampleErrorPercent, W("HillClimbing_MaxSampleErrorPercent"), 15, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_SampleIntervalLow, W("HillClimbing_SampleIntervalLow"), 10, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_SampleIntervalHigh, W("HillClimbing_SampleIntervalHigh"), 200, ""); RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent, W("HillClimbing_GainExponent"), 200, "The exponent to apply to the gain, times 100. 100 means to use linear gain, higher values will enhance large moves and damp small ones."); /// /// Tiered Compilation /// #ifdef FEATURE_TIERED_COMPILATION #ifdef _DEBUG // Use lower values to exercise more paths sooner #define TC_BackgroundWorkerTimeoutMs (100) #define TC_CallCountThreshold (2) #define TC_CallCountingDelayMs (1) #define TC_DelaySingleProcMultiplier (2) #else // !_DEBUG #define TC_BackgroundWorkerTimeoutMs (4000) #define TC_CallCountThreshold (30) #define TC_CallCountingDelayMs (100) #define TC_DelaySingleProcMultiplier (10) #endif // _DEBUG RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 1, "For methods that would be jitted, enable using quick JIT when appropriate.") #if defined(TARGET_AMD64) || defined(TARGET_ARM64) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 1, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") #else // !(defined(TARGET_AMD64) || defined(TARGET_ARM64)) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") #endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_AggressiveTiering, W("TC_AggressiveTiering"), 0, "Transition through tiers aggressively.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), TC_BackgroundWorkerTimeoutMs, "How long in milliseconds the background worker thread may remain idle before exiting.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), TC_CallCountThreshold, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountingDelayMs, W("TC_CallCountingDelayMs"), TC_CallCountingDelayMs, "A perpetual delay in milliseconds that is applied to call counting in tier 0 and jitting at higher tiers, while there is startup-like activity.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DelaySingleProcMultiplier, W("TC_DelaySingleProcMultiplier"), TC_DelaySingleProcMultiplier, "Multiplier for TC_CallCountingDelayMs that is applied on a single-processor machine or when the process is affinitized to a single processor.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCounting, W("TC_CallCounting"), 1, "Enabled by default (only activates when TieredCompilation is also enabled). If disabled immediately backpatches prestub, and likely prevents any promotion to higher tiers") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_UseCallCountingStubs, W("TC_UseCallCountingStubs"), 1, "Uses call counting stubs for faster call counting.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_DeleteCallCountingStubsAfter, W("TC_DeleteCallCountingStubsAfter"), 0, "Deletes call counting stubs after this many have completed. Zero to disable deleting.") #undef TC_BackgroundWorkerTimeoutMs #undef TC_CallCountThreshold #undef TC_CallCountingDelayMs #undef TC_DelaySingleProcMultiplier #undef TC_DeleteCallCountingStubsAfter #endif // FEATURE_TIERED_COMPILATION /// /// On-Stack Replacement /// #ifdef FEATURE_ON_STACK_REPLACEMENT RETAIL_CONFIG_DWORD_INFO(INTERNAL_OSR_CounterBump, W("OSR_CounterBump"), 1000, "Counter reload value when a patchpoint is hit") RETAIL_CONFIG_DWORD_INFO(INTERNAL_OSR_HitLimit, W("OSR_HitLimit"), 10, "Number of times a patchpoint must call back to trigger an OSR transition") CONFIG_DWORD_INFO(INTERNAL_OSR_LowId, W("OSR_LowId"), (DWORD)-1, "Low end of enabled patchpoint range (inclusive)"); CONFIG_DWORD_INFO(INTERNAL_OSR_HighId, W("OSR_HighId"), 10000000, "High end of enabled patchpoint range (inclusive)"); #endif /// /// Profile Guided Opts /// #ifdef FEATURE_PGO RETAIL_CONFIG_STRING_INFO(INTERNAL_PGODataPath, W("PGODataPath"), "Read/Write PGO data from/to the indicated file.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_ReadPGOData, W("ReadPGOData"), 0, "Read PGO data") RETAIL_CONFIG_DWORD_INFO(INTERNAL_WritePGOData, W("WritePGOData"), 0, "Write PGO data") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredPGO, W("TieredPGO"), 0, "Instrument Tier0 code and make counts available to Tier1") // TieredPGO_InstrumentOnlyHotCode values: // // 0) Instrument all IL-only code, R2R'd code is never instrumented // 1) Instrument only hot IL-only and hot R2R code (use optimizations in the instrumented tier for hot R2R and no optimizations for hot IL-only) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TieredPGO_InstrumentOnlyHotCode, W("TieredPGO_InstrumentOnlyHotCode"), 1, "Strategy for TieredPGO, see comments in clrconfigvalues.h") #endif /// /// Entry point slot backpatch /// RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_BackpatchEntryPointSlots, W("BackpatchEntryPointSlots"), 1, "Indicates whether to enable entry point slot backpatching, for instance to avoid making virtual calls through a precode and instead to patch virtual slots for a method when its entry point changes.") /// /// TypeLoader /// CONFIG_DWORD_INFO(INTERNAL_TypeLoader_InjectInterfaceDuplicates, W("INTERNAL_TypeLoader_InjectInterfaceDuplicates"), 0, "Injects duplicates in interface map for all types.") /// /// Virtual call stubs /// CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubCollideMonoPct, W("VirtualCallStubCollideMonoPct"), 0, "Used only when STUB_LOGGING is defined, which by default is not.") CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubCollideWritePct, W("VirtualCallStubCollideWritePct"), 100, "Used only when STUB_LOGGING is defined, which by default is not.") CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubDumpLogCounter, W("VirtualCallStubDumpLogCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.") CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubDumpLogIncr, W("VirtualCallStubDumpLogIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_VirtualCallStubLogging, W("VirtualCallStubLogging"), 0, "Worth keeping, but should be moved into \"#ifdef STUB_LOGGING\" blocks. This goes for most (or all) of the stub logging infrastructure.") CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubMissCount, W("VirtualCallStubMissCount"), 100, "Used only when STUB_LOGGING is defined, which by default is not.") CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubResetCacheCounter, W("VirtualCallStubResetCacheCounter"), 0, "Used only when STUB_LOGGING is defined, which by default is not.") CONFIG_DWORD_INFO(INTERNAL_VirtualCallStubResetCacheIncr, W("VirtualCallStubResetCacheIncr"), 0, "Used only when STUB_LOGGING is defined, which by default is not.") /// /// Watson /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_DisableWatsonForManagedExceptions, W("DisableWatsonForManagedExceptions"), 0, "Disable Watson and debugger launching for managed exceptions") /// /// Dump generation /// RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgEnableMiniDump, W("DbgEnableMiniDump"), 0, "Enable unhandled exception crash dump generation") RETAIL_CONFIG_STRING_INFO(INTERNAL_DbgMiniDumpName, W("DbgMiniDumpName"), "Crash dump name") RETAIL_CONFIG_DWORD_INFO(INTERNAL_DbgMiniDumpType, W("DbgMiniDumpType"), 0, "Crash dump type: 1 normal, 2 withheap, 3 triage, 4 full") RETAIL_CONFIG_DWORD_INFO(INTERNAL_CreateDumpDiagnostics, W("CreateDumpDiagnostics"), 0, "Enable crash dump generation diagnostic logging") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EnableDumpOnSigTerm, W("EnableDumpOnSigTerm"), 0, "Enable crash dump generation on SIGTERM") /// /// Zap /// RETAIL_CONFIG_STRING_INFO(INTERNAL_ZapBBInstr, W("ZapBBInstr"), "") RETAIL_CONFIG_STRING_INFO(EXTERNAL_ZapBBInstrDir, W("ZapBBInstrDir"), "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ZapDisable, W("ZapDisable"), 0, "") RETAIL_CONFIG_STRING_INFO(INTERNAL_NativeImageSearchPaths, W("NativeImageSearchPaths"), "Extra search paths for native composite R2R images") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ReadyToRun, W("ReadyToRun"), 1, "Enable/disable use of ReadyToRun native code") // On by default for CoreCLR RETAIL_CONFIG_STRING_INFO(EXTERNAL_ReadyToRunExcludeList, W("ReadyToRunExcludeList"), "List of assemblies that cannot use Ready to Run images") RETAIL_CONFIG_STRING_INFO(EXTERNAL_ReadyToRunLogFile, W("ReadyToRunLogFile"), "Name of file to log success/failure of using Ready to Run images") #if defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableEventLog, W("EnableEventLog"), 0, "Enable/disable use of EnableEventLogging mechanism ") // Off by default RETAIL_CONFIG_STRING_INFO(INTERNAL_EventSourceFilter, W("EventSourceFilter"), "") RETAIL_CONFIG_STRING_INFO(INTERNAL_EventNameFilter, W("EventNameFilter"), "") #endif //defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT) /// /// Interop /// RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_InteropValidatePinnedObjects, W("InteropValidatePinnedObjects"), 0, "After returning from a managed-to-unmanaged interop call, validate GC heap around objects pinned by IL stubs.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_InteropLogArguments, W("InteropLogArguments"), 0, "Log all pinned arguments passed to an interop call") RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_LogCCWRefCountChange, W("LogCCWRefCountChange"), "Outputs debug information and calls LogCCWRefCountChange_BREAKPOINT when AddRef or Release is called on a CCW.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EnableRCWCleanupOnSTAShutdown, W("EnableRCWCleanupOnSTAShutdown"), 0, "Performs RCW cleanup when STA shutdown is detected using IInitializeSpy in classic processes.") // // EventPipe // RETAIL_CONFIG_DWORD_INFO(INTERNAL_EnableEventPipe, W("EnableEventPipe"), 0, "Enable/disable event pipe. Non-zero values enable tracing.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeNetTraceFormat, W("EventPipeNetTraceFormat"), 1, "Enable/disable using the newer nettrace file format.") RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeOutputPath, W("EventPipeOutputPath"), "The full path excluding file name for the trace file that will be written when DOTNET_EnableEventPipe=1") RETAIL_CONFIG_STRING_INFO(INTERNAL_EventPipeConfig, W("EventPipeConfig"), "Configuration for EventPipe.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeRundown, W("EventPipeRundown"), 1, "Enable/disable eventpipe rundown.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeCircularMB, W("EventPipeCircularMB"), 1024, "The EventPipe circular buffer size in megabytes.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeProcNumbers, W("EventPipeProcNumbers"), 0, "Enable/disable capturing processor numbers in EventPipe event headers") RETAIL_CONFIG_DWORD_INFO(INTERNAL_EventPipeOutputStreaming, W("EventPipeOutputStreaming"), 0, "Enable/disable streaming for trace file set in DOTNET_EventPipeOutputPath. Non-zero values enable streaming.") #ifdef FEATURE_AUTO_TRACE RETAIL_CONFIG_DWORD_INFO_EX(INTERNAL_AutoTrace_N_Tracers, W("AutoTrace_N_Tracers"), 0, "", CLRConfig::LookupOptions::ParseIntegerAsBase10) RETAIL_CONFIG_STRING_INFO(INTERNAL_AutoTrace_Command, W("AutoTrace_Command"), "") #endif // FEATURE_AUTO_TRACE // // Generational Aware Analysis // RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisGen, W("GCGenAnalysisGen"), 0, "The generation to trigger generational aware analysis") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisBytes, W("GCGenAnalysisBytes"), 0, "The number of bytes to trigger generational aware analysis") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisTimeUSec, W("GCGenAnalysisTimeUSec"), 0, "The number of microseconds to trigger generational aware analysis") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisTimeMSec, W("GCGenAnalysisTimeMSec"), 0, "The number of milliseconds to trigger generational aware analysis") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisIndex, W("GCGenAnalysisIndex"), 0, "The gc index to trigger generational aware analysis") RETAIL_CONFIG_STRING_INFO(EXTERNAL_GCGenAnalysisCmd, W("GCGenAnalysisCmd"), "An optional filter to match with the command line used to spawn the process") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisTrace, W("GCGenAnalysisTrace"), 1, "Enable/Disable capturing a trace") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_GCGenAnalysisDump, W("GCGenAnalysisDump"), 0, "Enable/Disable capturing a dump") // // Diagnostics Ports // RETAIL_CONFIG_DWORD_INFO(EXTERNAL_DOTNET_DefaultDiagnosticPortSuspend, W("DefaultDiagnosticPortSuspend"), 0, "This sets the deafult diagnostic port to suspend causing the runtime to pause during startup before major subsystems are started. Resume using the Diagnostics IPC ResumeStartup command on the default diagnostic port."); RETAIL_CONFIG_STRING_INFO(EXTERNAL_DOTNET_DiagnosticPorts, W("DiagnosticPorts"), "A semicolon delimited list of additional Diagnostic Ports, where a Diagnostic Port is a NamedPipe path without '\\\\.\\pipe\\' on Windows or the full path of Unix Domain Socket on Linux/Unix followed by optional tags, e.g., ',connect,nosuspend;'"); // // LTTng // RETAIL_CONFIG_STRING_INFO(INTERNAL_LTTngConfig, W("LTTngConfig"), "Configuration for LTTng.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_LTTng, W("LTTng"), 1, "If DOTNET_LTTng is set to 0, this will prevent the LTTng library from being loaded at runtime") // // Executable code // RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableWriteXorExecute, W("EnableWriteXorExecute"), 1, "Enable W^X for executable memory."); #ifdef FEATURE_GDBJIT /// /// GDBJIT /// CONFIG_STRING_INFO(INTERNAL_GDBJitElfDump, W("GDBJitElfDump"), "Dump ELF for specified method") #ifdef FEATURE_GDBJIT_FRAME RETAIL_CONFIG_DWORD_INFO(INTERNAL_GDBJitEmitDebugFrame, W("GDBJitEmitDebugFrame"), TRUE, "Enable .debug_frame generation") #endif #endif // // Hardware Intrinsic ISAs; keep in sync with jitconfigvalues.h // #if defined(TARGET_LOONGARCH64) //TODO: should implement LoongArch64's features. RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableHWIntrinsic, W("EnableHWIntrinsic"), 0, "Allows Base+ hardware intrinsics to be disabled") #else RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableHWIntrinsic, W("EnableHWIntrinsic"), 1, "Allows Base+ hardware intrinsics to be disabled") #endif // defined(TARGET_LOONGARCH64) #if defined(TARGET_AMD64) || defined(TARGET_X86) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAES, W("EnableAES"), 1, "Allows AES+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX, W("EnableAVX"), 1, "Allows AVX+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX2, W("EnableAVX2"), 1, "Allows AVX2+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512BW, W("EnableAVX512BW"), 1, "Allows AVX512BW+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512BW_VL, W("EnableAVX512BW_VL"), 1, "Allows AVX512BW_VL+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512CD, W("EnableAVX512CD"), 1, "Allows AVX512CD+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512CD_VL, W("EnableAVX512CD_VL"), 1, "Allows AVX512CD_VL+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512DQ, W("EnableAVX512DQ"), 1, "Allows AVX512DQ+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512DQ_VL, W("EnableAVX512DQ_VL"), 1, "Allows AVX512DQ_VL+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512F, W("EnableAVX512F"), 1, "Allows AVX512F+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVX512F_VL, W("EnableAVX512F_VL"), 1, "Allows AVX512F_VL+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableAVXVNNI, W("EnableAVXVNNI"), 1, "Allows AVX VNNI+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableBMI1, W("EnableBMI1"), 1, "Allows BMI1+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableBMI2, W("EnableBMI2"), 1, "Allows BMI2+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableFMA, W("EnableFMA"), 1, "Allows FMA+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableLZCNT, W("EnableLZCNT"), 1, "Allows LZCNT+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnablePCLMULQDQ, W("EnablePCLMULQDQ"), 1, "Allows PCLMULQDQ+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableMOVBE, W("EnableMOVBE"), 1, "Allows MOVBE+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnablePOPCNT, W("EnablePOPCNT"), 1, "Allows POPCNT+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE, W("EnableSSE"), 1, "Allows SSE+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE2, W("EnableSSE2"), 1, "Allows SSE2+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE3, W("EnableSSE3"), 1, "Allows SSE3+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE3_4, W("EnableSSE3_4"), 1, "Allows SSE3+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE41, W("EnableSSE41"), 1, "Allows SSE4.1+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSE42, W("EnableSSE42"), 1, "Allows SSE4.2+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableSSSE3, W("EnableSSSE3"), 1, "Allows SSSE3+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableX86Serialize, W("EnableX86Serialize"), 1, "Allows X86Serialize+ hardware intrinsics to be disabled") #elif defined(TARGET_ARM64) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64AdvSimd, W("EnableArm64AdvSimd"), 1, "Allows Arm64 AdvSimd+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Aes, W("EnableArm64Aes"), 1, "Allows Arm64 Aes+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Atomics, W("EnableArm64Atomics"), 1, "Allows Arm64 Atomics+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Crc32, W("EnableArm64Crc32"), 1, "Allows Arm64 Crc32+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Dczva, W("EnableArm64Dczva"), 1, "Allows Arm64 Dczva+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Dp, W("EnableArm64Dp"), 1, "Allows Arm64 Dp+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Rdm, W("EnableArm64Rdm"), 1, "Allows Arm64 Rdm+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Sha1, W("EnableArm64Sha1"), 1, "Allows Arm64 Sha1+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Sha256, W("EnableArm64Sha256"), 1, "Allows Arm64 Sha256+ hardware intrinsics to be disabled") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableArm64Rcpc, W("EnableArm64Rcpc"), 1, "Allows Arm64 Rcpc+ hardware intrinsics to be disabled") #endif /// /// Uncategorized /// // // Unknown // //--------------------------------------------------------------------------------------- // ** // PLEASE MOVE ANY CONFIG SWITCH YOU OWN OUT OF THIS SECTION INTO A CATEGORY ABOVE // // DO NOT ADD ANY MORE CONFIG SWITCHES TO THIS SECTION! // ** CONFIG_DWORD_INFO(INTERNAL_ActivatePatchSkip, W("ActivatePatchSkip"), 0, "Allows an assert when ActivatePatchSkip is called") CONFIG_DWORD_INFO(INTERNAL_AlwaysUseMetadataInterfaceMapLayout, W("AlwaysUseMetadataInterfaceMapLayout"), 0, "Used for debugging generic interface map layout.") CONFIG_DWORD_INFO(INTERNAL_AssertOnUnneededThis, W("AssertOnUnneededThis"), 0, "While the ConfigDWORD is unnecessary, the contained ASSERT should be kept. This may result in some work tracking down violating MethodDescCallSites.") CONFIG_DWORD_INFO(INTERNAL_AssertStacktrace, W("AssertStacktrace"), 1, "") CONFIG_DWORD_INFO(INTERNAL_CPUFamily, W("CPUFamily"), 0xFFFFFFFF, "") CONFIG_DWORD_INFO(INTERNAL_CPUFeatures, W("CPUFeatures"), 0xFFFFFFFF, "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_DisableConfigCache, W("DisableConfigCache"), 0, "Used to disable the \"probabilistic\" config cache, which walks through the appropriate config registry keys on init and probabilistically keeps track of which exist.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_DisableStackwalkCache, W("DisableStackwalkCache"), 0, "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_DoubleArrayToLargeObjectHeap, W("DoubleArrayToLargeObjectHeap"), 0, "Controls double[] placement") CONFIG_STRING_INFO(INTERNAL_DumpOnClassLoad, W("DumpOnClassLoad"), "Dumps information about loaded class to log.") CONFIG_DWORD_INFO(INTERNAL_ExpandAllOnLoad, W("ExpandAllOnLoad"), 0, "") CONFIG_DWORD_INFO(INTERNAL_ForceRelocs, W("ForceRelocs"), 0, "") CONFIG_DWORD_INFO(INTERNAL_GenerateLongJumpDispatchStubRatio, W("GenerateLongJumpDispatchStubRatio"), 0, "Useful for testing VSD on AMD64") CONFIG_DWORD_INFO(INTERNAL_HashStack, W("HashStack"), 0, "") CONFIG_DWORD_INFO(INTERNAL_HostManagerConfig, W("HostManagerConfig"), (DWORD)-1, "") CONFIG_DWORD_INFO(INTERNAL_HostTestThreadAbort, W("HostTestThreadAbort"), 0, "") CONFIG_STRING_INFO(INTERNAL_InvokeHalt, W("InvokeHalt"), "Throws an assert when the given method is invoked through reflection.") CONFIG_DWORD_INFO(INTERNAL_MaxStubUnwindInfoSegmentSize, W("MaxStubUnwindInfoSegmentSize"), 0, "") CONFIG_DWORD_INFO(INTERNAL_MessageDebugOut, W("MessageDebugOut"), 0, "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_NativeImageRequire, W("NativeImageRequire"), 0, "") CONFIG_DWORD_INFO(INTERNAL_NestedEhOom, W("NestedEhOom"), 0, "") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_NoProcedureSplitting, W("NoProcedureSplitting"), 0, "") CONFIG_DWORD_INFO(INTERNAL_PauseOnLoad, W("PauseOnLoad"), 0, "Stops in SystemDomain::init. I think it can be removed.") CONFIG_DWORD_INFO(INTERNAL_PerfAllocsSizeThreshold, W("PerfAllocsSizeThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") CONFIG_DWORD_INFO(INTERNAL_PerfNumAllocsThreshold, W("PerfNumAllocsThreshold"), 0x3FFFFFFF, "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") CONFIG_STRING_INFO(INTERNAL_PerfTypesToLog, W("PerfTypesToLog"), "Log facility LF_GCALLOC logs object allocations. This flag controls which ones also log stacktraces. Predates ClrProfiler.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_Prepopulate1, W("Prepopulate1"), 1, "") CONFIG_STRING_INFO(INTERNAL_PrestubGC, W("PrestubGC"), "") CONFIG_STRING_INFO(INTERNAL_PrestubHalt, W("PrestubHalt"), "") RETAIL_CONFIG_STRING_INFO(EXTERNAL_RestrictedGCStressExe, W("RestrictedGCStressExe"), "") CONFIG_DWORD_INFO(INTERNAL_ReturnSourceTypeForTesting, W("ReturnSourceTypeForTesting"), 0, "Allows returning the (internal only) source type of an IL to Native mapping for debugging purposes") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RSStressLog, W("RSStressLog"), 0, "Allows turning on logging for RS startup") CONFIG_DWORD_INFO(INTERNAL_SBDumpOnNewIndex, W("SBDumpOnNewIndex"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") CONFIG_DWORD_INFO(INTERNAL_SBDumpOnResize, W("SBDumpOnResize"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") CONFIG_DWORD_INFO(INTERNAL_SBDumpStyle, W("SBDumpStyle"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_SleepOnExit, W("SleepOnExit"), 0, "Used for lrak detection. I'd say deprecated by umdh.") CONFIG_DWORD_INFO(INTERNAL_StubLinkerUnwindInfoVerificationOn, W("StubLinkerUnwindInfoVerificationOn"), 0, "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_SuccessExit, W("SuccessExit"), 0, "") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TestDataConsistency, W("TestDataConsistency"), FALSE, "Allows ensuring the left side is not holding locks (and may thus be in an inconsistent state) when inspection occurs") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_ThreadGuardPages, W("ThreadGuardPages"), 0, "") #ifdef _DEBUG RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TraceWrap, W("TraceWrap"), 0, "") #endif RETAIL_CONFIG_DWORD_INFO(EXTERNAL_UseMethodDataCache, W("UseMethodDataCache"), FALSE, "Used during feature development; may now be removed.") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_UseParentMethodData, W("UseParentMethodData"), TRUE, "Used during feature development; may now be removed.") CONFIG_DWORD_INFO(INTERNAL_VerifierOff, W("VerifierOff"), 0, "") // ** // PLEASE MOVE ANY CONFIG SWITCH YOU OWN OUT OF THIS SECTION INTO A CATEGORY ABOVE // // DO NOT ADD ANY MORE CONFIG SWITCHES TO THIS SECTION! // ** //--------------------------------------------------------------------------------------- ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrdata.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** clrdata.idl - Common Language Runtime data access interfaces for ** ** clients needing to access runtime state from outside ** ** runtime, such as out-of-process debuggers. ** ** ** ** The access interface defines two different types of code running: ** ** The host is the user of the access interface. ** ** The target is the target of the access. ** ** ** ** The host and target can be have different instruction sets, ** ** pointer sizes, runtime versions and so on. ** ** ** *****************************************************************************/ import "unknwn.idl"; /* ------------------------------------------------------------------------- * * Forward declarations. * ------------------------------------------------------------------------- */ interface ICLRDataEnumMemoryRegions; interface ICLRDataEnumMemoryRegionsCallback; interface ICLRDataEnumMemoryRegionsCallback2; interface ICLRDataEnumMemoryRegionsCallback3; interface ICLRDataTarget; interface ICLRDataTarget2; interface ICLRMetadataLocator; /* * Addresses in the access interface are always the largest possible. * If the target uses a smaller address size then addresses are converted * up by sign extension. */ typedef ULONG64 CLRDATA_ADDRESS; /* ------------------------------------------------------------------------- * * Creation function. * Can create ICLRDataEnumMemoryRegions. * ------------------------------------------------------------------------- */ #pragma midl_echo("STDAPI CLRDataCreateInstance(REFIID iid, ICLRDataTarget* target, void** iface);") #pragma midl_echo("typedef HRESULT (STDAPICALLTYPE* PFN_CLRDataCreateInstance)(REFIID iid, ICLRDataTarget* target, void** iface);") /* * Interface for providing access to a particular target process. The * data access services will call functions on this interface to * access memory and other data in the target process. * * The API client must implement this interface as appropriate for the * particular target (for example, a live process or a memory dump). * */ [ object, local, uuid(3E11CCEE-D08B-43e5-AF01-32717A64DA03), pointer_default(unique) ] interface ICLRDataTarget : IUnknown { /* * Return which kind of instruction set is in use in the * target. Value is one of the IMAGE_FILE_MACHINE_* constants. */ HRESULT GetMachineType([out] ULONG32* machineType); /* * Return the size of a pointer on the target, in bytes. */ HRESULT GetPointerSize([out] ULONG32* pointerSize); /* * Find the base address for a given image. * Image name may or may not have a path. If a path * is given matching is done with the whole path, otherwise * matching is done only on the file part. * In either case, matching should be case-insensitive. */ HRESULT GetImageBase([in, string] LPCWSTR imagePath, [out] CLRDATA_ADDRESS* baseAddress); /* * Virtual memory access. If any bytes can be processed * the call is considered successful. */ HRESULT ReadVirtual([in] CLRDATA_ADDRESS address, [out, size_is(bytesRequested), length_is(*bytesRead)] BYTE* buffer, [in] ULONG32 bytesRequested, [out] ULONG32* bytesRead); HRESULT WriteVirtual([in] CLRDATA_ADDRESS address, [in, size_is(bytesRequested)] BYTE* buffer, [in] ULONG32 bytesRequested, [out] ULONG32* bytesWritten); /* * TLS data access for the current thread. */ HRESULT GetTLSValue([in] ULONG32 threadID, [in] ULONG32 index, [out] CLRDATA_ADDRESS* value); HRESULT SetTLSValue([in] ULONG32 threadID, [in] ULONG32 index, [in] CLRDATA_ADDRESS value); /* * System ID for the current thread. * If there is no "current" thread for the target * implementation this can fail. */ HRESULT GetCurrentThreadID([out] ULONG32* threadID); /* * Thread context. */ HRESULT GetThreadContext([in] ULONG32 threadID, [in] ULONG32 contextFlags, [in] ULONG32 contextSize, [out, size_is(contextSize)] BYTE* context); HRESULT SetThreadContext([in] ULONG32 threadID, [in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE* context); /* * Generic request facility to allow addition of * queries and operations without requiring an interface revision. */ HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); }; /* * Interface used by the data access services layer to manipulate * virtual memory regions in the target. The target may not support * modification. */ [ object, local, uuid(6d05fae3-189c-4630-a6dc-1c251e1c01ab), pointer_default(unique) ] interface ICLRDataTarget2 : ICLRDataTarget { /* * Ask the target to allocate memory in its address space. */ HRESULT AllocVirtual([in] CLRDATA_ADDRESS addr, [in] ULONG32 size, [in] ULONG32 typeFlags, [in] ULONG32 protectFlags, [out] CLRDATA_ADDRESS* virt); /* * Ask the target to free a previously allocated memory block. */ HRESULT FreeVirtual([in] CLRDATA_ADDRESS addr, [in] ULONG32 size, [in] ULONG32 typeFlags); }; /* * Interface for providing access to exception and context records. */ [ object, local, uuid(a5664f95-0af4-4a1b-960e-2f3346b4214c), pointer_default(unique) ] interface ICLRDataTarget3 : ICLRDataTarget2 { /* * Returns an associated exception record, if any. */ HRESULT GetExceptionRecord([in] ULONG32 bufferSize, [out] ULONG32* bufferUsed, [out, size_is(bufferSize)] BYTE* buffer); /* * Returns a context record associated with the exception, if any. */ HRESULT GetExceptionContextRecord([in] ULONG32 bufferSize, [out] ULONG32* bufferUsed, [out, size_is(bufferSize)] BYTE* buffer); /* * Returns the ID of the thread raising the exception. */ HRESULT GetExceptionThreadID([out] ULONG32* threadID); }; [ object, local, uuid(b760bf44-9377-4597-8be7-58083bdc5146), pointer_default(unique) ] interface ICLRRuntimeLocator : IUnknown { /* Returns the base address of the module containing the runtime. */ HRESULT GetRuntimeBase([out] CLRDATA_ADDRESS* baseAddress); }; /* * Interface used by the data access services layer to locate metadata * of assemblies in a target. * * The API client must implement this interface as appropriate for the * particular target (for example, a live process or a memory dump). * * This is an old interface you should not be using. * see code:ICorDebugMetaDataLocator in cordebug.idl * */ [ object, local, uuid(aa8fa804-bc05-4642-b2c5-c353ed22fc63), pointer_default(unique) ] interface ICLRMetadataLocator : IUnknown { /* * Ask the target to retrieve metadata for an image. */ HRESULT GetMetadata([in] LPCWSTR imagePath, [in] ULONG32 imageTimestamp, [in] ULONG32 imageSize, [in] GUID* mvid, [in] ULONG32 mdRva, [in] ULONG32 flags, [in] ULONG32 bufferSize, [out, size_is(bufferSize), length_is(*dataSize)] BYTE* buffer, [out] ULONG32* dataSize); }; /* * Callback interface for enumerating memory regions. */ [ object, local, uuid(BCDD6908-BA2D-4ec5-96CF-DF4D5CDCB4A4) ] interface ICLRDataEnumMemoryRegionsCallback : IUnknown { /* * ICLRDataEnumMemoryRegions::EnumMemoryRegions will call this * function for every memory region enumerated. Regions reported * through this callback may be duplicate or overlapping. Failure * return results will be noted, but will not stop the * enumeration. */ HRESULT EnumMemoryRegion([in] CLRDATA_ADDRESS address, [in] ULONG32 size); } /* * Callback interface for writing/poisoning memory regions. */ [ object, local, uuid(3721A26F-8B91-4D98-A388-DB17B356FADB) ] interface ICLRDataEnumMemoryRegionsCallback2 : ICLRDataEnumMemoryRegionsCallback { /* * ICLRDataEnumMemoryRegions::EnumMemoryRegions will call this function * for every memory regions it needs to overwrite/poison with the specified * data buffer passed as input argument. */ HRESULT UpdateMemoryRegion( [in] CLRDATA_ADDRESS address, [in] ULONG32 bufferSize, [in, size_is(bufferSize)] BYTE* buffer); } /* * Optional callback interface for logging EnumMemoryRegions operations and errors. */ [ object, local, uuid(F315248D-8B79-49DB-B184-37426559F703) ] interface ICLRDataLoggingCallback : IUnknown { HRESULT LogMessage( [in] LPCSTR message); } /* * Flags for controlling which memory regions are enumerated. */ typedef enum CLRDataEnumMemoryFlags { CLRDATA_ENUM_MEM_DEFAULT = 0x0, CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, // generating skinny mini-dump CLRDATA_ENUM_MEM_HEAP = 0x1, // generating heap dump CLRDATA_ENUM_MEM_TRIAGE = 0x2, // generating triage mini-dump /* Generate heap dumps faster with less memory usage than CLRDATA_ENUM_MEM_HEAP by adding the loader heaps instead of traversing all the individual runtime data structures. */ CLRDATA_ENUM_MEM_HEAP2 = 0x3, /* More bits to be added here later */ } CLRDataEnumMemoryFlags; /* * Memory enumeration interface. * This is one of the top-level interfaces creatable by CLRDataCreateInstance. */ [ object, local, uuid(471c35b4-7c2f-4ef0-a945-00f8c38056f1) ] interface ICLRDataEnumMemoryRegions : IUnknown { /* * EnumMemoryRegions enumerates regions of interest as specified * by the flags argument by calling the * ICLRDataEnumMemoryRegionsCallback::EnumMemoryRegion for every * region being enumerated. Attempts to enumerate as many regions * as possible, even if the callback returns failures during * enumeration. */ HRESULT EnumMemoryRegions([in] ICLRDataEnumMemoryRegionsCallback *callback, [in] ULONG32 miniDumpFlags, [in] CLRDataEnumMemoryFlags clrFlags); } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrhost.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // #ifndef __CLRHOST_H__ #define __CLRHOST_H__ #include "windows.h" // worth to include before mscoree.h so we are guaranteed to pick few definitions #ifdef CreateSemaphore #undef CreateSemaphore #endif #include "mscoree.h" #include "clrinternal.h" #include "switches.h" #include "holder.h" #include "new.hpp" #include "staticcontract.h" #include "predeftlsslot.h" #include "safemath.h" #include "debugreturn.h" #include "yieldprocessornormalized.h" #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif #define BEGIN_PRESERVE_LAST_ERROR \ { \ DWORD __dwLastError = ::GetLastError(); \ DEBUG_ASSURE_NO_RETURN_BEGIN(PRESERVE_LAST_ERROR); \ { #define END_PRESERVE_LAST_ERROR \ } \ DEBUG_ASSURE_NO_RETURN_END(PRESERVE_LAST_ERROR); \ ::SetLastError(__dwLastError); \ } // // TRASH_LASTERROR macro sets bogus last error in debug builds to help find places that fail to save it // #ifdef _DEBUG #define LAST_ERROR_TRASH_VALUE 42424 /* = 0xa5b8 */ #define TRASH_LASTERROR \ SetLastError(LAST_ERROR_TRASH_VALUE) #else // _DEBUG #define TRASH_LASTERROR #endif // _DEBUG LPVOID ClrVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); BOOL ClrVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); SIZE_T ClrVirtualQuery(LPCVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer, SIZE_T dwLength); BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); #ifdef HOST_WINDOWS HANDLE ClrGetProcessExecutableHeap(); #endif #ifdef FAILPOINTS_ENABLED extern int RFS_HashStack(); #endif // Critical section support for CLR DLLs other than the EE. // Include the header defining each Crst type and its corresponding level (relative rank). This is // auto-generated from a tool that takes a high-level description of each Crst type and its dependencies. #include "crsttypes_generated.h" // critical section api CRITSEC_COOKIE ClrCreateCriticalSection(CrstType type, CrstFlags flags); void ClrDeleteCriticalSection(CRITSEC_COOKIE cookie); void ClrEnterCriticalSection(CRITSEC_COOKIE cookie); void ClrLeaveCriticalSection(CRITSEC_COOKIE cookie); DWORD ClrSleepEx(DWORD dwMilliseconds, BOOL bAlertable); // Rather than use the above APIs directly, it is recommended that holder classes // be used. This guarantees that the locks will be vacated when the scope is popped, // either on exception or on return. typedef Holder CRITSEC_Holder; // Use this holder to manage CRITSEC_COOKIE allocation to ensure it will be released if anything goes wrong FORCEINLINE void VoidClrDeleteCriticalSection(CRITSEC_COOKIE cs) { if (cs != NULL) ClrDeleteCriticalSection(cs); } typedef Wrapper, VoidClrDeleteCriticalSection, NULL> CRITSEC_AllocationHolder; #ifndef DACCESS_COMPILE // Suspend/resume APIs that fail-fast on errors #ifdef TARGET_WINDOWS DWORD ClrSuspendThread(HANDLE hThread); #endif // TARGET_WINDOWS DWORD ClrResumeThread(HANDLE hThread); #endif // !DACCESS_COMPILE DWORD GetClrModulePathName(SString& buffer); extern thread_local int t_CantAllocCount; inline void IncCantAllocCount() { t_CantAllocCount++; } inline void DecCantAllocCount() { t_CantAllocCount--; } class CantAllocHolder { public: CantAllocHolder () { IncCantAllocCount (); } ~CantAllocHolder() { DecCantAllocCount (); } }; // At places where want to allocate stress log, we need to first check if we are allowed to do so. inline bool IsInCantAllocRegion () { return t_CantAllocCount != 0; } inline BOOL IsInCantAllocStressLogRegion() { return t_CantAllocCount != 0; } #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrinternal.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /************************************************************************************** ** ** ** clrinternal.idl - interface definitions for internal usage. ** ** ** **************************************************************************************/ // // Interface descriptions // import "unknwn.idl"; // import mscoree.idl for BucketParameters definition import "mscoree.idl"; // This ID is embedded in the CLRDEBUGINFO resource so that the shim can differentiate dlls which happen to be named // clr.dll from official Microsoft clr.dll implementations. This is not intended to authenticate a CLR in a strong // security sense but short of deliberate 3rd party spoofing it should provide a good identity. // // Using a different ID allows us to completely hide different CLR SKUs from each other. The recommendation is to keep // the ID constant between different versions of the same SKU and use mscordbi's logic to determine whether a given // version is compatible. This allows debuggers to give different errors for 'future version of the CLR I don't // support' vs. 'No CLR is loaded at all.' // // This guid first appears in version 4.0 of CLR on x86 and amd64 - earlier versions had no resource // GUID CLR_ID_V4_DESKTOP : uuid{267F3989-D786-4b9a-9AF6-D19E42D557EC} cpp_quote("EXTERN_GUID(CLR_ID_V4_DESKTOP, 0x267f3989, 0xd786, 0x4b9a, 0x9a, 0xf6, 0xd1, 0x9e, 0x42, 0xd5, 0x57, 0xec);") // This guid has been set aside for CoreCLR usage - at present CoreCLR doesn't use it though // GUID CLR_ID_CORECLR : uuid{8CB8E075-0A91-408E-9228-D66E00A3BFF6} cpp_quote("EXTERN_GUID(CLR_ID_CORECLR, 0x8CB8E075, 0x0A91, 0x408E, 0x92, 0x28, 0xD6, 0x6E, 0x00, 0xA3, 0xBF, 0xF6 );") // This guid first appears in the CoreCLR port to Windows Phone 8 - note that it is separate from the CoreCLR id because it will // potentially have a different versioning lineage than CoreCLR // GUID CLR_ID_PHONE_CLR : uuid{E7237E9C-31C0-488C-AD48-324D3E7ED92A} cpp_quote("EXTERN_GUID(CLR_ID_PHONE_CLR, 0xE7237E9C, 0x31C0, 0x488C, 0xAD, 0x48, 0x32, 0x4D, 0x3E, 0x7E, 0xD9, 0x2A);") // This guid first appears 8/19/14 as CoreCLR evolves to OneCore, ProjectK, and versions of Phone after PhoneBlue // The new guid intentionally creates a breaking change so we can simplify the file naming on mscordaccore.dll and mscordbi.dll // in xplat hosting scenarios. Old versions of dbgshim.dll will not be able to support this. // GUID CLR_ID_ONECORE_CLR : uuid{B1EE760D-6C4A-4533-BA41-6F4F661FABAF} cpp_quote("EXTERN_GUID(CLR_ID_ONECORE_CLR, 0xb1ee760d, 0x6c4a, 0x4533, 0xba, 0x41, 0x6f, 0x4f, 0x66, 0x1f, 0xab, 0xaf);") // IID_IPrivateManagedExceptionReporting : uuid{AD76A023-332D-4298-8001-07AA9350DCA4} cpp_quote("EXTERN_GUID(IID_IPrivateManagedExceptionReporting, 0xad76a023, 0x332d, 0x4298, 0x80, 0x01, 0x07, 0xaa, 0x93, 0x50, 0xdc, 0xa4);") //***************************************************************************** // Interface for exposing services from the EE to other DLLs of the CLR. //***************************************************************************** typedef void * CRITSEC_COOKIE; typedef enum { CRST_DEFAULT = 0x0, CRST_REENTRANCY = 0x1, // allow same thread to take lock multiple times. CRST_UNSAFE_SAMELEVEL = 0x2, // AVOID THIS! Can take other locks @ same level in // any order. CRST_UNSAFE_COOPGC = 0x4, // AVOID THIS! Lock must be taken in cooperative mode. CRST_UNSAFE_ANYMODE = 0x8, // AVOID THIS! Lock can be taken in either GC mode. CRST_DEBUGGER_THREAD = 0x10, // This lock can be taken on the debugger's helper thread. CRST_HOST_BREAKABLE = 0x20, // This lock is held while running managed code. It can be terminated by a host. // CRST_UNUSED = 0x40, CRST_TAKEN_DURING_SHUTDOWN = 0x80, // This lock is taken during the shutdown sequence in EEShutdown(helper) CRST_GC_NOTRIGGER_WHEN_TAKEN = 0x100, // User of this lock cannot trigger GC, while it is locked. // Note that Enter on this lock can trigger GC if called from COOPERATIVE mode. // It is useful for locks which can be taken on GC or debugger threads. CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD = 0x200, // Some rare locks should be taken only in ForbidSuspend region (i.e. profiler cannot walk the stack), // this option will assert it in debug mode. } CrstFlags; //******************************************************************************************** // Interface for exposing GetBucketParametersForCurrentException to Watson testing harness. //******************************************************************************************** [ uuid(AD76A023-332D-4298-8001-07AA9350DCA4), helpstring("Private Managed Exception Reporting Interface"), pointer_default(unique), local ] interface IPrivateManagedExceptionReporting : IUnknown { HRESULT GetBucketParametersForCurrentException([out]BucketParameters *pParams); } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrnt.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef CLRNT_H_ #define CLRNT_H_ #include "staticcontract.h" #include "cfi.h" // // This file is the result of some changes to the SDK header files. // In particular, nt.h and some of its dependencies are no longer // available except as "nonship" files. As a result, this file // was created as a simple cut and past of structures and functions // from NT that are either not yet documented or have been overlooked // as being part of the platform SDK. // // // ALL PLATFORMS // #define STATUS_INVALID_PARAMETER_3 ((NTSTATUS)0xC00000F1L) #define STATUS_INVALID_PARAMETER_4 ((NTSTATUS)0xC00000F2L) #define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L) #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) #ifndef STATUS_UNWIND #define STATUS_UNWIND ((NTSTATUS)0x80000027L) #endif #ifndef DBG_PRINTEXCEPTION_C #define DBG_PRINTEXCEPTION_C ((DWORD)0x40010006L) #endif #ifndef STATUS_UNWIND_CONSOLIDATE #define STATUS_UNWIND_CONSOLIDATE ((NTSTATUS)0x80000029L) #endif #ifndef STATUS_LONGJUMP #define STATUS_LONGJUMP ((NTSTATUS)0x80000026L) #endif #ifndef LOCALE_NAME_MAX_LENGTH #define LOCALE_NAME_MAX_LENGTH 85 #endif // !LOCALE_NAME_MAX_LENGTH #ifndef SUBLANG_CUSTOM_DEFAULT #define SUBLANG_CUSTOM_DEFAULT 0x03 // default custom language/locale #define SUBLANG_CUSTOM_UNSPECIFIED 0x04 // custom language/locale #define LOCALE_CUSTOM_DEFAULT \ (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_DEFAULT), SORT_DEFAULT)) #define LOCALE_CUSTOM_UNSPECIFIED \ (MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_CUSTOM_UNSPECIFIED), SORT_DEFAULT)) #endif // !SUBLANG_CUSTOM_DEFAULT #ifndef __out_xcount_opt #define __out_xcount_opt(var) __out #endif #ifndef __encoded_pointer #define __encoded_pointer #endif #ifndef __range #define __range(min, man) #endif #ifndef __field_bcount #define __field_bcount(size) #endif #ifndef __field_ecount_opt #define __field_ecount_opt(nFields) #endif #ifndef __field_ecount #define __field_ecount(EHCount) #endif #undef _Ret_bytecap_ #define _Ret_bytecap_(_Size) #ifndef NT_SUCCESS #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0) #endif #define ARGUMENT_PRESENT(ArgumentPointer) (\ (CHAR *)(ArgumentPointer) != (CHAR *)(NULL) ) #define EXCEPTION_CHAIN_END ((PEXCEPTION_REGISTRATION_RECORD)-1) typedef signed char SCHAR; typedef SCHAR *PSCHAR; typedef LONG NTSTATUS; #ifndef HOST_UNIX #define TLS_MINIMUM_AVAILABLE 64 // winnt #define TLS_EXPANSION_SLOTS 1024 typedef enum _THREADINFOCLASS { ThreadBasicInformation, ThreadTimes, ThreadPriority, ThreadBasePriority, ThreadAffinityMask, ThreadImpersonationToken, ThreadDescriptorTableEntry, ThreadEnableAlignmentFaultFixup, ThreadEventPair_Reusable, ThreadQuerySetWin32StartAddress, ThreadZeroTlsCell, ThreadPerformanceCount, ThreadAmILastThread, ThreadIdealProcessor, ThreadPriorityBoost, ThreadSetTlsArrayAddress, ThreadIsIoPending, ThreadHideFromDebugger, ThreadBreakOnTermination, MaxThreadInfoClass } THREADINFOCLASS; typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation, SystemProcessorInformation, // obsolete...delete SystemPerformanceInformation, SystemTimeOfDayInformation, SystemPathInformation, SystemProcessInformation, SystemCallCountInformation, SystemDeviceInformation, SystemProcessorPerformanceInformation, SystemFlagsInformation, SystemCallTimeInformation, SystemModuleInformation, SystemLocksInformation, SystemStackTraceInformation, SystemPagedPoolInformation, SystemNonPagedPoolInformation, SystemHandleInformation, SystemObjectInformation, SystemPageFileInformation, SystemVdmInstemulInformation, SystemVdmBopInformation, SystemFileCacheInformation, SystemPoolTagInformation, SystemInterruptInformation, SystemDpcBehaviorInformation, SystemFullMemoryInformation, SystemLoadGdiDriverInformation, SystemUnloadGdiDriverInformation, SystemTimeAdjustmentInformation, SystemSummaryMemoryInformation, SystemMirrorMemoryInformation, SystemPerformanceTraceInformation, SystemObsolete0, SystemExceptionInformation, SystemCrashDumpStateInformation, SystemKernelDebuggerInformation, SystemContextSwitchInformation, SystemRegistryQuotaInformation, SystemExtendServiceTableInformation, SystemPrioritySeparation, SystemVerifierAddDriverInformation, SystemVerifierRemoveDriverInformation, SystemProcessorIdleInformation, SystemLegacyDriverInformation, SystemCurrentTimeZoneInformation, SystemLookasideInformation, SystemTimeSlipNotification, SystemSessionCreate, SystemSessionDetach, SystemSessionInformation, SystemRangeStartInformation, SystemVerifierInformation, SystemVerifierThunkExtend, SystemSessionProcessInformation, SystemLoadGdiDriverInSystemSpace, SystemNumaProcessorMap, SystemPrefetcherInformation, SystemExtendedProcessInformation, SystemRecommendedSharedDataAlignment, SystemComPlusPackage, SystemNumaAvailableMemory, SystemProcessorPowerInformation, SystemEmulationBasicInformation, SystemEmulationProcessorInformation, SystemExtendedHandleInformation, SystemLostDelayedWriteInformation } SYSTEM_INFORMATION_CLASS; typedef enum _EVENT_INFORMATION_CLASS { EventBasicInformation } EVENT_INFORMATION_CLASS; typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; // DEVL only LARGE_INTEGER InterruptTime; // DEVL only ULONG InterruptCount; } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; typedef enum _EVENT_TYPE { NotificationEvent, SynchronizationEvent } EVENT_TYPE; typedef struct _EVENT_BASIC_INFORMATION { EVENT_TYPE EventType; LONG EventState; } EVENT_BASIC_INFORMATION, *PEVENT_BASIC_INFORMATION; #define RTL_MEG (1024UL * 1024UL) #define RTLP_IMAGE_MAX_DOS_HEADER ( 256UL * RTL_MEG) typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION { BOOLEAN KernelDebuggerEnabled; BOOLEAN KernelDebuggerNotPresent; } SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION; typedef struct _STRING { USHORT Length; USHORT MaximumLength; #ifdef MIDL_PASS [size_is(MaximumLength), length_is(Length) ] #endif // MIDL_PASS PCHAR Buffer; } STRING; typedef STRING *PSTRING; typedef STRING ANSI_STRING; typedef PSTRING PANSI_STRING; typedef STRING OEM_STRING; typedef PSTRING POEM_STRING; typedef CONST STRING* PCOEM_STRING; typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; #ifdef MIDL_PASS [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer; #else // MIDL_PASS PWSTR Buffer; #endif // MIDL_PASS } UNICODE_STRING; typedef UNICODE_STRING *PUNICODE_STRING; typedef const UNICODE_STRING *PCUNICODE_STRING; #define UNICODE_NULL ((WCHAR)0) // winnt typedef struct _STRING32 { USHORT Length; USHORT MaximumLength; ULONG Buffer; } STRING32; typedef STRING32 *PSTRING32; typedef STRING32 UNICODE_STRING32; typedef UNICODE_STRING32 *PUNICODE_STRING32; typedef STRING32 ANSI_STRING32; typedef ANSI_STRING32 *PANSI_STRING32; typedef struct _STRING64 { USHORT Length; USHORT MaximumLength; ULONGLONG Buffer; } STRING64; typedef STRING64 *PSTRING64; typedef STRING64 UNICODE_STRING64; typedef UNICODE_STRING64 *PUNICODE_STRING64; typedef STRING64 ANSI_STRING64; typedef ANSI_STRING64 *PANSI_STRING64; #define GDI_HANDLE_BUFFER_SIZE32 34 #define GDI_HANDLE_BUFFER_SIZE64 60 #if !defined(TARGET_AMD64) #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32 #else #define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE64 #endif typedef ULONG GDI_HANDLE_BUFFER32[GDI_HANDLE_BUFFER_SIZE32]; typedef ULONG GDI_HANDLE_BUFFER64[GDI_HANDLE_BUFFER_SIZE64]; typedef ULONG GDI_HANDLE_BUFFER [GDI_HANDLE_BUFFER_SIZE ]; typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; HANDLE SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; PVOID EntryInProgress; } PEB_LDR_DATA, *PPEB_LDR_DATA; typedef struct _PEB_FREE_BLOCK { struct _PEB_FREE_BLOCK *Next; ULONG Size; } PEB_FREE_BLOCK, *PPEB_FREE_BLOCK; typedef PVOID* PPVOID; typedef VOID (*PPS_POST_PROCESS_INIT_ROUTINE) ( VOID ); typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union _foo { LIST_ENTRY HashLinks; struct _bar { PVOID SectionPointer; ULONG CheckSum; }; }; union _foo2 { struct _bar2 { ULONG TimeDateStamp; }; struct _bar3 { PVOID LoadedImports; }; }; PVOID EntryPointActivationContext; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; #define TYPE3(arg) arg typedef struct _PEB { BOOLEAN InheritedAddressSpace; // These four fields cannot change unless the BOOLEAN ReadImageFileExecOptions; // BOOLEAN BeingDebugged; // BOOLEAN SpareBool; // HANDLE Mutant; // INITIAL_PEB structure is also updated. PVOID ImageBaseAddress; PPEB_LDR_DATA Ldr; TYPE3(struct _RTL_USER_PROCESS_PARAMETERS*) ProcessParameters; PVOID SubSystemData; PVOID ProcessHeap; TYPE3(struct _RTL_CRITICAL_SECTION*) FastPebLock; PVOID FastPebLockRoutine; PVOID FastPebUnlockRoutine; ULONG EnvironmentUpdateCount; PVOID KernelCallbackTable; ULONG SystemReserved[1]; struct _foo { ULONG ExecuteOptions : 2; ULONG SpareBits : 30; }; PPEB_FREE_BLOCK FreeList; ULONG TlsExpansionCounter; PVOID TlsBitmap; ULONG TlsBitmapBits[2]; // TLS_MINIMUM_AVAILABLE bits PVOID ReadOnlySharedMemoryBase; PVOID ReadOnlySharedMemoryHeap; PPVOID ReadOnlyStaticServerData; PVOID AnsiCodePageData; PVOID OemCodePageData; PVOID UnicodeCaseTableData; // // Useful information for LdrpInitialize ULONG NumberOfProcessors; ULONG NtGlobalFlag; // // Passed up from MmCreatePeb from Session Manager registry key // LARGE_INTEGER CriticalSectionTimeout; SIZE_T HeapSegmentReserve; SIZE_T HeapSegmentCommit; SIZE_T HeapDeCommitTotalFreeThreshold; SIZE_T HeapDeCommitFreeBlockThreshold; // // Where heap manager keeps track of all heaps created for a process // Fields initialized by MmCreatePeb. ProcessHeaps is initialized // to point to the first free byte after the PEB and MaximumNumberOfHeaps // is computed from the page size used to hold the PEB, less the fixed // size of this data structure. // ULONG NumberOfHeaps; ULONG MaximumNumberOfHeaps; PPVOID ProcessHeaps; // // PVOID GdiSharedHandleTable; PVOID ProcessStarterHelper; ULONG GdiDCAttributeList; PVOID LoaderLock; // // Following fields filled in by MmCreatePeb from system values and/or // image header. // ULONG OSMajorVersion; ULONG OSMinorVersion; USHORT OSBuildNumber; USHORT OSCSDVersion; ULONG OSPlatformId; ULONG ImageSubsystem; ULONG ImageSubsystemMajorVersion; ULONG ImageSubsystemMinorVersion; ULONG_PTR ImageProcessAffinityMask; GDI_HANDLE_BUFFER GdiHandleBuffer; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; PVOID TlsExpansionBitmap; ULONG TlsExpansionBitmapBits[32]; // TLS_EXPANSION_SLOTS bits // // Id of the Hydra session in which this process is running // ULONG SessionId; // // Filled in by LdrpInstallAppcompatBackend // ULARGE_INTEGER AppCompatFlags; // // ntuser appcompat flags // ULARGE_INTEGER AppCompatFlagsUser; // // Filled in by LdrpInstallAppcompatBackend // PVOID pShimData; // // Filled in by LdrQueryImageFileExecutionOptions // PVOID AppCompatInfo; // // Used by GetVersionExW as the szCSDVersion string // UNICODE_STRING CSDVersion; // // Fusion stuff // PVOID ActivationContextData; PVOID ProcessAssemblyStorageMap; PVOID SystemDefaultActivationContextData; PVOID SystemAssemblyStorageMap; // // Enforced minimum initial commit stack // SIZE_T MinimumStackCommit; } PEB, *PPEB; #define ACTIVATION_CONTEXT_STACK_FLAG_QUERIES_DISABLED (0x00000001) typedef struct _ACTIVATION_CONTEXT_STACK { ULONG Flags; ULONG NextCookieSequenceNumber; PVOID ActiveFrame; LIST_ENTRY FrameListCache; #if NT_SXS_PERF_COUNTERS_ENABLED struct _ACTIVATION_CONTEXT_STACK_PERF_COUNTERS { ULONGLONG Activations; ULONGLONG ActivationCycles; ULONGLONG Deactivations; ULONGLONG DeactivationCycles; } Counters; #endif // NT_SXS_PERF_COUNTERS_ENABLED } ACTIVATION_CONTEXT_STACK, *PACTIVATION_CONTEXT_STACK; typedef const ACTIVATION_CONTEXT_STACK *PCACTIVATION_CONTEXT_STACK; #define TEB_ACTIVE_FRAME_CONTEXT_FLAG_EXTENDED (0x00000001) typedef struct _TEB_ACTIVE_FRAME_CONTEXT { ULONG Flags; PCSTR FrameName; } TEB_ACTIVE_FRAME_CONTEXT, *PTEB_ACTIVE_FRAME_CONTEXT; typedef const struct _TEB_ACTIVE_FRAME_CONTEXT *PCTEB_ACTIVE_FRAME_CONTEXT; typedef struct _TEB_ACTIVE_FRAME_CONTEXT_EX { TEB_ACTIVE_FRAME_CONTEXT BasicContext; PCSTR SourceLocation; // e.g. "Z:\foo\bar\baz.c" } TEB_ACTIVE_FRAME_CONTEXT_EX, *PTEB_ACTIVE_FRAME_CONTEXT_EX; typedef const struct _TEB_ACTIVE_FRAME_CONTEXT_EX *PCTEB_ACTIVE_FRAME_CONTEXT_EX; #define TEB_ACTIVE_FRAME_FLAG_EXTENDED (0x00000001) typedef struct _TEB_ACTIVE_FRAME { ULONG Flags; TYPE3(struct _TEB_ACTIVE_FRAME*) Previous; PCTEB_ACTIVE_FRAME_CONTEXT Context; } TEB_ACTIVE_FRAME, *PTEB_ACTIVE_FRAME; typedef const struct _TEB_ACTIVE_FRAME *PCTEB_ACTIVE_FRAME; typedef struct _TEB_ACTIVE_FRAME_EX { TEB_ACTIVE_FRAME BasicFrame; PVOID ExtensionIdentifier; // use address of your DLL Main or something unique to your mapping in the address space } TEB_ACTIVE_FRAME_EX, *PTEB_ACTIVE_FRAME_EX; typedef const struct _TEB_ACTIVE_FRAME_EX *PCTEB_ACTIVE_FRAME_EX; typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID; typedef CLIENT_ID *PCLIENT_ID; #define GDI_BATCH_BUFFER_SIZE 310 typedef struct _GDI_TEB_BATCH { ULONG Offset; ULONG_PTR HDC; ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; } GDI_TEB_BATCH,*PGDI_TEB_BATCH; typedef struct _Wx86ThreadState { PULONG CallBx86Eip; PVOID DeallocationCpu; BOOLEAN UseKnownWx86Dll; char OleStubInvoked; } WX86THREAD, *PWX86THREAD; #define STATIC_UNICODE_BUFFER_LENGTH 261 #define WIN32_CLIENT_INFO_LENGTH 62 typedef struct _PEB* PPEB; typedef struct _TEB { NT_TIB NtTib; PVOID EnvironmentPointer; CLIENT_ID ClientId; PVOID ActiveRpcHandle; PVOID ThreadLocalStoragePointer; #if defined(PEBTEB_BITS) PVOID ProcessEnvironmentBlock; #else PPEB ProcessEnvironmentBlock; #endif ULONG LastErrorValue; ULONG CountOfOwnedCriticalSections; PVOID CsrClientThread; PVOID Win32ThreadInfo; // PtiCurrent ULONG User32Reserved[26]; // user32.dll items ULONG UserReserved[5]; // Winsrv SwitchStack PVOID WOW32Reserved; // used by WOW LCID CurrentLocale; ULONG FpSoftwareStatusRegister; // offset known by outsiders! PVOID SystemReserved1[54]; // Used by FP emulator NTSTATUS ExceptionCode; // for RaiseUserException ACTIVATION_CONTEXT_STACK ActivationContextStack; // Fusion activation stack // sizeof(PVOID) is a way to express processor-dependence, more generally than #ifdef HOST_64BIT UCHAR SpareBytes1[48 - sizeof(PVOID) - sizeof(ACTIVATION_CONTEXT_STACK)]; GDI_TEB_BATCH GdiTebBatch; // Gdi batching CLIENT_ID RealClientId; HANDLE GdiCachedProcessHandle; ULONG GdiClientPID; ULONG GdiClientTID; PVOID GdiThreadLocalInfo; ULONG_PTR Win32ClientInfo[WIN32_CLIENT_INFO_LENGTH]; // User32 Client Info PVOID glDispatchTable[233]; // OpenGL ULONG_PTR glReserved1[29]; // OpenGL PVOID glReserved2; // OpenGL PVOID glSectionInfo; // OpenGL PVOID glSection; // OpenGL PVOID glTable; // OpenGL PVOID glCurrentRC; // OpenGL PVOID glContext; // OpenGL ULONG LastStatusValue; UNICODE_STRING StaticUnicodeString; WCHAR StaticUnicodeBuffer[STATIC_UNICODE_BUFFER_LENGTH]; PVOID DeallocationStack; PVOID TlsSlots[TLS_MINIMUM_AVAILABLE]; LIST_ENTRY TlsLinks; PVOID Vdm; PVOID ReservedForNtRpc; PVOID DbgSsReserved[2]; ULONG HardErrorsAreDisabled; PVOID Instrumentation[16]; PVOID WinSockData; // WinSock ULONG GdiBatchCount; BOOLEAN InDbgPrint; BOOLEAN FreeStackOnTermination; BOOLEAN HasFiberData; BOOLEAN IdealProcessor; ULONG Spare3; PVOID ReservedForPerf; PVOID ReservedForOle; ULONG WaitingOnLoaderLock; WX86THREAD Wx86Thread; PPVOID TlsExpansionSlots; LCID ImpersonationLocale; // Current locale of impersonated user ULONG IsImpersonating; // Thread impersonation status PVOID NlsCache; // NLS thread cache PVOID pShimData; // Per thread data used in the shim ULONG HeapVirtualAffinity; HANDLE CurrentTransactionHandle;// reserved for TxF transaction context PTEB_ACTIVE_FRAME ActiveFrame; } TEB; typedef TEB *PTEB; typedef struct _CURDIR { UNICODE_STRING DosPath; HANDLE Handle; } CURDIR, *PCURDIR; #define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 #define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; USHORT Length; ULONG TimeStamp; STRING DosPath; } RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR; #define RTL_MAX_DRIVE_LETTERS 32 #define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; ULONG Length; ULONG Flags; ULONG DebugFlags; HANDLE ConsoleHandle; ULONG ConsoleFlags; HANDLE StandardInput; HANDLE StandardOutput; HANDLE StandardError; CURDIR CurrentDirectory; // ProcessParameters UNICODE_STRING DllPath; // ProcessParameters UNICODE_STRING ImagePathName; // ProcessParameters UNICODE_STRING CommandLine; // ProcessParameters PVOID Environment; // NtAllocateVirtualMemory ULONG StartingX; ULONG StartingY; ULONG CountX; ULONG CountY; ULONG CountCharsX; ULONG CountCharsY; ULONG FillAttribute; ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; // ProcessParameters UNICODE_STRING DesktopInfo; // ProcessParameters UNICODE_STRING ShellInfo; // ProcessParameters UNICODE_STRING RuntimeData; // ProcessParameters RTL_DRIVE_LETTER_CURDIR CurrentDirectores[ RTL_MAX_DRIVE_LETTERS ]; } RTL_USER_PROCESS_PARAMETERS, *PRTL_USER_PROCESS_PARAMETERS; typedef enum _PROCESSINFOCLASS { ProcessBasicInformation, ProcessQuotaLimits, ProcessIoCounters, ProcessVmCounters, ProcessTimes, ProcessBasePriority, ProcessRaisePriority, ProcessDebugPort, ProcessExceptionPort, ProcessAccessToken, ProcessLdtInformation, ProcessLdtSize, ProcessDefaultHardErrorMode, ProcessIoPortHandlers, // Note: this is kernel mode only ProcessPooledUsageAndLimits, ProcessWorkingSetWatch, ProcessUserModeIOPL, ProcessEnableAlignmentFaultFixup, ProcessPriorityClass, ProcessWx86Information, ProcessHandleCount, ProcessAffinityMask, ProcessPriorityBoost, ProcessDeviceMap, ProcessSessionInformation, ProcessForegroundInformation, ProcessWow64Information, ProcessImageFileName, ProcessLUIDDeviceMapsEnabled, ProcessBreakOnTermination, ProcessDebugObjectHandle, ProcessDebugFlags, ProcessHandleTracing, MaxProcessInfoClass // MaxProcessInfoClass should always be the last enum } PROCESSINFOCLASS; typedef struct _VM_COUNTERS { SIZE_T PeakVirtualSize; SIZE_T VirtualSize; ULONG PageFaultCount; SIZE_T PeakWorkingSetSize; SIZE_T WorkingSetSize; SIZE_T QuotaPeakPagedPoolUsage; SIZE_T QuotaPagedPoolUsage; SIZE_T QuotaPeakNonPagedPoolUsage; SIZE_T QuotaNonPagedPoolUsage; SIZE_T PagefileUsage; SIZE_T PeakPagefileUsage; } VM_COUNTERS; typedef VM_COUNTERS *PVM_COUNTERS; #undef TYPE3 #endif // !defined(HOST_UNIX) #if !defined(TARGET_X86) typedef enum _FUNCTION_TABLE_TYPE { RF_SORTED, RF_UNSORTED, RF_CALLBACK } FUNCTION_TABLE_TYPE; typedef struct _DYNAMIC_FUNCTION_TABLE { LIST_ENTRY Links; PT_RUNTIME_FUNCTION FunctionTable; LARGE_INTEGER TimeStamp; #ifdef TARGET_ARM ULONG MinimumAddress; ULONG MaximumAddress; ULONG BaseAddress; #else ULONG64 MinimumAddress; ULONG64 MaximumAddress; ULONG64 BaseAddress; #endif PGET_RUNTIME_FUNCTION_CALLBACK Callback; PVOID Context; PWSTR OutOfProcessCallbackDll; FUNCTION_TABLE_TYPE Type; ULONG EntryCount; } DYNAMIC_FUNCTION_TABLE, *PDYNAMIC_FUNCTION_TABLE; #endif // !TARGET_X86 // // AMD64 // #ifdef TARGET_AMD64 #define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress #define RUNTIME_FUNCTION__SetBeginAddress(prf,address) ((prf)->BeginAddress = (address)) #define RUNTIME_FUNCTION__EndAddress(prf, ImageBase) (prf)->EndAddress #define RUNTIME_FUNCTION__GetUnwindInfoAddress(prf) (prf)->UnwindData #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) #define OFFSETOF__RUNTIME_FUNCTION__UnwindInfoAddress offsetof(T_RUNTIME_FUNCTION, UnwindData) #include "win64unwind.h" typedef PEXCEPTION_ROUTINE (RtlVirtualUnwindFn) ( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL ); #ifndef HOST_UNIX extern RtlVirtualUnwindFn* RtlVirtualUnwind_Unsafe; #else // !HOST_UNIX PEXCEPTION_ROUTINE RtlVirtualUnwind_Unsafe( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, IN PT_RUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL ); #endif // !HOST_UNIX #endif // TARGET_AMD64 // // X86 // #ifdef TARGET_X86 #ifndef HOST_UNIX // // x86 ABI does not define RUNTIME_FUNCTION. Define our own to allow unification between x86 and other platforms. // #ifdef HOST_X86 typedef struct _RUNTIME_FUNCTION { DWORD BeginAddress; DWORD UnwindData; } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; typedef struct _DISPATCHER_CONTEXT { _EXCEPTION_REGISTRATION_RECORD* RegistrationPointer; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; #endif // HOST_X86 #endif // !HOST_UNIX #define RUNTIME_FUNCTION__BeginAddress(prf) (prf)->BeginAddress #define RUNTIME_FUNCTION__SetBeginAddress(prf,addr) ((prf)->BeginAddress = (addr)) #ifdef FEATURE_EH_FUNCLETS #include "win64unwind.h" #include "daccess.h" FORCEINLINE DWORD RtlpGetFunctionEndAddress ( _In_ PT_RUNTIME_FUNCTION FunctionEntry, _In_ TADDR ImageBase ) { PTR_UNWIND_INFO pUnwindInfo = (PTR_UNWIND_INFO)(ImageBase + FunctionEntry->UnwindData); return FunctionEntry->BeginAddress + pUnwindInfo->FunctionLength; } #define RUNTIME_FUNCTION__EndAddress(prf, ImageBase) RtlpGetFunctionEndAddress(prf, ImageBase) #define RUNTIME_FUNCTION__GetUnwindInfoAddress(prf) (prf)->UnwindData #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf, addr) do { (prf)->UnwindData = (addr); } while(0) #ifdef HOST_X86 EXTERN_C NTSYSAPI PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind ( _In_ DWORD HandlerType, _In_ DWORD ImageBase, _In_ DWORD ControlPc, _In_ PRUNTIME_FUNCTION FunctionEntry, __inout PT_CONTEXT ContextRecord, _Out_ PVOID *HandlerData, _Out_ PDWORD EstablisherFrame, __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers ); #endif // HOST_X86 #endif // FEATURE_EH_FUNCLETS #endif // TARGET_X86 #ifdef TARGET_ARM #include "daccess.h" // // Define unwind information flags. // #define UNW_FLAG_NHANDLER 0x0 /* any handler */ #define UNW_FLAG_EHANDLER 0x1 /* filter handler */ #define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ // This function returns the length of a function using the new unwind info on arm. // Taken from minkernel\ntos\rtl\arm\ntrtlarm.h. FORCEINLINE ULONG RtlpGetFunctionEndAddress ( _In_ PT_RUNTIME_FUNCTION FunctionEntry, _In_ TADDR ImageBase ) { ULONG FunctionLength; FunctionLength = FunctionEntry->UnwindData; if ((FunctionLength & 3) != 0) { FunctionLength = (FunctionLength >> 2) & 0x7ff; } else { FunctionLength = *(PTR_ULONG)(ImageBase + FunctionLength) & 0x3ffff; } return FunctionEntry->BeginAddress + 2 * FunctionLength; } #define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ThumbCodeToDataPointer((FunctionEntry)->BeginAddress) #define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = DataPointerToThumbCode(address)) #define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) ThumbCodeToDataPointer(RtlpGetFunctionEndAddress(FunctionEntry, ImageBase)) #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) typedef struct _UNWIND_INFO { // dummy } UNWIND_INFO, *PUNWIND_INFO; #if defined(HOST_UNIX) || defined(HOST_X86) EXTERN_C NTSYSAPI PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind ( _In_ DWORD HandlerType, _In_ DWORD ImageBase, _In_ DWORD ControlPc, _In_ PT_RUNTIME_FUNCTION FunctionEntry, __inout PT_CONTEXT ContextRecord, _Out_ PVOID *HandlerData, _Out_ PDWORD EstablisherFrame, __inout_opt PT_KNONVOLATILE_CONTEXT_POINTERS ContextPointers ); #endif // HOST_UNIX || HOST_X86 #define UNW_FLAG_NHANDLER 0x0 #endif // TARGET_ARM #ifdef TARGET_ARM64 #include "daccess.h" #define UNW_FLAG_NHANDLER 0x0 /* any handler */ #define UNW_FLAG_EHANDLER 0x1 /* filter handler */ #define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ // This function returns the RVA of the end of the function (exclusive, so one byte after the actual end) // using the unwind info on ARM64. (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) FORCEINLINE ULONG64 RtlpGetFunctionEndAddress ( _In_ PT_RUNTIME_FUNCTION FunctionEntry, _In_ ULONG64 ImageBase ) { ULONG64 FunctionLength; FunctionLength = FunctionEntry->UnwindData; if ((FunctionLength & 3) != 0) { // Compact form pdata. if ((FunctionLength & 7) == 3) { // Long branch pdata, by standard this is 3 so size is 12. FunctionLength = 3; } else { FunctionLength = (FunctionLength >> 2) & 0x7ff; } } else { // Get from the xdata record. FunctionLength = *(PTR_ULONG64)(ImageBase + FunctionLength) & 0x3ffff; } return FunctionEntry->BeginAddress + 4 * FunctionLength; } #define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ((FunctionEntry)->BeginAddress) #define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = (address)) #define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) (RtlpGetFunctionEndAddress(FunctionEntry, (ULONG64)(ImageBase))) #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) typedef struct _UNWIND_INFO { // dummy } UNWIND_INFO, *PUNWIND_INFO; EXTERN_C NTSYSAPI PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, IN PRUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL ); #endif #ifdef TARGET_LOONGARCH64 #include "daccess.h" #define UNW_FLAG_NHANDLER 0x0 /* any handler */ #define UNW_FLAG_EHANDLER 0x1 /* filter handler */ #define UNW_FLAG_UHANDLER 0x2 /* unwind handler */ // This function returns the RVA of the end of the function (exclusive, so one byte after the actual end) // using the unwind info on LOONGARCH64. (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) FORCEINLINE ULONG64 RtlpGetFunctionEndAddress ( _In_ PT_RUNTIME_FUNCTION FunctionEntry, _In_ ULONG64 ImageBase ) { ULONG64 FunctionLength; FunctionLength = FunctionEntry->UnwindData; if ((FunctionLength & 3) != 0) { FunctionLength = (FunctionLength >> 2) & 0x7ff; } else { memcpy(&FunctionLength, (void*)(ImageBase + FunctionLength), sizeof(UINT32)); FunctionLength &= 0x3ffff; } return FunctionEntry->BeginAddress + 4 * FunctionLength; } #define RUNTIME_FUNCTION__BeginAddress(FunctionEntry) ((FunctionEntry)->BeginAddress) #define RUNTIME_FUNCTION__SetBeginAddress(FunctionEntry,address) ((FunctionEntry)->BeginAddress = (address)) #define RUNTIME_FUNCTION__EndAddress(FunctionEntry, ImageBase) (RtlpGetFunctionEndAddress(FunctionEntry, (ULONG64)(ImageBase))) #define RUNTIME_FUNCTION__SetUnwindInfoAddress(prf,address) do { (prf)->UnwindData = (address); } while (0) typedef struct _UNWIND_INFO { // dummy } UNWIND_INFO, *PUNWIND_INFO; EXTERN_C NTSYSAPI PEXCEPTION_ROUTINE NTAPI RtlVirtualUnwind( IN ULONG HandlerType, IN ULONG64 ImageBase, IN ULONG64 ControlPc, IN PRUNTIME_FUNCTION FunctionEntry, IN OUT PCONTEXT ContextRecord, OUT PVOID *HandlerData, OUT PULONG64 EstablisherFrame, IN OUT PKNONVOLATILE_CONTEXT_POINTERS ContextPointers OPTIONAL ); #endif // TARGET_LOONGARCH64 #endif // CLRNT_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrtypes.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // ================================================================================ // Standard primitive types for CLR code // // This header serves as a platform layer containing all of the primitive types // which we use across CLR implementation code. // ================================================================================ #ifndef CLRTYPES_H_ #define CLRTYPES_H_ #if defined(_MSC_VER) && !defined(SOURCE_FORMATTING) // Prefer intsafe.h when available, which defines many of the MAX/MIN // values below (which is why they are in #ifndef blocks). #include #endif #include "crtwrap.h" #include "winwrap.h" #include "staticcontract.h" #include "static_assert.h" #if HOST_64BIT #define POINTER_BITS (64) #else #define POINTER_BITS (32) #endif // ================================================================================ // Integral types - use these for all integral types // These types are in ALL_CAPS. Each type has a _MIN and _MAX defined for it. // ================================================================================ // -------------------------------------------------------------------------------- // Use these types for fixed size integers: // INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 // -------------------------------------------------------------------------------- #ifndef INT8_MAX typedef signed char INT8; typedef unsigned char UINT8; typedef short INT16; typedef unsigned short UINT16; typedef int INT32; typedef unsigned int UINT32; typedef __int64 INT64; typedef unsigned __int64 UINT64; #ifdef _MSC_VER /* These macros must exactly match those in the Windows SDK's intsafe.h */ #define INT8_MIN (-127i8 - 1) #define INT16_MIN (-32767i16 - 1) #define INT32_MIN (-2147483647i32 - 1) #define INT64_MIN (-9223372036854775807i64 - 1) #define INT8_MAX 127i8 #define INT16_MAX 32767i16 #define INT32_MAX 2147483647i32 #define INT64_MAX 9223372036854775807i64 #define UINT8_MAX 0xffui8 #define UINT16_MAX 0xffffui16 #define UINT32_MAX 0xffffffffui32 #define UINT64_MAX 0xffffffffffffffffui64 #else #define INT8_MIN ((INT8)0x80) #define INT16_MIN ((INT16)0x8000) #define INT32_MIN ((INT32)0x80000000) #define INT64_MIN ((INT64) I64(0x8000000000000000)) #define INT8_MAX ((INT8)0x7f) #define INT16_MAX ((INT16)0x7fff) #define INT32_MAX ((INT32)0x7fffffff) #define INT64_MAX ((INT64) I64(0x7fffffffffffffff)) #define UINT8_MAX ((UINT8)0xffU) #define UINT16_MAX ((UINT16)0xffffU) #define UINT32_MAX ((UINT32)0xffffffffU) #define UINT64_MAX ((UINT64) UI64(0xffffffffffffffff)) #endif #endif // !INT8_MAX // UINTX_MINs aren't defined in standard header files, // so definition must be separately predicated. #ifndef UINT8_MIN #ifdef _MSC_VER #define UINT8_MIN 0ui8 #define UINT16_MIN 0ui16 #define UINT32_MIN 0ui32 #define UINT64_MIN 0ui64 #else #define UINT8_MIN ((UINT8)0U) #define UINT16_MIN ((UINT16)0U) #define UINT32_MIN ((UINT32)0U) #define UINT64_MIN ((UINT64) UI64(0)) #endif #endif // -------------------------------------------------------------------------------- // Use these types for pointer-sized integral types // SIZE_T SSIZE_T // // These types are the ONLY types which can be safely cast back and forth from a // pointer. // -------------------------------------------------------------------------------- #ifndef SIZE_T_MAX #if NEED_POINTER_SIZED_TYPEDEFS typedef size_t SIZE_T; typedef ptrdiff_t SSIZE_T; #endif #if POINTER_BITS == 64 #define SIZE_T_MAX UINT64_MAX #define SIZE_T_MIN UINT64_MIN #define SSIZE_T_MAX INT64_MAX #define SSIZE_T_MIN INT64_MIN #else #define SIZE_T_MAX UINT32_MAX #define SIZE_T_MIN UINT32_MIN #define SSIZE_T_MAX INT32_MAX #define SSIZE_T_MIN INT32_MIN #endif #endif // -------------------------------------------------------------------------------- // Non-pointer sized types // COUNT_T SCOUNT_T // // Use these types for "large" counts or indexes which will not exceed 32 bits. They // may also be used for pointer differences, if you can guarantee that the pointers // are pointing to the same region of memory. (It can NOT be used for arbitrary // pointer subtraction.) // -------------------------------------------------------------------------------- #ifndef COUNT_T_MAX typedef UINT32 COUNT_T; typedef INT32 SCOUNT_T; #define COUNT_T_MAX UINT32_MAX #define COUNT_T_MIN UINT32_MIN #define SCOUNT_T_MAX INT32_MAX #define SCOUNT_T_MIN INT32_MIN #endif // -------------------------------------------------------------------------------- // Integral types with additional semantic content // BOOL BYTE // -------------------------------------------------------------------------------- #ifndef BYTE_MAX #if NEED_BOOL_TYPEDEF typedef bool BOOL; #endif #define BOOL_MAX 1 #define BOOL_MIN 0 #define TRUE 1 #define FALSE 0 typedef UINT8 BYTE; #define BYTE_MAX UINT8_MAX #define BYTE_MIN UINT8_MIN #endif // -------------------------------------------------------------------------------- // Character types // CHAR SCHAR UCHAR WCHAR // -------------------------------------------------------------------------------- typedef char CHAR; typedef signed char SCHAR; typedef unsigned char UCHAR; typedef CHAR ASCII; typedef CHAR ANSI; typedef CHAR UTF8; // Standard C defines: // CHAR_MAX // CHAR_MIN // SCHAR_MAX // SCHAR_MIN // UCHAR_MAX // UCHAR_MIN // WCHAR_MAX // WCHAR_MIN #ifndef ASCII_MAX #define ASCII_MIN ((ASCII)0) #define ASCII_MAX ((ASCII)127) #define ANSI_MIN ((ANSI)0) #define ANSI_MAX ((ANSI)255) #define UTF8_MIN ((UTF8)0) #define UTF8_MAX ((UTF8)255) #endif // ================================================================================ // Non-integral types // These types are in ALL_CAPS. // ================================================================================ // -------------------------------------------------------------------------------- // Floating point types // FLOAT DOUBLE // -------------------------------------------------------------------------------- // ================================================================================ // Runtime type definitions - these are guaranteed to be identical with the // corresponding managed type // ================================================================================ typedef WCHAR CLR_CHAR; typedef INT8 CLR_I1; typedef UINT8 CLR_U1; typedef INT16 CLR_I2; typedef UINT16 CLR_U2; typedef INT32 CLR_I4; typedef UINT32 CLR_U4; typedef INT64 CLR_I8; typedef UINT64 CLR_U8; typedef FLOAT CLR_R4; typedef DOUBLE CLR_R8; typedef SSIZE_T CLR_I; typedef SIZE_T CLR_U; #define CLR_CHAR_MAX WCHAR_MAX #define CLR_CHAR_MIN WCHAR_MIN #define CLR_I1_MAX INT8_MAX #define CLR_I1_MIN INT8_MIN #define CLR_U1_MAX UINT8_MAX #define CLR_U1_MIN UINT8_MIN #define CLR_I2_MAX INT16_MAX #define CLR_I2_MIN INT16_MIN #define CLR_U2_MAX UINT16_MAX #define CLR_U2_MIN UINT16_MIN #define CLR_I4_MAX INT32_MAX #define CLR_I4_MIN INT32_MIN #define CLR_U4_MAX UINT32_MAX #define CLR_U4_MIN UINT32_MIN #define CLR_I8_MAX INT64_MAX #define CLR_I8_MIN INT64_MIN #define CLR_U8_MAX UINT64_MAX #define CLR_U8_MIN UINT64_MIN #define CLR_I_MAX SSIZE_T_MAX #define CLR_I_MIN SSIZE_T_MIN #define CLR_U_MAX SIZE_T_MAX #define CLR_U_MIN SIZE_T_MIN typedef bool CLR_BOOL; static_assert_no_msg(sizeof(CLR_BOOL) == 1); #define CLR_BOOL_MAX BOOL_MAX #define CLR_BOOL_MIN BOOL_MIN #define CLR_NAN_32 0xFFC00000 #define CLR_NAN_64 I64(0xFFF8000000000000) // ================================================================================ // Simple utility functions // ================================================================================ // Note that these routines are in terms of UINT, ULONG, and ULONG64, since those are // the unsigned integral types the compiler overloads based on. // -------------------------------------------------------------------------------- // Min/Max // -------------------------------------------------------------------------------- template T Min(T v1, T v2) { STATIC_CONTRACT_LEAF; return v1 < v2 ? v1 : v2; } template T Max(T v1, T v2) { STATIC_CONTRACT_LEAF; return v1 > v2 ? v1 : v2; } // -------------------------------------------------------------------------------- // Alignment bit twiddling macros - "alignment" must be power of 2 // // AlignUp - align value to given increment, rounding up // AlignmentPad - amount adjusted by AlignUp // AlignUp(value, x) == value + AlignmentPad(value, x) // // AlignDown - align value to given increment, rounding down // AlignmentTrim - amount adjusted by AlignDown // AlignDown(value, x) == value - AlignmentTrim(value, x) // -------------------------------------------------------------------------------- inline UINT AlignUp(UINT value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value+alignment-1)&~(alignment-1); } #if defined(_MSC_VER) inline ULONG AlignUp(ULONG value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value+alignment-1)&~(alignment-1); } #endif inline UINT64 AlignUp(UINT64 value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value+alignment-1)&~(UINT64)(alignment-1); } #ifdef __APPLE__ inline SIZE_T AlignUp(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value+alignment-1)&~(SIZE_T)(alignment-1); } #endif // __APPLE__ inline UINT AlignDown(UINT value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value&~(alignment-1)); } #if defined(_MSC_VER) inline ULONG AlignDown(ULONG value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value&~(ULONG)(alignment-1)); } #endif inline UINT64 AlignDown(UINT64 value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return (value&~(UINT64)(alignment-1)); } inline UINT AlignmentPad(UINT value, UINT alignment) { STATIC_CONTRACT_WRAPPER; return AlignUp(value, alignment) - value; } #if defined(_MSC_VER) inline UINT AlignmentPad(ULONG value, UINT alignment) { STATIC_CONTRACT_WRAPPER; return AlignUp(value, alignment) - value; } #endif inline UINT AlignmentPad(UINT64 value, UINT alignment) { STATIC_CONTRACT_WRAPPER; return (UINT) (AlignUp(value, alignment) - value); } #ifdef __APPLE__ inline UINT AlignmentPad(SIZE_T value, UINT alignment) { STATIC_CONTRACT_WRAPPER; return (UINT) (AlignUp(value, alignment) - value); } #endif // __APPLE__ inline UINT AlignmentTrim(UINT value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return value&(alignment-1); } #ifndef HOST_UNIX // For Unix this and the previous function get the same types. // So, exclude this one. inline UINT AlignmentTrim(ULONG value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return value&(alignment-1); } #endif // HOST_UNIX inline UINT AlignmentTrim(UINT64 value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return ((UINT)value)&(alignment-1); } #ifdef __APPLE__ inline UINT AlignmentTrim(SIZE_T value, UINT alignment) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; return ((UINT)value)&(alignment-1); } #endif // __APPLE__ #endif // CLRTYPES_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/clrversion.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include "runtime_version.h" #ifndef QUOTE_MACRO #define QUOTE_MACRO_HELPER(x) #x #define QUOTE_MACRO(x) QUOTE_MACRO_HELPER(x) #endif #ifndef QUOTE_MACRO_L #define QUOTE_MACRO_L_HELPER(x) L###x #define QUOTE_MACRO_L(x) QUOTE_MACRO_L_HELPER(x) #endif #define CLR_METADATA_VERSION "v4.0.30319" #define CLR_METADATA_VERSION_L W("v4.0.30319") #define CLR_PRODUCT_VERSION QUOTE_MACRO(RuntimeProductVersion) #define CLR_PRODUCT_VERSION_L QUOTE_MACRO_L(RuntimeProductVersion) #define VER_ASSEMBLYVERSION_STR QUOTE_MACRO(RuntimeAssemblyMajorVersion.RuntimeAssemblyMinorVersion.0.0) #define VER_ASSEMBLYVERSION_STR_L QUOTE_MACRO_L(RuntimeAssemblyMajorVersion.RuntimeAssemblyMinorVersion.0.0) #define VER_FILEVERSION_STR QUOTE_MACRO(RuntimeFileMajorVersion.RuntimeFileMinorVersion.RuntimeFileBuildVersion.RuntimeFileRevisionVersion) #define VER_FILEVERSION_STR_L QUOTE_MACRO_L(RuntimeFileMajorVersion.RuntimeFileMinorVersion.RuntimeFileBuildVersion.RuntimeFileRevisionVersion) #define VER_LEGALCOPYRIGHT_LOGO_STR "Copyright (c) Microsoft Corporation. All rights reserved." ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/complex.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // complex.h // // // Defines a basic complex number data type. We cannot use the standard C++ library's // complex implementation, because the CLR links to the wrong CRT. // #ifndef _COMPLEX_H_ #define _COMPLEX_H_ #include // // Default compilation mode is /fp:precise, which disables fp intrinsics. This causes us to pull in FP stuff (sqrt,etc.) from // The CRT, and increases our download size. We don't need the extra precision this gets us, so let's switch to // the intrinsic versions. // #ifdef _MSC_VER #pragma float_control(precise, off, push) #endif class Complex { public: double r; double i; Complex() : r(0), i(0) {} Complex(double real) : r(real), i(0) {} Complex(double real, double imag) : r(real), i(imag) {} Complex(const Complex& other) : r(other.r), i(other.i) {} }; inline Complex operator+(Complex left, Complex right) { LIMITED_METHOD_CONTRACT; return Complex(left.r + right.r, left.i + right.i); } inline Complex operator-(Complex left, Complex right) { LIMITED_METHOD_CONTRACT; return Complex(left.r - right.r, left.i - right.i); } inline Complex operator*(Complex left, Complex right) { LIMITED_METHOD_CONTRACT; return Complex( left.r * right.r - left.i * right.i, left.r * right.i + left.i * right.r); } inline Complex operator/(Complex left, Complex right) { LIMITED_METHOD_CONTRACT; double denom = right.r * right.r + right.i * right.i; return Complex( (left.r * right.r + left.i * right.i) / denom, (-left.r * right.i + left.i * right.r) / denom); } inline double abs(Complex c) { LIMITED_METHOD_CONTRACT; return sqrt(c.r * c.r + c.i * c.i); } #ifdef _MSC_VER #pragma float_control(pop) #endif #endif //_COMPLEX_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/configuration.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // -------------------------------------------------------------------------------------------------- // configuration.h // // // Access and update configuration values, falling back on legacy CLRConfig methods where necessary. // // -------------------------------------------------------------------------------------------------- #include "clrconfig.h" #ifndef __configuration_h__ #define __configuration_h__ class Configuration { public: static void InitializeConfigurationKnobs(int numberOfConfigs, LPCWSTR *configNames, LPCWSTR *configValues); // Returns (in priority order): // - The value of the ConfigDWORDInfo if it's set // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcstoul). // - The default set in the ConfigDWORDInfo static DWORD GetKnobDWORDValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo); // Returns (in priority order): // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcstoul) // - The default value passed in static DWORD GetKnobDWORDValue(LPCWSTR name, DWORD defaultValue); // Unfortunately our traditional config system insists on interpreting numbers as 32-bit so interpret the config // in the traditional way separately if you need to. // // Returns (in priority order): // - The value of the ConfigurationKnob (searched by name) if it's set (performs a _wcstoui64) // - The default value passed in static ULONGLONG GetKnobULONGLONGValue(LPCWSTR name, ULONGLONG defaultValue); // Returns (in priority order): // - The value of the ConfigStringInfo if it's set // - The value of the ConfigurationKnob (searched by name) if it's set // - nullptr static LPCWSTR GetKnobStringValue(LPCWSTR name, const CLRConfig::ConfigStringInfo& stringInfo); // Returns (in priority order): // - The value of the ConfigurationKnob (searched by name) if it's set // - nullptr static LPCWSTR GetKnobStringValue(LPCWSTR name); // Returns (in priority order): // - The value of the ConfigDWORDInfo if it's set (0 is false, anything else is true) // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). // - The default set in the ConfigDWORDInfo (0 is false, anything else is true) static bool GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo); // Returns (in priority order): // - The value of the ConfigDWORDInfo if it's set (0 is false, anything else is true) // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). // - The default value passed in static bool GetKnobBooleanValue(LPCWSTR name, const CLRConfig::ConfigDWORDInfo& dwordInfo, bool defaultValue); // Returns (in priority order): // - The value of the ConfigurationKnob (searched by name) if it's set (performs a wcscmp with "true"). // - The default value passed in static bool GetKnobBooleanValue(LPCWSTR name, bool defaultValue); }; #endif // __configuration_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/contract.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // Contract.h // // ! I am the owner for issues in the contract *infrastructure*, not for every // ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine // ! CONTRACT_VIOLATION, you will become the new owner of this file. //-------------------------------------------------------------------------------- // CONTRACTS - User Reference // // A CONTRACT is a container for a set of checked declarations about a // function. Besides giving developers a "laundry list" of checks to // make checking more complete, contracts compile these checks // as hidden annotations into the checked executable that our static scanner // uses to detect violations automatically. // // Contracts can be dynamic or static. Dynamic contracts perform runtime checks // as well as being visible to the static scanner. Static contracts generate no // runtime code but are still visible to the scanner. Dynamic contracts are // preferred unless perf or other considerations preclude them. // // The following annotations can appear in contracts: // // // THROWS an exception might be thrown out of the function // -or- NOTHROW an exception will NOT be thrown out of the function // // // // INJECT_FAULT(statement) function might require its caller to handle an OOM // -or- FAULT_FORBID function will NOT require its caller to handle an OOM // // // // GC_TRIGGERS the function can trigger a GC // -or- GC_NOTRIGGER the function will never trigger a GC provided its // called in coop mode. // // // MODE_COOPERATIVE the function requires Cooperative GC mode on entry // -or- MODE_PREEMPTIVE the function requires Preemptive GC mode on entry // -or- MODE_ANY the function can be entered in either mode // // LOADS_TYPE(level) the function promises not to load any types beyond "level" // // CAN_TAKE_LOCK the function has a code path that takes a lock // _or_ (CAN_TAKE_LOCK and CANNOT_RETAKE_LOCK) // the function has a code path that takes a lock, but never tries to reenter // locks held at the time this function was called. // -or- CANNOT_TAKE_LOCK the function will never allow a lock to be taken // -or- the default is WRAPPER(CAN_TAKE_LOCK). i.e., if any callees take locks, // then it's ok for this function to as well. If LIMITED_METHOD_CONTRACT is specified, // however, then CANNOT_TAKE_LOCK is assumed. // // // SUPPORTS_DAC The function has been written to be callable from out-of-process using DAC. // In builds where DACCESS_COMPILE is defined, such functions can only call // other such functions (and a few primitives like new). Functions that support // DAC must be carefully written to conform to the rules in daccess.h. // // SUPPORTS_DAC_HOST_ONLY The function and its call graph has been written to be callable from out of process // using DAC, but it differs from SUPPORTS_DAC in that these functions won't perform // any marshalling. Because it does no marshalling, SUPPORTS_DAC_HOST_ONLY functions // and their call graph won't be checked by DacCop. This should only be used by utility // functions which will never marshal anything. // // PRECONDITION(X) - generic CHECK or BOOL expression which should be true // on function entry // // POSTCONDITION(X) - generic CHECK or BOOL expression which should be true // on function entry. Note that variable RETVAL will be // available for use in the expression. // // // INSTANCE_CHECK - equivalent of: // PRECONDITION(CheckPointer(this)); // POSTCONDITION(CheckInvariant(this)); // INSTANCE_CHECK_NULL - equivalent of: // PRECONDITION(CheckPointer(this, NULL_OK)); // POSTCONDITION(CheckInvariant(this, NULL_OK)); // CONSTRUCTOR_CHECK - equivalent of: // POSTCONDITION(CheckPointer(this)); // DESTRUCTOR_CHECK - equivalent of: // PRECONDITION(CheckPointer(this)); // // // // // Contracts come in the following flavors: // // Dynamic: // CONTRACTL the standard version used for all dynamic contracts // except those including postconditions. // // CONTRACT(rettype) an uglier version of CONTRACTL that's unfortunately // needed to support postconditions. You must specify // the correct return type and it cannot be "void." // (Use CONTRACT_VOID instead) You must use the // RETURN macro rather than the "return" keyword. // // CONTRACT_VOID you can't supply "void" to a CONTRACT - use this // instead. // // Static: // LIMITED_METHOD_CONTRACT // A static contract equivalent to NOTHROW/GC_NOTRIGGER/FORBID_FAULT/MODE_ANY. // Use only for trivial functions that call only functions with LIMITED_METHOD_CONTRACTs // (as long as there is no cycle that may introduce infinite recursion). // // STATIC_CONTRACT_THROWS // STATIC_CONTRACT_NOTHROW // STATIC_CONTRACT_GC_TRIGGERS // STATIC_CONTRACT_GCNOTRIGGER // STATIC_CONTRACT_FAULT // STATIC_CONTRACT_FORBID_FAULT // use to implement statically checkable contracts // when runtime contracts cannot be used. // // // WRAPPER(annotation) // // When a function does not explicitly caused a condition, use the WRAPPER macro around // the declaration. This implies that the function is dependent on the functions it calls // for its behaviour, and guarantees nothing. // // // CONTRACT_VIOLATION(violationmask): // // A bandaid used to suppress contract assertions. A contract violation // is always a bug and you're expected to remove it before shipping. // If a violation cannot be fixed immediately, however, it's better // to use this on the offending callsite than to disable a contract entirely. // // The violationmask can be one or more of the following OR'd together. // // ThrowsViolation // GCViolation // ModeViolation // FaultViolation // FaultNotFatal // HostViolation // LoadsTypeViolation // TakesLockViolation // // The associated assertion will be suppressed until you leave the scope // containing the CONTRACT_VIOLATION. Note, however, that any called // function that redeclares the associated annotation reinstates // the assert for the scope of *its* call. This prevents a CONTRACT_VIOLATION // placed at the root of a calltree from decimating our entire protection. // // // PERMANENT_CONTRACT_VIOLATION(violationmask, permanentContractViolationReason): // // Like a CONTRACT_VIOLATION but also indicates that the violation was a deliberate decision // and we don't plan on removing the violation in the next release. The reason // for the violation should be given as the second parameter to the macro. Reasons // are currently for documentation purposes only and do not have an effect on the binary. // Valid values are listed below in the definition of PermanentContractViolationReason. // // // CONDITIONAL_CONTRACT_VIOLATION(violationmask, condition): // // Similar to CONTRACT_VIOLATION, but only suppresses the contract if the // condition evaluates to non-zero. The need for this macro should be very // rare, but it can be useful if a contract should be suppressed based on a // condition known only at run-time. For example, if a particular test causes // call sequences never expected by real scenarios, you may want to suppress // resulting violations, but only when that test is run. // // WRAPPER_NO_CONTRACT // // A do-nothing contract used by functions that trivially wrap another. // // // "LEGACY" stuff - these features have been mostly superseded by better solutions // so their use should be discouraged. // // // DISABLED(annotation) // // Indicates that a condition is supposed to be checked but is being suppressed // due to some temporary bug. The more surgical CONTRACT_VIOLATION is // preferred over DISABLED. // // UNCHECKED(annotation) // // Indicates that a condition is supposed to be checked but is being suppressed // due for perf reasons. Use STATIC_CONTRACT over this. // // // Default values: // If you don't specify certain annotaions, you get defaults. // - THROWS/NOTHROW defaults to THROWS // - GCTRIGGERS/GCNOTRIGGER defaults to GCTRIGGERS within the VM directory // and to no check otherwise // - INJECT/FORBID_FAULT defaults to no check // - MODE defaults to MODE_ANY // // The problem is that defaults don't work well with static contracts. // The scanner will always treat a missing annotation as DISABLED. // New code should not rely on defaults. Explicitly state your invariants. // // //-------------------------------------------------------------------------------- #ifndef CONTRACT_H_ #define CONTRACT_H_ #ifdef _MSC_VER #pragma warning(disable:4189) //local variable is initialized but not referenced #endif // We only enable contracts in _DEBUG builds #if defined(_DEBUG) && !defined(DISABLE_CONTRACTS) && !defined(JIT_BUILD) #define ENABLE_CONTRACTS_DATA #endif // Also, we won't enable contracts if this is a DAC build. #if defined(ENABLE_CONTRACTS_DATA) && !defined(DACCESS_COMPILE) && !defined(CROSS_COMPILE) #define ENABLE_CONTRACTS #endif // Finally, only define the implementation parts of contracts if this isn't a DAC build. #if defined(_DEBUG_IMPL) && defined(ENABLE_CONTRACTS) #define ENABLE_CONTRACTS_IMPL #endif #include "specstrings.h" #include "clrtypes.h" #include "malloc.h" #include "check.h" #include "debugreturn.h" #include "staticcontract.h" #ifdef ENABLE_CONTRACTS_DATA #include "eh.h" // We chain these onto a stack to give us a stack trace of contract assertions (useful // when the bug report doesn't contain valid symbols) struct ContractStackRecord { ContractStackRecord *m_pNext; const char *m_szFunction; const char *m_szFile; int m_lineNum; UINT m_testmask; // Bitmask of Contract::TestEnum bitsf const char *m_construct; // The syntactic construct that pushed this thing }; class CrstBase; // The next few enums / structs are used to keep track of all kinds of locks // currently taken by the current thread (crsts, spinlocks, CLR critical sections). // Across the VM, there are still multiple counts of locks. The lock counts in these // contract structs are used to verify consistency of lock take/release in EE code, and // for contracts. Both user and EE locks are tracked here, but it's EE code consistency // we're verifying. The Thread object keeps its own counts as well, primarily of user // locks for implementing thread abort & escalation policy. We tried to have the Thread // counts also be used for consistency checking, but that doesn't work. Thread counters // have the following behavior that hurts our internal consistency checks: // - They only count user locks. // - Counters are reset & restored as we leave and return to AppDomains // An array of these is stored in DbgStateLockData::m_rgTakenLockInfos // to remember which locks we've taken. If you hit an assert that // indicates we're exiting locks in the wrong order, or that locks were // taken when we expected none to be taken, then you can use // DbgStateLockData::m_rgTakenLockInfos to see the locks we know about. struct TakenLockInfo { // Generally, this will be a pointer to the lock, but really it's just // a value that identifies which lock is taken. Ya see, sometimes we don't // have a lock pointer handy (e.g., if the lock is based on a GC object, // which has no persistent object pointer we can use). Look at the source // indicated by m_szFile / m_lineNum to see what was specified as m_pvLock. // // A common case is that the lock is just a Crst, so to aid debugging, we // also include a statically typed version of this pointer (m_pCrstBase) just // for Crsts. Again, you'll want look at m_szFile / m_lineNum to see how to // interpret this union. union { void * m_pvLock; CrstBase * m_pCrstBase; }; // File & line of the *LOCK_TAKEN* macro that added this lock to our list const char * m_szFile; int m_lineNum; }; enum DbgStateLockType { // EE locks (used to sync EE structures). These do not include // CRST_HOST_BREAKABLE Crsts, and are thus not held while managed // code runs kDbgStateLockType_EE, // CRST_HOST_BREAKABLE Crsts. These can be held while arbitrary // managed code runs. kDbgStateLockType_HostBreakableCrst, // User locks (e.g., Monitor.Enter, ReaderWriterLock class) kDbgStateLockType_User, // add more lock types here kDbgStateLockType_Count }; // This keeps track of how many locks, and which locks, are currently owned // by the current thread. There is one instance of this structure per // thread (no EE Thread object required). This is in contrast to the // ClrDebugState structure, which is instantiated once per function // on the stack. Reason is that ClrDebugState resets its state on exit // of function (Contract destructor reinstates previous ClrDebugState), whereas // we want DbgStateLockData to persist across function enters & exits. struct DbgStateLockData { // When a lock is taken, we keep track of its pointer and file/line# when it // was added in a static-size array DbgStateLockData::m_rgTakenLockInfos. This is // the size of that array, and therefore indicates the maximum number of locks we // expect one thread to hold at the same time. If we should exceed this limit, // we'll lose this data for the latter locks that exceed this limit // (though still maintaining an accurate *count* of locks). static const int kMaxAllowedSimultaneousLocks = 20; // Count of locks taken, separately by type UINT m_rgcLocksTaken[kDbgStateLockType_Count]; // List of the specific locks that have been taken (all DbgStateLockTypes // intermingled), in the order they were taken. If we exceed the elements // in the array, we just won't track the latter locks in here (though they are // included in the counts above) TakenLockInfo m_rgTakenLockInfos[kMaxAllowedSimultaneousLocks]; void SetStartingValues(); void LockTaken(DbgStateLockType dbgStateLockType, UINT cEntrances, void * pvLock, _In_z_ const char * szFunction, _In_z_ const char * szFile, int lineNum); void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock); UINT GetLockCount(DbgStateLockType dbgStateLockType); UINT GetCombinedLockCount(); }; // This struct contains all lock contract information. It is created and destroyed along with // ClrDebugState. m_pLockData points to a DbgStateLockData object that is allocated per thread // and persists across function enters and exists. struct DbgStateLockState { private: // Count of locks taken at the time the function with CANNOT_RETAKE_LOCK contract // was called UINT m_cLocksEnteringCannotRetakeLock; DbgStateLockData * m_pLockData; // How many and which locks are currently taken on this thread public: void SetStartingValues(); void OnEnterCannotRetakeLockFunction(); BOOL IsLockRetaken(void * pvLock); BOOL IsSafeToRelease(UINT cReleases); void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData); DbgStateLockData * GetDbgStateLockData(); }; #define CONTRACT_BITMASK_OK_TO_THROW 0x1 << 0 #define CONTRACT_BITMASK_FAULT_FORBID 0x1 << 1 #define CONTRACT_BITMASK_HOSTCALLS 0x1 << 2 #define CONTRACT_BITMASK_SOTOLERANT 0x1 << 3 #define CONTRACT_BITMASK_DEBUGONLY 0x1 << 4 #define CONTRACT_BITMASK_SONOTMAINLINE 0x1 << 5 #define CONTRACT_BITMASK_OK_TO_LOCK 0x1 << 6 #define CONTRACT_BITMASK_OK_TO_RETAKE_LOCK 0x1 << 7 #define CONTRACT_BITMASK_IS_SET(whichbit) ((m_flags & (whichbit)) != 0) #define CONTRACT_BITMASK_SET(whichbit) (m_flags |= (whichbit)) #define CONTRACT_BITMASK_RESET(whichbit) (m_flags &= ~(whichbit)) #define CONTRACT_BITMASK_UPDATE(whichbit, value) ((value)?CONTRACT_BITMASK_SET(whichbit):CONTRACT_BITMASK_RESET(whichbit)) struct ClrDebugState { private: UINT_PTR m_flags; UINT_PTR m_violationmask; // Current CONTRACT_VIOLATIONS in effect ContractStackRecord *m_pContractStackTrace; UINT m_GCNoTriggerCount; UINT m_GCForbidCount; UINT m_maxLoadTypeLevel; // taken from enum ClassLoadLevel BOOL m_allowGetThread; // TRUE if GetThread() is ok in this scope DbgStateLockState m_LockState; public: // Use an explicit Init rather than ctor as we don't want automatic // construction of the ClrDebugState embedded inside the contract. void SetStartingValues() { m_violationmask = 0; // No violations allowed // Default is we're in a THROWS scope. This is not ideal, but there are // just too many places that I'd have to go clean up right now // (hundreds) in order to make this FALSE by default. // Faults not forbidden (an unfortunate default but // we'd never get this debug infrastructure bootstrapped otherwise.) // We start out in SO-tolerant mode and must probe before entering SO-intolerant // any global state updates. // Initial mode is non-debug until we say otherwise // Everything defaults to mainline // By default, GetThread() is perfectly fine to call // By default, it's ok to take a lock (or call someone who does) m_flags = CONTRACT_BITMASK_OK_TO_THROW| CONTRACT_BITMASK_HOSTCALLS| CONTRACT_BITMASK_SOTOLERANT| CONTRACT_BITMASK_OK_TO_LOCK| CONTRACT_BITMASK_OK_TO_RETAKE_LOCK; m_pContractStackTrace = NULL; // At top of stack, no contracts in force m_GCNoTriggerCount = 0; m_GCForbidCount = 0; m_maxLoadTypeLevel = ((UINT)(-1)); // ideally CLASS_LOAD_LEVEL_FINAL but we don't have access to that #define, so // the max integer value will do as a substitute. m_allowGetThread = TRUE; // By default, GetThread() is perfectly fine to call m_LockState.SetStartingValues(); } void CheckOkayToThrow(_In_z_ const char *szFunction, _In_z_ const char *szFile, int lineNum); // Asserts if its not okay to throw. BOOL CheckOkayToThrowNoAssert(); // Returns if OK to throw //--// UINT_PTR* ViolationMaskPtr() { return &m_violationmask; } UINT_PTR ViolationMask() { return m_violationmask; } void ViolationMaskSet( UINT_PTR value ) { m_violationmask |= value; } void ViolationMaskReset( UINT_PTR value ) { m_violationmask &= ~value; } //--// BOOL IsOkToThrow() { return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_THROW); } void SetOkToThrow() { CONTRACT_BITMASK_SET(CONTRACT_BITMASK_OK_TO_THROW); } BOOL SetOkToThrow( BOOL value ) { BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_THROW); CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_THROW, value); return prevState; } void ResetOkToThrow() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_THROW); } //--// BOOL IsFaultForbid() { return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID); } void SetFaultForbid() { CONTRACT_BITMASK_SET(CONTRACT_BITMASK_FAULT_FORBID); } BOOL SetFaultForbid(BOOL value) { BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_FAULT_FORBID); CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_FAULT_FORBID, value); return prevState; } void ResetFaultForbid() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_FAULT_FORBID); } //--// BOOL IsHostCaller() { return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_HOSTCALLS); } void SetHostCaller() { CONTRACT_BITMASK_SET(CONTRACT_BITMASK_HOSTCALLS); } BOOL SetHostCaller(BOOL value) { BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_HOSTCALLS); CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_HOSTCALLS,value); return prevState; } void ResetHostCaller() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_HOSTCALLS); } //--// BOOL IsDebugOnly() { STATIC_CONTRACT_WRAPPER; return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_DEBUGONLY); } void SetDebugOnly() { STATIC_CONTRACT_WRAPPER; CONTRACT_BITMASK_SET(CONTRACT_BITMASK_DEBUGONLY); } BOOL SetDebugOnly(BOOL value) { STATIC_CONTRACT_WRAPPER; BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_DEBUGONLY); CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_DEBUGONLY,value); return prevState; } void ResetDebugOnly() { STATIC_CONTRACT_LIMITED_METHOD; CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_DEBUGONLY); } //--// BOOL IsOkToLock() { return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_LOCK); } void SetOkToLock() { CONTRACT_BITMASK_SET(CONTRACT_BITMASK_OK_TO_LOCK); } BOOL SetOkToLock( BOOL value ) { BOOL prevState = CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_LOCK); CONTRACT_BITMASK_UPDATE(CONTRACT_BITMASK_OK_TO_LOCK, value); return prevState; } void ResetOkToLock() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_LOCK); } //--// BOOL IsOkToRetakeLock() { return CONTRACT_BITMASK_IS_SET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK); } void ResetOkToRetakeLock() { CONTRACT_BITMASK_RESET(CONTRACT_BITMASK_OK_TO_RETAKE_LOCK); } //--// void LinkContractStackTrace( ContractStackRecord* pContractStackTrace ) { pContractStackTrace->m_pNext = m_pContractStackTrace; m_pContractStackTrace = pContractStackTrace; } ContractStackRecord* GetContractStackTrace() { return m_pContractStackTrace; } void SetContractStackTrace(ContractStackRecord* pContractStackTrace ) { m_pContractStackTrace = pContractStackTrace; } //--// UINT GetGCNoTriggerCount() { return m_GCNoTriggerCount; } void DecrementGCNoTriggerCount() { m_GCNoTriggerCount--; } void IncrementGCNoTriggerCount() { m_GCNoTriggerCount++; } UINT GetGCForbidCount() { return m_GCForbidCount; } void DecrementGCForbidCount() { m_GCForbidCount--; } void IncrementGCForbidCount() { m_GCForbidCount++; } UINT GetMaxLoadTypeLevel() { return m_maxLoadTypeLevel; } void SetMaxLoadTypeLevel(UINT newLevel) { m_maxLoadTypeLevel = newLevel; } //--// void SetDbgStateLockData(DbgStateLockData * pDbgStateLockData) { m_LockState.SetDbgStateLockData(pDbgStateLockData); } DbgStateLockData * GetDbgStateLockData() { return m_LockState.GetDbgStateLockData(); } void OnEnterCannotRetakeLockFunction() { m_LockState.OnEnterCannotRetakeLockFunction(); } void CheckOkayToLock(_In_z_ const char *szFunction, _In_z_ const char *szFile, int lineNum); // Asserts if its not okay to lock BOOL CheckOkayToLockNoAssert(); // Returns if OK to lock void LockTaken(DbgStateLockType dbgStateLockType, UINT cEntrances, void * pvLock, _In_z_ const char * szFunction, _In_z_ const char * szFile, int lineNum); void LockReleased(DbgStateLockType dbgStateLockType, UINT cExits, void * pvLock); UINT GetLockCount(DbgStateLockType dbgStateLockType); UINT GetCombinedLockCount(); }; #endif // ENABLE_CONTRACTS #ifdef ENABLE_CONTRACTS_IMPL // Create ClrDebugState. // This routine is not allowed to return NULL. If it can't allocate the memory needed, // it should return a pointer to a global static ClrDebugState that indicates // that debug assertions should be skipped. ClrDebugState *CLRInitDebugState(); ClrDebugState *GetClrDebugState(BOOL fAlloc = TRUE); extern thread_local ClrDebugState* t_pClrDebugState; // This function returns a ClrDebugState if one has been created, but will not create one itself. inline ClrDebugState *CheckClrDebugState() { STATIC_CONTRACT_LIMITED_METHOD; return t_pClrDebugState; } void CONTRACT_ASSERT(const char *szElaboration, UINT whichTest, UINT whichTestMask, const char *szFunction, const char *szFile, int lineNum ); #endif // This needs to be defined up here b/c it is used by ASSERT_CHECK which is used by the contract impl #ifdef _DEBUG #ifdef ENTER_DEBUG_ONLY_CODE #undef ENTER_DEBUG_ONLY_CODE #endif #ifdef LEAVE_DEBUG_ONLY_CODE #undef LEAVE_DEBUG_ONLY_CODE #endif #ifdef ENABLE_CONTRACTS_IMPL // This can only appear in a debug function so don't define it non-debug class DebugOnlyCodeHolder { public: // We use GetClrDebugState on entry, but CheckClrDebugState on Leave // That way we make sure to create one if we need to set state, but // we don't recreated one on exit if its been deleted. DEBUG_NOINLINE void Enter() { SCAN_SCOPE_BEGIN; STATIC_CONTRACT_DEBUG_ONLY; m_pClrDebugState = GetClrDebugState(); if (m_pClrDebugState) { m_oldDebugOnlyValue = m_pClrDebugState->IsDebugOnly(); m_pClrDebugState->SetDebugOnly(); } } DEBUG_NOINLINE void Leave() { SCAN_SCOPE_END; STATIC_CONTRACT_DEBUG_ONLY; m_pClrDebugState = CheckClrDebugState(); if (m_pClrDebugState) { m_pClrDebugState->SetDebugOnly( m_oldDebugOnlyValue ); } } private: BOOL m_oldDebugOnlyValue; ClrDebugState *m_pClrDebugState; }; #define ENTER_DEBUG_ONLY_CODE \ DebugOnlyCodeHolder __debugOnlyCodeHolder; \ __debugOnlyCodeHolder.Enter(); #define LEAVE_DEBUG_ONLY_CODE \ __debugOnlyCodeHolder.Leave(); class AutoCleanupDebugOnlyCodeHolder : public DebugOnlyCodeHolder { public: DEBUG_NOINLINE AutoCleanupDebugOnlyCodeHolder() { SCAN_SCOPE_BEGIN; STATIC_CONTRACT_DEBUG_ONLY; Enter(); }; DEBUG_NOINLINE ~AutoCleanupDebugOnlyCodeHolder() { SCAN_SCOPE_END; Leave(); }; }; #define DEBUG_ONLY_FUNCTION \ STATIC_CONTRACT_DEBUG_ONLY; \ AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder; #define DEBUG_ONLY_REGION() \ AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder; #define BEGIN_DEBUG_ONLY_CODE \ { \ AutoCleanupDebugOnlyCodeHolder __debugOnlyCodeHolder; #define END_DEBUG_ONLY_CODE \ } #else // ENABLE_CONTRACTS_IMPL #define DEBUG_ONLY_FUNCTION STATIC_CONTRACT_DEBUG_ONLY #define DEBUG_ONLY_REGION() #define BEGIN_DEBUG_ONLY_CODE #define END_DEBUG_ONLY_CODE #define ENTER_DEBUG_ONLY_CODE #define LEAVE_DEBUG_ONLY_CODE #endif #else // _DEBUG #define DEBUG_ONLY_REGION() #endif #ifdef ENABLE_CONTRACTS_IMPL // These helpers encapsulate our access to our FLS debug state. To improve // contract perf, we'll soon move these to a private alloced block // so we can reuse the pointer instead of constantly refetching it. // Thus, these helpers are just to bridge this transition. inline LPVOID GetViolationMask() { ClrDebugState *pState = CheckClrDebugState(); if (pState) { return (LPVOID)pState->ViolationMask(); } else { return 0; } } // This is the default binding of the MAYBETEMPLATE identifier, // used in the RETURN macro template class ___maybetemplate { public: FORCEINLINE void *operator new (size_t size) { return NULL; } }; // This is an abstract base class for contracts. The main reason we have this is so that the dtor for many derived class can // be performant. If this class was not abstract and had a dtor, then the dtor for the derived class adds EH overhead (even if the derived // class did not anything special in its dtor) class BaseContract { // Really private, but used by macros public: // We use a single integer to specify all the settings for intrinsic tests // such as THROWS and GC_TRIGGERS. The compiler should be able to fold all // these clauses into a single constant. // // The value "0" is significant as this is what the entire mask will be initialized to // in the absence of any clauses. Hence, whichever value is assigned "0" will be the // default setting for the test. // // Also, there must be a "disabled" setting for each category in order to support // the DISABLED macro. enum TestEnum { THROWS_Mask = 0x00000003, THROWS_Yes = 0x00000000, // the default THROWS_No = 0x00000001, THROWS_Disabled = 0x00000002, GC_Mask = 0x0000000C, GC_Triggers = 0x00000000, // the default GC_NoTrigger = 0x00000004, GC_Disabled = 0x00000008, FAULT_Mask = 0x00000030, FAULT_Disabled = 0x00000000, // the default FAULT_Inject = 0x00000010, FAULT_Forbid = 0x00000020, MODE_Mask = 0x000000C0, MODE_Disabled = 0x00000000, // the default MODE_Preempt = 0x00000040, MODE_Coop = 0x00000080, DEBUG_ONLY_Yes = 0x00000400, // code runs under debug only SO_MAINLINE_No = 0x00000800, // code is not part of our mainline SO scenario // Any place where we can't safely call into the host should have a HOST_NoCalls contract HOST_Mask = 0x00003000, HOST_Calls = 0x00002000, HOST_NoCalls = 0x00001000, HOST_Disabled = 0x00000000, // the default // These enforce the CAN_TAKE_LOCK / CANNOT_TAKE_LOCK contracts CAN_TAKE_LOCK_Mask = 0x00060000, CAN_TAKE_LOCK_Yes = 0x00020000, CAN_TAKE_LOCK_No = 0x00040000, CAN_TAKE_LOCK_Disabled = 0x00000000, // the default // These enforce the CANNOT_RETAKE_LOCK contract CAN_RETAKE_LOCK_No = 0x00080000, CAN_RETAKE_LOCK_No_Disabled = 0x00000000, // the default PRECONDITION_Used = 0x00010000, // a PRECONDITION appeared inside the contract // IMPORTANT!!! LOADS_TYPE_Mask and LOADS_TYPE_Shift must be kept in sync. LOADS_TYPE_Mask = 0x00f00000, // the max loadstype level + 1 ("+1" because 0 is reserved for the default which is "disabled") LOADS_TYPE_Shift = 20, // # of bits to right-shift to get loadstype bits to rightmost position. LOADS_TYPE_Disabled = 0x00000000, // the default ALL_Disabled = THROWS_Disabled|GC_Disabled|FAULT_Disabled|MODE_Disabled|LOADS_TYPE_Disabled| HOST_Disabled|CAN_TAKE_LOCK_Disabled|CAN_RETAKE_LOCK_No_Disabled }; enum Operation { Setup = 0x01, Preconditions = 0x02, Postconditions = 0x04, }; NOTHROW_DECL BaseContract() : m_testmask(0), m_pClrDebugState(NULL) { } NOTHROW_DECL void Restore() { // m_pClrDebugState is setup in BaseContract::DoChecks. If an SO happens after the // BaseContract object is constructed but before DoChecks is invoked, m_pClrDebugState // will remain NULL (which is what it is set to in the BaseContract ctor). // // Thus, we should check for it being NULL before dereferencing it. if (m_pClrDebugState) { // Backout all changes to debug state. *m_pClrDebugState = m_IncomingClrDebugState; } } void DoChecks(UINT testmask, _In_z_ const char *szFunction, _In_z_ const char *szFile, int lineNum); void Disable() { } BOOL CheckFaultInjection(); protected: UINT m_testmask; // Override this function in any derived class to indicate that you have defined a destructor for that class // and that dtor calls Restore() virtual void DestructorDefinedThatCallsRestore() = 0; protected: ClrDebugState *m_pClrDebugState; ClrDebugState m_IncomingClrDebugState; ContractStackRecord m_contractStackRecord; public: // -------------------------------------------------------------------------------- // These classes and declarations are used to implement our fake return keyword. // -------------------------------------------------------------------------------- // ___box is used to protect the "detected" return value from being combined with other parts // of the return expression after we have processed it. This can happen if the return // expression is a non-parenthesized expression with an operator of lower precedence than // ">". // // If you have such a case (and see this class listed in an error message), // parenthesize your return value expression. template class Box__USE_PARENS_WITH_THIS_EXPRESSION { const T &value; public: FORCEINLINE Box__USE_PARENS_WITH_THIS_EXPRESSION(const T &value) : value(value) { } FORCEINLINE const T& Unbox() { return value; } }; // PseudoTemplate is a class which can be instantiated with a template-like syntax, resulting // in an expression which simply boxes a following value in a Box template class PseudoTemplate { public: FORCEINLINE void *operator new (size_t size) { return NULL; } FORCEINLINE Box__USE_PARENS_WITH_THIS_EXPRESSION operator>(const T &value) { return Box__USE_PARENS_WITH_THIS_EXPRESSION(value); } FORCEINLINE PseudoTemplate operator<(int dummy) { return PseudoTemplate(); } }; // Returner is used to assign the return value to the RETVAL local. Note the use of // operator , because of its low precedence. template class Returner { RETURNTYPE &m_value; BOOL m_got; public: FORCEINLINE Returner(RETURNTYPE &value) : m_value(value), m_got(FALSE) { } template FORCEINLINE RETURNTYPE operator,(Box__USE_PARENS_WITH_THIS_EXPRESSION value) { m_value = value.Unbox(); m_got = TRUE; return m_value; } FORCEINLINE void operator,(___maybetemplate<0> &dummy) { m_got = TRUE; } FORCEINLINE BOOL GotReturn() { return m_got; } }; // This type ensures that postconditions were run via RETURN or RETURN_VOID class RanPostconditions { public: bool ran; int count; const char *function; FORCEINLINE RanPostconditions(const char *function) : ran(false), count(0), function(function) { } FORCEINLINE int operator++() { return ++count; } FORCEINLINE ~RanPostconditions() { // Note: __uncaught_exception() is not a perfect check. It will return TRUE during any exception // processing. So, if there is a contract called from an exception filter (like our // COMPlusFrameHandler) then it will return TRUE and the saftey check below will not be performed. if (!__uncaught_exception()) ASSERT_CHECK(count == 0 || ran, function, "Didn't run postconditions - be sure to use RETURN at the end of the function"); } }; // Set contract enforcement level static void SetUnconditionalContractEnforcement(BOOL enforceUnconditionally); // Check contract enforcement static BOOL EnforceContract(); private: static BOOL s_alwaysEnforceContracts; }; class Contract: public BaseContract { // Have to override this function in any derived class to indicate that a valid destructor is defined for this class virtual void DestructorDefinedThatCallsRestore(){} public: NOTHROW_DECL ~Contract() { Restore(); } }; #endif // ENABLE_CONTRACTS_IMPL #ifdef _DEBUG // Valid parameters for CONTRACT_VIOLATION macro enum ContractViolationBits { ThrowsViolation = 0x00000001, // suppress THROW tags in this scope GCViolation = 0x00000002, // suppress GCTRIGGER tags in this scope ModeViolation = 0x00000004, // suppress MODE_PREEMP and MODE_COOP tags in this scope FaultViolation = 0x00000008, // suppress INJECT_FAULT assertions in this scope FaultNotFatal = 0x00000010, // suppress INJECT_FAULT but not fault injection by harness LoadsTypeViolation = 0x00000040, // suppress LOADS_TYPE tags in this scope TakesLockViolation = 0x00000080, // suppress CAN_TAKE_LOCK tags in this scope HostViolation = 0x00000100, // suppress HOST_CALLS tags in this scope //These are not violation bits. We steal some bits out of the violation mask to serve as // general flag bits. CanFreeMe = 0x00010000, // If this bit is ON, the ClrDebugState was allocated by // a version of utilcode that registers an Fls Callback to free // the state. If this bit is OFF, the ClrDebugState was allocated // by an old version of utilcode that doesn't. (And you can't // assume that the old utilcode used the same allocator as the new utilcode.) // (Most likely, this is because you are using an older shim with // a newer mscorwks.dll) // // The Fls callback must only attempt to free debugstates that // have this bit on. BadDebugState = 0x00020000, // If we OOM creating the ClrDebugState, we return a pointer to // a static ClrDebugState that has this bit turned on. (We don't // want to slow down contracts with null tests everywhere.) // Other than this specific bit, all other fields of the DebugState // must be considered trash. You can stomp on them and you can bit-test them // but you can't throw up any asserts based on them and you certainly // can't deref any pointers stored in the bad DebugState. AllViolation = 0xFFFFFFFF, }; #endif #ifdef ENABLE_CONTRACTS_IMPL // Global variables allow PRECONDITION and POSTCONDITION to be used outside contracts static const BaseContract::Operation ___op = (Contract::Operation) (Contract::Preconditions |Contract::Postconditions); enum { ___disabled = 0 }; static UINT ___testmask; // End of global variables static int ___ran; class __SafeToUsePostCondition { public: static int safe_to_use_postcondition() {return 0;}; }; class __YouCannotUseAPostConditionHere { private: static int safe_to_use_postcondition() {return 0;}; }; typedef __SafeToUsePostCondition __PostConditionOK; // Uncomment the following line to disable runtime contracts completely - PRE/POST conditions will still be present //#define __FORCE_NORUNTIME_CONTRACTS__ 1 #ifndef __FORCE_NORUNTIME_CONTRACTS__ #define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \ _returntype RETVAL; \ _contracttype ___contract; \ Contract::Returner<_returntype> ___returner(RETVAL); \ Contract::RanPostconditions ___ran(__FUNCTION__); \ Contract::Operation ___op = Contract::Setup; \ BOOL ___contract_enabled = FALSE; \ DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \ ___contract_enabled = Contract::EnforceContract(); \ enum {___disabled = 0}; \ if (!___contract_enabled) \ ___contract.Disable(); \ else \ { \ enum { ___CheckMustBeInside_CONTRACT = 1 }; \ if (0) \ { \ /* If you see an "unreferenced label" warning with this name, */\ /* Be sure that you have a RETURN at the end of your */ \ /* CONTRACT_VOID function */ \ ___run_postconditions_DID_YOU_FORGET_A_RETURN: \ if (___contract_enabled) \ { \ ___op = Contract::Postconditions; \ ___ran.ran = true; \ } \ else \ { \ DEBUG_OK_TO_RETURN_BEGIN(CONTRACT) \ ___run_return: \ return _returnexp; \ DEBUG_OK_TO_RETURN_END(CONTRACT) \ } \ } \ if (0) \ { \ ___run_preconditions: \ ___op = Contract::Preconditions; \ } \ UINT ___testmask = 0; \ #define CONTRACTL_SETUP(_contracttype) \ _contracttype ___contract; \ BOOL ___contract_enabled = Contract::EnforceContract(); \ enum {___disabled = 0}; \ if (!___contract_enabled) \ ___contract.Disable(); \ else \ { \ typedef __YouCannotUseAPostConditionHere __PostConditionOK; \ enum { ___CheckMustBeInside_CONTRACT = 1 }; \ Contract::Operation ___op = Contract::Setup; \ enum {___disabled = 0}; \ if (0) \ { \ ___run_preconditions: \ ___op = Contract::Preconditions; \ } \ if (0) \ { \ /* define for CONTRACT_END even though we can't get here */ \ ___run_return: \ UNREACHABLE(); \ } \ UINT ___testmask = 0; \ #else // #ifndef __FORCE_NORUNTIME_CONTRACTS__ #define CONTRACT_SETUP(_contracttype, _returntype, _returnexp) \ _returntype RETVAL; \ Contract::Returner<_returntype> ___returner(RETVAL); \ Contract::RanPostconditions ___ran(__FUNCTION__); \ Contract::Operation ___op = Contract::Setup; \ DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \ BOOL ___contract_enabled = Contract::EnforceContract(); \ enum {___disabled = 0}; \ { \ enum { ___CheckMustBeInside_CONTRACT = 1 }; \ if (0) \ { \ /* If you see an "unreferenced label" warning with this name, */\ /* Be sure that you have a RETURN at the end of your */ \ /* CONTRACT_VOID function */ \ ___run_postconditions_DID_YOU_FORGET_A_RETURN: \ if (___contract_enabled) \ { \ ___op = Contract::Postconditions; \ ___ran.ran = true; \ } \ else \ { \ DEBUG_OK_TO_RETURN_BEGIN(CONTRACT) \ ___run_return: \ return _returnexp; \ DEBUG_OK_TO_RETURN_END(CONTRACT) \ } \ } \ if (0) \ { \ ___run_preconditions: \ ___op = Contract::Preconditions; \ } \ UINT ___testmask = 0; \ #define CONTRACTL_SETUP(_contracttype) \ BOOL ___contract_enabled = Contract::EnforceContract(); \ enum {___disabled = 0}; \ { \ typedef __YouCannotUseAPostConditionHere __PostConditionOK; \ enum { ___CheckMustBeInside_CONTRACT = 1 }; \ Contract::Operation ___op = Contract::Setup; \ enum {___disabled = 0}; \ if (0) \ { \ ___run_preconditions: \ ___op = Contract::Preconditions; \ } \ if (0) \ { \ /* define for CONTRACT_END even though we can't get here */ \ ___run_return: \ UNREACHABLE(); \ } \ UINT ___testmask = 0; \ #endif // __FORCE_NORUNTIME_CONTRACTS__ #define CUSTOM_CONTRACT(_contracttype, _returntype) \ typedef Contract::PseudoTemplate<_returntype> ___maybetemplate; \ CONTRACT_SETUP(_contracttype, _returntype, RETVAL) #define CUSTOM_CONTRACT_VOID(_contracttype) \ CONTRACT_SETUP(_contracttype, int, ;) #define CUSTOM_CONTRACTL(_contracttype) \ CONTRACTL_SETUP(_contracttype) // Although this thing only needs to run in the Setup phase, we'll let it // run unconditionally. This way, the compiler will see a sequence like this: // // THROWS; GC_TRIGGERS; FORBID_FAULT ==> // // ___testmask |= constant // ___testmask |= constant // ___testmask |= constant // // and be able to fold all these into a single constant at runtime. // #define REQUEST_TEST(thetest, todisable) (___testmask |= (___CheckMustBeInside_CONTRACT, (___disabled ? (todisable) : (thetest)))) #define INJECT_FAULT(_statement) \ do \ { \ STATIC_CONTRACT_FAULT; \ REQUEST_TEST(Contract::FAULT_Inject, Contract::FAULT_Disabled); \ if (0) \ { \ _statement; \ } \ } \ while(0) \ #define FORBID_FAULT do { STATIC_CONTRACT_FORBID_FAULT; REQUEST_TEST(Contract::FAULT_Forbid, Contract::FAULT_Disabled); } while(0) #define THROWS do { STATIC_CONTRACT_THROWS; REQUEST_TEST(Contract::THROWS_Yes, Contract::THROWS_Disabled); } while(0) #define NOTHROW do { STATIC_CONTRACT_NOTHROW; REQUEST_TEST(Contract::THROWS_No, Contract::THROWS_Disabled); } while(0) \ #define ENTRY_POINT STATIC_CONTRACT_ENTRY_POINT #define LOADS_TYPE(maxlevel) do { REQUEST_TEST( ((maxlevel) + 1) << Contract::LOADS_TYPE_Shift, Contract::LOADS_TYPE_Disabled ); } while(0) #define CAN_TAKE_LOCK do { STATIC_CONTRACT_CAN_TAKE_LOCK; REQUEST_TEST(Contract::CAN_TAKE_LOCK_Yes, Contract::CAN_TAKE_LOCK_Disabled); } while(0) #define CANNOT_TAKE_LOCK do { STATIC_CONTRACT_CANNOT_TAKE_LOCK; REQUEST_TEST(Contract::CAN_TAKE_LOCK_No, Contract::CAN_TAKE_LOCK_Disabled); } while(0) #define CANNOT_RETAKE_LOCK do { REQUEST_TEST(Contract::CAN_RETAKE_LOCK_No, Contract::CAN_RETAKE_LOCK_No_Disabled); } while(0) #define DEBUG_ONLY do { STATIC_CONTRACT_DEBUG_ONLY; REQUEST_TEST(Contract::DEBUG_ONLY_Yes, 0); } while (0) #ifndef __DISABLE_PREPOST_CONDITIONS__ #define PRECONDITION_MSG(_expression, _message) \ do \ { \ enum { ___CheckMustBeInside_CONTRACT = 1 }; \ REQUEST_TEST(Contract::PRECONDITION_Used, 0); \ if ((___op&Contract::Preconditions) && !___disabled) \ ASSERT_CHECK(_expression, _message, "Precondition failure"); \ } \ while(0) #define PRECONDITION(_expression) \ PRECONDITION_MSG(_expression, NULL) #define POSTCONDITION_MSG(_expression, _message) \ ++___ran; \ if ((!(0 && __PostConditionOK::safe_to_use_postcondition())) && \ (___op&Contract::Postconditions) && \ !___disabled) \ { \ ASSERT_CHECK(_expression, _message, "Postcondition failure"); \ } #define POSTCONDITION(_expression) \ POSTCONDITION_MSG(_expression, NULL) #define INSTANCE_CHECK \ ___CheckMustBeInside_CONTRACT; \ if ((___op&Contract::Preconditions) && !___disabled) \ ASSERT_CHECK(CheckPointer(this), NULL, "Instance precheck failure"); \ ++___ran; \ if ((___op&Contract::Postconditions) && !___disabled) \ ASSERT_CHECK(CheckPointer(this), NULL, "Instance postcheck failure"); #define INSTANCE_CHECK_NULL \ ___CheckMustBeInside_CONTRACT; \ if ((___op&Contract::Preconditions) && !___disabled) \ ASSERT_CHECK(CheckPointer(this, NULL_OK), NULL, "Instance precheck failure"); \ ++___ran; \ if ((___op&Contract::Postconditions) && !___disabled) \ ASSERT_CHECK(CheckPointer(this, NULL_OK), NULL, "Instance postcheck failure"); #define CONSTRUCTOR_CHECK \ ___CheckMustBeInside_CONTRACT; \ ++___ran; \ if ((___op&Contract::Postconditions) && !___disabled) \ ASSERT_CHECK(CheckPointer(this), NULL, "Instance postcheck failure"); #define DESTRUCTOR_CHECK \ ___CheckMustBeInside_CONTRACT; \ NOTHROW; \ if ((___op&Contract::Preconditions) && !___disabled) \ ASSERT_CHECK(CheckPointer(this), NULL, "Instance precheck failure"); #else // __DISABLE_PREPOST_CONDITIONS__ #define PRECONDITION_MSG(_expression, _message) do { } while(0) #define PRECONDITION(_expression) do { } while(0) #define POSTCONDITION_MSG(_expression, _message) do { } while(0) #define POSTCONDITION(_expression) do { } while(0) #define INSTANCE_CHECK #define INSTANCE_CHECK_NULL #define CONSTRUCTOR_CHECK #define DESTRUCTOR_CHECK #endif // __DISABLE_PREPOST_CONDITIONS__ #define UNCHECKED(thecheck) \ do { \ ANNOTATION_UNCHECKED(thecheck); \ enum {___disabled = 1 }; \ thecheck; \ } while(0) #define DISABLED(thecheck) UNCHECKED(thecheck) #define WRAPPER(thecheck) UNCHECKED(thecheck) // This keyword is redundant but it's handy for reducing the nuisance editing you // have to when repeatedly enabling and disabling contract items while debugging. // You shouldn't check in code that explicitly uses ENABLED. #define ENABLED(_check) _check #ifndef __FORCE_NORUNTIME_CONTRACTS__ #define CONTRACTL_END \ if (___op & Contract::Setup) \ { \ ___contract.DoChecks(___testmask, __FUNCTION__, __FILE__, __LINE__); \ if (___testmask & Contract::PRECONDITION_Used) \ { \ goto ___run_preconditions; \ } \ } \ else if (___op & Contract::Postconditions) \ { \ goto ___run_return; \ } \ ___CheckMustBeInside_CONTRACT; \ } #else #define CONTRACTL_END \ if (___op & Contract::Setup) \ { \ if (___testmask & Contract::PRECONDITION_Used) \ { \ goto ___run_preconditions; \ } \ } \ else if (___op & Contract::Postconditions) \ { \ goto ___run_return; \ } \ ___CheckMustBeInside_CONTRACT; \ } \ #endif // __FORCE_NORUNTIME_CONTRACTS__ #define CONTRACT_END CONTRACTL_END \ DEBUG_ASSURE_NO_RETURN_END(CONTRACT) \ // The final expression in the RETURN macro deserves special explanation (or something.) // The expression is constructed so as to be syntactically ambiguous, depending on whether // __maybetemplate is a template or not. If it is a template, the expression is syntactically // correct as-is. If it is not, the angle brackets are interpreted as // less than & greater than, and the expression is incomplete. This is the point - we can // choose whether we need an expression or not based on the context in which the macro is used. // This allows the same RETURN macro to be used both in value-returning and void-returning // contracts. // // The "__returner ," portion of the expression is used instead of "RETVAL =", since "," // has lower precedence than "=". (Ain't overloaded operators fun.) // // Also note that the < and > operators on the non-template version of __maybetemplate // are overridden to "box" the return value in a special type and pass it // through to the __returner's "," operator. This is so we can detect a case where an // operator with lower precedence than ">" is in the return expression - in such a case we // will get a type error message, which instructs that parens be placed around the return // value expression. #define RETURN_BODY \ if (___returner.GotReturn()) \ goto ___run_postconditions_DID_YOU_FORGET_A_RETURN; \ else \ ___returner, * new ___maybetemplate < 0 > // We have two versions of the RETURN macro. CONTRACT_RETURN is for use inside the CONTRACT // scope where it is OK to return this way, even though the CONTRACT macro itself does not // allow a return. RETURN is for use inside the function body where it might not be OK // to return and we need to ensure that we don't allow a return where one should not happen // #define RETURN \ while (DEBUG_ASSURE_SAFE_TO_RETURN, TRUE) \ RETURN_BODY \ #define RETURN_VOID \ RETURN #define CONTRACT_RETURN \ while (___CheckMustBeInside_CONTRACT, TRUE) \ RETURN_BODY \ #define CONTRACT_RETURN_VOID \ CONTRACT_RETURN \ #if 0 #define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \ { \ _contracttype ___contract; \ STATIC_CONTRACT_LEAF; \ ___contract.DoChecks(Contract::THROWS_No|Contract::GC_NoTrigger|Contract::MODE_Disabled|Contract::FAULT_Disabled); \ /* Should add some assertion mechanism to ensure no other contracts are called */ \ } #else #define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \ { \ STATIC_CONTRACT_LEAF; \ } #endif #define CUSTOM_WRAPPER_NO_CONTRACT(_contracttype) \ { \ /* Should add some assertion mechanism to ensure one other contract is called */ \ STATIC_CONTRACT_WRAPPER; \ } #define CONTRACT_THROWS() \ { \ ::GetClrDebugState()->CheckOkayToThrow(__FUNCTION__, __FILE__, __LINE__); \ } #define CONTRACT_THROWSEX(__func, __file, __line) \ { \ ::GetClrDebugState()->CheckOkayToThrow(__func, __file, __line); \ } #else // ENABLE_CONTRACTS_IMPL #define CUSTOM_CONTRACT(_contracttype, _returntype) if (0) { struct YouCannotUseThisHere { int x; }; // This temporary typedef allows retail use of #define CUSTOM_CONTRACT_VOID(_contracttype) if (0) { struct YouCannotUseThisHere { int x; }; // FORBIDGC_LOADER_USE_ENABLED #define CUSTOM_CONTRACTL(_contracttype) if (0) { struct YouCannotUseThisHere { int x; }; // inside contracts and asserts but nowhere else. #define INJECT_FAULT(_statement) #define FORBID_FAULT #define THROWS #define NOTHROW #define CAN_TAKE_LOCK #define CANNOT_TAKE_LOCK #define CANNOT_RETAKE_LOCK #define LOADS_TYPE(maxlevel) #define ENTRY_POINT #ifdef _DEBUG // This can only appear in a debug function so don't define it non-debug #define DEBUG_ONLY STATIC_CONTRACT_DEBUG_ONLY #else #define DEBUG_ONLY #endif #define PRECONDITION_MSG(_expression, _message) do { } while(0) #define PRECONDITION(_expression) do { } while(0) #define POSTCONDITION_MSG(_expression, _message) do { } while(0) #define POSTCONDITION(_expression) do { } while(0) #define INSTANCE_CHECK #define INSTANCE_CHECK_NULL #define CONSTRUCTOR_CHECK #define DESTRUCTOR_CHECK #define UNCHECKED(thecheck) #define DISABLED(thecheck) #define WRAPPER(thecheck) #define ENABLED(_check) #define CONTRACT_END } #define CONTRACTL_END } #define CUSTOM_LIMITED_METHOD_CONTRACT(_contracttype) \ { \ /* Should add some assertion mechanism to ensure one other contract is called */ \ STATIC_CONTRACT_LEAF; \ } #define CUSTOM_WRAPPER_NO_CONTRACT(_contracttype) \ { \ /* Should add some assertion mechanism to ensure one other contract is called */ \ STATIC_CONTRACT_WRAPPER; \ } #define RETURN return #define RETURN_VOID RETURN #define CONTRACT_THROWS() #define CONTRACT_THROWSEX(__func, __file, __line) #endif // ENABLE_CONTRACTS_IMPL #define CONTRACT(_returntype) CUSTOM_CONTRACT(Contract, _returntype) #define CONTRACT_VOID CUSTOM_CONTRACT_VOID(Contract) #define CONTRACTL CUSTOM_CONTRACTL(Contract) // See description near the top of the file #define LIMITED_METHOD_CONTRACT CUSTOM_LIMITED_METHOD_CONTRACT(Contract) #define WRAPPER_NO_CONTRACT CUSTOM_WRAPPER_NO_CONTRACT(Contract) // GC_NOTRIGGER allowed but not currently enforced at runtime #define GC_NOTRIGGER STATIC_CONTRACT_GC_NOTRIGGER #define GC_TRIGGERS static_assert(false, "TriggersGC not supported in utilcode contracts") #ifdef ENABLE_CONTRACTS_IMPL template class ContractViolationHolder { public: ContractViolationHolder() { m_pviolationmask = NULL; m_oldviolationmask = 0; } DEBUG_NOINLINE void Enter(); DEBUG_NOINLINE void Leave() { SCAN_SCOPE_END; LeaveInternal(); }; protected: // We require that violationMask is passed as a parameter here to hopefully defeat the // compiler's desire to fold all the Enter and Ctor implementations together. FORCEINLINE void EnterInternal(UINT_PTR violationMask) { _ASSERTE(0 == (violationMask & ~(ThrowsViolation | GCViolation | ModeViolation | FaultViolation | FaultNotFatal | HostViolation | TakesLockViolation | LoadsTypeViolation)) || violationMask == AllViolation); m_pviolationmask = GetClrDebugState()->ViolationMaskPtr(); m_oldviolationmask = *m_pviolationmask; *m_pviolationmask = (m_oldviolationmask | violationMask); }; FORCEINLINE void LeaveInternal() { // This can be used in places where our debug state has been destroyed, so check for it first. if (CheckClrDebugState()) { _ASSERTE(m_pviolationmask != NULL); *m_pviolationmask = m_oldviolationmask; } }; UINT_PTR *m_pviolationmask; UINT_PTR m_oldviolationmask; }; template class AutoCleanupContractViolationHolder : ContractViolationHolder { public: DEBUG_NOINLINE AutoCleanupContractViolationHolder(BOOL fEnterViolation = TRUE); DEBUG_NOINLINE ~AutoCleanupContractViolationHolder() { SCAN_SCOPE_END; this->LeaveInternal(); }; }; #endif // ENABLE_CONTRACTS_IMPL #ifdef ENABLE_CONTRACTS_IMPL #define BEGIN_CONTRACT_VIOLATION(violationmask) \ { \ ContractViolationHolder __violationHolder_onlyOneAllowedPerScope; \ __violationHolder_onlyOneAllowedPerScope.Enter(); \ DEBUG_ASSURE_NO_RETURN_BEGIN(CONTRACT) \ // Use this to jump out prematurely from a violation. Used for EH // when the function might not return #define RESET_CONTRACT_VIOLATION() \ __violationHolder_onlyOneAllowedPerScope.Leave(); \ #define END_CONTRACT_VIOLATION \ DEBUG_ASSURE_NO_RETURN_END(CONTRACT) \ __violationHolder_onlyOneAllowedPerScope.Leave(); \ } \ // See description near the top of the file #define CONTRACT_VIOLATION(violationMask) \ AutoCleanupContractViolationHolder __violationHolder_onlyOneAllowedPerScope; // Reasons for having the violation. Use one of these values as an additional parameter to // E.g. PERMANENT_CONTRACT_VIOLATION(ThrowsViolation, ReasonContractInfrastructure) // New values and explanations can be added when needed. enum PermanentContractViolationReason { ReasonContractInfrastructure, // This violation is there for contract test or infrastructure purposes. ReasonDebugOnly, // Code path doesn't occur on retail builds ReasonNonShippingCode, // Code runs in undocumented non-shipping feature ReasonIBC, // Code runs in IBC scenarios only and the violation is safe. ReasonNGEN, // Code runs in NGEN scenarios only and the violation is safe. ReasonProfilerCallout, // Profiler implementers are guaranteed not to throw. ReasonUnsupportedForSQLF1Profiling, // This code path violates HOST_NOCALLS, but that's ok b/c SQL will never // invoke it, and thus SQL/F1 profiling (the primary reason to enforce // HOST_NOCALLS) is not in danger. ReasonRuntimeReentrancy, // e.g. SafeQueryInterface ReasonShutdownOnly, // Code path only runs as part of Shutdown and the violation is safe. ReasonSOTolerance, // We would like to redesign SO contracts anyways ReasonStartupOnly, // Code path only runs as part of Startup and the violation is safe. ReasonWorkaroundForScanBug, // Violation is needed because of a bug in SCAN ReasonProfilerAsyncCannotRetakeLock, // Profiler may call this from redirected thread, causing a CANNOT_TAKE_LOCK // violation, but the scope is still protected with CANNOT_RETAKE_LOCK ReasonILStubWillNotThrow, // Specially-crafted reverse COM IL stubs will not throw }; // See the discussion near the top of the file on the use of PERMANENT_CONTRACT_VIOLATION // The reasonEnum is currently only used for documentation and searchability. Here // we have the compiler check for a typo. #define PERMANENT_CONTRACT_VIOLATION(violationMask, reasonEnum) \ if (0) \ PermanentContractViolationReason reason = reasonEnum; \ CONTRACT_VIOLATION(violationMask) #define CONDITIONAL_CONTRACT_VIOLATION(violationMask, condition) \ AutoCleanupContractViolationHolder __violationHolder_onlyOneAllowedPerScope((condition)); #else #define BEGIN_CONTRACT_VIOLATION(violationmask) #define RESET_CONTRACT_VIOLATION() #define END_CONTRACT_VIOLATION #define CONTRACT_VIOLATION(violationmask) #define CONDITIONAL_CONTRACT_VIOLATION(violationMask, condition) #define PERMANENT_CONTRACT_VIOLATION(violationMask, reasonEnum) #endif #ifdef ENABLE_CONTRACTS_IMPL // Holder for setting up a faultforbid region class FaultForbidHolder { public: DEBUG_NOINLINE FaultForbidHolder(BOOL fConditional, BOOL fAlloc, const char *szFunction, const char *szFile, int lineNum) { SCAN_SCOPE_BEGIN; STATIC_CONTRACT_FORBID_FAULT; m_fConditional = fConditional; if (m_fConditional) { m_pClrDebugState = GetClrDebugState(fAlloc); // // If we fail to get a debug state, then we must not be allocating and // we simply no-op this holder. // if (m_pClrDebugState == NULL) { _ASSERTE(!fAlloc); m_fConditional = FALSE; return; } m_oldClrDebugState = *m_pClrDebugState; m_pClrDebugState->ViolationMaskReset( FaultViolation|FaultNotFatal ); m_pClrDebugState->SetFaultForbid(); m_ContractStackRecord.m_szFunction = szFunction; m_ContractStackRecord.m_szFile = szFile; m_ContractStackRecord.m_lineNum = lineNum; m_ContractStackRecord.m_testmask = (Contract::ALL_Disabled & ~((UINT)(Contract::FAULT_Mask))) | Contract::FAULT_Forbid; m_ContractStackRecord.m_construct = "FAULT_FORBID"; m_pClrDebugState->LinkContractStackTrace( &m_ContractStackRecord ); } } DEBUG_NOINLINE ~FaultForbidHolder() { SCAN_SCOPE_END; if (m_fConditional) { *m_pClrDebugState = m_oldClrDebugState; } } private: ClrDebugState *m_pClrDebugState; ClrDebugState m_oldClrDebugState; BOOL m_fConditional; ContractStackRecord m_ContractStackRecord; }; #endif // ENABLE_CONTRACTS_IMPL #ifdef ENABLE_CONTRACTS_IMPL #define FAULT_FORBID() FaultForbidHolder _ffh(TRUE, TRUE, __FUNCTION__, __FILE__, __LINE__); #define FAULT_FORBID_NO_ALLOC() FaultForbidHolder _ffh(TRUE, FALSE, __FUNCTION__, __FILE__, __LINE__); #define MAYBE_FAULT_FORBID(cond) FaultForbidHolder _ffh(cond, TRUE, __FUNCTION__, __FILE__, __LINE__); #define MAYBE_FAULT_FORBID_NO_ALLOC(cond) FaultForbidHolder _ffh(cond, FALSE, __FUNCTION__, __FILE__, __LINE__); #else // ENABLE_CONTRACTS_IMPL #define FAULT_FORBID() ; #define FAULT_FORBID_NO_ALLOC() ; #define MAYBE_FAULT_FORBID(cond) ; #define MAYBE_FAULT_FORBID_NO_ALLOC(cond) ; #endif // ENABLE_CONTRACTS_IMPL #ifdef ENABLE_CONTRACTS_IMPL inline BOOL AreFaultsForbiddenHelper() { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; ClrDebugState *pClrDebugState = CheckClrDebugState(); if (!pClrDebugState) { // By default, faults are not forbidden. Not the most desirable default // but we'd never get this debug infrastructure bootstrapped otherwise. return FALSE; } else { return pClrDebugState->IsFaultForbid() && (!(pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState))); } } #define ARE_FAULTS_FORBIDDEN() AreFaultsForbiddenHelper() #else // If you got an error about ARE_FAULTS_FORBIDDEN being undefined, it's because you tried // to use this predicate in a free build outside of a CONTRACT or ASSERT. // #define ARE_FAULTS_FORBIDDEN() (sizeof(YouCannotUseThisHere) != 0) #endif // This allows a fault-forbid region to invoke a non-mandatory allocation, such as for the // purpose of growing a lookaside cache (if the allocation fails, the code can abandon the // cache growing operation without negative effect.) // // Although it's implemented using CONTRACT_VIOLATION(), it's not a bug to have this in the code. // // It *is* a bug to use this to hide a situation where an OOM is genuinely fatal but not handled. #define FAULT_NOT_FATAL() CONTRACT_VIOLATION(FaultNotFatal) #ifdef ENABLE_CONTRACTS_IMPL //------------------------------------------------------------------------------------ // Underlying class support for TRIGGERS_TYPE_LOAD and OVERRIDE_TYPE_LOAD_LEVEL_LIMIT. // Don't reference this class directly. Use the macros. //------------------------------------------------------------------------------------ class LoadsTypeHolder { public: LoadsTypeHolder(BOOL fConditional, UINT newLevel, BOOL fEnforceLevelChangeDirection, const char *szFunction, const char *szFile, int lineNum ); ~LoadsTypeHolder(); private: ClrDebugState *m_pClrDebugState; ClrDebugState m_oldClrDebugState; BOOL m_fConditional; ContractStackRecord m_contractStackRecord; }; #endif // ENABLE_CONTRACTS_IMPL //------------------------------------------------------------------------------------ // TRIGGERS_TYPE_LOAD(newLevel) // Works just LOADS_TYPE in contracts but lets you protect individual scopes // // OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) // Sets a new limit just like TRIGGERS_TYPE_LOAD but does not restrict you // to decreasing the limit. Only the loader should use this and only when it // can prove structurally that no recursion will occur as a result. //------------------------------------------------------------------------------------ #ifdef ENABLE_CONTRACTS_IMPL #define TRIGGERS_TYPE_LOAD(newLevel) LoadsTypeHolder _lth(TRUE, newLevel, TRUE, __FUNCTION__, __FILE__, __LINE__); #define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable) LoadsTypeHolder _lth(fEnable, newLevel, TRUE, __FUNCTION__, __FILE__, __LINE__); #define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) LoadsTypeHolder _lth(TRUE, newLevel, FALSE, __FUNCTION__, __FILE__, __LINE__); #define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) LoadsTypeHolder _lth(fEnable, newLevel, FALSE, __FUNCTION__, __FILE__, __LINE__); #else // ENABLE_CONTRACTS_IMPL #define TRIGGERS_TYPE_LOAD(newLevel) #define MAYBE_TRIGGERS_TYPE_LOAD(newLevel, fEnable) #define OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel) #define MAYBE_OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(newLevel, fEnable) #endif // ENABLE_CONTRACTS_IMPL #ifdef ENABLE_CONTRACTS_IMPL // This sets up a marker that says its okay to throw on this thread. This is not a public macro, and should only be // used from within the implementation of various try/catch macros. class ClrTryMarkerHolder { public: DEBUG_NOINLINE ClrTryMarkerHolder() { SCAN_SCOPE_BEGIN; STATIC_CONTRACT_THROWS; m_pClrDebugState = GetClrDebugState(); m_oldOkayToThrowValue = m_pClrDebugState->IsOkToThrow(); m_pClrDebugState->SetOkToThrow(); } DEBUG_NOINLINE ~ClrTryMarkerHolder() { SCAN_SCOPE_END; m_pClrDebugState->SetOkToThrow( m_oldOkayToThrowValue ); } private: BOOL m_oldOkayToThrowValue; ClrDebugState *m_pClrDebugState; }; #define CLR_TRY_MARKER() ClrTryMarkerHolder ___tryMarkerHolder; #else // ENABLE_CONTRACTS_IMPL #define CLR_TRY_MARKER() #endif #ifdef ENABLE_CONTRACTS_IMPL // Note: This routine will create a ClrDebugState if called for the first time. // It cannot return NULL (see comment for InitClrDebugState). inline ClrDebugState *GetClrDebugState(BOOL fAlloc) { STATIC_CONTRACT_LIMITED_METHOD; ClrDebugState *pState = CheckClrDebugState(); if (pState) { return pState; } if (fAlloc) { return CLRInitDebugState(); } return NULL; } #endif // ENABLE_CONTRACTS_IMPL #ifdef ENABLE_CONTRACTS_IMPL class HostNoCallHolder { public: DEBUG_NOINLINE HostNoCallHolder() { SCAN_SCOPE_BEGIN; STATIC_CONTRACT_HOST_NOCALLS; m_clrDebugState = GetClrDebugState(); m_previousState = m_clrDebugState->SetHostCaller(FALSE); } DEBUG_NOINLINE ~HostNoCallHolder() { SCAN_SCOPE_END; m_clrDebugState->SetHostCaller(m_previousState); } private: BOOL m_previousState; ClrDebugState* m_clrDebugState; }; #define BEGIN_HOST_NOCALL_CODE \ { \ HostNoCallHolder __hostNoCallHolder; \ CantAllocHolder __cantAlloc; #define END_HOST_NOCALL_CODE \ } #else // ENABLE_CONTRACTS_IMPL #define BEGIN_HOST_NOCALL_CODE \ { \ CantAllocHolder __cantAlloc; \ #define END_HOST_NOCALL_CODE \ } #endif #if defined(ENABLE_CONTRACTS_IMPL) // Macros to indicate we're taking or releasing locks // Most general macros, not used directly #define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock) \ ::GetClrDebugState()->LockTaken((dbgStateLockType), (cEntrances), (void*) (pvLock), __FUNCTION__, __FILE__, __LINE__) #define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock) \ ::GetClrDebugState()->LockReleased((dbgStateLockType), (cExits), (void*) (pvLock)) // Use these only if you need to force multiple entrances or exits in a single // line (e.g., to restore the lock to a previous state). CRWLock in vm\rwlock.cpp does this #define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) \ LOCK_TAKEN_MULTIPLE(kDbgStateLockType_EE, cEntrances, pvLock) #define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) \ LOCK_RELEASED_MULTIPLE(kDbgStateLockType_EE, cExits, pvLock) #define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) \ LOCK_TAKEN_MULTIPLE(kDbgStateLockType_HostBreakableCrst, cEntrances, pvLock) #define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock) \ LOCK_RELEASED_MULTIPLE(kDbgStateLockType_HostBreakableCrst, cExits, pvLock) #define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) \ LOCK_TAKEN_MULTIPLE(kDbgStateLockType_User, cEntrances, pvLock) #define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) \ LOCK_RELEASED_MULTIPLE(kDbgStateLockType_User, cExits, pvLock) // These are most typically used #define EE_LOCK_TAKEN(pvLock) \ LOCK_TAKEN_MULTIPLE(kDbgStateLockType_EE, 1, pvLock) #define EE_LOCK_RELEASED(pvLock) \ LOCK_RELEASED_MULTIPLE(kDbgStateLockType_EE, 1, pvLock) #define HOST_BREAKABLE_CRST_TAKEN(pvLock) \ LOCK_TAKEN_MULTIPLE(kDbgStateLockType_HostBreakableCrst, 1, pvLock) #define HOST_BREAKABLE_CRST_RELEASED(pvLock) \ LOCK_RELEASED_MULTIPLE(kDbgStateLockType_HostBreakableCrst, 1, pvLock) #define USER_LOCK_TAKEN(pvLock) \ LOCK_TAKEN_MULTIPLE(kDbgStateLockType_User, 1, pvLock) #define USER_LOCK_RELEASED(pvLock) \ LOCK_RELEASED_MULTIPLE(kDbgStateLockType_User, 1, pvLock) #else // defined(ENABLE_CONTRACTS_IMPL) #define LOCK_TAKEN_MULTIPLE(dbgStateLockType, cEntrances, pvLock) #define LOCK_RELEASED_MULTIPLE(dbgStateLockType, cExits, pvLock) #define EE_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) #define EE_LOCK_RELEASED_MULTIPLE(cExits, pvLock) #define HOST_BREAKABLE_CRST_TAKEN_MULTIPLE(cEntrances, pvLock) #define HOST_BREAKABLE_CRST_RELEASED_MULTIPLE(cExits, pvLock) #define USER_LOCK_TAKEN_MULTIPLE(cEntrances, pvLock) #define USER_LOCK_RELEASED_MULTIPLE(cExits, pvLock) #define EE_LOCK_TAKEN(pvLock) #define EE_LOCK_RELEASED(pvLock) #define HOST_BREAKABLE_CRST_TAKEN(pvLock) #define HOST_BREAKABLE_CRST_RELEASED(pvLock) #define USER_LOCK_TAKEN(pvLock) #define USER_LOCK_RELEASED(pvLock) #endif // defined(ENABLE_CONTRACTS_IMPL) #if defined(ENABLE_CONTRACTS_IMPL) // Abbreviation for an assert that is only considered if there is a valid // ClrDebugState available. Useful if you want to assert based on the value // of GetDbgStateLockCount(), where a return of 0 (the default if there is no // valid ClrDebugState available) would cause your assert to fire. The variable // __pClrDebugState is set to the current ClrDebugState, and may be used within // your assert expression #define ASSERT_UNLESS_NO_DEBUG_STATE(e) \ { \ ClrDebugState * __pClrDebugState = GetClrDebugState(); \ _ASSERTE(((__pClrDebugState->ViolationMask() & BadDebugState) != 0) || (e)); \ } #else // defined(ENABLE_CONTRACTS_IMPL) #define ASSERT_UNLESS_NO_DEBUG_STATE(e) #endif // defined(ENABLE_CONTRACTS_IMPL) //----------------------------------------------------------------------------- // Debug support to ensure that nobody calls New on the helper thread. // This is for interop debugging. // They should be using the InteropSafe heap. // Having this in the meantime allows us to // assert that the helper thread never calls new, and maintain a finite list of // exceptions (bugs). // Eventually, all those bugs should be fixed this holder can be completely removed. // // It is also the case that we disallow allocations when any thread is OS suspended // This happens for a short time when we are suspending the EE. We suppress both // of these. // // @todo- ideally this would be rolled into the ContractViolation. // also, we'd have contract bit for whether APIs can be called on the helper thread. // @todo - if we really wanted to be strict, we should make this per-thread. //----------------------------------------------------------------------------- #ifdef ENABLE_CONTRACTS_IMPL extern Volatile g_DbgSuppressAllocationAsserts; #define SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE CounterHolder _AllowNewOnHelperHolder(&g_DbgSuppressAllocationAsserts); #else // Nothing in retail since this holder just disabled an assert. #define SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE #endif //----------------------------------------------------------------------------- // Support for contracts in DAC builds // // At the moment, most of the contract system is disabled in DAC builds. // We do however want some simple static contracts in order to support static // analysis tools that run on mscordacwks.dll like DacCop. // Note that we want these static contracts in both DEBUG and retail builds. // We also already get simple static contracts like WRAPPER and LEAF. // //----------------------------------------------------------------------------- #if defined(DACCESS_COMPILE) // SUPPORTS_DAC is an annotation that says the function is designed to be used in DAC builds. // This enables full DacCop analysis on the function, including verifying that all functions that are // called also support DAC. #define SUPPORTS_DAC do { STATIC_CONTRACT_SUPPORTS_DAC; } while(0) // Normally a function can be annotated just with WRAPPER_NO_CONTRACT, which (in addition to the normal // contract meaning) indicates to DacCop that the function should be considered to support DAC when // it is called from a supports-dac function. This is to avoid having to add a DAC-specific contract // to all the trivial one-line wrapper functions we have. // However, we occasionally want these semantics even for functions which are not appropriate to label // as WRAPPER_NO_CONTRACT. For example, a template function may support DAC for certain template arguments, // but not others (due to the functions it calls). We want to ensure that when such a function is called // in a DAC code path, analysis is enabled on that particular instantiation including checking all of the // call targets specific to this template instantiation. But we don't want to require that the call targets // for ALL instantiations support dac, since we may not even be using them in DAC code paths. Ideally we'd // remove any such code from the DAC build, but this will take time. #define SUPPORTS_DAC_WRAPPER do { STATIC_CONTRACT_WRAPPER; } while(0) // SUPPORTS_DAC_HOST_ONLY indicates that a function is allowed to be called in DAC builds, but rather // than being a normal DAC function which operates on marshalled data, it is a host-only utility function // that knows nothing about DAC and operates solely on the host. For example, DbgAssertDialog is a utility // function for popping assert dialogs - there is nothing DAC-specific about this. Ideally such utility // functions would be confined to their own library which had no access to DAC functionality, and which // is not analyzed by DacCop. At the moment splitting utilcode into two variations like this is too // painful, but we hope to do it in the future (primarily to support functions which can be used in either // DAC or host-only mode). // WARNING: This contract disables DacCop analysis on the function and any functions it calls, so it // should be used very carefully. #define SUPPORTS_DAC_HOST_ONLY do { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; } while(0) #else #define SUPPORTS_DAC #define SUPPORTS_DAC_HOST_ONLY #define SUPPORTS_DAC_WRAPPER #endif // DACCESS_COMPILE // LIMITED_METHOD_DAC_CONTRACT is a shortcut for LIMITED_METHOD_CONTRACT and SUPPORTS_DAC. Usefull for one-line inline functions. #define LIMITED_METHOD_DAC_CONTRACT LIMITED_METHOD_CONTRACT; SUPPORTS_DAC // // The default contract is the recommended contract for ordinary code. // The ordinary code can throw or trigger GC any time, does not operate // on raw object refs, etc. // #define STANDARD_VM_CHECK \ THROWS; #define STANDARD_VM_CONTRACT \ CONTRACTL \ { \ STANDARD_VM_CHECK; \ } \ CONTRACTL_END; \ #define STATIC_STANDARD_VM_CONTRACT \ STATIC_CONTRACT_THROWS; \ STATIC_CONTRACT_GC_TRIGGERS; \ STATIC_CONTRACT_MODE_PREEMPTIVE; #define AFTER_CONTRACTS #include "volatile.h" #endif // CONTRACT_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/contract.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // Contract.inl // // ! I am the owner for issues in the contract *infrastructure*, not for every // ! CONTRACT_VIOLATION dialog that comes up. If you interrupt my work for a routine // ! CONTRACT_VIOLATION, you will become the new owner of this file. // --------------------------------------------------------------------------- #ifndef CONTRACT_INL_ #define CONTRACT_INL_ #include "contract.h" #include #ifdef ENABLE_CONTRACTS_IMPL inline void BaseContract::DoChecks(UINT testmask, _In_z_ const char *szFunction, _In_z_ const char *szFile, int lineNum) { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; // Cache the pointer to our ClrDebugState if it's not already cached. // Derived types could set up this ptr before calling BaseContract::DoChecks if they have access to the Thread ptr if (m_pClrDebugState == NULL) { m_pClrDebugState = GetClrDebugState(); } // Save the incoming contents for restoration in the destructor m_IncomingClrDebugState = *m_pClrDebugState; m_testmask = testmask; // Save the testmask for destructor // Setup the new stack record. m_contractStackRecord.m_szFunction = szFunction; m_contractStackRecord.m_szFile = szFile; m_contractStackRecord.m_lineNum = lineNum; m_contractStackRecord.m_testmask = testmask; m_contractStackRecord.m_construct = "CONTRACT"; // Link the new ContractStackRecord into the chain for this thread. m_pClrDebugState->LinkContractStackTrace( &m_contractStackRecord ); if (testmask & DEBUG_ONLY_Yes) { m_pClrDebugState->SetDebugOnly(); } switch (testmask & FAULT_Mask) { case FAULT_Forbid: m_pClrDebugState->ViolationMaskReset( FaultViolation|FaultNotFatal ); m_pClrDebugState->SetFaultForbid(); break; case FAULT_Inject: if (m_pClrDebugState->IsFaultForbid() && !(m_pClrDebugState->ViolationMask() & (FaultViolation|FaultNotFatal|BadDebugState))) { CONTRACT_ASSERT("INJECT_FAULT called in a FAULTFORBID region.", BaseContract::FAULT_Forbid, BaseContract::FAULT_Mask, m_contractStackRecord.m_szFunction, m_contractStackRecord.m_szFile, m_contractStackRecord.m_lineNum); } break; case FAULT_Disabled: // Nothing break; default: UNREACHABLE(); } switch (testmask & THROWS_Mask) { case THROWS_Yes: m_pClrDebugState->CheckOkayToThrow(m_contractStackRecord.m_szFunction, m_contractStackRecord.m_szFile, m_contractStackRecord.m_lineNum); break; case THROWS_No: m_pClrDebugState->ViolationMaskReset( ThrowsViolation ); m_pClrDebugState->ResetOkToThrow(); break; case THROWS_Disabled: // Nothing break; default: UNREACHABLE(); } // LOADS_TYPE check switch (testmask & LOADS_TYPE_Mask) { case LOADS_TYPE_Disabled: // Nothing break; default: { UINT newTypeLoadLevel = ((testmask & LOADS_TYPE_Mask) >> LOADS_TYPE_Shift) - 1; if (newTypeLoadLevel > m_pClrDebugState->GetMaxLoadTypeLevel()) { if (!((LoadsTypeViolation|BadDebugState) & m_pClrDebugState->ViolationMask())) { CONTRACT_ASSERT("A function tried to load a type past the current level limit.", (m_pClrDebugState->GetMaxLoadTypeLevel() + 1) << LOADS_TYPE_Shift, Contract::LOADS_TYPE_Mask, m_contractStackRecord.m_szFunction, m_contractStackRecord.m_szFile, m_contractStackRecord.m_lineNum ); } } m_pClrDebugState->SetMaxLoadTypeLevel(newTypeLoadLevel); m_pClrDebugState->ViolationMaskReset(LoadsTypeViolation); } break; } if (testmask & CAN_RETAKE_LOCK_No) { m_pClrDebugState->OnEnterCannotRetakeLockFunction(); m_pClrDebugState->ResetOkToRetakeLock(); } switch (testmask & CAN_TAKE_LOCK_Mask) { case CAN_TAKE_LOCK_Yes: m_pClrDebugState->CheckOkayToLock(m_contractStackRecord.m_szFunction, m_contractStackRecord.m_szFile, m_contractStackRecord.m_lineNum); break; case CAN_TAKE_LOCK_No: m_pClrDebugState->ViolationMaskReset(TakesLockViolation); m_pClrDebugState->ResetOkToLock(); break; case CAN_TAKE_LOCK_Disabled: // Nothing break; default: UNREACHABLE(); } } FORCEINLINE BOOL BaseContract::CheckFaultInjection() { // ??? use m_tag to see if we should trigger an injection return FALSE; } inline BOOL ClrDebugState::CheckOkayToThrowNoAssert() { if (!IsOkToThrow() && !(m_violationmask & (ThrowsViolation|BadDebugState))) { return FALSE; } return TRUE; } inline void ClrDebugState::CheckOkayToThrow(_In_z_ const char *szFunction, _In_z_ const char *szFile, int lineNum) { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if (!CheckOkayToThrowNoAssert()) { CONTRACT_ASSERT("THROWS called in a NOTHROW region.", BaseContract::THROWS_No, BaseContract::THROWS_Mask, szFunction, szFile, lineNum); } } inline BOOL ClrDebugState::CheckOkayToLockNoAssert() { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if (!IsOkToLock() && !(m_violationmask & (TakesLockViolation|BadDebugState))) { return FALSE; } return TRUE; } inline void ClrDebugState::CheckOkayToLock(_In_z_ const char *szFunction, _In_z_ const char *szFile, int lineNum) { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if (!CheckOkayToLockNoAssert()) { CONTRACT_ASSERT("CAN_TAKE_LOCK called in a CANNOT_TAKE_LOCK region.", BaseContract::CAN_TAKE_LOCK_No, BaseContract::CAN_TAKE_LOCK_Mask, szFunction, szFile, lineNum); } } inline void ClrDebugState::LockTaken(DbgStateLockType dbgStateLockType, UINT cTakes, void * pvLock, _In_z_ const char * szFunction, _In_z_ const char * szFile, int lineNum) { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if ((m_violationmask & BadDebugState) != 0) { return; } // Assert if we're taking a lock in a CANNOT_TAKE_LOCK scope. Even if this asserts, we'll // continue to the following lines to track the lock CheckOkayToLock(szFunction, szFile, lineNum); _ASSERTE(GetDbgStateLockData() != NULL); if (!IsOkToRetakeLock()) { if (m_LockState.IsLockRetaken(pvLock)) { CONTRACT_ASSERT("You cannot take a lock which is already being held in a CANNOT_RETAKE_LOCK scope.", BaseContract::CAN_RETAKE_LOCK_No, BaseContract::CAN_RETAKE_LOCK_No, szFunction, szFile, lineNum); } } GetDbgStateLockData()->LockTaken(dbgStateLockType, cTakes, pvLock, szFunction, szFile, lineNum); } inline void ClrDebugState::LockReleased(DbgStateLockType dbgStateLockType, UINT cReleases, void * pvLock) { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if ((m_violationmask & BadDebugState) != 0) { return; } _ASSERTE(GetDbgStateLockData() != NULL); if (!IsOkToRetakeLock()) { // It is very suspicious to release any locks being hold at the time this function was // called in a CANNOT_RETAKE_LOCK scope _ASSERTE(m_LockState.IsSafeToRelease(cReleases)); } GetDbgStateLockData()->LockReleased(dbgStateLockType, cReleases, pvLock); } inline UINT ClrDebugState::GetLockCount(DbgStateLockType dbgStateLockType) { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if ((m_violationmask & BadDebugState) != 0) { return 0; } _ASSERTE(GetDbgStateLockData() != NULL); return GetDbgStateLockData()->GetLockCount(dbgStateLockType); } inline UINT ClrDebugState::GetCombinedLockCount() { STATIC_CONTRACT_DEBUG_ONLY; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; if ((m_violationmask & BadDebugState) != 0) { return 0; } _ASSERTE(GetDbgStateLockData() != NULL); return GetDbgStateLockData()->GetCombinedLockCount(); } inline void DbgStateLockData::LockTaken(DbgStateLockType dbgStateLockType, UINT cTakes, // # times we're taking this lock (usually 1) void * pvLock, _In_z_ const char * szFunction, _In_z_ const char * szFile, int lineNum) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; // Technically the lock's already been taken before we're called, but it's // handy to have this contract here at the leaf end of the call chain, as it // ensures SCAN will enforce that no use of the LOCK_TAKEN macros occurs // in a CANNOT_TAKE_LOCK scope (as LOCK_TAKEN macros just call this function). STATIC_CONTRACT_CAN_TAKE_LOCK; // Valid enum? _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); UINT cCombinedLocks = GetCombinedLockCount(); // Are we exceeding the threshold for what we can store in m_rgTakenLockInfos? // If so, assert a warning, but we'll deal with it. if ((cCombinedLocks <= ARRAY_SIZE(m_rgTakenLockInfos)) && (cCombinedLocks + cTakes > ARRAY_SIZE(m_rgTakenLockInfos))) { // Actually, for now we are NOT asserting until I can dedicate more time // to this. Some class loader code paths legally hold many simultaneous // locks (>10). Need to do further analysis on reasonable value to set // for kMaxAllowedSimultaneousLocks. Since lock order checking is turned // off for the moment anyway, exceeding kMaxAllowedSimultaneousLocks // has no consequences for now anyway. } m_rgcLocksTaken[dbgStateLockType] += cTakes; // Remember as many of these new entrances in m_rgTakenLockInfos as we can for (UINT i = cCombinedLocks; i < min (ARRAY_SIZE(m_rgTakenLockInfos), cCombinedLocks + cTakes); i++) { m_rgTakenLockInfos[i].m_pvLock = pvLock; m_rgTakenLockInfos[i].m_szFile = szFile; m_rgTakenLockInfos[i].m_lineNum = lineNum; } } inline void DbgStateLockData::LockReleased(DbgStateLockType dbgStateLockType, UINT cReleases, void * pvLock) { // Valid enum? _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); if (cReleases > m_rgcLocksTaken[dbgStateLockType]) { _ASSERTE(!"Releasing lock(s) that were never taken"); cReleases = m_rgcLocksTaken[dbgStateLockType]; } UINT cCombinedLocks = GetCombinedLockCount(); // If lock count is within range of our m_rgTakenLockInfos buffer size, then // make sure we're releasing locks in reverse order of how we took them for (UINT i = cCombinedLocks - cReleases; i < min (ARRAY_SIZE(m_rgTakenLockInfos), cCombinedLocks); i++) { if (m_rgTakenLockInfos[i].m_pvLock != pvLock) { // Ok, I lied. We're not really checking that we're releasing locks in reverse // order, because sometimes we legally release them out of order. (The loader // does this intentionally in a few places.) We should consider whether those // places can be changed, or whether we can add some kind of macro to declare // that we're releasing out of order, and that it's ok & intentional. At that // point, we can place a nice ASSERTE right here. Until then, do nothing. } // We may be clearing out the wrong entry in m_rgTakenLockInfos here, if the locks // were released out of order. However, it will eventually correct itself once all // the out-of-order locks have been released. And our count // (i.e., m_rgcLocksTaken[dbgStateLockType]) will always be accurate memset(&(m_rgTakenLockInfos[i]), 0, sizeof(m_rgTakenLockInfos[i])); } m_rgcLocksTaken[dbgStateLockType] -= cReleases; } inline void DbgStateLockData::SetStartingValues() { memset(this, 0, sizeof(*this)); } inline UINT DbgStateLockData::GetLockCount(DbgStateLockType dbgStateLockType) { _ASSERTE(UINT(dbgStateLockType) < kDbgStateLockType_Count); return m_rgcLocksTaken[dbgStateLockType]; } inline UINT DbgStateLockData::GetCombinedLockCount() { // If this fires, the set of lock types must have changed. You'll need to // fix the sum below to include all lock types _ASSERTE(kDbgStateLockType_Count == 3); return m_rgcLocksTaken[0] + m_rgcLocksTaken[1] + m_rgcLocksTaken[2]; } inline void DbgStateLockState::SetStartingValues() { m_cLocksEnteringCannotRetakeLock = 0; m_pLockData = NULL; // Will get filled in by CLRInitDebugState() } // We set a marker to record the number of locks that have been taken when // CANNOT_RETAKE_LOCK contract is constructed. inline void DbgStateLockState::OnEnterCannotRetakeLockFunction() { m_cLocksEnteringCannotRetakeLock = m_pLockData->GetCombinedLockCount(); } inline BOOL DbgStateLockState::IsLockRetaken(void * pvLock) { // m_cLocksEnteringCannotRetakeLock must be in valid range _ASSERTE(m_cLocksEnteringCannotRetakeLock <= m_pLockData->GetCombinedLockCount()); // m_cLocksEnteringCannotRetakeLock records the number of locks that were taken // when CANNOT_RETAKE_LOCK contract was constructed. for (UINT i = 0; i < min(ARRAY_SIZE(m_pLockData->m_rgTakenLockInfos), m_cLocksEnteringCannotRetakeLock); ++i) { if (m_pLockData->m_rgTakenLockInfos[i].m_pvLock == pvLock) { return TRUE; } } return FALSE; } inline BOOL DbgStateLockState::IsSafeToRelease(UINT cReleases) { return m_cLocksEnteringCannotRetakeLock <= (m_pLockData->GetCombinedLockCount() - cReleases); } inline void DbgStateLockState::SetDbgStateLockData(DbgStateLockData * pDbgStateLockData) { m_pLockData = pDbgStateLockData; } inline DbgStateLockData * DbgStateLockState::GetDbgStateLockData() { return m_pLockData; } inline void CONTRACT_ASSERT(const char *szElaboration, UINT whichTest, UINT whichTestMask, const char *szFunction, const char *szFile, int lineNum) { if (CheckClrDebugState() && ( CheckClrDebugState()->ViolationMask() & BadDebugState)) { _ASSERTE(!"Someone tried to assert a contract violation although the contracts were disabled in this thread due to" " an OOM or a shim/mscorwks mismatch. You can probably safely ignore this assert - however, whoever" " called CONTRACT_ASSERT was supposed to checked if the current violationmask had the BadDebugState set." " Look up the stack, see who called CONTRACT_ASSERT and file a bug against the owner."); return; } // prevent recursion - we use the same mechanism as CHECK, so this will // also prevent mutual recursion involving ASSERT_CHECKs CHECK _check; if (_check.EnterAssert()) { char Buf[512*20 + 2048 + 1024]; sprintf_s(Buf,ARRAY_SIZE(Buf), "CONTRACT VIOLATION by %s at \"%s\" @ %d\n\n%s\n", szFunction, szFile, lineNum, szElaboration); int count = 20; ContractStackRecord *pRec = CheckClrDebugState() ? CheckClrDebugState()->GetContractStackTrace() : NULL; BOOL foundconflict = FALSE; BOOL exceptionBuildingStack = FALSE; PAL_TRY_NAKED { while (pRec != NULL) { char tmpbuf[512]; BOOL fshowconflict = FALSE; if (!foundconflict) { if (whichTest == (pRec->m_testmask & whichTestMask)) { foundconflict = TRUE; fshowconflict = TRUE; } } if (count != 0 || fshowconflict) { if (count != 0) { count--; } else { // Show that some lines have been skipped strcat_s(Buf, ARRAY_SIZE(Buf), "\n ..."); } sprintf_s(tmpbuf,ARRAY_SIZE(tmpbuf), "\n%s %s in %s at \"%s\" @ %d", fshowconflict ? "VIOLATED-->" : " ", pRec->m_construct, pRec->m_szFunction, pRec->m_szFile, pRec->m_lineNum ); strcat_s(Buf, ARRAY_SIZE(Buf), tmpbuf); } pRec = pRec->m_pNext; } } PAL_EXCEPT_NAKED(EXCEPTION_EXECUTE_HANDLER) { // We're done trying to walk the stack of contracts. We faulted trying to form the contract stack trace, // and that usually means that its corrupted. A common cause of this is having CONTRACTs in functions that // never return, but instead do a non-local goto. count = 0; exceptionBuildingStack = TRUE; } PAL_ENDTRY_NAKED; if (count == 0) { strcat_s(Buf,ARRAY_SIZE(Buf), "\n ..."); } if (exceptionBuildingStack) { strcat_s(Buf,ARRAY_SIZE(Buf), "\n" "\nError forming contract stack. Any contract stack displayed above is correct," "\nbut it's most probably truncated. This is probably due to a CONTRACT in a" "\nfunction that does a non-local goto. There are two bugs here:" "\n" "\n 1) the CONTRACT violation, and" "\n 2) the CONTRACT in the function with the non-local goto." "\n" "\nPlease fix both bugs!" "\n" ); } strcat_s(Buf,ARRAY_SIZE(Buf), "\n\n"); if (!foundconflict && count != 0) { if (whichTest == BaseContract::THROWS_No) { strcat_s(Buf,ARRAY_SIZE(Buf), "You can't throw here because there is no handler on the stack.\n"); } else { strcat_s(Buf,ARRAY_SIZE(Buf), "We can't find the violated contract. Look for an old-style non-holder-based contract.\n"); } } DbgAssertDialog((char *)szFile, lineNum, Buf); _check.LeaveAssert(); } } FORCEINLINE BOOL BaseContract::EnforceContract() { if (s_alwaysEnforceContracts) return TRUE; else return CHECK::EnforceAssert(); } inline void BaseContract::SetUnconditionalContractEnforcement(BOOL value) { s_alwaysEnforceContracts = value; } inline UINT GetDbgStateCombinedLockCount() { return GetClrDebugState()->GetCombinedLockCount(); } inline UINT GetDbgStateLockCount(DbgStateLockType dbgStateLockType) { return GetClrDebugState()->GetLockCount(dbgStateLockType); } #define ASSERT_NO_USER_LOCKS_HELD() \ _ASSERTE(GetDbgStateLockCount(kDbgStateLockType_User) == 0) #define ASSERT_NO_HOST_BREAKABLE_CRSTS_HELD() \ _ASSERTE(GetDbgStateLockCount(kDbgStateLockType_HostBreakableCrst) == 0) #define ASSERT_NO_EE_LOCKS_HELD() \ _ASSERTE(GetDbgStateLockCount(kDbgStateLockType_EE) == 0) #else // ENABLE_CONTRACTS_IMPL #define ASSERT_NO_USER_LOCKS_HELD() #define ASSERT_NO_HOST_BREAKABLE_CRSTS_HELD() #define ASSERT_NO_EE_LOCKS_HELD() #endif // ENABLE_CONTRACTS_IMPL #endif // CONTRACT_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cor.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** Cor.h - general header for the Runtime. ** ** ** *****************************************************************************/ #ifndef _COR_H_ #define _COR_H_ //***************************************************************************** // Required includes #include // Definitions of OLE types. #include #include "corerror.h" //***************************************************************************** #ifdef __cplusplus extern "C" { #endif // {BED7F4EA-1A96-11d2-8F08-00A0C9A6186D} EXTERN_GUID(LIBID_ComPlusRuntime, 0xbed7f4ea, 0x1a96, 0x11d2, 0x8f, 0x8, 0x0, 0xa0, 0xc9, 0xa6, 0x18, 0x6d); // {90883F05-3D28-11D2-8F17-00A0C9A6186D} EXTERN_GUID(GUID_ExportedFromComPlus, 0x90883f05, 0x3d28, 0x11d2, 0x8f, 0x17, 0x0, 0xa0, 0xc9, 0xa6, 0x18, 0x6d); // {0F21F359-AB84-41e8-9A78-36D110E6D2F9} EXTERN_GUID(GUID_ManagedName, 0xf21f359, 0xab84, 0x41e8, 0x9a, 0x78, 0x36, 0xd1, 0x10, 0xe6, 0xd2, 0xf9); // {54FC8F55-38DE-4703-9C4E-250351302B1C} EXTERN_GUID(GUID_Function2Getter, 0x54fc8f55, 0x38de, 0x4703, 0x9c, 0x4e, 0x25, 0x3, 0x51, 0x30, 0x2b, 0x1c); // CLSID_CorMetaDataDispenserRuntime: {1EC2DE53-75CC-11d2-9775-00A0C9B4D50C} // Dispenser coclass for version 1.5 and 2.0 meta data. To get the "latest" bind // to CLSID_MetaDataDispenser. EXTERN_GUID(CLSID_CorMetaDataDispenserRuntime, 0x1ec2de53, 0x75cc, 0x11d2, 0x97, 0x75, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); // {CD2BC5C9-F452-4326-B714-F9C539D4DA58} EXTERN_GUID(GUID_DispIdOverride, 0xcd2bc5c9, 0xf452, 0x4326, 0xb7, 0x14, 0xf9, 0xc5, 0x39, 0xd4, 0xda, 0x58); // {B64784EB-D8D4-4d9b-9ACD-0E30806426F7} EXTERN_GUID(GUID_ForceIEnumerable, 0xb64784eb, 0xd8d4, 0x4d9b, 0x9a, 0xcd, 0x0e, 0x30, 0x80, 0x64, 0x26, 0xf7); // {2941FF83-88D8-4F73-B6A9-BDF8712D000D} EXTERN_GUID(GUID_PropGetCA, 0x2941ff83, 0x88d8, 0x4f73, 0xb6, 0xa9, 0xbd, 0xf8, 0x71, 0x2d, 0x00, 0x0d); // {29533527-3683-4364-ABC0-DB1ADD822FA2} EXTERN_GUID(GUID_PropPutCA, 0x29533527, 0x3683, 0x4364, 0xab, 0xc0, 0xdb, 0x1a, 0xdd, 0x82, 0x2f, 0xa2); // CLSID_CLR_v1_MetaData: {005023CA-72B1-11D3-9FC4-00C04F79A0A3} // Used to generate v1 metadata (for v1.0 and v1.1 CLR compatibility). EXTERN_GUID(CLSID_CLR_v1_MetaData, 0x005023ca, 0x72b1, 0x11d3, 0x9f, 0xc4, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); // CLSID_CLR_v2_MetaData: {EFEA471A-44FD-4862-9292-0C58D46E1F3A} EXTERN_GUID(CLSID_CLR_v2_MetaData, 0xefea471a, 0x44fd, 0x4862, 0x92, 0x92, 0xc, 0x58, 0xd4, 0x6e, 0x1f, 0x3a); // CLSID_CorMetaDataRuntime: // This will can always be used to generate the "latest" metadata available. #define CLSID_CorMetaDataRuntime CLSID_CLR_v2_MetaData // {30FE7BE8-D7D9-11D2-9F80-00C04F79A0A3} EXTERN_GUID(MetaDataCheckDuplicatesFor, 0x30fe7be8, 0xd7d9, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); // {DE3856F8-D7D9-11D2-9F80-00C04F79A0A3} EXTERN_GUID(MetaDataRefToDefCheck, 0xde3856f8, 0xd7d9, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); // {E5D71A4C-D7DA-11D2-9F80-00C04F79A0A3} EXTERN_GUID(MetaDataNotificationForTokenMovement, 0xe5d71a4c, 0xd7da, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); // {2eee315c-d7db-11d2-9f80-00c04f79a0a3} EXTERN_GUID(MetaDataSetUpdate, 0x2eee315c, 0xd7db, 0x11d2, 0x9f, 0x80, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); #define MetaDataSetENC MetaDataSetUpdate // Use this guid in SetOption to indicate if the import enumerator should skip over // delete items or not. The default is yes. // // {79700F36-4AAC-11d3-84C3-009027868CB1} EXTERN_GUID(MetaDataImportOption, 0x79700f36, 0x4aac, 0x11d3, 0x84, 0xc3, 0x0, 0x90, 0x27, 0x86, 0x8c, 0xb1); // Use this guid in the SetOption if compiler wants to have MetaData API to take reader/writer lock // // {F7559806-F266-42ea-8C63-0ADB45E8B234} EXTERN_GUID(MetaDataThreadSafetyOptions, 0xf7559806, 0xf266, 0x42ea, 0x8c, 0x63, 0xa, 0xdb, 0x45, 0xe8, 0xb2, 0x34); // Use this guid in the SetOption if compiler wants error when some tokens are emitted out of order // {1547872D-DC03-11d2-9420-0000F8083460} EXTERN_GUID(MetaDataErrorIfEmitOutOfOrder, 0x1547872d, 0xdc03, 0x11d2, 0x94, 0x20, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); // Use this guid in the SetOption to indicate if the tlbimporter should generate the // TCE adapters for COM connection point containers. // {DCC9DE90-4151-11d3-88D6-00902754C43A} EXTERN_GUID(MetaDataGenerateTCEAdapters, 0xdcc9de90, 0x4151, 0x11d3, 0x88, 0xd6, 0x0, 0x90, 0x27, 0x54, 0xc4, 0x3a); // Use this guid in the SetOption to specifiy a non-default namespace for typelib import. // {F17FF889-5A63-11d3-9FF2-00C04FF7431A} EXTERN_GUID(MetaDataTypeLibImportNamespace, 0xf17ff889, 0x5a63, 0x11d3, 0x9f, 0xf2, 0x0, 0xc0, 0x4f, 0xf7, 0x43, 0x1a); // Use this guid in the SetOption to specify the behavior of UnmarkAll. See CorLinkerOptions. // {47E099B6-AE7C-4797-8317-B48AA645B8F9} EXTERN_GUID(MetaDataLinkerOptions, 0x47e099b6, 0xae7c, 0x4797, 0x83, 0x17, 0xb4, 0x8a, 0xa6, 0x45, 0xb8, 0xf9); // Use this guid in the SetOption to specify the runtime version stored in the CLR metadata. // {47E099B7-AE7C-4797-8317-B48AA645B8F9} EXTERN_GUID(MetaDataRuntimeVersion, 0x47e099b7, 0xae7c, 0x4797, 0x83, 0x17, 0xb4, 0x8a, 0xa6, 0x45, 0xb8, 0xf9); // Use this guid in the SetOption to specify the behavior of the merger. // {132D3A6E-B35D-464e-951A-42EFB9FB6601} EXTERN_GUID(MetaDataMergerOptions, 0x132d3a6e, 0xb35d, 0x464e, 0x95, 0x1a, 0x42, 0xef, 0xb9, 0xfb, 0x66, 0x1); // Use this guid in SetOption to disable optimizing module-local refs to defs // {a55c0354-e91b-468b-8648-7cc31035d533} EXTERN_GUID(MetaDataPreserveLocalRefs, 0xa55c0354, 0xe91b, 0x468b, 0x86, 0x48, 0x7c, 0xc3, 0x10, 0x35, 0xd5, 0x33); interface IMetaDataImport; interface IMetaDataAssemblyEmit; interface IMetaDataAssemblyImport; interface IMetaDataEmit; typedef UNALIGNED void const *UVCP_CONSTANT; // Constant for connection id and task id #define INVALID_CONNECTION_ID 0x0 #define INVALID_TASK_ID 0x0 #define MAX_CONNECTION_NAME MAX_PATH #define MAIN_CLR_MODULE_NAME_W W("coreclr") #define MAIN_CLR_MODULE_NAME_A "coreclr" #define MAIN_CLR_DLL_NAME_W MAKEDLLNAME_W(MAIN_CLR_MODULE_NAME_W) #define MAIN_CLR_DLL_NAME_A MAKEDLLNAME_A(MAIN_CLR_MODULE_NAME_A) #define TARGET_MAIN_CLR_DLL_NAME_W MAKE_TARGET_DLLNAME_W(MAIN_CLR_MODULE_NAME_W) #define TARGET_MAIN_CLR_DLL_NAME_A MAKE_TARGET_DLLNAME_A(MAIN_CLR_MODULE_NAME_A) //***************************************************************************** //***************************************************************************** // // I L & F I L E F O R M A T D E C L A R A T I O N S // //***************************************************************************** //***************************************************************************** // #ifndef _WINDOWS_UPDATES_ #include #endif // updates //***************************************************************************** //***************************************************************************** // CLSID_Cor: {bee00000-ee77-11d0-a015-00c04fbbb884} EXTERN_GUID(CLSID_Cor, 0xbee00010, 0xee77, 0x11d0, 0xa0, 0x15, 0x00, 0xc0, 0x4f, 0xbb, 0xb8, 0x84); // CLSID_CorMetaDataDispenser: {E5CB7A31-7512-11d2-89CE-0080C792E5D8} // This is the "Master Dispenser", always guaranteed to be the most recent // dispenser on the machine. EXTERN_GUID(CLSID_CorMetaDataDispenser, 0xe5cb7a31, 0x7512, 0x11d2, 0x89, 0xce, 0x0, 0x80, 0xc7, 0x92, 0xe5, 0xd8); // CLSID_CorMetaDataDispenserReg: {435755FF-7397-11d2-9771-00A0C9B4D50C} // Dispenser coclass for version 1.0 meta data. To get the "latest" bind // to CLSID_CorMetaDataDispenser. EXTERN_GUID(CLSID_CorMetaDataDispenserReg, 0x435755ff, 0x7397, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); // CLSID_CorMetaDataReg: {87F3A1F5-7397-11d2-9771-00A0C9B4D50C} // For COM+ Meta Data, Data Driven Registration EXTERN_GUID(CLSID_CorMetaDataReg, 0x87f3a1f5, 0x7397, 0x11d2, 0x97, 0x71, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); interface IMetaDataDispenser; //------------------------------------- //--- IMetaDataError //------------------------------------- // {B81FF171-20F3-11d2-8DCC-00A0C9B09C19} EXTERN_GUID(IID_IMetaDataError, 0xb81ff171, 0x20f3, 0x11d2, 0x8d, 0xcc, 0x0, 0xa0, 0xc9, 0xb0, 0x9c, 0x19); //--- #undef INTERFACE #define INTERFACE IMetaDataError DECLARE_INTERFACE_(IMetaDataError, IUnknown) { STDMETHOD(OnError)(HRESULT hrError, mdToken token) PURE; }; //------------------------------------- //--- IMapToken //------------------------------------- // IID_IMapToken: {06A3EA8B-0225-11d1-BF72-00C04FC31E12} EXTERN_GUID(IID_IMapToken, 0x6a3ea8b, 0x225, 0x11d1, 0xbf, 0x72, 0x0, 0xc0, 0x4f, 0xc3, 0x1e, 0x12); //--- #undef INTERFACE #define INTERFACE IMapToken DECLARE_INTERFACE_(IMapToken, IUnknown) { STDMETHOD(Map)(mdToken tkImp, mdToken tkEmit) PURE; }; //------------------------------------- //--- IMetaDataDispenser //------------------------------------- // {809C652E-7396-11D2-9771-00A0C9B4D50C} EXTERN_GUID(IID_IMetaDataDispenser, 0x809c652e, 0x7396, 0x11d2, 0x97, 0x71, 0x00, 0xa0, 0xc9, 0xb4, 0xd5, 0x0c); //--- #undef INTERFACE #define INTERFACE IMetaDataDispenser DECLARE_INTERFACE_(IMetaDataDispenser, IUnknown) { STDMETHOD(DefineScope)( // Return code. REFCLSID rclsid, // [in] What version to create. DWORD dwCreateFlags, // [in] Flags on the create. REFIID riid, // [in] The interface desired. IUnknown **ppIUnk) PURE; // [out] Return interface on success. STDMETHOD(OpenScope)( // Return code. LPCWSTR szScope, // [in] The scope to open. DWORD dwOpenFlags, // [in] Open mode flags. REFIID riid, // [in] The interface desired. IUnknown **ppIUnk) PURE; // [out] Return interface on success. STDMETHOD(OpenScopeOnMemory)( // Return code. LPCVOID pData, // [in] Location of scope data. ULONG cbData, // [in] Size of the data pointed to by pData. DWORD dwOpenFlags, // [in] Open mode flags. REFIID riid, // [in] The interface desired. IUnknown **ppIUnk) PURE; // [out] Return interface on success. }; //------------------------------------- //--- IMetaDataEmit //------------------------------------- // {BA3FEE4C-ECB9-4e41-83B7-183FA41CD859} EXTERN_GUID(IID_IMetaDataEmit, 0xba3fee4c, 0xecb9, 0x4e41, 0x83, 0xb7, 0x18, 0x3f, 0xa4, 0x1c, 0xd8, 0x59); //--- #undef INTERFACE #define INTERFACE IMetaDataEmit DECLARE_INTERFACE_(IMetaDataEmit, IUnknown) { STDMETHOD(SetModuleProps)( // S_OK or error. LPCWSTR szName) PURE; // [IN] If not NULL, the name of the module to set. STDMETHOD(Save)( // S_OK or error. LPCWSTR szFile, // [IN] The filename to save to. DWORD dwSaveFlags) PURE; // [IN] Flags for the save. STDMETHOD(SaveToStream)( // S_OK or error. IStream *pIStream, // [IN] A writable stream to save to. DWORD dwSaveFlags) PURE; // [IN] Flags for the save. STDMETHOD(GetSaveSize)( // S_OK or error. CorSaveSize fSave, // [IN] cssAccurate or cssQuick. DWORD *pdwSaveSize) PURE; // [OUT] Put the size here. STDMETHOD(DefineTypeDef)( // S_OK or error. LPCWSTR szTypeDef, // [IN] Name of TypeDef DWORD dwTypeDefFlags, // [IN] CustomAttribute flags mdToken tkExtends, // [IN] extends this TypeDef or typeref mdToken rtkImplements[], // [IN] Implements interfaces mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here STDMETHOD(DefineNestedType)( // S_OK or error. LPCWSTR szTypeDef, // [IN] Name of TypeDef DWORD dwTypeDefFlags, // [IN] CustomAttribute flags mdToken tkExtends, // [IN] extends this TypeDef or typeref mdToken rtkImplements[], // [IN] Implements interfaces mdTypeDef tdEncloser, // [IN] TypeDef token of the enclosing type. mdTypeDef *ptd) PURE; // [OUT] Put TypeDef token here STDMETHOD(SetHandler)( // S_OK. IUnknown *pUnk) PURE; // [IN] The new error handler. STDMETHOD(DefineMethod)( // S_OK or error. mdTypeDef td, // Parent TypeDef LPCWSTR szName, // Name of member DWORD dwMethodFlags, // Member attributes PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob ULONG ulCodeRVA, DWORD dwImplFlags, mdMethodDef *pmd) PURE; // Put member token here STDMETHOD(DefineMethodImpl)( // S_OK or error. mdTypeDef td, // [IN] The class implementing the method mdToken tkBody, // [IN] Method body - MethodDef or MethodRef mdToken tkDecl) PURE; // [IN] Method declaration - MethodDef or MethodRef STDMETHOD(DefineTypeRefByName)( // S_OK or error. mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. LPCWSTR szName, // [IN] Name of the TypeRef. mdTypeRef *ptr) PURE; // [OUT] Put TypeRef token here. STDMETHOD(DefineImportType)( // S_OK or error. IMetaDataAssemblyImport *pAssemImport, // [IN] Assembly containing the TypeDef. const void *pbHashValue, // [IN] Hash Blob for Assembly. ULONG cbHashValue, // [IN] Count of bytes. IMetaDataImport *pImport, // [IN] Scope containing the TypeDef. mdTypeDef tdImport, // [IN] The imported TypeDef. IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the TypeDef is imported. mdTypeRef *ptr) PURE; // [OUT] Put TypeRef token here. STDMETHOD(DefineMemberRef)( // S_OK or error mdToken tkImport, // [IN] ClassRef or ClassDef importing a member. LPCWSTR szName, // [IN] member's name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMemberRef *pmr) PURE; // [OUT] memberref token STDMETHOD(DefineImportMember)( // S_OK or error. IMetaDataAssemblyImport *pAssemImport, // [IN] Assembly containing the Member. const void *pbHashValue, // [IN] Hash Blob for Assembly. ULONG cbHashValue, // [IN] Count of bytes. IMetaDataImport *pImport, // [IN] Import scope, with member. mdToken mbMember, // [IN] Member in import scope. IMetaDataAssemblyEmit *pAssemEmit, // [IN] Assembly into which the Member is imported. mdToken tkParent, // [IN] Classref or classdef in emit scope. mdMemberRef *pmr) PURE; // [OUT] Put member ref here. STDMETHOD(DefineEvent) ( mdTypeDef td, // [IN] the class/interface on which the event is being defined LPCWSTR szEvent, // [IN] Name of the event DWORD dwEventFlags, // [IN] CorEventAttr mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class mdMethodDef mdAddOn, // [IN] required add method mdMethodDef mdRemoveOn, // [IN] required remove method mdMethodDef mdFire, // [IN] optional fire method mdMethodDef rmdOtherMethods[], // [IN] optional array of other methods associate with the event mdEvent *pmdEvent) PURE; // [OUT] output event token STDMETHOD(SetClassLayout) ( mdTypeDef td, // [IN] typedef DWORD dwPackSize, // [IN] packing size specified as 1, 2, 4, 8, or 16 COR_FIELD_OFFSET rFieldOffsets[], // [IN] array of layout specification ULONG ulClassSize) PURE; // [IN] size of the class STDMETHOD(DeleteClassLayout) ( mdTypeDef td) PURE; // [IN] typedef whose layout is to be deleted. STDMETHOD(SetFieldMarshal) ( mdToken tk, // [IN] given a fieldDef or paramDef token PCCOR_SIGNATURE pvNativeType, // [IN] native type specification ULONG cbNativeType) PURE; // [IN] count of bytes of pvNativeType STDMETHOD(DeleteFieldMarshal) ( mdToken tk) PURE; // [IN] given a fieldDef or paramDef token STDMETHOD(DefinePermissionSet) ( mdToken tk, // [IN] the object to be decorated. DWORD dwAction, // [IN] CorDeclSecurity. void const *pvPermission, // [IN] permission blob. ULONG cbPermission, // [IN] count of bytes of pvPermission. mdPermission *ppm) PURE; // [OUT] returned permission token. STDMETHOD(SetRVA)( // S_OK or error. mdMethodDef md, // [IN] Method for which to set offset ULONG ulRVA) PURE; // [IN] The offset STDMETHOD(GetTokenFromSig)( // S_OK or error. PCCOR_SIGNATURE pvSig, // [IN] Signature to define. ULONG cbSig, // [IN] Size of signature data. mdSignature *pmsig) PURE; // [OUT] returned signature token. STDMETHOD(DefineModuleRef)( // S_OK or error. LPCWSTR szName, // [IN] DLL name mdModuleRef *pmur) PURE; // [OUT] returned // @FUTURE: This should go away once everyone starts using SetMemberRefProps. STDMETHOD(SetParent)( // S_OK or error. mdMemberRef mr, // [IN] Token for the ref to be fixed up. mdToken tk) PURE; // [IN] The ref parent. STDMETHOD(GetTokenFromTypeSpec)( // S_OK or error. PCCOR_SIGNATURE pvSig, // [IN] TypeSpec Signature to define. ULONG cbSig, // [IN] Size of signature data. mdTypeSpec *ptypespec) PURE; // [OUT] returned TypeSpec token. STDMETHOD(SaveToMemory)( // S_OK or error. void *pbData, // [OUT] Location to write data. ULONG cbData) PURE; // [IN] Max size of data buffer. STDMETHOD(DefineUserString)( // Return code. LPCWSTR szString, // [IN] User literal string. ULONG cchString, // [IN] Length of string. mdString *pstk) PURE; // [OUT] String token. STDMETHOD(DeleteToken)( // Return code. mdToken tkObj) PURE; // [IN] The token to be deleted STDMETHOD(SetMethodProps)( // S_OK or error. mdMethodDef md, // [IN] The MethodDef. DWORD dwMethodFlags, // [IN] Method attributes. ULONG ulCodeRVA, // [IN] Code RVA. DWORD dwImplFlags) PURE; // [IN] Impl flags. STDMETHOD(SetTypeDefProps)( // S_OK or error. mdTypeDef td, // [IN] The TypeDef. DWORD dwTypeDefFlags, // [IN] TypeDef flags. mdToken tkExtends, // [IN] Base TypeDef or TypeRef. mdToken rtkImplements[]) PURE; // [IN] Implemented interfaces. STDMETHOD(SetEventProps)( // S_OK or error. mdEvent ev, // [IN] The event token. DWORD dwEventFlags, // [IN] CorEventAttr. mdToken tkEventType, // [IN] A reference (mdTypeRef or mdTypeRef) to the Event class. mdMethodDef mdAddOn, // [IN] Add method. mdMethodDef mdRemoveOn, // [IN] Remove method. mdMethodDef mdFire, // [IN] Fire method. mdMethodDef rmdOtherMethods[]) PURE;// [IN] Array of other methods associate with the event. STDMETHOD(SetPermissionSetProps)( // S_OK or error. mdToken tk, // [IN] The object to be decorated. DWORD dwAction, // [IN] CorDeclSecurity. void const *pvPermission, // [IN] Permission blob. ULONG cbPermission, // [IN] Count of bytes of pvPermission. mdPermission *ppm) PURE; // [OUT] Permission token. STDMETHOD(DefinePinvokeMap)( // Return code. mdToken tk, // [IN] FieldDef or MethodDef. DWORD dwMappingFlags, // [IN] Flags used for mapping. LPCWSTR szImportName, // [IN] Import name. mdModuleRef mrImportDLL) PURE; // [IN] ModuleRef token for the target DLL. STDMETHOD(SetPinvokeMap)( // Return code. mdToken tk, // [IN] FieldDef or MethodDef. DWORD dwMappingFlags, // [IN] Flags used for mapping. LPCWSTR szImportName, // [IN] Import name. mdModuleRef mrImportDLL) PURE; // [IN] ModuleRef token for the target DLL. STDMETHOD(DeletePinvokeMap)( // Return code. mdToken tk) PURE; // [IN] FieldDef or MethodDef. // New CustomAttribute functions. STDMETHOD(DefineCustomAttribute)( // Return code. mdToken tkOwner, // [IN] The object to put the value on. mdToken tkCtor, // [IN] Constructor of the CustomAttribute type (MemberRef/MethodDef). void const *pCustomAttribute, // [IN] The custom value data. ULONG cbCustomAttribute, // [IN] The custom value data length. mdCustomAttribute *pcv) PURE; // [OUT] The custom value token value on return. STDMETHOD(SetCustomAttributeValue)( // Return code. mdCustomAttribute pcv, // [IN] The custom value token whose value to replace. void const *pCustomAttribute, // [IN] The custom value data. ULONG cbCustomAttribute) PURE;// [IN] The custom value data length. STDMETHOD(DefineField)( // S_OK or error. mdTypeDef td, // Parent TypeDef LPCWSTR szName, // Name of member DWORD dwFieldFlags, // Member attributes PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* void const *pValue, // [IN] constant value ULONG cchValue, // [IN] size of constant value (string, in wide chars). mdFieldDef *pmd) PURE; // [OUT] Put member token here STDMETHOD(DefineProperty)( mdTypeDef td, // [IN] the class/interface on which the property is being defined LPCWSTR szProperty, // [IN] Name of the property DWORD dwPropFlags, // [IN] CorPropertyAttr PCCOR_SIGNATURE pvSig, // [IN] the required type signature ULONG cbSig, // [IN] the size of the type signature blob DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* void const *pValue, // [IN] constant value ULONG cchValue, // [IN] size of constant value (string, in wide chars). mdMethodDef mdSetter, // [IN] optional setter of the property mdMethodDef mdGetter, // [IN] optional getter of the property mdMethodDef rmdOtherMethods[], // [IN] an optional array of other methods mdProperty *pmdProp) PURE; // [OUT] output property token STDMETHOD(DefineParam)( mdMethodDef md, // [IN] Owning method ULONG ulParamSeq, // [IN] Which param LPCWSTR szName, // [IN] Optional param name DWORD dwParamFlags, // [IN] Optional param flags DWORD dwCPlusTypeFlag, // [IN] flag for value type. selected ELEMENT_TYPE_* void const *pValue, // [IN] constant value ULONG cchValue, // [IN] size of constant value (string, in wide chars). mdParamDef *ppd) PURE; // [OUT] Put param token here STDMETHOD(SetFieldProps)( // S_OK or error. mdFieldDef fd, // [IN] The FieldDef. DWORD dwFieldFlags, // [IN] Field attributes. DWORD dwCPlusTypeFlag, // [IN] Flag for the value type, selected ELEMENT_TYPE_* void const *pValue, // [IN] Constant value. ULONG cchValue) PURE; // [IN] size of constant value (string, in wide chars). STDMETHOD(SetPropertyProps)( // S_OK or error. mdProperty pr, // [IN] Property token. DWORD dwPropFlags, // [IN] CorPropertyAttr. DWORD dwCPlusTypeFlag, // [IN] Flag for value type, selected ELEMENT_TYPE_* void const *pValue, // [IN] Constant value. ULONG cchValue, // [IN] size of constant value (string, in wide chars). mdMethodDef mdSetter, // [IN] Setter of the property. mdMethodDef mdGetter, // [IN] Getter of the property. mdMethodDef rmdOtherMethods[]) PURE;// [IN] Array of other methods. STDMETHOD(SetParamProps)( // Return code. mdParamDef pd, // [IN] Param token. LPCWSTR szName, // [IN] Param name. DWORD dwParamFlags, // [IN] Param flags. DWORD dwCPlusTypeFlag, // [IN] Flag for value type. selected ELEMENT_TYPE_*. void const *pValue, // [OUT] Constant value. ULONG cchValue) PURE; // [IN] size of constant value (string, in wide chars). // Specialized Custom Attributes for security. STDMETHOD(DefineSecurityAttributeSet)( // Return code. mdToken tkObj, // [IN] Class or method requiring security attributes. COR_SECATTR rSecAttrs[], // [IN] Array of security attribute descriptions. ULONG cSecAttrs, // [IN] Count of elements in above array. ULONG *pulErrorAttr) PURE; // [OUT] On error, index of attribute causing problem. STDMETHOD(ApplyEditAndContinue)( // S_OK or error. IUnknown *pImport) PURE; // [IN] Metadata from the delta PE. STDMETHOD(TranslateSigWithScope)( IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface const void *pbHashValue, // [IN] Hash Blob for Assembly. ULONG cbHashValue, // [IN] Count of bytes. IMetaDataImport *import, // [IN] importing interface PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope ULONG cbSigBlob, // [IN] count of bytes of signature IMetaDataAssemblyEmit *pAssemEmit, // [IN] emit assembly interface IMetaDataEmit *emit, // [IN] emit interface PCOR_SIGNATURE pvTranslatedSig, // [OUT] buffer to hold translated signature ULONG cbTranslatedSigMax, ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature STDMETHOD(SetMethodImplFlags)( // [IN] S_OK or error. mdMethodDef md, // [IN] Method for which to set ImplFlags DWORD dwImplFlags) PURE; STDMETHOD(SetFieldRVA)( // [IN] S_OK or error. mdFieldDef fd, // [IN] Field for which to set offset ULONG ulRVA) PURE; // [IN] The offset STDMETHOD(Merge)( // S_OK or error. IMetaDataImport *pImport, // [IN] The scope to be merged. IMapToken *pHostMapToken, // [IN] Host IMapToken interface to receive token remap notification IUnknown *pHandler) PURE; // [IN] An object to receive to receive error notification. STDMETHOD(MergeEnd)() PURE; // S_OK or error. // This interface is sealed. Do not change, add, or remove anything. Instead, derive a new iterface. }; // IMetaDataEmit //------------------------------------- //--- IMetaDataEmit2 //------------------------------------- // {F5DD9950-F693-42e6-830E-7B833E8146A9} EXTERN_GUID(IID_IMetaDataEmit2, 0xf5dd9950, 0xf693, 0x42e6, 0x83, 0xe, 0x7b, 0x83, 0x3e, 0x81, 0x46, 0xa9); //--- #undef INTERFACE #define INTERFACE IMetaDataEmit2 DECLARE_INTERFACE_(IMetaDataEmit2, IMetaDataEmit) { STDMETHOD(DefineMethodSpec)( mdToken tkParent, // [IN] MethodDef or MemberRef PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of COM+ signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMethodSpec *pmi) PURE; // [OUT] method instantiation token STDMETHOD(GetDeltaSaveSize)( // S_OK or error. CorSaveSize fSave, // [IN] cssAccurate or cssQuick. DWORD *pdwSaveSize) PURE; // [OUT] Put the size here. STDMETHOD(SaveDelta)( // S_OK or error. LPCWSTR szFile, // [IN] The filename to save to. DWORD dwSaveFlags) PURE; // [IN] Flags for the save. STDMETHOD(SaveDeltaToStream)( // S_OK or error. IStream *pIStream, // [IN] A writable stream to save to. DWORD dwSaveFlags) PURE; // [IN] Flags for the save. STDMETHOD(SaveDeltaToMemory)( // S_OK or error. void *pbData, // [OUT] Location to write data. ULONG cbData) PURE; // [IN] Max size of data buffer. STDMETHOD(DefineGenericParam)( // S_OK or error. mdToken tk, // [IN] TypeDef or MethodDef ULONG ulParamSeq, // [IN] Index of the type parameter DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance) LPCWSTR szname, // [IN] Name DWORD reserved, // [IN] For future use (e.g. non-type parameters) mdToken rtkConstraints[], // [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) mdGenericParam *pgp) PURE; // [OUT] Put GenericParam token here STDMETHOD(SetGenericParamProps)( // S_OK or error. mdGenericParam gp, // [IN] GenericParam DWORD dwParamFlags, // [IN] Flags, for future use (e.g. variance) LPCWSTR szName, // [IN] Optional name DWORD reserved, // [IN] For future use (e.g. non-type parameters) mdToken rtkConstraints[]) PURE;// [IN] Array of type constraints (TypeDef,TypeRef,TypeSpec) STDMETHOD(ResetENCLog)() PURE; // S_OK or error. }; //------------------------------------- //--- IMetaDataImport //------------------------------------- // {7DAC8207-D3AE-4c75-9B67-92801A497D44} EXTERN_GUID(IID_IMetaDataImport, 0x7dac8207, 0xd3ae, 0x4c75, 0x9b, 0x67, 0x92, 0x80, 0x1a, 0x49, 0x7d, 0x44); //--- #undef INTERFACE #define INTERFACE IMetaDataImport DECLARE_INTERFACE_(IMetaDataImport, IUnknown) { STDMETHOD_(void, CloseEnum)(HCORENUM hEnum) PURE; STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG *pulCount) PURE; STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos) PURE; STDMETHOD(EnumTypeDefs)(HCORENUM *phEnum, mdTypeDef rTypeDefs[], ULONG cMax, ULONG *pcTypeDefs) PURE; STDMETHOD(EnumInterfaceImpls)(HCORENUM *phEnum, mdTypeDef td, mdInterfaceImpl rImpls[], ULONG cMax, ULONG* pcImpls) PURE; STDMETHOD(EnumTypeRefs)(HCORENUM *phEnum, mdTypeRef rTypeRefs[], ULONG cMax, ULONG* pcTypeRefs) PURE; STDMETHOD(FindTypeDefByName)( // S_OK or error. LPCWSTR szTypeDef, // [IN] Name of the Type. mdToken tkEnclosingClass, // [IN] TypeDef/TypeRef for Enclosing class. mdTypeDef *ptd) PURE; // [OUT] Put the TypeDef token here. STDMETHOD(GetScopeProps)( // S_OK or error. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Put the name here. ULONG cchName, // [IN] Size of name buffer in wide chars. ULONG *pchName, // [OUT] Put size of name (wide chars) here. GUID *pmvid) PURE; // [OUT, OPTIONAL] Put MVID here. STDMETHOD(GetModuleFromScope)( // S_OK. mdModule *pmd) PURE; // [OUT] Put mdModule token here. STDMETHOD(GetTypeDefProps)( // S_OK or error. mdTypeDef td, // [IN] TypeDef token for inquiry. _Out_writes_to_opt_(cchTypeDef, *pchTypeDef) LPWSTR szTypeDef, // [OUT] Put name here. ULONG cchTypeDef, // [IN] size of name buffer in wide chars. ULONG *pchTypeDef, // [OUT] put size of name (wide chars) here. DWORD *pdwTypeDefFlags, // [OUT] Put flags here. mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here. STDMETHOD(GetInterfaceImplProps)( // S_OK or error. mdInterfaceImpl iiImpl, // [IN] InterfaceImpl token. mdTypeDef *pClass, // [OUT] Put implementing class token here. mdToken *ptkIface) PURE; // [OUT] Put implemented interface token here. STDMETHOD(GetTypeRefProps)( // S_OK or error. mdTypeRef tr, // [IN] TypeRef token. mdToken *ptkResolutionScope, // [OUT] Resolution scope, ModuleRef or AssemblyRef. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Name of the TypeRef. ULONG cchName, // [IN] Size of buffer. ULONG *pchName) PURE; // [OUT] Size of Name. STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown **ppIScope, mdTypeDef *ptd) PURE; STDMETHOD(EnumMembers)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. mdToken rMembers[], // [OUT] Put MemberDefs here. ULONG cMax, // [IN] Max MemberDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumMembersWithName)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. LPCWSTR szName, // [IN] Limit results to those with this name. mdToken rMembers[], // [OUT] Put MemberDefs here. ULONG cMax, // [IN] Max MemberDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumMethods)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. mdMethodDef rMethods[], // [OUT] Put MethodDefs here. ULONG cMax, // [IN] Max MethodDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumMethodsWithName)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. LPCWSTR szName, // [IN] Limit results to those with this name. mdMethodDef rMethods[], // [OU] Put MethodDefs here. ULONG cMax, // [IN] Max MethodDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumFields)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. mdFieldDef rFields[], // [OUT] Put FieldDefs here. ULONG cMax, // [IN] Max FieldDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumFieldsWithName)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef cl, // [IN] TypeDef to scope the enumeration. LPCWSTR szName, // [IN] Limit results to those with this name. mdFieldDef rFields[], // [OUT] Put MemberDefs here. ULONG cMax, // [IN] Max MemberDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumParams)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdMethodDef mb, // [IN] MethodDef to scope the enumeration. mdParamDef rParams[], // [OUT] Put ParamDefs here. ULONG cMax, // [IN] Max ParamDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumMemberRefs)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tkParent, // [IN] Parent token to scope the enumeration. mdMemberRef rMemberRefs[], // [OUT] Put MemberRefs here. ULONG cMax, // [IN] Max MemberRefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumMethodImpls)( // S_OK, S_FALSE, or error HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef td, // [IN] TypeDef to scope the enumeration. mdToken rMethodBody[], // [OUT] Put Method Body tokens here. mdToken rMethodDecl[], // [OUT] Put Method Declaration tokens here. ULONG cMax, // [IN] Max tokens to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumPermissionSets)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tk, // [IN] if !NIL, token to scope the enumeration. DWORD dwActions, // [IN] if !0, return only these actions. mdPermission rPermission[], // [OUT] Put Permissions here. ULONG cMax, // [IN] Max Permissions to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(FindMember)( mdTypeDef td, // [IN] given typedef LPCWSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdToken *pmb) PURE; // [OUT] matching memberdef STDMETHOD(FindMethod)( mdTypeDef td, // [IN] given typedef LPCWSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMethodDef *pmb) PURE; // [OUT] matching memberdef STDMETHOD(FindField)( mdTypeDef td, // [IN] given typedef LPCWSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdFieldDef *pmb) PURE; // [OUT] matching memberdef STDMETHOD(FindMemberRef)( mdTypeRef td, // [IN] given typeRef LPCWSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMemberRef *pmr) PURE; // [OUT] matching memberref STDMETHOD (GetMethodProps)( mdMethodDef mb, // The method for which to get props. mdTypeDef *pClass, // Put method's class here. _Out_writes_to_opt_(cchMethod, *pchMethod) LPWSTR szMethod, // Put method's name here. ULONG cchMethod, // Size of szMethod buffer in wide chars. ULONG *pchMethod, // Put actual size here DWORD *pdwAttr, // Put flags here. PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob, // [OUT] actual size of signature blob ULONG *pulCodeRVA, // [OUT] codeRVA DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags STDMETHOD(GetMemberRefProps)( // S_OK or error. mdMemberRef mr, // [IN] given memberref mdToken *ptk, // [OUT] Put classref or classdef here. _Out_writes_to_opt_(cchMember, *pchMember) LPWSTR szMember, // [OUT] buffer to fill for member's name ULONG cchMember, // [IN] the count of char of szMember ULONG *pchMember, // [OUT] actual count of char in member name PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to meta data blob value ULONG *pbSig) PURE; // [OUT] actual size of signature blob STDMETHOD(EnumProperties)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef td, // [IN] TypeDef to scope the enumeration. mdProperty rProperties[], // [OUT] Put Properties here. ULONG cMax, // [IN] Max properties to put. ULONG *pcProperties) PURE; // [OUT] Put # put here. STDMETHOD(EnumEvents)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdTypeDef td, // [IN] TypeDef to scope the enumeration. mdEvent rEvents[], // [OUT] Put events here. ULONG cMax, // [IN] Max events to put. ULONG *pcEvents) PURE; // [OUT] Put # put here. STDMETHOD(GetEventProps)( // S_OK, S_FALSE, or error. mdEvent ev, // [IN] event token mdTypeDef *pClass, // [OUT] typedef containing the event declarion. LPCWSTR szEvent, // [OUT] Event name ULONG cchEvent, // [IN] the count of wchar of szEvent ULONG *pchEvent, // [OUT] actual count of wchar for event's name DWORD *pdwEventFlags, // [OUT] Event flags. mdToken *ptkEventType, // [OUT] EventType class mdMethodDef *pmdAddOn, // [OUT] AddOn method of the event mdMethodDef *pmdRemoveOn, // [OUT] RemoveOn method of the event mdMethodDef *pmdFire, // [OUT] Fire method of the event mdMethodDef rmdOtherMethod[], // [OUT] other method of the event ULONG cMax, // [IN] size of rmdOtherMethod ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this event STDMETHOD(EnumMethodSemantics)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdMethodDef mb, // [IN] MethodDef to scope the enumeration. mdToken rEventProp[], // [OUT] Put Event/Property here. ULONG cMax, // [IN] Max properties to put. ULONG *pcEventProp) PURE; // [OUT] Put # put here. STDMETHOD(GetMethodSemantics)( // S_OK, S_FALSE, or error. mdMethodDef mb, // [IN] method token mdToken tkEventProp, // [IN] event/property token. DWORD *pdwSemanticsFlags) PURE; // [OUT] the role flags for the method/propevent pair STDMETHOD(GetClassLayout) ( mdTypeDef td, // [IN] give typedef DWORD *pdwPackSize, // [OUT] 1, 2, 4, 8, or 16 COR_FIELD_OFFSET rFieldOffset[], // [OUT] field offset array ULONG cMax, // [IN] size of the array ULONG *pcFieldOffset, // [OUT] needed array size ULONG *pulClassSize) PURE; // [OUT] the size of the class STDMETHOD(GetFieldMarshal) ( mdToken tk, // [IN] given a field's memberdef PCCOR_SIGNATURE *ppvNativeType, // [OUT] native type of this field ULONG *pcbNativeType) PURE; // [OUT] the count of bytes of *ppvNativeType STDMETHOD(GetRVA)( // S_OK or error. mdToken tk, // Member for which to set offset ULONG *pulCodeRVA, // The offset DWORD *pdwImplFlags) PURE; // the implementation flags STDMETHOD(GetPermissionSetProps) ( mdPermission pm, // [IN] the permission token. DWORD *pdwAction, // [OUT] CorDeclSecurity. void const **ppvPermission, // [OUT] permission blob. ULONG *pcbPermission) PURE; // [OUT] count of bytes of pvPermission. STDMETHOD(GetSigFromToken)( // S_OK or error. mdSignature mdSig, // [IN] Signature token. PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. ULONG *pcbSig) PURE; // [OUT] return size of signature. STDMETHOD(GetModuleRefProps)( // S_OK or error. mdModuleRef mur, // [IN] moduleref token. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] buffer to fill with the moduleref name. ULONG cchName, // [IN] size of szName in wide characters. ULONG *pchName) PURE; // [OUT] actual count of characters in the name. STDMETHOD(EnumModuleRefs)( // S_OK or error. HCORENUM *phEnum, // [IN|OUT] pointer to the enum. mdModuleRef rModuleRefs[], // [OUT] put modulerefs here. ULONG cmax, // [IN] max memberrefs to put. ULONG *pcModuleRefs) PURE; // [OUT] put # put here. STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. mdTypeSpec typespec, // [IN] TypeSpec token. PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to TypeSpec signature ULONG *pcbSig) PURE; // [OUT] return size of signature. STDMETHOD(GetNameFromToken)( // Not Recommended! May be removed! mdToken tk, // [IN] Token to get name from. Must have a name. MDUTF8CSTR *pszUtf8NamePtr) PURE; // [OUT] Return pointer to UTF8 name in heap. STDMETHOD(EnumUnresolvedMethods)( // S_OK, S_FALSE, or error. HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken rMethods[], // [OUT] Put MemberDefs here. ULONG cMax, // [IN] Max MemberDefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(GetUserString)( // S_OK or error. mdString stk, // [IN] String token. _Out_writes_to_opt_(cchString, *pchString) LPWSTR szString, // [OUT] Copy of string. ULONG cchString, // [IN] Max chars of room in szString. ULONG *pchString) PURE; // [OUT] How many chars in actual string. STDMETHOD(GetPinvokeMap)( // S_OK or error. mdToken tk, // [IN] FieldDef or MethodDef. DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. _Out_writes_to_opt_(cchImportName, *pchImportName) LPWSTR szImportName, // [OUT] Import name. ULONG cchImportName, // [IN] Size of the name buffer. ULONG *pchImportName, // [OUT] Actual number of characters stored. mdModuleRef *pmrImportDLL) PURE; // [OUT] ModuleRef token for the target DLL. STDMETHOD(EnumSignatures)( // S_OK or error. HCORENUM *phEnum, // [IN|OUT] pointer to the enum. mdSignature rSignatures[], // [OUT] put signatures here. ULONG cmax, // [IN] max signatures to put. ULONG *pcSignatures) PURE; // [OUT] put # put here. STDMETHOD(EnumTypeSpecs)( // S_OK or error. HCORENUM *phEnum, // [IN|OUT] pointer to the enum. mdTypeSpec rTypeSpecs[], // [OUT] put TypeSpecs here. ULONG cmax, // [IN] max TypeSpecs to put. ULONG *pcTypeSpecs) PURE; // [OUT] put # put here. STDMETHOD(EnumUserStrings)( // S_OK or error. HCORENUM *phEnum, // [IN/OUT] pointer to the enum. mdString rStrings[], // [OUT] put Strings here. ULONG cmax, // [IN] max Strings to put. ULONG *pcStrings) PURE; // [OUT] put # put here. STDMETHOD(GetParamForMethodIndex)( // S_OK or error. mdMethodDef md, // [IN] Method token. ULONG ulParamSeq, // [IN] Parameter sequence. mdParamDef *ppd) PURE; // [IN] Put Param token here. STDMETHOD(EnumCustomAttributes)( // S_OK or error. HCORENUM *phEnum, // [IN, OUT] COR enumerator. mdToken tk, // [IN] Token to scope the enumeration, 0 for all. mdToken tkType, // [IN] Type of interest, 0 for all. mdCustomAttribute rCustomAttributes[], // [OUT] Put custom attribute tokens here. ULONG cMax, // [IN] Size of rCustomAttributes. ULONG *pcCustomAttributes) PURE; // [OUT, OPTIONAL] Put count of token values here. STDMETHOD(GetCustomAttributeProps)( // S_OK or error. mdCustomAttribute cv, // [IN] CustomAttribute token. mdToken *ptkObj, // [OUT, OPTIONAL] Put object token here. mdToken *ptkType, // [OUT, OPTIONAL] Put AttrType token here. void const **ppBlob, // [OUT, OPTIONAL] Put pointer to data here. ULONG *pcbSize) PURE; // [OUT, OPTIONAL] Put size of date here. STDMETHOD(FindTypeRef)( mdToken tkResolutionScope, // [IN] ModuleRef, AssemblyRef or TypeRef. LPCWSTR szName, // [IN] TypeRef Name. mdTypeRef *ptr) PURE; // [OUT] matching TypeRef. STDMETHOD(GetMemberProps)( mdToken mb, // The member for which to get props. mdTypeDef *pClass, // Put member's class here. _Out_writes_to_opt_(cchMember, *pchMember) LPWSTR szMember, // Put member's name here. ULONG cchMember, // Size of szMember buffer in wide chars. ULONG *pchMember, // Put actual size here DWORD *pdwAttr, // Put flags here. PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob, // [OUT] actual size of signature blob ULONG *pulCodeRVA, // [OUT] codeRVA DWORD *pdwImplFlags, // [OUT] Impl. Flags DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* UVCP_CONSTANT *ppValue, // [OUT] constant value ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. STDMETHOD(GetFieldProps)( mdFieldDef mb, // The field for which to get props. mdTypeDef *pClass, // Put field's class here. _Out_writes_to_opt_(cchField, *pchField) LPWSTR szField, // Put field's name here. ULONG cchField, // Size of szField buffer in wide chars. ULONG *pchField, // Put actual size here DWORD *pdwAttr, // Put flags here. PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob, // [OUT] actual size of signature blob DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* UVCP_CONSTANT *ppValue, // [OUT] constant value ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. STDMETHOD(GetPropertyProps)( // S_OK, S_FALSE, or error. mdProperty prop, // [IN] property token mdTypeDef *pClass, // [OUT] typedef containing the property declarion. LPCWSTR szProperty, // [OUT] Property name ULONG cchProperty, // [IN] the count of wchar of szProperty ULONG *pchProperty, // [OUT] actual count of wchar for property name DWORD *pdwPropFlags, // [OUT] property flags. PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob ULONG *pbSig, // [OUT] count of bytes in *ppvSig DWORD *pdwCPlusTypeFlag, // [OUT] flag for value type. selected ELEMENT_TYPE_* UVCP_CONSTANT *ppDefaultValue, // [OUT] constant value ULONG *pcchDefaultValue, // [OUT] size of constant string in chars, 0 for non-strings. mdMethodDef *pmdSetter, // [OUT] setter method of the property mdMethodDef *pmdGetter, // [OUT] getter method of the property mdMethodDef rmdOtherMethod[], // [OUT] other method of the property ULONG cMax, // [IN] size of rmdOtherMethod ULONG *pcOtherMethod) PURE; // [OUT] total number of other method of this property STDMETHOD(GetParamProps)( // S_OK or error. mdParamDef tk, // [IN]The Parameter. mdMethodDef *pmd, // [OUT] Parent Method token. ULONG *pulSequence, // [OUT] Parameter sequence. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Put name here. ULONG cchName, // [OUT] Size of name buffer. ULONG *pchName, // [OUT] Put actual size of name here. DWORD *pdwAttr, // [OUT] Put flags here. DWORD *pdwCPlusTypeFlag, // [OUT] Flag for value type. selected ELEMENT_TYPE_*. UVCP_CONSTANT *ppValue, // [OUT] Constant value. ULONG *pcchValue) PURE; // [OUT] size of constant string in chars, 0 for non-strings. STDMETHOD(GetCustomAttributeByName)( // S_OK or error. mdToken tkObj, // [IN] Object with Custom Attribute. LPCWSTR szName, // [IN] Name of desired Custom Attribute. const void **ppData, // [OUT] Put pointer to data here. ULONG *pcbData) PURE; // [OUT] Put size of data here. STDMETHOD_(BOOL, IsValidToken)( // True or False. mdToken tk) PURE; // [IN] Given token. STDMETHOD(GetNestedClassProps)( // S_OK or error. mdTypeDef tdNestedClass, // [IN] NestedClass token. mdTypeDef *ptdEnclosingClass) PURE; // [OUT] EnclosingClass token. STDMETHOD(GetNativeCallConvFromSig)( // S_OK or error. void const *pvSig, // [IN] Pointer to signature. ULONG cbSig, // [IN] Count of signature bytes. ULONG *pCallConv) PURE; // [OUT] Put calling conv here (see CorPinvokemap). STDMETHOD(IsGlobal)( // S_OK or error. mdToken pd, // [IN] Type, Field, or Method token. int *pbGlobal) PURE; // [OUT] Put 1 if global, 0 otherwise. // This interface is sealed. Do not change, add, or remove anything. Instead, derive a new iterface. }; // IMetaDataImport //------------------------------------- //--- IMetaDataImport2 //------------------------------------- // {FCE5EFA0-8BBA-4f8e-A036-8F2022B08466} EXTERN_GUID(IID_IMetaDataImport2, 0xfce5efa0, 0x8bba, 0x4f8e, 0xa0, 0x36, 0x8f, 0x20, 0x22, 0xb0, 0x84, 0x66); //--- #undef INTERFACE #define INTERFACE IMetaDataImport2 DECLARE_INTERFACE_(IMetaDataImport2, IMetaDataImport) { STDMETHOD(EnumGenericParams)( HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tk, // [IN] TypeDef or MethodDef whose generic parameters are requested mdGenericParam rGenericParams[], // [OUT] Put GenericParams here. ULONG cMax, // [IN] Max GenericParams to put. ULONG *pcGenericParams) PURE; // [OUT] Put # put here. STDMETHOD(GetGenericParamProps)( // S_OK or error. mdGenericParam gp, // [IN] GenericParam ULONG *pulParamSeq, // [OUT] Index of the type parameter DWORD *pdwParamFlags, // [OUT] Flags, for future use (e.g. variance) mdToken *ptOwner, // [OUT] Owner (TypeDef or MethodDef) DWORD *reserved, // [OUT] For future use (e.g. non-type parameters) _Out_writes_to_opt_(cchName, *pchName) LPWSTR wzname, // [OUT] Put name here ULONG cchName, // [IN] Size of buffer ULONG *pchName) PURE; // [OUT] Put size of name (wide chars) here. STDMETHOD(GetMethodSpecProps)( mdMethodSpec mi, // [IN] The method instantiation mdToken *tkParent, // [OUT] MethodDef or MemberRef PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob STDMETHOD(EnumGenericParamConstraints)( HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdGenericParam tk, // [IN] GenericParam whose constraints are requested mdGenericParamConstraint rGenericParamConstraints[], // [OUT] Put GenericParamConstraints here. ULONG cMax, // [IN] Max GenericParamConstraints to put. ULONG *pcGenericParamConstraints) PURE; // [OUT] Put # put here. STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. mdGenericParamConstraint gpc, // [IN] GenericParamConstraint mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained mdToken *ptkConstraintType) PURE; // [OUT] TypeDef/Ref/Spec constraint STDMETHOD(GetPEKind)( // S_OK or error. DWORD* pdwPEKind, // [OUT] The kind of PE (0 - not a PE) DWORD* pdwMAchine) PURE; // [OUT] Machine as defined in NT header STDMETHOD(GetVersionString)( // S_OK or error. _Out_writes_to_opt_(ccBufSize, *pccBufSize) LPWSTR pwzBuf, // [OUT] Put version string here. DWORD ccBufSize, // [IN] size of the buffer, in wide chars DWORD *pccBufSize) PURE; // [OUT] Size of the version string, wide chars, including terminating nul. STDMETHOD(EnumMethodSpecs)( HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdToken tk, // [IN] MethodDef or MemberRef whose MethodSpecs are requested mdMethodSpec rMethodSpecs[], // [OUT] Put MethodSpecs here. ULONG cMax, // [IN] Max tokens to put. ULONG *pcMethodSpecs) PURE; // [OUT] Put actual count here. }; // IMetaDataImport2 //------------------------------------- //--- IMetaDataFilter //------------------------------------- // {D0E80DD1-12D4-11d3-B39D-00C04FF81795} EXTERN_GUID(IID_IMetaDataFilter, 0xd0e80dd1, 0x12d4, 0x11d3, 0xb3, 0x9d, 0x0, 0xc0, 0x4f, 0xf8, 0x17, 0x95); //--- #undef INTERFACE #define INTERFACE IMetaDataFilter DECLARE_INTERFACE_(IMetaDataFilter, IUnknown) { STDMETHOD(UnmarkAll)() PURE; STDMETHOD(MarkToken)(mdToken tk) PURE; STDMETHOD(IsTokenMarked)(mdToken tk, BOOL *pIsMarked) PURE; }; //------------------------------------- //--- IHostFilter //------------------------------------- // {D0E80DD3-12D4-11d3-B39D-00C04FF81795} EXTERN_GUID(IID_IHostFilter, 0xd0e80dd3, 0x12d4, 0x11d3, 0xb3, 0x9d, 0x0, 0xc0, 0x4f, 0xf8, 0x17, 0x95); //--- #undef INTERFACE #define INTERFACE IHostFilter DECLARE_INTERFACE_(IHostFilter, IUnknown) { STDMETHOD(MarkToken)(mdToken tk) PURE; }; //***************************************************************************** // Assembly Declarations //***************************************************************************** typedef struct { DWORD dwOSPlatformId; // Operating system platform. DWORD dwOSMajorVersion; // OS Major version. DWORD dwOSMinorVersion; // OS Minor version. } OSINFO; typedef struct { USHORT usMajorVersion; // Major Version. USHORT usMinorVersion; // Minor Version. USHORT usBuildNumber; // Build Number. USHORT usRevisionNumber; // Revision Number. LPWSTR szLocale; // Locale. ULONG cbLocale; // [IN/OUT] Size of the buffer in wide chars/Actual size. DWORD *rProcessor; // Processor ID array. ULONG ulProcessor; // [IN/OUT] Size of the Processor ID array/Actual # of entries filled in. OSINFO *rOS; // OSINFO array. ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. } ASSEMBLYMETADATA; // {211EF15B-5317-4438-B196-DEC87B887693} EXTERN_GUID(IID_IMetaDataAssemblyEmit, 0x211ef15b, 0x5317, 0x4438, 0xb1, 0x96, 0xde, 0xc8, 0x7b, 0x88, 0x76, 0x93); //--- #undef INTERFACE #define INTERFACE IMetaDataAssemblyEmit DECLARE_INTERFACE_(IMetaDataAssemblyEmit, IUnknown) { STDMETHOD(DefineAssembly)( // S_OK or error. const void *pbPublicKey, // [IN] Public key of the assembly. ULONG cbPublicKey, // [IN] Count of bytes in the public key. ULONG ulHashAlgId, // [IN] Hash algorithm used to hash the files. LPCWSTR szName, // [IN] Name of the assembly. const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. DWORD dwAssemblyFlags, // [IN] Flags. mdAssembly *pma) PURE; // [OUT] Returned Assembly token. STDMETHOD(DefineAssemblyRef)( // S_OK or error. const void *pbPublicKeyOrToken, // [IN] Public key or token of the assembly. ULONG cbPublicKeyOrToken, // [IN] Count of bytes in the public key or token. LPCWSTR szName, // [IN] Name of the assembly being referenced. const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. const void *pbHashValue, // [IN] Hash Blob. ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. DWORD dwAssemblyRefFlags, // [IN] Flags. mdAssemblyRef *pmdar) PURE; // [OUT] Returned AssemblyRef token. STDMETHOD(DefineFile)( // S_OK or error. LPCWSTR szName, // [IN] Name of the file. const void *pbHashValue, // [IN] Hash Blob. ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. DWORD dwFileFlags, // [IN] Flags. mdFile *pmdf) PURE; // [OUT] Returned File token. STDMETHOD(DefineExportedType)( // S_OK or error. LPCWSTR szName, // [IN] Name of the Com Type. mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef or mdExportedType mdTypeDef tkTypeDef, // [IN] TypeDef token within the file. DWORD dwExportedTypeFlags, // [IN] Flags. mdExportedType *pmdct) PURE; // [OUT] Returned ExportedType token. STDMETHOD(DefineManifestResource)( // S_OK or error. LPCWSTR szName, // [IN] Name of the resource. mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. DWORD dwOffset, // [IN] Offset to the beginning of the resource within the file. DWORD dwResourceFlags, // [IN] Flags. mdManifestResource *pmdmr) PURE; // [OUT] Returned ManifestResource token. STDMETHOD(SetAssemblyProps)( // S_OK or error. mdAssembly pma, // [IN] Assembly token. const void *pbPublicKey, // [IN] Public key of the assembly. ULONG cbPublicKey, // [IN] Count of bytes in the public key. ULONG ulHashAlgId, // [IN] Hash algorithm used to hash the files. LPCWSTR szName, // [IN] Name of the assembly. const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. DWORD dwAssemblyFlags) PURE; // [IN] Flags. STDMETHOD(SetAssemblyRefProps)( // S_OK or error. mdAssemblyRef ar, // [IN] AssemblyRefToken. const void *pbPublicKeyOrToken, // [IN] Public key or token of the assembly. ULONG cbPublicKeyOrToken, // [IN] Count of bytes in the public key or token. LPCWSTR szName, // [IN] Name of the assembly being referenced. const ASSEMBLYMETADATA *pMetaData, // [IN] Assembly MetaData. const void *pbHashValue, // [IN] Hash Blob. ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. DWORD dwAssemblyRefFlags) PURE; // [IN] Token for Execution Location. STDMETHOD(SetFileProps)( // S_OK or error. mdFile file, // [IN] File token. const void *pbHashValue, // [IN] Hash Blob. ULONG cbHashValue, // [IN] Count of bytes in the Hash Blob. DWORD dwFileFlags) PURE; // [IN] Flags. STDMETHOD(SetExportedTypeProps)( // S_OK or error. mdExportedType ct, // [IN] ExportedType token. mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef or mdExportedType. mdTypeDef tkTypeDef, // [IN] TypeDef token within the file. DWORD dwExportedTypeFlags) PURE; // [IN] Flags. STDMETHOD(SetManifestResourceProps)( // S_OK or error. mdManifestResource mr, // [IN] ManifestResource token. mdToken tkImplementation, // [IN] mdFile or mdAssemblyRef that provides the resource. DWORD dwOffset, // [IN] Offset to the beginning of the resource within the file. DWORD dwResourceFlags) PURE; // [IN] Flags. }; // IMetaDataAssemblyEmit // {EE62470B-E94B-424e-9B7C-2F00C9249F93} EXTERN_GUID(IID_IMetaDataAssemblyImport, 0xee62470b, 0xe94b, 0x424e, 0x9b, 0x7c, 0x2f, 0x0, 0xc9, 0x24, 0x9f, 0x93); //--- #undef INTERFACE #define INTERFACE IMetaDataAssemblyImport DECLARE_INTERFACE_(IMetaDataAssemblyImport, IUnknown) { STDMETHOD(GetAssemblyProps)( // S_OK or error. mdAssembly mda, // [IN] The Assembly for which to get the properties. const void **ppbPublicKey, // [OUT] Pointer to the public key. ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. ULONG *pulHashAlgId, // [OUT] Hash Algorithm. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with assembly's simply name. ULONG cchName, // [IN] Size of buffer in wide chars. ULONG *pchName, // [OUT] Actual # of wide chars in name. ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. DWORD *pdwAssemblyFlags) PURE; // [OUT] Flags. STDMETHOD(GetAssemblyRefProps)( // S_OK or error. mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. _Out_writes_to_opt_(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. ULONG cchName, // [IN] Size of buffer in wide chars. ULONG *pchName, // [OUT] Actual # of wide chars in name. ASSEMBLYMETADATA *pMetaData, // [OUT] Assembly MetaData. const void **ppbHashValue, // [OUT] Hash blob. ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. STDMETHOD(GetFileProps)( // S_OK or error. mdFile mdf, // [IN] The File for which to get the properties. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. ULONG cchName, // [IN] Size of buffer in wide chars. ULONG *pchName, // [OUT] Actual # of wide chars in name. const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. DWORD *pdwFileFlags) PURE; // [OUT] Flags. STDMETHOD(GetExportedTypeProps)( // S_OK or error. mdExportedType mdct, // [IN] The ExportedType for which to get the properties. _Out_writes_to_opt_(cchName, *pchName) LPWSTR szName, // [OUT] Buffer to fill with name. ULONG cchName, // [IN] Size of buffer in wide chars. ULONG *pchName, // [OUT] Actual # of wide chars in name. mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef or mdExportedType. mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. STDMETHOD(GetManifestResourceProps)( // S_OK or error. mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. _Out_writes_to_opt_(cchName, *pchName)LPWSTR szName, // [OUT] Buffer to fill with name. ULONG cchName, // [IN] Size of buffer in wide chars. ULONG *pchName, // [OUT] Actual # of wide chars in name. mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ManifestResource. DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. DWORD *pdwResourceFlags) PURE;// [OUT] Flags. STDMETHOD(EnumAssemblyRefs)( // S_OK or error HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdAssemblyRef rAssemblyRefs[], // [OUT] Put AssemblyRefs here. ULONG cMax, // [IN] Max AssemblyRefs to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumFiles)( // S_OK or error HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdFile rFiles[], // [OUT] Put Files here. ULONG cMax, // [IN] Max Files to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumExportedTypes)( // S_OK or error HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdExportedType rExportedTypes[], // [OUT] Put ExportedTypes here. ULONG cMax, // [IN] Max ExportedTypes to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(EnumManifestResources)( // S_OK or error HCORENUM *phEnum, // [IN|OUT] Pointer to the enum. mdManifestResource rManifestResources[], // [OUT] Put ManifestResources here. ULONG cMax, // [IN] Max Resources to put. ULONG *pcTokens) PURE; // [OUT] Put # put here. STDMETHOD(GetAssemblyFromScope)( // S_OK or error mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. STDMETHOD(FindExportedTypeByName)( // S_OK or error LPCWSTR szName, // [IN] Name of the ExportedType. mdToken mdtExportedType, // [IN] ExportedType for the enclosing class. mdExportedType *ptkExportedType) PURE; // [OUT] Put the ExportedType token here. STDMETHOD(FindManifestResourceByName)( // S_OK or error LPCWSTR szName, // [IN] Name of the ManifestResource. mdManifestResource *ptkManifestResource) PURE; // [OUT] Put the ManifestResource token here. STDMETHOD_(void, CloseEnum)( HCORENUM hEnum) PURE; // Enum to be closed. STDMETHOD(FindAssembliesByName)( // S_OK or error LPCWSTR szAppBase, // [IN] optional - can be NULL LPCWSTR szPrivateBin, // [IN] optional - can be NULL LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting IUnknown *ppIUnk[], // [OUT] put IMetaDataAssemblyImport pointers here ULONG cMax, // [IN] The max number to put ULONG *pcAssemblies) PURE; // [OUT] The number of assemblies returned. }; // IMetaDataAssemblyImport //***************************************************************************** // End Assembly Declarations //***************************************************************************** //***************************************************************************** // MetaData Validator Declarations //***************************************************************************** // Specifies the type of the module, PE file vs. .obj file. typedef enum { ValidatorModuleTypeInvalid = 0x0, ValidatorModuleTypeMin = 0x00000001, ValidatorModuleTypePE = 0x00000001, ValidatorModuleTypeObj = 0x00000002, ValidatorModuleTypeEnc = 0x00000003, ValidatorModuleTypeIncr = 0x00000004, ValidatorModuleTypeMax = 0x00000004, } CorValidatorModuleType; // {4709C9C6-81FF-11D3-9FC7-00C04F79A0A3} EXTERN_GUID(IID_IMetaDataValidate, 0x4709c9c6, 0x81ff, 0x11d3, 0x9f, 0xc7, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); //--- #undef INTERFACE #define INTERFACE IMetaDataValidate DECLARE_INTERFACE_(IMetaDataValidate, IUnknown) { STDMETHOD(ValidatorInit)( // S_OK or error. DWORD dwModuleType, // [IN] Specifies the type of the module. IUnknown *pUnk) PURE; // [IN] Validation error handler. STDMETHOD(ValidateMetaData)( // S_OK or error. ) PURE; }; // IMetaDataValidate //***************************************************************************** // End MetaData Validator Declarations //***************************************************************************** //***************************************************************************** // IMetaDataDispenserEx declarations. //***************************************************************************** // {31BCFCE2-DAFB-11D2-9F81-00C04F79A0A3} EXTERN_GUID(IID_IMetaDataDispenserEx, 0x31bcfce2, 0xdafb, 0x11d2, 0x9f, 0x81, 0x0, 0xc0, 0x4f, 0x79, 0xa0, 0xa3); #undef INTERFACE #define INTERFACE IMetaDataDispenserEx DECLARE_INTERFACE_(IMetaDataDispenserEx, IMetaDataDispenser) { STDMETHOD(SetOption)( // Return code. REFGUID optionid, // [in] GUID for the option to be set. const VARIANT *value) PURE; // [in] Value to which the option is to be set. STDMETHOD(GetOption)( // Return code. REFGUID optionid, // [in] GUID for the option to be set. VARIANT *pvalue) PURE; // [out] Value to which the option is currently set. STDMETHOD(OpenScopeOnITypeInfo)( // Return code. ITypeInfo *pITI, // [in] ITypeInfo to open. DWORD dwOpenFlags, // [in] Open mode flags. REFIID riid, // [in] The interface desired. IUnknown **ppIUnk) PURE; // [out] Return interface on success. STDMETHOD(GetCORSystemDirectory)( // Return code. _Out_writes_to_opt_(cchBuffer, *pchBuffer) LPWSTR szBuffer, // [out] Buffer for the directory name DWORD cchBuffer, // [in] Size of the buffer DWORD* pchBuffer) PURE; // [OUT] Number of characters returned STDMETHOD(FindAssembly)( // S_OK or error LPCWSTR szAppBase, // [IN] optional - can be NULL LPCWSTR szPrivateBin, // [IN] optional - can be NULL LPCWSTR szGlobalBin, // [IN] optional - can be NULL LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting LPCWSTR szName, // [OUT] buffer - to hold name ULONG cchName, // [IN] the name buffer's size ULONG *pcName) PURE; // [OUT] the number of characters returned in the buffer STDMETHOD(FindAssemblyModule)( // S_OK or error LPCWSTR szAppBase, // [IN] optional - can be NULL LPCWSTR szPrivateBin, // [IN] optional - can be NULL LPCWSTR szGlobalBin, // [IN] optional - can be NULL LPCWSTR szAssemblyName, // [IN] required - this is the assembly you are requesting LPCWSTR szModuleName, // [IN] required - the name of the module _Out_writes_to_opt_(cchName, *pcName) LPWSTR szName, // [OUT] buffer - to hold name ULONG cchName, // [IN] the name buffer's size ULONG *pcName) PURE; // [OUT] the number of characters returned in the buffer }; //********************************************************************** //********************************************************************** //--- IMetaDataTables //------------------------------------- // This API isn't big endian friendly since it indexes directly into the memory that // is stored in little endian format. // {D8F579AB-402D-4b8e-82D9-5D63B1065C68} EXTERN_GUID(IID_IMetaDataTables, 0xd8f579ab, 0x402d, 0x4b8e, 0x82, 0xd9, 0x5d, 0x63, 0xb1, 0x6, 0x5c, 0x68); DECLARE_INTERFACE_(IMetaDataTables, IUnknown) { STDMETHOD (GetStringHeapSize) ( ULONG *pcbStrings) PURE; // [OUT] Size of the string heap. STDMETHOD (GetBlobHeapSize) ( ULONG *pcbBlobs) PURE; // [OUT] Size of the Blob heap. STDMETHOD (GetGuidHeapSize) ( ULONG *pcbGuids) PURE; // [OUT] Size of the Guid heap. STDMETHOD (GetUserStringHeapSize) ( ULONG *pcbBlobs) PURE; // [OUT] Size of the User String heap. STDMETHOD (GetNumTables) ( ULONG *pcTables) PURE; // [OUT] Count of tables. STDMETHOD (GetTableIndex) ( ULONG token, // [IN] Token for which to get table index. ULONG *pixTbl) PURE; // [OUT] Put table index here. STDMETHOD (GetTableInfo) ( ULONG ixTbl, // [IN] Which table. ULONG *pcbRow, // [OUT] Size of a row, bytes. ULONG *pcRows, // [OUT] Number of rows. ULONG *pcCols, // [OUT] Number of columns in each row. ULONG *piKey, // [OUT] Key column, or -1 if none. const char **ppName) PURE; // [OUT] Name of the table. STDMETHOD (GetColumnInfo) ( ULONG ixTbl, // [IN] Which Table ULONG ixCol, // [IN] Which Column in the table ULONG *poCol, // [OUT] Offset of the column in the row. ULONG *pcbCol, // [OUT] Size of a column, bytes. ULONG *pType, // [OUT] Type of the column. const char **ppName) PURE; // [OUT] Name of the Column. STDMETHOD (GetCodedTokenInfo) ( ULONG ixCdTkn, // [IN] Which kind of coded token. ULONG *pcTokens, // [OUT] Count of tokens. ULONG **ppTokens, // [OUT] List of tokens. const char **ppName) PURE; // [OUT] Name of the CodedToken. STDMETHOD (GetRow) ( ULONG ixTbl, // [IN] Which table. ULONG rid, // [IN] Which row. void **ppRow) PURE; // [OUT] Put pointer to row here. STDMETHOD (GetColumn) ( ULONG ixTbl, // [IN] Which table. ULONG ixCol, // [IN] Which column. ULONG rid, // [IN] Which row. ULONG *pVal) PURE; // [OUT] Put the column contents here. STDMETHOD (GetString) ( ULONG ixString, // [IN] Value from a string column. const char **ppString) PURE; // [OUT] Put a pointer to the string here. STDMETHOD (GetBlob) ( ULONG ixBlob, // [IN] Value from a blob column. ULONG *pcbData, // [OUT] Put size of the blob here. const void **ppData) PURE; // [OUT] Put a pointer to the blob here. STDMETHOD (GetGuid) ( ULONG ixGuid, // [IN] Value from a guid column. const GUID **ppGUID) PURE; // [OUT] Put a pointer to the GUID here. STDMETHOD (GetUserString) ( ULONG ixUserString, // [IN] Value from a UserString column. ULONG *pcbData, // [OUT] Put size of the UserString here. const void **ppData) PURE; // [OUT] Put a pointer to the UserString here. STDMETHOD (GetNextString) ( ULONG ixString, // [IN] Value from a string column. ULONG *pNext) PURE; // [OUT] Put the index of the next string here. STDMETHOD (GetNextBlob) ( ULONG ixBlob, // [IN] Value from a blob column. ULONG *pNext) PURE; // [OUT] Put the index of the netxt blob here. STDMETHOD (GetNextGuid) ( ULONG ixGuid, // [IN] Value from a guid column. ULONG *pNext) PURE; // [OUT] Put the index of the next guid here. STDMETHOD (GetNextUserString) ( ULONG ixUserString, // [IN] Value from a UserString column. ULONG *pNext) PURE; // [OUT] Put the index of the next user string here. // Interface is sealed. }; // This API isn't big endian friendly since it indexes directly into the memory that // is stored in little endian format. // {BADB5F70-58DA-43a9-A1C6-D74819F19B15} EXTERN_GUID(IID_IMetaDataTables2, 0xbadb5f70, 0x58da, 0x43a9, 0xa1, 0xc6, 0xd7, 0x48, 0x19, 0xf1, 0x9b, 0x15); DECLARE_INTERFACE_(IMetaDataTables2, IMetaDataTables) { STDMETHOD (GetMetaDataStorage) ( //@todo: name? const void **ppvMd, // [OUT] put pointer to MD section here (aka, 'BSJB'). ULONG *pcbMd) PURE; // [OUT] put size of the stream here. STDMETHOD (GetMetaDataStreamInfo) ( // Get info about the MD stream. ULONG ix, // [IN] Stream ordinal desired. const char **ppchName, // [OUT] put pointer to stream name here. const void **ppv, // [OUT] put pointer to MD stream here. ULONG *pcb) PURE; // [OUT] put size of the stream here. }; // IMetaDataTables2 #ifdef _DEFINE_META_DATA_META_CONSTANTS #ifndef _META_DATA_META_CONSTANTS_DEFINED #define _META_DATA_META_CONSTANTS_DEFINED const unsigned int iRidMax = 63; const unsigned int iCodedToken = 64; // base of coded tokens. const unsigned int iCodedTokenMax = 95; const unsigned int iSHORT = 96; // fixed types. const unsigned int iUSHORT = 97; const unsigned int iLONG = 98; const unsigned int iULONG = 99; const unsigned int iBYTE = 100; const unsigned int iSTRING = 101; // pool types. const unsigned int iGUID = 102; const unsigned int iBLOB = 103; inline int IsRidType(ULONG ix) { return ix <= iRidMax; } inline int IsCodedTokenType(ULONG ix) { return (ix >= iCodedToken) && (ix <= iCodedTokenMax); } inline int IsRidOrToken(ULONG ix) { return ix <= iCodedTokenMax; } inline int IsHeapType(ULONG ix) { return ix >= iSTRING; } inline int IsFixedType(ULONG ix) { return (ix < iSTRING) && (ix > iCodedTokenMax); } #endif #endif //********************************************************************** // End of IMetaDataTables. //********************************************************************** //------------------------------------- //--- IMetaDataInfo //------------------------------------- // {7998EA64-7F95-48B8-86FC-17CAF48BF5CB} EXTERN_GUID(IID_IMetaDataInfo, 0x7998EA64, 0x7F95, 0x48B8, 0x86, 0xFC, 0x17, 0xCA, 0xF4, 0x8B, 0xF5, 0xCB); //--- #undef INTERFACE #define INTERFACE IMetaDataInfo DECLARE_INTERFACE_(IMetaDataInfo, IUnknown) { // Return Values: // S_OK - All parameters are filled. // COR_E_NOTSUPPORTED - The API is not supported for this particular scope (e.g. .obj files, scope // opened without whole file via code:IMetaDataDispenser::OpenScopeOnMemory, etc.). // E_INVALIDARG - If NULL is passed as parameter. STDMETHOD(GetFileMapping)( const void ** ppvData, // [out] Pointer to the start of the mapped file. ULONGLONG * pcbData, // [out] Size of the mapped memory region. DWORD * pdwMappingType) PURE; // [out] Type of file mapping (code:CorFileMapping). }; // class IMetaDataInfo //********************************************************************** // // Predefined CustomAttribute and structures for these custom value // //********************************************************************** // // Native Link method custom value definitions. This is for N-direct support. // #include typedef struct { BYTE m_linkType; // see CorNativeLinkType below BYTE m_flags; // see CorNativeLinkFlags below mdMemberRef m_entryPoint; // member ref token giving entry point, format is lib:entrypoint } COR_NATIVE_LINK; #include typedef enum { nltNone = 1, // none of the keywords are specified nltAnsi = 2, // ansi keyword specified nltUnicode = 3, // unicode keyword specified nltAuto = 4, // auto keyword specified nltMaxValue = 7, // used so we can assert how many bits are required for this enum } CorNativeLinkType; typedef enum { nlfNone = 0x00, // no flags nlfLastError = 0x01, // setLastError keyword specified nlfNoMangle = 0x02, // nomangle keyword specified nlfMaxValue = 0x03, // used so we can assert how many bits are required for this enum } CorNativeLinkFlags; // // Base class for security custom attributes. // #define COR_BASE_SECURITY_ATTRIBUTE_CLASS L"System.Security.Permissions.SecurityAttribute" #define COR_BASE_SECURITY_ATTRIBUTE_CLASS_ANSI "System.Security.Permissions.SecurityAttribute" // // Name of custom attribute used to indicate that per-call security checks should // be disabled for P/Invoke calls. // #define COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE L"System.Security.SuppressUnmanagedCodeSecurityAttribute" #define COR_SUPPRESS_UNMANAGED_CODE_CHECK_ATTRIBUTE_ANSI "System.Security.SuppressUnmanagedCodeSecurityAttribute" // // Name of custom attribute tagged on module to indicate it contains // unverifiable code. // #define COR_UNVER_CODE_ATTRIBUTE L"System.Security.UnverifiableCodeAttribute" #define COR_UNVER_CODE_ATTRIBUTE_ANSI "System.Security.UnverifiableCodeAttribute" // // Name of custom attribute indicating that a method requires a security object // slot on the caller's stack. // #define COR_REQUIRES_SECOBJ_ATTRIBUTE W("System.Security.DynamicSecurityMethodAttribute") #define COR_REQUIRES_SECOBJ_ATTRIBUTE_ANSI "System.Security.DynamicSecurityMethodAttribute" #define COR_COMPILERSERVICE_DISCARDABLEATTRIBUTE L"System.Runtime.CompilerServices.DiscardableAttribute" #define COR_COMPILERSERVICE_DISCARDABLEATTRIBUTE_ASNI "System.Runtime.CompilerServices.DiscardableAttribute" #ifdef __cplusplus } //***************************************************************************** //***************************************************************************** // // C O M + s i g n a t u r e s u p p o r t // //***************************************************************************** //***************************************************************************** #ifndef FORCEINLINE #if _MSC_VER < 1200 #define FORCEINLINE inline #else #define FORCEINLINE __forceinline #endif #endif // We need a version that is FORCEINLINE on retail and NOINLINE on debug #ifndef DEBUG_NOINLINE #if defined(_DEBUG) #define DEBUG_NOINLINE NOINLINE #else #define DEBUG_NOINLINE #endif #endif #ifndef NOINLINE #ifdef _MSC_VER #define NOINLINE __declspec(noinline) #elif defined __GNUC__ #define NOINLINE __attribute__ ((noinline)) #else #define NOINLINE #endif #endif // !NOINLINE // return true if it is a primitive type, i.e. only need to store CorElementType FORCEINLINE int CorIsPrimitiveType(CorElementType elementtype) { return (elementtype < ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_I || elementtype == ELEMENT_TYPE_U); } // Return true if element type is a modifier, i.e. ELEMENT_TYPE_MODIFIER bits are // turned on. For now, it is checking for ELEMENT_TYPE_PTR and ELEMENT_TYPE_BYREF // as well. This will be removed when we turn on ELEMENT_TYPE_MODIFIER bits for // these two enum members. // FORCEINLINE int CorIsModifierElementType(CorElementType elementtype) { if (elementtype == ELEMENT_TYPE_PTR || elementtype == ELEMENT_TYPE_BYREF) return 1; return (elementtype & ELEMENT_TYPE_MODIFIER); } // Given a compress byte (*pData), return the size of the uncompressed data. inline ULONG CorSigUncompressedDataSize( PCCOR_SIGNATURE pData) { if ((*pData & 0x80) == 0) return 1; else if ((*pData & 0xC0) == 0x80) return 2; else return 4; } ///////////////////////////////////////////////////////////////////////////////////////////// // // Given a compressed integer(*pData), expand the compressed int to *pDataOut. // Return value is the number of bytes that the integer occupies in the compressed format // It is caller's responsibility to ensure pDataOut has at least 4 bytes to be written to. // // This function returns -1 if pass in with an incorrectly compressed data, such as // (*pBytes & 0xE0) == 0XE0. ///////////////////////////////////////////////////////////////////////////////////////////// inline ULONG CorSigUncompressBigData( PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data { ULONG res; // 1 byte data is handled in CorSigUncompressData // _ASSERTE(*pData & 0x80); // Medium. if ((*pData & 0xC0) == 0x80) // 10?? ???? { res = (ULONG)((*pData++ & 0x3f) << 8); res |= *pData++; } else // 110? ???? { res = (*pData++ & 0x1f) << 24; res |= *pData++ << 16; res |= *pData++ << 8; res |= *pData++; } return res; } FORCEINLINE ULONG CorSigUncompressData( PCCOR_SIGNATURE & pData) // [IN,OUT] compressed data { // Handle smallest data inline. if ((*pData & 0x80) == 0x00) // 0??? ???? return *pData++; return CorSigUncompressBigData(pData); } #ifdef HOST_WINDOWS inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the signature is bad PCCOR_SIGNATURE pData, // [IN] compressed data DWORD len, // [IN] length of the signature ULONG * pDataOut, // [OUT] the expanded *pData ULONG * pDataLen) // [OUT] length of the expanded *pData { HRESULT hr = S_OK; BYTE const *pBytes = reinterpret_cast(pData); // Smallest. if ((*pBytes & 0x80) == 0x00) // 0??? ???? { if (len < 1) { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } else { *pDataOut = *pBytes; *pDataLen = 1; } } // Medium. else if ((*pBytes & 0xC0) == 0x80) // 10?? ???? { if (len < 2) { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } else { *pDataOut = (ULONG)(((*pBytes & 0x3f) << 8 | *(pBytes+1))); *pDataLen = 2; } } else if ((*pBytes & 0xE0) == 0xC0) // 110? ???? { if (len < 4) { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } else { *pDataOut = (ULONG)(((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3))); *pDataLen = 4; } } else // We don't recognize this encoding { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } return hr; } #endif // HOST_WINDOWS inline HRESULT CorSigUncompressData(// return S_OK or E_BADIMAGEFORMAT if the signature is bad PCCOR_SIGNATURE pData, // [IN] compressed data DWORD len, // [IN] length of the signature uint32_t * pDataOut, // [OUT] the expanded *pData uint32_t * pDataLen) // [OUT] length of the expanded *pData { HRESULT hr = S_OK; BYTE const *pBytes = reinterpret_cast(pData); // Smallest. if ((*pBytes & 0x80) == 0x00) // 0??? ???? { if (len < 1) { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } else { *pDataOut = *pBytes; *pDataLen = 1; } } // Medium. else if ((*pBytes & 0xC0) == 0x80) // 10?? ???? { if (len < 2) { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } else { *pDataOut = (uint32_t)(((*pBytes & 0x3f) << 8 | *(pBytes+1))); *pDataLen = 2; } } else if ((*pBytes & 0xE0) == 0xC0) // 110? ???? { if (len < 4) { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } else { *pDataOut = (uint32_t)(((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3))); *pDataLen = 4; } } else // We don't recognize this encoding { *pDataOut = 0; *pDataLen = 0; hr = META_E_BAD_SIGNATURE; } return hr; } inline ULONG CorSigUncompressData( // return number of bytes of that compressed data occupied in pData PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut) // [OUT] the expanded *pData { ULONG dwSizeOfData = 0; // We don't know how big the signature is, so we'll just say that it's big enough if (FAILED(CorSigUncompressData(pData, 0xff, reinterpret_cast(pDataOut), reinterpret_cast(&dwSizeOfData)))) { *pDataOut = 0; return (ULONG)-1; } return dwSizeOfData; } FORCEINLINE mdToken CorSigDecodeTokenType(int encoded) { static const mdToken s_tableTokenTypes[] = {mdtTypeDef, mdtTypeRef, mdtTypeSpec, mdtBaseType}; return s_tableTokenTypes[encoded]; } // uncompress a token inline mdToken CorSigUncompressToken( // return the token. PCCOR_SIGNATURE &pData) // [IN,OUT] compressed data { mdToken tk; mdToken tkType; tk = CorSigUncompressData(pData); tkType = CorSigDecodeTokenType(tk & 0x3); tk = TokenFromRid(tk >> 2, tkType); return tk; } inline ULONG CorSigUncompressToken( // return number of bytes of that compressed data occupied in pData PCCOR_SIGNATURE pData, // [IN] compressed data mdToken * pToken) // [OUT] the expanded *pData { ULONG cb; mdToken tk; mdToken tkType; cb = CorSigUncompressData(pData, (ULONG *)&tk); tkType = CorSigDecodeTokenType(tk & 0x3); tk = TokenFromRid(tk >> 2, tkType); *pToken = tk; return cb; } inline HRESULT CorSigUncompressToken( PCCOR_SIGNATURE pData, // [IN] compressed data uint32_t dwLen, // [IN] Remaining length of sigature mdToken * pToken, // [OUT] the expanded *pData uint32_t * dwTokenLength) // [OUT] The length of the token in the sigature { mdToken tk; mdToken tkType; HRESULT hr = CorSigUncompressData(pData, dwLen, (uint32_t *)&tk, dwTokenLength); if (SUCCEEDED(hr)) { tkType = CorSigDecodeTokenType(tk & 0x3); tk = TokenFromRid(tk >> 2, tkType); *pToken = tk; } else { *pToken = mdTokenNil; } return hr; } FORCEINLINE ULONG CorSigUncompressCallingConv( PCCOR_SIGNATURE & pData) // [IN,OUT] Compressed data { return *pData++; } FORCEINLINE HRESULT CorSigUncompressCallingConv( PCCOR_SIGNATURE pData, // [IN] Signature DWORD dwLen, // [IN] Length of signature uint32_t * data) // [OUT] Compressed data { if (dwLen > 0) { *data = *pData; return S_OK; } else { *data = 0; return META_E_BAD_SIGNATURE; } } enum { SIGN_MASK_ONEBYTE = 0xffffffc0, // Mask the same size as the missing bits. SIGN_MASK_TWOBYTE = 0xffffe000, // Mask the same size as the missing bits. SIGN_MASK_FOURBYTE = 0xf0000000, // Mask the same size as the missing bits. }; // uncompress a signed integer inline ULONG CorSigUncompressSignedInt( // return number of bytes of that compressed data occupied in pData PCCOR_SIGNATURE pData, // [IN] compressed data int * pInt) // [OUT] the expanded *pInt { ULONG cb; ULONG ulSigned; ULONG iData; cb = CorSigUncompressData(pData, &iData); if (cb == (ULONG) -1) return cb; ulSigned = iData & 0x1; iData = iData >> 1; if (ulSigned) { if (cb == 1) { iData |= SIGN_MASK_ONEBYTE; } else if (cb == 2) { iData |= SIGN_MASK_TWOBYTE; } else { iData |= SIGN_MASK_FOURBYTE; } } *pInt = (int)iData; return cb; } // uncompress encoded element type FORCEINLINE CorElementType CorSigUncompressElementType( // Element type PCCOR_SIGNATURE & pData) // [IN,OUT] Compressed data { return (CorElementType)*pData++; } inline ULONG CorSigUncompressElementType( // Return number of bytes of that compressed data occupied in pData PCCOR_SIGNATURE pData, // [IN] Compressed data CorElementType * pElementType) // [OUT] The expanded *pData { *pElementType = (CorElementType)(*pData & 0x7f); return 1; } ///////////////////////////////////////////////////////////////////////////////////////////// // // Given an uncompressed unsigned integer (iLen), Store it to pDataOut in a compressed format. // Return value is the number of bytes that the integer occupies in the compressed format. // It is caller's responsibilityt to ensure *pDataOut has at least 4 bytes to write to. // // Note that this function returns -1 if iLen is too big to be compressed. We currently can // only represent to 0x1FFFFFFF. // ///////////////////////////////////////////////////////////////////////////////////////////// inline ULONG CorSigCompressData( // return number of bytes that compressed form of iLen will take ULONG iLen, // [IN] given uncompressed data void * pDataOut) // [OUT] buffer where iLen will be compressed and stored. { BYTE *pBytes = reinterpret_cast(pDataOut); if (iLen <= 0x7F) { *pBytes = BYTE(iLen); return 1; } if (iLen <= 0x3FFF) { *pBytes = BYTE((iLen >> 8) | 0x80); *(pBytes+1) = BYTE(iLen & 0xff); return 2; } if (iLen <= 0x1FFFFFFF) { *pBytes = BYTE((iLen >> 24) | 0xC0); *(pBytes+1) = BYTE((iLen >> 16) & 0xff); *(pBytes+2) = BYTE((iLen >> 8) & 0xff); *(pBytes+3) = BYTE(iLen & 0xff); return 4; } return (ULONG) -1; } // compress a token // The least significant bit of the first compress byte will indicate the token type. // inline ULONG CorSigCompressToken( // return number of bytes that compressed form of the token will take mdToken tk, // [IN] given token void * pDataOut) // [OUT] buffer where the token will be compressed and stored. { RID rid = RidFromToken(tk); ULONG32 ulTyp = TypeFromToken(tk); if (rid > 0x3FFFFFF) // token is too big to be compressed return (ULONG) -1; rid = (rid << 2); // TypeDef is encoded with low bits 00 // TypeRef is encoded with low bits 01 // TypeSpec is encoded with low bits 10 // BaseType is encoded with low bit 11 // if (ulTyp == CorSigDecodeTokenType(1)) { // make the last two bits 01 rid |= 0x1; } else if (ulTyp == CorSigDecodeTokenType(2)) { // make last two bits 0 rid |= 0x2; } else if (ulTyp == CorSigDecodeTokenType(3)) { rid |= 0x3; } return CorSigCompressData((ULONG)rid, pDataOut); } // compress a signed integer // The least significant bit of the first compress byte will be the signed bit. // inline ULONG CorSigCompressSignedInt( // return number of bytes that compressed form of iData will take int iData, // [IN] given integer void * pDataOut) // [OUT] buffer where iLen will be compressed and stored. { ULONG isSigned = 0; BYTE *pBytes = reinterpret_cast(pDataOut); if (iData < 0) isSigned = 0x1; // Note that we cannot use code:CorSigCompressData to pack the iData value, because of negative values // like: 0xffffe000 (-8192) which has to be encoded as 1 in 2 bytes, i.e. 0x81 0x00 // However CorSigCompressedData would store value 1 as 1 byte: 0x01 if ((iData & SIGN_MASK_ONEBYTE) == 0 || (iData & SIGN_MASK_ONEBYTE) == SIGN_MASK_ONEBYTE) { iData = (int)((iData & ~SIGN_MASK_ONEBYTE) << 1 | isSigned); //_ASSERTE(iData <= 0x7f); *pBytes = BYTE(iData); return 1; } else if ((iData & SIGN_MASK_TWOBYTE) == 0 || (iData & SIGN_MASK_TWOBYTE) == SIGN_MASK_TWOBYTE) { iData = (int)((iData & ~SIGN_MASK_TWOBYTE) << 1 | isSigned); //_ASSERTE(iData <= 0x3fff); *pBytes = BYTE((iData >> 8) | 0x80); *(pBytes + 1) = BYTE(iData & 0xff); return 2; } else if ((iData & SIGN_MASK_FOURBYTE) == 0 || (iData & SIGN_MASK_FOURBYTE) == SIGN_MASK_FOURBYTE) { iData = (int)((iData & ~SIGN_MASK_FOURBYTE) << 1 | isSigned); //_ASSERTE(iData <= 0x1FFFFFFF); *pBytes = BYTE((iData >> 24) | 0xC0); *(pBytes + 1) = BYTE((iData >> 16) & 0xff); *(pBytes + 2) = BYTE((iData >> 8) & 0xff); *(pBytes + 3) = BYTE(iData & 0xff); return 4; } // Out of compressible range return (ULONG)-1; } // CorSigCompressSignedInt // uncompress encoded element type inline ULONG CorSigCompressElementType( // return number of bytes of that compressed data occupied in pData CorElementType et, // [OUT] the expanded *pData void * pData) // [IN] compressed data { BYTE *pBytes = (BYTE *)(pData); *pBytes = BYTE(et); return 1; } // Compress a pointer (used for internal element types only, never for persisted // signatures). inline ULONG CorSigCompressPointer( // return number of bytes of that compressed data occupied void * pvPointer, // [IN] given uncompressed data void * pData) // [OUT] buffer where iLen will be compressed and stored. { *((void * UNALIGNED *)pData) = pvPointer; return sizeof(void *); } // Uncompress a pointer (see above for comments). inline ULONG CorSigUncompressPointer( // return number of bytes of that compressed data occupied PCCOR_SIGNATURE pData, // [IN] compressed data void ** ppvPointer) // [OUT] the expanded *pData { *ppvPointer = *(void * const UNALIGNED *)pData; return sizeof(void *); } #endif // __cplusplus #endif // _COR_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corcompile.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*****************************************************************************\ * * * CorCompile.h - EE / Compiler interface * * * * Version 1.0 * ******************************************************************************* * * * * * * \*****************************************************************************/ #ifndef _COR_COMPILE_H_ #define _COR_COMPILE_H_ #include #include #include #include #include #include #include #include #include typedef DPTR(struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE) PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE; typedef DPTR(struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY) PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY; typedef DPTR(struct CORCOMPILE_EXCEPTION_CLAUSE) PTR_CORCOMPILE_EXCEPTION_CLAUSE; typedef DPTR(struct CORCOMPILE_EXTERNAL_METHOD_DATA_ENTRY) PTR_CORCOMPILE_EXTERNAL_METHOD_DATA_ENTRY; typedef DPTR(struct READYTORUN_IMPORT_SECTION) PTR_READYTORUN_IMPORT_SECTION; inline ReadyToRunImportSectionFlags operator |( const ReadyToRunImportSectionFlags left, const ReadyToRunImportSectionFlags right) { return static_cast(static_cast(left) | static_cast(right)); } inline ReadyToRunImportSectionFlags operator &( const ReadyToRunImportSectionFlags left, const ReadyToRunImportSectionFlags right) { return static_cast(static_cast(left) & static_cast(right)); } inline ReadyToRunCrossModuleInlineFlags operator |( const ReadyToRunCrossModuleInlineFlags left, const ReadyToRunCrossModuleInlineFlags right) { return static_cast(static_cast(left) | static_cast(right)); } inline ReadyToRunCrossModuleInlineFlags operator &( const ReadyToRunCrossModuleInlineFlags left, const ReadyToRunCrossModuleInlineFlags right) { return static_cast(static_cast(left) & static_cast(right)); } #ifdef TARGET_X86 typedef DPTR(RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; // Chained unwind info. Used for cold methods. #ifdef HOST_X86 #define RUNTIME_FUNCTION_INDIRECT 0x80000000 #else // If not hosted on X86, undefine RUNTIME_FUNCTION_INDIRECT as it likely isn't correct #ifdef RUNTIME_FUNCTION_INDIRECT #undef RUNTIME_FUNCTION_INDIRECT #endif // RUNTIME_FUNCTION_INDIRECT #endif // HOST_X86 #endif // TARGET_X86 typedef DPTR(struct CORCOMPILE_RUNTIME_DLL_INFO) PTR_CORCOMPILE_RUNTIME_DLL_INFO; typedef DPTR(struct COR_ILMETHOD) PTR_COR_ILMETHOD; // // GCRefMap blob starts with DWORDs lookup index of relative offsets into the blob. This lookup index is used to limit amount // of linear scanning required to find entry in the GCRefMap. The size of this lookup index is // / GCREFMAP_LOOKUP_STRIDE. // #define GCREFMAP_LOOKUP_STRIDE 1024 enum CORCOMPILE_GCREFMAP_TOKENS { GCREFMAP_SKIP = 0, GCREFMAP_REF = 1, GCREFMAP_INTERIOR = 2, GCREFMAP_METHOD_PARAM = 3, GCREFMAP_TYPE_PARAM = 4, GCREFMAP_VASIG_COOKIE = 5, }; // Tags for fixup blobs enum CORCOMPILE_FIXUP_BLOB_KIND { ENCODE_NONE = 0, ENCODE_MODULE_OVERRIDE = 0x80, /* When the high bit is set, override of the module immediately follows */ ENCODE_DICTIONARY_LOOKUP_THISOBJ = 0x07, ENCODE_DICTIONARY_LOOKUP_TYPE = 0x08, ENCODE_DICTIONARY_LOOKUP_METHOD = 0x09, ENCODE_TYPE_HANDLE = 0x10, /* Type handle */ ENCODE_METHOD_HANDLE, /* Method handle */ ENCODE_FIELD_HANDLE, /* Field handle */ ENCODE_METHOD_ENTRY, /* For calling a method entry point */ ENCODE_METHOD_ENTRY_DEF_TOKEN, /* Smaller version of ENCODE_METHOD_ENTRY - method is def token */ ENCODE_METHOD_ENTRY_REF_TOKEN, /* Smaller version of ENCODE_METHOD_ENTRY - method is ref token */ ENCODE_VIRTUAL_ENTRY, /* For invoking a virtual method */ ENCODE_VIRTUAL_ENTRY_DEF_TOKEN, /* Smaller version of ENCODE_VIRTUAL_ENTRY - method is def token */ ENCODE_VIRTUAL_ENTRY_REF_TOKEN, /* Smaller version of ENCODE_VIRTUAL_ENTRY - method is ref token */ ENCODE_VIRTUAL_ENTRY_SLOT, /* Smaller version of ENCODE_VIRTUAL_ENTRY - type & slot */ ENCODE_READYTORUN_HELPER, /* ReadyToRun helper */ ENCODE_STRING_HANDLE, /* String token */ ENCODE_NEW_HELPER, /* Dynamically created new helpers */ ENCODE_NEW_ARRAY_HELPER, ENCODE_ISINSTANCEOF_HELPER, /* Dynamically created casting helper */ ENCODE_CHKCAST_HELPER, ENCODE_FIELD_ADDRESS, /* For accessing a cross-module static fields */ ENCODE_CCTOR_TRIGGER, /* Static constructor trigger */ ENCODE_STATIC_BASE_NONGC_HELPER, /* Dynamically created static base helpers */ ENCODE_STATIC_BASE_GC_HELPER, ENCODE_THREAD_STATIC_BASE_NONGC_HELPER, ENCODE_THREAD_STATIC_BASE_GC_HELPER, ENCODE_FIELD_BASE_OFFSET, /* Field base */ ENCODE_FIELD_OFFSET, ENCODE_TYPE_DICTIONARY, ENCODE_METHOD_DICTIONARY, ENCODE_CHECK_TYPE_LAYOUT, ENCODE_CHECK_FIELD_OFFSET, ENCODE_DELEGATE_CTOR, ENCODE_DECLARINGTYPE_HANDLE, ENCODE_INDIRECT_PINVOKE_TARGET, /* For calling a pinvoke method ptr indirectly */ ENCODE_PINVOKE_TARGET, /* For calling a pinvoke method ptr */ ENCODE_CHECK_INSTRUCTION_SET_SUPPORT, /* Define the set of instruction sets that must be supported/unsupported to use the fixup */ ENCODE_VERIFY_FIELD_OFFSET, /* Used for the R2R compiler can generate a check against the real field offset used at runtime */ ENCODE_VERIFY_TYPE_LAYOUT, /* Used for the R2R compiler can generate a check against the real type layout used at runtime */ ENCODE_CHECK_VIRTUAL_FUNCTION_OVERRIDE, /* Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, code will not be used */ ENCODE_VERIFY_VIRTUAL_FUNCTION_OVERRIDE, /* Generate a runtime check to ensure that virtual function resolution has equivalent behavior at runtime as at compile time. If not equivalent, generate runtime failure. */ ENCODE_CHECK_IL_BODY, /* Check to see if an IL method is defined the same at runtime as at compile time. A failed match will cause code not to be used. */ ENCODE_VERIFY_IL_BODY, /* Verify an IL body is defined the same at compile time and runtime. A failed match will cause a hard runtime failure. */ ENCODE_MODULE_HANDLE = 0x50, /* Module token */ ENCODE_STATIC_FIELD_ADDRESS, /* For accessing a static field */ ENCODE_MODULE_ID_FOR_GENERIC_STATICS, /* For accessing static fields */ ENCODE_CLASS_ID_FOR_STATICS, /* For accessing static fields */ ENCODE_SYNC_LOCK, /* For synchronizing access to a type */ ENCODE_PROFILING_HANDLE, /* For the method's profiling counter */ ENCODE_VARARGS_METHODDEF, /* For calling a varargs method */ ENCODE_VARARGS_METHODREF, ENCODE_VARARGS_SIG, }; enum EncodeMethodSigFlags { ENCODE_METHOD_SIG_UnboxingStub = 0x01, ENCODE_METHOD_SIG_InstantiatingStub = 0x02, ENCODE_METHOD_SIG_MethodInstantiation = 0x04, ENCODE_METHOD_SIG_SlotInsteadOfToken = 0x08, ENCODE_METHOD_SIG_MemberRefToken = 0x10, ENCODE_METHOD_SIG_Constrained = 0x20, ENCODE_METHOD_SIG_OwnerType = 0x40, ENCODE_METHOD_SIG_UpdateContext = 0x80, }; enum EncodeFieldSigFlags { ENCODE_FIELD_SIG_IndexInsteadOfToken = 0x08, ENCODE_FIELD_SIG_MemberRefToken = 0x10, ENCODE_FIELD_SIG_OwnerType = 0x40, }; class SBuffer; class SigBuilder; class PEDecoder; class GCRefMapBuilder; //REVIEW: include for ee exception info #include "eexcp.h" struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY { DWORD MethodStartRVA; DWORD ExceptionInfoRVA; }; struct CORCOMPILE_EXCEPTION_LOOKUP_TABLE { // pointer to the first element of m_numLookupEntries elements CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY m_Entries[1]; CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY* ExceptionLookupEntry(unsigned i) { SUPPORTS_DAC_WRAPPER; return &(PTR_CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY(PTR_HOST_MEMBER_TADDR(CORCOMPILE_EXCEPTION_LOOKUP_TABLE,this,m_Entries))[i]); } }; struct CORCOMPILE_EXCEPTION_CLAUSE { CorExceptionFlag Flags; DWORD TryStartPC; DWORD TryEndPC; DWORD HandlerStartPC; DWORD HandlerEndPC; union { mdToken ClassToken; DWORD FilterOffset; }; }; /*********************************************************************************/ // When NGEN install /Profile is run, the ZapProfilingHandleImport fixup table contains // these 5 values per MethodDesc enum { kZapProfilingHandleImportValueIndexFixup = 0, kZapProfilingHandleImportValueIndexEnterAddr = 1, kZapProfilingHandleImportValueIndexLeaveAddr = 2, kZapProfilingHandleImportValueIndexTailcallAddr = 3, kZapProfilingHandleImportValueIndexClientData = 4, kZapProfilingHandleImportValueIndexCount }; #endif /* COR_COMPILE_H_ */ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cordbpriv.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* ------------------------------------------------------------------------- * * cordbpriv.h -- header file for private Debugger data shared by various * Runtime components. * ------------------------------------------------------------------------- */ #ifndef _cordbpriv_h_ #define _cordbpriv_h_ #include "corhdr.h" #include // // Initial value for EnC versions // #define CorDB_DEFAULT_ENC_FUNCTION_VERSION 1 #define CorDB_UNKNOWN_ENC_FUNCTION_VERSION ((SIZE_T)(-1)) enum DebuggerLaunchSetting { DLS_ASK_USER = 0, DLS_ATTACH_DEBUGGER = 1 }; // // Flags used to control the Runtime's debugging modes. These indicate to // the Runtime that it needs to load the Runtime Controller, track data // during JIT's, etc. // enum DebuggerControlFlag { DBCF_NORMAL_OPERATION = 0x0000, DBCF_USER_MASK = 0x00FF, DBCF_GENERATE_DEBUG_CODE = 0x0001, DBCF_ALLOW_JIT_OPT = 0x0008, DBCF_PROFILER_ENABLED = 0x0020, // DBCF_ACTIVATE_REMOTE_DEBUGGING = 0x0040, Deprecated. DO NOT USE DBCF_INTERNAL_MASK = 0xFF00, DBCF_PENDING_ATTACH = 0x0100, DBCF_ATTACHED = 0x0200, DBCF_FIBERMODE = 0x0400 }; // // Flags used to control the debuggable state of modules and // assemblies. // enum DebuggerAssemblyControlFlags { DACF_NONE = 0x00, DACF_USER_OVERRIDE = 0x01, DACF_ALLOW_JIT_OPTS = 0x02, DACF_OBSOLETE_TRACK_JIT_INFO = 0x04, // obsolete in V2.0, we're always tracking. DACF_ENC_ENABLED = 0x08, DACF_IGNORE_PDBS = 0x20, DACF_CONTROL_FLAGS_MASK = 0x2F, DACF_PDBS_COPIED = 0x10, DACF_MISC_FLAGS_MASK = 0x10, }; #endif /* _cordbpriv_h_ */ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cordebug.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** Cordebug.idl - Common Language Runtime Debugging interfaces. ** ** ** *****************************************************************************/ /* ------------------------------------------------------------------------- * * Imported types * ------------------------------------------------------------------------- */ #if !DEFINITIONS_FROM_NON_IMPORTABLE_PLACES cpp_quote("#if 0") import "unknwn.idl"; import "objidl.idl"; typedef UINT32 mdToken; typedef mdToken mdModule; typedef SIZE_T mdScope; typedef mdToken mdTypeDef; typedef mdToken mdSourceFile; typedef mdToken mdMemberRef; typedef mdToken mdMethodDef; typedef mdToken mdFieldDef; typedef mdToken mdSignature; typedef ULONG CorElementType; typedef SIZE_T PCCOR_SIGNATURE; typedef SIZE_T LPDEBUG_EVENT; typedef SIZE_T LPSTARTUPINFOW; typedef SIZE_T LPPROCESS_INFORMATION; typedef const void far *LPCVOID; cpp_quote("#endif") typedef [wire_marshal(unsigned long)] void *HPROCESS; typedef [wire_marshal(unsigned long)] void *HTHREAD; typedef UINT64 TASKID; typedef DWORD CONNID; #endif cpp_quote("#ifndef _COR_IL_MAP") cpp_quote("#define _COR_IL_MAP") // Note that this structure is also defined in CorProf.idl - PROPAGATE CHANGES // BOTH WAYS, or this'll become a really insidious bug some day. typedef struct _COR_IL_MAP { ULONG32 oldOffset; // Old IL offset relative to beginning of function ULONG32 newOffset; // New IL offset relative to beginning of function BOOL fAccurate; // TRUE if mapping is known to be good, FALSE otherwise } COR_IL_MAP; cpp_quote("#endif //_COR_IL_MAP") cpp_quote("#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_") cpp_quote("#define _COR_DEBUG_IL_TO_NATIVE_MAP_") /* ICorDebugCode:: GetILToNativeMapping returns an array of * COR_DEBUG_IL_TO_NATIVE_MAP structures. In order to convey that certain * ranges of native instructions correspond to special regions of code (for * example, the prolog), an entry in the array may have it's ilOffset field set * to one of these values. */ typedef enum CorDebugIlToNativeMappingTypes { NO_MAPPING = -1, PROLOG = -2, EPILOG = -3 } CorDebugIlToNativeMappingTypes; typedef struct COR_DEBUG_IL_TO_NATIVE_MAP { ULONG32 ilOffset; ULONG32 nativeStartOffset; ULONG32 nativeEndOffset; } COR_DEBUG_IL_TO_NATIVE_MAP; cpp_quote("#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_") cpp_quote("#define REMOTE_DEBUGGING_DLL_ENTRY L\"Software\\\\Microsoft\\\\.NETFramework\\\\Debugger\\\\ActivateRemoteDebugging\"") typedef enum CorDebugJITCompilerFlags { CORDEBUG_JIT_DEFAULT = 0x1, // Track info, enable optimizations CORDEBUG_JIT_DISABLE_OPTIMIZATION = 0x3, // Includes track info, disable opts, CORDEBUG_JIT_ENABLE_ENC = 0x7 // Includes track & disable opt & Edit and Continue. } CorDebugJITCompilerFlags; typedef enum CorDebugJITCompilerFlagsDecprecated { CORDEBUG_JIT_TRACK_DEBUG_INFO = 0x1, // Use CORDEBUG_JIT_DEFAULT instead } CorDebugJITCompilerFlagsDeprecated; typedef enum CorDebugNGENPolicy { DISABLE_LOCAL_NIC = 1 // indicates that the native image cache for a modern application should be ignored } CorDebugNGENPolicy; /* ------------------------------------------------------------------------- * * Forward declarations * ------------------------------------------------------------------------- */ #pragma warning(push) #pragma warning(disable:28718) //Unable to annotate as this is not a local interface interface ICorDebug; interface ICorDebugController; interface ICorDebugProcess; interface ICorDebugProcess2; interface ICorDebugAppDomain; interface ICorDebugAssembly; interface ICorDebugAssembly2; interface ICorDebugBreakpoint; interface ICorDebugFunctionBreakpoint; interface ICorDebugModuleBreakpoint; interface ICorDebugValueBreakpoint; interface ICorDebugStepper; interface ICorDebugEval; interface ICorDebugEval2; interface ICorDebugThread; interface ICorDebugThread2; interface ICorDebugThread3; interface ICorDebugThread4; interface ICorDebugThread5; interface ICorDebugStackWalk; interface ICorDebugChain; interface ICorDebugFrame; interface ICorDebugILFrame; interface ICorDebugInternalFrame; interface ICorDebugInternalFrame2; interface ICorDebugNativeFrame; interface ICorDebugNativeFrame2; interface ICorDebugRuntimeUnwindableFrame; interface ICorDebugContext; interface ICorDebugModule; interface ICorDebugFunction; interface ICorDebugFunction2; interface ICorDebugCode; interface ICorDebugILCode; interface ICorDebugClass; interface ICorDebugType; interface ICorDebugValue; interface ICorDebugGenericValue; interface ICorDebugReferenceValue; interface ICorDebugHeapValue; interface ICorDebugHeapValue2; interface ICorDebugHeapValue3; interface ICorDebugHeapValue4; interface ICorDebugHandleValue; interface ICorDebugObjectValue; interface ICorDebugStringValue; interface ICorDebugArrayValue; interface ICorDebugEnum; interface ICorDebugObjectEnum; interface ICorDebugProcessEnum; interface ICorDebugBreakpointEnum; interface ICorDebugStepperEnum; interface ICorDebugModuleEnum; interface ICorDebugThreadEnum; interface ICorDebugChainEnum; interface ICorDebugTypeEnum; interface ICorDebugCodeEnum; interface ICorDebugFrameEnum; interface ICorDebugValueEnum; interface ICorDebugVariableHomeEnum; interface ICorDebugAppDomainEnum; interface ICorDebugAssemblyEnum; interface ICorDebugBlockingObjectEnum; interface ICorDebugErrorInfoEnum; interface ICorDebugMDA; /* DEPRECATED */ interface ICorDebugEditAndContinueSnapshot; /* DEPRECATED */ interface ICorDebugEditAndContinueErrorInfo; #pragma warning(pop) // All target addresses in ICorDebug are represented as 0-extended 64-bit integer values. typedef ULONG64 CORDB_ADDRESS; typedef ULONG64 CORDB_REGISTER; typedef DWORD CORDB_CONTINUE_STATUS; typedef enum CorDebugBlockingReason { BLOCKING_NONE = 0x0, BLOCKING_MONITOR_CRITICAL_SECTION = 0x1, BLOCKING_MONITOR_EVENT = 0x2 } CorDebugBlockingReason; typedef struct CorDebugBlockingObject { ICorDebugValue *pBlockingObject; DWORD dwTimeout; CorDebugBlockingReason blockingReason; } CorDebugBlockingObject; typedef struct CorDebugExceptionObjectStackFrame { ICorDebugModule* pModule; CORDB_ADDRESS ip; mdMethodDef methodDef; BOOL isLastForeignExceptionFrame; } CorDebugExceptionObjectStackFrame; typedef struct CorDebugGuidToTypeMapping { GUID iid; ICorDebugType * pType; } CorDebugGuidToTypeMapping; /* * Callback interface for providing access to a particular target process. The * debugging services will call functions on this interface to access memory * and other data in the target process. The debugger client must implement * this interface as appropriate for the particular target (for example, a live * process or a memory dump). The DataTarget will only be invoked from within * the implementation of other ICorDebug APIs (i.e. the debugger client has * control over which thread it is invoked on, and when) * * Error HRESULTS returned by DataTarget APIs will propagate up and be returned * by the active ICorDebug API call. * * The DataTarget implementation must always return up-to-date information * about the target. The target process should be stopped (not changing * in any way) while ICorDebug APIs (and hence DataTarget APIs) are being * called. If the target is a live process and it's state changes, * OpenVirtualProcess needs to be called again to provide a replacement * ICorDebugProcess instance. */ [ object, local, uuid(FE06DC28-49FB-4636-A4A3-E80DB4AE116C), pointer_default(unique) ] interface ICorDebugDataTarget : IUnknown { /* * GetPlatform returns the processor architecture and operating system on * which the target process is (or was) running. * * This is used by ICorDebug to determine details of the target process * such as its pointer size, address space layout, register set, * instruction format, context layout, and calling conventions, etc. * This platforms in this list are the only ones supported by this version * of ICorDebug, but more may be added in future versions. * * Note that this may actually indicate the platform which is being * emulated for the target, not the actual hardware in use. For example, * a process running in the WOW on Windows x64 should use * CORDB_PLATFORM_WINDOWS_X86. * * Implementations should be sure to describe what the platform of the * target actually is, not just what the host expects it to be. * * This function must succeed. If it fails, the DataTarget is unusable. */ typedef enum CorDebugPlatform { CORDB_PLATFORM_WINDOWS_X86, // Windows on Intel x86 CORDB_PLATFORM_WINDOWS_AMD64, // Windows x64 (Amd64, Intel EM64T) CORDB_PLATFORM_WINDOWS_IA64, // Windows on Intel IA-64 CORDB_PLATFORM_MAC_PPC, // Mac OS on PowerPC (Deprecated) CORDB_PLATFORM_MAC_X86, // Mac OS on Intel x86 (Deprecated, use CORDB_PLATFORM_POSIX_X86) CORDB_PLATFORM_WINDOWS_ARM, // Windows on ARM CORDB_PLATFORM_MAC_AMD64, // Mac OS on Intel x64 (Deprecated, use CORDB_PLATFORM_POSIX_AMD64) CORDB_PLATFORM_WINDOWS_ARM64, // Windows on ARM64 CORDB_PLATFORM_POSIX_AMD64, // Posix supporting OS on Intel x64 CORDB_PLATFORM_POSIX_X86, // Posix supporting OS on Intel x86 CORDB_PLATFORM_POSIX_ARM, // Posix supporting OS on ARM32 CORDB_PLATFORM_POSIX_ARM64, // Posix supporting OS on ARM64 CORDB_PLATFORM_POSIX_LOONGARCH64 // Posix supporting OS on LoongArch64 } CorDebugPlatform; HRESULT GetPlatform([out] CorDebugPlatform * pTargetPlatform); /* * ReadVirtual - Read virtual memory from the target process. * * Requests contiguous memory starting at the specified target address to * be read from the target process into the supplied buffer. If at least * the first byte (at the specified start address) can be read, the call * should return success (to support efficient reading of data structures * with self-describing length, like null-terminated strings). * * On success, the actual number of bytes read must be stored into * pBytesRead. */ HRESULT ReadVirtual([in] CORDB_ADDRESS address, [out, size_is(bytesRequested), length_is(*pBytesRead)] BYTE * pBuffer, [in] ULONG32 bytesRequested, [out] ULONG32 * pBytesRead); /* * GetThreadContext - Get the thread context (register values) for a thread. * * Requests the current thread context for the specified (operating-system * defined) thread identifier. The size and format of the context record * is platform dependant, and is determined by the result of the call to * GetPlatform. * * The context flags specify, in a platform-dependent manor, which portions * of the context should be read. contextSize specifies the size of the * supplied buffer, but the function is free to not fill the whole buffer * if it is possible to determine the actual size from the context. * * On Windows platforms, the buffer must be a CONTEXT structure appropriate * for the machine type specified by GetPlatform. contextFlags has the * same values as the ContextFlags field of CONTEXT. */ HRESULT GetThreadContext([in] DWORD dwThreadID, [in] ULONG32 contextFlags, [in] ULONG32 contextSize, [out, size_is(contextSize)] BYTE * pContext); }; /* * Used to retrieve the debug-symbol information for a static field. */ [ object, local, uuid(CBF9DA63-F68D-4BBB-A21C-15A45EAADF5B), pointer_default(unique) ] interface ICorDebugStaticFieldSymbol : IUnknown { /* * GetName - gives the name of the static field */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetSize - gives the size of the static field */ HRESULT GetSize([out] ULONG32 *pcbSize); /* * GetAddress - gives the RVA of the static field */ HRESULT GetAddress([out] CORDB_ADDRESS *pRVA); } /* * Used to retrieve the debug-symbol information for an instance field. */ [ object, local, uuid(A074096B-3ADC-4485-81DA-68C7A4EA52DB), pointer_default(unique) ] interface ICorDebugInstanceFieldSymbol : IUnknown { /* * GetName - gives the name of the instance field */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetSize - gives the size of the instance field */ HRESULT GetSize([out] ULONG32 *pcbSize); /* * GetOffset - gives the offset of the instance field in its parent class */ HRESULT GetOffset([out] ULONG32 *pcbOffset); } /* * Used to retrieve the debug-symbol information for a variable. */ [ object, local, uuid(707E8932-1163-48D9-8A93-F5B1F480FBB7), pointer_default(unique) ] interface ICorDebugVariableSymbol : IUnknown { /* * GetName - gives the name of the variable */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetSize - gives the size of a variable */ HRESULT GetSize([out] ULONG32 *pcbValue); /* * GetValue - Used to get the value of a variable as a byte array. * * offset: read the value starting at this offset in variable, this is used when reading member fields in an object * context: thread context used to read the value * cbContext: size of thread context * * cbValue: size of pValue buffer * pcbValue: size of pValue buffer filled with value * pValue: buffer used to hold the read value */ HRESULT GetValue([in] ULONG32 offset, [in] ULONG32 cbContext, [in, size_is(cbContext)] BYTE context[], [in] ULONG32 cbValue, [out] ULONG32 *pcbValue, [out, size_is(cbValue), length_is(*pcbValue)] BYTE pValue[]); /* * SetValue - Given a byte array, sets it as the value of the variable. * * offset: set the value starting at this offset in variable, this is used when writing member fields in an object * threadID: thread id used to indentify the thread whose context must be updated to reflect the new value * context: thread context used to write the value * cbContext: size of thread context * * cbValue: size of pValue buffer * pValue: buffer to hold the value to set */ HRESULT SetValue([in] ULONG32 offset, [in] DWORD threadID, [in] ULONG32 cbContext, [in, size_is(cbContext)] BYTE context[], [in] ULONG32 cbValue, [in, size_is(cbValue)] BYTE pValue[]); /* * GetSlotIndex - Gives the managed slot-index of a local variable. * This slot-index can be used to retrieve the metadata information for this local. * * Returns E_FAIL if the variable is a function argument. */ HRESULT GetSlotIndex([out] ULONG32 *pSlotIndex); } /* * Represents an in-memory buffer. */ [ object, uuid(677888B3-D160-4B8C-A73B-D79E6AAA1D13), local, pointer_default(unique) ] interface ICorDebugMemoryBuffer : IUnknown { /* * GetStartAddress - Gives the address where buffer starts. */ HRESULT GetStartAddress([out] LPCVOID *address); /* * GetStartAddress - Gives the size of memory buffer. */ HRESULT GetSize([out] ULONG32 *pcbBufferLength); } /* * Used to get information about a merged assembly. */ [ object, uuid(FAA8637B-3BBE-4671-8E26-3B59875B922A), local, pointer_default(unique) ] interface ICorDebugMergedAssemblyRecord : IUnknown { /* * GetSimpleName - Gives the simple name of the assembly (for example "System.Collections") * These names do not include qualifiers such as file extensions, culture, version, or public key token */ HRESULT GetSimpleName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetVersion - Gives the assembly version information */ HRESULT GetVersion([out] USHORT *pMajor, [out] USHORT *pMinor, [out] USHORT *pBuild, [out] USHORT *pRevision); /* * GetCulture - Gives culture string for the assembly (for example "neutral" or "en-US") */ HRESULT GetCulture([in] ULONG32 cchCulture, [out] ULONG32 *pcchCulture, [out, size_is(cchCulture), length_is(*pcchCulture)] WCHAR szCulture[]); /* * GetPublicKey - Gives the assembly public key */ HRESULT GetPublicKey([in] ULONG32 cbPublicKey, [out] ULONG32 *pcbPublicKey, [out, size_is(cbPublicKey), length_is(*pcbPublicKey)] BYTE pbPublicKey[]); /* * GetPublicKeyToken - Gives the assembly public key token (the last 8 bytes of a SHA1 hash of the public key) */ HRESULT GetPublicKeyToken([in] ULONG32 cbPublicKeyToken, [out] ULONG32 *pcbPublicKeyToken, [out, size_is(cbPublicKeyToken), length_is(*pcbPublicKeyToken)] BYTE pbPublicKeyToken[]); /* * GetIndex - Gives prefix index used to prevent name collisions in the merged metadata type names */ HRESULT GetIndex([out] ULONG32 *pIndex); } /* * Used to retrieve debug symbol information. */ [ object, uuid(3948A999-FD8A-4C38-A708-8A71E9B04DBB), local, pointer_default(unique) ] interface ICorDebugSymbolProvider : IUnknown { /* * GetStaticFieldSymbols - given a typespec signature, gives back its static field symbols */ HRESULT GetStaticFieldSymbols([in] ULONG32 cbSignature, [in, size_is(cbSignature)] BYTE typeSig[], [in] ULONG32 cRequestedSymbols, [out] ULONG32 *pcFetchedSymbols, [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugStaticFieldSymbol *pSymbols[]); /* * GetInstanceFieldSymbols - given a typespec signature, gives back its instance field symbols */ HRESULT GetInstanceFieldSymbols([in] ULONG32 cbSignature, [in, size_is(cbSignature)] BYTE typeSig[], [in] ULONG32 cRequestedSymbols, [out] ULONG32 *pcFetchedSymbols, [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugInstanceFieldSymbol *pSymbols[]); /* * GetMethodLocalSymbols - given rva in a method, gives back its local symbols */ HRESULT GetMethodLocalSymbols([in] ULONG32 nativeRVA, [in] ULONG32 cRequestedSymbols, [out] ULONG32 *pcFetchedSymbols, [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugVariableSymbol *pSymbols[]); /* * GetMethodParameterSymbols - given rva in a method, gives back its parameter symbols */ HRESULT GetMethodParameterSymbols([in] ULONG32 nativeRVA, [in] ULONG32 cRequestedSymbols, [out] ULONG32 *pcFetchedSymbols, [out, size_is(cRequestedSymbols), length_is(*pcFetchedSymbols)] ICorDebugVariableSymbol *pSymbols[]); /* * GetMergedAssemblyRecords - gets symbol records for all the merged assemblies */ HRESULT GetMergedAssemblyRecords([in] ULONG32 cRequestedRecords, [out] ULONG32 *pcFetchedRecords, [out, size_is(cRequestedRecords), length_is(*pcFetchedRecords)] ICorDebugMergedAssemblyRecord *pRecords[]); /* * GetMethodProps - given an rva in a method, gives back the * pMethodToken - method's token * pcGenericParams - number of generic parameters associated with this method * cbSignature - size of signature array, set to 0 and pass signature as NULL to get the actual size in pcbSignature * pcbSignature - returned size of signature * signature - buffer to hold the type-spec signatures of all generic parameters */ HRESULT GetMethodProps([in] ULONG32 codeRva, [out] mdToken *pMethodToken, [out] ULONG32 *pcGenericParams, [in] ULONG32 cbSignature, [out] ULONG32 *pcbSignature, [out, size_is(cbSignature), length_is(*pcbSignature)] BYTE signature[]); /* * GetTypeProps - given a vtable rva, gives back the * cbSignature - size of signature array, set to 0 and pass signature as NULL to get the actual size in pcbSignature * pcbSignature - returned size of signature * signature - buffer to hold the signature of type corresponding to input vtableRva */ HRESULT GetTypeProps([in] ULONG32 vtableRva, [in] ULONG32 cbSignature, [out] ULONG32 *pcbSignature, [out, size_is(cbSignature), length_is(*pcbSignature)] BYTE signature[]); /* * GetCodeRange - given rva in a method, gives back the method start address and size. */ HRESULT GetCodeRange([in] ULONG32 codeRva, [out] ULONG32* pCodeStartAddress, ULONG32* pCodeSize); /* * GetAssemblyImageBytes - given an RVA in the merged assembly and size, reads data from the merged assembly and gives it back as an ICorDebugMemoryBuffer */ HRESULT GetAssemblyImageBytes([in] CORDB_ADDRESS rva, [in] ULONG32 length, [out] ICorDebugMemoryBuffer** ppMemoryBuffer); /* * GetObjectSize - given a typespec signature, gives back its object size */ HRESULT GetObjectSize([in] ULONG32 cbSignature, [in, size_is(cbSignature)] BYTE typeSig[], [out] ULONG32 *pObjectSize); /* * GetAssemblyImageMetadata - gives back the merged assembly metadata as an ICorDebugMemoryBuffer */ HRESULT GetAssemblyImageMetadata([out] ICorDebugMemoryBuffer** ppMemoryBuffer); } /* * Used to retrieve debug symbol information. */ [ object, uuid(F9801807-4764-4330-9E67-4F685094165E), local, pointer_default(unique) ] interface ICorDebugSymbolProvider2 : IUnknown { /* * Gives back the generic dictionary map as an ICorDebugMemoryBuffer * * At the highest level, the map consists of two sections. * The first section contains a "directory" of all dictionaries (RVA) covered by this map, the second section * is a byte aligned heap with instantiation information starting right after the last directory entry. * Each entry in the "directory" refers to an offset inside the "heap" (relative to the start of the heap). * Please note that it is possible that multiple directory entries point to the same offset into the heap. * * Contents of the map: * * - First 4 bytes: number of RVA/dictionary entries (N) * If the high bit is set, the following N entries are sorted by RVA in ascending order. * * - N 8 byte wide entries, each entry consisting of 2 4-byte entries: * 1st 4 byte entry - RVA: the dictionary's RVA * 2nd 4 byte entry - Offset: an offset relative to the start of the heap. * * - Heap * * The heap's size can be computed be a stream reader by subtracting the directory size + 4. * * The format for each instantiation info in heap is as follows: * - Length of this instantiation info (in bytes, not including this length information) in compressed ECMA metadata format. * - Number of instantiation types (T, in compressed ECMA metadata format) * - T types, each expressed in ECMA type signature format * * The inclusion of the length for each heap element enables simple sorting of the directory section without affecting the heap. */ HRESULT GetGenericDictionaryInfo([out] ICorDebugMemoryBuffer** ppMemoryBuffer); /* * GetFrameProps: * For a given code-rva, gives the method start rva (pCodeStartRva) and parent * frame's start rva (pParentFrameStartRva). * If there is no parent frame, then pParentFrameStartRva is set to 0 */ HRESULT GetFrameProps([in] ULONG32 codeRva, [out] ULONG32 *pCodeStartRva, [out] ULONG32 *pParentFrameStartRva); } /* * Implemented by the debugger and helps in stack unwinding. */ [ object, uuid(F69126B7-C787-4F6B-AE96-A569786FC670), local, pointer_default(unique) ] interface ICorDebugVirtualUnwinder : IUnknown { /* * Get the current context of this unwinder. * * contextBuf is passed in by ICorDebugStackWalk. As unwinding may only restore a subset of the * registers, such as only non-volatile registers, the context may not exactly match the register * state at the time of the actual call. * * Any failing HRESULT received by mscordbi is considered fatal and will cause ICorDebug * APIs to return CORDBG_E_DATA_TARGET_ERROR. */ HRESULT GetContext([in] ULONG32 contextFlags, [in] ULONG32 cbContextBuf, [out] ULONG32* contextSize, [out, size_is(cbContextBuf)] BYTE contextBuf[]); /* * Advances to the callers context. * * If a failing HRESULT is returned ICorDebug APIs will return CORDBG_E_DATA_TARGET_ERROR. * If the unwind can not be completed because there are no more frames the unwinder should * return CORDBG_S_AT_END_OF_STACK. * If the unwind occurred successfully return S_OK. * * The stackwalker should ensure forward progress is being made, so that eventually a call * to Next() will return a failing HRESULT or CORDBG_S_AT_END_OF_STACK. Returning S_OK * indefinitely may cause an infinite loop. */ HRESULT Next(); } [ object, uuid(2eb364da-605b-4e8d-b333-3394c4828d41), local, pointer_default(unique) ] interface ICorDebugDataTarget2 : IUnknown { /* * GetImageFromPointer: * Given address in a module, gives back the module base address and size. */ HRESULT GetImageFromPointer([in] CORDB_ADDRESS addr, [out] CORDB_ADDRESS *pImageBase, [out] ULONG32 *pSize); /* * GetImageLocation: * Given module base address, gives back the module's path. */ HRESULT GetImageLocation([in] CORDB_ADDRESS baseAddress, [in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetImageLocation: * Given address in a module, gives back a symbol-provider for the module. */ HRESULT GetSymbolProviderForImage([in] CORDB_ADDRESS imageBaseAddress, [out] ICorDebugSymbolProvider **ppSymProvider); /* * EnumerateThreadIDs: * Gives back the list of active thread ids. */ HRESULT EnumerateThreadIDs([in] ULONG32 cThreadIds, [out] ULONG32 *pcThreadIds, [out, size_is(cThreadIds), length_is(*pcThreadIds)] ULONG32 pThreadIds[]); /* * CreateVirtualUnwinder: * Create a new stack unwinder that starts unwinding from initialContext (which isn't * necessarily the leaf of a thread). * Any failing HRESULT received by mscordbi is considered fatal and will cause ICorDebug * APIs to return CORDBG_E_DATA_TARGET_ERROR. */ HRESULT CreateVirtualUnwinder([in] DWORD nativeThreadID, [in] ULONG32 contextFlags, [in] ULONG32 cbContext, [in, size_is(cbContext)] BYTE initialContext[], [out] ICorDebugVirtualUnwinder ** ppUnwinder); }; /* * Provides the information about a loaded module. * Note that this interface is implemented by debugger and is used by DBI to get * the loaded module information from debugger. */ [ object, uuid(817F343A-6630-4578-96C5-D11BC0EC5EE2), local, pointer_default(unique) ] interface ICorDebugLoadedModule : IUnknown { /* * gives the base address */ HRESULT GetBaseAddress([out] CORDB_ADDRESS *pAddress); /* * gives the module name */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * gives the module size */ HRESULT GetSize([out] ULONG32 *pcBytes); }; [ object, uuid(D05E60C3-848C-4E7D-894E-623320FF6AFA), local, pointer_default(unique) ] interface ICorDebugDataTarget3 : IUnknown { /* * gives back the list of modules loaded so far. */ HRESULT GetLoadedModules([in] ULONG32 cRequestedModules, [out] ULONG32 *pcFetchedModules, [out, size_is(cRequestedModules), length_is(*pcFetchedModules)] ICorDebugLoadedModule *pLoadedModules[]); }; /* * Data target that knows how to obtain debugee's process id. * Debugee is not necessarily a living process at that time or on the same machine. */ [ object, uuid(E799DC06-E099-4713-BDD9-906D3CC02CF2), local, pointer_default(unique) ] interface ICorDebugDataTarget4 : IUnknown { /* * Unwinds one native stack frame in the target process/thread */ HRESULT VirtualUnwind([in] DWORD threadId, [in] ULONG32 contextSize, [in, out, size_is(contextSize)] BYTE *context); }; /* * Mutable extension to the data target. This version of ICorDebugDataTarget * can be implemented by targets that wish to support modification of the target * process (such as for live invasive debugging). * * All of these APIs are optional in the sense that no core inspection-based * debugging functionality will be lost by not implementing this interface or * by the failure of these methods. Any failure HRESULT from these APIs will * propagate out as the HRESULT from the ICorDebug API call. * * Note that a single ICorDebug API call may result in multiple mutations, * and there is no mechanism for ensuring related mutations are applied * transactionally (all-or-none). This means that if a mutation fails after * others (for the same ICorDebug call) have succeeded, the target process may * be left in an inconsistent state and debugging may become unreliable. */ [ object, uuid(A1B8A756-3CB6-4CCB-979F-3DF999673A59), local, pointer_default(unique) ] interface ICorDebugMutableDataTarget : ICorDebugDataTarget { /* * WriteVirtual - write memory into the target process address space * * Write the specified buffer into the target process at the specified * address. If any bytes cannot be written, the call should fail without * changing any bytes in the target (otherwise the target may be in an * inconsistent state which makes further debugging unreliable). */ HRESULT WriteVirtual([in] CORDB_ADDRESS address, [in, size_is(bytesRequested)] const BYTE * pBuffer, [in] ULONG32 bytesRequested); /* * SetThreadContext - set the context (register values) for a thread. * * Updates the current context for the thread specified by the (OS-defined) * dwThreadID. The format of the context record is determined by the platform * indicated by GetPlatform. On Windows, this is a CONTEXT structure. * contextSize specifies the size of the buffer being passed. */ HRESULT SetThreadContext([in] DWORD dwThreadID, [in] ULONG32 contextSize, [in, size_is(contextSize)] const BYTE * pContext); /* * Invoke to change the continue-status for the outstanding debug-event on * the specified thread. * * Arguments: * dwThreadId - OS Thread Id of the debug event * continueStatus - New continue status being requested. See the * definition of CORDB_CONTINUE_STATUS for details. * * This API is used when the Debugger makes an ICorDebug API request * which requires the current debug event to be handled in a way that is * potentially different from which it would be otherwise. For example, * if there is an outstanding exception, and the debugger requests an * operation that would cancel the exception (such as SetIp or FuncEval), * than this API is used to request the exception be cancelled. */ HRESULT ContinueStatusChanged([in] DWORD dwThreadId, [in] CORDB_CONTINUE_STATUS continueStatus); }; /* * Interface used by the data access services layer to locate metadata * of assemblies in a target. * * The API client must implement this interface as appropriate for the * particular target (for example, a live process or a memory dump). * */ [ object, local, uuid(7cef8ba9-2ef7-42bf-973f-4171474f87d9), pointer_default(unique) ] interface ICorDebugMetaDataLocator : IUnknown { /* * Ask the debugger to return the full path to a module whose metadata is * needed to complete an operation the debugger requested. * * Arguments: * wszImagePath - This buffer will always contain a NULL-terminated string * representing the full path to the file when available, and the * FileName.extension otherwise. * dwImageTimeStamp - The TimeStamp from the image's PE headers; can * potentially be used for a symsrv lookup. * dwImageSize - Size of the image from PE headers; potentially used for * a symsrv lookup. * cchPathBuffer - The count of WCHARs pointed to by wszPathBuffer. * pcchPathBuffer - When the callee returns E_NOT_SUFFICIENT_BUFFER, contains * the count of WCHARs needed to store the path. * For all other return values, pcchPathBuffer contains the count of * WCHARs written to wszPathBuffer. * wszPathBuffer - Pointer to a buffer into which the debugger will copy * the full path to the file containing the requested metadata. * CorOpenFlags.ofReadOnly access to the metadata in this file will * be requested. * * Assumptions: * The returned file represents a Windows module containing the metadata * needed to complete a request made by the debugger. * * Return Value: * S_OK on success. wszPathBuffer contains the full path to the file and * is NULL-terminated. * * E_NOT_SUFFICIENT_BUFFER if the current size of wszPathBuffer is not * sufficient to hold the full path. pcchPathBuffer will contain the * needed count of WCHARs, including the terminating NULL. * In this case GetMetaData will be called a second time with the * requested buffer size. * * All other failure HRESULTs are interpreted to mean that the file * is not retrievable. * * Notes: * If wszImagePath contains a full path for a module from a dump, that * path will be the path from the machine where the dump was collected. * The file may not exist at this location, or an incorrect file with the * same name may be stored on the path. */ HRESULT GetMetaData( [in] LPCWSTR wszImagePath, [in] DWORD dwImageTimeStamp, [in] DWORD dwImageSize, [in] ULONG32 cchPathBuffer, [out, annotation("_Out_")] ULONG32 * pcchPathBuffer, [out, size_is(cchPathBuffer), length_is(*pcchPathBuffer), annotation("_Out_writes_to_(cchPathBuffer, *pcchPathBuffer) ")] WCHAR wszPathBuffer[]); }; /* ------------------------------------------------------------------------- * * User Callback interface * ------------------------------------------------------------------------- */ #pragma warning(push) #pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugManagedCallback */ /* * ICorDebugManagedCallback is implemented by the user of the * ICorDebug interfaces in order to respond to events in managed code * in the debuggee process. * This interface handles manage debug events from v1.0/v1.1 */ [ object, local, uuid(3d6f5f60-7538-11d3-8d5b-00104b35e7ef), pointer_default(unique) ] interface ICorDebugManagedCallback : IUnknown { /* * All callbacks are called with the process in the synchronized state * All callbacks are serialized, and are called in the same thread. * Each callback implementor must call Continue in a callback to * resume execution. * If Continue is not called before returning, the process will * remain stopped. Continue must later be called before any more * event callbacks will happen. * */ /* * Breakpoint is called when a breakpoint is hit. */ HRESULT Breakpoint([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugBreakpoint *pBreakpoint); /* * StepComplete is called when a step has completed. The stepper * may be used to continue stepping if desired (except for TERMINATE * reasons.) * * STEP_NORMAL means that stepping completed normally, in the same * function. * * STEP_RETURN means that stepping continued normally, after the function * returned. * * STEP_CALL means that stepping continued normally, at the start of * a newly called function. * * STEP_EXCEPTION_FILTER means that control passed to an exception filter * after an exception was thrown. * * STEP_EXCEPTION_HANDLER means that control passed to an exception handler * after an exception was thrown. * * STEP_INTERCEPT means that control passed to an interceptor. * * STEP_EXIT means that the thread exited before the step completed. * No more stepping can be performed with the stepper. */ typedef enum CorDebugStepReason { STEP_NORMAL, STEP_RETURN, STEP_CALL, STEP_EXCEPTION_FILTER, STEP_EXCEPTION_HANDLER, STEP_INTERCEPT, STEP_EXIT } CorDebugStepReason; HRESULT StepComplete([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugStepper *pStepper, [in] CorDebugStepReason reason); /* * Break is called when a break opcode in the code stream is * executed. */ HRESULT Break([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *thread); /* * Exception is called when an exception is thrown from managed * code, The specific exception can be retrieved from the thread object. * * If unhandled is FALSE, this is a "first chance" exception that * hasn't had a chance to be processed by the application. If * unhandled is TRUE, this is an unhandled exception which will * terminate the process. */ HRESULT Exception([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] BOOL unhandled); /* * EvalComplete is called when an evaluation is completed. */ HRESULT EvalComplete([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugEval *pEval); /* * EvalException is called when an evaluation terminates with * an unhandled exception. */ HRESULT EvalException([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugEval *pEval); /* * CreateProcess is called when a process is first attached to or * started. * * This entry point won't be called until the EE is initialized. * Most of the ICorDebug API will return CORDBG_E_NOTREADY prior * to the CreateProcess callback. */ HRESULT CreateProcess([in] ICorDebugProcess *pProcess); /* * ExitProcess is called when a process exits. * * Note: you don't Continue from an ExitProcess event, and this * event may fire asynchronously to other events, while the * process appears to be stopped. This can occur if the process * dies while stopped, usually due to some external force. * * If the CLR is already dispatching a managed callback, this event * will be delayed until after that callback has returned. * * This is the only exit/unload event that is guaranteed to get called * on shutdown. */ HRESULT ExitProcess([in] ICorDebugProcess *pProcess); /* * CreateThread is called when a thread first begins executing managed * code. The thread will be positioned immediately at the first * managed code to be executed. */ HRESULT CreateThread([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *thread); /* * ExitThread is called when a thread which has run managed code exits. * Once this callback is fired, the thread no longer will appear in thread enumerations. */ HRESULT ExitThread([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *thread); /* * LoadModule is called when a Common Language Runtime module is successfully * loaded. This is an appropriate time to examine metadata for the * module, set JIT compiler flags, or enable or disable * class loading callbacks for the module. */ HRESULT LoadModule([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugModule *pModule); /* * UnloadModule is called when a Common Language Runtime module (DLL) is unloaded. The module * should not be used after this point. */ HRESULT UnloadModule([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugModule *pModule); /* * LoadClass is called when a class finishes loading. This callback only * occurs if ClassLoading has been enabled for the class's module. * * ClassLoading is always enabled for dynamic modules. This is a good time * to update symbols (ICorDebugModule3::CreateReaderForInMemorySymbols) and * bind breakpoints to newly generated classes in dynamic modules. */ HRESULT LoadClass([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugClass *c); /* * UnloadClass is called immediately before a class is unloaded. The class * should not be referenced after this point. This callback only occurs if * ClassLoading has been enabled for the class's module. */ HRESULT UnloadClass([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugClass *c); /* * DebuggerError is called when an error occurs while attempting to * handle an event from the Common Language Runtime. It is very strongly * advised that debuggers log this message to the end user because * this callback indicates the debugging services have been disabled due to * an error. * * ICorDebugProcess::GetID() will be safe to call, but all other APIs should * not be called and will fail if they are. * This includes ICorDebugProcess::Terminate and ICorDebug Process::Detach. The * debugger should use OS facilities for terminating processes to shut down the process. */ HRESULT DebuggerError([in] ICorDebugProcess *pProcess, [in] HRESULT errorHR, [in] DWORD errorCode); /* * Enum defining log message LoggingLevels */ typedef enum LoggingLevelEnum { LTraceLevel0 = 0, LTraceLevel1, LTraceLevel2, LTraceLevel3, LTraceLevel4, LStatusLevel0 = 20, LStatusLevel1, LStatusLevel2, LStatusLevel3, LStatusLevel4, LWarningLevel = 40, LErrorLevel = 50, LPanicLevel = 100 } LoggingLevelEnum; typedef enum LogSwitchCallReason { SWITCH_CREATE, SWITCH_MODIFY, SWITCH_DELETE } LogSwitchCallReason; /* * LogMessage is called when a Common Language Runtime managed thread calls the Log * class in the System.Diagnostics package to log an event. */ HRESULT LogMessage([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] LONG lLevel, [in] WCHAR *pLogSwitchName, [in] WCHAR *pMessage); /* * LogSwitch is called when a Common Language Runtime managed thread calls the LogSwitch * class in the System.Diagnostics package to create/modify a LogSwitch. */ HRESULT LogSwitch([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] LONG lLevel, [in] ULONG ulReason, [in] WCHAR *pLogSwitchName, [in] WCHAR *pParentName); /* * CreateAppDomain is called when an app domain is created. */ HRESULT CreateAppDomain([in] ICorDebugProcess *pProcess, [in] ICorDebugAppDomain *pAppDomain); /* * ExitAppDomain is called when an app domain exits. */ HRESULT ExitAppDomain([in] ICorDebugProcess *pProcess, [in] ICorDebugAppDomain *pAppDomain); /* * LoadAssembly is called when a Common Language Runtime assembly is successfully * loaded. */ HRESULT LoadAssembly([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugAssembly *pAssembly); /* * UnloadAssembly is called when a Common Language Runtime assembly is unloaded. The assembly * should not be used after this point. */ HRESULT UnloadAssembly([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugAssembly *pAssembly); /* * ControlCTrap is called if a CTRL-C is trapped in the process being * debugged. All appdomains within the process are stopped for * this callback. * Return values: * S_OK : Debugger will handle the ControlC Trap * S_FALSE : Debugger won't handle the ControlC Trap */ HRESULT ControlCTrap([in] ICorDebugProcess *pProcess); /* * NameChange() is called if either an AppDomain's or * Thread's name changes. */ HRESULT NameChange([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread); /* * UpdateModuleSymbols is called when PDB debug symbols are available for an * in-memory module. This is a debugger's chance to load the symbols * (using ISymUnmanagedBinder::GetReaderForStream), and bind source-level * breakpoints for the module. * * This callback is no longer dispatched for dynamic modules. Instead, * debuggers should call ICorDebugModule3::CreateReaderForInMemorySymbols * to obtain a symbol reader for a dynamic module. */ HRESULT UpdateModuleSymbols([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugModule *pModule, [in] IStream *pSymbolStream); /* * DEPRECATED */ HRESULT EditAndContinueRemap([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugFunction *pFunction, [in] BOOL fAccurate); /* * BreakpointSetError is called if the CLR was unable to accuratley bind a breakpoint that * was set before a function was JIT compiled. The given breakpoint will never be hit. The * debugger should deactivate it and rebind it appropiatley. */ HRESULT BreakpointSetError([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugBreakpoint *pBreakpoint, [in] DWORD dwError); }; #pragma warning(pop) #pragma warning(push) [ object, local, uuid(264EA0FC-2591-49AA-868E-835E6515323F), pointer_default(unique) ] interface ICorDebugManagedCallback3 : IUnknown { /* Callback indicating an enabled custom debugger notification has been * raised. pThread points to the thread that issued the notification. * A subsequent call to GetCurrentCustomDebuggerNotification will retrieve the object that was passed to * System.Diagnostics.Debugger.CustomNotification, whose type will be one * that has been enabled via SetEnableCustomNotification. * Note that this will return non-null if and only if we are currently inside a CustomNotification * callback. * The debugger can read type-specific parameters from fields of the data * object, and store responses into fields. * ICorDebug imposes no policy on the types of notifications or their * contents, and their semantics are strictly a contract between * debuggers and applications/frameworks. */ HRESULT CustomNotification([in] ICorDebugThread * pThread, [in] ICorDebugAppDomain * pAppDomain); } [ object, local, uuid(322911AE-16A5-49BA-84A3-ED69678138A3), pointer_default(unique) ] interface ICorDebugManagedCallback4 : IUnknown { // // Callback indicating a garbage collection is about to start. // // Parameters // pProcess - the process that is going to perform garbage collection. // // Returns // S_OK - on success // HRESULT BeforeGarbageCollection([in] ICorDebugProcess* pProcess); // // Callback indicating a garbage collection is about to complete. // // Parameters // pProcess - the process that is going to complete garbage collection. // // Returns // S_OK - on success // HRESULT AfterGarbageCollection([in] ICorDebugProcess* pProcess); // // Callback indicating a data breakpoint is hit // // Parameters // pProcess - the process that hits the data breakpoint // pThread - the thread that hits the data breakpoint // pContext - a pointer to the CONTEXT structure // contextSize - the size of the CONTEXT structure // // Returns // S_OK - on success // HRESULT DataBreakpoint([in] ICorDebugProcess* pProcess, [in] ICorDebugThread* pThread, [in] BYTE* pContext, [in] ULONG32 contextSize); } #pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugManagedCallback2 */ /* * ICorDebugManagedCallback2 is a logical extension to ICorDebugManagedCallback. * This handles new debug events introduced in V2.0. A debugger's callback object * to ICorDebug::SetManagedHandler must implement this interface if it is debugging v2.0 apps. */ [ object, local, uuid(250E5EEA-DB5C-4C76-B6F3-8C46F12E3203), pointer_default(unique) ] interface ICorDebugManagedCallback2 : IUnknown { /* * FunctionRemapOpportunity is fired whenever execution reaches a sequence point in an older version * of an edited function. This event gives the debugger an opportunity to remap the IP to its proper * place in the new version by calling ICorDebugILFrame2::RemapFunction. If the debugger does not call * RemapFunction before calling Continue, the runtime will continue executing the old code and will * fire another FunctionRemapOpportunity callback at the next sequence point */ HRESULT FunctionRemapOpportunity([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugFunction *pOldFunction, [in] ICorDebugFunction *pNewFunction, [in] ULONG32 oldILOffset); /* * CreateConnection is called when a new connection is created. */ HRESULT CreateConnection([in] ICorDebugProcess *pProcess, [in] CONNID dwConnectionId, [in] WCHAR *pConnName); /* * ChangeConnection is called when a connection's set of tasks changes. */ HRESULT ChangeConnection([in] ICorDebugProcess *pProcess, [in] CONNID dwConnectionId ); /* * DestroyConnection is called when a connection is ended. */ HRESULT DestroyConnection([in] ICorDebugProcess *pProcess, [in] CONNID dwConnectionId ); typedef enum CorDebugExceptionCallbackType { DEBUG_EXCEPTION_FIRST_CHANCE = 1, /* Fired when exception thrown */ DEBUG_EXCEPTION_USER_FIRST_CHANCE = 2, /* Fired when search reaches first user code */ DEBUG_EXCEPTION_CATCH_HANDLER_FOUND = 3, /* Fired if & when search finds a handler */ DEBUG_EXCEPTION_UNHANDLED = 4 /* Fired if search doesnt find a handler */ } CorDebugExceptionCallbackType; typedef enum CorDebugExceptionFlags { DEBUG_EXCEPTION_NONE = 0, DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x0001 /* Indicates interceptable exception */ } CorDebugExceptionFlags; /* * Exception is called at various points during the search phase of the * exception-handling process. The exception being processed can be * retrieved from the ICorDebugThread. */ HRESULT Exception( [in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugFrame *pFrame, [in] ULONG32 nOffset, [in] CorDebugExceptionCallbackType dwEventType, [in] DWORD dwFlags ); typedef enum CorDebugExceptionUnwindCallbackType { DEBUG_EXCEPTION_UNWIND_BEGIN = 1, /* Fired at the beginning of the unwind */ DEBUG_EXCEPTION_INTERCEPTED = 2 /* Fired after an exception has been intercepted */ } CorDebugExceptionUnwindCallbackType; /* * For non-intercepted exceptions, ExceptionUnwind is called at the beginning of the second pass * when we start to unwind the stack. For intercepted exceptions, ExceptionUnwind is called when * the interception is complete, conceptually at the end of the second pass. * * dwFlags is not currently used. */ HRESULT ExceptionUnwind( [in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] CorDebugExceptionUnwindCallbackType dwEventType, [in] DWORD dwFlags ); /* * FunctionRemapComplete is fired whenever execution has completed switching over to a * new version of an edited function (as requested by a call to ICorDebugILFrame2::RemapFunction). * At this point (and no sooner) steppers can be added to that new version of the function. */ HRESULT FunctionRemapComplete([in] ICorDebugAppDomain *pAppDomain, [in] ICorDebugThread *pThread, [in] ICorDebugFunction *pFunction); // Notification that an Managed Debug Assistant (MDA) was hit in the debuggee process. // - MDAs are heuristic warnings and do not require any explicit debugger action (other than continue, of course) for proper functionality. // - The CLR can change what MDAs are fired (and what data is in any given MDA) at any point. // - Therefore, debuggers should not build any specific functionality requiring specific MDAs patterns. // - MDAs may be queued and fired "after the fact". This could happen if the runtime needs to slip from when an // MDA occurs to get to a safe point for firing it. It also means the runtime reserves the right to fire a bunch of MDAs // in a single set of callback queue (similar for what we do w/ attach events). // // See the MDA documentation for how to enable / disable notifications. // // Parameters: // - pController is the controller object (process or appdomain) that the MDA occurred in. // Clients should not make any assumption about whether the controller is a process or appdomain (though they can // always QI to find out). // Call continue on this to resume the debuggee. // - pThread - managed thread on which the debug event occurred. If the MDA occurred on an unmanaged thread then // this will be null. Get the OS thread ID from the MDA object itself. // - pMDA is an object containing MDA information. // Suggested usage is that the client does not keep a reference to the MDA object after returning from this callback // because that lets the CLR quickly recycle the MDA's memory. This could be a performance win if there are // lots of MDAs firing. HRESULT MDANotification( [in] ICorDebugController * pController, [in] ICorDebugThread *pThread, [in] ICorDebugMDA * pMDA ); }; #pragma warning(pop) [ object, local, uuid(5263E909-8CB5-11d3-BD2F-0000F80849BD), pointer_default(unique) ] interface ICorDebugUnmanagedCallback : IUnknown { /* * DebugEvent is called when a DEBUG_EVENT is received which is * not directly related to the Common Language Runtime. * * DO NOT USE any parts of the debugging API from the Win32 Event * Thread. Only ICorDebugController::Continue() can be called on * the Win32 Event Thread, and only when continuing from an out-of-band * event. * * This callback is an exception to the rules about callbacks. * When this callback is called, the process will be in the "raw" * OS debug stopped state. The process will not be synchronized. * The process will automatically enter the synchronized state when * necessary to satisfy certain requests for information about * managed code. (Note that this may result in other nested * DebugEvent callbacks.) * * Call ClearCurrentException on the process to ignore an * exception event before continuing the process. (Causes * DBG_CONTINUE to be sent on continue rather than * DBG_EXCEPTION_NOT_HANDLED) * Out-of-band Breakpoint and single-step exceptions are automatically cleared. * * fOutOfBand will be FALSE if the debugging services support * interaction with the process's managed state while the process * is stopped due to this event. fOutOfBand will be TRUE if * interaction with the process's managed state is impossible until * the unmanaged event is continued from. * * Out-Of-Band events can come at anytime; even when there debuggee appears stopped * and even when there's already an outstanding inband event. * * In v2.0, it is strongly recommended that the debugger just immediately * continues OOB breakpoint events. The debugger should be using the ICorDebugProcess2 * SetUnmanagedBreakpoint and ClearUnmanagedBreakpoint APIs to add/remove breakpoints. * Those APIs will already skip over any OOB breakpoints automatically. Thus the only * oob breakpoints that get dispatched should be raw breakpoints already in the * instruction stream (eg, like a call to kernel32!DebugBreak). In these cases, * just continuing past the breakpoint is the correct thing to do. Do not try to use * any other portion of the API like ClearCurrentException or Get/SetThreadContext. * */ HRESULT DebugEvent([in] LPDEBUG_EVENT pDebugEvent, [in] BOOL fOutOfBand); }; /* ------------------------------------------------------------------------- * * Debugger interface * ------------------------------------------------------------------------- */ typedef enum CorDebugCreateProcessFlags { DEBUG_NO_SPECIAL_OPTIONS = 0x0000 } CorDebugCreateProcessFlags; /* ICorDebugHeapValue::CreateHandle takes a handle flavor. * - A strong handle will keep an object alive while allowing GC relocation * - A weak handle will not keep an object alive * - A pinned handle will keep an object alive and disallow GC relocation */ typedef enum CorDebugHandleType { HANDLE_STRONG = 1, HANDLE_WEAK_TRACK_RESURRECTION = 2, HANDLE_PINNED = 3 } CorDebugHandleType; #pragma warning(push) #pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebug */ /* * ICorDebug represents an event processing loop for a debugger process. * * The debugger must wait for the ExitProcess callback from all * processes being debugged before releasing this interface. * * The ICorDebug object is the initial object to control all further managed debugging. * In v1.0 + v1.1, this object was a CoClass created from COM. * In v2.0, this object is no longer a CoClass and must be created from the function: * CreateDebuggingInterfaceFromVersion( * int iDebuggerVersion, // <--- CorDebugVersion_2_0 if Debugger is V2.0 * LPCWSTR szDebuggeeVersion, // <--- version string of debuggee. Eg, "v1.1.4322" * IUnknown ** ppCordb * ) * declared in mscoree.idl. * This new creation function is more version-aware. It allows clients to get a * specific implementation (as specified by szDebuggeeVersion) of ICorDebug, which * also emulates a specific version of the debugging API (as specified by iDebuggerVersion). */ [ object, local, uuid(3d6f5f61-7538-11d3-8d5b-00104b35e7ef), pointer_default(unique) ] interface ICorDebug : IUnknown { /* * The debugger calls this method at creation time to initialize the debugging * services, and must be called at creation time before any other method on * ICorDebug is called. */ HRESULT Initialize(); /* * Terminate must be called when the ICorDebug is no longer needed. * * NOTE: Terminate should not be called until an ExitProcess callback has * been received for all processes being debugged. * */ HRESULT Terminate(); /* * SetManagedHandler should be called at creation time to specify the * event handler object for managed events. * * Returns: * S_OK on success. * E_NOINTERFACE - if pCallback does not implement sufficient interfaces * to receive debug events for the version of the API it requested. * Eg, if debugging a V2.0 app, pCallback must implement ICorDebugManagedCallback2. * */ HRESULT SetManagedHandler([in] ICorDebugManagedCallback *pCallback); /* * SetUnmanagedHandler should be called at creation time to specify the * event handler object for unmanaged events. * * This should be set after Initialize and before any calls to CreateProcess or DebugActiveProcess. * * However, for legacy purposes, it is not absolutely required to set this until * before the first native debug event is fired. Specifically, if CreateProcess has the * CREATE_SUSPENDED flag, native debug events will not be dispatched until the main thread * is resumed. * DebugActiveProcess will dispatch native debug events immediately, and so the unmanaged callback * must be set before DebugActiveProcess is called. * * Returns: * S_OK if callback pointer is successfully updated. * failure on any failure. * */ HRESULT SetUnmanagedHandler([in] ICorDebugUnmanagedCallback *pCallback); /* * CreateProcess launches a process under the control of the debugger * All parameters are the same as the win32 CreateProcess call. * * To enable unmanaged (mixed-mode) debugging, pass * DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS to dwCreationFlags. DEBUG_PROCESS * alone is not supported. If only managed debugging is desired, do not set * these flags. * * The debugger and debuggee share a single console, then it's possible for * the debuggee to hold "console locks" and then get stopped at a debug event. * The debugger will then block trying to use the console. This is only an issue * when interop debugging and if debugger + debuggee share the console. * It is recommended to use the CREATE_NEW_CONSOLE flag to avoid this problem. * */ HRESULT CreateProcess([in] LPCWSTR lpApplicationName, [in] LPWSTR lpCommandLine, [in] LPSECURITY_ATTRIBUTES lpProcessAttributes, [in] LPSECURITY_ATTRIBUTES lpThreadAttributes, [in] BOOL bInheritHandles, [in] DWORD dwCreationFlags, [in] PVOID lpEnvironment, [in] LPCWSTR lpCurrentDirectory, [in] LPSTARTUPINFOW lpStartupInfo, [in] LPPROCESS_INFORMATION lpProcessInformation, [in] CorDebugCreateProcessFlags debuggingFlags, [out] ICorDebugProcess **ppProcess); /* * DebugActiveProcess is used to attach to an existing process. * * If win32Attach is TRUE, then the debugger becomes the Win32 * debugger for the process and will begin dispatching the * unmanaged callbacks. * */ HRESULT DebugActiveProcess([in] DWORD id, [in] BOOL win32Attach, [out] ICorDebugProcess **ppProcess); /* * EnumerateProcesses returns an enum of processes being debugged. * */ HRESULT EnumerateProcesses([out] ICorDebugProcessEnum **ppProcess); /* * GetProcess returns the ICorDebugProcess with the given OS Id. */ HRESULT GetProcess([in] DWORD dwProcessId, [out] ICorDebugProcess **ppProcess); /* * CanLaunchOrAttach returns S_OK if the debugging services believe that * launching a new process or attaching to the given process is possible * given what it knows about the current machine and runtime configuration. * * If you plan to launch with win32 debugging enabled, or to attach with * win32 debugging enabled then pass in TRUE for win32DebuggineEnabled. * The answer may be different if this option will be used. * * Note: the rest of the API will not stop you from launching or attaching * to a process anyway. This function is purely informational. * * Possible HRESULTs: S_OK, CORDBG_E_DEBUGGING_NOT_POSSIBLE, * CORDBG_E_KERNEL_DEBUGGER_PRESENT, CORDBG_E_KERNEL_DEBUGGER_ENABLED * */ HRESULT CanLaunchOrAttach([in] DWORD dwProcessId, [in] BOOL win32DebuggingEnabled); }; #pragma warning(pop) /* * A debugger can implement this interface and pass it to ICorDebugRemote to specify the host name of the * target machine in Mac remote debugging scenarios. This is only supported on Silverlight. */ [ object, local, uuid(C3ED8383-5A49-4cf5-B4B7-01864D9E582D), pointer_default(unique) ] interface ICorDebugRemoteTarget : IUnknown { /* * Return the host name of the target machine. The host name can either be a fully qualified domain name or * an IPv4 address. If cchHostName is 0 and szHostName is NULL, this function just returns the number of * characters including the NULL character in the host name. * * cchHostName is the number of characters in the buffer szHostName. If this is 0, then szHostName must * be NULL. If it is not 0, then szHostName must be non-NULL. * * pcchHostName returns the number of characters including the NULL character in the host name. This can * be NULL. * * szHostName is the buffer for returning the host name. */ HRESULT GetHostName([in] ULONG32 cchHostName, [out, annotation("_Out_")] ULONG32 * pcchHostName, [out, size_is(cchHostName), length_is(*pcchHostName), annotation("_Out_writes_to_opt_(cchHostName, *pcchHostName)")] WCHAR szHostName[]); } /* * A debugger can QI for this interface from an ICorDebug interface in order to specify a target machine in * Mac remote debugging scenarios. This is only supported on Silverlight. */ [ object, local, uuid(D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64), pointer_default(unique) ] interface ICorDebugRemote : IUnknown { HRESULT CreateProcessEx([in] ICorDebugRemoteTarget * pRemoteTarget, [in] LPCWSTR lpApplicationName, [in, annotation("_In_")] LPWSTR lpCommandLine, [in] LPSECURITY_ATTRIBUTES lpProcessAttributes, [in] LPSECURITY_ATTRIBUTES lpThreadAttributes, [in] BOOL bInheritHandles, [in] DWORD dwCreationFlags, [in] PVOID lpEnvironment, [in] LPCWSTR lpCurrentDirectory, [in] LPSTARTUPINFOW lpStartupInfo, [in] LPPROCESS_INFORMATION lpProcessInformation, [in] CorDebugCreateProcessFlags debuggingFlags, [out] ICorDebugProcess ** ppProcess); HRESULT DebugActiveProcessEx([in] ICorDebugRemoteTarget * pRemoteTarget, [in] DWORD dwProcessId, [in] BOOL fWin32Attach, [out] ICorDebugProcess ** ppProcess); } typedef struct _COR_VERSION { DWORD dwMajor; DWORD dwMinor; DWORD dwBuild; DWORD dwSubBuild; } COR_VERSION; [ object, local, uuid(ECCCCF2E-B286-4b3e-A983-860A8793D105), pointer_default(unique) ] /* * Sets the maximum version of the runtime supported by the debugger using this * object. */ interface ICorDebug2 : IUnknown { typedef enum CorDebugInterfaceVersion { CorDebugInvalidVersion = 0, CorDebugVersion_1_0 = CorDebugInvalidVersion + 1, ver_ICorDebugManagedCallback = CorDebugVersion_1_0, ver_ICorDebugUnmanagedCallback = CorDebugVersion_1_0, ver_ICorDebug = CorDebugVersion_1_0, ver_ICorDebugController = CorDebugVersion_1_0, ver_ICorDebugAppDomain = CorDebugVersion_1_0, ver_ICorDebugAssembly = CorDebugVersion_1_0, ver_ICorDebugProcess = CorDebugVersion_1_0, ver_ICorDebugBreakpoint = CorDebugVersion_1_0, ver_ICorDebugFunctionBreakpoint = CorDebugVersion_1_0, ver_ICorDebugModuleBreakpoint = CorDebugVersion_1_0, ver_ICorDebugValueBreakpoint = CorDebugVersion_1_0, ver_ICorDebugStepper = CorDebugVersion_1_0, ver_ICorDebugRegisterSet = CorDebugVersion_1_0, ver_ICorDebugThread = CorDebugVersion_1_0, ver_ICorDebugChain = CorDebugVersion_1_0, ver_ICorDebugFrame = CorDebugVersion_1_0, ver_ICorDebugILFrame = CorDebugVersion_1_0, ver_ICorDebugNativeFrame = CorDebugVersion_1_0, ver_ICorDebugModule = CorDebugVersion_1_0, ver_ICorDebugFunction = CorDebugVersion_1_0, ver_ICorDebugCode = CorDebugVersion_1_0, ver_ICorDebugClass = CorDebugVersion_1_0, ver_ICorDebugEval = CorDebugVersion_1_0, ver_ICorDebugValue = CorDebugVersion_1_0, ver_ICorDebugGenericValue = CorDebugVersion_1_0, ver_ICorDebugReferenceValue = CorDebugVersion_1_0, ver_ICorDebugHeapValue = CorDebugVersion_1_0, ver_ICorDebugObjectValue = CorDebugVersion_1_0, ver_ICorDebugBoxValue = CorDebugVersion_1_0, ver_ICorDebugStringValue = CorDebugVersion_1_0, ver_ICorDebugArrayValue = CorDebugVersion_1_0, ver_ICorDebugContext = CorDebugVersion_1_0, ver_ICorDebugEnum = CorDebugVersion_1_0, ver_ICorDebugObjectEnum = CorDebugVersion_1_0, ver_ICorDebugBreakpointEnum = CorDebugVersion_1_0, ver_ICorDebugStepperEnum = CorDebugVersion_1_0, ver_ICorDebugProcessEnum = CorDebugVersion_1_0, ver_ICorDebugThreadEnum = CorDebugVersion_1_0, ver_ICorDebugFrameEnum = CorDebugVersion_1_0, ver_ICorDebugChainEnum = CorDebugVersion_1_0, ver_ICorDebugModuleEnum = CorDebugVersion_1_0, ver_ICorDebugValueEnum = CorDebugVersion_1_0, ver_ICorDebugCodeEnum = CorDebugVersion_1_0, ver_ICorDebugTypeEnum = CorDebugVersion_1_0, ver_ICorDebugErrorInfoEnum = CorDebugVersion_1_0, ver_ICorDebugAppDomainEnum = CorDebugVersion_1_0, ver_ICorDebugAssemblyEnum = CorDebugVersion_1_0, ver_ICorDebugEditAndContinueErrorInfo = CorDebugVersion_1_0, ver_ICorDebugEditAndContinueSnapshot = CorDebugVersion_1_0, CorDebugVersion_1_1 = CorDebugVersion_1_0 + 1, // no interface definitions in v1.1 CorDebugVersion_2_0 = CorDebugVersion_1_1 + 1, ver_ICorDebugManagedCallback2 = CorDebugVersion_2_0, ver_ICorDebugAppDomain2 = CorDebugVersion_2_0, ver_ICorDebugAssembly2 = CorDebugVersion_2_0, ver_ICorDebugProcess2 = CorDebugVersion_2_0, ver_ICorDebugStepper2 = CorDebugVersion_2_0, ver_ICorDebugRegisterSet2 = CorDebugVersion_2_0, ver_ICorDebugThread2 = CorDebugVersion_2_0, ver_ICorDebugILFrame2 = CorDebugVersion_2_0, ver_ICorDebugInternalFrame = CorDebugVersion_2_0, ver_ICorDebugModule2 = CorDebugVersion_2_0, ver_ICorDebugFunction2 = CorDebugVersion_2_0, ver_ICorDebugCode2 = CorDebugVersion_2_0, ver_ICorDebugClass2 = CorDebugVersion_2_0, ver_ICorDebugValue2 = CorDebugVersion_2_0, ver_ICorDebugEval2 = CorDebugVersion_2_0, ver_ICorDebugObjectValue2 = CorDebugVersion_2_0, // CLR v4 - next major CLR version after CLR v2 // Includes Silverlight 4 CorDebugVersion_4_0 = CorDebugVersion_2_0 + 1, ver_ICorDebugThread3 = CorDebugVersion_4_0, ver_ICorDebugThread4 = CorDebugVersion_4_0, ver_ICorDebugStackWalk = CorDebugVersion_4_0, ver_ICorDebugNativeFrame2 = CorDebugVersion_4_0, ver_ICorDebugInternalFrame2 = CorDebugVersion_4_0, ver_ICorDebugRuntimeUnwindableFrame = CorDebugVersion_4_0, ver_ICorDebugHeapValue3 = CorDebugVersion_4_0, ver_ICorDebugBlockingObjectEnum = CorDebugVersion_4_0, ver_ICorDebugValue3 = CorDebugVersion_4_0, CorDebugVersion_4_5 = CorDebugVersion_4_0 + 1, ver_ICorDebugComObjectValue = CorDebugVersion_4_5, ver_ICorDebugAppDomain3 = CorDebugVersion_4_5, ver_ICorDebugCode3 = CorDebugVersion_4_5, ver_ICorDebugILFrame3 = CorDebugVersion_4_5, CorDebugLatestVersion = CorDebugVersion_4_5 } CorDebugInterfaceVersion; }; /* ------------------------------------------------------------------------- * * Controller interface * ------------------------------------------------------------------------- */ /* * A thread's DebugState determines whether the debugger lets a thread * run or not. Possible states are: * * THREAD_RUN - thread runs freely, unless a debug event occurs * THREAD_SUSPEND - thread cannot run. * * NOTE: We allow for message pumping via a callback provided to the Hosting * API, thus we don't need an 'interrupted' state here. */ typedef enum CorDebugThreadState { THREAD_RUN, THREAD_SUSPEND } CorDebugThreadState; /* * ICorDebugController represents a scope at which program execution context * can be controlled. It represents either a process or an app domain. * * If this is the controller of a process, this controller affects all * threads in the process. Otherwise it just affects the threads of * a particular app domain */ [ object, local, uuid(3d6f5f62-7538-11d3-8d5b-00104b35e7ef), pointer_default(unique) ] interface ICorDebugController : IUnknown { /* * Stop performs a cooperative stop on all threads running managed * code in the process. When managed-only debugging, unmanaged threads may continue * to run (but will be blocked when trying to call managed code). When-interop debugging, * unmanaged threads will also be stopped. * The timeout value is currently ignored and treated as INFINTE (-1). * If the cooperative stop fails due to a deadlock, all threads are suspended (and E_TIMEOUT is returned) * * NOTE: This function is the one function in the debugging API * that is synchronous. When Stop returns with S_OK, the process * is stopped. (No callback will be given to notify of the stop.) * The debugger must call Continue when it wishes to allow * the process to resume running. * * The debugger maintains a "stop-counter". When the counter goes to zero, the * Controller is resumed. Each call to Stop() or each dispatched callback will increment * the counter. Each call to continue will decrement the counter. */ HRESULT Stop([in] DWORD dwTimeoutIgnored); /* * Continue continues the process after a call to Stop. * * Continue continues the process. fIsOutOfBand is set to TRUE * if continuing from an unmanaged event that was sent with the * fOutOfBand flag in the unmanaged callback and it is set to * FALSE if continuing from a managed event or a normal * unmanaged event. * * When doing mixed-mode debugging, Continue cannot be called on * the Win32 Event Thread unless it is continuing from an * out-of-band event. */ HRESULT Continue([in] BOOL fIsOutOfBand); /* * IsRunning returns TRUE if the threads in the process are running freely. * */ HRESULT IsRunning([out] BOOL *pbRunning); /* * HasQueuedCallbacks returns TRUE if there are currently managed * callbacks which are queued up for the given thread. These * callbacks will be dispatched one at a time, each time Continue * is called. * * The debugger can check this flag if it wishes to report multiple * debugging events which occur simultaneously. * * If NULL is given for the pThread parameter, HasQueuedCallbacks * will return TRUE if there are currently managed callbacks * queued for any thread. * * Note that once debug events have been queued, they've already occurred, * and so the debugger must drain the entire queue to be sure of the state * of the debuggee. For example, if the queue contains 2 debug events on thread X, * and the debugger suspends thread X after the 1st debug event and then calls continue, * the 2nd debug event for thread X will still be dispatched even though the thread * is suspended. * */ HRESULT HasQueuedCallbacks([in] ICorDebugThread *pThread, [out] BOOL *pbQueued); /* * EnumerateThreads returns an enum of all managed threads active in the process. * A thread is considered Managed threads after the CreateThread callback has been * dispatched and before the ExitThread callback has been dispatched. * A managed thread may not necessarily have any managed frames on its stack. * * Threads can be enumerated even before the CreateProcess callback. The enumeration * will naturally be empty. */ HRESULT EnumerateThreads([out] ICorDebugThreadEnum **ppThreads); /* * SetAllThreadsDebugState sets the current debug state of each thread. * See ICorDebugThread::SetDebugState for details. * * The pExceptThisThread parameter allows you to specify one * thread which is exempted from the debug state change. Pass NULL * if you want to affect all threads. * * This may affect threads not visible via EnumerateThreads, so threads suspended * via this API will need to be resumed via this API too. * */ HRESULT SetAllThreadsDebugState([in] CorDebugThreadState state, [in] ICorDebugThread *pExceptThisThread); /* * Detach detaches the debugger from the process. The process * continues execution normally. The ICorDebugProcess object is * no longer valid and no further callbacks will occur. This is * not implemented for AppDomains (detaching is process-wide). * * Note that currently if unmanaged debugging is enabled this call will * fail due to OS limitations. * * Returns S_OK on success. * */ HRESULT Detach(); /* * Terminate terminates the process (with extreme prejudice, I might add). * * NOTE: If the process or appdomain is stopped when Terminate is called, * the process or appdomain should be continued using Continue so that the * ExitProcess or ExitAppDomain callback is received. * * NOTE: This method is not implemented by an appdomain. */ HRESULT Terminate([in] UINT exitCode); /* * DEPRECATED */ HRESULT CanCommitChanges([in] ULONG cSnapshots, [in, size_is(cSnapshots)] ICorDebugEditAndContinueSnapshot *pSnapshots[], [out] ICorDebugErrorInfoEnum **pError); /* * DEPRECATED */ HRESULT CommitChanges([in] ULONG cSnapshots, [in, size_is(cSnapshots)] ICorDebugEditAndContinueSnapshot *pSnapshots[], [out] ICorDebugErrorInfoEnum **pError); }; #pragma warning(push) #pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugAppDomain */ /* ------------------------------------------------------------------------- * * * AppDomain interface * * ------------------------------------------------------------------------- */ [ object, local, uuid(3d6f5f63-7538-11d3-8d5b-00104b35e7ef), pointer_default(unique) ] interface ICorDebugAppDomain : ICorDebugController { /* * GetProcess returns the process containing the app domain */ HRESULT GetProcess([out] ICorDebugProcess **ppProcess); /* * EnumerateAssemblies enumerates all assemblies in the app domain * */ HRESULT EnumerateAssemblies([out] ICorDebugAssemblyEnum **ppAssemblies); /* * GetModuleFromMetaDataInterface returns the ICorDebugModule with * the given metadata interface. */ HRESULT GetModuleFromMetaDataInterface([in] IUnknown *pIMetaData, [out] ICorDebugModule **ppModule); /* * EnumerateBreakpoints returns an enum (ICorDebugBreakpointEnum) of all active * breakpoints in the app domain. This includes all types of breakpoints : * function breakpoints, data breakpoints, etc. */ HRESULT EnumerateBreakpoints([out] ICorDebugBreakpointEnum **ppBreakpoints); /* * EnumerateSteppers returns an enum of all active steppers in the app domain. * */ HRESULT EnumerateSteppers([out] ICorDebugStepperEnum **ppSteppers); /* * DEPRECATED. Always returns TRUE in V3 (attaching is process-wide). */ HRESULT IsAttached([out] BOOL *pbAttached); /* * GetName returns the name of the app domain. * * Usage pattern: * *pcchName is always set to the length of pInputString (including NULL) in characters. This lets * callers know the full size of buffer they'd need to allocate to get the full string. * * if (cchName == 0) then we're in "query" mode: * This fails if szName is non-null or pcchName is null * Else this function will set pcchName to let the caller know how large of a buffer to allocate * and return S_OK. * * if (cchName != 0) then * This fails if szName is null. * Else this copies as much as can fit into szName (it will always null terminate szName) and returns S_OK. * pcchName can be null. If it's non-null, we set it. * * The expected usage pattern is that a client will call once to get the size of a buffer needed for the name, * allocate the buffer, and then call a 2nd time to fill in the buffer. * * The rest of the GetName() functions have the same semantics for the parameters unless otherwise noted. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetObject returns a reference to the System.AppDomain object which represents this AppDomain * from within the runtime. * * Note: this object is lazily initialized within the runtime and may return NULL if the object * does not yet exist. This case will return S_FALSE and is not considered a failure. * */ HRESULT GetObject([out] ICorDebugValue **ppObject); /* * DEPRECATED. This does nothing in V3. Attaching is process-wide. */ HRESULT Attach(); /* * Get the ID of this app domain. The ID will be unique within the * containing process. */ HRESULT GetID([out] ULONG32 *pId); }; #pragma warning(pop) [ object, local, uuid(096E81D5-ECDA-4202-83F5-C65980A9EF75), pointer_default(unique) ] interface ICorDebugAppDomain2 : IUnknown { /* * GetArrayOrPointerType returns an array, pointer, byref or function pointer type. * elementType indicated the kind of type to be created and * must be one of ELEMENT_TYPE_PTR, ELEMENT_TYPE_BYREF, * ELEMENT_TYPE_ARRAY or ELEMENT_TYPE_SZARRAY. If used with * ELEMENT_TYPE_PTR or ELEMENT_TYPE_BYREF then nRank must be zero. */ HRESULT GetArrayOrPointerType([in] CorElementType elementType, [in] ULONG32 nRank, [in] ICorDebugType *pTypeArg, [out] ICorDebugType **ppType); /* * GetFunctionPointerType returns a function pointer type. * This corresponds to ELEMENT_TYPE_FNPTR. The first type in the type arguments * must be the return type and the remainder the argument types. */ HRESULT GetFunctionPointerType( [in] ULONG32 nTypeArgs, [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], [out] ICorDebugType **ppType); }; [ object, local, uuid(6164D242-1015-4BD6-8CBE-D0DBD4B8275A), pointer_default(unique) ] interface ICorDebugGuidToTypeEnum : ICorDebugEnum { /* * Gets the next "celt" number of IID / Type pairs from the app domain cache. * The actual number of frames retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of pairs retrieved is smaller * than the number of pairs requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] CorDebugGuidToTypeMapping values[], [out] ULONG* pceltFetched); }; [ object, local, uuid(8CB96A16-B588-42E2-B71C-DD849FC2ECCC), pointer_default(unique) ] interface ICorDebugAppDomain3 : IUnknown { /* * Returns an enumeration of types corresponding to the IIDs passed in * guidsToResolve. The enumeration will have the same cReqTypes elements * with NULL values corresponding to unknown IIDs. */ HRESULT GetCachedWinRTTypesForIIDs( [in] ULONG32 cReqTypes, [in, size_is(cReqTypes)] GUID * iidsToResolve, [out] ICorDebugTypeEnum ** ppTypesEnum); /* * Returns an enumeration of IID / Type pairs. This is the exhaustive * list of pairs as they were cached in the current app domain. */ HRESULT GetCachedWinRTTypes( [out] ICorDebugGuidToTypeEnum ** ppGuidToTypeEnum); }; [ object, local, uuid(FB99CC40-83BE-4724-AB3B-768E796EBAC2), pointer_default(unique) ] interface ICorDebugAppDomain4 : IUnknown { /* * gives back the managed object for a given CCW pointer */ HRESULT GetObjectForCCW([in]CORDB_ADDRESS ccwPointer, [out]ICorDebugValue **ppManagedObject); }; #pragma warning(push) #pragma warning(disable:28718) /* disable warning 28718 for interface ICorDebugAssembly */ /* ------------------------------------------------------------------------- * * Assembly interface * An ICorDebugAssembly instance corresponds to a managed assembly loaded * into a specific AppDomain in the CLR. For assemblies shared between multiple * AppDomains (eg. CoreLib), there will be a separate ICorDebugAssembly instance * per AppDomain in which it is used. * ------------------------------------------------------------------------- */ [ object, local, uuid(df59507c-d47a-459e-bce2-6427eac8fd06), pointer_default(unique) ] interface ICorDebugAssembly : IUnknown { /* * GetProcess returns the process containing the assembly */ HRESULT GetProcess([out] ICorDebugProcess **ppProcess); /* * GetAppDomain returns the app domain containing the assembly. */ HRESULT GetAppDomain([out] ICorDebugAppDomain **ppAppDomain); /* * EnumerateModules enumerates all modules in the assembly * */ HRESULT EnumerateModules([out] ICorDebugModuleEnum **ppModules); /* * NOT YET IMPLEMENTED */ HRESULT GetCodeBase([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * GetName returns the full path and filename of the assembly. * If the assembly has no filename (i.e. it is in-memory only), * S_FALSE is returned, and a fabricated string is stored into szName. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); }; #pragma warning(pop) [ object, local, uuid(426d1f9e-6dd4-44c8-aec7-26cdbaf4e398), pointer_default(unique) ] interface ICorDebugAssembly2 : IUnknown { /* * IsFullyTrusted sets a flag indicating whether the assembly has * been granted full trust by the runtime security system. * This may return CORDBG_E_NOTREADY if the security policy for * the assembly has not yet been resolved (eg. no code in the * assembly has been run yet). */ HRESULT IsFullyTrusted([out] BOOL *pbFullyTrusted); }; [ object, local, uuid(76361AB2-8C86-4FE9-96F2-F73D8843570A), pointer_default(unique) ] interface ICorDebugAssembly3 : IUnknown { /* * If this assembly has been merged with others inside a single container assembly, * this gives back the container. Otherwise *ppAssembly = NULL and the result is S_FALSE. */ HRESULT GetContainerAssembly(ICorDebugAssembly **ppAssembly); /* * Gets an enumeration for all the assemblies contained within this assembly * If the assembly isn't a container, the result is S_FALSE and the enumeration * will be empty. Symbols are needed to compute this result; if they aren't * present an error will be returned and no enumeration provided. */ HRESULT EnumerateContainedAssemblies(ICorDebugAssemblyEnum **ppAssemblies); }; /* ------------------------------------------------------------------------- * * Heap enumeration interface * ------------------------------------------------------------------------- */ cpp_quote("#ifndef _DEF_COR_TYPEID_") cpp_quote("#define _DEF_COR_TYPEID_") typedef struct COR_TYPEID { UINT64 token1; UINT64 token2; } COR_TYPEID; cpp_quote("#endif // _DEF_COR_TYPEID_") typedef struct _COR_HEAPOBJECT { CORDB_ADDRESS address; // The address (in memory) of the object. ULONG64 size; // The total size of the object. COR_TYPEID type; // The fully instantiated type of the object. } COR_HEAPOBJECT; [ object, local, uuid(76D7DAB8-D044-11DF-9A15-7E29DFD72085), pointer_default(unique) ] interface ICorDebugHeapEnum : ICorDebugEnum { /* * Gets the next "celt" number of objects in the enumeration. * The actual number of objects retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of objects retrieved is smaller * than the number of objects requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] COR_HEAPOBJECT objects[], [out] ULONG *pceltFetched); }; /* ------------------------------------------------------------------------- * * Segment enumeration interface * ------------------------------------------------------------------------- */ typedef enum CorDebugGenerationTypes { CorDebug_Gen0 = 0, CorDebug_Gen1 = 1, CorDebug_Gen2 = 2, CorDebug_LOH = 3, CorDebug_POH = 4, } CorDebugGenerationTypes; typedef struct _COR_SEGMENT { CORDB_ADDRESS start; // The start address of the segment. CORDB_ADDRESS end; // The end address of the segment. CorDebugGenerationTypes type; // The generation of the segment. ULONG heap; // The heap the segment resides in. } COR_SEGMENT; typedef enum CorDebugGCType { CorDebugWorkstationGC, CorDebugServerGC } CorDebugGCType; typedef struct _COR_HEAPINFO { BOOL areGCStructuresValid; // TRUE if it's ok to walk the heap, FALSE otherwise. DWORD pointerSize; // The size of pointers on the target architecture in bytes. DWORD numHeaps; // The number of logical GC heaps in the process. BOOL concurrent; // Is the GC concurrent? CorDebugGCType gcType; // Workstation or Server? } COR_HEAPINFO; [ object, local, uuid(A2FA0F8E-D045-11DF-AC8E-CE2ADFD72085), pointer_default(unique) ] interface ICorDebugHeapSegmentEnum : ICorDebugEnum { /* * Gets the next "celt" number of objects in the enumeration. * The actual number of objects retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of objects retrieved is smaller * than the number of objects requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] COR_SEGMENT segments[], [out] ULONG *pceltFetched); }; /* ------------------------------------------------------------------------- * * Reference enumeration interface * ------------------------------------------------------------------------- */ typedef enum CorGCReferenceType { CorHandleStrong = 1<<0, CorHandleStrongPinning = 1<<1, CorHandleWeakShort = 1<<2, CorHandleWeakLong = 1<<3, CorHandleWeakRefCount = 1<<4, CorHandleStrongRefCount = 1<<5, CorHandleStrongDependent = 1<<6, CorHandleStrongAsyncPinned = 1<<7, CorHandleStrongSizedByref = 1<<8, CorHandleWeakNativeCom = 1<<9, CorHandleWeakWinRT = CorHandleWeakNativeCom, CorReferenceStack = 0x80000001, CorReferenceFinalizer = 80000002, // Used for EnumHandles CorHandleStrongOnly = 0x1E3, CorHandleWeakOnly = 0x21C, CorHandleAll = 0x7FFFFFFF } CorGCReferenceType; cpp_quote("#ifndef _DEF_COR_GC_REFERENCE_") cpp_quote("#define _DEF_COR_GC_REFERENCE_") typedef struct COR_GC_REFERENCE { ICorDebugAppDomain *Domain; // The AppDomain of the handle/object, may be null. ICorDebugValue *Location; // A reference to the object CorGCReferenceType Type; // Where the root came from. /* DependentSource - for HandleDependent RefCount - for HandleStrongRefCount Size - for HandleSizedByref */ UINT64 ExtraData; } COR_GC_REFERENCE; cpp_quote("#endif // _DEF_COR_GC_REFERENCE_") [ object, local, uuid(7F3C24D3-7E1D-4245-AC3A-F72F8859C80C), pointer_default(unique) ] interface ICorDebugGCReferenceEnum : ICorDebugEnum { HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] COR_GC_REFERENCE roots[], [out] ULONG *pceltFetched); } cpp_quote("#ifndef _DEF_COR_ARRAY_LAYOUT_") cpp_quote("#define _DEF_COR_ARRAY_LAYOUT_") typedef struct COR_ARRAY_LAYOUT { COR_TYPEID componentID; // The type of objects the array contains CorElementType componentType; // Whether the component itself is a GC reference, value class, or primitive ULONG32 firstElementOffset; // The offset to the first element ULONG32 elementSize; // The size of each element ULONG32 countOffset; // The offset to the number of elements in the array. // For multidimensional arrays (works with normal arrays too). ULONG32 rankSize; // The size of the rank ULONG32 numRanks; // The number of ranks in the array (1 for array, N for multidimensional array) ULONG32 rankOffset; // The offset at which the ranks start } COR_ARRAY_LAYOUT; cpp_quote("#endif // _DEF_COR_ARRAY_LAYOUT_") cpp_quote("#ifndef _DEF_COR_TYPE_LAYOUT_") cpp_quote("#define _DEF_COR_TYPE_LAYOUT_") typedef struct COR_TYPE_LAYOUT { COR_TYPEID parentID; ULONG32 objectSize; ULONG32 numFields; ULONG32 boxOffset; CorElementType type; } COR_TYPE_LAYOUT; cpp_quote("#endif // _DEF_COR_TYPE_LAYOUT_") cpp_quote("#ifndef _DEF_COR_FIELD_") cpp_quote("#define _DEF_COR_FIELD_") typedef struct COR_FIELD { mdFieldDef token; // FieldDef token to get the field info ULONG32 offset; // Offset in object of data. COR_TYPEID id; // TYPEID of the field CorElementType fieldType; } COR_FIELD; cpp_quote("#endif // _DEF_COR_FIELD_") /* ------------------------------------------------------------------------- * * Process interface * ------------------------------------------------------------------------- */ #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugProcess */ /* * ICorDebugProcess represents a process running some managed code. */ [ object, local, uuid(3d6f5f64-7538-11d3-8d5b-00104b35e7ef), pointer_default(unique) ] interface ICorDebugProcess : ICorDebugController { /* * GetID returns the OS ID of the process. */ HRESULT GetID([out] DWORD *pdwProcessId); /* * GetHandle returns a handle to the process. This handle is owned * by the debugging API; the debugger should duplicate it before * using it. */ HRESULT GetHandle([out] HPROCESS *phProcessHandle); /* * GetThread returns the ICorDebugThread with the given OS Id. * * Note that eventually there will not be a one to one correspondence * between OS threads and runtime threads, so this entry point will * go away. */ HRESULT GetThread([in] DWORD dwThreadId, [out] ICorDebugThread **ppThread); /* * NOT YET IMPLEMENTED */ HRESULT EnumerateObjects([out] ICorDebugObjectEnum **ppObjects); /* * IsTransitionStub tests whether an address is inside of a transition stub * which will cause a transition to managed code. This can be used by * unmanaged stepping code to decide when to return stepping control to * the managed stepper. * * Note that, tentatively, these stubs may also be able to be identified * ahead of time by looking at information in the PE file. * */ HRESULT IsTransitionStub([in] CORDB_ADDRESS address, [out] BOOL *pbTransitionStub); /* * IsOSSuspended returns whether or not the thread has been * suspended as part of the debugger logic of stopping the process. * (that is, it has had its Win32 suspend count incremented by * one.) The debugger UI may want to take this into account if * it shows the user the OS suspend count of the thread. * * This function only makes sense in the context of * unmanaged debugging - during managed debugging threads are not * OS suspended. (They are cooperatively suspended.) */ HRESULT IsOSSuspended([in] DWORD threadID, [out] BOOL *pbSuspended); /* * GetThreadContext returns the context for the given thread. The * debugger should call this function rather than the Win32 * GetThreadContext, because the thread may actually be in a "hijacked" * state where its context has been temporarily changed. * * This should only be used on when a thread is in native code. Use ICorDebugRegisterSet * for threads in managed code. * * The data returned is a CONTEXT structure for the current platform. * (CONTEXT is typically declared in winnt.h) Just as with a call * to Win32's GetThreadContext, the caller should initialize the * CONTEXT struct before calling. * */ HRESULT GetThreadContext([in] DWORD threadID, [in] ULONG32 contextSize, [in, out, length_is(contextSize), size_is(contextSize)] BYTE context[]); /* * SetThreadContext sets the context for the given thread. The * debugger should call this function rather than the Win32 * SetThreadContext, because the thread may actually be in a "hijacked" * state where its context has been temporarily changed. * * This should only be used on when a thread is in native code. Use ICorDebugRegisterSet * for threads in managed code. * * This should never be needed to modify the context of a thread during an oob-debug * event. * * The data passed should be a CONTEXT structure for the current platform. * (CONTEXT is typically declared in winnt.h) * * This is a dangerous call which can corrupt the runtime if used * improperly. * */ HRESULT SetThreadContext([in] DWORD threadID, [in] ULONG32 contextSize, [in, length_is(contextSize), size_is(contextSize)] BYTE context[]); /* * ReadMemory reads memory from the process. * This is primarily intended to be used by interop-debugging to inspect memory * regions used by the unmanaged portion of the debuggee. * * This can also be used to read IL and native jitted code. * Any managed breakpoints will be automatically stripped from the returned buffer. * No adjustments will be made for Native breakpoints set by ICorDebugProcess2::SetUnmanagedBreakpoint * * No caching of process memory is performed. * These parameters have the same semantics as kernel32!ReadProcessMemory. * The entire range must be read for the function to return success. */ HRESULT ReadMemory([in] CORDB_ADDRESS address, [in] DWORD size, [out, size_is(size), length_is(size)] BYTE buffer[], [out] SIZE_T *read); /* * WriteMemory writes memory in the process. * In v2.0, Native debuggers should *not* use this to inject breakpoints * into the instruction stream. Use ICorDebugProcess2::SetUnamangedBreakpoint * instead. * * This is a dangerous call which can corrupt the runtime if used * improperly. It is highly recommended that this is only used outside * of managed code. * * These parameters have the same semantics as kernel32!WriteProcessMemory. */ HRESULT WriteMemory([in] CORDB_ADDRESS address, [in] DWORD size, [in, size_is(size)] BYTE buffer[], [out]SIZE_T *written); /* * ClearCurrentException clears the current unmanaged exception on * the given thread. Call this before calling Continue when a * thread has reported an unmanaged exception that should be * ignored by the debuggee. * * This will clear both the outstanding IB and OOB events on the given thread. * Out-of-band Breakpoint and single-step exceptions are automatically cleared. * * See ICorDebugThread2::InterceptCurrentException for continuing managed exceptions. * */ HRESULT ClearCurrentException([in] DWORD threadID); /* * EnableLogMessages enables/disables sending of log messages to the * debugger for logging. * This is only valid after the CreateProcess callback. * */ HRESULT EnableLogMessages([in]BOOL fOnOff); /* * ModifyLogSwitch modifies the specified switch's severity level. * This is only valid after the CreateProcess callback. * */ HRESULT ModifyLogSwitch([in, annotation("_In_")] WCHAR *pLogSwitchName, [in]LONG lLevel); /* * EnumerateAppDomains enumerates all app domains in the process. * This can be used before the CreateProcess callback. * */ HRESULT EnumerateAppDomains([out] ICorDebugAppDomainEnum **ppAppDomains); /* * NOT YET IMPLEMENTED */ HRESULT GetObject([out] ICorDebugValue **ppObject); /* * DEPRECATED */ HRESULT ThreadForFiberCookie([in] DWORD fiberCookie, [out] ICorDebugThread **ppThread); /* * Returns the OS thread id of the debugger's internal helper thread. * During managed/unmanaged debugging, it is the debugger's * responsibility to ensure that the thread with this ID remains running * if it hits a breakpoint placed by the debugger. A debugger may also * wish to hide this thread from the user. * * If there is no helper thread in the process yet, then this method * will return zero as the thread id. * * Note: you cannot cache this value. The ID of the helper thread may * change over time, so this value must be re-queried at every stopping * event. * * Note: this value will be correct on every unmanaged CreateThread event. * This will allow a debugger to determine the TID of the helper thread * and hide it from the user. A thread identified as a helper thread during * an unmanaged CreateThread event will never run managed user code. */ HRESULT GetHelperThreadID([out] DWORD *pThreadID); }; #pragma warning(pop) [ object, local, uuid(AD1B3588-0EF0-4744-A496-AA09A9F80371), pointer_default(unique) ] interface ICorDebugProcess2 : IUnknown { /* * Return a ICorDebugThread2 interface given a TASKID * Host can set TASKID using ICLRTask::SetTaskIdentifier */ HRESULT GetThreadForTaskID( [in] TASKID taskid, [out] ICorDebugThread2 **ppThread); /* * Returns the version of the runtime the debugee process is running. */ HRESULT GetVersion([out] COR_VERSION* version); /* * Set an unmanaged breakpoint at the given native address. If the address is within * the runtime, the breakpoint will be ignored. * This allows the CLR to avoid dispatching out-of-band breakpoints for breakpoints * set by the debugger. * buffer[] returns the opcode at the address that is replaced by the breakpoint. */ HRESULT SetUnmanagedBreakpoint([in] CORDB_ADDRESS address, [in] ULONG32 bufsize, [out, size_is(bufsize), length_is(*bufLen)] BYTE buffer[], [out] ULONG32 * bufLen); /* * Remove a breakpoint set by SetUnmanagedBreakpoint. */ HRESULT ClearUnmanagedBreakpoint([in] CORDB_ADDRESS address); /* * SetDesiredNGENCompilerFlags specifies the set of flags that must be set in a pre-JITted * image in order for the runtime to load that image into this app domain. If no such image exists, * the runtime will load the IL and JIT instead. The flags set by this function are just used to select the * correct pre-JITted image; if no suitable image is found the debugger will still need to use * ICorDebugModule2::SetJITCompilerFlags to set the flags as desired for JIT. * * This function must be called during the CreateProcess callback. * Attempts to call it after this callback has been delivered will fail. */ HRESULT SetDesiredNGENCompilerFlags( [in] DWORD pdwFlags ); /* * GetDesiredNGENCompilerFlags gets the set of flags that must be set in a pre-JITted image in order * for the runtime to load that image into this process. */ HRESULT GetDesiredNGENCompilerFlags( [out] DWORD *pdwFlags ); /* * Gets an ICorDebugReferenceValue object from a raw GC handle value. * * handle is the IntPtr within a GCHandle. Do not confuse * this with a GC reference value. This is a potentially dangerous API and may * corrupt both the debugger and debuggee if a bogus handle is passed in. * This API does not necessarily validate that the handle is valid. * * The ICorDebugReferenceValue will behave much like a normal reference. It will * be neutered on the next continue; the lifetime of the target object will * not be affected by the existence of the ReferenceValue. */ HRESULT GetReferenceValueFromGCHandle( [in] UINT_PTR handle, [out] ICorDebugReferenceValue **pOutValue); }; [ object, local, uuid(2EE06488-C0D4-42B1-B26D-F3795EF606FB), pointer_default(unique) ] interface ICorDebugProcess3 : IUnknown { /* Enables (or disables) custom debugger notifications of a specified * type (which implements ICustomDebuggerNotification). * When this has been enabled, calls to * System.Diagnostics.Debugger.CustomNotification with a data argument * of the specified class will trigger a CustomNotification callback. * Notifications are disabled by default and the debugger must opt-into * any notification types it knows of and wishes to handle. * Since ICorDebugClass is scoped by appdomains, the debugger needs to * call this API for every appdomain in the process if it's interested in * receiving the notification across the entire process. */ HRESULT SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable); } [ object, local, uuid(21e9d9c0-fcb8-11df-8cff-0800200c9a66), pointer_default(unique) ] interface ICorDebugProcess5 : IUnknown { HRESULT GetGCHeapInformation([out] COR_HEAPINFO *pHeapInfo); HRESULT EnumerateHeap([out] ICorDebugHeapEnum **ppObjects); HRESULT EnumerateHeapRegions([out] ICorDebugHeapSegmentEnum **ppRegions); HRESULT GetObject([in] CORDB_ADDRESS addr, [out] ICorDebugObjectValue **pObject); HRESULT EnumerateGCReferences([in] BOOL enumerateWeakReferences, [out] ICorDebugGCReferenceEnum **ppEnum); HRESULT EnumerateHandles([in] CorGCReferenceType types, [out] ICorDebugGCReferenceEnum **ppEnum); HRESULT GetTypeID([in] CORDB_ADDRESS obj, [out] COR_TYPEID *pId); HRESULT GetTypeForTypeID([in] COR_TYPEID id, [out] ICorDebugType **ppType); HRESULT GetArrayLayout([in] COR_TYPEID id, [out] COR_ARRAY_LAYOUT *pLayout); HRESULT GetTypeLayout([in] COR_TYPEID id, [out] COR_TYPE_LAYOUT *pLayout); HRESULT GetTypeFields([in] COR_TYPEID id, ULONG32 celt, COR_FIELD fields[], ULONG32 *pceltNeeded); /* * Enables the specified policy. */ HRESULT EnableNGENPolicy([in] CorDebugNGENPolicy ePolicy); } // Describes formats of pRecord byte blob in DecodeEvent. // This is dependent on the target architecture. typedef enum CorDebugRecordFormat { FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1, FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2, } CorDebugRecordFormat; // dwFlags in DecodeEvent is dependent on the target architecture. // Definition of DecodeEvent flags on Windows. typedef enum CorDebugDecodeEventFlagsWindows { IS_FIRST_CHANCE = 1, } CorDebugDecodeEventFlagsWindows; // Possible events which can be decoded in DecodeEvent typedef enum CorDebugDebugEventKind { DEBUG_EVENT_KIND_MODULE_LOADED = 1, DEBUG_EVENT_KIND_MODULE_UNLOADED = 2, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_FIRST_CHANCE = 3, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_USER_FIRST_CHANCE = 4, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_CATCH_HANDLER_FOUND = 5, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6 } CorDebugDebugEventKind; // Describes what amount of cached data must be discarded based on changes to the // process typedef enum CorDebugStateChange { PROCESS_RUNNING = 0x0000001, // The process reached a new memory state via // forward execution. FLUSH_ALL = 0x0000002, // The process' memory might be arbitrarily // different than it was before. } CorDebugStateChange; // Base interface from which all ICorDebug debug events derive [ object, local, uuid(41BD395D-DE99-48F1-BF7A-CC0F44A6D281), pointer_default(unique) ] interface ICorDebugDebugEvent : IUnknown { /* * Quickly determines what kind of event this is. Based on the answer you * you can QI to get a more precise debug event interface with additional data * available. */ HRESULT GetEventKind([out]CorDebugDebugEventKind *pDebugEventKind); /* * Gets the thread on which the event occurred */ HRESULT GetThread([out]ICorDebugThread **ppThread); } typedef enum CorDebugCodeInvokeKind { CODE_INVOKE_KIND_NONE, // if there is any managed code invoked by this method, it will have // have to be located by explicit events/breakpoints later // OR we may just miss some of the managed code this method calls // because there is no easy way to stop on it // OR the method may never invoke managed code CODE_INVOKE_KIND_RETURN, // This method will invoke managed code via a return instruction, // Stepping out should arrive at the next managed code CODE_INVOKE_KIND_TAILCALL, // This method will invoke managed code via a tail-call. Single-stepping // + stepping over any call instructions should arrive at managed code } CorDebugCodeInvokeKind; typedef enum CorDebugCodeInvokePurpose { CODE_INVOKE_PURPOSE_NONE, CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION, // The managed code will run any managed entrypoint // such as a reverse p-invoke. Any more detailed purpose // is unknown by the runtime. CODE_INVOKE_PURPOSE_CLASS_INIT, // The managed code will run a static constructor CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH, // The managed code will run the implementation for // some interface method that was called } CorDebugCodeInvokePurpose; [ object, local, uuid(11588775-7205-4CEB-A41A-93753C3153E9), pointer_default(unique) ] interface ICorDebugProcess6 : IUnknown { //Decodes managed debug events which have been encapsulated in the payload of //specially crafted native exception debug events HRESULT DecodeEvent( [in, length_is(countBytes), size_is(countBytes)] const BYTE pRecord[], [in] DWORD countBytes, [in] CorDebugRecordFormat format, [in] DWORD dwFlags, [in] DWORD dwThreadId, [out] ICorDebugDebugEvent **ppEvent); // Debugger calls this to notify ICorDebug that the process is running. // // Notes: // ProcessStateChanged(PROCESS_RUNNING) has similar semantics to // ICorDebugProcess::Continue(); HRESULT ProcessStateChanged([in] CorDebugStateChange change); // Get information about managed code at codeAddress HRESULT GetCode([in] CORDB_ADDRESS codeAddress, [out] ICorDebugCode **ppCode); // Virtual module splitting causes ICorDebug to recognize modules that were // merged together during the build process and present them as a group of separate // modules rather than a single large module. Doing this changes the behavior of // various ICorDebug APIs described below. // // Terminology // The aggregate modules are called containers, the modules inside are called // sub-modules or virtual modules. Both container modules and sub-modules are // represented with the ICorDebugModule interface, however the behavior of the // interface is slightly different in each case, as described below. // In addition there may still be modules loaded that weren't merged during build. // These modules, called regular modules, are neither container modules nor // sub-modules. // // Modules and assemblies // Multi-module assemblies are not supported for assembly merging scenarios // so module and assembly are exactly 1:1. Each ICorDebugModule, regardless of // whether it represents a container module or a sub-module, has a corresponding // ICorDebugAssembly. ICorDebugModule.GetAssembly() converts from the module to the // assembly. To map the other direction, ICorDebugAssembly.EnumerateModules() will // enumerate only 1 module. Because assembly and module form a tightly coupled pair // in this case, the terms assembly and module become largely interchangeable. // // Differences in behavior for container modules vs. sub-modules // Container modules: // -have metadata for all of the constituent sub-modules merged together // -type names may be mangled // -ICorDebugModule.GetName() will return the path to an on-disk module // -ICorDebugModule.GetSize() returns the size of that image. // -ICorDebugAssembly3.EnumerateContainedAssemblies will list the sub-modules // -ICorDebugAssembly3.GetContainerAssembly returns S_FALSE // Sub-modules: // -have a reduced set of metadata that corresponds only to the original // assembly that was merged in. // -The metadata names have no mangling. // -Metadata tokens are unlikely to match with the tokens in the original // assembly before it was merged in the build process // -ICorDebugModule.GetName() returns the assembly name (not a file path) // -ICorDebug.GetSize() returns the original unmerged image size. // -ICorDebugModule3.EnumerateContainedAssemblies will return S_FALSE // -ICorDebugAssembly3.GetContainerAssembly will return the containing module // // Interfaces retrieved from modules // There are a variety of interfaces that can be created from modules, such as // ICorDebugModule.GetClassFromToken() -> ICorDebugClass // These objects are always cached by ICorDebug, and they will have the same pointer // identity regardless of whether they were created/queried from the container module // or a sub-module. The sub-module serves as a filtered view of these cached // objects, not a separate cache with its own copies. // // Enabling Virtual Module Splitting has the following effects elsewhere in the API: // ICorDebugFunction.GetModule // Disabled - Returns the container module this function was merged into // Enabled - Returns the sub-module this function was originally defined in // ICorDebugClass.GetModule // Disabled - Returns the container module this class was merged into // Enabled - Returns the sub-module this class was originally defined in // ICorDebugModuleDebugEvent.GetModule // Enabled OR Disabled - Returns the container module that was loaded. // Sub-modules are not given load events regardless of this // setting. // ICorDebugAppDomain.EnumerateAssemblies // Disabled - Returns a list of container assemblies + regular assemblies // (no sub-assemblies are shown) // Enabled - Returns the list of sub-assemblies + regular assemblies // (no container assemblies are shown). // Note: If any container assembly is missing symbols, none of its // sub-assemblies will be enumerated. If any regular assembly is // missing symbols it may or may not be enumerated. // ICorDebugCode.GetCode (when referring to IL code only) // Disabled - Returns the IL in the post-merge assembly image. // Enabled - Returns IL that would be valid in a pre-merge assembly image. Specifically // any inline metadata tokens will correctly be TypeRef or MemberRef tokens // when the types being referred to are not defined in the virtual module // containing the IL. These TypeRefs/MemberRefs can be looked up in the // IMetaDataImport for the corresponding virtual ICorDebugModule. // // This setting can be changed at any time. It does not incur any stateful functional // changes in ICorDebug, beyond altering the behavior of the above APIs at the time they are // called. Using virtual modules does incur a performance penalty for all the above // APIs. Additionally the virtualized metadata may do significant in-memory caching required // to correctly implement the IMetaDataImport APIs, and these caches may be retained // even after virtual module splitting has been turned off. HRESULT EnableVirtualModuleSplitting(BOOL enableSplitting); // Changes internal state of the debuggee so that the System.Debugger.IsAttached API in the BCL // returns true. // // Returns // S_OK - debuggee is successfully updated // CORDBG_E_MODULE_NOT_LOADED - assembly containing System.Debugger.IsAttached API is not loaded // or some other error is preventing it from being recognized such as missing metadata. This error // is common and benign - it is recommended to try the call again when future assemblies load. // // other misc failing HRESULTs are possible, but likely indicate misbehaving debugger or compiler // components HRESULT MarkDebuggerAttached(BOOL fIsAttached); // Provides information on runtime exported functions to help step to managed code // // Parameters // pszExportName - The name of a runtime export function as written in the PE export table // invokeKind - [out] A description of how the exported function will invoke managed code // invokePurpose - [out] A description of why the exported function will call managed code // // Returns // S_OK - on success // E_POINTER - pInvokeKind or pInvokePurpose is NULL // Other failing HRESULTs as appropriate // HRESULT GetExportStepInfo([in]LPCWSTR pszExportName, [out]CorDebugCodeInvokeKind* pInvokeKind, [out]CorDebugCodeInvokePurpose* pInvokePurpose); } typedef enum WriteableMetadataUpdateMode { LegacyCompatPolicy, AlwaysShowUpdates } WriteableMetadataUpdateMode; [ object, local, uuid(9B2C54E4-119F-4D6F-B402-527603266D69), pointer_default(unique) ] interface ICorDebugProcess7 : IUnknown { // Configures how the debugger handles metadata that has been updated in-memory // within the target process. These updates could come from EnC, a profiler, // or Reflection.Emit HRESULT SetWriteableMetadataUpdateMode(WriteableMetadataUpdateMode flags); } [ object, local, uuid(2E6F28C1-85EB-4141-80AD-0A90944B9639), pointer_default(unique) ] interface ICorDebugProcess8 : IUnknown { /* * EnableExceptionCallbacksOutsideOfMyCode enables/disables certain types of exception callback to ICorDebugManagedCallback2. * If the flag is FALSE: * 1) DEBUG_EXCEPTION_FIRST_CHANCE callbacks won't called in the debugger. * 2) DEBUG_EXCEPTION_CATCH_HANDLER_FOUND callbacks won't be called if an exception never escapes into user code. * (i.e. a path from an exception origin to an exception handler has no methods marked as JMC) * * Default value of this flag is TRUE. */ HRESULT EnableExceptionCallbacksOutsideOfMyCode([in] BOOL enableExceptionsOutsideOfJMC); } [ object, local, uuid(8F378F6F-1017-4461-9890-ECF64C54079F), pointer_default(unique) ] interface ICorDebugProcess10 : IUnknown { // // Enable or disable the GC notification events. The GC notification events are turned off by default // They will be delivered through ICorDebugManagedCallback4 // // This interface is deprecated. The EnableGCNotificationEvents(true) occasionally deadlocked debug sessions // in .NET Core 5.0 and later. Please use the IID_ICorDebugHeapValue4 to pin an object and prevent its relocation // // Parameters // fEnable - true to enable the events, false to disable // // Returns // S_OK - on success // HRESULT EnableGCNotificationEvents(BOOL fEnable); } // The memory range described by this structure is a closed-open // interval, that is only the start is inclusive. typedef struct _COR_MEMORY_RANGE { CORDB_ADDRESS start; // The start address of the range. CORDB_ADDRESS end; // The end address of the range. } COR_MEMORY_RANGE; [ object, local, uuid(D1A0BCFC-5865-4437-BE3F-36F022951F8A), pointer_default(unique) ] interface ICorDebugMemoryRangeEnum : ICorDebugEnum { /* * Gets the next "celt" number of objects in the enumeration. * The actual number of objects retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of objects retrieved is smaller * than the number of objects requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] COR_MEMORY_RANGE objects[], [out] ULONG *pceltFetched); }; [ object, local, uuid(344B37AA-F2C0-4D3B-9909-91CCF787DA8C), pointer_default(unique) ] interface ICorDebugProcess11 : IUnknown { HRESULT EnumerateLoaderHeapMemoryRegions([out] ICorDebugMemoryRangeEnum** ppRanges); } // Event types MODULE_LOADED and MODULE_UNLOADED implement this interface [ object, local, uuid(51A15E8D-9FFF-4864-9B87-F4FBDEA747A2), pointer_default(unique) ] interface ICorDebugModuleDebugEvent : ICorDebugDebugEvent { /* * Gets the merged module that was just loaded or unloaded. Use * ICorDebugDebugEvent.GetEventType() to determine whether it was load/unload. */ HRESULT GetModule([out]ICorDebugModule **ppModule); } // This interface is implemented by events types: // MANAGED_EXCEPTION_FIRST_CHANCE, // MANAGED_EXCEPTION_USER_FIRST_CHANCE, // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND, // MANAGED_EXCEPTION_UNHANDLED, [ object, local, uuid(AF79EC94-4752-419C-A626-5FB1CC1A5AB7), pointer_default(unique) ] interface ICorDebugExceptionDebugEvent : ICorDebugDebugEvent { // The meaning of this stack pointer varies based on event type (available from // ICorDebugDebugEvent.GetEventType()) // // MANAGED_EXCEPTION_FIRST_CHANCE -> The stack pointer for the frame that threw the exception // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> The stack pointer for the user-code frame closest to the point of // the thrown exception // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND -> The stack pointer for the frame that contains the catch handler // MANAGED_EXCEPTION_UNHANDLED -> *pStackPointer will be NULL HRESULT GetStackPointer([out]CORDB_ADDRESS *pStackPointer); // The meaning of the IP varies based on event type (available from // ICorDebugDebugEvent.GetEventType()) // // MANAGED_EXCEPTION_FIRST_CHANCE -> The address of the faulting instruction // MANAGED_EXCEPTION_USER_FIRST_CHANCE -> Within the frame indicated by GetStackPointer(), // this is the code address where execution would resume if no exception had been // raised. The exception may or may not cause different code to be executed in this // frame such as a catch of finally clause. // MANAGED_EXCEPTION_CATCH_HANDLER_FOUND -> Within the frame indicated by GetStackPointer(), // this is the code address where catch handler execution will start // MANAGED_EXCEPTION_UNHANDLED -> *pIP will be 0 HRESULT GetNativeIP([out]CORDB_ADDRESS *pIP); // Gets a flag that indicates if the exception is interceptable. HRESULT GetFlags([out]CorDebugExceptionFlags *pdwFlags); } /* ------------------------------------------------------------------------- * * Breakpoint interface * ------------------------------------------------------------------------- */ /* * ICorDebugBreakpoint represents a breakpoint; either a breakpoint * set in a function, or a watchpoint set on a value. * * Note that breakpoints have no direct support for condition * expressions. The debugger must implement this functionality on top of * this interface if desired. * */ [ object, local, uuid(CC7BCAE8-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugBreakpoint : IUnknown { /* * Sets the active state of the breakpoint */ HRESULT Activate([in] BOOL bActive); /* * Returns whether the breakpoint is active. */ HRESULT IsActive([out] BOOL *pbActive); }; [ object, local, uuid(CC7BCAE9-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugFunctionBreakpoint : ICorDebugBreakpoint { /* * Returns the function on which this breakpoint is set */ HRESULT GetFunction([out] ICorDebugFunction **ppFunction); /* * Returns the offset of this breakpoint within the function */ HRESULT GetOffset([out] ULONG32 *pnOffset); }; [ object, local, uuid(CC7BCAEA-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugModuleBreakpoint : ICorDebugBreakpoint { /* * Returns the module on which this breakpoint is set. */ HRESULT GetModule([out] ICorDebugModule **ppModule); }; [ object, local, uuid(CC7BCAEB-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugValueBreakpoint : ICorDebugBreakpoint { /* * Gets the value on which this breakpoint is set. */ HRESULT GetValue([out] ICorDebugValue **ppValue); }; /* ------------------------------------------------------------------------- * * Stepper interface * ------------------------------------------------------------------------- */ /* * A Stepper object represents a stepping operation being performed by * the debugger. Note that there can be more than one stepper per * thread; for instance a breakpoint may be hit in the midst of a * stepping over a function, and the user may wish to start a new * stepping operation inside that function. (Note that it is up to the * debugger how to handle this; it may want to cancel the original * stepping operation, or nest them. This API allows either behavior.) * * Also, a stepper may migrate between threads if a cross-thread * marshalled call is made by the EE. * * This object serves several purposes. Its serves as an identifier between a * step command issued and the completion of that command. It also * provides a central interface to encapsulate all of the stepping * that can be performed. Finally it provides a way to prematurely * cancel a stepping operation. * */ [ object, local, uuid(CC7BCAEC-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugStepper : IUnknown { /* * IsActive returns whether or not the stepper is active, that is, whether * it is currently stepping. * * Any step action remains active until StepComplete is called. Note that * this automatically deactivates the stepper. * * A stepper may also be deactivated prematurely by calling * Deactivate before a callback condition is reached. */ HRESULT IsActive([out] BOOL *pbActive); /* * Deactivate causes a stepper to cancel the last stepping command it * received. A new stepping command may then be issued. */ HRESULT Deactivate(); /* * SetInterceptMask controls which intercept code will be stepped * into by the stepper. If the bit for an interceptor is set, the * stepper will complete with reason STEPPER_INTERCEPT when the * given type of intercept occurs. If the bit is cleared, the * intercepting code will be skipped. * * Note that SetInterceptMask may have unforeseen interactions * with SetUnmappedStopMask (from the user's point of view). For * example, if the only visible (ie, non internal) portion of class * init code lacks mapping info (STOP_NO_MAPPING_INFO) and * STOP_NO_MAPPING_INFO isn't set, then we'll step over the class init. * * By default, only INTERCEPT_NONE will be used. */ typedef enum CorDebugIntercept { INTERCEPT_NONE = 0x0 , INTERCEPT_CLASS_INIT = 0x01, INTERCEPT_EXCEPTION_FILTER = 0x02, INTERCEPT_SECURITY = 0x04, INTERCEPT_CONTEXT_POLICY = 0x08, INTERCEPT_INTERCEPTION = 0x10, INTERCEPT_ALL = 0xffff } CorDebugIntercept; HRESULT SetInterceptMask([in] CorDebugIntercept mask); /* * SetUnmappedStopMask controls whether the stepper * will stop in jitted code which is not mapped to IL. * * If the given flag is set, then that type of unmapped code * will be stopped in. Otherwise stepping transparently continues. * * It should be noted that if one doesn't use a stepper to enter a * method (for example, the main() method of C++), then one * won't necessarily step over prologs,etc. * * By default, STOP_OTHER_UNMAPPED will be used. * * STOP_UNMANAGED is only valid w/ interop debugging. */ typedef enum CorDebugUnmappedStop { STOP_NONE = 0x0, STOP_PROLOG = 0x01, STOP_EPILOG = 0x02, STOP_NO_MAPPING_INFO = 0x04, STOP_OTHER_UNMAPPED = 0x08, STOP_UNMANAGED = 0x10, STOP_ALL = 0xffff, } CorDebugUnmappedStop; HRESULT SetUnmappedStopMask([in] CorDebugUnmappedStop mask); /* * Step is called when a thread is to be single stepped. The step * will complete at the next managed instruction executed by the * EE in the stepper's frame. * * If bStepIn is TRUE, any function calls made during the step * will be stepped into. Otherwise they will be skipped. * * If Step is called on a stepper which is not in managed code, * the step will complete when the next managed code is executed * by the thread. (if bStepIn is FALSE, it will only complete * when managed code is returned to, not when it is stepped into.) */ HRESULT Step([in] BOOL bStepIn); /* * StepRange works just like Step, except it will not complete * until code outside the given range is reached. This can be * more efficient than stepping one instruction at a time. * * Ranges are specified as a list of offset pairs [start, end) * (note that end is exclusive) from the start of the stepper's * frame's code. * * Ranges are in relative to the IL code of a method. Call * SetRangeIL(FALSE) to specify ranges relative to the native code * of a method. */ typedef struct COR_DEBUG_STEP_RANGE { ULONG32 startOffset, endOffset; } COR_DEBUG_STEP_RANGE; HRESULT StepRange([in] BOOL bStepIn, [in,size_is(cRangeCount)] COR_DEBUG_STEP_RANGE ranges[], [in] ULONG32 cRangeCount); /* * A StepOut operation will complete after the current frame is * returned from normally and the previous frame is reactivated. * * If this is called when in unmanaged code, the step will complete * when the calling managed code is returned to. * * In v2.0, we explicitly forbid StepOut with the STOP_UNMANAGED mask * and will fail that. Interop debuggers must do step-out-to-native * themselves. */ HRESULT StepOut(); /* * SetRangeIL is used to set whether the ranges passed StepRange are * relative to the IL code or the native code for the method being * stepped in. * * By default the range is in IL. */ HRESULT SetRangeIL([in] BOOL bIL); }; /* * ICorDebugStepper2 exposes JMC functionality. */ [ object, local, uuid(C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7), pointer_default(unique) ] interface ICorDebugStepper2 : IUnknown { HRESULT SetJMC([in] BOOL fIsJMCStepper); } /* ------------------------------------------------------------------------- * * Program state object interfaces * ------------------------------------------------------------------------- */ /* * ICorDebugRegisterSet */ [ object, local, uuid(CC7BCB0B-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugRegisterSet : IUnknown { typedef enum CorDebugRegister { // registers (potentially) available on all architectures // Note that these overlap with the architecture-specific // registers // // NOTE: On IA64, REGISTER_FRAME_POINTER represents the BSP register. REGISTER_INSTRUCTION_POINTER = 0, REGISTER_STACK_POINTER, REGISTER_FRAME_POINTER, // X86 registers REGISTER_X86_EIP = 0, REGISTER_X86_ESP, REGISTER_X86_EBP, REGISTER_X86_EAX, REGISTER_X86_ECX, REGISTER_X86_EDX, REGISTER_X86_EBX, REGISTER_X86_ESI, REGISTER_X86_EDI, REGISTER_X86_FPSTACK_0, REGISTER_X86_FPSTACK_1, REGISTER_X86_FPSTACK_2, REGISTER_X86_FPSTACK_3, REGISTER_X86_FPSTACK_4, REGISTER_X86_FPSTACK_5, REGISTER_X86_FPSTACK_6, REGISTER_X86_FPSTACK_7, // AMD64 registers REGISTER_AMD64_RIP = 0, REGISTER_AMD64_RSP, REGISTER_AMD64_RBP, REGISTER_AMD64_RAX, REGISTER_AMD64_RCX, REGISTER_AMD64_RDX, REGISTER_AMD64_RBX, REGISTER_AMD64_RSI, REGISTER_AMD64_RDI, REGISTER_AMD64_R8, REGISTER_AMD64_R9, REGISTER_AMD64_R10, REGISTER_AMD64_R11, REGISTER_AMD64_R12, REGISTER_AMD64_R13, REGISTER_AMD64_R14, REGISTER_AMD64_R15, // Xmm FP REGISTER_AMD64_XMM0, REGISTER_AMD64_XMM1, REGISTER_AMD64_XMM2, REGISTER_AMD64_XMM3, REGISTER_AMD64_XMM4, REGISTER_AMD64_XMM5, REGISTER_AMD64_XMM6, REGISTER_AMD64_XMM7, REGISTER_AMD64_XMM8, REGISTER_AMD64_XMM9, REGISTER_AMD64_XMM10, REGISTER_AMD64_XMM11, REGISTER_AMD64_XMM12, REGISTER_AMD64_XMM13, REGISTER_AMD64_XMM14, REGISTER_AMD64_XMM15, // IA64 registers REGISTER_IA64_BSP = REGISTER_FRAME_POINTER, // To get a particular general register, add the register number // to REGISTER_IA64_R0. The same also goes for floating point // registers. // // For example, if you need REGISTER_IA64_R83, // use REGISTER_IA64_R0 + 83. REGISTER_IA64_R0 = REGISTER_IA64_BSP + 1, REGISTER_IA64_F0 = REGISTER_IA64_R0 + 128, // ARM registers (@ARMTODO: FP?) REGISTER_ARM_PC = 0, REGISTER_ARM_SP, REGISTER_ARM_R0, REGISTER_ARM_R1, REGISTER_ARM_R2, REGISTER_ARM_R3, REGISTER_ARM_R4, REGISTER_ARM_R5, REGISTER_ARM_R6, REGISTER_ARM_R7, REGISTER_ARM_R8, REGISTER_ARM_R9, REGISTER_ARM_R10, REGISTER_ARM_R11, REGISTER_ARM_R12, REGISTER_ARM_LR, REGISTER_ARM_D0, REGISTER_ARM_D1, REGISTER_ARM_D2, REGISTER_ARM_D3, REGISTER_ARM_D4, REGISTER_ARM_D5, REGISTER_ARM_D6, REGISTER_ARM_D7, REGISTER_ARM_D8, REGISTER_ARM_D9, REGISTER_ARM_D10, REGISTER_ARM_D11, REGISTER_ARM_D12, REGISTER_ARM_D13, REGISTER_ARM_D14, REGISTER_ARM_D15, REGISTER_ARM_D16, REGISTER_ARM_D17, REGISTER_ARM_D18, REGISTER_ARM_D19, REGISTER_ARM_D20, REGISTER_ARM_D21, REGISTER_ARM_D22, REGISTER_ARM_D23, REGISTER_ARM_D24, REGISTER_ARM_D25, REGISTER_ARM_D26, REGISTER_ARM_D27, REGISTER_ARM_D28, REGISTER_ARM_D29, REGISTER_ARM_D30, REGISTER_ARM_D31, // ARM64 registers REGISTER_ARM64_PC = 0, REGISTER_ARM64_SP, REGISTER_ARM64_FP, REGISTER_ARM64_X0, REGISTER_ARM64_X1, REGISTER_ARM64_X2, REGISTER_ARM64_X3, REGISTER_ARM64_X4, REGISTER_ARM64_X5, REGISTER_ARM64_X6, REGISTER_ARM64_X7, REGISTER_ARM64_X8, REGISTER_ARM64_X9, REGISTER_ARM64_X10, REGISTER_ARM64_X11, REGISTER_ARM64_X12, REGISTER_ARM64_X13, REGISTER_ARM64_X14, REGISTER_ARM64_X15, REGISTER_ARM64_X16, REGISTER_ARM64_X17, REGISTER_ARM64_X18, REGISTER_ARM64_X19, REGISTER_ARM64_X20, REGISTER_ARM64_X21, REGISTER_ARM64_X22, REGISTER_ARM64_X23, REGISTER_ARM64_X24, REGISTER_ARM64_X25, REGISTER_ARM64_X26, REGISTER_ARM64_X27, REGISTER_ARM64_X28, REGISTER_ARM64_LR, REGISTER_ARM64_V0, REGISTER_ARM64_V1, REGISTER_ARM64_V2, REGISTER_ARM64_V3, REGISTER_ARM64_V4, REGISTER_ARM64_V5, REGISTER_ARM64_V6, REGISTER_ARM64_V7, REGISTER_ARM64_V8, REGISTER_ARM64_V9, REGISTER_ARM64_V10, REGISTER_ARM64_V11, REGISTER_ARM64_V12, REGISTER_ARM64_V13, REGISTER_ARM64_V14, REGISTER_ARM64_V15, REGISTER_ARM64_V16, REGISTER_ARM64_V17, REGISTER_ARM64_V18, REGISTER_ARM64_V19, REGISTER_ARM64_V20, REGISTER_ARM64_V21, REGISTER_ARM64_V22, REGISTER_ARM64_V23, REGISTER_ARM64_V24, REGISTER_ARM64_V25, REGISTER_ARM64_V26, REGISTER_ARM64_V27, REGISTER_ARM64_V28, REGISTER_ARM64_V29, REGISTER_ARM64_V30, REGISTER_ARM64_V31, // LoongArch64 registers REGISTER_LOONGARCH64_PC = 0, REGISTER_LOONGARCH64_SP, REGISTER_LOONGARCH64_FP, REGISTER_LOONGARCH64_RA, REGISTER_LOONGARCH64_TP, REGISTER_LOONGARCH64_A0, REGISTER_LOONGARCH64_A1, REGISTER_LOONGARCH64_A2, REGISTER_LOONGARCH64_A3, REGISTER_LOONGARCH64_A4, REGISTER_LOONGARCH64_A5, REGISTER_LOONGARCH64_A6, REGISTER_LOONGARCH64_A7, REGISTER_LOONGARCH64_T0, REGISTER_LOONGARCH64_T1, REGISTER_LOONGARCH64_T2, REGISTER_LOONGARCH64_T3, REGISTER_LOONGARCH64_T4, REGISTER_LOONGARCH64_T5, REGISTER_LOONGARCH64_T6, REGISTER_LOONGARCH64_T7, REGISTER_LOONGARCH64_T8, REGISTER_LOONGARCH64_X0, REGISTER_LOONGARCH64_S0, REGISTER_LOONGARCH64_S1, REGISTER_LOONGARCH64_S2, REGISTER_LOONGARCH64_S3, REGISTER_LOONGARCH64_S4, REGISTER_LOONGARCH64_S5, REGISTER_LOONGARCH64_S6, REGISTER_LOONGARCH64_S7, REGISTER_LOONGARCH64_S8, REGISTER_LOONGARCH64_F0, REGISTER_LOONGARCH64_F1, REGISTER_LOONGARCH64_F2, REGISTER_LOONGARCH64_F3, REGISTER_LOONGARCH64_F4, REGISTER_LOONGARCH64_F5, REGISTER_LOONGARCH64_F6, REGISTER_LOONGARCH64_F7, REGISTER_LOONGARCH64_F8, REGISTER_LOONGARCH64_F9, REGISTER_LOONGARCH64_F10, REGISTER_LOONGARCH64_F11, REGISTER_LOONGARCH64_F12, REGISTER_LOONGARCH64_F13, REGISTER_LOONGARCH64_F14, REGISTER_LOONGARCH64_F15, REGISTER_LOONGARCH64_F16, REGISTER_LOONGARCH64_F17, REGISTER_LOONGARCH64_F18, REGISTER_LOONGARCH64_F19, REGISTER_LOONGARCH64_F20, REGISTER_LOONGARCH64_F21, REGISTER_LOONGARCH64_F22, REGISTER_LOONGARCH64_F23, REGISTER_LOONGARCH64_F24, REGISTER_LOONGARCH64_F25, REGISTER_LOONGARCH64_F26, REGISTER_LOONGARCH64_F27, REGISTER_LOONGARCH64_F28, REGISTER_LOONGARCH64_F29, REGISTER_LOONGARCH64_F30, REGISTER_LOONGARCH64_F31, // other architectures here } CorDebugRegister; /* * GetRegistersAvailable returns a mask indicating which registers * are available in the given register set. Registers may be unavailable * if their value is undeterminable for the given situation. The returned * word contains a bit for each register (1 << register index), which will * be 1 if the register is available or 0 if it is not. */ HRESULT GetRegistersAvailable([out] ULONG64 *pAvailable); /* * GetRegisters returns an array of register values corresponding * to the given mask. The registers which have their bit set in * the mask will be packed into the resulting array. (No room is * assigned in the array for registers whose mask bit is not set.) * Thus, the size of the array should be equal to the number of * 1's in the mask. * * If an unavailable register is indicated by the mask, an indeterminate * value will be returned for the corresponding register. * * registerBufferCount should indicate number of elements in the * buffer to receive the register values. If it is too small for * the number of registers indicated by the mask, the higher * numbered registers will be truncated from the set. Or, if it * is too large, the unused registerBuffer elements will be * unmodified. */ HRESULT GetRegisters([in] ULONG64 mask, [in] ULONG32 regCount, [out, size_is(regCount), length_is(regCount)] CORDB_REGISTER regBuffer[]); /* * NOT YET IMPLEMENTED */ HRESULT SetRegisters([in] ULONG64 mask, [in] ULONG32 regCount, [in, size_is(regCount)] CORDB_REGISTER regBuffer[]); /* * GetThreadContext returns the context for the given thread. The * debugger should call this function rather than the Win32 * GetThreadContext, because the thread may actually be in a "hijacked" * state where its context has been temporarily changed. * * The data returned is a CONTEXT structure for the current platform. * * For non-leaf frames, clients should check which registers are valid by * using GetRegistersAvailable. * */ HRESULT GetThreadContext([in] ULONG32 contextSize, [in, out, length_is(contextSize), size_is(contextSize)] BYTE context[]); /* * Not implemented in v2.0. It is too dangerous to manipulate the context of * threads in Managed code. Use other high level operations (like SetIp, * ICorDebugValue::SetValue) instead. * */ HRESULT SetThreadContext([in] ULONG32 contextSize, [in, length_is(contextSize), size_is(contextSize)] BYTE context[]); } /* * ICorDebugRegisterSet2 is an extension for hardward platforms with more * than 64 registers, since ICorDebugRegisterSet::GetRegisters() only * recognizes a 64-bit mask. */ [ object, local, uuid(6DC7BA3F-89BA-4459-9EC1-9D60937B468D), pointer_default(unique) ] interface ICorDebugRegisterSet2 : IUnknown { /* * Given a CorDebugRegister value, its position in the mask is determined as * follows: * * 1) (value >> 3) is used to index the array of BYTEs, and * 2) (value & 7) (the least significant three bits) represents the bit position * within the indexed BYTE, where bit 0 is the least significant bit. * * Or, in code: * * #define REGISTER_IA64_MAX REGISTER_IA64_F0 + 128 * #define MAX_MASK_COUNT ((REGISTER_IA64_MAX + 7) >> 3) * #define SET_BIT_MASK(_mask, _reg) _mask[(_reg) >> 3] |= (1 << ((_reg) & 7)) * #define RESET_BIT_MASK(_mask, _reg) _mask[(_reg) >> 3] &= ~(1 << ((_reg) & 7)) * #define IS_SET_BIT_MASK(_mask, _reg) _mask[(_reg) >> 3] & (1 << ((_reg) & 7)) * * CorDebugRegister value = ; * BYTE pAvailable[MAX_MASK_COUNT]; * * GetRegistersAvailable(MAX_MASK_COUNT, pAvailable); * ASSERT(value < REGISTER_IA64_MAX); * IS_SET_BIT_MASK(pAvailable, value); */ HRESULT GetRegistersAvailable([in] ULONG32 numChunks, [out, size_is(numChunks)] BYTE availableRegChunks[]); HRESULT GetRegisters([in] ULONG32 maskCount, [in, size_is(maskCount)] BYTE mask[], [in] ULONG32 regCount, [out, size_is(regCount)] CORDB_REGISTER regBuffer[]); HRESULT SetRegisters([in] ULONG32 maskCount, [in, size_is(maskCount)] BYTE mask[], [in] ULONG32 regCount, [in, size_is(regCount)] CORDB_REGISTER regBuffer[]); } /* * ICorDebugThread represents a thread in the process. The lifetime of a * thread object is equal to the lifetime of the thread it represents. */ [ object, local, uuid(938c6d66-7fb6-4f69-b389-425b8987329b), pointer_default(unique) ] interface ICorDebugThread : IUnknown { /* * GetProcess returns the process of which this thread is a part. */ HRESULT GetProcess([out] ICorDebugProcess **ppProcess); /* * GetID returns the current OS ID of the active part of the thread. * Note that this may theoretically change as the process executes, * and even be different for different parts of the thread. */ HRESULT GetID([out] DWORD *pdwThreadId); /* * GetHandle returns the current Handle of the active part of the thread. * Note that this may theoretically change as the process executes, * and even be different for different parts of the thread. * * This handle is owned by the debugging API. The debugger should duplicate * it before using it. */ HRESULT GetHandle([out] HTHREAD *phThreadHandle); /* * GetAppDomain returns the app domain which the thread is currently * executing in. */ HRESULT GetAppDomain([out] ICorDebugAppDomain **ppAppDomain); /* * SetDebugState sets the current debug state of the thread. * (The "current debug state" * represents the debug state if the process were to be continued, * not the actual current state.) * * The normal value for this is THREAD_RUNNING. Only the debugger * can affect the debug state of a thread. Debug states do * last across continues, so if you want to keep a thread * THREAD_SUSPENDed over multiple continues, you can set it once * and thereafter not have to worry about it. * * Suspending threads and resuming the process can cause deadlocks, though it's * usually unlikely. This is an intrinsic quality of threads and processes and is by-design. * A debugger can async break and resume the threads to break the deadlock. * * If the thread's user state includes USER_UNSAFE_POINT, then the thread may block a GC. * This means the suspended thread has a mcuh higher chance of causing a deadlock. * * This may not affect debug events already queued. Thus a debugger should drain the entire * event queue (via calling HasQueuedCallbacks) before suspending or resuming threads. Else it * may get events on a thread that it believes it has already suspended. * */ HRESULT SetDebugState([in] CorDebugThreadState state); /* * GetDebugState returns the current debug state of the thread. * (If the process is currently stopped, the "current debug state" * represents the debug state if the process were to be continued, * not the actual current state.) */ HRESULT GetDebugState([out] CorDebugThreadState *pState); /* * GetUserState returns the user state of the thread, that is, the state * which it has when the program being debugged examines it. * A thread may have multiple state bits set. */ typedef enum CorDebugUserState { USER_STOP_REQUESTED = 0x01, USER_SUSPEND_REQUESTED = 0x02, USER_BACKGROUND = 0x04, USER_UNSTARTED = 0x08, USER_STOPPED = 0x10, USER_WAIT_SLEEP_JOIN = 0x20, USER_SUSPENDED = 0x40, // An "unsafe point" is a place where the thread may block a Garbage Collection (GC). // Debug events may be dispatched from unsafe points, but suspending a thread at // an unsafe spot will very likely cause a deadlock (until the thread is resumed). // This is a function of the thread's IP and the available GC info. The exact details // of what is safe and unsafe is unspecified and highly determined by jit/gc implementation details. USER_UNSAFE_POINT = 0x80, // indicates that this thread is a threadpool thread USER_THREADPOOL = 0x100, } CorDebugUserState; HRESULT GetUserState([out] CorDebugUserState *pState); /* * GetCurrentException returns the exception object which is * currently being thrown by the thread. This will exist from the time the exception * is thrown until the end of the catch block. That range will include filters * and finallys. * * FuncEval will clear out the exception object on setup and restore it on completion. * * Exceptions can be nested (eg, if an exception is thrown in filter or a func-eval), * so there may be multiple outstanding exceptions on a single thread. * This returns the most current exception. * * The exception object and type may change throughout the life of the exception. For example, an * exception of type X may be thrown, but then the CLR may run out of memory and promote * that to an OutOfMemory exception. */ HRESULT GetCurrentException([out] ICorDebugValue **ppExceptionObject); /* * This is not implemented. */ HRESULT ClearCurrentException(); /* * CreateStepper creates a stepper object which operates relative * to the active frame in the given thread. (Note that this may be * unmanaged code.) The Stepper API must then be used to perform * actual stepping. * */ HRESULT CreateStepper([out] ICorDebugStepper **ppStepper); /* * EnumerateChains returns an enum which will return all the stack * chains in the thread, starting at the active (most recent) one. * These chains represent the physical call stack for the thread. * * Chain boundaries occur for several reasons: * managed <-> unmanaged transitions * context switches * debugger hijacking of user threads * * Note that in the simple case for a thread running purely * managed code in a single context there will be a one to one * correspondence between threads & chains. * * A debugger may want to rearrange the physical call * stacks of all threads into logical call stacks. This would involve * sorting all the threads' chains by their caller/callee * relationships & regrouping them. * */ HRESULT EnumerateChains([out] ICorDebugChainEnum **ppChains); /* * GetActiveChain is a convenience routine to return the * active (most recent) chain on the thread, if any. * */ HRESULT GetActiveChain([out] ICorDebugChain **ppChain); /* * GetActiveFrame is a convenience routine to return the * active (most recent) frame on the thread, if any. * If there are no frames on the stack, ppFrame will point to NULL * and the function still returns S_OK. */ HRESULT GetActiveFrame([out] ICorDebugFrame **ppFrame); /* * GetRegisterSet returns the register set for the active part * of the thread. * */ HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters); /* * CreateEval creates an evaluation object which operates on the * given thread. The Eval will push a new chain on the thread before * doing its computation. * * Note that this interrupts the computation currently * being performed on the thread until the eval completes. * */ HRESULT CreateEval([out] ICorDebugEval **ppEval); /* * Returns the runtime thread object. */ HRESULT GetObject([out] ICorDebugValue **ppObject); }; /* * ICorDebugThread2 is a logical extension to ICorDebugThread. */ [ object, local, uuid(2BD956D9-7B07-4bef-8A98-12AA862417C5), pointer_default(unique) ] interface ICorDebugThread2 : IUnknown { typedef struct _COR_ACTIVE_FUNCTION { ICorDebugAppDomain *pAppDomain; // Pointer to the owning AppDomain of the below IL Offset. ICorDebugModule *pModule; // Pointer to the owning Module of the below IL Offset. ICorDebugFunction2 *pFunction; // Pointer to the owning Function of the below IL Offset. ULONG32 ilOffset; // IL Offset of the frame. ULONG32 flags; // Bit mask of flags, currently unused. Reserved. } COR_ACTIVE_FUNCTION; /* * Retrieves the active functions for the given threads' frames. This * includes AppDomain ID, Module ID, Funtion ID and IL offset for * each active statement on the stack. A flags field is also included * for future information about the frame that might need to be conveyed. * * If pFunctions is NULL, returns only the number of functions that * is on the stack in pcFunctions. */ HRESULT GetActiveFunctions([in] ULONG32 cFunctions, [out] ULONG32 *pcFunctions, [in, out, size_is(cFunctions), length_is(*pcFunctions)] COR_ACTIVE_FUNCTION pFunctions[] ); /* * Returns 0 if not part of a connection * Maps to a SPID in SQL Server */ HRESULT GetConnectionID( [out] CONNID *pdwConnectionId); /* * Return the TASKID of this thread. */ HRESULT GetTaskID( [out] TASKID *pTaskId); /* * Return the OS Thread ID */ HRESULT GetVolatileOSThreadID( [out] DWORD *pdwTid); /* * Allow the debugger to intercept the current exception on a thread. It can be * called between an Exception callback and the associated call to ICorDebugProcess::Continue. * * pFrame specifies where we should intercept the exception. It must be a valid ICDFrame pointer, * which can be obtained from a stackwalk. However, you must not call Continue() between * doing the stackwalk and calling this function. */ HRESULT InterceptCurrentException( [in] ICorDebugFrame *pFrame); } /* * ICorDebugThread3 is a logical extension to ICorDebugThread. */ [ object, local, uuid(F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5), pointer_default(unique) ] interface ICorDebugThread3 : IUnknown { HRESULT CreateStackWalk([out] ICorDebugStackWalk **ppStackWalk); HRESULT GetActiveInternalFrames([in] ULONG32 cInternalFrames, [out] ULONG32 *pcInternalFrames, [in, out, size_is(cInternalFrames), length_is(*pcInternalFrames)] ICorDebugInternalFrame2 * ppInternalFrames[] ); }; /* * ICorDebugThread4 is a logical extension to ICorDebugThread. */ [ object, local, uuid(1A1F204B-1C66-4637-823F-3EE6C744A69C), pointer_default(unique) ] interface ICorDebugThread4 : IUnknown { /* * Returns S_OK if ICorDebugThread::GetCurrentException() is non-NULL and the exception * it refers to has completed the first pass of exception handling without locating * a catch clause. * Returns S_FALSE if there is no exception, it hasn't completed first pass handling, * or a catch handler was located * Returns an appropriate error HRESULT when the answer can not be determined */ HRESULT HasUnhandledException(); HRESULT GetBlockingObjects([out] ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); /* * Gets the current CustomNotification object on the current thread. This could be NULL if no * current notification object exists. If we aren't currently inside a CustomNotification callback, * this will always return NULL. * A debugger can examine this object to determine how to handle the notification. * See ICorDebugManagedCallback3::CustomNotification for more information about * custom notifications. */ HRESULT GetCurrentCustomDebuggerNotification([out] ICorDebugValue ** ppNotificationObject); }; /* * ICorDebugThread5 is a logical extension to ICorDebugThread. */ [ object, local, uuid(F98421C4-E506-4D24-916F-0237EE853EC6), pointer_default(unique) ] interface ICorDebugThread5 : IUnknown { /* * Returns S_OK if it was possible to obtain the allocation information for the thread * and sets the corresponding SOH and UOH allocations. * Returns E_INVALIDARG if any of the pointers for the outputs is null. * Can return E_FAIL if the process is not properly stopped. */ HRESULT GetBytesAllocated([out] ULONG64 *pSohAllocatedBytes, [out] ULONG64 *pUohAllocatedBytes); }; /* * The new V3.0 stackwalking API. */ [ object, local, uuid(A0647DE9-55DE-4816-929C-385271C64CF7), pointer_default(unique) ] interface ICorDebugStackWalk : IUnknown { typedef enum CorDebugSetContextFlag { SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1, SET_CONTEXT_FLAG_UNWIND_FRAME = 0x2, } CorDebugSetContextFlag; /* * Get the current context of this stack frame. * * The CONTEXT is retrieved from the ICorDebugStackWalk. As unwinding may only restore a subset of the * registers, such as only non-volatile registers, the context may not exactly match the register state at * the time of the actual call. */ HRESULT GetContext([in] ULONG32 contextFlags, [in] ULONG32 contextBufSize, [out] ULONG32* contextSize, [out, size_is(contextBufSize)] BYTE contextBuf[]); /* * Change the current context of this stack walk, allowing the * debugger to move it to an arbitrary context. Does not actually * alter the current context of the thread whose stack is being walked. * * The CONTEXT has to be a valid CONTEXT of a stack frame on the thread. * If the CONTEXT is outside of the current thread's stack range, we'll * return a failure HRESULT. Otherwise, in the case of an invalid CONTEXT, * the result is undefined. */ HRESULT SetContext([in] CorDebugSetContextFlag flag, [in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE context[]); /* * Attempt to advance the stackwalk to the next frame. * If the current frame type is a native stack frame, Next() will not advance to the caller frame. * Instead, Next() will advance to the next managed stack frame or the next internal frame marker. * * If a debugger wants to unwind unmanaged stack frames, it needs to start from the * native stack frame itself. It can seed the unwind by calling GetContext(). * * This function will return CORDBG_S_AT_END_OF_STACK when there are no more frames. */ HRESULT Next(); /* * Return the current frame. If the stackwalker is stopped at a native stack frame, we will return S_FALSE * and set pFrame to NULL. */ HRESULT GetFrame([out] ICorDebugFrame ** pFrame); }; /* * ICorDebugChain represents a segment of a physical or logical call * stack. All frames in a chain occupy contiguous stack space, and * they share the same thread & context. A chain may represent either * managed or unmanaged code. Chains may be empty. Unmanaged chains are * always empty. */ [ object, local, uuid(CC7BCAEE-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugChain : IUnknown { /* * GetThread returns the physical thread which this call chain is * part of. */ HRESULT GetThread([out] ICorDebugThread **ppThread); /* * GetStackRange returns the address range of the stack segment for the * call chain. Note that you cannot make any assumptions about * what is actually stored on the stack - the numeric range is to compare * stack frame locations only. * The start of a stack range is the leafmost boundary of the chain, and * the end of a stack range is the rootmost boundary of the chain. */ HRESULT GetStackRange([out] CORDB_ADDRESS *pStart, [out] CORDB_ADDRESS *pEnd); /* * NOT YET IMPLEMENTED */ HRESULT GetContext([out] ICorDebugContext **ppContext); /* * GetCaller returns a pointer to the chain which called this * chain. Note that this may be a chain on another thread in the * case of cross-thread-marshalled calls. The caller will be NULL * for spontaneously called chains (e.g. the ThreadProc, a * debugger initiated call, etc.) */ HRESULT GetCaller([out] ICorDebugChain **ppChain); /* * GetCallee returns a pointer to the chain which this chain is * waiting on before it resumes. Note that this may be a chain on * another thread in the case of cross-thread-marshalled * calls. The callee will be NULL if the chain is currently * actively running. */ HRESULT GetCallee([out] ICorDebugChain **ppChain); /* * GetPrevious returns a pointer to the chain which was on this * thread before the current one was pushed, if there is one. */ HRESULT GetPrevious([out] ICorDebugChain **ppChain); /* * GetNext returns a pointer to the chain which was pushed on this * thread after the current one, if there is one. */ HRESULT GetNext([out] ICorDebugChain **ppChain); /* * IsManaged returns whether or not the chain is running managed * code. */ HRESULT IsManaged([out] BOOL *pManaged); /* * These chains represent the physical call stack for the thread. * EnumerateFrames returns an iterator which will list all the stack * frames in the chain, starting at the active (most recent) one. This * should be called only for managed chains. * * NOTE: The debugging API does not provide methods for obtaining * frames contained in unmanaged chains. The debugger needs to use * other means to obtain this information. */ HRESULT EnumerateFrames([out] ICorDebugFrameEnum **ppFrames); /* * GetActiveFrame is a convenience routine to return the * active (most recent) frame on the chain, if any. * * If the active frame is not available, the call will succeed * and *ppFrame will be NULL. Active frames will not be available * for all CHAIN_ENTER_UNMANAGED chains, and for some * CHAIN_CLASS_INIT chains. */ HRESULT GetActiveFrame([out] ICorDebugFrame **ppFrame); /* * GetRegisterSet returns the register set for the beginnning (the leafmost end) * of the chain. */ HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters); /* * GetReason returns the reason for the genesis of this calling chain. */ typedef enum CorDebugChainReason { // Note that the first five line up with CorDebugIntercept CHAIN_NONE = 0x000, CHAIN_CLASS_INIT = 0x001, CHAIN_EXCEPTION_FILTER = 0x002, CHAIN_SECURITY = 0x004, CHAIN_CONTEXT_POLICY = 0x008, CHAIN_INTERCEPTION = 0x010, CHAIN_PROCESS_START = 0x020, CHAIN_THREAD_START = 0x040, CHAIN_ENTER_MANAGED = 0x080, CHAIN_ENTER_UNMANAGED = 0x100, CHAIN_DEBUGGER_EVAL = 0x200, CHAIN_CONTEXT_SWITCH = 0x400, CHAIN_FUNC_EVAL = 0x800, } CorDebugChainReason; HRESULT GetReason([out] CorDebugChainReason *pReason); }; [ object, local, uuid(CC7BCAEF-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugFrame : IUnknown { /* * GetChain returns the chain of which this stack frame is a part. */ HRESULT GetChain([out] ICorDebugChain **ppChain); /* * GetCode returns the code which this stack frame is running if any. */ HRESULT GetCode([out] ICorDebugCode **ppCode); /* * GetFunction returns the function for the code which this stack * frame is running. * For ICorDebugInternalFrames, this may point to a method the * frame is associated with (which may be in a different AppDomain * from the frame itself), or may fail if the frame doesn't relate to any * particular function. */ HRESULT GetFunction([out] ICorDebugFunction **ppFunction); /* * GetFunctionToken is a convenience routine to return the token for the * function for the code which this stack frame is running. * The scope to resolve the token can be gotten from the ICorDebugFunction * associated with this frame. */ HRESULT GetFunctionToken([out] mdMethodDef *pToken); /* * GetStackRange returns the absolute address range of the stack * frame. (This is useful for piecing together interleaved stack * traces gathered from multiple debugging engines.) Note that you * cannot make any assumptions about what is actually stored on * the stack - the numeric range is to compare stack frame * locations only. * The start of a stack range is the leafmost boundary of the frame, and * the end of a stack range is the rootmost boundary of the frame. */ HRESULT GetStackRange([out] CORDB_ADDRESS *pStart, [out] CORDB_ADDRESS *pEnd); /* * GetCaller returns a pointer to the frame in the current chain * which called this frame, or NULL if this is the rootmost frame * in the chain. */ HRESULT GetCaller([out] ICorDebugFrame **ppFrame); /* * GetCallee returns a pointer to the frame in the current chain * which this frame called, or NULL if this is the leafmost frame * in the chain. */ HRESULT GetCallee([out] ICorDebugFrame **ppFrame); /* * CreateStepper creates a stepper object which operates relative to the * frame. The Stepper API must then be used to perform actual stepping. * * Note that if this frame is not active, the frame will typically have to * be returned to before the step is completed. * */ HRESULT CreateStepper([out] ICorDebugStepper **ppStepper); }; [ object, local, uuid(B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4), pointer_default(unique) ] interface ICorDebugInternalFrame : ICorDebugFrame { typedef enum CorDebugInternalFrameType { // This is a 'null' value for GetFrameType and is included for completeness sake. // ICorDebugInternalFrame::GetFrameType() should never actually return this. STUBFRAME_NONE = 0x00000000, // This frame is a M2U stub-frame. This could include both PInvoke // and COM-interop calls. STUBFRAME_M2U = 0x0000001, // This is a U2M stub frame. STUBFRAME_U2M = 0x0000002, // AppDomain transition. STUBFRAME_APPDOMAIN_TRANSITION = 0x00000003, // LightWeight method calls. STUBFRAME_LIGHTWEIGHT_FUNCTION = 0x00000004, // Start of Func-eval. This is included for CHF callbacks. // Funcevals also have a chain CHAIN_FUNC_EVAL (legacy from v1.0) STUBFRAME_FUNC_EVAL = 0x00000005, // Start of an internal call into the CLR. STUBFRAME_INTERNALCALL = 0x00000006, // start of a class initialization; corresponds to CHAIN_CLASS_INIT STUBFRAME_CLASS_INIT = 0x00000007, // an exception is thrown; corresponds to CHAIN_EXCEPTION_FILTER STUBFRAME_EXCEPTION = 0x00000008, // a frame used for code-access security purposes; corresponds to CHAIN_SECURITY STUBFRAME_SECURITY = 0x00000009, // a frame used to mark that the runtime is jitting a managed method STUBFRAME_JIT_COMPILATION = 0x0000000a, } CorDebugInternalFrameType; // Get the type of internal frame. This will never be STUBFRAME_NONE. // Debuggers should gracefully ignore unrecognized internal frame types. HRESULT GetFrameType([out] CorDebugInternalFrameType * pType); }; [ object, local, uuid(C0815BDC-CFAB-447e-A779-C116B454EB5B), pointer_default(unique) ] interface ICorDebugInternalFrame2 : IUnknown { /* * Returns the stack address of the internal frame marker. */ HRESULT GetAddress([out] CORDB_ADDRESS *pAddress); /* * Check if an internal frame is closer to the leaf than pFrameToCompare. */ HRESULT IsCloserToLeaf([in] ICorDebugFrame * pFrameToCompare, [out] BOOL * pIsCloser); }; /* * ICorDebugILFrame is a specialized interface of ICorDebugFrame for IL frames or jitted frames. * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.) */ [ object, local, uuid(03E26311-4F76-11d3-88C6-006097945418), pointer_default(unique) ] interface ICorDebugILFrame : ICorDebugFrame { /* * GetIP returns the stack frame's offset into the function's IL code. * If this stack frame is active, this address is the next * instruction to execute. If this stack frame is not active, this is the * next instruction to execute when the stack frame is reactivated. * * Note that if this a jitted frame, the IP will be determined by * mapping backwards from the actual native IP, so the value may * be only approximately correct. * * If pMappingResult is not NULL, A mapping result is returned which * indicates the details of how the IP was obtained. The following values * can be returned: * * MAPPING_EXACT - the IP is correct; either the frame is * interpreted or there is an exact IL map for the function. * * MAPPING_APPROXIMATE - the IP was successfully mapped, but may * be only approximately correct * * MAPPING_UNMAPPED_ADDRESS - although there is mapping info for * the function, the current address is not mappable to IL. An * IP of 0 is returned. * * MAPPING_PROLOG - the native code is in the prolog, so an IP of * 0 is returned * * MAPPING_EPILOG - the native code is in an epilog, so the last * IP of the method is returned * * MAPPING_NO_INFO - no mapping info is available for the method, * so an IP of 0 is returned * */ typedef enum CorDebugMappingResult { MAPPING_PROLOG = 0x1, MAPPING_EPILOG = 0x2, MAPPING_NO_INFO = 0x4, MAPPING_UNMAPPED_ADDRESS = 0x8, MAPPING_EXACT = 0x10, MAPPING_APPROXIMATE = 0x20, } CorDebugMappingResult; HRESULT GetIP([out] ULONG32 *pnOffset, [out] CorDebugMappingResult *pMappingResult); /* * SetIP sets the instruction pointer to the IL at the given offset. * The debugger will do its best to fix up the state of the executing code * so that it is consistent with the new IP as far as the EE is concerned, * while preserving as much of the state of the user program as possible. * * Calling SetIP immediately invalidates all frames and chains for the * current thread; the debugger must perform a new stack trace if it * requires frame information after calling SetIP. * */ HRESULT SetIP([in] ULONG32 nOffset); /* * EnumerateLocalVariables returns a list of the local variables * available in the frame. Note that this may not include all of * the locals in the running function, as some of them may not be * active. */ HRESULT EnumerateLocalVariables([out] ICorDebugValueEnum **ppValueEnum); /* * GetLocalVariable gets the value for a local variable * in an IL frame. This can be used either in an IL * frame or a jitted frame. */ HRESULT GetLocalVariable([in] DWORD dwIndex, [out] ICorDebugValue **ppValue); /* * EnumerateArguments returns a list of the arguments available in the * frame. Note that this will include varargs arguments as well as * arguments declared by the function signature (inlucding the implicit * "this" argument if any). */ HRESULT EnumerateArguments([out] ICorDebugValueEnum **ppValueEnum); /* * GetArgument gets the value for an argument * in an IL frame. This can be used either in an IL * frame or a jitted frame. * For instance (non-static) methods, argument index 0 is the "this" object, * and the normal explicit arguments start with index 1. */ HRESULT GetArgument([in] DWORD dwIndex, [out] ICorDebugValue **ppValue); /* * NOT YET IMPLEMENTED */ HRESULT GetStackDepth([out] ULONG32 *pDepth); /* * NOT YET IMPLEMENTED */ HRESULT GetStackValue([in] DWORD dwIndex, [out] ICorDebugValue **ppValue); /* * CanSetIP attempts to determine if it's safe to set the instruction pointer * to the IL at the given offset. If this returns S_OK, then executing * SetIP (see above) will result in a safe, correct, continued execution. * If CanSetIP returns anything else, SetIP can still be invoked, but * continued, correct execution of the debuggee cannot be guaranteed. * */ HRESULT CanSetIP([in] ULONG32 nOffset); }; /* * ICorDebugILFrame2 is a logical extension to ICorDebugILFrame. */ [ object, local, uuid(5D88A994-6C30-479b-890F-BCEF88B129A5), pointer_default(unique) ] interface ICorDebugILFrame2 : IUnknown { /* * Performs an on-stack replacement for an outstanding function remap opportunity. * This is used to update execution of an edited function to the latest version, * preserving the current frame state (such as the values of all locals). * This can only be called when a FunctionRemapOpportunity callback has been delivered * for this leaf frame, and the callback has not yet been continued. newILOffset * is the offset into the new function at which execution should continue. * When the remap has completed, a FunctionRemapComplete callback will be delivered. */ HRESULT RemapFunction([in] ULONG32 newILOffset); /* * EnumerateTypeParameters returns the type parameters active on a frame. * This will include both the class type parameters (if any) followed by the method type * parameters (if any). * Use the metadata API IMetaDataImport2::EnumGenericParams to determine how many * Class type parameters vs. Method Type parameters there are in this list. * The type parameters will not always be available. */ HRESULT EnumerateTypeParameters([out] ICorDebugTypeEnum **ppTyParEnum); }; [ object, local, uuid(9A9E2ED6-04DF-4FE0-BB50-CAB64126AD24), pointer_default(unique) ] interface ICorDebugILFrame3 : IUnknown { /* * For the specified IL offset, obtains an ICorDebugValue object that encapsulates * the return value of a function. The provided IL offset should be at a function * call site and the debuggee should be stopped at a breakpoint set at the native * offset returned by ICorDebugCode3::GetNativeOffsetForReturnValueBreakpoint for * the same IL offset. * If the debuggee is not stopped at the correct location for the specified IL offset * the API will fail. * If the function call doesn't return a value the API will fail. */ HRESULT GetReturnValueForILOffset(ULONG32 ILoffset, [out] ICorDebugValue** ppReturnValue); }; typedef enum ILCodeKind { ILCODE_ORIGINAL_IL = 0x1, ILCODE_REJIT_IL = 0x2, } ILCodeKind; [ object, local, uuid(AD914A30-C6D1-4AC5-9C5E-577F3BAA8A45), pointer_default(unique) ] interface ICorDebugILFrame4 : IUnknown { /* * EnumerateLocalVariablesEx returns a list of the local variables * available in the frame. Note that this may not include all of * the locals in the running function, as some of them may not be * active. The Ex version of this function optionally accesses * variables added in profiler ReJIT instrumentation. * * flags: * ILCODE_ORIGINAL_IL preserves the same behavior as calling * EnermateLocalVariables in ICorDebugILFrame. * If the method is instrumented with additional locals, those locals * will not be viewable. * ILCODE_REJIT_IL allows viewing the locals defined * in the profiler's updated local var signature included with the * instrumented IL. If the IL is not instrumented the enumeration will * be empty and S_OK is returned. */ HRESULT EnumerateLocalVariablesEx([in] ILCodeKind flags, [out] ICorDebugValueEnum **ppValueEnum); /* * GetLocalVariableEx gets the value for a local variable * in an IL frame. The Ex version of this function optionally accesses * variables added in profiler ReJIT instrumentation. * * flags: * ILCODE_ORIGINAL_IL preserves the same behavior as calling * GetLocalVariable in ICorDebugILFrame. * If the method is instrumented with additional locals, those locals * will not be addressable or viewable. * ILCODE_REJIT_IL allows viewing the locals defined * in the profiler's updated local var signature included with the * instrumented IL. If the IL is not instrumented the method will * return E_INVALIDARG. */ HRESULT GetLocalVariableEx([in] ILCodeKind flags, [in] DWORD dwIndex, [out] ICorDebugValue **ppValue); /* * GetCode returns the code which this stack frame is running if any. * * flags: * ILCODE_ORIGINAL_IL preserves the same behavior as calling * GetCode in ICorDebugFrame. * If the method is instrumented that IL will not be visible. * ILCODE_REJIT_IL allows viewing the IL defined by the profiler's * rejit request. If the IL is not instrumented *ppCode will be * set to NULL and S_OK is returned. */ HRESULT GetCodeEx([in] ILCodeKind flags, [out] ICorDebugCode **ppCode); }; /* * ICorDebugNativeFrame is a specialized interface of ICorDebugFrame for jitted frames, i.e. * native frames for managed methods. * (Note that jitted frames implement both ICorDebugILFrame and ICorDebugNativeFrame.) */ [ object, local, uuid(03E26314-4F76-11d3-88C6-006097945418), pointer_default(unique) ] interface ICorDebugNativeFrame : ICorDebugFrame { /* * GetIP returns the stack frame's offset into the function's * native code. If this stack frame is active, this address is * the next instruction to execute. If this stack frame is not * active, this is the next instruction to execute when the stack * frame is reactivated. */ HRESULT GetIP([out] ULONG32 *pnOffset); /* * SetIP sets the instruction pointer to the given native * offset. CorDebug will attempt to keep the stack frame in a * coherent state. (Note that even if the frame is in a valid * state as far as the runtime is concerned, there still may be * problems - e.g. uninitialized local variables, etc. The caller * (or perhaps the user) is responsible for insuring coherency of * the running program.) * * Calling SetIP immediately invalidates all frames and chains for the * current thread; the debugger must perform a new stack trace if it * requires frame information after calling SetIP. */ HRESULT SetIP([in] ULONG32 nOffset); /* * GetRegisterSet returns the register set for the given frame. * */ HRESULT GetRegisterSet([out] ICorDebugRegisterSet **ppRegisters); /* * GetLocalRegisterValue gets the value for a local variable or * argument stored in a register of a native frame. This can be * used either in a native frame or a jitted frame. */ HRESULT GetLocalRegisterValue([in] CorDebugRegister reg, [in] ULONG cbSigBlob, [in] PCCOR_SIGNATURE pvSigBlob, [out] ICorDebugValue **ppValue); /* * GetLocalDoubleRegisterValue gets the value for a local variable * or argument stored in 2 registers of a native frame. This can * be used either in a native frame or a jitted frame. */ HRESULT GetLocalDoubleRegisterValue([in] CorDebugRegister highWordReg, [in] CorDebugRegister lowWordReg, [in] ULONG cbSigBlob, [in] PCCOR_SIGNATURE pvSigBlob, [out] ICorDebugValue **ppValue); /* * GetLocalMemoryValue gets the value for a local variable stored * at the given address. */ HRESULT GetLocalMemoryValue([in] CORDB_ADDRESS address, [in] ULONG cbSigBlob, [in] PCCOR_SIGNATURE pvSigBlob, [out] ICorDebugValue **ppValue); /* * GetLocalRegisterMemoryValue gets the value for a local which * is stored half in a register and half in memory. */ HRESULT GetLocalRegisterMemoryValue([in] CorDebugRegister highWordReg, [in] CORDB_ADDRESS lowWordAddress, [in] ULONG cbSigBlob, [in] PCCOR_SIGNATURE pvSigBlob, [out] ICorDebugValue **ppValue); /* * GetLocalMemoryRegisterValue gets the value for a local which * is stored half in a register and half in memory. */ HRESULT GetLocalMemoryRegisterValue([in] CORDB_ADDRESS highWordAddress, [in] CorDebugRegister lowWordRegister, [in] ULONG cbSigBlob, [in] PCCOR_SIGNATURE pvSigBlob, [out] ICorDebugValue **ppValue); /* * CanSetIP attempts to determine if it's safe to set the instruction pointer * to the given native offset. If this returns S_OK, then executing * SetIP (see above) will result in a safe, correct, continued execution. * If CanSetIP returns anything else, SetIP can still be invoked, but * continued, correct execution of the debuggee cannot be guaranteed. * */ HRESULT CanSetIP([in] ULONG32 nOffset); }; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugModule */ [ object, local, uuid(35389FF1-3684-4c55-A2EE-210F26C60E5E), pointer_default(unique) ] interface ICorDebugNativeFrame2 : IUnknown { /* * Returns true if the current frame is a child frame. */ HRESULT IsChild([out] BOOL *pIsChild); /* * Return true if the specified frame is the parent frame of the current frame. */ HRESULT IsMatchingParentFrame([in] ICorDebugNativeFrame2 *pPotentialParentFrame, [out] BOOL *pIsParent); /* * Return the stack parameter size on x86. On other platforms, we return S_FALSE and set pSize to 0. * This is because other platforms don't need this information for unwinding. */ HRESULT GetStackParameterSize([out] ULONG32 * pSize); }; /* * ICorDebugModule3 is a logical extension to ICorDebugModule. */ [ object, local, uuid(86F012BF-FF15-4372-BD30-B6F11CAAE1DD), pointer_default(unique) ] interface ICorDebugModule3 : IUnknown { /* * CreateReaderForInMemorySymbols creates a debug symbol reader object (eg. * ISymUnmanagedReader) for a dynamic module. This symbol reader becomes stale * and is usually discarded whenever a LoadClass callback is delivered for the * module. * * Arguments: * riid - The IID of the COM interface to return (typically IID_ISymUnmanagedReader) * ppObj - Where to store the reader interface. * * Return Value: * S_OK on success * Error hresults otherwise, including: * CORDBG_E_MODULE_LOADED_FROM_DISK if this isn't an in-memory or dynamic module * CORDBG_E_SYMBOLS_NOT_AVAILABLE if symbols weren't supplied by the application or aren't * yet available. * * Notes: * This API can also be used to create a symbol reader object for in-memory * (non-dynamic) modules, but only after the symbols are first available * (indicated by the UpdateModuleSymbols callback). * * This API returns a new reader instance every time it is called (like CoCreateInstance) * and so the debugger should cache the result and only request a new one when * the underlying data may have changed (i.e. a LoadClass event). * * Dynamic modules do not have any symbols available until the first type has been * loaded into them (as indicated by the LoadClass callback). */ HRESULT CreateReaderForInMemorySymbols([in] REFIID riid, [out][iid_is(riid)] void **ppObj); } /* * ICorDebugModule4 is a logical extension to ICorDebugModule. */ [ object, local, uuid(FF8B8EAF-25CD-4316-8859-84416DE4402E), pointer_default(unique) ] interface ICorDebugModule4 : IUnknown { /* * Query to see if the module is loaded into memory in mapped/hydrated format * * Arguments: * pIsMapped - BOOL to store mapping information. TRUE will represent mapped format while FALSE represents flat format. * Return Value: * S_OK in successful case. * S_FALSE if they layout could not be determined. * Notes: * The pIsMapped value set in pIsMapped should only be interpreted as valid * when this function returns S_OK. All other return values (including * S_FALSE) indicate that the layout could not be determined and pIsMapped * should be ignored. */ HRESULT IsMappedLayout([out] BOOL *pIsMapped); } /* * ICorDebugRuntimeUnwindableFrame is a specialized interface of ICorDebugFrame for unmanaged methods * which requires special knowledge to unwind. They are not jitted code. When the debugger sees this type * of frames, it should use ICorDebugStackWalk::Next() to unwind, but it should do inspection itself. * The debugger can call ICorDebugStackWalk::GetContext() to retrieve the CONTEXT of the frame when it gets * an ICorDebugRuntimeUnwindableFrame. */ [ object, local, uuid(879CAC0A-4A53-4668-B8E3-CB8473CB187F), pointer_default(unique) ] interface ICorDebugRuntimeUnwindableFrame : ICorDebugFrame { } /* * ICorDebugModule represents a Common Language Runtime module that is loaded into a * specific AppDomain. Normally this is an executable or a DLL, but it may also be * some other file of a multi-module assembly. There is an ICorDebugModule instance * for each AppDomain a module is loaded into, even in the case of shared modules like * CoreLib. */ [ object, local, uuid(dba2d8c1-e5c5-4069-8c13-10a7c6abf43d), pointer_default(unique) ] interface ICorDebugModule : IUnknown { /* * GetProcess returns the process of which this module is a part. */ HRESULT GetProcess([out] ICorDebugProcess **ppProcess); /* * GetBaseAddress returns the base address of the module. * * For modules loaded from NGEN images, the base address will be 0. */ HRESULT GetBaseAddress([out] CORDB_ADDRESS *pAddress); /* * GetAssembly returns the assembly of which this module is a part. */ HRESULT GetAssembly([out] ICorDebugAssembly **ppAssembly); /* * GetName returns a name identifying the module. * * For on-disk modules this is a full path. For dynamic modules this * is just the filename if one was provided. Otherwise, and for other * in-memory modules, this is just the simple name stored in the module's * metadata. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * EnableJITDebugging controls whether the jitter preserves * debugging information for methods within this module. * If bTrackJITInfo is true, then the jitter preserves * mapping information between the IL version of a function and * the jitted version for functions in the module. If bAllowJitOpts * is true, then the jitter will generate code with certain (JIT-specific) * optimizations. * * JITDebug is enabled by default for all modules loaded when the * debugger is active. Programmatically enabling/disabling these * settings will override global settings. * */ HRESULT EnableJITDebugging([in] BOOL bTrackJITInfo, [in] BOOL bAllowJitOpts); /* * EnableClassLoadCallbacks controls whether on not LoadClass and * UnloadClass callbacks are called for the particular module. * For non-dynamic modules, they are off by default. * For dynamic modules, they are on by default and can not be disabled. */ HRESULT EnableClassLoadCallbacks([in] BOOL bClassLoadCallbacks); /* * GetFunctionFromToken returns the ICorDebugFunction from * metadata information. Returns CORDBG_E_FUNCTION_NOT_IL if * called with a methodDef that does not refer to an IL method. * In the EnC case, this will return the most recent version of the function. */ HRESULT GetFunctionFromToken([in] mdMethodDef methodDef, [out] ICorDebugFunction **ppFunction); /* * NOT YET IMPLEMENTED */ HRESULT GetFunctionFromRVA([in] CORDB_ADDRESS rva, [out] ICorDebugFunction **ppFunction); /* * GetClassFromToken returns the ICorDebugClass from metadata information. */ HRESULT GetClassFromToken([in] mdTypeDef typeDef, [out] ICorDebugClass **ppClass); /* * NOT YET IMPLEMENTED */ HRESULT CreateBreakpoint([out] ICorDebugModuleBreakpoint **ppBreakpoint); /* * DEPRECATED */ HRESULT GetEditAndContinueSnapshot([out] ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot); /* * Return a metadata interface pointer that can be used to examine the * metadata for this module. */ HRESULT GetMetaDataInterface([in] REFIID riid, [out] IUnknown **ppObj); /* * Return the token for the Module table entry for this object. The token * may then be passed to the meta data import api's. */ HRESULT GetToken([out] mdModule *pToken); /* * If this is a dynamic module, IsDynamic sets *pDynamic to true, otherwise * sets *pDynamic to false. * Dynamic modules can continue to grow new classes (receive LoadClass callbacks) even after * the module is loaded. */ HRESULT IsDynamic([out] BOOL *pDynamic); /* * GetGlobalVariableValue returns a value object for the given global * variable. */ HRESULT GetGlobalVariableValue([in] mdFieldDef fieldDef, [out] ICorDebugValue **ppValue); /* * GetSize returns the size, in bytes, of the module. * * For modules loaded from NGEN images, the size will be 0. */ HRESULT GetSize([out] ULONG32 *pcBytes); /* * If this is a module that exists only in the debuggee's memory, * then pInMemory will be set to TRUE. The Runtime supports * loading assemblies from raw streams of bytes. Such modules are * called "in memory" modules and they have no on-disk * representation. */ HRESULT IsInMemory([out] BOOL *pInMemory); }; #pragma warning(pop) /* * ICorDebugModule2 is a logical extension to ICorDebugModule. */ [ object, local, uuid(7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7), pointer_default(unique) ] interface ICorDebugModule2 : IUnknown { /* * SetUserCode sets the user-code status of all the functions on all the classes in * the module to bIsJustMyCode, except for the functions or classes in the tokens array, * which it sets to !bIsJustMyCode. * These settings erase all previous JMC settings in this module. * JMC status can be refined by calls to SetJMCStatus on the Class and Function. * Returns S_OK if all functions were set successfully, * CORDBG_E_FUNCTION_NOT_DEBUGGABLE if some function to be marked TRUE was not * debuggable. */ HRESULT SetJMCStatus([in] BOOL bIsJustMyCode, [in] ULONG32 cTokens, [in, size_is(cTokens)] mdToken pTokens[]); /* * ApplyChanges is called to apply an Edit and Continue delta to the running process. * An EnC delta consists of a delta metadata blob (created by IMetadataEmit2::SaveDelta) * and a delta IL blob (a method body stream just like the one in an on disk assembly). * If this operation fails, the debug session is considered to be in an invalid state * and must be restarted. */ HRESULT ApplyChanges([in] ULONG cbMetadata, [in, size_is(cbMetadata)] BYTE pbMetadata[], [in] ULONG cbIL, [in, size_is(cbIL)] BYTE pbIL[]); /* * SetJITCompilerFlags sets the flags that control the JIT compiler. If the set of flags is invalid, * the function will fail. This function can only be called from within the true LoadModule callback * for the given module. Attempts to call it after this callback has been delivered or in a "faked" * LoadModule callback for debugger attach will fail. */ HRESULT SetJITCompilerFlags( [in] DWORD dwFlags ); /* * GetJITCompilerFlags gets the set of flags that control the JIT compiler for this module. */ HRESULT GetJITCompilerFlags( [out] DWORD *pdwFlags ); /* * Resolve an assembly given an AssemblyRef token. Note that * this will not trigger the loading of assembly. If assembly is not yet loaded, * this will return an CORDBG_E_CANNOT_RESOLVE_ASSEMBLY error * */ HRESULT ResolveAssembly([in] mdToken tkAssemblyRef, [out] ICorDebugAssembly **ppAssembly); }; /* ICorDebugFunction represents a managed function. In the non-EnC case, it is 1:1 with a methoddef metadata token. For EnC, each version of a function has its own ICorDebugFunction instance. EnCed functions keep the same metadata tokens, but will get new ICorDebugCode instances. ICorDebugFunction does not represent generic typeparameters. That means that there's an ICDFunction for Func, but not for Func or Func. Get the generic parameters from ICorDebugIlFrame::EnumerateTypeParameters. */ [ object, local, uuid(CC7BCAF3-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugFunction : IUnknown { /* * GetModule returns the module for the function. */ HRESULT GetModule([out] ICorDebugModule **ppModule); /* * GetClass returns the class for the function. Returns null if * the function is not a member. */ HRESULT GetClass([out] ICorDebugClass **ppClass); /* * GetToken returns the metadata methodDef token for the function. */ HRESULT GetToken([out] mdMethodDef *pMethodDef); /* * GetILCode returns the IL code for the function. Returns null * if there is no IL code for the function. Note that this will * get the IL code corresponding to this function's EnC version of * the code in the runtime, if this function has been EnC'd. */ HRESULT GetILCode([out] ICorDebugCode **ppCode); /* * GetNativeCode returns the native code for the function. * Returns null if there is no native code for the function * (i.e. it is an IL function which has not been jitted) * If this function has been jitted multiple times (Eg, generics) this * will return a random Native Code object. */ HRESULT GetNativeCode([out] ICorDebugCode **ppCode); /* * CreateBreakpoint creates a breakpoint at the start of the function. * */ HRESULT CreateBreakpoint([out] ICorDebugFunctionBreakpoint **ppBreakpoint); /* * Returns the token for the local variable signature for this function. * If there is no signature (ie, the function doesn't have any local * variables), then mdSignatureNil will be returned. */ HRESULT GetLocalVarSigToken([out] mdSignature *pmdSig); /* * Obtains the latest (largest) EnC version number for this function. * If this function has never been edited with EnC, this will return * the same value as ICorDebugFunction2::GetVersionNumber. */ HRESULT GetCurrentVersionNumber([out] ULONG32 *pnCurrentVersion); }; /* ICorDebugFunction2 is a logical extension to ICorDebugFunction. */ [ object, local, uuid(EF0C490B-94C3-4e4d-B629-DDC134C532D8), pointer_default(unique) ] interface ICorDebugFunction2 : IUnknown { /* * Sets the User-code status (for JMC stepping) for this function. * A JMC stepper will skip non-user code. * User code must be a subset of debuggable code. * Returns S_OK if successful, CORDBG_E_FUNCTION_NOT_DEBUGGABLE * if bIsJustMyCode is TRUE and the function is not debuggable. */ HRESULT SetJMCStatus([in] BOOL bIsJustMyCode); /* * IsUserCode outputs whether the function is marked as user code. * Always outputs FALSE for non-debuggable functions. * Returns S_OK if successful. */ HRESULT GetJMCStatus([out] BOOL * pbIsJustMyCode); /* * Not yet implemented. */ HRESULT EnumerateNativeCode([out] ICorDebugCodeEnum **ppCodeEnum); /* * Obtains the EnC version number of the function represented by this ICorDebugFunction2. * When a function is edited with EnC, the new function has a larger version number than * that of any previous version (not necessarily exactly 1 greater). * This function's version number will be less than or equal to the value returned by * ICorDebugFunction::GetCurrentVersionNumber. */ HRESULT GetVersionNumber([out] ULONG32 *pnVersion); }; /* ICorDebugFunction3 is a logical extension to ICorDebugFunction. */ [ object, local, uuid(09B70F28-E465-482D-99E0-81A165EB0532), pointer_default(unique) ] interface ICorDebugFunction3 : IUnknown { /* * If this function has an active rejit request it will be returned in * pRejitedILCode. * If there is no active request (a common case) then *ppRejitedILCode = NULL * * A rejit request becomes active just after execution returns from the call * ICorProfilerCallback4::GetReJITParameters(). It may not yet be jitted * and threads may still be executing in the original version of the code. * * A rejit request becomes inactive during the profiler's call to * ICorProfInfo::RequestRevert. Even after being reverted a thread can still * be executing in the rejited code. */ HRESULT GetActiveReJitRequestILCode(ICorDebugILCode **ppReJitedILCode); }; /* ICorDebugFunction4 is a logical extension to ICorDebugFunction. */ [ object, local, uuid(72965963-34fd-46e9-9434-b817fe6e7f43), pointer_default(unique) ] interface ICorDebugFunction4 : IUnknown { /* * Sets a breakpoint at offset 0 of any current or future jitted methods. */ HRESULT CreateNativeBreakpoint(ICorDebugFunctionBreakpoint **ppBreakpoint); }; /* ICorDebugCode represents an IL or native code blob. For methods that take offsets, the units are the same as the units on the CordbCode object. (eg, IL offsets for an IL code object, and native offsets for a native code object) V2 allows multiple code-regions. CordbCode presents an abstraction where these are merged together in a single linear, continuous space. So if the code is split with 0x5 bytes at address 0x1000, and 0x10 bytes at address 0x2000, then: - GetAddress() yields a start address of 0x1000. - GetSize() is the size of the merged regions = 0x5+ 0x10 = 0x15 bytes. - The (Offset --> Address) mapping is: 0x0 --> 0x1000 0x1 --> 0x1001 0x4 --> 0x1004 0x5 --> 0x2000 0x6 --> 0x2001 0x15 --> 0x2010 A caller can get the specific code regions via ICorDebugCode2. */ [ object, local, uuid(CC7BCAF4-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugCode : IUnknown { /* * IsIL returns whether the code is IL (as opposed to native.) */ HRESULT IsIL([out] BOOL *pbIL); /* * GetFunction returns the function for the code. */ HRESULT GetFunction([out] ICorDebugFunction **ppFunction); /* * GetAddress returns the address of the code. */ HRESULT GetAddress([out] CORDB_ADDRESS *pStart); /* * GetSize returns the size in bytes of the code. */ HRESULT GetSize([out] ULONG32 *pcBytes); /* * CreateBreakpoint creates a breakpoint in the function at the * given offset. * * If this code is IL code, and there is a jitted native version * of the code, the breakpoint will be applied in the jitted code * as well. (The same is true if the code is later jitted.) * */ HRESULT CreateBreakpoint([in] ULONG32 offset, [out] ICorDebugFunctionBreakpoint **ppBreakpoint); /* * GetCode returns the code of the method, suitable for disassembly. Note * that instruction boundaries aren't checked. * This glues together multiple code-regions into a single binary stream. * Caller must use ICorDebugCode2::GetCodeChunks to get (start,size) for * code chunks to be able to properly resolve addresses embedded in the instructions. */ HRESULT GetCode([in] ULONG32 startOffset, [in] ULONG32 endOffset, [in] ULONG32 cBufferAlloc, [out, size_is(cBufferAlloc), length_is(*pcBufferSize)] BYTE buffer[], [out] ULONG32 *pcBufferSize); /* * GetVersionNumber returns the 1 based number identifying the * version of the code that this ICorDebugCode corresponds to. The * version number is incremented each time the function is Edit-And- * Continue'd. */ HRESULT GetVersionNumber([out] ULONG32 *nVersion); /* * GetILToNativeMapping returns a map from IL offsets to native * offsets for this code. An array of COR_DEBUG_IL_TO_NATIVE_MAP * structs will be returned, and some of the ilOffsets in this array * map be the values specified in CorDebugIlToNativeMappingTypes. * * Note: this method is only valid for ICorDebugCodes representing * native code that was jitted from IL code. * Note: There is no ordering to the array of elements returned, nor * should you assume that there is or will be. */ HRESULT GetILToNativeMapping([in] ULONG32 cMap, [out] ULONG32 *pcMap, [out, size_is(cMap), length_is(*pcMap)] COR_DEBUG_IL_TO_NATIVE_MAP map[]); /* * Not implemented. */ HRESULT GetEnCRemapSequencePoints([in] ULONG32 cMap, [out] ULONG32 *pcMap, [out, size_is(cMap), length_is(*pcMap)] ULONG32 offsets[]); }; [ object, local, uuid(5F696509-452F-4436-A3FE-4D11FE7E2347), pointer_default(unique) ] interface ICorDebugCode2 : IUnknown { typedef struct _CodeChunkInfo { CORDB_ADDRESS startAddr; ULONG32 length; } CodeChunkInfo; // The native code for a code object may be split up into multiple regions. // HRESULT GetCodeChunks( [in] ULONG32 cbufSize, [out] ULONG32 * pcnumChunks, [out, size_is(cbufSize), length_is(*pcnumChunks)] CodeChunkInfo chunks[]); // GetCompilerFlags returns the flags under which this piece of code was JITted or NGENed. HRESULT GetCompilerFlags( [out] DWORD *pdwFlags ); }; [ object, local, uuid(D13D3E88-E1F2-4020-AA1D-3D162DCBE966), pointer_default(unique) ] interface ICorDebugCode3 : IUnknown { /* * For the specified IL offset, obtains the native offset where a breakpoint should * be placed so that the debugger can obtain the return value from a function. * The provided IL offset should be at a function call site, if not the API will fail. * If the function call doesn't return a value the API will fail. * * Returns: * S_OK - on success. * CORDBG_E_INVALID_OPCODE - If the given IL offset site was not a call instruction * or if the function returns "void". * CORDBG_E_UNSUPPORTED - If the given IL offset is a proper call, but the return * type is unsupported for getting return value. */ HRESULT GetReturnValueLiveOffset([in] ULONG32 ILoffset, [in] ULONG32 bufferSize, [out] ULONG32 *pFetched, [out, size_is(bufferSize), length_is(*pFetched)] ULONG32 pOffsets[]); }; [ object, local, uuid(18221fa4-20cb-40fa-b19d-9f91c4fa8c14), pointer_default(unique) ] interface ICorDebugCode4 : IUnknown { /* * EnumerateVariableHomes - gives an enum for local variables and arguments * in the function. * This may include multiple ICorDebugVariableHomes for the same slot or * argument index if they have different homes at different points in the * function. */ HRESULT EnumerateVariableHomes([out] ICorDebugVariableHomeEnum **ppEnum); } [ object, local, uuid(598D46C2-C877-42A7-89D2-3D0C7F1C1264), pointer_default(unique) ] interface ICorDebugILCode : IUnknown { /* * Represents an exception clause for a given piece of IL. These fields should be interpretted * the same was as an EH clause in encoded IL in the ECMA CLI specification. */ typedef struct _CorDebugEHClause { ULONG32 Flags; ULONG32 TryOffset; ULONG32 TryLength; ULONG32 HandlerOffset; ULONG32 HandlerLength; ULONG32 ClassToken; ULONG32 FilterOffset; } CorDebugEHClause; /* * Returns a list of EH clauses that were defined for this IL. The EH clause information * is defined by the CLI specification. * If cClauses is 0 and pcClauses is non-NULL, *pcClauses will be set to the number of * available EH clauses. * If cClauses is non-zero it represents the storage capacity of the clauses array, which * be filled with at most cClauses entries. *pcClauses will be set to the number of clauses * actually written into clauses array. */ HRESULT GetEHClauses( [in] ULONG32 cClauses, [out] ULONG32 * pcClauses, [out, size_is(cClauses), length_is(*pcClauses)] CorDebugEHClause clauses[]); } [ object, local, uuid(46586093-D3F5-4DB6-ACDB-955BCE228C15), pointer_default(unique) ] interface ICorDebugILCode2 : IUnknown { /* * Returns the token for the local variable signature for this function. * If there is no signature (ie, the function doesn't have any local * variables), then mdSignatureNil will be returned. */ HRESULT GetLocalVarSigToken([out] mdSignature *pmdSig); /* * GetInstrumentedILMap returns a map from profiler instrumentated IL * offsets to original method IL offsets. * * If the IL hasn't been instrumentated or the mapping wasn't provided * by a profiler then this function returns S_OK and pcMap = 0. */ HRESULT GetInstrumentedILMap([in] ULONG32 cMap, [out] ULONG32 *pcMap, [out, size_is(cMap), length_is(*pcMap)] COR_IL_MAP map[]); } /* ICorDebugClass represents a Class (mdTypeDef) in the IL image. For generic types, it represents the generic type definition (eg. List) not any of the specific instantiations (eg. List). Use ICorDebugClass2::GetParameterizedType to build an ICorDebugType from an ICorDebugClass and type parameters. Classes live in a module and are uniquely identified by a mdTypeDef. In other words, you can round-trip a class like so: ICorDebugClass * pClass1 = ...; // some initial class ICorDebugModule * pModule = NULL; pClass1->GetModule(&pModule); mdTypeDef token; pClass1->GetToken(&token); ICorDebugClass * pClass2; pModule->GetClassFromToken(token, &pClass2); // Now: pClass1 == pClass2 */ [ object, local, uuid(CC7BCAF5-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugClass : IUnknown { /* * GetModule returns the module for the class. */ HRESULT GetModule([out] ICorDebugModule **pModule); /* * GetTypeDefToken returns the metadata typedef token for the class. */ HRESULT GetToken([out] mdTypeDef *pTypeDef); /* * GetStaticFieldValue returns a value object (ICorDebugValue) for the given static field * variable. If the static field could possibly be relative to either * a thread, context, or appdomain, then pFrame will help the debugger * determine the proper value. * * Note that if the class accepts type parameters, then you should * use GetStaticField on an appropriate ICorDebugType rather than on the * ICorDebugClass. * * Returns: * S_OK on success. * CORDBG_E_FIELD_NOT_STATIC if the field is not static. * CORDBG_E_STATIC_VAR_NOT_AVAILABLE if field is not yet available (storage for statics * may be lazily allocated). * CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL if the field is actually a metadata literal. In this * case, the debugger should get the value from the metadata. * error on other errors. */ HRESULT GetStaticFieldValue([in] mdFieldDef fieldDef, [in] ICorDebugFrame *pFrame, [out] ICorDebugValue **ppValue); }; [ object, local, uuid(B008EA8D-7AB1-43f7-BB20-FBB5A04038AE), pointer_default(unique) ] interface ICorDebugClass2 : IUnknown { /* * GetParameterizedType returns a type that corresponds to this class. * * If the class is non-generic, i.e. has no type parameters, then * this simply gets the type object corresponding to the class. * elementType should be set to the correct element type for the * class, i.e. ELEMENT_TYPE_VALUETYPE if the class is a value type * otherwise ELEMENT_TYPE_CLASS. * * If the class accepts type parameters, e.g. ArrayList, then * this function can be used to construct a type object for an * instantiated type such as ArrayList. */ HRESULT GetParameterizedType([in] CorElementType elementType, [in] ULONG32 nTypeArgs, [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], [out] ICorDebugType **ppType); /* * Sets the User-code status (for JMC stepping) for all methods * in this class. This is functionally equivalent to setting the * JMCStatus onall methods in this class. * A JMC stepper will skip non-user code. * User code must be a subset of debuggable code. * * Returns S_OK if all methods are set successfully. * Return failure if any are not set. * On failure, some may still be set. */ HRESULT SetJMCStatus([in] BOOL bIsJustMyCode); }; /* ------------------------------------------------------------------------- * * Function call interfaces * ------------------------------------------------------------------------- */ /* * ICorDebugEval collects functionality which requires running code * inside the debuggee. Note that the operations do not complete until * ICorDebugProcess::Continue is called, and the EvalComplete callback * is called. * * An ICorDebugEval object is created in the context of a specific * thread, which will be used to perform the evaluations. * * If you need to use this functionality without allowing other threads * to run, set the DebugState of the program's threads to STOP * before calling Continue. * * Note that since user code is running when the evaluation is in * progress, any debug events can occur, including class loads, * breakpoints, etc. Callbacks will be called normally in such a * case. The state of the Eval will be seen as part of the normal * program state inspection, the stack chain will be a CHAIN_FUNC_EVAL chain; * the full debugger API continues to operate as normal. Evals can even be nested. * * Also, the user code may never complete due to deadlock or infinite * looping. In this case you will need to Abort the Eval before * resuming the program. * * All objects and types used in a given func-eval must all reside within the * same app domain. That app-domain need not be the same as the current * app domain of the thread. * */ [ object, local, uuid(CC7BCAF6-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugEval : IUnknown { /* * CallFunction sets up a function call. Note that if the function * is virtual, this will perform virtual dispatch. If the function is * not static, then the first argument must be the "this" object. * If the function is in an a different AppDomain, a transition will * occur (but all arguments must also be in the target AppDomain) */ HRESULT CallFunction([in] ICorDebugFunction *pFunction, [in] ULONG32 nArgs, [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); /* * NewObject allocates and calls the constructor for an object. */ HRESULT NewObject([in] ICorDebugFunction *pConstructor, [in] ULONG32 nArgs, [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); /* * NewObjectNoConstructor allocates a new object without * attempting to call any constructor on the object. */ HRESULT NewObjectNoConstructor([in] ICorDebugClass *pClass); /* * NewString allocates a string object with the given contents. * The string is always created in the AppDomain the thread is currently in. */ HRESULT NewString([in] LPCWSTR string); /* * NewArray allocates a new array with the given element type and * dimensions. If the elementType is a primitive, pElementClass * may be NULL. Otherwise, pElementClass should be the class of * the elements of the array. Note: lowBounds is optional. If * omitted, a zero lower bound for each dimension is assumed. * The array is always created in the AppDomain the thread is currently in. * * NOTE: In the current release, rank must be 1. */ HRESULT NewArray([in] CorElementType elementType, [in] ICorDebugClass *pElementClass, [in] ULONG32 rank, [in, size_is(rank)] ULONG32 dims[], [in, size_is(rank)] ULONG32 lowBounds[]); /* * IsActive returns whether the func-eval is currently executing. */ HRESULT IsActive([out] BOOL *pbActive); /* * Abort aborts the current computation. Note that in the case of nested * Evals, this may fail unless it is the most recent Eval. */ HRESULT Abort(); /* * GetResult returns the result of the evaluation. This is only * valid after the evaluation is completed. * * If the evaluation completes normally, the result will be the * return value. If it terminates with an exception, the result * is the exception thrown. If the evaluation was for a new object, * the return value is the reference to the object. */ HRESULT GetResult([out] ICorDebugValue **ppResult); /* * GetThread returns the thread on which this eval will run or is running. */ HRESULT GetThread([out] ICorDebugThread **ppThread); /* * CreateValue creates an ICorDebugValue of the given type for the * sole purpose of using it in a function evaluation. These can be * used to pass user constants as parameters. The value has a zero * or NULL initial value. Use ICorDebugValue::SetValue to * set the value. * * pElementClass is only required for value classes. Pass NULL * otherwise. * * If elementType == ELEMENT_TYPE_CLASS, then you get an * ICorDebugReferenceValue representing the NULL object reference. * You can use this to pass NULL to evals that have object reference * parameters. You cannot set the ICorDebugReferenceValue to * anything... it always remains NULL. */ HRESULT CreateValue([in] CorElementType elementType, [in] ICorDebugClass *pElementClass, [out] ICorDebugValue **ppValue); }; [ object, local, uuid(FB0D9CE7-BE66-4683-9D32-A42A04E2FD91), pointer_default(unique) ] interface ICorDebugEval2 : IUnknown { /* * CallParameterizedFunction is like CallFunction except the function * may be inside a class with type parameters, or may itself take type * parameters, or both. The type arguments should be given for the * class first, then the function. * * If the function is in an a different AppDomain, a transition will occur. * However, all type and value arguments must be in the target AppDomain. * * Func-eval can only be performed in limited scenarios. If Call*Function * fails, then the HR makes a best effort at describing the most general * possible reason for failure. */ HRESULT CallParameterizedFunction([in] ICorDebugFunction *pFunction, [in] ULONG32 nTypeArgs, [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], [in] ULONG32 nArgs, [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); /* * CreateValueForType generalizes CreateValue by allowing you to specify an * arbitrary object type including constructed types such as List. * Once again the sole purpose is to generate a value to pass for a function evaluation. * * The element type of the type must be ELEMENT_TYPE_CLASS or * ELEMENT_TYPE_VALUE, or one of the simple types. You cannot use this * to create array values or string values. */ HRESULT CreateValueForType([in] ICorDebugType *pType, [out] ICorDebugValue **ppValue); /* * NewParameterizedObject allocates and calls the constructor for an object. * The object may be in a class that includes type parameters. */ HRESULT NewParameterizedObject([in] ICorDebugFunction *pConstructor, [in] ULONG32 nTypeArgs, [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[], [in] ULONG32 nArgs, [in, size_is(nArgs)] ICorDebugValue *ppArgs[]); /* * NewParameterizedObjectNoConstructor allocates a new object without * attempting to call any constructor on the object. * The object may be in a class that includes type parameters. */ HRESULT NewParameterizedObjectNoConstructor([in] ICorDebugClass *pClass, [in] ULONG32 nTypeArgs, [in, size_is(nTypeArgs)] ICorDebugType *ppTypeArgs[]); /* * NewParameterizedArray allocates a new array whose elements may be instances * of a generic type. The array is always created in the AppDomain the thread is * currently in. */ HRESULT NewParameterizedArray([in] ICorDebugType *pElementType, [in] ULONG32 rank, [in, size_is(rank)] ULONG32 dims[], [in, size_is(rank)] ULONG32 lowBounds[]); /* * NewStringWithLength allocates a string object with the given contents. * The length is specified in uiLength. This is used for user to pass in null * embedded string. If the string's tailing null is expected to be in * the managed string, client has to ensure the length including the tailing null. * * The string is always created in the AppDomain the thread is currently in. */ HRESULT NewStringWithLength([in] LPCWSTR string, [in] UINT uiLength); /* * RudeAbort aborts the current computation. Any locks the aborted * eval was holding are not released, and thus the debugging session * is in an unsafe state. */ HRESULT RudeAbort(void); }; /* ------------------------------------------------------------------------- * * Runtime value interfaces * ------------------------------------------------------------------------- */ /* * ICorDebugValue represents a value in the remote process. Note that * the values can be both Get and Set; they are "lvalues". * * In general, ownership of a value object is passed when it is returned. The * recipient is responsible for removing a reference from the object when * finished with it. * * Depending on where the value was retrieved from, the value may not remain * valid after the process is resumed, * so in general they shouldn't be held across continues. */ [ object, local, uuid(CC7BCAF7-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugValue : IUnknown { /* * GetType returns the simple type of the value. If the object * has a more complex runtime type, that type may be examined through the * appropriate subclasses (e.g. ICorDebugObjectValue can get the class of * an object.) */ HRESULT GetType([out] CorElementType *pType); /* * GetSize returns the size of the value in bytes. Note that for reference * types this will be the size of the pointer rather than the size of * the object. */ HRESULT GetSize([out] ULONG32 *pSize); /* * GetAddress returns the address of the value in the debugee * process. This might be useful information for the debugger to * show. * * If the value is unavailable, 0 is returned. This could happen if * it is at least partly in registers or stored in a GC Handle. */ HRESULT GetAddress([out] CORDB_ADDRESS *pAddress); /* * NOT YET IMPLEMENTED */ HRESULT CreateBreakpoint([out] ICorDebugValueBreakpoint **ppBreakpoint); }; [ object, local, uuid(5E0B54E7-D88A-4626-9420-A691E0A78B49), pointer_default(unique) ] interface ICorDebugValue2 : IUnknown { /* * GetExactType returns the runtime type of the object in the value. */ HRESULT GetExactType([out] ICorDebugType **ppType); }; [ object, local, uuid(565005FC-0F8A-4F3E-9EDB-83102B156595), pointer_default(unique) ] interface ICorDebugValue3 : IUnknown { /* * GetSize returns the size of the value in bytes. It has the same * semantics as ICorDebugValue::GetSize except that it works * for arrays >4GB. */ HRESULT GetSize64([out] ULONG64 *pSize); }; /* * ICorDebugGenericValue is a subclass of ICorDebugValue which applies to * all values, and can be used to get & set the value. It is a * separate subinterface because it is non-remotable. * * Note that for reference types, the value is the reference rather than * the contents. */ [ object, local, uuid(CC7BCAF8-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugGenericValue : ICorDebugValue { /* * GetValue copies the value into the specified buffer. The buffer should * be the appropriate size for the simple type. */ HRESULT GetValue([out] void *pTo); /* * SetValue copies a new value from the specified buffer. The buffer should * be the approprirate size for the simple type. * */ HRESULT SetValue([in] void *pFrom); }; /* ISSUE: an remotable interface for each simple type * * It might be nice to have a subclass with a typesafe Get/Set for each simple * type. */ /* * ICorDebugReferenceValue is a subclass of ICorDebugValue which applies to * a reference type. * The runtime may Garbage Collect objects once the debuggee is continued. The GC may * move objects around in memory. * * An ICorDebugReference will either cooperate with GCs such that its information is updated * after the GC, or it will be implicitly neutered before the GC. * * The ICorDebugReferenceValue interface may be implicitly neutered after the debuggee * has been continued. The derived ICorDebugHandleValue is not neutered until explicitly * released or exposed. * */ [ object, local, uuid(CC7BCAF9-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugReferenceValue : ICorDebugValue { /* * IsNull tests whether the reference is null. */ HRESULT IsNull([out] BOOL *pbNull); /* * GetValue returns the current address of the object referred to by this * reference. */ HRESULT GetValue([out] CORDB_ADDRESS *pValue); /* * SetValue sets this reference to refer to a different address. */ HRESULT SetValue([in] CORDB_ADDRESS value); /* * Dereference returns a ICorDebugValue representing the value * referenced. This is only valid while the interface has not yet been neutered. */ HRESULT Dereference([out] ICorDebugValue **ppValue); /* * DEPRECATED */ HRESULT DereferenceStrong([out] ICorDebugValue **ppValue); }; /* * ICorDebugHeapValue is a subclass of ICorDebugValue which represents * a garbage collected object */ [ object, local, uuid(CC7BCAFA-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugHeapValue : ICorDebugValue { /* * DEPRECATED. * All objects are only valid until Continue is called, at which time they are neutered. */ HRESULT IsValid([out] BOOL *pbValid); /* * NOT YET IMPLEMENTED */ HRESULT CreateRelocBreakpoint([out] ICorDebugValueBreakpoint **ppBreakpoint); }; /* * ICorDebugHeapValue2 */ [ object, local, uuid(E3AC4D6C-9CB7-43e6-96CC-B21540E5083C), pointer_default(unique) ] interface ICorDebugHeapValue2 : IUnknown { /* * Creates a handle of the given type for this heap value. * */ HRESULT CreateHandle([in] CorDebugHandleType type, [out] ICorDebugHandleValue ** ppHandle); }; /* * ICorDebugHeapValue3 - exposes the monitor lock properties of objects */ [ object, local, uuid(A69ACAD8-2374-46e9-9FF8-B1F14120D296), pointer_default(unique) ] interface ICorDebugHeapValue3 : IUnknown { /* * Gets the owning thread for a monitor lock */ HRESULT GetThreadOwningMonitorLock([out] ICorDebugThread **ppThread, [out] DWORD *pAcquisitionCount); /* * Gets the list of threads waiting on a monitor event */ HRESULT GetMonitorEventWaitList([out] ICorDebugThreadEnum **ppThreadEnum); }; /* * ICorDebugHeapValue4 */ [ object, local, uuid(B35DD495-A555-463B-9BE9-C55338486BB8), pointer_default(unique) ] interface ICorDebugHeapValue4 : IUnknown { /* * Creates a handle of the given type for this heap value. * */ HRESULT CreatePinnedHandle([out] ICorDebugHandleValue ** ppHandle); }; /* * ICorDebugObjectValue is a subclass of ICorDebugValue which applies to * values which contain an object. * An ICorDebugObjectValue becomes invalid after the debuggee is continued. */ [ object, local, uuid(18AD3D6E-B7D2-11d2-BD04-0000F80849BD), pointer_default(unique) ] interface ICorDebugObjectValue : ICorDebugValue { /* * GetClass returns the runtime class of the object in the value. */ HRESULT GetClass([out] ICorDebugClass **ppClass); /* * GetFieldValue returns a value for the given field in the given * class. The class must be on the class hierarchy of the object's * class, and the field must be a field of that class. */ HRESULT GetFieldValue([in] ICorDebugClass *pClass, [in] mdFieldDef fieldDef, [out] ICorDebugValue **ppValue); /* * NOT YET IMPLEMENTED */ HRESULT GetVirtualMethod([in] mdMemberRef memberRef, [out] ICorDebugFunction **ppFunction); /* * NOT YET IMPLEMENTED */ HRESULT GetContext([out] ICorDebugContext **ppContext); /* * IsValueClass returns true if the class of this object is * a value class. */ HRESULT IsValueClass([out] BOOL *pbIsValueClass); /* * DEPRECATED */ HRESULT GetManagedCopy([out] IUnknown **ppObject); /* * DEPRECATED */ HRESULT SetFromManagedCopy([in] IUnknown *pObject); }; [ object, local, uuid(49E4A320-4A9B-4eca-B105-229FB7D5009F), pointer_default(unique) ] interface ICorDebugObjectValue2 : IUnknown { /* * GetVirtualMethodForType returns the most derived function * for the given ref on this object. * * Note: not yet implemented. */ HRESULT GetVirtualMethodAndType([in] mdMemberRef memberRef, [out] ICorDebugFunction **ppFunction, [out] ICorDebugType **ppType); }; [ object, local, uuid(3AF70CC7-6047-47F6-A5C5-090A1A622638), pointer_default(unique) ] interface ICorDebugDelegateObjectValue : IUnknown { /* * GetTarget retrieves the object on which the delegate calls the function. * Returns: * - S_OK: * - The ICorDebugReferenceValue object targeted by the function. * - NULL if the delegate function is a static function or an open delegate * - HRESULT CORDBG_E_UNSUPPORTED_DELEGATE for curently unsupported delegates. * In this case, the value of ppObject should not be used. Some of these * include: Wrapper delegates, Open Virual delegates. */ HRESULT GetTarget([out] ICorDebugReferenceValue **ppObject); /* * GetFunction returns the function that gets run by the delegate. * - S_OK: * - The ICorDebugFunction function for the function the delegate would invoke. * - There are a few cases where the ICorDebugFunction can be different from what's expected, * such as generic methods, which won't contain the instantiation. * - HRESULT CORDBG_E_UNSUPPORTED_DELEGATE for curently unsupported delegates. * In this case, the value of ppObject should not be used. Some of these * include: Wrapper delegates, Open Virual delegates. */ HRESULT GetFunction([out] ICorDebugFunction **ppFunction); } /* * ICorDebugBoxValue is a subclass of ICorDebugValue which * represents a boxed value class object. */ [ object, local, uuid(CC7BCAFC-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugBoxValue : ICorDebugHeapValue { /* * GetObject returns the value object which is in the box. */ HRESULT GetObject([out] ICorDebugObjectValue **ppObject); }; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugStringValue */ /* * ICorDebugStringValue is a subclass of ICorDebugValue which * applies to values which contain a string. This interface * provides an easy way to get the string contents. */ [ object, local, uuid(CC7BCAFD-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugStringValue : ICorDebugHeapValue { /* * GetLength returns the number of characters in the string. */ HRESULT GetLength([out] ULONG32 *pcchString); /* * GetString returns the contents of the string. */ HRESULT GetString([in] ULONG32 cchString, [out] ULONG32 *pcchString, [out, size_is(cchString), length_is(*pcchString)] WCHAR szString[]); }; #pragma warning(pop) /* * ICorDebugArrayValue is a subclass of ICorDebugValue which applies * to values which contain an array. This interface supports both * single and multidimension arrays. */ [ object, local, uuid(0405B0DF-A660-11d2-BD02-0000F80849BD), pointer_default(unique) ] interface ICorDebugArrayValue : ICorDebugHeapValue { /* * GetElementType returns the simple type of the elements in the * array. */ HRESULT GetElementType([out] CorElementType *pType); /* * GetRank returns the number of dimensions in the array. */ HRESULT GetRank([out] ULONG32 *pnRank); /* * GetCount returns the total number of elements in the array. */ HRESULT GetCount([out] ULONG32 *pnCount); /* * GetDimensions returns the dimensions of the array. */ HRESULT GetDimensions([in] ULONG32 cdim, [out, size_is(cdim), length_is(cdim)] ULONG32 dims[]); /* * HasBaseIndicies returns whether or not the array has base indices. * If the answer is no, then all dimensions have a base index of 0. */ HRESULT HasBaseIndicies([out] BOOL *pbHasBaseIndicies); /* * GetBaseIndicies returns the base index of each dimension in * the array */ HRESULT GetBaseIndicies([in] ULONG32 cdim, [out, size_is(cdim), length_is(cdim)] ULONG32 indices[]); /* * GetElement returns a value representing the given element in the array. * The indices array must not be null. */ HRESULT GetElement([in] ULONG32 cdim, [in, size_is(cdim), length_is(cdim)] ULONG32 indices[], [out] ICorDebugValue **ppValue); /* * GetElementAtPosition returns the element at the given position, * treating the array as a zero-based, single-dimensional array. * * Multidimensional array layout follows the C++ style of array layout. */ HRESULT GetElementAtPosition([in] ULONG32 nPosition, [out] ICorDebugValue **ppValue); }; [ object, local, uuid(50847b8d-f43f-41b0-924c-6383a5f2278b), pointer_default(unique) ] interface ICorDebugVariableHome : IUnknown { /* * GetCode - gives the ICorDebugCode instance containing this * ICorDebugVariableHome. */ HRESULT GetCode([out] ICorDebugCode **ppCode); /* * GetSlotIndex - gives the managed slot-index of a local variable. * The slot-index can be used to retrieve the metadata for this local. * Returns E_FAIL if the variable is a function argument. */ HRESULT GetSlotIndex([out] ULONG32 *pSlotIndex); /* * GetArgumentIndex - gives the argument index of a function argument. * The argument index can be used to retrieve the metadata for this * argument. * Returns E_FAIL if the variable is a local variable. */ HRESULT GetArgumentIndex([out] ULONG32* pArgumentIndex); /* * GetLiveRange - gives the native range over which this variable is live. * pStartOffset is the logical offset at which the variable is first live. * pEndOffset is the logical offset immediately after that at which the * variable is last live. */ HRESULT GetLiveRange([out] ULONG32* pStartOffset, [out] ULONG32 *pEndOffset); typedef enum VariableLocationType { VLT_REGISTER, // variable is in a register VLT_REGISTER_RELATIVE, // variable is in a register-relative memory // location VLT_INVALID } VariableLocationType; /* * GetLocationType - gives the type of native location. See * VariableLocationType. * Returns VLT_INVALID if the variable is not stored in a register or in a * register-relative memory location. */ HRESULT GetLocationType([out] VariableLocationType *pLocationType); /* * GetRegister - gives the register containing the variables with location * type VLT_REGISTER, and the base register for variables with location * type VLT_REGISTER_RELATIVE. * Returns E_FAIL if the variable is not in a register or in a * register-relative location. */ HRESULT GetRegister([out] CorDebugRegister *pRegister); /* * GetOffset - gives the offset from the base register for a variable. * Returns E_FAIL if the variable is not in a register-relative memory * location. */ HRESULT GetOffset([out] LONG *pOffset); } /* * ICorDebugHandleValue represents a reference value that the debugger has * explicitly created a GC handle to. It does not represent GC Handles in the debuggee process, * A normal ICorDebugReference becomes neutered after the debuggee has been * continued. A ICorDebugHandleValue will survive across continues and can be * dereferenced until the client explicitly disposes the handle. * * * ICorDebugHeapValu2::CreateHandle will create ICorDebugHandleValue */ [ object, local, uuid(029596E8-276B-46a1-9821-732E96BBB00B), pointer_default(unique) ] interface ICorDebugHandleValue : ICorDebugReferenceValue { /* * returns the type of this handle. * */ HRESULT GetHandleType([out] CorDebugHandleType *pType); /* * The final release of the interface will also dispose of the handle. This * API provides the ability for client to early dispose the handle. * */ HRESULT Dispose(); }; /* * ICorDebugContext represents a context object. * * Interface TBD. */ [ object, local, uuid(CC7BCB00-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugContext : ICorDebugObjectValue { }; /* * ICorDebugComObjectValue applies to values which contain a COM object. * An ICorDebugComObjectValue becomes invalid after the debuggee is continued. */ [ object, local, uuid(5F69C5E5-3E12-42DF-B371-F9D761D6EE24), pointer_default(unique) ] interface ICorDebugComObjectValue : IUnknown { /* * GetCachedInterfaceTypes returns an enum of the types of all interfaces * that are cached by the COM object. */ HRESULT GetCachedInterfaceTypes( [in] BOOL bIInspectableOnly, [out] ICorDebugTypeEnum **ppInterfacesEnum); /* * GetCachedInterfacePointers returns at most celt values of the * interface pointer values cached by the COM object. It fills * pcEltFetched with the actual number of fetched elements. * When called with NULL for ptrs, and 0 for celt, it simply returns * the number of elements it needs. */ HRESULT GetCachedInterfacePointers( [in] BOOL bIInspectableOnly, [in] ULONG32 celt, [out] ULONG32 *pcEltFetched, [out, size_is(celt), length_is(*pcEltFetched)] CORDB_ADDRESS * ptrs); }; /* ------------------------------------------------------------------------- * * Enum interfaces * ------------------------------------------------------------------------- */ /* * ICorDebugEnum is an abstract enumerator. */ [ object, local, uuid(CC7BCB01-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugEnum : IUnknown { /* * Moves the current position forward the given number of * elements. */ HRESULT Skip([in] ULONG celt); /* * Sets the position of the enumerator to the beginning of the * enumeration. */ HRESULT Reset(); /* * Creates another enumerator with the same current position * as this one. */ HRESULT Clone([out] ICorDebugEnum **ppEnum); /* * Gets the number of elements in the enumeration */ HRESULT GetCount([out] ULONG *pcelt); }; [ object, local, uuid(CC7BCB02-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugObjectEnum : ICorDebugEnum { /* * Gets the next "celt" number of objects in the enumeration. * The actual number of objects retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of objects retrieved is smaller * than the number of objects requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] CORDB_ADDRESS objects[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB03-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugBreakpointEnum : ICorDebugEnum { /* * Gets the next "celt" number of breakpoints in the enumeration. * The actual number of breakpoints retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of breakpoints retrieved is smaller * than the number of breakpoints requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugBreakpoint *breakpoints[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB04-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugStepperEnum : ICorDebugEnum { /* * Gets the next "celt" number of steppers in the enumeration. * The actual number of steppers retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of steppers retrieved is smaller * than the number of steppers requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugStepper *steppers[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB05-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugProcessEnum : ICorDebugEnum { /* * Gets the next "celt" number of processes in the enumeration. * The actual number of processes retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of processes retrieved is smaller * than the number of processes requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugProcess *processes[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB06-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugThreadEnum : ICorDebugEnum { /* * Gets the next "celt" number of threads in the enumeration. * The actual number of threads retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of threads retrieved is smaller * than the number of threads requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugThread *threads[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB07-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugFrameEnum : ICorDebugEnum { /* * Gets the next "celt" number of frames in the enumeration. * The actual number of frames retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of frames retrieved is smaller * than the number of frames requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugFrame *frames[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB08-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugChainEnum : ICorDebugEnum { /* * Gets the next "celt" number of chains in the enumeration. * The actual number of chains retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of chains retrieved is smaller * than the number of chains requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugChain *chains[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB09-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugModuleEnum : ICorDebugEnum { /* * Gets the next "celt" number of modules in the enumeration. * The actual number of modules retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of modules retrieved is smaller * than the number of modules requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugModule *modules[], [out] ULONG *pceltFetched); }; [ object, local, uuid(CC7BCB0A-8A68-11d2-983C-0000F808342D), pointer_default(unique) ] interface ICorDebugValueEnum : ICorDebugEnum { /* * Gets the next "celt" number of values in the enumeration. * The actual number of values retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of values retrieved is smaller * than the number of values requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugValue *values[], [out] ULONG *pceltFetched); }; [ object, local, uuid(e76b7a57-4f7a-4309-85a7-5d918c3deaf7), pointer_default(unique) ] interface ICorDebugVariableHomeEnum : ICorDebugEnum { /* * Next - gives the specified number of ICorDebugVariableHome instances from * the enumeration, starting at the current position. * celt is the number of requested instances. * pceltFetched is the number of instances retrieved. * returns S_FALSE if the actual number of instances retrieved is smaller * than the number of instances requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugVariableHome *homes[], [out] ULONG *pceltFetched); }; [ object, local, uuid(55E96461-9645-45e4-A2FF-0367877ABCDE), pointer_default(unique) ] interface ICorDebugCodeEnum : ICorDebugEnum { /* * Gets the next "celt" number of code objects in the enumeration. * The actual number of code objects retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of code objects retrieved is smaller * than the number of code objects requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugCode *values[], [out] ULONG *pceltFetched); }; [ object, local, uuid(10F27499-9DF2-43ce-8333-A321D7C99CB4), pointer_default(unique) ] interface ICorDebugTypeEnum : ICorDebugEnum { /* * Gets the next "celt" number of types in the enumeration. * The actual number of types retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of types retrieved is smaller * than the number of types requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugType *values[], [out] ULONG *pceltFetched); }; /* * ICorDebugType represents an instantiated type in the debugggee. * Unlike ICorDebugClass, it can store type-parameter information and thus can * represent instantiated generic types (Eg, List) * Use the metadata interfaces to get static (Compile-time) information about the type. * * A type (and all of its type parameters) lives in an single AppDomain and becomes * invalid once the containing ICorDebugAppDomain is unloaded. * * Types may be lazily loaded, so if the debugger queries for a type that hasn't been * loaded yet, it may be unavailable. */ [ object, local, uuid(D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5), pointer_default(unique) ] interface ICorDebugType : IUnknown { /* * GetType gets the basic type of the generic parameter. This can be used to * determine if it is necessary to call GetClass to find the full information for the * generic type parameter. */ HRESULT GetType([out] CorElementType *ty); /* * GetClass is used if the CorElementType returned by GetType is ELEMENT_TYPE_CLASS, * ELEMENT_TYPE_VALUETYPE. If the type is a constructed type, e.g. List, * then this will return the ICorDebugClass for the type constructor, i.e. "List". * * GetClass should not be used if the element type is anything other than these two element * types. In particular, it may not be used if the element type is ELEMENT_TYPE_STRING. */ HRESULT GetClass([out] ICorDebugClass **ppClass); /* * EnumerateTypeParameters may be used if the CorElementType * returned by GetType is one of ELEMENT_TYPE_CLASS, * ELEMENT_TYPE_VALUETYPE, ELEMENT_TYPE_ARRAY, ELEMENT_TYPE_SZARRAY, * ELEMENT_TYPE_BYREF, ELEMENT_TYPE_PTR or ELEMENT_TYPE_FNPTR. * It returns the parameters specifying further information about * the type. For example, if the type is "class Dict" * then EnumerateTypeParameters will return "String" and "int32" * in sequence. * */ HRESULT EnumerateTypeParameters([out] ICorDebugTypeEnum **ppTyParEnum); /* * GetFirstTypeParameter can be used in those cases where the further * information about the type involves at most one type * parameter. You can determine this from the element type returned by * GetType. In particular it may be used with * ELEMENT_TYPE_ARRAY, ELEMENT_TYPE_SZARRAY, ELEMENT_TYPE_BYREF * or ELEMENT_TYPE_PTR. * This can only be called if the type does indeed have a type-parameter. */ HRESULT GetFirstTypeParameter([out] ICorDebugType **value); /* * GetBase returns the ICorDebugType object for the base type of this type, if it * has one, i.e. if the type is a class type. * For example, if * class MyStringDict : Dict * then the base type of "MyStringDict" will be "Dict". * * This is a helper function - you could compute this from EnumerateTypeParameters, * GetClass and the relevant metadata, but it is relatively painful: you would * have to lookup the class, then the metadata of that class * to find the "generic" base type, then instantiate this generic base type by * looking up the type parameters to the initial type, * and then perform the appropriate instantiation in the case where the class * happens to be either a generic class or a normal class with a constructed type * as its parent. Looking up the base types is useful to implement common * debugger functionality, e.g. printing out all the fields of an object, including its * superclasses. * */ HRESULT GetBase([out] ICorDebugType **pBase); /* * GetStaticFieldValue returns a value object (ICorDebugValue) * for the given static field variable. For non-parameterized * types, this is identical to calling GetStaticFieldValue on the * ICorDebugClass object returned by ICorDebugType::GetClass. * For parameterized types a static field value will be relative to a * particular instantiation. If in addition the static field could * possibly be relative to either a thread, context, or appdomain, then pFrame * will help the debugger determine the proper value. * * This may only be used when ICorDebugType::GetType returns * ELEMENT_TYPE_CLASS or ELEMENT_TYPE_VALUETYPE. */ HRESULT GetStaticFieldValue([in] mdFieldDef fieldDef, [in] ICorDebugFrame *pFrame, [out] ICorDebugValue **ppValue); /* * GetRank returns the number of dimensions in an array type */ HRESULT GetRank([out] ULONG32 *pnRank); }; [ object, local, uuid(e6e91d79-693d-48bc-b417-8284b4f10fb5), pointer_default(unique) ] interface ICorDebugType2 : IUnknown { /* * GetTypeID - gives a COR_TYPEID for the ICorDebugType. This * provides a mapping from the ICorDebugType, which represents a * type that may or may not have been loaded into the runtime, to * a COR_TYPEID, which serves as an opaque handle identifying a * type loaded into the runtime. When the type that the * ICorDebugType represents has not yet been loaded, this returns * CORDBG_E_CLASS_NOT_LOADED. Returns CORDBG_E_UNSUPPORTED for * unsupported types. */ HRESULT GetTypeID([out] COR_TYPEID *id); }; /* ------------------------------------------------------------------------- * * DEPRECATED * * ICorDebugErrorInfoEnum interface * * ------------------------------------------------------------------------- */ [ object, local, uuid(F0E18809-72B5-11d2-976F-00A0C9B4D50C), pointer_default(unique) ] interface ICorDebugErrorInfoEnum : ICorDebugEnum { /* * DEPRECATED */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugEditAndContinueErrorInfo *errors[], [out] ULONG *pceltFetched); }; /* ------------------------------------------------------------------------- * * AppDomainEnum interface * ------------------------------------------------------------------------- */ [ object, local, uuid(63ca1b24-4359-4883-bd57-13f815f58744), pointer_default(unique) ] interface ICorDebugAppDomainEnum : ICorDebugEnum { /* * Gets the next "celt" app domains in the enumeration */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugAppDomain *values[], [out] ULONG *pceltFetched); }; /* ------------------------------------------------------------------------- * * AssemblyEnum interface * ------------------------------------------------------------------------- */ [ object, local, uuid(4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83), pointer_default(unique) ] interface ICorDebugAssemblyEnum : ICorDebugEnum { /* * Gets the next "celt" assemblies in the enumeration */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorDebugAssembly *values[], [out] ULONG *pceltFetched); }; /* ------------------------------------------------------------------------- * * BlockingObjectEnum interface * ------------------------------------------------------------------------- */ [ object, local, uuid(976A6278-134A-4a81-81A3-8F277943F4C3), pointer_default(unique) ] interface ICorDebugBlockingObjectEnum : ICorDebugEnum { /* * Gets the next "celt" blocking objects in the enumeration */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] CorDebugBlockingObject values[], [out] ULONG *pceltFetched); }; #pragma warning(push) #pragma warning(disable:28718) // Represent data for an Managed Debugging Assistant (MDA) notification. See the MDA documentation for MDA-specific information like: // - enabling / disabling MDAs // - MDA naming conventions // - What the contents of an MDA look like, schemas, etc. [ object, local, uuid(CC726F2F-1DB7-459b-B0EC-05F01D841B42), pointer_default(unique) ] interface ICorDebugMDA : IUnknown { // Get the string for the type of the MDA. Never empty. // This is a convenient performant alternative to getting the XML stream and extracting // the type from that based off the schema. HRESULT GetName( [in] ULONG32 cchName, [out] ULONG32 * pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); // Get a string description of the MDA. This may be empty (0-length). HRESULT GetDescription( [in] ULONG32 cchName, [out] ULONG32 * pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); // Get the full associated XML for the MDA. This may be empty. // This could be a potentially expensive operation if the xml stream is large. // See the MDA documentation for the schema for this XML stream. HRESULT GetXML( [in] ULONG32 cchName, [out] ULONG32 * pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); // Get the flags associated w/ the MDA. New flags may be added in future versions. typedef enum CorDebugMDAFlags { // If this flag is high, then the thread may have slipped since the MDA was fired. MDA_FLAG_SLIP = 0x2 } CorDebugMDAFlags; HRESULT GetFlags([in] CorDebugMDAFlags * pFlags); // Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a // native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread // object for it yet) HRESULT GetOSThreadId([out] DWORD * pOsTid); }; #pragma warning(pop) /* ------------------------------------------------------------------------- * * Edit and Continue interfaces * DEPRECATED * ------------------------------------------------------------------------- */ #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface ICorDebugEditAndContinueErrorInfo */ /* * DEPRECATED * * ICorDebugEditAndContinueErrorInfo * */ [ object, local, uuid(8D600D41-F4F6-4cb3-B7EC-7BD164944036), pointer_default(unique) ] interface ICorDebugEditAndContinueErrorInfo : IUnknown { /* * DEPRECATED */ HRESULT GetModule([out] ICorDebugModule **ppModule); /* * DEPRECATED */ HRESULT GetToken([out]mdToken *pToken); /* * DEPRECATED */ HRESULT GetErrorCode([out]HRESULT *pHr); /* * DEPRECATED */ HRESULT GetString([in] ULONG32 cchString, [out] ULONG32 *pcchString, [out, size_is(cchString), length_is(*pcchString)] WCHAR szString[]); } #pragma warning(pop) /* * DEPRECATED * * ICorDebugEditAndContinueSnapshot */ [ object, local, uuid(6DC3FA01-D7CB-11d2-8A95-0080C792E5D8), pointer_default(unique) ] interface ICorDebugEditAndContinueSnapshot : IUnknown { /* * DEPRECATED */ HRESULT CopyMetaData([in] IStream *pIStream, [out] GUID *pMvid); /* * DEPRECATED */ HRESULT GetMvid([out] GUID *pMvid); /* * DEPRECATED */ HRESULT GetRoDataRVA([out] ULONG32 *pRoDataRVA); /* * DEPRECATED */ HRESULT GetRwDataRVA([out] ULONG32 *pRwDataRVA); /* * DEPRECATED */ HRESULT SetPEBytes([in] IStream *pIStream); /* * DEPRECATED */ HRESULT SetILMap([in] mdToken mdFunction, [in] ULONG cMapSize, [in, size_is(cMapSize)] COR_IL_MAP map[]); /* * DEPRECATED */ HRESULT SetPESymbolBytes([in] IStream *pIStream); }; [ object, local, uuid(ED775530-4DC4-41F7-86D0-9E2DEF7DFC66), pointer_default(unique) ] interface ICorDebugExceptionObjectCallStackEnum : ICorDebugEnum { /* * Gets the next "celt" number of frames in the enumeration. * The actual number of frames retrieved is returned in "pceltFetched". * Returns S_FALSE if the actual number of frames retrieved is smaller * than the number of frames requested. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] CorDebugExceptionObjectStackFrame values[], [out] ULONG* pceltFetched); }; [ object, local, uuid(AE4CA65D-59DD-42A2-83A5-57E8A08D8719), pointer_default(unique) ] interface ICorDebugExceptionObjectValue : IUnknown { HRESULT EnumerateExceptionCallStack([out] ICorDebugExceptionObjectCallStackEnum** ppCallStackEnum); }; /* ------------------------------------------------------------------------- * * Library definition * ------------------------------------------------------------------------- */ [ uuid(53D13620-F417-11d1-9762-A63826A4F255), version(1.0), helpstring("Common Language Runtime Debugging 1.0 Type Library") ] library CORDBLib { importlib("stdole32.tlb"); // There should be no co-class for V2.0 CorDebug at all. // Clients should create the ICorDebug object using the shim API // CreateDebuggerInterfaceFromVersion defined in mscoree.idl. // This guid here is the same as the v1.1 guid for setup / breaking-change purposes. [ uuid(6fef44d0-39e7-4c77-be8e-c9f8cf988630) ] coclass CorDebug { [default] interface ICorDebug; }; [ uuid(211f1254-bc7e-4af5-b9aa-067308d83dd1) ] coclass EmbeddedCLRCorDebug { [default] interface ICorDebug; }; interface ICorDebugReferenceValue; interface ICorDebugStringValue; interface ICorDebugGenericValue; interface ICorDebugBoxValue; interface ICorDebugArrayValue; interface ICorDebugILFrame; interface ICorDebugInternalFrame; interface ICorDebugInternalFrame2; interface ICorDebugNativeFrame; interface ICorDebugNativeFrame2; interface ICorDebugRuntimeUnwindableFrame; interface ICorDebugManagedCallback2; interface ICorDebugAppDomain2; interface ICorDebugAppDomain3; interface ICorDebugAssembly2; interface ICorDebugProcess2 ; interface ICorDebugStepper2 ; interface ICorDebugThread2 ; interface ICorDebugThread3 ; interface ICorDebugILFrame2; interface ICorDebugModule2 ; interface ICorDebugFunction2; interface ICorDebugClass2 ; interface ICorDebugEval2 ; interface ICorDebugValue2; interface ICorDebugObjectValue2; interface ICorDebugHandleValue; interface ICorDebugHeapValue2; interface ICorDebugComObjectValue; interface ICorDebugModule3; }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cordebuginfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Keep in sync with llvm/tools/objwriter/cordebuginfo.h in current objwriter branch in https://github.com/dotnet/llvm-project repo // /**********************************************************************************/ // DebugInfo types shared by JIT-EE interface and EE-Debugger interface class ICorDebugInfo { public: /*----------------------------- Boundary-info ---------------------------*/ enum MappingTypes { NO_MAPPING = -1, PROLOG = -2, EPILOG = -3, MAX_MAPPING_VALUE = -3 // Sentinel value. This should be set to the largest magnitude value in the enum // so that the compression routines know the enum's range. }; enum BoundaryTypes { NO_BOUNDARIES = 0x00, // No implicit boundaries STACK_EMPTY_BOUNDARIES = 0x01, // Boundary whenever the IL evaluation stack is empty NOP_BOUNDARIES = 0x02, // Before every CEE_NOP instruction CALL_SITE_BOUNDARIES = 0x04, // Before every CEE_CALL, CEE_CALLVIRT, etc instruction // Set of boundaries that debugger should always reasonably ask the JIT for. DEFAULT_BOUNDARIES = STACK_EMPTY_BOUNDARIES | NOP_BOUNDARIES | CALL_SITE_BOUNDARIES }; // Note that SourceTypes can be OR'd together - it's possible that // a sequence point will also be a stack_empty point, and/or a call site. // The debugger will check to see if a boundary offset's source field & // SEQUENCE_POINT is true to determine if the boundary is a sequence point. enum SourceTypes { SOURCE_TYPE_INVALID = 0x00, // To indicate that nothing else applies SEQUENCE_POINT = 0x01, // The debugger asked for it. STACK_EMPTY = 0x02, // The stack is empty here CALL_SITE = 0x04, // This is a call site. NATIVE_END_OFFSET_UNKNOWN = 0x08, // Indicates a epilog endpoint CALL_INSTRUCTION = 0x10 // The actual instruction of a call. }; struct OffsetMapping { uint32_t nativeOffset; uint32_t ilOffset; // IL offset or one of the special values in MappingTypes SourceTypes source; // The debugger needs this so that // we don't put Edit and Continue breakpoints where // the stack isn't empty. We can put regular breakpoints // there, though, so we need a way to discriminate // between offsets. }; /*------------------------------ Var-info -------------------------------*/ // Note: The debugger needs to target register numbers on platforms other than which the debugger itself // is running. To this end it maintains its own values for REGNUM_SP and REGNUM_AMBIENT_SP across multiple // platforms. So any change here that may effect these values should be reflected in the definitions // contained in debug/inc/DbgIPCEvents.h. enum RegNum { #ifdef TARGET_X86 REGNUM_EAX, REGNUM_ECX, REGNUM_EDX, REGNUM_EBX, REGNUM_ESP, REGNUM_EBP, REGNUM_ESI, REGNUM_EDI, #elif TARGET_ARM REGNUM_R0, REGNUM_R1, REGNUM_R2, REGNUM_R3, REGNUM_R4, REGNUM_R5, REGNUM_R6, REGNUM_R7, REGNUM_R8, REGNUM_R9, REGNUM_R10, REGNUM_R11, REGNUM_R12, REGNUM_SP, REGNUM_LR, REGNUM_PC, #elif TARGET_ARM64 REGNUM_X0, REGNUM_X1, REGNUM_X2, REGNUM_X3, REGNUM_X4, REGNUM_X5, REGNUM_X6, REGNUM_X7, REGNUM_X8, REGNUM_X9, REGNUM_X10, REGNUM_X11, REGNUM_X12, REGNUM_X13, REGNUM_X14, REGNUM_X15, REGNUM_X16, REGNUM_X17, REGNUM_X18, REGNUM_X19, REGNUM_X20, REGNUM_X21, REGNUM_X22, REGNUM_X23, REGNUM_X24, REGNUM_X25, REGNUM_X26, REGNUM_X27, REGNUM_X28, REGNUM_FP, REGNUM_LR, REGNUM_SP, REGNUM_PC, #elif TARGET_AMD64 REGNUM_RAX, REGNUM_RCX, REGNUM_RDX, REGNUM_RBX, REGNUM_RSP, REGNUM_RBP, REGNUM_RSI, REGNUM_RDI, REGNUM_R8, REGNUM_R9, REGNUM_R10, REGNUM_R11, REGNUM_R12, REGNUM_R13, REGNUM_R14, REGNUM_R15, #elif TARGET_LOONGARCH64 REGNUM_R0, REGNUM_RA, REGNUM_TP, REGNUM_SP, REGNUM_A0, REGNUM_A1, REGNUM_A2, REGNUM_A3, REGNUM_A4, REGNUM_A5, REGNUM_A6, REGNUM_A7, REGNUM_T0, REGNUM_T1, REGNUM_T2, REGNUM_T3, REGNUM_T4, REGNUM_T5, REGNUM_T6, REGNUM_T7, REGNUM_T8, REGNUM_X0, REGNUM_FP, REGNUM_S0, REGNUM_S1, REGNUM_S2, REGNUM_S3, REGNUM_S4, REGNUM_S5, REGNUM_S6, REGNUM_S7, REGNUM_S8, REGNUM_PC, #else PORTABILITY_WARNING("Register numbers not defined on this platform") #endif REGNUM_COUNT, REGNUM_AMBIENT_SP, // ambient SP support. Ambient SP is the original SP in the non-BP based frame. // Ambient SP should not change even if there are push/pop operations in the method. #ifdef TARGET_X86 REGNUM_FP = REGNUM_EBP, REGNUM_SP = REGNUM_ESP, #elif TARGET_AMD64 REGNUM_SP = REGNUM_RSP, #elif TARGET_ARM #ifdef REDHAWK REGNUM_FP = REGNUM_R7, #else REGNUM_FP = REGNUM_R11, #endif //REDHAWK #elif TARGET_ARM64 //Nothing to do here. FP is already alloted. #elif TARGET_LOONGARCH64 //Nothing to do here. FP is already alloted. #else // RegNum values should be properly defined for this platform REGNUM_FP = 0, REGNUM_SP = 1, #endif }; // VarLoc describes the location of a native variable. Note that currently, VLT_REG_BYREF and VLT_STK_BYREF // are only used for value types on X64. enum VarLocType { VLT_REG, // variable is in a register VLT_REG_BYREF, // address of the variable is in a register VLT_REG_FP, // variable is in an fp register VLT_STK, // variable is on the stack (memory addressed relative to the frame-pointer) VLT_STK_BYREF, // address of the variable is on the stack (memory addressed relative to the frame-pointer) VLT_REG_REG, // variable lives in two registers VLT_REG_STK, // variable lives partly in a register and partly on the stack VLT_STK_REG, // reverse of VLT_REG_STK VLT_STK2, // variable lives in two slots on the stack VLT_FPSTK, // variable lives on the floating-point stack VLT_FIXED_VA, // variable is a fixed argument in a varargs function (relative to VARARGS_HANDLE) VLT_COUNT, VLT_INVALID, }; // VLT_REG/VLT_REG_FP -- Any pointer-sized enregistered value (TYP_INT, TYP_REF, etc) // eg. EAX // VLT_REG_BYREF -- the specified register contains the address of the variable // eg. [EAX] struct vlReg { RegNum vlrReg; }; // VLT_STK -- Any 32 bit value which is on the stack // eg. [ESP+0x20], or [EBP-0x28] // VLT_STK_BYREF -- the specified stack location contains the address of the variable // eg. mov EAX, [ESP+0x20]; [EAX] struct vlStk { RegNum vlsBaseReg; signed vlsOffset; }; // VLT_REG_REG -- TYP_LONG with both uint32_ts enregistred // eg. RBM_EAXEDX struct vlRegReg { RegNum vlrrReg1; RegNum vlrrReg2; }; // VLT_REG_STK -- Partly enregistered TYP_LONG // eg { LowerDWord=EAX UpperDWord=[ESP+0x8] } struct vlRegStk { RegNum vlrsReg; struct { RegNum vlrssBaseReg; signed vlrssOffset; } vlrsStk; }; // VLT_STK_REG -- Partly enregistered TYP_LONG // eg { LowerDWord=[ESP+0x8] UpperDWord=EAX } struct vlStkReg { struct { RegNum vlsrsBaseReg; signed vlsrsOffset; } vlsrStk; RegNum vlsrReg; }; // VLT_STK2 -- Any 64 bit value which is on the stack, // in 2 successive DWords. // eg 2 DWords at [ESP+0x10] struct vlStk2 { RegNum vls2BaseReg; signed vls2Offset; }; // VLT_FPSTK -- enregisterd TYP_DOUBLE (on the FP stack) // eg. ST(3). Actually it is ST("FPstkHeight - vpFpStk") struct vlFPstk { unsigned vlfReg; }; // VLT_FIXED_VA -- fixed argument of a varargs function. // The argument location depends on the size of the variable // arguments (...). Inspecting the VARARGS_HANDLE indicates the // location of the first arg. This argument can then be accessed // relative to the position of the first arg struct vlFixedVarArg { unsigned vlfvOffset; }; // VLT_MEMORY struct vlMemory { void *rpValue; // pointer to the in-process // location of the value. }; struct VarLoc { VarLocType vlType; union { ICorDebugInfo::vlReg vlReg; ICorDebugInfo::vlStk vlStk; ICorDebugInfo::vlRegReg vlRegReg; ICorDebugInfo::vlRegStk vlRegStk; ICorDebugInfo::vlStkReg vlStkReg; ICorDebugInfo::vlStk2 vlStk2; ICorDebugInfo::vlFPstk vlFPstk; ICorDebugInfo::vlFixedVarArg vlFixedVarArg; ICorDebugInfo::vlMemory vlMemory; }; }; // This is used to report implicit/hidden arguments enum { VARARGS_HND_ILNUM = -1, // Value for the CORINFO_VARARGS_HANDLE varNumber RETBUF_ILNUM = -2, // Pointer to the return-buffer TYPECTXT_ILNUM = -3, // ParamTypeArg for CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG UNKNOWN_ILNUM = -4, // Unknown variable MAX_ILNUM = -4 // Sentinel value. This should be set to the largest magnitude value in th enum // so that the compression routines know the enum's range. }; struct ILVarInfo { uint32_t startOffset; uint32_t endOffset; uint32_t varNumber; }; struct NativeVarInfo { uint32_t startOffset; uint32_t endOffset; uint32_t varNumber; VarLoc loc; }; // Represents an individual entry in the inline tree. // This is ordinarily stored as a flat array in which [0] is the root, and // the indices below indicate the tree structure. struct InlineTreeNode { // Method handle of inlinee (or root) CORINFO_METHOD_HANDLE Method; // IL offset of IL instruction resulting in the inline uint32_t ILOffset; // Index of child in tree, 0 if no children uint32_t Child; // Index of sibling in tree, 0 if no sibling uint32_t Sibling; }; struct RichOffsetMapping { // Offset in emitted code uint32_t NativeOffset; // Index of inline tree node containing the IL offset (0 for root) uint32_t Inlinee; // IL offset of IL instruction in inlinee that this mapping was created from uint32_t ILOffset; // Source information about the IL instruction in the inlinee SourceTypes Source; }; }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/coredistools.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //===--------- coredistools.h - Dissassembly tools for CoreClr ------------===// // // Core Disassembly Tools API Version 1.0.1-prerelease // Disassembly tools required by CoreCLR for utilities like // GCStress and SuperPMI //===----------------------------------------------------------------------===// #if !defined(_COREDISTOOLS_H_) #define _COREDISTOOLS_H_ #include #if defined(__cplusplus) #define EXTERN_C extern "C" #else #define EXTERN_C #endif // defined(__cplusplus) #if defined(_MSC_VER) #if defined(DllInterfaceExporter) #define DllIface EXTERN_C __declspec(dllexport) #else #define DllIface EXTERN_C __declspec(dllimport) #endif // defined(DllInterfaceExporter) #else #if !defined(__cdecl) #if defined(__i386__) #define __cdecl __attribute__((cdecl)) #else #define __cdecl #endif #endif #define DllIface EXTERN_C #endif // defined(_MSC_VER) enum TargetArch { Target_Host, // Target is the same as host architecture Target_X86, Target_X64, Target_Thumb, Target_Arm64 }; struct CorDisasm; struct CorAsmDiff; // The custom print functionality to be provide by the // users of this Library typedef void(__cdecl *Printer)(const char *msg, ...); struct PrintControl { const Printer Error; const Printer Warning; const Printer Log; const Printer Dump; }; // The type of a custom function provided by the user to determine // if two offsets are considered equivalent wrt diffing code blocks. // Offset1 and Offset2 are the two offsets to be compared. // BlockOffset is the offest of the instructions (that contain Offset1 // and Offset2) from the beginning of their respective code blocks. // InstructionLength is the length of the current instruction being // compared for equivalency. typedef bool(__cdecl *OffsetComparator)(const void *UserData, size_t BlockOffset, size_t InstructionLength, uint64_t Offset1, uint64_t Offset2); // The Export/Import definitions for CoreDistools library are defined below. // A typedef for each interface function's type is defined in order to aid // the importer. // Initialize the disassembler, using default print controls typedef CorDisasm * __cdecl InitDisasm_t(enum TargetArch Target); DllIface InitDisasm_t InitDisasm; // Initialize the disassembler using custom print controls typedef CorDisasm * __cdecl NewDisasm_t(enum TargetArch Target, const PrintControl *PControl); DllIface NewDisasm_t NewDisasm; // Delete the disassembler typedef void __cdecl FinishDisasm_t(const CorDisasm *Disasm); DllIface FinishDisasm_t FinishDisasm; // DisasmInstruction -- Disassemble one instruction // Arguments: // Disasm -- The Disassembler // Address -- The address at which the bytes of the instruction // are intended to execute // Bytes -- Pointer to the actual bytes which need to be disassembled // MaxLength -- Number of bytes available in Bytes buffer // Returns: // -- The Size of the disassembled instruction // -- Zero on failure typedef size_t __cdecl DisasmInstruction_t(const CorDisasm *Disasm, const uint8_t *Address, const uint8_t *Bytes, size_t Maxlength); DllIface DisasmInstruction_t DisasmInstruction; // Initialize the Code Differ typedef CorAsmDiff * __cdecl NewDiffer_t(enum TargetArch Target, const PrintControl *PControl, const OffsetComparator Comparator); DllIface NewDiffer_t NewDiffer; // Delete the Code Differ typedef void __cdecl FinishDiff_t(const CorAsmDiff *AsmDiff); DllIface FinishDiff_t FinishDiff; // NearDiffCodeBlocks -- Compare two code blocks for semantic // equivalence // Arguments: // AsmDiff -- The Asm-differ // UserData -- Any data the user wishes to pass through into // the OffsetComparator // Address1 -- Address at which first block will execute // Bytes1 -- Pointer to the actual bytes of the first block // Size1 -- The size of the first block // Address2 -- Address at which second block will execute // Bytes2 -- Pointer to the actual bytes of the second block // Size2 -- The size of the second block // Returns: // -- true if the two blocks are equivalent, false if not. typedef bool __cdecl NearDiffCodeBlocks_t(const CorAsmDiff *AsmDiff, const void *UserData, const uint8_t *Address1, const uint8_t *Bytes1, size_t Size1, const uint8_t *Address2, const uint8_t *Bytes2, size_t Size2); DllIface NearDiffCodeBlocks_t NearDiffCodeBlocks; // Print a code block according to the Disassembler's Print Controls typedef void __cdecl DumpCodeBlock_t(const CorDisasm *Disasm, const uint8_t *Address, const uint8_t *Bytes, size_t Size); DllIface DumpCodeBlock_t DumpCodeBlock; // Print the two code blocks being diffed, according to // AsmDiff's PrintControls. typedef void __cdecl DumpDiffBlocks_t(const CorAsmDiff *AsmDiff, const uint8_t *Address1, const uint8_t *Bytes1, size_t Size1, const uint8_t *Address2, const uint8_t *Bytes2, size_t Size2); DllIface DumpDiffBlocks_t DumpDiffBlocks; #endif // !defined(_COREDISTOOLS_H_) ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corerror.xml ================================================ CLDB_S_TRUNCATION STATUS: Data value was truncated. META_S_DUPLICATE Attempt to define an object that already exists in valid scenerios. CORDBG_S_BAD_START_SEQUENCE_POINT Attempt to SetIP not at a sequence point sequence point. CORDBG_S_BAD_END_SEQUENCE_POINT Attempt to SetIP when not going to a sequence point. If both this and CORDBG_E_BAD_START_SEQUENCE_POINT are true, only CORDBG_E_BAD_START_SEQUENCE_POINT will be reported. CORDBG_S_FUNC_EVAL_HAS_NO_RESULT Some Func evals will lack a return value, CORDBG_S_VALUE_POINTS_TO_VOID The Debugging API doesn't support dereferencing void pointers. CORDBG_S_FUNC_EVAL_ABORTED The func eval completed, but was aborted. CORDBG_S_AT_END_OF_STACK "The stack walk has reached the end of the stack. There are no more frames to walk." The stack walk has reached the end of the stack. There are no more frames to walk. CORDBG_S_NOT_ALL_BITS_SET Not all bits specified were successfully applied COR_E_TYPEUNLOADED "Type has been unloaded." The type had been unloaded. COR_E_APPDOMAINUNLOADED "Attempted to access an unloaded appdomain." access unloaded appdomain COR_E_CANNOTUNLOADAPPDOMAIN "Error while unloading appdomain." Error while unloading an appdomain MSEE_E_ASSEMBLYLOADINPROGRESS "Assembly is still being loaded." Assembly is being currently being loaded COR_E_ASSEMBLYEXPECTED "The module was expected to contain an assembly manifest." The module was expected to contain an assembly manifest. COR_E_NEWER_RUNTIME "This assembly is built by a runtime newer than the currently loaded runtime and cannot be loaded." The assembly is built by a runtime newer than the currently loaded runtime, and cannot be loaded. COR_E_MULTIMODULEASSEMBLIESDIALLOWED "The module cannot be loaded because only single file assemblies are supported." The module cannot be loaded because only single file assemblies are supported. HOST_E_INVALIDOPERATION "Invalid operation." The operation is invalid HOST_E_CLRNOTAVAILABLE "CLR has been disabled due to unrecoverable error." CLR has been disabled due to unrecoverable error FUSION_E_REF_DEF_MISMATCH "The located assembly's manifest definition does not match the assembly reference." The located assembly's manifest definition does not match the assembly reference. FUSION_E_PRIVATE_ASM_DISALLOWED "A strongly-named assembly is required." A strongly-named assembly is required. FUSION_E_INVALID_NAME "The given assembly name was invalid." The given assembly name was invalid. FUSION_E_CACHEFILE_FAILED "Failed to add file to AppDomain cache." Failed to add file to AppDomain cache FUSION_E_APP_DOMAIN_LOCKED "The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest." The requested assembly version conflicts with what is already bound in the app domain or specified in the manifest COR_E_LOADING_REFERENCE_ASSEMBLY "Reference assemblies cannot not be loaded for execution." Reference assemblies cannot not be loaded for execution. COR_E_AMBIGUOUSIMPLEMENTATION "Ambiguous implementation found." Ambiguous implementation found CLDB_E_FILE_BADREAD "Error occurred during a read." Error occurred during a read. CLDB_E_FILE_BADWRITE "Error occurred during a write." Error occurred during a write. CLDB_E_FILE_OLDVER "Old version error." Old version error. CLDB_E_SMDUPLICATE "Create of shared memory failed. A memory mapping of the same name already exists." Create of shared memory failed. A memory mapping of the same name already exists. CLDB_E_NO_DATA "No .CLB data in the memory or stream." There isn't .CLB data in the memory or stream. CLDB_E_INCOMPATIBLE "Importing scope is not compatible with the emitting scope." The importing scope is not comptabile with the emitting scope CLDB_E_FILE_CORRUPT "File is corrupt." File is corrupt. CLDB_E_BADUPDATEMODE "Cannot open a incrementally build scope for full update." cannot open a incrementally build scope for full update CLDB_E_INDEX_NOTFOUND "Index not found." Index %s not found. CLDB_E_RECORD_NOTFOUND "Record not found on lookup." Record wasn't found on lookup. CLDB_E_RECORD_OUTOFORDER "Record is emitted out of order." Record is emitted out of order. CLDB_E_TOO_BIG "A blob or string was too big." A blob or string was too big. META_E_INVALID_TOKEN_TYPE "A token of the wrong type passed to a metadata function." A token of the wrong type passed to a metadata function. TLBX_E_LIBNOTREGISTERED "Typelib export: Type library is not registered." Typelib export: type library is not registered. META_E_BADMETADATA "Merge: Inconsistency in meta data import scope." Merge: Inconsistency in meta data import scope META_E_BAD_SIGNATURE "Bad binary signature." Bad binary signature META_E_BAD_INPUT_PARAMETER "Bad input parameters." Bad input parameters META_E_CANNOTRESOLVETYPEREF "Cannot resolve typeref." Cannot resolve typeref META_E_STRINGSPACE_FULL "No logical space left to create more user strings." No logical space left to create more user strings. META_E_HAS_UNMARKALL "Unmark all has been called already." Unmark all has been called already META_E_MUST_CALL_UNMARKALL "Must call UnmarkAll first before marking." Must call UnmarkAll first before marking. META_E_CA_INVALID_TARGET "Known custom attribute on invalid target." Known custom attribute on invalid target. META_E_CA_INVALID_VALUE "Known custom attribute had invalid value." Known custom attribute had invalid value. META_E_CA_INVALID_BLOB "Known custom attribute blob has bad format." Known custom attribute blob is bad format. META_E_CA_REPEATED_ARG "Known custom attribute blob has repeated named argument." Known custom attribute blob has repeated named argument. META_E_CA_UNKNOWN_ARGUMENT "Known custom attribute named argument not recognized." Known custom attrubte named arg not recognized. META_E_CA_UNEXPECTED_TYPE "Known attribute parser found unexpected type." Known attribute parser found unexpected type. META_E_CA_INVALID_ARGTYPE "Known attribute parser only handles fields, not properties." Known attribute parser only handles fields -- no properties. META_E_CA_INVALID_ARG_FOR_TYPE "Known attribute parser found an argument that is invalid for the object it is applied to." Known attribute parser found an argument that is invalid for the object it is applied to. META_E_CA_INVALID_UUID "The format of the UUID was invalid." The format of the UUID was invalid. META_E_CA_INVALID_MARSHALAS_FIELDS "The MarshalAs attribute has fields set that are not valid for the specified unmanaged type." The MarshalAs attribute has fields set that are not valid for the specified unmanaged type. META_E_CA_NT_FIELDONLY "The specified unmanaged type is only valid on fields." The specified unmanaged type is only valid on fields. META_E_CA_NEGATIVE_PARAMINDEX "The parameter index cannot be negative." The parameter index cannot be negative. META_E_CA_NEGATIVE_CONSTSIZE "The constant size cannot be negative." The constant size cannot be negative. META_E_CA_FIXEDSTR_SIZE_REQUIRED "A fixed string requires a size." A fixed string requires a size. META_E_CA_CUSTMARSH_TYPE_REQUIRED "A custom marshaler requires the custom marshaler type." A custom marshaler requires the custom marshaler type. META_E_NOT_IN_ENC_MODE "SaveDelta was called without being in EnC mode." SaveDelta was called without being in EnC mode META_E_CA_BAD_FRIENDS_ARGS "InternalsVisibleTo can't have a version, culture, or processor architecture." InternalsVisibleTo can't have a version, culture, or processor architecture. META_E_CA_FRIENDS_SN_REQUIRED Strong-name signed assemblies can only grant friend access to strong name-signed assemblies VLDTR_E_RID_OUTOFRANGE "Rid is out of range." Rid is out of range. VLDTR_E_STRING_INVALID "String offset is invalid." String offset is invalid. VLDTR_E_GUID_INVALID "GUID offset is invalid." GUID offset is invalid. VLDTR_E_BLOB_INVALID "Blob offset if invalid." Blob offset if invalid. VLDTR_E_MR_BADCALLINGCONV "MemberRef has invalid calling convention." MemberRef has invalid calling convention. VLDTR_E_SIGNULL "Signature specified is zero-sized." Signature specified is zero-sized. VLDTR_E_MD_BADCALLINGCONV "Method signature has invalid calling convention." Method signature has invalid calling convention. VLDTR_E_MD_THISSTATIC "Method is marked static but has HASTHIS/EXPLICITTHIS set on the calling convention." Method is marked static but has HASTHIS/EXPLICITTHIS set on the calling convention. VLDTR_E_MD_NOTTHISNOTSTATIC "Method is not marked static but is not HASTHIS or EXPLICITTHIS." Method is not marked static but is not HASTHIS/EXPLICITTHIS. VLDTR_E_MD_NOARGCNT "Method signature is missing the argument count." Method signature is missing the argument count. VLDTR_E_SIG_MISSELTYPE "Signature missing element type." Signature missing element type. VLDTR_E_SIG_MISSTKN "Signature missing token." Signature missing token. VLDTR_E_SIG_TKNBAD "Signature has bad token." Signature has bad token. VLDTR_E_SIG_MISSFPTR "Signature is missing function pointer." Signature is missing function pointer. VLDTR_E_SIG_MISSFPTRARGCNT "Signature has function pointer missing argument count." Signature has function pointer missing argument count. VLDTR_E_SIG_MISSRANK "Signature is missing rank specification." Signature is missing rank specification. VLDTR_E_SIG_MISSNSIZE "Signature is missing count of sized dimensions." Signature is missing count of sized dimensions. VLDTR_E_SIG_MISSSIZE "Signature is missing size of dimension." Signature is missing size of dimension. VLDTR_E_SIG_MISSNLBND "Signature is missing count of lower bounds." Signature is missing count of lower bounds. VLDTR_E_SIG_MISSLBND "Signature is missing a lower bound." Signature is missing a lower bound. VLDTR_E_SIG_BADELTYPE "Signature has bad element type." Signature has bad element type. VLDTR_E_TD_ENCLNOTNESTED "TypeDef not nested has encloser." TypeDef not nested has encloser. VLDTR_E_FMD_PINVOKENOTSTATIC "Field or method is PInvoke but is not marked Static." Field/method is PInvoke but is not marked Static. VLDTR_E_SIG_SENTINMETHODDEF "E_T_SENTINEL in MethodDef signature." E_T_SENTINEL in MethodDef signature VLDTR_E_SIG_SENTMUSTVARARG "E_T_SENTINEL <=> VARARG." E_T_SENTINEL <=> VARARG VLDTR_E_SIG_MULTSENTINELS "Multiple E_T_SENTINELs." Multiple E_T_SENTINELs VLDTR_E_SIG_MISSARG "Signature missing argument." Signature missing argument VLDTR_E_SIG_BYREFINFIELD "Field of ByRef type." Field of ByRef type CORDBG_E_UNRECOVERABLE_ERROR "Unrecoverable API error." Unrecoverable API error. CORDBG_E_PROCESS_TERMINATED "Process was terminated." Process was terminated. CORDBG_E_PROCESS_NOT_SYNCHRONIZED "Process not synchronized." Process not synchronized. CORDBG_E_CLASS_NOT_LOADED "A class is not loaded." A class is not loaded. CORDBG_E_IL_VAR_NOT_AVAILABLE "An IL variable is not available at the current native IP." An IL variable is not available at the CORDBG_E_BAD_REFERENCE_VALUE "A reference value was found to be bad during dereferencing." A reference value was found to be bad CORDBG_E_FIELD_NOT_AVAILABLE "A field in a class is not available, because the runtime optimized it away." A field in a class is not available, CORDBG_E_NON_NATIVE_FRAME "'Native-frame-only' operation on non-native frame." "Native frame only" operation on CORDBG_E_CODE_NOT_AVAILABLE "The code is currently unavailable." The code is currently unavailable CORDBG_E_FUNCTION_NOT_IL "Attempt to get a ICorDebugFunction for a function that is not IL." Attempt to get a ICorDebugFunction for CORDBG_E_CANT_SET_IP_INTO_FINALLY "SetIP is not possible because SetIP would move EIP from outside of an exception handling finally clause to a point inside of one." SetIP isn't possible, because SetIP would CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY "SetIP is not possible because it would move EIP from within an exception handling finally clause to a point outside of one." SetIP isn't possible because it would move CORDBG_E_CANT_SET_IP_INTO_CATCH "SetIP is not possible, because SetIP would move EIP from outside of an exception handling catch clause to a point inside of one." SetIP isn't possible, because SetIP would CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME "SetIP cannot be done on any frame except the leaf frame." Setip cannot be done on any frame except CORDBG_E_SET_IP_IMPOSSIBLE "SetIP is not allowed." SetIP isn't allowed. For example, there is CORDBG_E_FUNC_EVAL_BAD_START_POINT "Func eval cannot work. Bad starting point." Func eval can't work if we're, for example, CORDBG_E_INVALID_OBJECT "This object value is no longer valid." This object value is no longer valid. CORDBG_E_FUNC_EVAL_NOT_COMPLETE "CordbEval::GetResult called before func eval has finished." If you call CordbEval::GetResult before the CORDBG_E_STATIC_VAR_NOT_AVAILABLE "A static variable is not available because it has not been initialized yet." A static variable isn't available because CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER "SetIP cannot leave or enter a filter." SetIP can't leave or enter a filter CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE "JIT settings for ZAP modules cannot be changed." You can't change JIT settings for ZAP CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64 "SetIP is not possible because it would move EIP from within a finally clause to a point outside of one on this platforms." SetIP isn't possible because it would move CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64 "SetIP is not possible because it would move EIP from within a catch clause to a point outside of one on this platforms." SetIP isn't possible because it would move CORDBG_E_CANT_SET_TO_JMC "Cannot use JMC on this code (likely wrong JIT settings)." Can't use JMC on this code (likely wrong jit settings). CORDBG_E_NO_CONTEXT_FOR_INTERNAL_FRAME "Internal frame markers have no associated context." Internal frame markers have no associated context. CORDBG_E_NOT_CHILD_FRAME "The current frame is not a child frame." The current frame is not a child frame. CORDBG_E_NON_MATCHING_CONTEXT "The provided CONTEXT does not match the specified thread." The provided CONTEXT does not match the specified thread. The stack pointer in the provided CONTEXT must match the cached stack base and stack limit of the thread. CORDBG_E_PAST_END_OF_STACK "The stackwalker is now past the end of stack. No information is available." The stackwalker is now past the end of stack. No information is available. CORDBG_E_FUNC_EVAL_CANNOT_UPDATE_REGISTER_IN_NONLEAF_FRAME "Func eval cannot update a variable stored in a register on a non-leaf frame. The most likely cause is that such a variable is passed as a ref/out argument." Func eval cannot update a variable stored in a register on a non-leaf frame. The most likely cause is that such a variable is passed as a ref/out argument. CORDBG_E_BAD_THREAD_STATE "The state of the thread is invalid." The state of the thread is invalid. CORDBG_E_DEBUGGER_ALREADY_ATTACHED "This process has already been attached." This process has already been attached to CORDBG_E_SUPERFLOUS_CONTINUE "Returned from a call to Continue that was not matched with a stopping event." Returned from a call to Continue that was CORDBG_E_SET_VALUE_NOT_ALLOWED_ON_NONLEAF_FRAME "Cannot perfrom SetValue on non-leaf frames." Can't perfrom SetValue on non-leaf frames. CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED "Tried to do Edit and Continue on a module that was not started in Edit and Continue mode." Tried to do EnC on a module that wasn't CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION "SetIP cannot be done on any exception." Setip cannot be done on any exception CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL "The 'variable' does not exist because it is a literal optimized away by the compiler." The 'variable' doesn't exist because it is a CORDBG_E_PROCESS_DETACHED "Process has been detached." Process has been detached from CORDBG_E_ENC_CANT_ADD_FIELD_TO_VALUE_OR_LAYOUT_CLASS "Adding a field to a value or layout class is prohibited." Adding a field to a value or layout class is prohibitted, CORDBG_E_FIELD_NOT_STATIC "GetStaticFieldValue called on a non-static field." Returned if someone tries to call GetStaticFieldValue CORDBG_E_FIELD_NOT_INSTANCE "Returned if someone tries to call GetStaticFieldValue on a non-instance field." Returned if someone tries to call GetStaticFieldValue CORDBG_E_ENC_JIT_CANT_UPDATE "The JIT is unable to update the method." The JIT is unable to update the method. CORDBG_E_ENC_INTERNAL_ERROR "Internal Runtime Error while doing Edit-and-Continue." Generic message for "Something user doesn't control went wrong" message. CORDBG_E_ENC_HANGING_FIELD "The field was added via Edit and Continue after the class was loaded." The field was added via EnC after the class was loaded, and so instead of the field being contiguous with the other fields, it's 'hanging' off the instance or type. This error is used to indicate that either the storage for this field is not yet available and so the field value cannot be read, or the debugger needs to use an EnC specific code path to get the value. CORDBG_E_MODULE_NOT_LOADED "Module not loaded." If the module isn't loaded, including if it's been unloaded. CORDBG_E_UNABLE_TO_SET_BREAKPOINT "Cannot set a breakpoint here." Can't set a breakpoint here. CORDBG_E_DEBUGGING_NOT_POSSIBLE "Debugging is not possible due to an incompatibility within the CLR implementation." Debugging isn't possible due to an incompatibility within the CLR implementation. CORDBG_E_KERNEL_DEBUGGER_ENABLED "A kernel debugger is enabled on the system. User-mode debugging will trap to the kernel debugger." Debugging isn't possible because a kernel debugger is enabled on the system. CORDBG_E_KERNEL_DEBUGGER_PRESENT "A kernel debugger is present on the system. User-mode debugging will trap to the kernel debugger." Debugging isn't possible because a kernel debugger is present on the system. CORDBG_E_INCOMPATIBLE_PROTOCOL "The debugger's protocol is incompatible with the debuggee." The debugger's protocol is incompatible with the debuggee. CORDBG_E_TOO_MANY_PROCESSES "The debugger can only handle a finite number of debuggees." The debugger can only handle a finite number of debuggees. CORDBG_E_INTEROP_NOT_SUPPORTED "Interop debugging is not supported." Interop debugging is not supported CORDBG_E_NO_REMAP_BREAKPIONT "Cannot call RemapFunction until have received RemapBreakpoint." Cannot call RemapFunction until have received RemapBreakpoint CORDBG_E_OBJECT_NEUTERED "Object is in a zombie state." Object has been neutered (it's in a zombie state). CORPROF_E_FUNCTION_NOT_COMPILED "Function not yet compiled." Function not yet compiled. CORPROF_E_DATAINCOMPLETE "The ID is not fully loaded/defined yet." The ID is not fully loaded/defined yet. CORPROF_E_FUNCTION_NOT_IL "The Method has no associated IL." The Method has no associated IL CORPROF_E_NOT_MANAGED_THREAD "The thread has never run managed code before." The thread has never run managed code before CORPROF_E_CALL_ONLY_FROM_INIT "The function may only be called during profiler initialization." The function may only be called during profiler init CORPROF_E_NOT_YET_AVAILABLE "Requested information is not yet available." This is a general error used to indicated that the information CORPROF_E_TYPE_IS_PARAMETERIZED "The given type is a generic and cannot be used with this method." The given type is a generic and cannot be used with this method. CORPROF_E_FUNCTION_IS_PARAMETERIZED "The given function is a generic and cannot be used with this method." The given function is a generic and cannot be used with this method. CORPROF_E_STACKSNAPSHOT_INVALID_TGT_THREAD A profiler tried to walk the stack of an invalid thread CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX A profiler can not walk a thread that is currently executing unmanaged code CORPROF_E_STACKSNAPSHOT_UNSAFE A stackwalk at this point may cause dead locks or data corruption CORPROF_E_STACKSNAPSHOT_ABORTED Stackwalking callback requested the walk to abort CORPROF_E_LITERALS_HAVE_NO_ADDRESS Returned when asked for the address of a static that is a literal. CORPROF_E_UNSUPPORTED_CALL_SEQUENCE A call was made at an unsupported time. Examples include illegally calling a profiling API method asynchronously, calling a method that might trigger a GC at an unsafe time, and calling a method at a time that could cause locks to be taken out of order. CORPROF_E_ASYNCHRONOUS_UNSAFE A legal asynchronous call was made at an unsafe time (e.g., CLR locks are held) CORPROF_E_CLASSID_IS_ARRAY The specified ClassID cannot be inspected by this function because it is an array CORPROF_E_CLASSID_IS_COMPOSITE The specified ClassID is a non-array composite type (e.g., ref) and cannot be inspected CORPROF_E_PROFILER_DETACHING The profiler's call into the CLR is disallowed because the profiler is attempting to detach. CORPROF_E_PROFILER_NOT_ATTACHABLE The profiler does not support attaching to a live process. CORPROF_E_UNRECOGNIZED_PIPE_MSG_FORMAT The message sent on the profiling API attach pipe is in an unrecognized format. CORPROF_E_PROFILER_ALREADY_ACTIVE The request to attach a profiler was denied because a profiler is already loaded. CORPROF_E_PROFILEE_INCOMPATIBLE_WITH_TRIGGER Unable to request a profiler attach because the target profilee's runtime is of a version incompatible with the current process calling AttachProfiler(). CORPROF_E_IPC_FAILED AttachProfiler() encountered an error while communicating on the pipe to the target profilee. This is often caused by a target profilee that is shutting down or killed while AttachProfiler() is reading or writing the pipe. CORPROF_E_PROFILEE_PROCESS_NOT_FOUND AttachProfiler() was unable to find a profilee with the specified process ID. CORPROF_E_CALLBACK3_REQUIRED Profiler must implement ICorProfilerCallback3 interface for this call to be supported. CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER This call was attempted by a profiler that attached to the process after startup, but this call is only supported by profilers that are loaded into the process on startup. CORPROF_E_IRREVERSIBLE_INSTRUMENTATION_PRESENT Detach is impossible because the profiler has either instrumented IL or inserted enter/leave hooks. Detach was not attempted; the profiler is still fully attached. CORPROF_E_RUNTIME_UNINITIALIZED The profiler called a function that cannot complete because the CLR is not yet fully initialized. The profiler may try again once the CLR has fully started. CORPROF_E_IMMUTABLE_FLAGS_SET Detach is impossible because immutable flags were set by the profiler at startup. Detach was not attempted; the profiler is still fully attached. CORPROF_E_PROFILER_NOT_YET_INITIALIZED The profiler called a function that cannot complete because the profiler is not yet fully initialized. CORPROF_E_INCONSISTENT_WITH_FLAGS The profiler called a function that first requires additional flags to be set in the event mask. This HRESULT may also indicate that the profiler called a function that first requires that some of the flags currently set in the event mask be reset. CORPROF_E_PROFILER_CANCEL_ACTIVATION The profiler has requested that the CLR instance not load the profiler into this process. CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE Concurrent GC mode is enabled, which prevents use of COR_PRF_MONITOR_GC CORPROF_E_DEBUGGING_DISABLED This functionality requires CoreCLR debugging to be enabled. CORPROF_E_TIMEOUT_WAITING_FOR_CONCURRENT_GC Timed out on waiting for concurrent GC to finish during attach. CORPROF_E_MODULE_IS_DYNAMIC The specified module was dynamically generated (e.g., via Reflection.Emit API), and is thus not supported by this API method. CORPROF_E_CALLBACK4_REQUIRED Profiler must implement ICorProfilerCallback4 interface for this call to be supported. CORPROF_E_REJIT_NOT_ENABLED This call is not supported unless ReJIT is first enabled during initialization by setting COR_PRF_ENABLE_REJIT via SetEventMask. CORPROF_E_FUNCTION_IS_COLLECTIBLE The specified function is instantiated into a collectible assembly, and is thus not supported by this API method. CORPROF_E_CALLBACK6_REQUIRED Profiler must implement ICorProfilerCallback6 interface for this call to be supported. CORPROF_E_CALLBACK7_REQUIRED Profiler must implement ICorProfilerCallback7 interface for this call to be supported. CORPROF_E_REJIT_INLINING_DISABLED The runtime's tracking of inlined methods for ReJIT is not enabled. CORDIAGIPC_E_BAD_ENCODING The runtime was unable to decode the Header or Payload. CORDIAGIPC_E_UNKNOWN_COMMAND The specified CommandSet or CommandId is unknown. CORDIAGIPC_E_UNKNOWN_MAGIC The magic version of Diagnostics IPC is unknown. CORDIAGIPC_E_UNKNOWN_ERROR An unknown error occurred in the Diagnpostics IPC Server. CORPROF_E_SUSPENSION_IN_PROGRESS The runtime cannot be suspened since a suspension is already in progress. CORSEC_E_POLICY_EXCEPTION "PolicyException thrown." PolicyException thrown CORSEC_E_MIN_GRANT_FAIL "Failed to grant minimum permission requests." Failed to grant minimum permission requests CORSEC_E_NO_EXEC_PERM "Failed to grant permission to execute." Failed to grant permission to execute CORSEC_E_XMLSYNTAX "XML Syntax error." XML Syntax error CORSEC_E_INVALID_STRONGNAME "Strong name validation failed." Strong name validation failed CORSEC_E_INVALID_IMAGE_FORMAT "Invalid assembly file format." Invalid assembly file format CORSEC_E_INVALID_PUBLICKEY "Invalid assembly public key." Invalid assembly public key CORSEC_E_SIGNATURE_MISMATCH "Signature size mismatch." Signature size mismatch CORSEC_E_CRYPTO "Failure during Cryptographic operation." generic CryptographicException CORSEC_E_CRYPTO_UNEX_OPER "Unexpected Cryptographic operation." generic CryptographicUnexpectedOperationException COR_E_EXCEPTION "General Exception" Base class for all exceptions in the runtime COR_E_SYSTEM "System.Exception" The base class for the runtime's "less serious" exceptions COR_E_ARGUMENTOUTOFRANGE "An argument was out of its legal range." An argument was out of its legal range. COR_E_ARRAYTYPEMISMATCH "Attempted to store an object of the wrong type in an array." Attempted to store an object of the wrong type in an array COR_E_CONTEXTMARSHAL "Attempted to marshal an object across a context boundary." COR_E_TIMEOUT "Operation timed out." COR_E_EXECUTIONENGINE "Internal CLR error." An internal error happened in the Common Language Runtime's Execution Engine COR_E_FIELDACCESS "Access to this field is denied." Access to this field is denied. COR_E_INDEXOUTOFRANGE "Array subscript out of range." Attempted to access an element within an array by using an index that is COR_E_INVALIDOPERATION "An operation is not legal in the current state." An operation is not legal in the current state. COR_E_SECURITY "An error relating to security occurred." An error relating to security occurred. COR_E_SERIALIZATION "An error relating to serialization occurred." An error relating to serialization has occurred. COR_E_VERIFICATION "A verification failure has occurred." A verification failure occurred COR_E_METHODACCESS "Access to this method is denied." Access to this method is denied. COR_E_MISSINGFIELD "Field does not exist." An attempt was made to dynamically access a field that does not exist. COR_E_MISSINGMEMBER "Member does not exist." An attempt was made to dynamically invoke or access a field or method COR_E_MISSINGMETHOD "Method does not exist." An attempt was made to dynamically invoke a method that does not exist COR_E_MULTICASTNOTSUPPORTED "Attempt to combine delegates that are not multicast." Attempted to combine delegates that are not multicast COR_E_NOTSUPPORTED "Operation is not supported." The operation is not supported COR_E_OVERFLOW "Arithmetic, casting or conversion operation overflowed or underflowed." An arithmetic, casting, or conversion operation overflowed or underflowed. COR_E_RANK "An array has the wrong number of dimensions for a particular operation." An array has the wrong number of dimensions for a particular operation. COR_E_SYNCHRONIZATIONLOCK "This operation must be called from a synchronized block." Wait(), Notify() or NotifyAll() was called from an unsynchronized ** block of c COR_E_THREADINTERRUPTED "Thread was interrupted from a waiting state." Indicates that the thread was interrupted from a waiting state COR_E_MEMBERACCESS "Access to this member is denied." Access to this member is denied. COR_E_THREADSTATE "Thread is in an invalid state for this operation." Indicate that the Thread class is in an invalid state for the method call COR_E_THREADSTOP "Thread is stopping." Thrown into a thread to cause it to stop. This exception is typically not caught COR_E_TYPELOAD "Could not find or load a type." Could not find or load a specific type (class, enum, etc). COR_E_ENTRYPOINTNOTFOUND "Could not find the specified DllImport entrypoint." Could not find the specified DllImport entry point COR_E_DLLNOTFOUND "Could not find the specified DllImport Dll." Could not find the specified DllImport DLL. COR_E_THREADSTART Indicate that a user thread fails to start. COR_E_INVALIDCOMOBJECT "An invalid __ComObject has been used." An invalid __ComObject has been used. COR_E_NOTFINITENUMBER "Not a Number." Thrown if value (a floating point number) is either the not a number value (NaN) or +- infinity value COR_E_DUPLICATEWAITOBJECT "An object appears more than once in the wait objects array." An object appears more than once in the wait objects array. COR_E_SEMAPHOREFULL "Reached maximum count for semaphore." Adding the given count to the semaphore would cause it to exceed its maximum count. COR_E_WAITHANDLECANNOTBEOPENED "No semaphore of the given name exists." No Semaphore of the given name exists. COR_E_ABANDONEDMUTEX "The wait completed due to an abandoned mutex." The wait completed due to an abandoned mutex. COR_E_THREADABORTED "Thread has aborted." Thrown into a thread to cause it to abort. Not catchable. COR_E_INVALIDOLEVARIANTTYPE "OLE Variant has an invalid type." The type of an OLE variant that was passed into the runtime is invalid. COR_E_MISSINGMANIFESTRESOURCE "An expected resource in the assembly manifest was missing." An expected resource in the assembly manifest was missing. COR_E_SAFEARRAYTYPEMISMATCH "A mismatch has occurred between the runtime type of the array and the sub type recorded in the metadata." A mismatch has occurred between the runtime type of the array and the subtype recorded in the metadata COR_E_TYPEINITIALIZATION "Uncaught exception during type initialization." An exception was thrown by a type's initializer (.cctor). COR_E_MARSHALDIRECTIVE "Invalid marshaling directives." The marshaling directives are invalid. COR_E_MISSINGSATELLITEASSEMBLY "An expected satellite assembly containing the ultimate fallback resources for a given culture was not found or could not be loaded." An expected satellite assembly containing the ultimate fallback resources COR_E_FORMAT "The format of one argument does not meet the contract of the method." The format of one argument does not meet the contract of the method. COR_E_SAFEARRAYRANKMISMATCH "A mismatch has occurred between the runtime rank of the array and the rank recorded in the metadata." A mismatch has occurred between the runtime rank of the array and the rank recorded in the metadata COR_E_PLATFORMNOTSUPPORTED "Operation is not supported on this platform." The method is not supported on this platform COR_E_INVALIDPROGRAM "Invalid IL or CLR metadata." A program contained invalid IL or bad metadata. Usually this is a compiler bug. COR_E_OPERATIONCANCELED "The operation was cancelled." The operation was cancelled. COR_E_INSUFFICIENTMEMORY Not enough memory was available for an operation. COR_E_RUNTIMEWRAPPED An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException. COR_E_DATAMISALIGNED "A datatype misalignment was detected in a load or store instruction." A datatype misalignment was detected in a load or store instruction. COR_E_CODECONTRACTFAILED "A managed code contract (ie, precondition, postcondition, invariant, or assert) failed." A managed code contract (ie, precondition, postcondition, invariant, or assert) failed. COR_E_TYPEACCESS "Access to this type is denied." Access to this type is denied. COR_E_ACCESSING_CCW "Fail to access a CCW because the corresponding managed object is already collected." Fail to access a CCW because the corresponding managed object is already collected. COR_E_KEYNOTFOUND "The given key was not present in the dictionary." COR_E_INSUFFICIENTEXECUTIONSTACK "Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space." Insufficient stack to continue executing the program safely. This can happen from having too many functions on the call stack or function on the stack using too much stack space. COR_E_APPLICATION "Application exception" The base class for all "less serious" exceptions. COR_E_INVALIDFILTERCRITERIA "The given filter criteria does not match the filter content." The given filter criteria does not match the filter contract. COR_E_REFLECTIONTYPELOAD "Could not find or load a specific class that was requested through Reflection." Could not find or load a specific class that was requested through Reflection COR_E_TARGET "Attempt to invoke non-static method with a null Object." - If you attempt to invoke a non-static method with a null Object - If you atte COR_E_TARGETINVOCATION "Uncaught exception thrown by method called through Reflection." If the method called throws an exception COR_E_CUSTOMATTRIBUTEFORMAT "Custom attribute has invalid format." If the binary format of a custom attribute is invalid. COR_E_IO "Error during managed I/O." Some sort of I/O error. COR_E_FILELOAD "Could not find or load a specific file." COR_E_OBJECTDISPOSED "The object has already been disposed." The object has already been disposed. COR_E_FAILFAST "Runtime operation halted by call to System.Environment.FailFast()." Runtime operation halted by call to System.Environment.FailFast(). COR_E_HOSTPROTECTION "The host has forbidden this operation." Attempted to perform an operation that was forbidden by the host. COR_E_ILLEGAL_REENTRANCY "Attempted to call into managed code when executing inside a low level extensibility point." Attempted to call into managed code when executing inside a low level extensibility point. CLR_E_SHIM_RUNTIMELOAD "Failed to load the runtime." Failed to load the runtime CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND "A runtime has already been bound for legacy activation policy use." VER_E_FIELD_SIG "[field sig]" VER_E_CIRCULAR_VAR_CONSTRAINTS "Method parent has circular class type parameter constraints." VER_E_CIRCULAR_MVAR_CONSTRAINTS "Method has circular method type parameter constraints." COR_E_Data VLDTR_E_SIG_BADVOID "Illegal 'void' in signature." Illegal "void" in signature VLDTR_E_GP_ILLEGAL_VARIANT_MVAR "GenericParam is a method type parameter and must be non-variant." GenericParam is a method type parameter and must be non-variant CORDBG_E_THREAD_NOT_SCHEDULED "Thread is not scheduled. Thus we may not have OSThreadId, handle, or context." Thread is not scheduled. Thus we may not have OSThreadId, handle, or context CORDBG_E_HANDLE_HAS_BEEN_DISPOSED "Handle has been disposed." Handle has been disposed. CORDBG_E_NONINTERCEPTABLE_EXCEPTION "Cannot intercept this exception." Cant intercept this exception. CORDBG_E_INTERCEPT_FRAME_ALREADY_SET "The intercept frame for this exception has already been set." The intercept frame for this exception has already been set. CORDBG_E_NO_NATIVE_PATCH_AT_ADDR "There is no native patch at the given address." there's no native patch at the given address. CORDBG_E_MUST_BE_INTEROP_DEBUGGING "This API is only allowed when interop debugging." This API is only allowed when interop debugging. CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR "There is already a native patch at the address." There's already a native patch at the address CORDBG_E_TIMEOUT "A wait timed out, likely an indication of deadlock." a wait timed out .. likely an indication of deadlock. CORDBG_E_CANT_CALL_ON_THIS_THREAD "Cannot use the API on this thread." Can't use the API on this thread. CORDBG_E_ENC_INFOLESS_METHOD "Method was not JIT'd in EnC mode." Method was not JITed in EnC mode CORDBG_E_ENC_IN_FUNCLET "Method is in a callable handler/filter. Cannot increase stack." Method is in a callable handler/filter. Cant grow stack CORDBG_E_ENC_EDIT_NOT_SUPPORTED "Attempt to perform unsupported edit." Attempt to perform unsupported edit CORDBG_E_NOTREADY "The LS is not in a good spot to perform the requested operation." The LS is not in a good spot to perform the requested operation. CORDBG_E_CANNOT_RESOLVE_ASSEMBLY "We failed to resolve assembly given an AssemblyRef token. Assembly may be not loaded yet or not a valid token." We failed to resolve assembly given an AssemblyRef token. Assembly may be not loaded yet or not a valid token. CORDBG_E_MUST_BE_IN_LOAD_MODULE "Must be in context of LoadModule callback to perform requested operation." Must be in context of LoadModule callback to perform requested operation CORDBG_E_CANNOT_BE_ON_ATTACH "Requested operation cannot be performed during an attach operation." Requested operation cannot be performed during an attach operation CORDBG_E_NGEN_NOT_SUPPORTED "NGEN must be supported to perform the requested operation." NGEN must be supported to perform the requested operation CORDBG_E_ILLEGAL_SHUTDOWN_ORDER "Trying to shutdown out of order." Trying to shutdown out of order. CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS "Debugging fiber mode managed process is not supported." For Whidbey, we don't support debugging fiber mode managed process CORDBG_E_MUST_BE_IN_CREATE_PROCESS "Must be in context of CreateProcess callback to perform requested operation." Must be in context of CreateProcess callback to perform requested operation CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS "All outstanding func-evals have not completed, detaching is not allowed at this time." All outstanding func-evals have not completed, detaching is not allowed at this time. CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS "All outstanding steppers have not been closed, detaching is not allowed at this time." All outstanding steppers have not been closed, detaching is not allowed at this time. CORDBG_E_CANT_INTEROP_STEP_OUT "Cannot have an ICorDebugStepper do a native step-out." Can't have an ICorDebugStepper do a native step-out. CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS "All outstanding breakpoints have not been closed, detaching is not allowed at this time." All outstanding breakpoints have not been closed, detaching is not allowed at this time. CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW "The operation is illegal because of a stack overflow." the operation is illegal because of a stackoverflow. CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT "The operation failed because it is a GC unsafe point." The operation failed because it's a GC unsafe point. CORDBG_E_ILLEGAL_IN_PROLOG "The operation failed because the thread is in the prolog." The operation failed because the thread is in the prolog CORDBG_E_ILLEGAL_IN_NATIVE_CODE "The operation failed because the thread is in native code." The operation failed because the thread is in native code CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE "The operation failed because the thread is in optimized code." The operation failed because the thread is in optimized code. CORDBG_E_APPDOMAIN_MISMATCH "A supplied object or type belongs to the wrong AppDomain." A supplied object or type belongs to the wrong AppDomain CORDBG_E_CONTEXT_UNVAILABLE "The thread's context is not available." The thread's context is not available. CORDBG_E_INCOMPATIBLE_PLATFORMS "The operation failed because debuggee and debugger are on incompatible platforms." The operation failed because debuggee and debugger are on incompatible platform CORDBG_E_DEBUGGING_DISABLED "The operation failed because the debugging has been disabled" The operation failed because the debugging has been disabled CORDBG_E_DETACH_FAILED_ON_ENC "Detach is illegal after an Edit and Continue on a module." Detach is illegal after a module has been EnCed. CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE "Cannot intercept the current exception at the specified frame." Interception of the current exception is not legal CORDBG_E_HELPER_MAY_DEADLOCK "The debugger helper thread cannot obtain the locks it needs to perform this operation." Helper thread can not safely run code. The opereration may work at a later time. CORDBG_E_MISSING_METADATA "The operation failed because the debugger could not get the metadata." The operation failed because the debugger could not get the metadata. CORDBG_E_TARGET_INCONSISTENT "The debuggee is in a corrupt state." The debuggee is in a corrupt state. CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES "Detach failed because there are outstanding resources in the target." The debugger is holding resource in the target (such as GC handles, function evaluations, etc). These resources must be released through the appropriate ICorDebug API before detach can succeed. CORDBG_E_TARGET_READONLY "The debuggee is read-only." The provided ICorDebugDataTarget does not implement ICorDebugMutableDataTarget. CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS "The version of clr.dll in the target does not match the one mscordacwks.dll was built for." A clr/mscordacwks mismatch will cause DAC to fail to initialize in ClrDataAccess::Initialize CORDBG_E_MODULE_LOADED_FROM_DISK "Symbols are not supplied for modules loaded from disk." Symbols are not supplied for modules loaded from disk CORDBG_E_SYMBOLS_NOT_AVAILABLE "The application did not supply symbols when it loaded or created this module, or they are not yet available." The application did not supply symbols when it loaded or created this module, or they are not yet available CORDBG_E_DEBUG_COMPONENT_MISSING "A debug component is not installed." A debug component is not installed CORDBG_E_LIBRARY_PROVIDER_ERROR "The ICLRDebuggingLibraryProvider callback returned an error or did not provide a valid handle." The ICLRDebuggingLibraryProvider callback returned an error or did not provide a valid handle CORDBG_E_NOT_CLR "The module at the base address indicated was not recognized as a CLR" The module at the base address indicated was not recognized as a CLR CORDBG_E_MISSING_DATA_TARGET_INTERFACE "The provided data target does not implement the required interfaces for this version of the runtime" The provided data target does not implement the required interfaces for this version of the runtime CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL "This debugging model is unsupported by the specified runtime" This debugging model is unsupported by the specified runtime CORDBG_E_UNSUPPORTED_FORWARD_COMPAT "The debugger is not designed to support the version of the CLR the debuggee is using." The debugger is not designed to support the version of the CLR the debuggee is using. CORDBG_E_UNSUPPORTED_VERSION_STRUCT "The version struct has an unrecognized value for wStructVersion" The version struct has an unrecognized value for wStructVersion CORDBG_E_READVIRTUAL_FAILURE "A call into a ReadVirtual implementation returned failure" A call into a ReadVirtual implementation returned failure CORDBG_E_VALUE_POINTS_TO_FUNCTION "The Debugging API doesn't support dereferencing function pointers." The Debugging API doesn't support dereferencing function pointers. CORDBG_E_CORRUPT_OBJECT "The address provided does not point to a valid managed object." The address provided does not point to a valid managed object. CORDBG_E_GC_STRUCTURES_INVALID "The GC heap structures are not in a valid state for traversal." The GC heap structures are not in a valid state for traversal. CORDBG_E_INVALID_OPCODE "The specified IL offset or opcode is not supported for this operation." The specified IL offset or opcode is not supported for this operation. CORDBG_E_UNSUPPORTED "The specified action is unsupported by this version of the runtime." The specified action is unsupported by this version of the runtime. CORDBG_E_MISSING_DEBUGGER_EXPORTS "The debuggee memory space does not have the expected debugging export table." The debuggee memory space does not have the expected debugging export table. CORDBG_E_DATA_TARGET_ERROR "Failure when calling a data target method." Failure when calling a data target method. CORDBG_E_UNSUPPORTED_DELEGATE "The delegate contains a delegate currently not supported by the API." The delegate contains a delegate currently not supported by the API. CORDBG_E_ASSEMBLY_UPDATES_APPLIED "The operation is not supported because assembly updates have been applied." The operation is not supported because assembly updates have been applied. PEFMT_E_64BIT "File is PE32+." File is PE32+ PEFMT_E_32BIT "File is PE32" File is PE32 CLDB_E_INTERNALERROR CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW "The bound assembly has a version that is lower than that of the request." For AppX binder, indicates that bound assembly has a version lower than that requested, and we will refuse version rollback. CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH "The assembly version has a public key token that does not match that of the request." For AppX binder, indicates that bound assembly's public key token doesn't match the key in the assembly name. CLR_E_BIND_IMAGE_UNAVAILABLE "The requested image was not found or is unavailable." Occurs if a request for a native image is made on an BINDER_SPACE::Assembly interface when one is not available. CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT "The provided identity format is not recognized." If a binder is provided an identity format that it cannot parse, it returns this error. CLR_E_BIND_ASSEMBLY_NOT_FOUND "A binding for the specified assembly name was not found." Returned by binders that bind based on assembly identity. CLR_E_BIND_TYPE_NOT_FOUND "A binding for the specified type name was not found." Returned by binders that bind based on type identity. CLR_E_GC_OOM "Failfast due to an OOM during a GC" During a GC when we try to allocate memory for GC datastructures we could not. CLR_E_GC_BAD_AFFINITY_CONFIG "GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't specify any CPUs the current process is affinitized to." During a GC initialization, the affinity mask specified via GCHeapAffinitizeMask or GCHeapAffinitizeRanges didn't contain any CPUs the current process is affinitized to. CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT "GCHeapAffinitizeRanges configuration string has invalid format." During a GC initialization, the GCHeapAffinitizeRanges config couldn't be parsed due to its invalid format. CLR_E_GC_BAD_HARD_LIMIT "GC heap hard limit configuration is invalid." During a GC initialization, the GC heap hard limit configuration is invalid. CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT "GC large page support requires hard limit settings." During a GC initialization, GC large page support requires hard limit settings. COR_E_UNAUTHORIZEDACCESS 0x80070005 // Access is denied. COR_E_ARGUMENT 0x80070057 // An argument does not meet the contract of the method. COR_E_INVALIDCAST 0x80004002 // Indicates a bad cast condition COR_E_OUTOFMEMORY 0x8007000E // The EE thows this exception when no more memory is avaible to continue execution COR_E_NULLREFERENCE 0x80004003 // Dereferencing a null reference. In general class libraries should not throw this COR_E_ARITHMETIC 0x80070216 // Overflow or underflow in mathematical operations. COR_E_PATHTOOLONG The specified path was too long. COR_E_FILENOTFOUND COR_E_ENDOFSTREAM Thrown when the End of file is reached COR_E_DIRECTORYNOTFOUND The specified path couldn't be found. COR_E_STACKOVERFLOW 0x800703E9 // Is raised by the EE when the execution stack overflows as it is attempting to ex COR_E_AMBIGUOUSMATCH While late binding to a method via reflection, could not resolve between COR_E_TARGETPARAMCOUNT DISP_E_BADPARAMCOUNT // There was a mismatch between number of arguments provided and the number expected COR_E_DIVIDEBYZERO DISP_E_DIVBYZERO // Attempted to divide a number by zero. COR_E_BADIMAGEFORMAT "The format of a DLL or executable being loaded is invalid." The format of DLL or executable being loaded is invalid. ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corexcep.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /********************************************************************* ** ** ** CorExcep.h - lists the exception codes used by the CLR. ** ** ** *********************************************************************/ #ifndef __COREXCEP_H__ #define __COREXCEP_H__ // All COM+ exceptions are expressed as a RaiseException with this exception // code. If you change this value, you must also change // Exception.cs's _COMPlusExceptionCode value. #define EXCEPTION_MSVC 0xe06d7363 // 0xe0000000 | 'msc' #define EXCEPTION_COMPLUS 0xe0434352 // 0xe0000000 | 'CCR' #define EXCEPTION_HIJACK 0xe0434f4e // 0xe0000000 | 'COM'+1 #if defined(_DEBUG) #define EXCEPTION_INTERNAL_ASSERT 0xe0584d4e // 0xe0000000 | 'XMN' // An internal Assert will raise this exception when the config // value "RaiseExceptionOnAssert" si specified. This is used in // stress to facilitate failure triaging. #endif // This is the exception code to report SetupThread failure to caller of reverse pinvoke // It is misleading to use our COM+ exception code, since this is not a managed exception. // In the end, we picked e0455858 (EXX). #define EXCEPTION_EXX 0xe0455858 // 0xe0000000 | 'EXX' #endif // __COREXCEP_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corhdr.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** CorHdr.h - contains definitions for the Runtime structures, ** ** ** needed to work with metadata. ** ** ** *****************************************************************************/ // // The top most managed code structure in a EXE or DLL is the IMAGE_COR20_HEADER // see code:#ManagedHeader for more #ifndef __CORHDR_H__ #define __CORHDR_H__ #include #ifdef _MSC_VER #pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union. #endif typedef void* mdScope; // Obsolete; not used in the runtime. typedef uint32_t mdToken; // Generic token // Token definitions typedef mdToken mdModule; // Module token (roughly, a scope) typedef mdToken mdTypeRef; // TypeRef reference (this or other scope) typedef mdToken mdTypeDef; // TypeDef in this scope typedef mdToken mdFieldDef; // Field in this scope typedef mdToken mdMethodDef; // Method in this scope typedef mdToken mdParamDef; // param token typedef mdToken mdInterfaceImpl; // interface implementation token typedef mdToken mdMemberRef; // MemberRef (this or other scope) typedef mdToken mdCustomAttribute; // attribute token typedef mdToken mdPermission; // DeclSecurity typedef mdToken mdSignature; // Signature object typedef mdToken mdEvent; // event token typedef mdToken mdProperty; // property token typedef mdToken mdModuleRef; // Module reference (for the imported modules) // Assembly tokens. typedef mdToken mdAssembly; // Assembly token. typedef mdToken mdAssemblyRef; // AssemblyRef token. typedef mdToken mdFile; // File token. typedef mdToken mdExportedType; // ExportedType token. typedef mdToken mdManifestResource; // ManifestResource token. typedef mdToken mdTypeSpec; // TypeSpec object typedef mdToken mdGenericParam; // formal parameter to generic type or method typedef mdToken mdMethodSpec; // instantiation of a generic method typedef mdToken mdGenericParamConstraint; // constraint on a formal generic parameter // Application string. typedef mdToken mdString; // User literal string token. typedef mdToken mdCPToken; // constantpool token #ifndef MACROS_NOT_SUPPORTED typedef uint32_t RID; #else typedef unsigned RID; #endif // MACROS_NOT_SUPPORTED typedef enum ReplacesGeneralNumericDefines { // Directory entry macro for CLR data. #ifndef IMAGE_DIRECTORY_ENTRY_COMHEADER IMAGE_DIRECTORY_ENTRY_COMHEADER =14, #endif // IMAGE_DIRECTORY_ENTRY_COMHEADER } ReplacesGeneralNumericDefines; // The COMIMAGE_FLAGS_32BITREQUIRED and COMIMAGE_FLAGS_32BITPREFERRED flags defined below interact as a pair // in order to get the performance profile we desire for platform neutral assemblies while retaining backwards // compatibility with pre-4.5 runtimes/OSs, which don't know about COMIMAGE_FLAGS_32BITPREFERRED. // // COMIMAGE_FLAGS_32BITREQUIRED originally meant "this assembly is x86-only" (required to distinguish platform // neutral assemblies which also mark their PE MachineType as IMAGE_FILE_MACHINE_I386). // // COMIMAGE_FLAGS_32BITPREFERRED has been added so we can create a sub-class of platform neutral assembly that // prefers to be loaded into 32-bit environment for perf reasons, but is still compatible with 64-bit // environments. // // In order to retain maximum backwards compatibility you cannot simply read or write one of these flags. // You must treat them as a pair, a two-bit field with the following meanings: // // 32BITREQUIRED 32BITPREFERRED // 0 0 : no special meaning, MachineType and ILONLY flag determine image requirements // 0 1 : illegal, reserved for future use // 1 0 : image is x86-specific // 1 1 : image is platform neutral and prefers to be loaded 32-bit when possible // // To simplify manipulation of these flags the following macros are provided below. #define COR_IS_32BIT_REQUIRED(_flags) \ (((_flags) & (COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED)) == (COMIMAGE_FLAGS_32BITREQUIRED)) #define COR_IS_32BIT_PREFERRED(_flags) \ (((_flags) & (COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED)) == (COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED)) #define COR_SET_32BIT_REQUIRED(_flagsfield) \ do { _flagsfield = (_flagsfield & ~COMIMAGE_FLAGS_32BITPREFERRED) | COMIMAGE_FLAGS_32BITREQUIRED; } while (false) #define COR_SET_32BIT_PREFERRED(_flagsfield) \ do { _flagsfield |= COMIMAGE_FLAGS_32BITPREFERRED|COMIMAGE_FLAGS_32BITREQUIRED; } while (false) #define COR_CLEAR_32BIT_REQUIRED(_flagsfield) \ do { _flagsfield &= ~(COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED); } while (false) #define COR_CLEAR_32BIT_PREFERRED(_flagsfield) \ do { _flagsfield &= ~(COMIMAGE_FLAGS_32BITREQUIRED|COMIMAGE_FLAGS_32BITPREFERRED); } while (false) #ifndef __IMAGE_COR20_HEADER_DEFINED__ #define __IMAGE_COR20_HEADER_DEFINED__ typedef enum ReplacesCorHdrNumericDefines { // COM+ Header entry point flags. COMIMAGE_FLAGS_ILONLY =0x00000001, COMIMAGE_FLAGS_32BITREQUIRED =0x00000002, // *** Do not manipulate this bit directly (see notes above) COMIMAGE_FLAGS_IL_LIBRARY =0x00000004, COMIMAGE_FLAGS_STRONGNAMESIGNED =0x00000008, COMIMAGE_FLAGS_NATIVE_ENTRYPOINT =0x00000010, COMIMAGE_FLAGS_TRACKDEBUGDATA =0x00010000, COMIMAGE_FLAGS_32BITPREFERRED =0x00020000, // *** Do not manipulate this bit directly (see notes above) // Version flags for image. COR_VERSION_MAJOR_V2 =2, COR_VERSION_MAJOR =COR_VERSION_MAJOR_V2, COR_VERSION_MINOR =5, COR_DELETED_NAME_LENGTH =8, COR_VTABLEGAP_NAME_LENGTH =8, // Maximum size of a NativeType descriptor. NATIVE_TYPE_MAX_CB =1, COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE=0xFF, // V-table constants COR_VTABLE_32BIT =0x01, // V-table slots are 32-bits in size. COR_VTABLE_64BIT =0x02, // V-table slots are 64-bits in size. COR_VTABLE_FROM_UNMANAGED =0x04, // If set, transition from unmanaged. COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN=0x08, // NEW COR_VTABLE_CALL_MOST_DERIVED =0x10, // Call most derived method described by // EATJ constants IMAGE_COR_EATJ_THUNK_SIZE = 32, // Size of a jump thunk reserved range. // Max name lengths //@todo: Change to unlimited name lengths. MAX_CLASS_NAME =1024, MAX_PACKAGE_NAME =1024, } ReplacesCorHdrNumericDefines; // // Directory format. // #ifndef IMAGE_DATA_DIRECTORY_DEFINED #define IMAGE_DATA_DIRECTORY_DEFINED typedef struct _IMAGE_DATA_DIRECTORY { uint32_t VirtualAddress; uint32_t Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; #endif // IMAGE_DATA_DIRECTORY_DEFINED // #ManagedHeader // // A managed code EXE or DLL uses the same basic format that unmanaged executables use call the Portable // Executable (PE) format. See http://en.wikipedia.org/wiki/Portable_Executable or // http://msdn.microsoft.com/msdnmag/issues/02/02/PE/default.aspx for more on this format and RVAs. // // PE files define fixed table of well known entry pointers call Directory entries. Each entry holds the // relative virtual address (RVA) and length of a blob of data within the PE file. You can see these using // the command // // link /dump /headers // // // Managed code has defined one of these entries (the 14th see code:IMAGE_DIRECTORY_ENTRY_COMHEADER) and the RVA points // that the IMAGE_COR20_HEADER. This header shows up in the previous dump as the following line // // // Managed code is identified by is following line // // 2008 [ 48] RVA [size] of COM Descriptor Directory // // The IMAGE_COR20_HEADER is mostly just RVA:Length pairs (pointers) to other interesting data structures. // The most important of these is the MetaData tables. The easiest way of looking at meta-data is using // the IlDasm.exe tool. // // MetaData holds most of the information in the IL image. The exceptions are resource blobs and the IL // instructions streams for individual methods. Instead the Meta-data for a method holds an RVA to a // code:IMAGE_COR_ILMETHOD which holds all the IL stream (and exception handling information). // // Precompiled (NGEN) images use the same IMAGE_COR20_HEADER but also use the ManagedNativeHeader field to // point at structures that only exist in precompiled images. // typedef struct IMAGE_COR20_HEADER { // Header versioning uint32_t cb; uint16_t MajorRuntimeVersion; uint16_t MinorRuntimeVersion; // Symbol table and startup information IMAGE_DATA_DIRECTORY MetaData; uint32_t Flags; // The main program if it is an EXE (not used if a DLL?) // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set, EntryPointToken represents a managed entrypoint. // If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set, EntryPointRVA represents an RVA to a native entrypoint // (deprecated for DLLs, use modules constructors instead). union { uint32_t EntryPointToken; uint32_t EntryPointRVA; }; // This is the blob of managed resources. Fetched using code:AssemblyNative.GetResource and // code:PEAssembly.GetResource and accessible from managed code from // System.Assembly.GetManifestResourceStream. The meta data has a table that maps names to offsets into // this blob, so logically the blob is a set of resources. IMAGE_DATA_DIRECTORY Resources; // IL assemblies can be signed with a public-private key to validate who created it. The signature goes // here if this feature is used. IMAGE_DATA_DIRECTORY StrongNameSignature; IMAGE_DATA_DIRECTORY CodeManagerTable; // Deprecated, not used // Used for manged code that has unmanaged code inside it (or exports methods as unmanaged entry points) IMAGE_DATA_DIRECTORY VTableFixups; IMAGE_DATA_DIRECTORY ExportAddressTableJumps; // null for ordinary IL images. // In Ready2Run images it points to a READYTORUN_HEADER. IMAGE_DATA_DIRECTORY ManagedNativeHeader; } IMAGE_COR20_HEADER, *PIMAGE_COR20_HEADER; #else // !__IMAGE_COR20_HEADER_DEFINED__ // @TODO: This is required because we pull in the COM+ 2.0 PE header // definition from WinNT.h, and these constants have not yet propagated to there. // #define COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN 0x08 #define COMIMAGE_FLAGS_32BITPREFERRED 0x00020000 #endif // __IMAGE_COR20_HEADER_DEFINED__ // The most recent version. #define COR_CTOR_METHOD_NAME ".ctor" #define COR_CTOR_METHOD_NAME_W W(".ctor") #define COR_CCTOR_METHOD_NAME ".cctor" #define COR_CCTOR_METHOD_NAME_W W(".cctor") #define COR_ENUM_FIELD_NAME "value__" #define COR_ENUM_FIELD_NAME_W W("value__") // The predefined name for deleting a typeDef,MethodDef, FieldDef, Property and Event #define COR_DELETED_NAME_A "_Deleted" #define COR_DELETED_NAME_W W("_Deleted") #define COR_VTABLEGAP_NAME_A "_VtblGap" #define COR_VTABLEGAP_NAME_W W("_VtblGap") // We intentionally use strncmp so that we will ignore any suffix #define IsDeletedName(strName) (strncmp(strName, COR_DELETED_NAME_A, COR_DELETED_NAME_LENGTH) == 0) #define IsVtblGapName(strName) (strncmp(strName, COR_VTABLEGAP_NAME_A, COR_VTABLEGAP_NAME_LENGTH) == 0) // TypeDef/ExportedType attr bits, used by DefineTypeDef. typedef enum CorTypeAttr { // Use this mask to retrieve the type visibility information. tdVisibilityMask = 0x00000007, tdNotPublic = 0x00000000, // Class is not public scope. tdPublic = 0x00000001, // Class is public scope. tdNestedPublic = 0x00000002, // Class is nested with public visibility. tdNestedPrivate = 0x00000003, // Class is nested with private visibility. tdNestedFamily = 0x00000004, // Class is nested with family visibility. tdNestedAssembly = 0x00000005, // Class is nested with assembly visibility. tdNestedFamANDAssem = 0x00000006, // Class is nested with family and assembly visibility. tdNestedFamORAssem = 0x00000007, // Class is nested with family or assembly visibility. // Use this mask to retrieve class layout information tdLayoutMask = 0x00000018, tdAutoLayout = 0x00000000, // Class fields are auto-laid out tdSequentialLayout = 0x00000008, // Class fields are laid out sequentially tdExplicitLayout = 0x00000010, // Layout is supplied explicitly // end layout mask // Use this mask to retrieve class semantics information. tdClassSemanticsMask = 0x00000020, tdClass = 0x00000000, // Type is a class. tdInterface = 0x00000020, // Type is an interface. // end semantics mask // Special semantics in addition to class semantics. tdAbstract = 0x00000080, // Class is abstract tdSealed = 0x00000100, // Class is concrete and may not be extended tdSpecialName = 0x00000400, // Class name is special. Name describes how. // Implementation attributes. tdImport = 0x00001000, // Class / interface is imported tdSerializable = 0x00002000, // The class is Serializable. tdWindowsRuntime = 0x00004000, // The type is a Windows Runtime type // Use tdStringFormatMask to retrieve string information for native interop tdStringFormatMask = 0x00030000, tdAnsiClass = 0x00000000, // LPTSTR is interpreted as ANSI in this class tdUnicodeClass = 0x00010000, // LPTSTR is interpreted as UNICODE tdAutoClass = 0x00020000, // LPTSTR is interpreted automatically tdCustomFormatClass = 0x00030000, // A non-standard encoding specified by CustomFormatMask tdCustomFormatMask = 0x00C00000, // Use this mask to retrieve non-standard encoding information for native interop. The meaning of the values of these 2 bits is unspecified. // end string format mask tdBeforeFieldInit = 0x00100000, // Initialize the class any time before first static field access. tdForwarder = 0x00200000, // This ExportedType is a type forwarder. // Flags reserved for runtime use. tdReservedMask = 0x00040800, tdRTSpecialName = 0x00000800, // Runtime should check name encoding. tdHasSecurity = 0x00040000, // Class has security associate with it. } CorTypeAttr; // Macros for accessing the members of the CorTypeAttr. #define IsTdNotPublic(x) (((x) & tdVisibilityMask) == tdNotPublic) #define IsTdPublic(x) (((x) & tdVisibilityMask) == tdPublic) #define IsTdNestedPublic(x) (((x) & tdVisibilityMask) == tdNestedPublic) #define IsTdNestedPrivate(x) (((x) & tdVisibilityMask) == tdNestedPrivate) #define IsTdNestedFamily(x) (((x) & tdVisibilityMask) == tdNestedFamily) #define IsTdNestedAssembly(x) (((x) & tdVisibilityMask) == tdNestedAssembly) #define IsTdNestedFamANDAssem(x) (((x) & tdVisibilityMask) == tdNestedFamANDAssem) #define IsTdNestedFamORAssem(x) (((x) & tdVisibilityMask) == tdNestedFamORAssem) #define IsTdNested(x) (((x) & tdVisibilityMask) >= tdNestedPublic) #define IsTdAutoLayout(x) (((x) & tdLayoutMask) == tdAutoLayout) #define IsTdSequentialLayout(x) (((x) & tdLayoutMask) == tdSequentialLayout) #define IsTdExplicitLayout(x) (((x) & tdLayoutMask) == tdExplicitLayout) #define IsTdClass(x) (((x) & tdClassSemanticsMask) == tdClass) #define IsTdInterface(x) (((x) & tdClassSemanticsMask) == tdInterface) #define IsTdAbstract(x) ((x) & tdAbstract) #define IsTdSealed(x) ((x) & tdSealed) #define IsTdSpecialName(x) ((x) & tdSpecialName) #define IsTdImport(x) ((x) & tdImport) #define IsTdSerializable(x) ((x) & tdSerializable) #define IsTdWindowsRuntime(x) ((x) & tdWindowsRuntime) #define IsTdAnsiClass(x) (((x) & tdStringFormatMask) == tdAnsiClass) #define IsTdUnicodeClass(x) (((x) & tdStringFormatMask) == tdUnicodeClass) #define IsTdAutoClass(x) (((x) & tdStringFormatMask) == tdAutoClass) #define IsTdCustomFormatClass(x) (((x) & tdStringFormatMask) == tdCustomFormatClass) #define IsTdBeforeFieldInit(x) ((x) & tdBeforeFieldInit) #define IsTdForwarder(x) ((x) & tdForwarder) #define IsTdRTSpecialName(x) ((x) & tdRTSpecialName) #define IsTdHasSecurity(x) ((x) & tdHasSecurity) // MethodDef attr bits, Used by DefineMethod. typedef enum CorMethodAttr { // member access mask - Use this mask to retrieve accessibility information. mdMemberAccessMask = 0x0007, mdPrivateScope = 0x0000, // Member not referencable. mdPrivate = 0x0001, // Accessible only by the parent type. mdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. mdAssem = 0x0003, // Accessibly by anyone in the Assembly. mdFamily = 0x0004, // Accessible only by type and sub-types. mdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. mdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. // end member access mask // method contract attributes. mdStatic = 0x0010, // Defined on type, else per instance. mdFinal = 0x0020, // Method may not be overridden. mdVirtual = 0x0040, // Method virtual. mdHideBySig = 0x0080, // Method hides by name+sig, else just by name. // vtable layout mask - Use this mask to retrieve vtable attributes. mdVtableLayoutMask = 0x0100, mdReuseSlot = 0x0000, // The default. mdNewSlot = 0x0100, // Method always gets a new slot in the vtable. // end vtable layout mask // method implementation attributes. mdCheckAccessOnOverride = 0x0200, // Overridability is the same as the visibility. mdAbstract = 0x0400, // Method does not provide an implementation. mdSpecialName = 0x0800, // Method is special. Name describes how. // interop attributes mdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke. mdUnmanagedExport = 0x0008, // Managed method exported via thunk to unmanaged code. // Reserved flags for runtime use only. mdReservedMask = 0xd000, mdRTSpecialName = 0x1000, // Runtime should check name encoding. mdHasSecurity = 0x4000, // Method has security associate with it. mdRequireSecObject = 0x8000, // Method calls another method containing security code. } CorMethodAttr; // Macros for accessing the members of CorMethodAttr. #define IsMdPrivateScope(x) (((x) & mdMemberAccessMask) == mdPrivateScope) #define IsMdPrivate(x) (((x) & mdMemberAccessMask) == mdPrivate) #define IsMdFamANDAssem(x) (((x) & mdMemberAccessMask) == mdFamANDAssem) #define IsMdAssem(x) (((x) & mdMemberAccessMask) == mdAssem) #define IsMdFamily(x) (((x) & mdMemberAccessMask) == mdFamily) #define IsMdFamORAssem(x) (((x) & mdMemberAccessMask) == mdFamORAssem) #define IsMdPublic(x) (((x) & mdMemberAccessMask) == mdPublic) #define IsMdStatic(x) ((x) & mdStatic) #define IsMdFinal(x) ((x) & mdFinal) #define IsMdVirtual(x) ((x) & mdVirtual) #define IsMdHideBySig(x) ((x) & mdHideBySig) #define IsMdReuseSlot(x) (((x) & mdVtableLayoutMask) == mdReuseSlot) #define IsMdNewSlot(x) (((x) & mdVtableLayoutMask) == mdNewSlot) #define IsMdCheckAccessOnOverride(x) ((x) & mdCheckAccessOnOverride) #define IsMdAbstract(x) ((x) & mdAbstract) #define IsMdSpecialName(x) ((x) & mdSpecialName) #define IsMdPinvokeImpl(x) ((x) & mdPinvokeImpl) #define IsMdUnmanagedExport(x) ((x) & mdUnmanagedExport) #define IsMdRTSpecialName(x) ((x) & mdRTSpecialName) #define IsMdInstanceInitializer(x, str) (((x) & mdRTSpecialName) && !strcmp((str), COR_CTOR_METHOD_NAME)) #define IsMdInstanceInitializerW(x, str) (((x) & mdRTSpecialName) && !wcscmp((str), COR_CTOR_METHOD_NAME_W)) #define IsMdClassConstructor(x, str) (((x) & mdRTSpecialName) && !strcmp((str), COR_CCTOR_METHOD_NAME)) #define IsMdClassConstructorW(x, str) (((x) & mdRTSpecialName) && !wcscmp((str), COR_CCTOR_METHOD_NAME_W)) #define IsMdHasSecurity(x) ((x) & mdHasSecurity) #define IsMdRequireSecObject(x) ((x) & mdRequireSecObject) // FieldDef attr bits, used by DefineField. typedef enum CorFieldAttr { // member access mask - Use this mask to retrieve accessibility information. fdFieldAccessMask = 0x0007, fdPrivateScope = 0x0000, // Member not referencable. fdPrivate = 0x0001, // Accessible only by the parent type. fdFamANDAssem = 0x0002, // Accessible by sub-types only in this Assembly. fdAssembly = 0x0003, // Accessibly by anyone in the Assembly. fdFamily = 0x0004, // Accessible only by type and sub-types. fdFamORAssem = 0x0005, // Accessibly by sub-types anywhere, plus anyone in assembly. fdPublic = 0x0006, // Accessibly by anyone who has visibility to this scope. // end member access mask // field contract attributes. fdStatic = 0x0010, // Defined on type, else per instance. fdInitOnly = 0x0020, // Field may only be initialized, not written to after init. fdLiteral = 0x0040, // Value is compile time constant. fdNotSerialized = 0x0080, // Field does not have to be serialized when type is remoted. fdSpecialName = 0x0200, // field is special. Name describes how. // interop attributes fdPinvokeImpl = 0x2000, // Implementation is forwarded through pinvoke. // Reserved flags for runtime use only. fdReservedMask = 0x9500, fdRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. fdHasFieldMarshal = 0x1000, // Field has marshalling information. fdHasDefault = 0x8000, // Field has default. fdHasFieldRVA = 0x0100, // Field has RVA. } CorFieldAttr; // Macros for accessing the members of CorFieldAttr. #define IsFdPrivateScope(x) (((x) & fdFieldAccessMask) == fdPrivateScope) #define IsFdPrivate(x) (((x) & fdFieldAccessMask) == fdPrivate) #define IsFdFamANDAssem(x) (((x) & fdFieldAccessMask) == fdFamANDAssem) #define IsFdAssembly(x) (((x) & fdFieldAccessMask) == fdAssembly) #define IsFdFamily(x) (((x) & fdFieldAccessMask) == fdFamily) #define IsFdFamORAssem(x) (((x) & fdFieldAccessMask) == fdFamORAssem) #define IsFdPublic(x) (((x) & fdFieldAccessMask) == fdPublic) #define IsFdStatic(x) ((x) & fdStatic) #define IsFdInitOnly(x) ((x) & fdInitOnly) #define IsFdLiteral(x) ((x) & fdLiteral) #define IsFdNotSerialized(x) ((x) & fdNotSerialized) #define IsFdPinvokeImpl(x) ((x) & fdPinvokeImpl) #define IsFdSpecialName(x) ((x) & fdSpecialName) #define IsFdHasFieldRVA(x) ((x) & fdHasFieldRVA) #define IsFdRTSpecialName(x) ((x) & fdRTSpecialName) #define IsFdHasFieldMarshal(x) ((x) & fdHasFieldMarshal) #define IsFdHasDefault(x) ((x) & fdHasDefault) // Param attr bits, used by DefineParam. typedef enum CorParamAttr { pdIn = 0x0001, // Param is [In] pdOut = 0x0002, // Param is [out] pdOptional = 0x0010, // Param is optional // Reserved flags for Runtime use only. pdReservedMask = 0xf000, pdHasDefault = 0x1000, // Param has default value. pdHasFieldMarshal = 0x2000, // Param has FieldMarshal. pdUnused = 0xcfe0, } CorParamAttr; // Macros for accessing the members of CorParamAttr. #define IsPdIn(x) ((x) & pdIn) #define IsPdOut(x) ((x) & pdOut) #define IsPdOptional(x) ((x) & pdOptional) #define IsPdHasDefault(x) ((x) & pdHasDefault) #define IsPdHasFieldMarshal(x) ((x) & pdHasFieldMarshal) // Property attr bits, used by DefineProperty. typedef enum CorPropertyAttr { prSpecialName = 0x0200, // property is special. Name describes how. // Reserved flags for Runtime use only. prReservedMask = 0xf400, prRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. prHasDefault = 0x1000, // Property has default prUnused = 0xe9ff, } CorPropertyAttr; // Macros for accessing the members of CorPropertyAttr. #define IsPrSpecialName(x) ((x) & prSpecialName) #define IsPrRTSpecialName(x) ((x) & prRTSpecialName) #define IsPrHasDefault(x) ((x) & prHasDefault) // Event attr bits, used by DefineEvent. typedef enum CorEventAttr { evSpecialName = 0x0200, // event is special. Name describes how. // Reserved flags for Runtime use only. evReservedMask = 0x0400, evRTSpecialName = 0x0400, // Runtime(metadata internal APIs) should check name encoding. } CorEventAttr; // Macros for accessing the members of CorEventAttr. #define IsEvSpecialName(x) ((x) & evSpecialName) #define IsEvRTSpecialName(x) ((x) & evRTSpecialName) // MethodSemantic attr bits, used by DefineProperty, DefineEvent. typedef enum CorMethodSemanticsAttr { msSetter = 0x0001, // Setter for property msGetter = 0x0002, // Getter for property msOther = 0x0004, // other method for property or event msAddOn = 0x0008, // AddOn method for event msRemoveOn = 0x0010, // RemoveOn method for event msFire = 0x0020, // Fire method for event } CorMethodSemanticsAttr; // Macros for accessing the members of CorMethodSemanticsAttr. #define IsMsSetter(x) ((x) & msSetter) #define IsMsGetter(x) ((x) & msGetter) #define IsMsOther(x) ((x) & msOther) #define IsMsAddOn(x) ((x) & msAddOn) #define IsMsRemoveOn(x) ((x) & msRemoveOn) #define IsMsFire(x) ((x) & msFire) // DeclSecurity attr bits, used by DefinePermissionSet. typedef enum CorDeclSecurity { dclActionMask = 0x001f, // Mask allows growth of enum. dclActionNil = 0x0000, // dclRequest = 0x0001, // dclDemand = 0x0002, // dclAssert = 0x0003, // dclDeny = 0x0004, // dclPermitOnly = 0x0005, // dclLinktimeCheck = 0x0006, // dclInheritanceCheck = 0x0007, // dclRequestMinimum = 0x0008, // dclRequestOptional = 0x0009, // dclRequestRefuse = 0x000a, // dclPrejitGrant = 0x000b, // Persisted grant set at prejit time dclPrejitDenied = 0x000c, // Persisted denied set at prejit time dclNonCasDemand = 0x000d, // dclNonCasLinkDemand = 0x000e, // dclNonCasInheritance = 0x000f, // dclMaximumValue = 0x000f, // Maximum legal value } CorDeclSecurity; // Macros for accessing the members of CorDeclSecurity. #define IsDclActionNil(x) (((x) & dclActionMask) == dclActionNil) // Is this a demand that can trigger a stackwalk? #define IsDclActionAnyStackModifier(x) ((((x) & dclActionMask) == dclAssert) || \ (((x) & dclActionMask) == dclDeny) || \ (((x) & dclActionMask) == dclPermitOnly)) // Is this an assembly level attribute (i.e. not applicable on Type/Member)? #define IsAssemblyDclAction(x) (((x) >= dclRequestMinimum) && \ ((x) <= dclRequestRefuse)) // Is this an NGen only attribute? #define IsNGenOnlyDclAction(x) (((x) == dclPrejitGrant) || \ ((x) == dclPrejitDenied)) // MethodImpl attr bits, used by DefineMethodImpl. typedef enum CorMethodImpl { // code impl mask miCodeTypeMask = 0x0003, // Flags about code type. miIL = 0x0000, // Method impl is IL. miNative = 0x0001, // Method impl is native. miOPTIL = 0x0002, // Method impl is OPTIL miRuntime = 0x0003, // Method impl is provided by the runtime. // end code impl mask // managed mask miManagedMask = 0x0004, // Flags specifying whether the code is managed or unmanaged. miUnmanaged = 0x0004, // Method impl is unmanaged, otherwise managed. miManaged = 0x0000, // Method impl is managed. // end managed mask // implementation info and interop miForwardRef = 0x0010, // Indicates method is defined; used primarily in merge scenarios. miPreserveSig = 0x0080, // Indicates method sig is not to be mangled to do HRESULT conversion. miInternalCall = 0x1000, // Reserved for internal use. miSynchronized = 0x0020, // Method is single threaded through the body. miNoInlining = 0x0008, // Method may not be inlined. miAggressiveInlining = 0x0100, // Method should be inlined if possible. miNoOptimization = 0x0040, // Method may not be optimized. miAggressiveOptimization = 0x0200, // Method may contain hot code and should be aggressively optimized. // These are the flags that are allowed in MethodImplAttribute's Value // property. This should include everything above except the code impl // flags (which are used for MethodImplAttribute's MethodCodeType field). miUserMask = miManagedMask | miForwardRef | miPreserveSig | miInternalCall | miSynchronized | miNoInlining | miAggressiveInlining | miNoOptimization | miAggressiveOptimization, miMaxMethodImplVal = 0xffff, // Range check value } CorMethodImpl; // Macros for accessing the members of CorMethodImpl. #define IsMiIL(x) (((x) & miCodeTypeMask) == miIL) #define IsMiNative(x) (((x) & miCodeTypeMask) == miNative) #define IsMiOPTIL(x) (((x) & miCodeTypeMask) == miOPTIL) #define IsMiRuntime(x) (((x) & miCodeTypeMask) == miRuntime) #define IsMiUnmanaged(x) (((x) & miManagedMask) == miUnmanaged) #define IsMiManaged(x) (((x) & miManagedMask) == miManaged) #define IsMiForwardRef(x) ((x) & miForwardRef) #define IsMiPreserveSig(x) ((x) & miPreserveSig) #define IsMiInternalCall(x) ((x) & miInternalCall) #define IsMiSynchronized(x) ((x) & miSynchronized) #define IsMiNoInlining(x) ((x) & miNoInlining) #define IsMiAggressiveInlining(x) ((x) & miAggressiveInlining) #define IsMiNoOptimization(x) ((x) & miNoOptimization) #define IsMiAggressiveOptimization(x) (((x) & (miAggressiveOptimization | miNoOptimization)) == miAggressiveOptimization) // PinvokeMap attr bits, used by DefinePinvokeMap. typedef enum CorPinvokeMap { pmNoMangle = 0x0001, // Pinvoke is to use the member name as specified. // Use this mask to retrieve the CharSet information. pmCharSetMask = 0x0006, pmCharSetNotSpec = 0x0000, pmCharSetAnsi = 0x0002, pmCharSetUnicode = 0x0004, pmCharSetAuto = 0x0006, pmBestFitUseAssem = 0x0000, pmBestFitEnabled = 0x0010, pmBestFitDisabled = 0x0020, pmBestFitMask = 0x0030, pmThrowOnUnmappableCharUseAssem = 0x0000, pmThrowOnUnmappableCharEnabled = 0x1000, pmThrowOnUnmappableCharDisabled = 0x2000, pmThrowOnUnmappableCharMask = 0x3000, pmSupportsLastError = 0x0040, // Information about target function. Not relevant for fields. // None of the calling convention flags is relevant for fields. pmCallConvMask = 0x0700, pmCallConvWinapi = 0x0100, // Pinvoke will use native callconv appropriate to target windows platform. pmCallConvCdecl = 0x0200, pmCallConvStdcall = 0x0300, pmCallConvThiscall = 0x0400, // In M9, pinvoke will raise exception. pmCallConvFastcall = 0x0500, pmMaxValue = 0xFFFF, } CorPinvokeMap; // Macros for accessing the members of CorPinvokeMap #define IsPmNoMangle(x) ((x) & pmNoMangle) #define IsPmCharSetNotSpec(x) (((x) & pmCharSetMask) == pmCharSetNotSpec) #define IsPmCharSetAnsi(x) (((x) & pmCharSetMask) == pmCharSetAnsi) #define IsPmCharSetUnicode(x) (((x) & pmCharSetMask) == pmCharSetUnicode) #define IsPmCharSetAuto(x) (((x) & pmCharSetMask) == pmCharSetAuto) #define IsPmSupportsLastError(x) ((x) & pmSupportsLastError) #define IsPmCallConvWinapi(x) (((x) & pmCallConvMask) == pmCallConvWinapi) #define IsPmCallConvCdecl(x) (((x) & pmCallConvMask) == pmCallConvCdecl) #define IsPmCallConvStdcall(x) (((x) & pmCallConvMask) == pmCallConvStdcall) #define IsPmCallConvThiscall(x) (((x) & pmCallConvMask) == pmCallConvThiscall) #define IsPmCallConvFastcall(x) (((x) & pmCallConvMask) == pmCallConvFastcall) #define IsPmBestFitEnabled(x) (((x) & pmBestFitMask) == pmBestFitEnabled) #define IsPmBestFitDisabled(x) (((x) & pmBestFitMask) == pmBestFitDisabled) #define IsPmBestFitUseAssem(x) (((x) & pmBestFitMask) == pmBestFitUseAssem) #define IsPmThrowOnUnmappableCharEnabled(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharEnabled) #define IsPmThrowOnUnmappableCharDisabled(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharDisabled) #define IsPmThrowOnUnmappableCharUseAssem(x) (((x) & pmThrowOnUnmappableCharMask) == pmThrowOnUnmappableCharUseAssem) // Assembly attr bits, used by DefineAssembly. typedef enum CorAssemblyFlags { afPublicKey = 0x0001, // The assembly ref holds the full (unhashed) public key. afPA_None = 0x0000, // Processor Architecture unspecified afPA_MSIL = 0x0010, // Processor Architecture: neutral (PE32) afPA_x86 = 0x0020, // Processor Architecture: x86 (PE32) afPA_IA64 = 0x0030, // Processor Architecture: Itanium (PE32+) afPA_AMD64 = 0x0040, // Processor Architecture: AMD X64 (PE32+) afPA_ARM = 0x0050, // Processor Architecture: ARM (PE32) afPA_ARM64 = 0x0060, // Processor Architecture: ARM64 (PE32+) afPA_NoPlatform = 0x0070, // applies to any platform but cannot run on any (e.g. reference assembly), should not have "specified" set afPA_Specified = 0x0080, // Propagate PA flags to AssemblyRef record afPA_Mask = 0x0070, // Bits describing the processor architecture afPA_FullMask = 0x00F0, // Bits describing the PA incl. Specified afPA_Shift = 0x0004, // NOT A FLAG, shift count in PA flags <--> index conversion afEnableJITcompileTracking = 0x8000, // From "DebuggableAttribute". afDisableJITcompileOptimizer = 0x4000, // From "DebuggableAttribute". afDebuggableAttributeMask = 0xc000, afRetargetable = 0x0100, // The assembly can be retargeted (at runtime) to an // assembly from a different publisher. afContentType_Default = 0x0000, afContentType_WindowsRuntime = 0x0200, afContentType_Mask = 0x0E00, // Bits describing ContentType } CorAssemblyFlags; // Macros for accessing the members of CorAssemblyFlags. #define IsAfRetargetable(x) ((x) & afRetargetable) #define IsAfContentType_Default(x) (((x) & afContentType_Mask) == afContentType_Default) #define IsAfContentType_WindowsRuntime(x) (((x) & afContentType_Mask) == afContentType_WindowsRuntime) // Macros for accessing the Processor Architecture flags of CorAssemblyFlags. #define IsAfPA_MSIL(x) (((x) & afPA_Mask) == afPA_MSIL) #define IsAfPA_x86(x) (((x) & afPA_Mask) == afPA_x86) #define IsAfPA_IA64(x) (((x) & afPA_Mask) == afPA_IA64) #define IsAfPA_AMD64(x) (((x) & afPA_Mask) == afPA_AMD64) #define IsAfPA_ARM(x) (((x) & afPA_Mask) == afPA_ARM) #define IsAfPA_ARM64(x) (((x) & afPA_Mask) == afPA_ARM64) #define IsAfPA_NoPlatform(x) (((x) & afPA_FullMask) == afPA_NoPlatform) #define IsAfPA_Specified(x) ((x) & afPA_Specified) #define PAIndex(x) (((x) & afPA_Mask) >> afPA_Shift) #define PAFlag(x) (((x) << afPA_Shift) & afPA_Mask) #define PrepareForSaving(x) ((x) & (((x) & afPA_Specified) ? ~afPA_Specified : ~afPA_FullMask)) #define IsAfEnableJITcompileTracking(x) ((x) & afEnableJITcompileTracking) #define IsAfDisableJITcompileOptimizer(x) ((x) & afDisableJITcompileOptimizer) // Macros for accessing the public key flags of CorAssemblyFlags. #define IsAfPublicKey(x) ((x) & afPublicKey) #define IsAfPublicKeyToken(x) (((x) & afPublicKey) == 0) // ManifestResource attr bits, used by DefineManifestResource. typedef enum CorManifestResourceFlags { mrVisibilityMask = 0x0007, mrPublic = 0x0001, // The Resource is exported from the Assembly. mrPrivate = 0x0002, // The Resource is private to the Assembly. } CorManifestResourceFlags; // Macros for accessing the members of CorManifestResourceFlags. #define IsMrPublic(x) (((x) & mrVisibilityMask) == mrPublic) #define IsMrPrivate(x) (((x) & mrVisibilityMask) == mrPrivate) // File attr bits, used by DefineFile. typedef enum CorFileFlags { ffContainsMetaData = 0x0000, // This is not a resource file ffContainsNoMetaData = 0x0001, // This is a resource file or other non-metadata-containing file } CorFileFlags; // Macros for accessing the members of CorFileFlags. #define IsFfContainsMetaData(x) (!((x) & ffContainsNoMetaData)) #define IsFfContainsNoMetaData(x) ((x) & ffContainsNoMetaData) // PE file kind bits, returned by IMetaDataImport2::GetPEKind() typedef enum CorPEKind { peNot = 0x00000000, // not a PE file peILonly = 0x00000001, // flag IL_ONLY is set in COR header pe32BitRequired=0x00000002, // flag 32BITREQUIRED is set and 32BITPREFERRED is clear in COR header pe32Plus = 0x00000004, // PE32+ file (64 bit) pe32Unmanaged=0x00000008, // PE32 without COR header pe32BitPreferred=0x00000010 // flags 32BITREQUIRED and 32BITPREFERRED are set in COR header } CorPEKind; // GenericParam bits, used by DefineGenericParam. typedef enum CorGenericParamAttr { // Variance of type parameters, only applicable to generic parameters // for generic interfaces and delegates gpVarianceMask = 0x0003, gpNonVariant = 0x0000, gpCovariant = 0x0001, gpContravariant = 0x0002, // Special constraints, applicable to any type parameters gpSpecialConstraintMask = 0x003C, gpNoSpecialConstraint = 0x0000, gpReferenceTypeConstraint = 0x0004, // type argument must be a reference type gpNotNullableValueTypeConstraint = 0x0008, // type argument must be a value type but not Nullable gpDefaultConstructorConstraint = 0x0010, // type argument must have a public default constructor gpAcceptByRefLike = 0x0020, // type argument can be ByRefLike } CorGenericParamAttr; // structures and enums moved from COR.H typedef uint8_t COR_SIGNATURE; typedef COR_SIGNATURE* PCOR_SIGNATURE; // pointer to a cor sig. Not void* so that // the bytes can be incremented easily typedef const COR_SIGNATURE* PCCOR_SIGNATURE; typedef const char * MDUTF8CSTR; typedef char * MDUTF8STR; //***************************************************************************** // // Element type for Cor signature // //***************************************************************************** typedef enum CorElementType { ELEMENT_TYPE_END = 0x00, ELEMENT_TYPE_VOID = 0x01, ELEMENT_TYPE_BOOLEAN = 0x02, ELEMENT_TYPE_CHAR = 0x03, ELEMENT_TYPE_I1 = 0x04, ELEMENT_TYPE_U1 = 0x05, ELEMENT_TYPE_I2 = 0x06, ELEMENT_TYPE_U2 = 0x07, ELEMENT_TYPE_I4 = 0x08, ELEMENT_TYPE_U4 = 0x09, ELEMENT_TYPE_I8 = 0x0a, ELEMENT_TYPE_U8 = 0x0b, ELEMENT_TYPE_R4 = 0x0c, ELEMENT_TYPE_R8 = 0x0d, ELEMENT_TYPE_STRING = 0x0e, // every type above PTR will be simple type ELEMENT_TYPE_PTR = 0x0f, // PTR ELEMENT_TYPE_BYREF = 0x10, // BYREF // Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated. ELEMENT_TYPE_VALUETYPE = 0x11, // VALUETYPE ELEMENT_TYPE_CLASS = 0x12, // CLASS ELEMENT_TYPE_VAR = 0x13, // a class type variable VAR ELEMENT_TYPE_ARRAY = 0x14, // MDARRAY ... ... ELEMENT_TYPE_GENERICINST = 0x15, // GENERICINST ... ELEMENT_TYPE_TYPEDBYREF = 0x16, // TYPEDREF (it takes no args) a typed reference to some other type ELEMENT_TYPE_I = 0x18, // native integer size ELEMENT_TYPE_U = 0x19, // native unsigned integer size ELEMENT_TYPE_FNPTR = 0x1b, // FNPTR ELEMENT_TYPE_OBJECT = 0x1c, // Shortcut for System.Object ELEMENT_TYPE_SZARRAY = 0x1d, // Shortcut for single dimension zero lower bound array // SZARRAY ELEMENT_TYPE_MVAR = 0x1e, // a method type variable MVAR // This is only for binding ELEMENT_TYPE_CMOD_REQD = 0x1f, // required C modifier : E_T_CMOD_REQD ELEMENT_TYPE_CMOD_OPT = 0x20, // optional C modifier : E_T_CMOD_OPT // This is for signatures generated internally (which will not be persisted in any way). ELEMENT_TYPE_INTERNAL = 0x21, // INTERNAL // Note that this is the max of base type excluding modifiers ELEMENT_TYPE_MAX = 0x22, // first invalid element type ELEMENT_TYPE_MODIFIER = 0x40, ELEMENT_TYPE_SENTINEL = 0x01 | ELEMENT_TYPE_MODIFIER, // sentinel for varargs ELEMENT_TYPE_PINNED = 0x05 | ELEMENT_TYPE_MODIFIER, } CorElementType; //***************************************************************************** // // Serialization types for Custom attribute support // //***************************************************************************** typedef enum CorSerializationType { SERIALIZATION_TYPE_UNDEFINED = 0, SERIALIZATION_TYPE_BOOLEAN = ELEMENT_TYPE_BOOLEAN, SERIALIZATION_TYPE_CHAR = ELEMENT_TYPE_CHAR, SERIALIZATION_TYPE_I1 = ELEMENT_TYPE_I1, SERIALIZATION_TYPE_U1 = ELEMENT_TYPE_U1, SERIALIZATION_TYPE_I2 = ELEMENT_TYPE_I2, SERIALIZATION_TYPE_U2 = ELEMENT_TYPE_U2, SERIALIZATION_TYPE_I4 = ELEMENT_TYPE_I4, SERIALIZATION_TYPE_U4 = ELEMENT_TYPE_U4, SERIALIZATION_TYPE_I8 = ELEMENT_TYPE_I8, SERIALIZATION_TYPE_U8 = ELEMENT_TYPE_U8, SERIALIZATION_TYPE_R4 = ELEMENT_TYPE_R4, SERIALIZATION_TYPE_R8 = ELEMENT_TYPE_R8, SERIALIZATION_TYPE_STRING = ELEMENT_TYPE_STRING, SERIALIZATION_TYPE_SZARRAY = ELEMENT_TYPE_SZARRAY, // Shortcut for single dimension zero lower bound array SERIALIZATION_TYPE_TYPE = 0x50, SERIALIZATION_TYPE_TAGGED_OBJECT= 0x51, SERIALIZATION_TYPE_FIELD = 0x53, SERIALIZATION_TYPE_PROPERTY = 0x54, SERIALIZATION_TYPE_ENUM = 0x55 } CorSerializationType; // // Calling convention flags. // typedef enum CorUnmanagedCallingConvention { IMAGE_CEE_UNMANAGED_CALLCONV_C = 0x1, IMAGE_CEE_UNMANAGED_CALLCONV_STDCALL = 0x2, IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL = 0x3, IMAGE_CEE_UNMANAGED_CALLCONV_FASTCALL = 0x4, } CorUnmanagedCallingConvention; typedef enum CorCallingConvention { IMAGE_CEE_CS_CALLCONV_DEFAULT = 0x0, IMAGE_CEE_CS_CALLCONV_C = IMAGE_CEE_UNMANAGED_CALLCONV_C, IMAGE_CEE_CS_CALLCONV_STDCALL = IMAGE_CEE_UNMANAGED_CALLCONV_STDCALL, IMAGE_CEE_CS_CALLCONV_THISCALL = IMAGE_CEE_UNMANAGED_CALLCONV_THISCALL, IMAGE_CEE_CS_CALLCONV_FASTCALL = IMAGE_CEE_UNMANAGED_CALLCONV_FASTCALL, IMAGE_CEE_CS_CALLCONV_VARARG = 0x5, IMAGE_CEE_CS_CALLCONV_FIELD = 0x6, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG = 0x7, IMAGE_CEE_CS_CALLCONV_PROPERTY = 0x8, IMAGE_CEE_CS_CALLCONV_UNMANAGED = 0x9, // Unmanaged calling convention encoded as modopts IMAGE_CEE_CS_CALLCONV_GENERICINST = 0xa, // generic method instantiation IMAGE_CEE_CS_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for 64bit vararg PInvoke calls IMAGE_CEE_CS_CALLCONV_MAX = 0xc, // first invalid calling convention // The high bits of the calling convention convey additional info IMAGE_CEE_CS_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits IMAGE_CEE_CS_CALLCONV_HASTHIS = 0x20, // Top bit indicates a 'this' parameter IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = 0x40, // This parameter is explicitly in the signature IMAGE_CEE_CS_CALLCONV_GENERIC = 0x10, // Generic method sig with explicit number of type arguments (precedes ordinary parameter count) // 0x80 is reserved for internal use } CorCallingConvention; #define IMAGE_CEE_CS_CALLCONV_INSTANTIATION IMAGE_CEE_CS_CALLCONV_GENERICINST typedef enum CorArgType { IMAGE_CEE_CS_END = 0x0, IMAGE_CEE_CS_VOID = 0x1, IMAGE_CEE_CS_I4 = 0x2, IMAGE_CEE_CS_I8 = 0x3, IMAGE_CEE_CS_R4 = 0x4, IMAGE_CEE_CS_R8 = 0x5, IMAGE_CEE_CS_PTR = 0x6, IMAGE_CEE_CS_OBJECT = 0x7, IMAGE_CEE_CS_STRUCT4 = 0x8, IMAGE_CEE_CS_STRUCT32 = 0x9, IMAGE_CEE_CS_BYVALUE = 0xA, } CorArgType; //***************************************************************************** // // Native type for N-Direct // //***************************************************************************** typedef enum CorNativeType { // Keep this in-sync with ndp\clr\src\BCL\System\runtime\interopservices\attributes.cs NATIVE_TYPE_END = 0x0, //DEPRECATED NATIVE_TYPE_VOID = 0x1, //DEPRECATED NATIVE_TYPE_BOOLEAN = 0x2, // (4 byte boolean value: TRUE = non-zero, FALSE = 0) NATIVE_TYPE_I1 = 0x3, NATIVE_TYPE_U1 = 0x4, NATIVE_TYPE_I2 = 0x5, NATIVE_TYPE_U2 = 0x6, NATIVE_TYPE_I4 = 0x7, NATIVE_TYPE_U4 = 0x8, NATIVE_TYPE_I8 = 0x9, NATIVE_TYPE_U8 = 0xa, NATIVE_TYPE_R4 = 0xb, NATIVE_TYPE_R8 = 0xc, NATIVE_TYPE_SYSCHAR = 0xd, //DEPRECATED NATIVE_TYPE_VARIANT = 0xe, //DEPRECATED NATIVE_TYPE_CURRENCY = 0xf, NATIVE_TYPE_PTR = 0x10, //DEPRECATED NATIVE_TYPE_DECIMAL = 0x11, //DEPRECATED NATIVE_TYPE_DATE = 0x12, //DEPRECATED NATIVE_TYPE_BSTR = 0x13, //COMINTEROP NATIVE_TYPE_LPSTR = 0x14, NATIVE_TYPE_LPWSTR = 0x15, NATIVE_TYPE_LPTSTR = 0x16, NATIVE_TYPE_FIXEDSYSSTRING = 0x17, NATIVE_TYPE_OBJECTREF = 0x18, //DEPRECATED NATIVE_TYPE_IUNKNOWN = 0x19, //COMINTEROP NATIVE_TYPE_IDISPATCH = 0x1a, //COMINTEROP NATIVE_TYPE_STRUCT = 0x1b, NATIVE_TYPE_INTF = 0x1c, //COMINTEROP NATIVE_TYPE_SAFEARRAY = 0x1d, //COMINTEROP NATIVE_TYPE_FIXEDARRAY = 0x1e, NATIVE_TYPE_INT = 0x1f, NATIVE_TYPE_UINT = 0x20, NATIVE_TYPE_NESTEDSTRUCT = 0x21, //DEPRECATED (use NATIVE_TYPE_STRUCT) NATIVE_TYPE_BYVALSTR = 0x22, //COMINTEROP NATIVE_TYPE_ANSIBSTR = 0x23, //COMINTEROP NATIVE_TYPE_TBSTR = 0x24, // select BSTR or ANSIBSTR depending on platform //COMINTEROP NATIVE_TYPE_VARIANTBOOL = 0x25, // (2-byte boolean value: TRUE = -1, FALSE = 0) //COMINTEROP NATIVE_TYPE_FUNC = 0x26, NATIVE_TYPE_ASANY = 0x28, NATIVE_TYPE_ARRAY = 0x2a, NATIVE_TYPE_LPSTRUCT = 0x2b, NATIVE_TYPE_CUSTOMMARSHALER = 0x2c, // Custom marshaler native type. This must be followed // by a string of the following format: // "Native type name/0Custom marshaler type name/0Optional cookie/0" // Or // "{Native type GUID}/0Custom marshaler type name/0Optional cookie/0" NATIVE_TYPE_ERROR = 0x2d, // This native type coupled with ELEMENT_TYPE_I4 will map to VT_HRESULT //COMINTEROP NATIVE_TYPE_IINSPECTABLE = 0x2e, NATIVE_TYPE_HSTRING = 0x2f, NATIVE_TYPE_LPUTF8STR = 0x30, // utf-8 string NATIVE_TYPE_MAX = 0x50, // first invalid element type } CorNativeType; enum { DESCR_GROUP_METHODDEF = 0, // DESCR group for MethodDefs DESCR_GROUP_METHODIMPL, // DESCR group for MethodImpls }; /***********************************************************************************/ // a COR_ILMETHOD_SECT is a generic container for attributes that are private // to a particular method. The COR_ILMETHOD structure points to one of these // (see GetSect()). COR_ILMETHOD_SECT can decode the Kind of attribute (but not // its internal data layout), and can skip past the current attribute to find the // Next one. The overhead for COR_ILMETHOD_SECT is a minimum of 2 bytes. typedef enum CorILMethodSect // codes that identify attributes { CorILMethod_Sect_Reserved = 0, CorILMethod_Sect_EHTable = 1, CorILMethod_Sect_OptILTable = 2, CorILMethod_Sect_KindMask = 0x3F, // The mask for decoding the type code CorILMethod_Sect_FatFormat = 0x40, // fat format CorILMethod_Sect_MoreSects = 0x80, // there is another attribute after this one } CorILMethodSect; /************************************/ /* NOTE this structure must be DWORD aligned!! */ typedef struct IMAGE_COR_ILMETHOD_SECT_SMALL { uint8_t Kind; uint8_t DataSize; } IMAGE_COR_ILMETHOD_SECT_SMALL; /************************************/ /* NOTE this structure must be DWORD aligned!! */ typedef struct IMAGE_COR_ILMETHOD_SECT_FAT { unsigned Kind : 8; unsigned DataSize : 24; } IMAGE_COR_ILMETHOD_SECT_FAT; /***********************************************************************************/ /* If COR_ILMETHOD_SECT_HEADER::Kind() = CorILMethod_Sect_EHTable then the attribute is a list of exception handling clauses. There are two formats, fat or small */ typedef enum CorExceptionFlag // definitions for the Flags field below (for both big and small) { COR_ILEXCEPTION_CLAUSE_NONE, // This is a typed handler COR_ILEXCEPTION_CLAUSE_OFFSETLEN = 0x0000, // Deprecated COR_ILEXCEPTION_CLAUSE_DEPRECATED = 0x0000, // Deprecated COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004, // Fault clause (finally that is called on exception only) COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clause. This clause was duplicated to a funclet which was pulled out of line } CorExceptionFlag; /***********************************/ typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT { CorExceptionFlag Flags; uint32_t TryOffset; uint32_t TryLength; // relative to start of try block uint32_t HandlerOffset; uint32_t HandlerLength; // relative to start of handler union { uint32_t ClassToken; // use for type-based exception handlers uint32_t FilterOffset; // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set) }; } IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT; typedef struct IMAGE_COR_ILMETHOD_SECT_EH_FAT { IMAGE_COR_ILMETHOD_SECT_FAT SectFat; IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size } IMAGE_COR_ILMETHOD_SECT_EH_FAT; /***********************************/ typedef struct IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL { #ifdef HOST_64BIT unsigned Flags : 16; #else // !HOST_64BIT CorExceptionFlag Flags : 16; #endif unsigned TryOffset : 16; unsigned TryLength : 8; // relative to start of try block unsigned HandlerOffset : 16; unsigned HandlerLength : 8; // relative to start of handler union { uint32_t ClassToken; uint32_t FilterOffset; }; } IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL; /***********************************/ typedef struct IMAGE_COR_ILMETHOD_SECT_EH_SMALL { IMAGE_COR_ILMETHOD_SECT_SMALL SectSmall; uint16_t Reserved; IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size } IMAGE_COR_ILMETHOD_SECT_EH_SMALL; typedef union IMAGE_COR_ILMETHOD_SECT_EH { IMAGE_COR_ILMETHOD_SECT_EH_SMALL Small; IMAGE_COR_ILMETHOD_SECT_EH_FAT Fat; } IMAGE_COR_ILMETHOD_SECT_EH; /***********************************************************************************/ // Legal values for // * code:IMAGE_COR_ILMETHOD_FAT::Flags or // * code:IMAGE_COR_ILMETHOD_TINY::Flags_CodeSize fields. // // The only semantic flag at present is CorILMethod_InitLocals typedef enum CorILMethodFlags { CorILMethod_InitLocals = 0x0010, // call default constructor on all local vars CorILMethod_MoreSects = 0x0008, // there is another attribute after this one CorILMethod_CompressedIL = 0x0040, // Not used. // Indicates the format for the COR_ILMETHOD header CorILMethod_FormatShift = 3, CorILMethod_FormatMask = ((1 << CorILMethod_FormatShift) - 1), CorILMethod_TinyFormat = 0x0002, // use this code if the code size is even CorILMethod_SmallFormat = 0x0000, CorILMethod_FatFormat = 0x0003, CorILMethod_TinyFormat1 = 0x0006, // use this code if the code size is odd } CorILMethodFlags; /***************************************************************************/ /* Used when the method is tiny (< 64 bytes), and there are no local vars */ typedef struct IMAGE_COR_ILMETHOD_TINY { uint8_t Flags_CodeSize; } IMAGE_COR_ILMETHOD_TINY; /************************************/ // This structure is the 'fat' layout, where no compression is attempted. // Note that this structure can be added on at the end, thus making it extensible typedef struct IMAGE_COR_ILMETHOD_FAT { unsigned Flags : 12; // Flags see code:CorILMethodFlags unsigned Size : 4; // size in DWords of this structure (currently 3) unsigned MaxStack : 16; // maximum number of items (I4, I, I8, obj ...), on the operand stack uint32_t CodeSize; // size of the code mdSignature LocalVarSigTok; // token that indicates the signature of the local vars (0 means none) } IMAGE_COR_ILMETHOD_FAT; // an IMAGE_COR_ILMETHOD holds the IL instructions for a individual method. To save space they come in two // flavors Fat and Tiny. Conceptually Tiny is just a compressed version of Fat, so code:IMAGE_COR_ILMETHOD_FAT // is the logical structure for all headers. Conceptually this blob holds the IL, the Exception Handling // Tables, the local variable information and some flags. typedef union IMAGE_COR_ILMETHOD { IMAGE_COR_ILMETHOD_TINY Tiny; IMAGE_COR_ILMETHOD_FAT Fat; } IMAGE_COR_ILMETHOD; //***************************************************************************** // Non VOS v-table entries. Define an array of these pointed to by // IMAGE_COR20_HEADER.VTableFixups. Each entry describes a contiguous array of // v-table slots. The slots start out initialized to the meta data token value // for the method they need to call. At image load time, the CLR Loader will // turn each entry into a pointer to machine code for the CPU and can be // called directly. //***************************************************************************** typedef struct IMAGE_COR_VTABLEFIXUP { uint32_t RVA; // Offset of v-table array in image. uint16_t Count; // How many entries at location. uint16_t Type; // COR_VTABLE_xxx type of entries. } IMAGE_COR_VTABLEFIXUP; //***************************************************************************** //***************************************************************************** // // M E T A - D A T A D E C L A R A T I O N S // //***************************************************************************** //***************************************************************************** //***************************************************************************** // // Enums for SetOption API. // //***************************************************************************** // flags for MetaDataCheckDuplicatesFor typedef enum CorCheckDuplicatesFor { MDDupAll = 0xffffffff, MDDupENC = MDDupAll, MDNoDupChecks = 0x00000000, MDDupTypeDef = 0x00000001, MDDupInterfaceImpl = 0x00000002, MDDupMethodDef = 0x00000004, MDDupTypeRef = 0x00000008, MDDupMemberRef = 0x00000010, MDDupCustomAttribute = 0x00000020, MDDupParamDef = 0x00000040, MDDupPermission = 0x00000080, MDDupProperty = 0x00000100, MDDupEvent = 0x00000200, MDDupFieldDef = 0x00000400, MDDupSignature = 0x00000800, MDDupModuleRef = 0x00001000, MDDupTypeSpec = 0x00002000, MDDupImplMap = 0x00004000, MDDupAssemblyRef = 0x00008000, MDDupFile = 0x00010000, MDDupExportedType = 0x00020000, MDDupManifestResource = 0x00040000, MDDupGenericParam = 0x00080000, MDDupMethodSpec = 0x00100000, MDDupGenericParamConstraint = 0x00200000, // gap for debug junk MDDupAssembly = 0x10000000, // This is the default behavior on metadata. It will check duplicates for TypeRef, MemberRef, Signature, TypeSpec and MethodSpec. MDDupDefault = MDNoDupChecks | MDDupTypeRef | MDDupMemberRef | MDDupSignature | MDDupTypeSpec | MDDupMethodSpec, } CorCheckDuplicatesFor; // flags for MetaDataRefToDefCheck typedef enum CorRefToDefCheck { // default behavior is to always perform TypeRef to TypeDef and MemberRef to MethodDef/FieldDef optimization MDRefToDefDefault = 0x00000003, MDRefToDefAll = 0xffffffff, MDRefToDefNone = 0x00000000, MDTypeRefToDef = 0x00000001, MDMemberRefToDef = 0x00000002 } CorRefToDefCheck; // MetaDataNotificationForTokenMovement typedef enum CorNotificationForTokenMovement { // default behavior is to notify TypeRef, MethodDef, MemberRef, and FieldDef token remaps MDNotifyDefault = 0x0000000f, MDNotifyAll = 0xffffffff, MDNotifyNone = 0x00000000, MDNotifyMethodDef = 0x00000001, MDNotifyMemberRef = 0x00000002, MDNotifyFieldDef = 0x00000004, MDNotifyTypeRef = 0x00000008, MDNotifyTypeDef = 0x00000010, MDNotifyParamDef = 0x00000020, MDNotifyInterfaceImpl = 0x00000040, MDNotifyProperty = 0x00000080, MDNotifyEvent = 0x00000100, MDNotifySignature = 0x00000200, MDNotifyTypeSpec = 0x00000400, MDNotifyCustomAttribute = 0x00000800, MDNotifySecurityValue = 0x00001000, MDNotifyPermission = 0x00002000, MDNotifyModuleRef = 0x00004000, MDNotifyNameSpace = 0x00008000, MDNotifyAssemblyRef = 0x01000000, MDNotifyFile = 0x02000000, MDNotifyExportedType = 0x04000000, MDNotifyResource = 0x08000000, } CorNotificationForTokenMovement; typedef enum CorSetENC { MDSetENCOn = 0x00000001, // Deprecated name. MDSetENCOff = 0x00000002, // Deprecated name. MDUpdateENC = 0x00000001, // ENC mode. Tokens don't move; can be updated. MDUpdateFull = 0x00000002, // "Normal" update mode. MDUpdateExtension = 0x00000003, // Extension mode. Tokens don't move, adds only. MDUpdateIncremental = 0x00000004, // Incremental compilation MDUpdateDelta = 0x00000005, // If ENC on, save only deltas. MDUpdateMask = 0x00000007, } CorSetENC; #define IsENCDelta(x) (((x) & MDUpdateMask) == MDUpdateDelta) // flags used in SetOption when pair with MetaDataErrorIfEmitOutOfOrder guid typedef enum CorErrorIfEmitOutOfOrder { MDErrorOutOfOrderDefault = 0x00000000, // default not to generate any error MDErrorOutOfOrderNone = 0x00000000, // do not generate error for out of order emit MDErrorOutOfOrderAll = 0xffffffff, // generate out of order emit for method, field, param, property, and event MDMethodOutOfOrder = 0x00000001, // generate error when methods are emitted out of order MDFieldOutOfOrder = 0x00000002, // generate error when fields are emitted out of order MDParamOutOfOrder = 0x00000004, // generate error when params are emitted out of order MDPropertyOutOfOrder = 0x00000008, // generate error when properties are emitted out of order MDEventOutOfOrder = 0x00000010, // generate error when events are emitted out of order } CorErrorIfEmitOutOfOrder; // flags used in SetOption when pair with MetaDataImportOption guid typedef enum CorImportOptions { MDImportOptionDefault = 0x00000000, // default to skip over deleted records MDImportOptionAll = 0xFFFFFFFF, // Enumerate everything MDImportOptionAllTypeDefs = 0x00000001, // all the typedefs including the deleted typedef MDImportOptionAllMethodDefs = 0x00000002, // all the methoddefs including the deleted ones MDImportOptionAllFieldDefs = 0x00000004, // all the fielddefs including the deleted ones MDImportOptionAllProperties = 0x00000008, // all the properties including the deleted ones MDImportOptionAllEvents = 0x00000010, // all the events including the deleted ones MDImportOptionAllCustomAttributes = 0x00000020, // all the custom attributes including the deleted ones MDImportOptionAllExportedTypes = 0x00000040, // all the ExportedTypes including the deleted ones } CorImportOptions; // flags for MetaDataThreadSafetyOptions typedef enum CorThreadSafetyOptions { // default behavior is to have thread safety turn off. This means that MetaData APIs will not take reader/writer // lock. Clients are responsible to make sure the properly thread synchronization when using MetaData APIs. MDThreadSafetyDefault = 0x00000000, MDThreadSafetyOff = 0x00000000, MDThreadSafetyOn = 0x00000001, } CorThreadSafetyOptions; // flags for MetaDataLinkerOptions typedef enum CorLinkerOptions { // default behavior is not to keep private types MDAssembly = 0x00000000, MDNetModule = 0x00000001, } CorLinkerOptions; // flags for MetaDataMergeOptions typedef enum MergeFlags { MergeFlagsNone = 0, MergeManifest = 0x00000001, DropMemberRefCAs = 0x00000002, NoDupCheck = 0x00000004, MergeExportedTypes = 0x00000008 } MergeFlags; // flags for MetaDataPreserveLocalRefs typedef enum CorLocalRefPreservation { MDPreserveLocalRefsNone = 0x00000000, MDPreserveLocalTypeRef = 0x00000001, MDPreserveLocalMemberRef = 0x00000002 } CorLocalRefPreservation; // // struct used to retrieve field offset // used by GetClassLayout and SetClassLayout // #ifndef _COR_FIELD_OFFSET_ #define _COR_FIELD_OFFSET_ typedef struct COR_FIELD_OFFSET { mdFieldDef ridOfField; uint32_t ulOffset; } COR_FIELD_OFFSET; #endif // // Token tags. // typedef enum CorTokenType { mdtModule = 0x00000000, // mdtTypeRef = 0x01000000, // mdtTypeDef = 0x02000000, // mdtFieldDef = 0x04000000, // mdtMethodDef = 0x06000000, // mdtParamDef = 0x08000000, // mdtInterfaceImpl = 0x09000000, // mdtMemberRef = 0x0a000000, // mdtCustomAttribute = 0x0c000000, // mdtPermission = 0x0e000000, // mdtSignature = 0x11000000, // mdtEvent = 0x14000000, // mdtProperty = 0x17000000, // mdtMethodImpl = 0x19000000, // mdtModuleRef = 0x1a000000, // mdtTypeSpec = 0x1b000000, // mdtAssembly = 0x20000000, // mdtAssemblyRef = 0x23000000, // mdtFile = 0x26000000, // mdtExportedType = 0x27000000, // mdtManifestResource = 0x28000000, // mdtNestedClass = 0x29000000, // mdtGenericParam = 0x2a000000, // mdtMethodSpec = 0x2b000000, // mdtGenericParamConstraint = 0x2c000000, mdtString = 0x70000000, // mdtName = 0x71000000, // mdtBaseType = 0x72000000, // Leave this on the high end value. This does not correspond to metadata table } CorTokenType; // // Build / decompose tokens. // #define RidToToken(rid,tktype) ((rid) |= (tktype)) #define TokenFromRid(rid,tktype) ((rid) | (tktype)) #define RidFromToken(tk) ((RID) ((tk) & 0x00ffffff)) #define TypeFromToken(tk) ((ULONG32)((tk) & 0xff000000)) #define IsNilToken(tk) ((RidFromToken(tk)) == 0) // // Nil tokens // #define mdTokenNil ((mdToken)0) #define mdModuleNil ((mdModule)mdtModule) #define mdTypeRefNil ((mdTypeRef)mdtTypeRef) #define mdTypeDefNil ((mdTypeDef)mdtTypeDef) #define mdFieldDefNil ((mdFieldDef)mdtFieldDef) #define mdMethodDefNil ((mdMethodDef)mdtMethodDef) #define mdParamDefNil ((mdParamDef)mdtParamDef) #define mdInterfaceImplNil ((mdInterfaceImpl)mdtInterfaceImpl) #define mdMemberRefNil ((mdMemberRef)mdtMemberRef) #define mdCustomAttributeNil ((mdCustomAttribute)mdtCustomAttribute) #define mdPermissionNil ((mdPermission)mdtPermission) #define mdSignatureNil ((mdSignature)mdtSignature) #define mdEventNil ((mdEvent)mdtEvent) #define mdPropertyNil ((mdProperty)mdtProperty) #define mdModuleRefNil ((mdModuleRef)mdtModuleRef) #define mdTypeSpecNil ((mdTypeSpec)mdtTypeSpec) #define mdAssemblyNil ((mdAssembly)mdtAssembly) #define mdAssemblyRefNil ((mdAssemblyRef)mdtAssemblyRef) #define mdFileNil ((mdFile)mdtFile) #define mdExportedTypeNil ((mdExportedType)mdtExportedType) #define mdManifestResourceNil ((mdManifestResource)mdtManifestResource) #define mdGenericParamNil ((mdGenericParam)mdtGenericParam) #define mdGenericParamConstraintNil ((mdGenericParamConstraint)mdtGenericParamConstraint) #define mdMethodSpecNil ((mdMethodSpec)mdtMethodSpec) #define mdStringNil ((mdString)mdtString) // // Open bits. // typedef enum CorOpenFlags { ofRead = 0x00000000, // Open scope for read ofWrite = 0x00000001, // Open scope for write. ofReadWriteMask = 0x00000001, // Mask for read/write bit. ofCopyMemory = 0x00000002, // Open scope with memory. Ask metadata to maintain its own copy of memory. ofReadOnly = 0x00000010, // Open scope for read. Will be unable to QI for a IMetadataEmit* interface ofTakeOwnership = 0x00000020, // The memory was allocated with CoTaskMemAlloc and will be freed by the metadata // These are obsolete and are ignored. // ofCacheImage = 0x00000004, // EE maps but does not do relocations or verify image // ofManifestMetadata = 0x00000008, // Open scope on ngen image, return the manifest metadata instead of the IL metadata ofNoTypeLib = 0x00000080, // Don't OpenScope on a typelib. ofNoTransform = 0x00001000, // Disable automatic transforms of .winmd files. // Internal bits ofReserved1 = 0x00000100, // Reserved for internal use. ofReserved2 = 0x00000200, // Reserved for internal use. ofReserved3 = 0x00000400, // Reserved for internal use. ofReserved = 0xffffef40 // All the reserved bits. } CorOpenFlags; #define IsOfRead(x) (((x) & ofReadWriteMask) == ofRead) #define IsOfReadWrite(x) (((x) & ofReadWriteMask) == ofWrite) #define IsOfCopyMemory(x) ((x) & ofCopyMemory) #define IsOfReadOnly(x) ((x) & ofReadOnly) #define IsOfTakeOwnership(x) ((x) & ofTakeOwnership) #define IsOfReserved(x) (((x) & ofReserved) != 0) // // Type of file mapping returned by code:IMetaDataInfo::GetFileMapping. // typedef enum CorFileMapping { fmFlat = 0, // Flat file mapping - file is mapped as data file (code:SEC_IMAGE flag was not // passed to code:CreateFileMapping). fmExecutableImage = 1, // Executable image file mapping - file is mapped for execution // (either via code:LoadLibrary or code:CreateFileMapping with code:SEC_IMAGE flag). } CorFileMapping; typedef CorTypeAttr CorRegTypeAttr; // // Opaque type for an enumeration handle. // typedef void *HCORENUM; // Note that this must be kept in sync with System.AttributeTargets. typedef enum CorAttributeTargets { catAssembly = 0x0001, catModule = 0x0002, catClass = 0x0004, catStruct = 0x0008, catEnum = 0x0010, catConstructor = 0x0020, catMethod = 0x0040, catProperty = 0x0080, catField = 0x0100, catEvent = 0x0200, catInterface = 0x0400, catParameter = 0x0800, catDelegate = 0x1000, catGenericParameter = 0x4000, catAll = catAssembly | catModule | catClass | catStruct | catEnum | catConstructor | catMethod | catProperty | catField | catEvent | catInterface | catParameter | catDelegate | catGenericParameter, catClassMembers = catClass | catStruct | catEnum | catConstructor | catMethod | catProperty | catField | catEvent | catDelegate | catInterface, } CorAttributeTargets; #ifndef MACROS_NOT_SUPPORTED // // Some well-known custom attributes // #ifndef IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS #define IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS (IMAGE_CEE_CS_CALLCONV_DEFAULT | IMAGE_CEE_CS_CALLCONV_HASTHIS) #endif #define INTEROP_DISPID_TYPE_W W("System.Runtime.InteropServices.DispIdAttribute") #define INTEROP_DISPID_TYPE "System.Runtime.InteropServices.DispIdAttribute" #define INTEROP_DISPID_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I4} #define INTEROP_INTERFACETYPE_TYPE_W W("System.Runtime.InteropServices.InterfaceTypeAttribute") #define INTEROP_INTERFACETYPE_TYPE "System.Runtime.InteropServices.InterfaceTypeAttribute" #define INTEROP_INTERFACETYPE_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2} #define INTEROP_GUID_TYPE_W W("System.Runtime.InteropServices.GuidAttribute") #define INTEROP_GUID_TYPE "System.Runtime.InteropServices.GuidAttribute" #define INTEROP_GUID_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} #define INTEROP_TYPELIBVERSION_TYPE_W W("System.Runtime.InteropServices.TypeLibVersionAttribute") #define INTEROP_TYPELIBVERSION_TYPE "System.Runtime.InteropServices.TypeLibVersionAttribute" #define INTEROP_TYPELIBVERSION_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_I2, ELEMENT_TYPE_I2} #define INTEROP_COMEVENTINTERFACE_TYPE_W W("System.Runtime.InteropServices.ComEventInterfaceAttribute") #define INTEROP_COMEVENTINTERFACE_TYPE "System.Runtime.InteropServices.ComEventInterfaceAttribute" #define FRIEND_ASSEMBLY_TYPE_W W("System.Runtime.CompilerServices.InternalsVisibleToAttribute") #define FRIEND_ASSEMBLY_TYPE "System.Runtime.CompilerServices.InternalsVisibleToAttribute" #define FRIEND_ASSEMBLY_TYPE_NAMESPACE "System.Runtime.CompilerServices" #define FRIEND_ASSEMBLY_TYPE_NAME "InternalsVisibleToAttribute" #define FRIEND_ASSEMBLY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 2, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING, ELEMENT_TYPE_BOOLEAN} #define SUBJECT_ASSEMBLY_TYPE_W W("System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute") #define SUBJECT_ASSEMBLY_TYPE "System.Runtime.CompilerServices.IgnoresAccessChecksToAttribute" #define SUBJECT_ASSEMBLY_TYPE_NAMESPACE "System.Runtime.CompilerServices" #define SUBJECT_ASSEMBLY_TYPE_NAME "IgnoresAccessChecksToAttribute" #define SUBJECT_ASSEMBLY_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 1, ELEMENT_TYPE_VOID, ELEMENT_TYPE_STRING} #define DEFAULTDOMAIN_STA_TYPE_W W("System.STAThreadAttribute") #define DEFAULTDOMAIN_STA_TYPE "System.STAThreadAttribute" #define DEFAULTDOMAIN_STA_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} #define DEFAULTDOMAIN_MTA_TYPE_W W("System.MTAThreadAttribute") #define DEFAULTDOMAIN_MTA_TYPE "System.MTAThreadAttribute" #define DEFAULTDOMAIN_MTA_SIG {IMAGE_CEE_CS_CALLCONV_DEFAULT_HASTHIS, 0, ELEMENT_TYPE_VOID} #define DEBUGGABLE_ATTRIBUTE_TYPE_W W("System.Diagnostics.DebuggableAttribute") #define DEBUGGABLE_ATTRIBUTE_TYPE "System.Diagnostics.DebuggableAttribute" #define DEBUGGABLE_ATTRIBUTE_TYPE_NAMESPACE "System.Diagnostics" #define DEBUGGABLE_ATTRIBUTE_TYPE_NAME "DebuggableAttribute" // Keep in sync with RuntimeCompatibilityAttribute.cs #define RUNTIMECOMPATIBILITY_TYPE_W W("System.Runtime.CompilerServices.RuntimeCompatibilityAttribute") #define RUNTIMECOMPATIBILITY_TYPE "System.Runtime.CompilerServices.RuntimeCompatibilityAttribute" // Keep in sync with AssemblySettingAttributes.cs typedef enum NGenHintEnum { NGenDefault = 0x0000, // No preference specified NGenEager = 0x0001, // NGen at install time NGenLazy = 0x0002, // NGen after install time NGenNever = 0x0003 // Assembly should not be ngened } NGenHintEnum; typedef enum LoadHintEnum { LoadDefault = 0x0000, // No preference specified LoadAlways = 0x0001, // Dependency is always loaded LoadSometimes = 0x0002, // Dependency is sometimes loaded LoadNever = 0x0003 // Dependency is never loaded } LoadHintEnum; #define CMOD_CALLCONV_NAMESPACE_OLD "System.Runtime.InteropServices" #define CMOD_CALLCONV_NAMESPACE "System.Runtime.CompilerServices" #define CMOD_CALLCONV_NAME_CDECL "CallConvCdecl" #define CMOD_CALLCONV_NAME_STDCALL "CallConvStdcall" #define CMOD_CALLCONV_NAME_THISCALL "CallConvThiscall" #define CMOD_CALLCONV_NAME_FASTCALL "CallConvFastcall" #define CMOD_CALLCONV_NAME_SUPPRESSGCTRANSITION "CallConvSuppressGCTransition" #define CMOD_CALLCONV_NAME_MEMBERFUNCTION "CallConvMemberFunction" #endif // MACROS_NOT_SUPPORTED // // GetSaveSize accuracy // #ifndef _CORSAVESIZE_DEFINED_ #define _CORSAVESIZE_DEFINED_ typedef enum CorSaveSize { cssAccurate = 0x0000, // Find exact save size, accurate but slower. cssQuick = 0x0001, // Estimate save size, may pad estimate, but faster. cssDiscardTransientCAs = 0x0002, // remove all of the CAs of discardable types } CorSaveSize; #endif #define COR_IS_METHOD_MANAGED_IL(flags) (((flags) & 0xf) == (miIL | miManaged)) #define COR_IS_METHOD_MANAGED_OPTIL(flags) (((flags) & 0xf) == (miOPTIL | miManaged)) #define COR_IS_METHOD_MANAGED_NATIVE(flags) (((flags) & 0xf) == (miNative | miManaged)) #define COR_IS_METHOD_UNMANAGED_NATIVE(flags) (((flags) & 0xf) == (miNative | miUnmanaged)) // // Enum used with NATIVE_TYPE_ARRAY. // typedef enum NativeTypeArrayFlags { ntaSizeParamIndexSpecified = 0x0001, ntaReserved = 0xfffe // All the reserved bits. } NativeTypeArrayFlags; // // Enum used for HFA type recognition. // Supported across architectures, so that it can be used in altjits and cross-compilation. typedef enum CorInfoHFAElemType : unsigned { CORINFO_HFA_ELEM_NONE, CORINFO_HFA_ELEM_FLOAT, CORINFO_HFA_ELEM_DOUBLE, CORINFO_HFA_ELEM_VECTOR64, CORINFO_HFA_ELEM_VECTOR128, } CorInfoHFAElemType; // // Opaque types for security properties and values. // typedef void * PSECURITY_PROPS ; typedef void * PSECURITY_VALUE ; typedef void ** PPSECURITY_PROPS ; typedef void ** PPSECURITY_VALUE ; //------------------------------------- //--- Security data structures //------------------------------------- // Descriptor for a single security custom attribute. typedef struct COR_SECATTR { mdMemberRef tkCtor; // Ref to constructor of security attribute. const void *pCustomAttribute; // Blob describing ctor args and field/property values. uint32_t cbCustomAttribute; // Length of the above blob. } COR_SECATTR; #endif // __CORHDR_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corhlpr.cpp ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /**************************************************************************** ** ** ** Corhlpr.h - signature helpers. ** ** ** ****************************************************************************/ #ifndef SOS_INCLUDE #ifdef _BLD_CLR #include "utilcode.h" #endif #include "corhlpr.h" #include #endif // !SOS_INCLUDE //***************************************************************************** // //***** File format helper classes // //***************************************************************************** extern "C" { /***************************************************************************/ /* Note that this constructor does not set the LocalSig, but has the advantage that it does not have any dependency on EE structures. inside the EE use the FunctionDesc constructor */ void __stdcall DecoderInit(void *pThis, COR_ILMETHOD *header) { memset(pThis, 0, sizeof(COR_ILMETHOD_DECODER)); COR_ILMETHOD_DECODER *decoder = (COR_ILMETHOD_DECODER *)pThis; if (header->Tiny.IsTiny()) { decoder->SetMaxStack(header->Tiny.GetMaxStack()); decoder->Code = header->Tiny.GetCode(); decoder->SetCodeSize(header->Tiny.GetCodeSize()); decoder->SetFlags(CorILMethod_TinyFormat); return; } if (header->Fat.IsFat()) { #ifdef HOST_64BIT if((((size_t) header) & 3) == 0) // header is aligned #else assert((((size_t) header) & 3) == 0); // header is aligned #endif { *((COR_ILMETHOD_FAT *)decoder) = header->Fat; decoder->Code = header->Fat.GetCode(); if (header->Fat.GetSize() >= (sizeof(COR_ILMETHOD_FAT) / 4)) // Size if valid { decoder->Sect = header->Fat.GetSect(); if ((decoder->Sect != NULL) && (decoder->Sect->Kind() == CorILMethod_Sect_EHTable)) { decoder->EH = (COR_ILMETHOD_SECT_EH *)decoder->Sect; decoder->Sect = decoder->Sect->Next(); } } } return; } } // DecoderInit // Calculate the total method size. First get address of end of code. If there are no sections, then // the end of code addr marks end of COR_ILMETHOD. Otherwise find addr of end of last section and use it // to mark end of COR_ILMETHOD. Assumes that the code is directly followed // by each section in the on-disk format int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header) { COR_ILMETHOD_DECODER* decoder = (COR_ILMETHOD_DECODER*)pThis; if (decoder->Code == NULL) return 0; BYTE *lastAddr = (BYTE*)decoder->Code + decoder->GetCodeSize(); // addr of end of code const COR_ILMETHOD_SECT *sect = decoder->EH; if (sect != 0 && sect->Next() == 0) { lastAddr = (BYTE *)sect + sect->DataSize(); } else { const COR_ILMETHOD_SECT *nextSect; for (sect = decoder->Sect; sect; sect = nextSect) { nextSect = sect->Next(); if (nextSect == 0) { // sect points to the last section, so set lastAddr lastAddr = (BYTE *)sect + sect->DataSize(); break; } } } return (int)(lastAddr - (BYTE*)header); } /*********************************************************************/ /* APIs for emitting sections etc */ unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL moreSections) { if (header->GetMaxStack() <= 8 && (header->GetFlags() & ~CorILMethod_FormatMask) == 0 && header->GetLocalVarSigTok() == 0 && header->GetCodeSize() < 64 && !moreSections) return(sizeof(COR_ILMETHOD_TINY)); return(sizeof(COR_ILMETHOD_FAT)); } /*********************************************************************/ // emit the header (bestFormat) return amount emitted unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, BOOL moreSections, BYTE* outBuff) { #ifndef SOS_INCLUDE #ifdef _DEBUG BYTE* origBuff = outBuff; #endif #endif // !SOS_INCLUDE if (size == 1) { // Tiny format *outBuff++ = (BYTE) (CorILMethod_TinyFormat | (header->GetCodeSize() << 2)); } else { // Fat format assert((((size_t) outBuff) & 3) == 0); // header is dword aligned COR_ILMETHOD_FAT* fatHeader = (COR_ILMETHOD_FAT*) outBuff; outBuff += sizeof(COR_ILMETHOD_FAT); *fatHeader = *header; fatHeader->SetFlags(fatHeader->GetFlags() | CorILMethod_FatFormat); assert((fatHeader->GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); if (moreSections) fatHeader->SetFlags(fatHeader->GetFlags() | CorILMethod_MoreSects); fatHeader->SetSize(sizeof(COR_ILMETHOD_FAT) / 4); } #ifndef SOS_INCLUDE #ifdef _DEBUG assert(&origBuff[size] == outBuff); #endif #endif // !SOS_INCLUDE return(size); } /*********************************************************************/ /* static */ IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) { if (((COR_ILMETHOD_SECT_EH *)pSectEH)->IsFat()) return(&(((COR_ILMETHOD_SECT_EH *)pSectEH)->Fat.Clauses[idx])); COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)buff; COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&((COR_ILMETHOD_SECT_EH *)pSectEH)->Small.Clauses[idx]; // mask to remove sign extension - cast just wouldn't work fatClause->SetFlags((CorExceptionFlag)(smallClause->GetFlags()&0x0000ffff)); fatClause->SetClassToken(smallClause->GetClassToken()); fatClause->SetTryOffset(smallClause->GetTryOffset()); fatClause->SetTryLength(smallClause->GetTryLength()); fatClause->SetHandlerLength(smallClause->GetHandlerLength()); fatClause->SetHandlerOffset(smallClause->GetHandlerOffset()); return(buff); } /*********************************************************************/ // compute the size of the section (best format) // codeSize is the size of the method // deprecated unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize) { return((ehCount)? SectEH_SizeWorst(ehCount) : 0); } // will return worse-case size and then Emit will return actual size unsigned __stdcall SectEH_SizeWorst(unsigned ehCount) { return((ehCount)? (COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)) : 0); } // will return exact size which will match the size returned by Emit unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses) { if (ehCount == 0) return(0); unsigned smallSize = COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount); if (smallSize > COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)); for (unsigned i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&clauses[i]; if (fatClause->GetTryOffset() > 0xFFFF || fatClause->GetTryLength() > 0xFF || fatClause->GetHandlerOffset() > 0xFFFF || fatClause->GetHandlerLength() > 0xFF) { return(COR_ILMETHOD_SECT_EH_FAT::Size(ehCount)); } } return smallSize; } /*********************************************************************/ // emit the section (best format); unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, BOOL moreSections, BYTE* outBuff, ULONG* ehTypeOffsets) { if (size == 0) return(0); assert((((size_t) outBuff) & 3) == 0); // header is dword aligned BYTE* origBuff = outBuff; if (ehCount <= 0) return 0; // Initialize the ehTypeOffsets array. if (ehTypeOffsets) { for (unsigned int i = 0; i < ehCount; i++) ehTypeOffsets[i] = (ULONG) -1; } if (COR_ILMETHOD_SECT_EH_SMALL::Size(ehCount) < COR_ILMETHOD_SECT_SMALL_MAX_DATASIZE) { COR_ILMETHOD_SECT_EH_SMALL* EHSect = (COR_ILMETHOD_SECT_EH_SMALL*) outBuff; unsigned i; for (i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&clauses[i]; if (fatClause->GetTryOffset() > 0xFFFF || fatClause->GetTryLength() > 0xFF || fatClause->GetHandlerOffset() > 0xFFFF || fatClause->GetHandlerLength() > 0xFF) { break; // fall through and generate as FAT } assert((fatClause->GetFlags() & ~0xFFFF) == 0); assert((fatClause->GetTryOffset() & ~0xFFFF) == 0); assert((fatClause->GetTryLength() & ~0xFF) == 0); assert((fatClause->GetHandlerOffset() & ~0xFFFF) == 0); assert((fatClause->GetHandlerLength() & ~0xFF) == 0); COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&EHSect->Clauses[i]; smallClause->SetFlags((CorExceptionFlag) fatClause->GetFlags()); smallClause->SetTryOffset(fatClause->GetTryOffset()); smallClause->SetTryLength(fatClause->GetTryLength()); smallClause->SetHandlerOffset(fatClause->GetHandlerOffset()); smallClause->SetHandlerLength(fatClause->GetHandlerLength()); smallClause->SetClassToken(fatClause->GetClassToken()); } if (i >= ehCount) { // if actually got through all the clauses and they are small enough EHSect->Kind = CorILMethod_Sect_EHTable; if (moreSections) EHSect->Kind |= CorILMethod_Sect_MoreSects; EHSect->DataSize = (BYTE) EHSect->Size(ehCount); EHSect->Reserved = 0; assert(EHSect->DataSize == EHSect->Size(ehCount)); // make sure didn't overflow outBuff = (BYTE*) &EHSect->Clauses[ehCount]; // Set the offsets for the exception type tokens. if (ehTypeOffsets) { for (i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_SMALL* smallClause = (COR_ILMETHOD_SECT_EH_CLAUSE_SMALL*)&EHSect->Clauses[i]; if (smallClause->GetFlags() == COR_ILEXCEPTION_CLAUSE_NONE) { assert(! IsNilToken(smallClause->GetClassToken())); ehTypeOffsets[i] = (ULONG)((BYTE *)&smallClause->ClassToken - origBuff); } } } return(size); } } // either total size too big or one of constituent elements too big (eg. offset or length) COR_ILMETHOD_SECT_EH_FAT* EHSect = (COR_ILMETHOD_SECT_EH_FAT*) outBuff; EHSect->SetKind(CorILMethod_Sect_EHTable | CorILMethod_Sect_FatFormat); if (moreSections) EHSect->SetKind(EHSect->GetKind() | CorILMethod_Sect_MoreSects); EHSect->SetDataSize(EHSect->Size(ehCount)); memcpy(EHSect->Clauses, clauses, ehCount * sizeof(COR_ILMETHOD_SECT_EH_CLAUSE_FAT)); outBuff = (BYTE*) &EHSect->Clauses[ehCount]; assert(&origBuff[size] == outBuff); // Set the offsets for the exception type tokens. if (ehTypeOffsets) { for (unsigned int i = 0; i < ehCount; i++) { COR_ILMETHOD_SECT_EH_CLAUSE_FAT* fatClause = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)&EHSect->Clauses[i]; if (fatClause->GetFlags() == COR_ILEXCEPTION_CLAUSE_NONE) { assert(! IsNilToken(fatClause->GetClassToken())); ehTypeOffsets[i] = (ULONG)((BYTE *)&fatClause->ClassToken - origBuff); } } } return(size); } } // extern "C" ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corhlpr.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** Corhlpr.h - ** ** ** *****************************************************************************/ #ifndef __CORHLPR_H__ #define __CORHLPR_H__ #if defined(_MSC_VER) && defined(HOST_X86) && !defined(FPO_ON) #pragma optimize("y", on) // Small critical routines, don't put in EBP frame #define FPO_ON 1 #define CORHLPR_TURNED_FPO_ON 1 #endif #include #include "cor.h" #include "corhdr.h" #include "corerror.h" #include "unreachable.h" // This header is consumed both within the runtime and externally. In the former // case we need to wrap memory allocations, in the latter there is no // infrastructure to support this. Detect which way we're building and provide a // very simple abstraction layer (handles allocating bytes only). #ifdef _BLD_CLR #include "new.hpp" #define NEW_NOTHROW(_bytes) new (nothrow) BYTE[_bytes] #define NEW_THROWS(_bytes) new BYTE[_bytes] void DECLSPEC_NORETURN ThrowOutOfMemory(); inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() { ThrowOutOfMemory(); } #else #define NEW_NOTHROW(_bytes) new BYTE[_bytes] #define NEW_THROWS(_bytes) __CorHlprNewThrows(_bytes) static inline void DECLSPEC_NORETURN __CorHlprThrowOOM() { RaiseException(STATUS_NO_MEMORY, 0, 0, NULL); __UNREACHABLE(); } static inline BYTE *__CorHlprNewThrows(size_t bytes) { BYTE *pbMemory = new BYTE[bytes]; if (pbMemory == NULL) __CorHlprThrowOOM(); return pbMemory; } inline void DECLSPEC_NORETURN THROW_OUT_OF_MEMORY() { __CorHlprThrowOOM(); } #endif //***************************************************************************** // There are a set of macros commonly used in the helpers which you will want // to override to get richer behavior. The following defines what is needed // if you chose not to do the extra work. //***************************************************************************** #ifndef IfFailGoto #define IfFailGoto(EXPR, LABEL) \ do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0) #endif #ifndef IfFailGo #define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit) #endif #ifndef IfFailRet #define IfFailRet(EXPR) do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0) #endif #ifndef IfNullRet #define IfNullRet(EXPR) do { if ((EXPR) == NULL){ return (E_OUTOFMEMORY); } } while (0) #endif #if !BIGENDIAN #define VAL16(x) x #define VAL32(x) x #endif //***************************************************************************** // //***** Macro to assist with cleaning up local static variables // //***************************************************************************** #define CHECK_LOCAL_STATIC_VAR(x) \ x \ //***************************************************************************** // //***** Utility helpers // //***************************************************************************** #define MAX_CLASSNAME_LENGTH 1024 //***************************************************************************** // //***** Signature helpers // //***************************************************************************** inline bool isCallConv(unsigned sigByte, CorCallingConvention conv) { return ((sigByte & IMAGE_CEE_CS_CALLCONV_MASK) == (unsigned) conv); } //***************************************************************************** // //***** File format helper classes // //***************************************************************************** //***************************************************************************** typedef struct tagCOR_ILMETHOD_SECT_SMALL : IMAGE_COR_ILMETHOD_SECT_SMALL { //Data follows const BYTE* Data() const { return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_SMALL)); } bool IsSmall() const { return (Kind & CorILMethod_Sect_FatFormat) == 0; } bool More() const { return (Kind & CorILMethod_Sect_MoreSects) != 0; } } COR_ILMETHOD_SECT_SMALL; /************************************/ /* NOTE this structure must be DWORD aligned!! */ typedef struct tagCOR_ILMETHOD_SECT_FAT : IMAGE_COR_ILMETHOD_SECT_FAT { //Data follows const BYTE* Data() const { return(((const BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_SECT_FAT)); } //Endian-safe wrappers unsigned GetKind() const { /* return Kind; */ return *(BYTE*)this; } void SetKind(unsigned kind) { /* Kind = kind; */ *(BYTE*)this = (BYTE)kind; } unsigned GetDataSize() const { /* return DataSize; */ BYTE* p = (BYTE*)this; return ((unsigned)*(p+1)) | (((unsigned)*(p+2)) << 8) | (((unsigned)*(p+3)) << 16); } void SetDataSize(unsigned datasize) { /* DataSize = dataSize; */ BYTE* p = (BYTE*)this; *(p+1) = (BYTE)(datasize); *(p+2) = (BYTE)(datasize >> 8); *(p+3) = (BYTE)(datasize >> 16); } } COR_ILMETHOD_SECT_FAT; typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_FAT : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT { //Endian-safe wrappers CorExceptionFlag GetFlags() const { return (CorExceptionFlag)VAL32((unsigned)Flags); } void SetFlags(CorExceptionFlag flags) { Flags = (CorExceptionFlag)VAL32((unsigned)flags); } DWORD GetTryOffset() const { return VAL32(TryOffset); } void SetTryOffset(DWORD Offset) { TryOffset = VAL32(Offset); } DWORD GetTryLength() const { return VAL32(TryLength); } void SetTryLength(DWORD Length) { TryLength = VAL32(Length); } DWORD GetHandlerOffset() const { return VAL32(HandlerOffset); } void SetHandlerOffset(DWORD Offset) { HandlerOffset = VAL32(Offset); } DWORD GetHandlerLength() const { return VAL32(HandlerLength); } void SetHandlerLength(DWORD Length) { HandlerLength = VAL32(Length); } DWORD GetClassToken() const { return VAL32(ClassToken); } void SetClassToken(DWORD tok) { ClassToken = VAL32(tok); } DWORD GetFilterOffset() const { return VAL32(FilterOffset); } void SetFilterOffset(DWORD offset) { FilterOffset = VAL32(offset); } } COR_ILMETHOD_SECT_EH_CLAUSE_FAT; //***************************************************************************** struct COR_ILMETHOD_SECT_EH_FAT : public COR_ILMETHOD_SECT_FAT { static unsigned Size(unsigned ehCount) { return (sizeof(COR_ILMETHOD_SECT_EH_FAT) + sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT) * (ehCount-1)); } IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT Clauses[1]; // actually variable size }; typedef struct tagCOR_ILMETHOD_SECT_EH_CLAUSE_SMALL : public IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL { //Endian-safe wrappers CorExceptionFlag GetFlags() const { return (CorExceptionFlag)VAL16((SHORT)Flags); } void SetFlags(CorExceptionFlag flags) { Flags = (CorExceptionFlag)VAL16((SHORT)flags); } DWORD GetTryOffset() const { return VAL16(TryOffset); } void SetTryOffset(DWORD Offset) { assert((Offset & ~0xffff) == 0); TryOffset = VAL16(Offset); } DWORD GetTryLength() const { return TryLength; } void SetTryLength(DWORD Length) { assert((Length & ~0xff) == 0); TryLength = Length; } DWORD GetHandlerOffset() const { return VAL16(HandlerOffset); } void SetHandlerOffset(DWORD Offset) { assert((Offset & ~0xffff) == 0); HandlerOffset = VAL16(Offset); } DWORD GetHandlerLength() const { return HandlerLength; } void SetHandlerLength(DWORD Length) { assert((Length & ~0xff) == 0); HandlerLength = Length; } DWORD GetClassToken() const { return VAL32(ClassToken); } void SetClassToken(DWORD tok) { ClassToken = VAL32(tok); } DWORD GetFilterOffset() const { return VAL32(FilterOffset); } void SetFilterOffset(DWORD offset) { FilterOffset = VAL32(offset); } } COR_ILMETHOD_SECT_EH_CLAUSE_SMALL; //***************************************************************************** struct COR_ILMETHOD_SECT_EH_SMALL : public COR_ILMETHOD_SECT_SMALL { static unsigned Size(unsigned ehCount) { return (sizeof(COR_ILMETHOD_SECT_EH_SMALL) + sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL) * (ehCount-1)); } WORD Reserved; // alignment padding IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL Clauses[1]; // actually variable size }; /************************************/ /* NOTE this structure must be DWORD aligned!! */ struct COR_ILMETHOD_SECT { bool More() const { return((AsSmall()->Kind & CorILMethod_Sect_MoreSects) != 0); } CorILMethodSect Kind() const { return((CorILMethodSect) (AsSmall()->Kind & CorILMethod_Sect_KindMask)); } const COR_ILMETHOD_SECT* Next() const { if (!More()) return(0); return ((COR_ILMETHOD_SECT*)Align(((BYTE *)this) + DataSize())); } const BYTE* Data() const { if (IsFat()) return(AsFat()->Data()); return(AsSmall()->Data()); } unsigned DataSize() const { if (Kind() == CorILMethod_Sect_EHTable) { // VB and MC++ shipped with bug where they have not accounted for size of COR_ILMETHOD_SECT_EH_XXX // in DataSize. To avoid breaking these images, we will align the size of EH sections up. This works // because IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_XXX is bigger than COR_ILMETHOD_SECT_EH_XXX // (see VSWhidbey #99031 and related bugs for details). if (IsFat()) return Fat.Size(Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)); else return Small.Size(Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL)); } else { if (IsFat()) return(AsFat()->GetDataSize()); return(AsSmall()->DataSize); } } friend struct COR_ILMETHOD; friend struct tagCOR_ILMETHOD_FAT; friend struct tagCOR_ILMETHOD_TINY; bool IsFat() const { return((AsSmall()->Kind & CorILMethod_Sect_FatFormat) != 0); } static const void* Align(const void* p) { return((void*) ((((UINT_PTR) p) + 3) & ~3)); } protected: const COR_ILMETHOD_SECT_FAT* AsFat() const { return((COR_ILMETHOD_SECT_FAT*) this); } const COR_ILMETHOD_SECT_SMALL* AsSmall() const { return((COR_ILMETHOD_SECT_SMALL*) this); } public: // The body is either a COR_ILMETHOD_SECT_SMALL or COR_ILMETHOD_SECT_FAT // (as indicated by the CorILMethod_Sect_FatFormat bit union { COR_ILMETHOD_SECT_EH_SMALL Small; COR_ILMETHOD_SECT_EH_FAT Fat; }; }; /***********************************/ // exported functions (implementation in Format\Format.cpp: extern "C" { IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* __stdcall SectEH_EHClause(void *pSectEH, unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff); // compute the size of the section (best format) // codeSize is the size of the method // deprecated unsigned __stdcall SectEH_SizeWithCode(unsigned ehCount, unsigned codeSize); // will return worse-case size and then Emit will return actual size unsigned __stdcall SectEH_SizeWorst(unsigned ehCount); // will return exact size which will match the size returned by Emit unsigned __stdcall SectEH_SizeExact(unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses); // emit the section (best format); unsigned __stdcall SectEH_Emit(unsigned size, unsigned ehCount, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, BOOL moreSections, BYTE* outBuff, ULONG* ehTypeOffsets = 0); } // extern "C" struct COR_ILMETHOD_SECT_EH : public COR_ILMETHOD_SECT { unsigned EHCount() const { return (unsigned)(IsFat() ? (Fat.GetDataSize() / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)) : (Small.DataSize / sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_SMALL))); } // return one clause in its fat form. Use 'buff' if needed const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* EHClause(unsigned idx, IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* buff) const { return SectEH_EHClause((void *)this, idx, buff); }; // compute the size of the section (best format) // codeSize is the size of the method // deprecated unsigned static Size(unsigned ehCount, unsigned codeSize) { return SectEH_SizeWithCode(ehCount, codeSize); }; // will return worse-case size and then Emit will return actual size unsigned static Size(unsigned ehCount) { return SectEH_SizeWorst(ehCount); }; // will return exact size which will match the size returned by Emit unsigned static Size(unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses) { return SectEH_SizeExact(ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses); }; // emit the section (best format); unsigned static Emit(unsigned size, unsigned ehCount, const IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT* clauses, bool moreSections, BYTE* outBuff, ULONG* ehTypeOffsets = 0) { return SectEH_Emit(size, ehCount, (IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)clauses, moreSections, outBuff, ehTypeOffsets); }; }; /***************************************************************************/ /* Used when the method is tiny (< 64 bytes), and there are no local vars */ typedef struct tagCOR_ILMETHOD_TINY : IMAGE_COR_ILMETHOD_TINY { bool IsTiny() const { return((Flags_CodeSize & (CorILMethod_FormatMask >> 1)) == CorILMethod_TinyFormat); } unsigned GetCodeSize() const { return(((unsigned) Flags_CodeSize) >> (CorILMethod_FormatShift-1)); } unsigned GetMaxStack() const { return(8); } BYTE* GetCode() const { return(((BYTE*) this) + sizeof(struct tagCOR_ILMETHOD_TINY)); } DWORD GetLocalVarSigTok() const { return(0); } COR_ILMETHOD_SECT* GetSect() const { return(0); } } COR_ILMETHOD_TINY; /************************************/ // This structure is the 'fat' layout, where no compression is attempted. // Note that this structure can be added on at the end, thus making it extensible typedef struct tagCOR_ILMETHOD_FAT : IMAGE_COR_ILMETHOD_FAT { //Endian-safe wrappers unsigned GetSize() const { /* return Size; */ BYTE* p = (BYTE*)this; return *(p+1) >> 4; } void SetSize(unsigned size) { /* Size = size; */ BYTE* p = (BYTE*)this; *(p+1) = (BYTE)((*(p+1) & 0x0F) | (size << 4)); } unsigned GetFlags() const { /* return Flags; */ BYTE* p = (BYTE*)this; return ((unsigned)*(p+0)) | (( ((unsigned)*(p+1)) & 0x0F) << 8); } void SetFlags(unsigned flags) { /* flags = Flags; */ BYTE* p = (BYTE*)this; *p = (BYTE)flags; *(p+1) = (BYTE)((*(p+1) & 0xF0) | ((flags >> 8) & 0x0F)); } bool IsFat() const { /* return((IMAGE_COR_ILMETHOD_FAT::GetFlags() & CorILMethod_FormatMask) == CorILMethod_FatFormat); */ return (*(BYTE*)this & CorILMethod_FormatMask) == CorILMethod_FatFormat; } unsigned GetMaxStack() const { /* return MaxStack; */ return VAL16(*(USHORT*)((BYTE*)this+2)); } void SetMaxStack(unsigned maxStack) { /* MaxStack = maxStack; */ *(USHORT*)((BYTE*)this+2) = VAL16((USHORT)maxStack); } unsigned GetCodeSize() const { return VAL32(CodeSize); } void SetCodeSize(DWORD Size) { CodeSize = VAL32(Size); } mdToken GetLocalVarSigTok() const { return VAL32(LocalVarSigTok); } void SetLocalVarSigTok(mdSignature tok) { LocalVarSigTok = VAL32(tok); } BYTE* GetCode() const { return(((BYTE*) this) + 4*GetSize()); } bool More() const { // return (GetFlags() & CorILMethod_MoreSects) != 0; return (*(BYTE*)this & CorILMethod_MoreSects) != 0; } const COR_ILMETHOD_SECT* GetSect() const { if (!More()) return (0); return(((COR_ILMETHOD_SECT*) COR_ILMETHOD_SECT::Align(GetCode() + GetCodeSize()))); } } COR_ILMETHOD_FAT; extern "C" { /************************************/ // exported functions (impl. Format\Format.cpp) unsigned __stdcall IlmethodSize(COR_ILMETHOD_FAT* header, BOOL MoreSections); // emit the header (bestFormat) return amount emitted unsigned __stdcall IlmethodEmit(unsigned size, COR_ILMETHOD_FAT* header, BOOL moreSections, BYTE* outBuff); } struct COR_ILMETHOD { // a COR_ILMETHOD header should not be decoded by hand. Instead us // COR_ILMETHOD_DECODER to decode it. friend class COR_ILMETHOD_DECODER; // compute the size of the header (best format) unsigned static Size(const COR_ILMETHOD_FAT* header, bool MoreSections) { return IlmethodSize((COR_ILMETHOD_FAT*)header,MoreSections); }; // emit the header (bestFormat) return amount emitted unsigned static Emit(unsigned size, const COR_ILMETHOD_FAT* header, bool moreSections, BYTE* outBuff) { return IlmethodEmit(size, (COR_ILMETHOD_FAT*)header, moreSections, outBuff); }; //private: union { COR_ILMETHOD_TINY Tiny; COR_ILMETHOD_FAT Fat; }; // Code follows the Header, then immedately after the code comes // any sections (COR_ILMETHOD_SECT). }; extern "C" { /***************************************************************************/ /* COR_ILMETHOD_DECODER is the only way functions internal to the EE should fetch data from a COR_ILMETHOD. This way any dependency on the file format (and the multiple ways of encoding the header) is centralized to the COR_ILMETHOD_DECODER constructor) */ void __stdcall DecoderInit(void * pThis, COR_ILMETHOD* header); int __stdcall DecoderGetOnDiskSize(void * pThis, COR_ILMETHOD* header); } // extern "C" class COR_ILMETHOD_DECODER : public COR_ILMETHOD_FAT { public: // This returns an uninitialized decoder, suitable for placement new but nothing // else. Use with caution. COR_ILMETHOD_DECODER() {} // Typically the ONLY way you should access COR_ILMETHOD is through // this constructor so format changes are easier. COR_ILMETHOD_DECODER(const COR_ILMETHOD* header) { DecoderInit(this,(COR_ILMETHOD*)header); }; // The above variant of the constructor can not do a 'complete' job, because // it can not look up the local variable signature meta-data token. // This method should be used when you have access to the Meta data API // If the construction fails, the 'Code' field is set to 0 enum DecoderStatus {SUCCESS, FORMAT_ERROR, VERIFICATION_ERROR}; // If we want the decoder to verify the that local signature is OK we // will pass a non-NULL value for wbStatus // // When using LazyInit we want ask that the local signature be verified // But if we fail verification we still need access to the 'Code' field // Because we may be able to demand SkipVerification and thus it was OK // to have had a verification error. COR_ILMETHOD_DECODER(COR_ILMETHOD* header, void *pInternalImport, DecoderStatus* wbStatus); unsigned EHCount() const { return (EH != 0) ? EH->EHCount() : 0; } unsigned GetHeaderSize() const { return GetCodeSize() + ((EH != 0) ? EH->DataSize() : 0); } // returns total size of method for use in copying int GetOnDiskSize(const COR_ILMETHOD* header) { return DecoderGetOnDiskSize(this,(COR_ILMETHOD*)header); } // Flags these are available because we inherit COR_ILMETHOD_FAT // MaxStack // CodeSize const BYTE * Code; PCCOR_SIGNATURE LocalVarSig; // pointer to signature blob, or 0 if none DWORD cbLocalVarSig; // size of dignature blob, or 0 if none const COR_ILMETHOD_SECT_EH * EH; // eh table if any 0 if none const COR_ILMETHOD_SECT * Sect; // additional sections 0 if none }; // class COR_ILMETHOD_DECODER #if defined(CORHLPR_TURNED_FPO_ON) #pragma optimize("", on) // Go back to command line default optimizations #undef CORHLPR_TURNED_FPO_ON #undef FPO_ON #endif #endif // __CORHLPR_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corhlprpriv.cpp ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /**************************************************************************** ** ** ** Corhlprpriv.cpp - signature helpers. ** ** ** ****************************************************************************/ #ifndef SOS_INCLUDE #ifdef _BLD_CLR #include "utilcode.h" #endif #include "corhlprpriv.h" #include /************************************************************************************* * * implementation of CQuickMemoryBase * *************************************************************************************/ template HRESULT CQuickMemoryBase::ReSizeNoThrow(SIZE_T iItems) { #ifdef _BLD_CLR #ifdef _DEBUG #ifndef DACCESS_COMPILE // Exercise heap for OOM-fault injection purposes // But we can't do this if current thread suspends EE if (!IsSuspendEEThread ()) { BYTE *pTmp = NEW_NOTHROW(iItems); if (!pTmp) { return E_OUTOFMEMORY; } delete [] pTmp; } #endif #endif #endif BYTE *pbBuffNew; if (iItems <= cbTotal) { iSize = iItems; return NOERROR; } #ifdef _BLD_CLR #ifndef DACCESS_COMPILE // not allowed to do allocation if current thread suspends EE if (IsSuspendEEThread ()) return E_OUTOFMEMORY; #endif #endif pbBuffNew = NEW_NOTHROW(iItems + INCREMENT); if (!pbBuffNew) return E_OUTOFMEMORY; if (pbBuff) { memcpy(pbBuffNew, pbBuff, cbTotal); delete [] pbBuff; } else { _ASSERTE(cbTotal == SIZE); memcpy(pbBuffNew, rgData, cbTotal); } cbTotal = iItems + INCREMENT; iSize = iItems; pbBuff = pbBuffNew; return NOERROR; } /************************************************************************************* * * get number of bytes consumed by one argument/return type * *************************************************************************************/ #define CHECK_REMAINDER if(cbTotal >= cbTotalMax){hr=E_FAIL; goto ErrExit;} HRESULT _CountBytesOfOneArg( PCCOR_SIGNATURE pbSig, ULONG *pcbTotal) // Initially, *pcbTotal contains the remaining size of the sig blob { ULONG cb; ULONG cbTotal=0; ULONG cbTotalMax; CorElementType ulElementType; ULONG ulData; ULONG ulTemp; int iData; mdToken tk; ULONG cArg; ULONG callingconv; ULONG cArgsIndex; HRESULT hr = NOERROR; if(pcbTotal==NULL) return E_FAIL; cbTotalMax = *pcbTotal; CHECK_REMAINDER; cbTotal = CorSigUncompressElementType(pbSig, &ulElementType); while (CorIsModifierElementType((CorElementType) ulElementType)) { CHECK_REMAINDER; cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType); } switch (ulElementType) { case ELEMENT_TYPE_GENERICINST: // skip over generic type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; // skip over number of parameters CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &cArg); // loop through type parameters for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) { CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; } break; case ELEMENT_TYPE_SZARRAY: case 0x1e /* obsolete */: // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; break; case ELEMENT_TYPE_FNPTR: CHECK_REMAINDER; cbTotal += CorSigUncompressData (&pbSig[cbTotal], &callingconv); // remember number of bytes to represent the arg counts CHECK_REMAINDER; cbTotal += CorSigUncompressData (&pbSig[cbTotal], &cArg); // how many bytes to represent the return type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); cbTotal += cb; // loop through argument for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) { CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); cbTotal += cb; } break; case ELEMENT_TYPE_ARRAY: // syntax : ARRAY BaseType [i size_1... size_i] [j lowerbound_1 ... lowerbound_j] // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; // Parse for the rank CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); // if rank == 0, we are done if (ulData == 0) break; // any size of dimension specified? CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); while (ulData--) { CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulTemp); } // any lower bound specified? CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); while (ulData--) { CHECK_REMAINDER; cbTotal += CorSigUncompressSignedInt(&pbSig[cbTotal], &iData); } break; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: // count the bytes for the token compression CHECK_REMAINDER; cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk); if ( ulElementType == ELEMENT_TYPE_CMOD_REQD || ulElementType == ELEMENT_TYPE_CMOD_OPT) { // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; } break; default: break; } *pcbTotal = cbTotal; ErrExit: return hr; } #undef CHECK_REMAINDER //***************************************************************************** // copy fixed part of VarArg signature to a buffer //***************************************************************************** HRESULT _GetFixedSigOfVarArg( // S_OK or error. PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob of COM+ method signature ULONG cbSigBlob, // [IN] size of signature CQuickBytes *pqbSig, // [OUT] output buffer for fixed part of VarArg Signature ULONG *pcbSigBlob) // [OUT] number of bytes written to the above output buffer { HRESULT hr = NOERROR; ULONG cbCalling; ULONG cbTyArgsNumber = 0; // number of bytes to store the type arg count (generics only) ULONG cbArgsNumber; // number of bytes to store the original arg count ULONG cbArgsNumberTemp; // number of bytes to store the fixed arg count ULONG cbTotal = 0; // total of number bytes for return type + all fixed arguments ULONG cbCur = 0; // index through the pvSigBlob ULONG cb; ULONG cArg; ULONG cTyArg; ULONG callingconv; ULONG cArgsIndex; CorElementType ulElementType; BYTE *pbSig; _ASSERTE (pvSigBlob && pcbSigBlob); // remember the number of bytes to represent the calling convention cbCalling = CorSigUncompressData (pvSigBlob, &callingconv); if (cbCalling == ((ULONG)(-1))) { return E_INVALIDARG; } _ASSERTE (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_VARARG)); cbCur += cbCalling; if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC) { cbTyArgsNumber = CorSigUncompressData(&pvSigBlob[cbCur], &cTyArg); if (cbTyArgsNumber == ((ULONG)(-1))) { return E_INVALIDARG; } cbCur += cbTyArgsNumber; } // remember number of bytes to represent the arg counts cbArgsNumber= CorSigUncompressData (&pvSigBlob[cbCur], &cArg); if (cbArgsNumber == ((ULONG)(-1))) { return E_INVALIDARG; } cbCur += cbArgsNumber; // how many bytes to represent the return type cb = cbSigBlob-cbCur; IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) ); cbCur += cb; cbTotal += cb; // loop through argument until we found ELEMENT_TYPE_SENTINEL or run // out of arguments for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) { _ASSERTE(cbCur < cbSigBlob); // peak the outer most ELEMENT_TYPE_* CorSigUncompressElementType (&pvSigBlob[cbCur], &ulElementType); if (ulElementType == ELEMENT_TYPE_SENTINEL) break; cb = cbSigBlob-cbCur; IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) ); cbTotal += cb; cbCur += cb; } cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &cArg); // now cbCalling : the number of bytes needed to store the calling convention // cbArgNumberTemp : number of bytes to store the fixed arg count // cbTotal : the number of bytes to store the ret and fixed arguments *pcbSigBlob = cbCalling + cbArgsNumberTemp + cbTotal; // resize the buffer IfFailGo( pqbSig->ReSizeNoThrow(*pcbSigBlob) ); pbSig = (BYTE *)pqbSig->Ptr(); // copy over the calling convention cb = CorSigCompressData(callingconv, pbSig); // copy over the fixed arg count cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &pbSig[cb]); // copy over the fixed args + ret type memcpy(&pbSig[cb + cbArgsNumberTemp], &pvSigBlob[cbCalling + cbArgsNumber], cbTotal); ErrExit: return hr; } #endif // !SOS_INCLUDE ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corhlprpriv.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** Corhlprpriv.h - ** ** ** *****************************************************************************/ #ifndef __CORHLPRPRIV_H__ #define __CORHLPRPRIV_H__ #include "corhlpr.h" #include "fstring.h" #if defined(_MSC_VER) && defined(HOST_X86) #pragma optimize("y", on) // If routines don't get inlined, don't pay the EBP frame penalty #endif //***************************************************************************** // //***** Utility helpers // //***************************************************************************** #ifndef SOS_INCLUDE //***************************************************************************** // // **** CQuickBytes // This helper class is useful for cases where 90% of the time you allocate 512 // or less bytes for a data structure. This class contains a 512 byte buffer. // Alloc() will return a pointer to this buffer if your allocation is small // enough, otherwise it asks the heap for a larger buffer which is freed for // you. No mutex locking is required for the small allocation case, making the // code run faster, less heap fragmentation, etc... Each instance will allocate // 520 bytes, so use accordinly. // //***************************************************************************** namespace NSQuickBytesHelper { template struct _AllocBytes; template <> struct _AllocBytes { static BYTE *Invoke(SIZE_T iItems) { return NEW_THROWS(iItems); } }; template <> struct _AllocBytes { static BYTE *Invoke(SIZE_T iItems) { return NEW_NOTHROW(iItems); } }; }; void DECLSPEC_NORETURN ThrowHR(HRESULT hr); template class CQuickMemoryBase { protected: template static ELEM_T Min(ELEM_T a, ELEM_T b) { return a < b ? a : b; } template static ELEM_T Max(ELEM_T a, ELEM_T b) { return a < b ? b : a; } // bGrow - indicates that this is a resize and that the original data // needs to be copied over. // bThrow - indicates whether or not memory allocations will throw. template void *_Alloc(SIZE_T iItems) { #if defined(_BLD_CLR) && defined(_DEBUG) { // Exercise heap for OOM-fault injection purposes BYTE * pb = NSQuickBytesHelper::_AllocBytes::Invoke(iItems); _ASSERTE(!bThrow || pb != NULL); // _AllocBytes would have thrown if bThrow == TRUE if (pb == NULL) return NULL; // bThrow == FALSE and we failed to allocate memory delete [] pb; // Success, delete allocated memory. } #endif if (iItems <= cbTotal) { // Fits within existing memory allocation iSize = iItems; } else if (iItems <= SIZE) { // Will fit in internal buffer. if (pbBuff == NULL) { // Any previous allocation is in the internal buffer and the new // allocation fits in the internal buffer, so just update the size. iSize = iItems; cbTotal = SIZE; } else { // There was a previous allocation, sitting in pbBuff if (bGrow) { // If growing, need to copy any existing data over. memcpy(&rgData[0], pbBuff, Min(cbTotal, SIZE)); } delete [] pbBuff; pbBuff = NULL; iSize = iItems; cbTotal = SIZE; } } else { // Need to allocate a new buffer SIZE_T cbTotalNew = iItems + (bGrow ? INCREMENT : 0); BYTE * pbBuffNew = NSQuickBytesHelper::_AllocBytes::Invoke(cbTotalNew); if (!bThrow && pbBuffNew == NULL) { // Allocation failed. Zero out structure. if (pbBuff != NULL) { // Delete old buffer delete [] pbBuff; } pbBuff = NULL; iSize = 0; cbTotal = 0; return NULL; } if (bGrow && cbTotal > 0) { // If growing, need to copy any existing data over. memcpy(pbBuffNew, (BYTE *)Ptr(), Min(cbTotal, cbTotalNew)); } if (pbBuff != NULL) { // Delete old pre-existing buffer delete [] pbBuff; pbBuff = NULL; } pbBuff = pbBuffNew; cbTotal = cbTotalNew; iSize = iItems; } return Ptr(); } public: void Init() { pbBuff = 0; iSize = 0; cbTotal = SIZE; } void Destroy() { if (pbBuff) { delete [] pbBuff; pbBuff = 0; } } void *AllocThrows(SIZE_T iItems) { return _Alloc(iItems); } void *AllocNoThrow(SIZE_T iItems) { return _Alloc(iItems); } void ReSizeThrows(SIZE_T iItems) { _Alloc(iItems); } #ifdef __GNUC__ // This makes sure that we will not get an undefined symbol // when building a release version of libcoreclr using LLVM/GCC. __attribute__((used)) #endif // __GNUC__ HRESULT ReSizeNoThrow(SIZE_T iItems); void Shrink(SIZE_T iItems) { _ASSERTE(iItems <= cbTotal); iSize = iItems; } operator PVOID() { return ((pbBuff) ? pbBuff : (PVOID)&rgData[0]); } void *Ptr() { return ((pbBuff) ? pbBuff : (PVOID)&rgData[0]); } const void *Ptr() const { return ((pbBuff) ? pbBuff : (PVOID)&rgData[0]); } SIZE_T Size() const { return (iSize); } SIZE_T MaxSize() const { return (cbTotal); } void Maximize() { iSize = cbTotal; } // Convert UTF8 string to UNICODE string, optimized for speed HRESULT ConvertUtf8_UnicodeNoThrow(const char * utf8str) { bool allAscii; DWORD length; HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); if (SUCCEEDED(hr)) { LPWSTR buffer = (LPWSTR) AllocNoThrow((length + 1) * sizeof(WCHAR)); if (buffer == NULL) { hr = E_OUTOFMEMORY; } else { hr = FString::Utf8_Unicode(utf8str, allAscii, buffer, length); } } return hr; } // Convert UTF8 string to UNICODE string, optimized for speed void ConvertUtf8_Unicode(const char * utf8str) { bool allAscii; DWORD length; HRESULT hr = FString::Utf8_Unicode_Length(utf8str, & allAscii, & length); if (SUCCEEDED(hr)) { LPWSTR buffer = (LPWSTR) AllocThrows((length + 1) * sizeof(WCHAR)); hr = FString::Utf8_Unicode(utf8str, allAscii, buffer, length); } if (FAILED(hr)) { ThrowHR(hr); } } // Convert UNICODE string to UTF8 string, optimized for speed void ConvertUnicode_Utf8(const WCHAR * pString) { bool allAscii; DWORD length; HRESULT hr = FString::Unicode_Utf8_Length(pString, & allAscii, & length); if (SUCCEEDED(hr)) { LPSTR buffer = (LPSTR) AllocThrows((length + 1) * sizeof(char)); hr = FString::Unicode_Utf8(pString, allAscii, buffer, length); } if (FAILED(hr)) { ThrowHR(hr); } } // Copy single byte string and hold it const char * SetStringNoThrow(const char * pStr, SIZE_T len) { LPSTR buffer = (LPSTR) AllocNoThrow(len + 1); if (buffer != NULL) { memcpy(buffer, pStr, len); buffer[len] = 0; } return buffer; } #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { // Assume that 'this' is enumerated, either explicitly // or because this class is embedded in another. DacEnumMemoryRegion(dac_cast(pbBuff), iSize); } #endif // DACCESS_COMPILE BYTE *pbBuff; SIZE_T iSize; // number of bytes used SIZE_T cbTotal; // total bytes allocated in the buffer // use UINT64 to enforce the alignment of the memory UINT64 rgData[(SIZE+sizeof(UINT64)-1)/sizeof(UINT64)]; }; // These should be multiples of 8 so that data can be naturally aligned. #define CQUICKBYTES_BASE_SIZE 512 #define CQUICKBYTES_INCREMENTAL_SIZE 128 class CQuickBytesBase : public CQuickMemoryBase { }; class CQuickBytes : public CQuickBytesBase { public: CQuickBytes() { Init(); } ~CQuickBytes() { Destroy(); } }; /* to be used as static variable - no constructor/destructor, assumes zero initialized memory */ class CQuickBytesStatic : public CQuickBytesBase { }; template class CQuickBytesSpecifySizeBase : public CQuickMemoryBase { }; template class CQuickBytesSpecifySize : public CQuickBytesSpecifySizeBase { public: CQuickBytesSpecifySize() { this->Init(); } ~CQuickBytesSpecifySize() { this->Destroy(); } }; /* to be used as static variable - no constructor/destructor, assumes zero initialized memory */ template class CQuickBytesSpecifySizeStatic : public CQuickBytesSpecifySizeBase { }; template class CQuickArrayBase : public CQuickBytesBase { public: T* AllocThrows(SIZE_T iItems) { CheckOverflowThrows(iItems); return (T*)CQuickBytesBase::AllocThrows(iItems * sizeof(T)); } void ReSizeThrows(SIZE_T iItems) { CheckOverflowThrows(iItems); CQuickBytesBase::ReSizeThrows(iItems * sizeof(T)); } T* AllocNoThrow(SIZE_T iItems) { if (!CheckOverflowNoThrow(iItems)) { return NULL; } return (T*)CQuickBytesBase::AllocNoThrow(iItems * sizeof(T)); } HRESULT ReSizeNoThrow(SIZE_T iItems) { if (!CheckOverflowNoThrow(iItems)) { return E_OUTOFMEMORY; } return CQuickBytesBase::ReSizeNoThrow(iItems * sizeof(T)); } void Shrink(SIZE_T iItems) { CQuickBytesBase::Shrink(iItems * sizeof(T)); } T* Ptr() { return (T*) CQuickBytesBase::Ptr(); } const T* Ptr() const { return (T*) CQuickBytesBase::Ptr(); } SIZE_T Size() const { return CQuickBytesBase::Size() / sizeof(T); } SIZE_T MaxSize() const { return CQuickBytesBase::cbTotal / sizeof(T); } T& operator[] (SIZE_T ix) { _ASSERTE(ix < Size()); return *(Ptr() + ix); } const T& operator[] (SIZE_T ix) const { _ASSERTE(ix < Size()); return *(Ptr() + ix); } private: inline BOOL CheckOverflowNoThrow(SIZE_T iItems) { SIZE_T totalSize = iItems * sizeof(T); if (totalSize / sizeof(T) != iItems) { return FALSE; } return TRUE; } inline void CheckOverflowThrows(SIZE_T iItems) { if (!CheckOverflowNoThrow(iItems)) { THROW_OUT_OF_MEMORY(); } } }; template class CQuickArray : public CQuickArrayBase { public: CQuickArray() { this->Init(); } ~CQuickArray() { this->Destroy(); } }; // This is actually more of a stack with array access. Essentially, you can // only add elements through Push and remove them through Pop, but you can // access and modify any random element with the index operator. You cannot // access elements that have not been added. template class CQuickArrayList : protected CQuickArray { private: SIZE_T m_curSize; public: // Make these specific functions public. using CQuickArray::AllocThrows; using CQuickArray::ReSizeThrows; using CQuickArray::AllocNoThrow; using CQuickArray::ReSizeNoThrow; using CQuickArray::MaxSize; using CQuickArray::Ptr; CQuickArrayList() : m_curSize(0) { this->Init(); } ~CQuickArrayList() { this->Destroy(); } // Can only access values that have been pushed. T& operator[] (SIZE_T ix) { _ASSERTE(ix < m_curSize); return CQuickArray::operator[](ix); } // Can only access values that have been pushed. const T& operator[] (SIZE_T ix) const { _ASSERTE(ix < m_curSize); return CQuickArray::operator[](ix); } // THROWS: Resizes if necessary. void Push(const T & value) { // Resize if necessary - thows. if (m_curSize + 1 >= CQuickArray::Size()) ReSizeThrows((m_curSize + 1) * 2); // Append element to end of array. _ASSERTE(m_curSize + 1 < CQuickArray::Size()); SIZE_T ix = m_curSize++; (*this)[ix] = value; } // NOTHROW: Resizes if necessary. BOOL PushNoThrow(const T & value) { // Resize if necessary - nothow. if (m_curSize + 1 >= CQuickArray::Size()) { if (ReSizeNoThrow((m_curSize + 1) * 2) != NOERROR) return FALSE; } // Append element to end of array. _ASSERTE(m_curSize + 1 < CQuickArray::Size()); SIZE_T ix = m_curSize++; (*this)[ix] = value; return TRUE; } T Pop() { _ASSERTE(m_curSize > 0); T retval = (*this)[m_curSize - 1]; INDEBUG(ZeroMemory(&(this->Ptr()[m_curSize - 1]), sizeof(T));) --m_curSize; return retval; } SIZE_T Size() const { return m_curSize; } void Shrink() { CQuickArray::Shrink(m_curSize); } }; /* to be used as static variable - no constructor/destructor, assumes zero initialized memory */ template class CQuickArrayStatic : public CQuickArrayBase { }; typedef CQuickArrayBase CQuickWSTRBase; typedef CQuickArray CQuickWSTR; typedef CQuickArrayStatic CQuickWSTRStatic; typedef CQuickArrayBase CQuickSTRBase; typedef CQuickArray CQuickSTR; typedef CQuickArrayStatic CQuickSTRStatic; class RidBitmap { public: HRESULT InsertToken(mdToken token) { HRESULT hr = S_OK; mdToken rid = RidFromToken(token); SIZE_T index = rid / 8; BYTE bit = (BYTE)(1 << (rid % 8)); if (index >= buffer.Size()) { SIZE_T oldSize = buffer.Size(); SIZE_T newSize = index+1+oldSize/8; IfFailRet(buffer.ReSizeNoThrow(newSize)); memset(&buffer[oldSize], 0, newSize-oldSize); } buffer[index] |= bit; return hr; } bool IsTokenInBitmap(mdToken token) { mdToken rid = RidFromToken(token); SIZE_T index = rid / 8; BYTE bit = (BYTE)(1 << (rid % 8)); return ((index < buffer.Size()) && (buffer[index] & bit)); } void Reset() { if (buffer.Size()) { memset(&buffer[0], 0, buffer.Size()); } } private: CQuickArray buffer; }; //***************************************************************************** // //***** Signature helpers // //***************************************************************************** HRESULT _CountBytesOfOneArg( PCCOR_SIGNATURE pbSig, ULONG *pcbTotal); HRESULT _GetFixedSigOfVarArg( // S_OK or error. PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob of CLR signature ULONG cbSigBlob, // [IN] size of signature CQuickBytes *pqbSig, // [OUT] output buffer for fixed part of VarArg Signature ULONG *pcbSigBlob); // [OUT] number of bytes written to the above output buffer #endif //!SOS_INCLUDE #if defined(_MSC_VER) && defined(TARGET_X86) #pragma optimize("", on) // restore command line default optimizations #endif //--------------------------------------------------------------------------------------- // // Reads compressed integer from buffer pData, fills the result to *pnDataOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). // inline __checkReturn HRESULT CorSigUncompressData_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer DWORD * pnDataOut) // [OUT] Compressed integer read from the buffer { _ASSERTE(pData <= pDataEnd); HRESULT hr = S_OK; INT_PTR cbDataSize = pDataEnd - pData; if (cbDataSize > 4) { // Compressed integer cannot be bigger than 4 bytes cbDataSize = 4; } DWORD dwDataSize = (DWORD)cbDataSize; ULONG cbDataOutLength; IfFailRet(CorSigUncompressData( pData, dwDataSize, pnDataOut, &cbDataOutLength)); pData += cbDataOutLength; return hr; } // CorSigUncompressData_EndPtr //--------------------------------------------------------------------------------------- // // Reads CorElementType (1 byte) from buffer pData, fills the result to *pTypeOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). // inline __checkReturn HRESULT CorSigUncompressElementType_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer CorElementType * pTypeOut) // [OUT] ELEMENT_TYPE_* value read from the buffer { _ASSERTE(pData <= pDataEnd); // We don't expect pData > pDataEnd, but the runtime check doesn't cost much and it is more secure in // case caller has a bug if (pData >= pDataEnd) { // No data return META_E_BAD_SIGNATURE; } // Read 'type' as 1 byte *pTypeOut = (CorElementType)*pData; pData++; return S_OK; } // CorSigUncompressElementType_EndPtr //--------------------------------------------------------------------------------------- // // Reads pointer (4/8 bytes) from buffer pData, fills the result to *ppvPointerOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). // inline __checkReturn HRESULT CorSigUncompressPointer_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer void ** ppvPointerOut) // [OUT] Pointer value read from the buffer { _ASSERTE(pData <= pDataEnd); // We could just skip this check as pointers should be only in trusted (and therefore correct) // signatures and we check for that on the caller side, but it won't hurt to have this check and it will // make it easier to catch invalid signatures in trusted code (e.g. IL stubs, NGEN images, etc.) if (pData + sizeof(void *) > pDataEnd) { // Not enough data in the buffer _ASSERTE(!"This signature is invalid. Note that caller should check that it is not coming from untrusted source!"); return META_E_BAD_SIGNATURE; } *ppvPointerOut = *(void * UNALIGNED *)pData; pData += sizeof(void *); return S_OK; } // CorSigUncompressPointer_EndPtr //--------------------------------------------------------------------------------------- // // Reads compressed TypeDef/TypeRef/TypeSpec token, fills the result to *pnDataOut. Advances buffer pointer. // Doesn't read behind the end of the buffer (the end starts at pDataEnd). // inline __checkReturn HRESULT CorSigUncompressToken_EndPtr( PCCOR_SIGNATURE & pData, // [IN,OUT] Buffer PCCOR_SIGNATURE pDataEnd, // End of buffer mdToken * ptkTokenOut) // [OUT] Token read from the buffer { _ASSERTE(pData <= pDataEnd); HRESULT hr = S_OK; INT_PTR cbDataSize = pDataEnd - pData; if (cbDataSize > 4) { // Compressed token cannot be bigger than 4 bytes cbDataSize = 4; } DWORD dwDataSize = (DWORD)cbDataSize; uint32_t cbTokenOutLength; IfFailRet(CorSigUncompressToken( pData, dwDataSize, ptkTokenOut, &cbTokenOutLength)); pData += cbTokenOutLength; return hr; } // CorSigUncompressToken_EndPtr #endif // __CORHLPRPRIV_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corhost.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // //***************************************************************************** // CorHost.h // // Class factories are used by the pluming in COM to activate new objects. // This module contains the class factory code to instantiate the debugger // objects described in . // //***************************************************************************** #ifndef __CorHost__h__ #define __CorHost__h__ #include "windows.h" // worth to include before mscoree.h so we are guaranteed to pick few definitions #ifdef CreateSemaphore #undef CreateSemaphore #endif #include "mscoree.h" #include "clrinternal.h" #include "holder.h" #ifdef FEATURE_COMINTEROP #include "activation.h" // WinRT activation. #endif class AppDomain; class Assembly; class CorHost2 : ICLRRuntimeHost4 #ifndef TARGET_UNIX , public IPrivateManagedExceptionReporting /* This interface is for internal Watson testing only*/ #endif // TARGET_UNIX { friend struct _DacGlobals; public: CorHost2(); virtual ~CorHost2() {} // *** IUnknown methods *** STDMETHODIMP QueryInterface(REFIID riid, void** ppv); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); // *** ICorRuntimeHost methods *** #ifndef TARGET_UNIX // defined in IPrivateManagedExceptionReporting interface for internal Watson testing only STDMETHODIMP GetBucketParametersForCurrentException(BucketParameters *pParams); #endif // TARGET_UNIX // Starts the runtime. This is equivalent to CoInitializeCor(). STDMETHODIMP Start(); STDMETHODIMP Stop(); STDMETHODIMP ExecuteInAppDomain(DWORD dwAppDomainId, FExecuteInAppDomainCallback pCallback, void * cookie); // Class factory hook-up. static HRESULT CreateObject(REFIID riid, void **ppUnk); STDMETHODIMP STDMETHODCALLTYPE SetHostControl( IHostControl* pHostControl); STDMETHODIMP STDMETHODCALLTYPE GetCLRControl( ICLRControl** pCLRControl); STDMETHODIMP UnloadAppDomain(DWORD dwDomainId, BOOL fWaitUntilDone); STDMETHODIMP UnloadAppDomain2(DWORD dwDomainId, BOOL fWaitUntilDone, int *pLatchedExitCode); STDMETHODIMP GetCurrentAppDomainId(DWORD *pdwAppDomainId); STDMETHODIMP ExecuteApplication(LPCWSTR pwzAppFullName, DWORD dwManifestPaths, LPCWSTR *ppwzManifestPaths, DWORD dwActivationData, LPCWSTR *ppwzActivationData, int *pReturnValue); STDMETHODIMP ExecuteInDefaultAppDomain(LPCWSTR pwzAssemblyPath, LPCWSTR pwzTypeName, LPCWSTR pwzMethodName, LPCWSTR pwzArgument, DWORD *pReturnValue); // *** ICLRRuntimeHost2 methods *** STDMETHODIMP CreateAppDomainWithManager( LPCWSTR wszFriendlyName, DWORD dwSecurityFlags, LPCWSTR wszAppDomainManagerAssemblyName, LPCWSTR wszAppDomainManagerTypeName, int nProperties, LPCWSTR* pPropertyNames, LPCWSTR* pPropertyValues, DWORD* pAppDomainID); STDMETHODIMP CreateDelegate( DWORD appDomainID, LPCWSTR wszAssemblyName, LPCWSTR wszClassName, LPCWSTR wszMethodName, INT_PTR* fnPtr); STDMETHODIMP Authenticate(ULONGLONG authKey); STDMETHODIMP RegisterMacEHPort(); STDMETHODIMP SetStartupFlags(STARTUP_FLAGS flag); STDMETHODIMP DllGetActivationFactory( DWORD appDomainID, LPCWSTR wszTypeName, IActivationFactory ** factory); STDMETHODIMP ExecuteAssembly( DWORD dwAppDomainId, LPCWSTR pwzAssemblyPath, int argc, LPCWSTR* argv, DWORD* pReturnValue); static STARTUP_FLAGS GetStartupFlags(); static BOOL HasStarted() { return m_RefCount != 0; } private: LONG m_cRef; // COM ref count. // This flag indicates if this instance was the first to load and start CoreCLR BOOL m_fFirstToLoadCLR; // This flag will be used to ensure that a CoreCLR host can invoke Start/Stop in pairs only. BOOL m_fStarted; BOOL m_fAppDomainCreated; // this flag is used when an appdomain can only create a single appdomain // entrypoint helper to be wrapped in a filter to process unhandled exceptions VOID ExecuteMainInner(Assembly* pRootAssembly); static LONG m_RefCount; SVAL_DECL(STARTUP_FLAGS, m_dwStartupFlags); }; #endif // __CorHost__h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corimage.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // /*============================================================ ** ** CorImage.h ** ** IMAGEHLP routines so we can avoid early binding to that DLL. ** ===========================================================*/ #ifndef _CORIMAGE_H_ #define _CORIMAGE_H_ #include #ifdef __cplusplus extern "C" { #endif IMAGE_NT_HEADERS *Cor_RtlImageNtHeader(VOID *pvBase, ULONG FileLength); PIMAGE_SECTION_HEADER Cor_RtlImageRvaToSection(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG FileLength); PIMAGE_SECTION_HEADER Cor_RtlImageRvaRangeToSection(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG Range, ULONG FileLength); DWORD Cor_RtlImageRvaToOffset(PTR_IMAGE_NT_HEADERS NtHeaders, ULONG Rva, ULONG FileLength); PBYTE Cor_RtlImageRvaToVa(PTR_IMAGE_NT_HEADERS NtHeaders, PBYTE Base, ULONG Rva, ULONG FileLength); PBYTE Cor_RtlImageDirToVa(PTR_IMAGE_NT_HEADERS NtHeaders, PBYTE Base, UINT DirIndex, ULONG FileLength); PBYTE Cor_RtlImageRvaToVa32(PTR_IMAGE_NT_HEADERS32 NtHeaders, PBYTE Base, ULONG Rva, ULONG FileLength); PBYTE Cor_RtlImageRvaToVa64(PTR_IMAGE_NT_HEADERS64 NtHeaders, PBYTE Base, ULONG Rva, ULONG FileLength); #ifdef __cplusplus } #endif #endif // _CORIMAGE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corinfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // /*****************************************************************************\ * * * CorInfo.h - EE / Code generator interface * * * ******************************************************************************* * * This file exposes CLR runtime functionality. It can be used by compilers, * both Just-in-time and ahead-of-time, to generate native code which * executes in the runtime environment. ******************************************************************************* ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // // The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// #EEJitContractDetails The semantic contract between the EE and the JIT should be documented here It is incomplete, but as time goes on, that hopefully will change See file:../../doc/BookOfTheRuntime/JIT/JIT%20Design.doc for details on the JIT compiler. See code:EEStartup#TableOfContents for information on the runtime as a whole. ------------------------------------------------------------------------------- #Tokens The tokens in IL stream needs to be resolved to EE handles (CORINFO_CLASS/METHOD/FIELD_HANDLE) that the runtime operates with. ICorStaticInfo::resolveToken is the method that resolves the found in IL stream to set of EE handles (CORINFO_RESOLVED_TOKEN). All other APIs take resolved token as input. This design avoids redundant token resolutions. The token validation is done as part of token resolution. The JIT is not required to do explicit upfront token validation. ------------------------------------------------------------------------------- #ClassConstruction First of all class construction comes in two flavors precise and 'beforeFieldInit'. In C# you get the former if you declare an explicit class constructor method and the later if you declaratively initialize static fields. Precise class construction guarantees that the .cctor is run precisely before the first access to any method or field of the class. 'beforeFieldInit' semantics guarantees only that the .cctor will be run some time before the first static field access (note that calling methods (static or instance) or accessing instance fields does not cause .cctors to be run). Next you need to know that there are two kinds of code generation that can happen in the JIT: appdomain neutral and appdomain specialized. The difference between these two kinds of code is how statics are handled. For appdomain specific code, the address of a particular static variable is embedded in the code. This makes it usable only for one appdomain (since every appdomain gets a own copy of its statics). Appdomain neutral code calls a helper that looks up static variables off of a thread local variable. Thus the same code can be used by multiple appdomains in the same process. Generics also introduce a similar issue. Code for generic classes might be specialized for a particular set of type arguments, or it could use helpers to access data that depends on type parameters and thus be shared across several instantiations of the generic type. Thus there four cases * BeforeFieldInitCCtor - Unshared code. Cctors are only called when static fields are fetched. At the time the method that touches the static field is JITed (or fixed up in the case of NGENed code), the .cctor is called. * BeforeFieldInitCCtor - Shared code. Since the same code is used for multiple classes, the act of JITing the code can not be used as a hook. However, it is also the case that since the code is shared, it can not wire in a particular address for the static and thus needs to use a helper that looks up the correct address based on the thread ID. This helper does the .cctor check, and thus no additional cctor logic is needed. * PreciseCCtor - Unshared code. Any time a method is JITTed (or fixed up in the case of NGEN), a cctor check for the class of the method being JITTed is done. In addition the JIT inserts explicit checks before any static field accesses. Instance methods and fields do NOT have hooks because a .ctor method must be called before the instance can be created. * PreciseCctor - Shared code .cctor checks are placed in the prolog of every .ctor and static method. All methods that access static fields have an explicit .cctor check before use. Again instance methods don't have hooks because a .ctor would have to be called first. Technically speaking, however the optimization of avoiding checks on instance methods is flawed. It requires that a .ctor always precede a call to an instance methods. This break down when * A NULL is passed to an instance method. * A .ctor does not call its superclasses .ctor. This allows an instance to be created without necessarily calling all the .cctors of all the superclasses. A virtual call can then be made to a instance of a superclass without necessarily calling the superclass's .cctor. * The class is a value class (which exists without a .ctor being called) Nevertheless, the cost of plugging these holes is considered to high and the benefit is low. ---------------------------------------------------------------------- #ClassConstructionFlags Thus the JIT's cctor responsibilities require it to check with the EE on every static field access using initClass and before jitting any method to see if a .cctor check must be placed in the prolog. * CORINFO_FLG_BEFOREFIELDINIT indicate the class has beforeFieldInit semantics. The jit does not strictly need this information however, it is valuable in optimizing static field fetch helper calls. Helper call for classes with BeforeFieldInit semantics can be hoisted before other side effects where classes with precise .cctor semantics do not allow this optimization. Inlining also complicates things. Because the class could have precise semantics it is also required that the inlining of any constructor or static method must also do the initClass check. The inliner has the option of inserting any required runtime check or simply not inlining the function. ------------------------------------------------------------------------------- #StaticFields The first 4 options are mutually exclusive * CORINFO_FLG_HELPER If the field has this set, then the JIT must call getFieldHelper and call the returned helper with the object ref (for an instance field) and a fieldDesc. Note that this should be able to handle ANY field so to get a JIT up quickly, it has the option of using helper calls for all field access (and skip the complexity below). Note that for statics it is assumed that you will always ask for the ADDRESS helper and to the fetch in the JIT. * CORINFO_FLG_SHARED_HELPER This is currently only used for static fields. If this bit is set it means that the field is feched by a helper call that takes a module identifier (see getModuleDomainID) and a class identifier (see getClassDomainID) as arguments. The exact helper to call is determined by getSharedStaticBaseHelper. The return value is of this function is the base of all statics in the module. The offset from getFieldOffset must be added to this value to get the address of the field itself. (see also CORINFO_FLG_STATIC_IN_HEAP). * CORINFO_FLG_GENERICS_STATIC This is currently only used for static fields (of generic type). This function is intended to be called with a Generic handle as a argument (from embedGenericHandle). The exact helper to call is determined by getSharedStaticBaseHelper. The returned value is the base of all statics in the class. The offset from getFieldOffset must be added to this value to get the address of the (see also CORINFO_FLG_STATIC_IN_HEAP). * CORINFO_FLG_TLS This indicate that the static field is a Windows style Thread Local Static. (We also have managed thread local statics, which work through the HELPER. Support for this is considered legacy, and going forward, the EE should * This is a normal static field. Its address in memory is determined by getFieldAddress. (see also CORINFO_FLG_STATIC_IN_HEAP). This last field can modify any of the cases above except CORINFO_FLG_HELPER CORINFO_FLG_STATIC_IN_HEAP This is currently only used for static fields of value classes. If the field has this set then after computing what would normally be the field, what you actually get is a object pointer (that must be reported to the GC) to a boxed version of the value. Thus the actual field address is computed by addr = (*addr+sizeof(OBJECTREF)) Instance fields * CORINFO_FLG_HELPER This is used if the class is MarshalByRef, which means that the object might be a proxy to the real object in some other appdomain or process. If the field has this set, then the JIT must call getFieldHelper and call the returned helper with the object ref. If the helper returned is helpers that are for structures the args are as follows * CORINFO_HELP_GETFIELDSTRUCT - args are: retBuff, object, fieldDesc * CORINFO_HELP_SETFIELDSTRUCT - args are object fieldDesc value The other GET helpers take an object fieldDesc and return the value The other SET helpers take an object fieldDesc and value Note that unlike static fields there is no helper to take the address of a field because in general there is no address for proxies (LDFLDA is illegal on proxies). CORINFO_FLG_EnC This is to support adding new field for edit and continue. This field also indicates that a helper is needed to access this field. However this helper is always CORINFO_HELP_GETFIELDADDR, and this helper always takes the object and field handle and returns the address of the field. It is the JIT's responsibility to do the fetch or set. ------------------------------------------------------------------------------- TODO: Talk about initializing strutures before use ******************************************************************************* */ #ifndef _COR_INFO_H_ #define _COR_INFO_H_ #include "corhdr.h" #if !defined(_In_) // Minimum set of SAL annotations so that non Windows builds work #define _In_ #define _In_reads_(size) #define _Inout_updates_(size) #define _Out_ #define _Out_writes_(size) #define _Outptr_ #define _Outptr_opt_ #define _Outptr_opt_result_maybenull_ #define _Outptr_result_z_ #define _Outptr_result_buffer_(size) #define _Outptr_opt_result_buffer_(size) #endif #include "jiteeversionguid.h" #ifdef _MSC_VER typedef long JITINTERFACE_HRESULT; #else typedef int JITINTERFACE_HRESULT; #endif // _MSC_VER // For System V on the CLR type system number of registers to pass in and return a struct is the same. // The CLR type system allows only up to 2 eightbytes to be passed in registers. There is no SSEUP classification types. #define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS 2 #define CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_RETURN_IN_REGISTERS 2 #define CLR_SYSTEMV_MAX_STRUCT_BYTES_TO_PASS_IN_REGISTERS 16 // System V struct passing // The Classification types are described in the ABI spec at https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf enum SystemVClassificationType : uint8_t { SystemVClassificationTypeUnknown = 0, SystemVClassificationTypeStruct = 1, SystemVClassificationTypeNoClass = 2, SystemVClassificationTypeMemory = 3, SystemVClassificationTypeInteger = 4, SystemVClassificationTypeIntegerReference = 5, SystemVClassificationTypeIntegerByRef = 6, SystemVClassificationTypeSSE = 7, // SystemVClassificationTypeSSEUp = Unused, // Not supported by the CLR. // SystemVClassificationTypeX87 = Unused, // Not supported by the CLR. // SystemVClassificationTypeX87Up = Unused, // Not supported by the CLR. // SystemVClassificationTypeComplexX87 = Unused, // Not supported by the CLR. }; // Represents classification information for a struct. struct SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR { SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR() { Initialize(); } bool passedInRegisters; // Whether the struct is passable/passed (this includes struct returning) in registers. uint8_t eightByteCount; // Number of eightbytes for this struct. SystemVClassificationType eightByteClassifications[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS]; // The eightbytes type classification. uint8_t eightByteSizes[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS]; // The size of the eightbytes (an eightbyte could include padding. This represents the no padding size of the eightbyte). uint8_t eightByteOffsets[CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS]; // The start offset of the eightbytes (in bytes). // Members //------------------------------------------------------------------------ // CopyFrom: Copies a struct classification into this one. // // Arguments: // 'copyFrom' the struct classification to copy from. // void CopyFrom(const SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR& copyFrom) { passedInRegisters = copyFrom.passedInRegisters; eightByteCount = copyFrom.eightByteCount; for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++) { eightByteClassifications[i] = copyFrom.eightByteClassifications[i]; eightByteSizes[i] = copyFrom.eightByteSizes[i]; eightByteOffsets[i] = copyFrom.eightByteOffsets[i]; } } //------------------------------------------------------------------------ // IsIntegralSlot: Returns whether the eightbyte at slotIndex is of integral type. // // Arguments: // 'slotIndex' the slot number we are determining if it is of integral type. // // Return value: // returns true if we the eightbyte at index slotIndex is of integral type. // bool IsIntegralSlot(unsigned slotIndex) const { return ((eightByteClassifications[slotIndex] == SystemVClassificationTypeInteger) || (eightByteClassifications[slotIndex] == SystemVClassificationTypeIntegerReference) || (eightByteClassifications[slotIndex] == SystemVClassificationTypeIntegerByRef)); } //------------------------------------------------------------------------ // IsSseSlot: Returns whether the eightbyte at slotIndex is SSE type. // // Arguments: // 'slotIndex' the slot number we are determining if it is of SSE type. // // Return value: // returns true if we the eightbyte at index slotIndex is of SSE type. // // Follows the rules of the AMD64 System V ABI specification at https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf. // Please refer to it for definitions/examples. // bool IsSseSlot(unsigned slotIndex) const { return (eightByteClassifications[slotIndex] == SystemVClassificationTypeSSE); } private: void Initialize() { passedInRegisters = false; eightByteCount = 0; for (int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++) { eightByteClassifications[i] = SystemVClassificationTypeUnknown; eightByteSizes[i] = 0; eightByteOffsets[i] = 0; } } }; // StructFloadFieldInfoFlags: used on LoongArch64 architecture by `getLoongArch64PassStructInRegisterFlags` API // to convey struct argument passing information. // // `STRUCT_NO_FLOAT_FIELD` means structs are not passed using the float register(s). // // Otherwise, and only for structs with no more than two fields and a total struct size no larger // than two pointers: // // The lowest four bits denote the floating-point info: // bit 0: `1` means there is only one float or double field within the struct. // bit 1: `1` means only the first field is floating-point type. // bit 2: `1` means only the second field is floating-point type. // bit 3: `1` means the two fields are both floating-point type. // The bits[5:4] denoting whether the field size is 8-bytes: // bit 4: `1` means the first field's size is 8. // bit 5: `1` means the second field's size is 8. // // Note that bit 0 and 3 cannot both be set. enum StructFloatFieldInfoFlags { STRUCT_NO_FLOAT_FIELD = 0x0, STRUCT_FLOAT_FIELD_ONLY_ONE = 0x1, STRUCT_FLOAT_FIELD_ONLY_TWO = 0x8, STRUCT_FLOAT_FIELD_FIRST = 0x2, STRUCT_FLOAT_FIELD_SECOND = 0x4, STRUCT_FIRST_FIELD_SIZE_IS8 = 0x10, STRUCT_SECOND_FIELD_SIZE_IS8 = 0x20, STRUCT_FIRST_FIELD_DOUBLE = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FIRST_FIELD_SIZE_IS8), STRUCT_SECOND_FIELD_DOUBLE = (STRUCT_FLOAT_FIELD_SECOND | STRUCT_SECOND_FIELD_SIZE_IS8), STRUCT_FIELD_TWO_DOUBLES = (STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_SECOND_FIELD_SIZE_IS8 | STRUCT_FLOAT_FIELD_ONLY_TWO), STRUCT_MERGE_FIRST_SECOND = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO), STRUCT_MERGE_FIRST_SECOND_8 = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_SECOND_FIELD_SIZE_IS8), STRUCT_HAS_FLOAT_FIELDS_MASK = (STRUCT_FLOAT_FIELD_FIRST | STRUCT_FLOAT_FIELD_SECOND | STRUCT_FLOAT_FIELD_ONLY_TWO | STRUCT_FLOAT_FIELD_ONLY_ONE), STRUCT_HAS_8BYTES_FIELDS_MASK = (STRUCT_FIRST_FIELD_SIZE_IS8 | STRUCT_SECOND_FIELD_SIZE_IS8), }; #include "corinfoinstructionset.h" // CorInfoHelpFunc defines the set of helpers (accessed via the ICorDynamicInfo::getHelperFtn()) // These helpers can be called by native code which executes in the runtime. // Compilers can emit calls to these helpers. // // The signatures of the helpers are below (see RuntimeHelperArgumentCheck) enum CorInfoHelpFunc { CORINFO_HELP_UNDEF, // invalid value. This should never be used /* Arithmetic helpers */ CORINFO_HELP_DIV, // For the ARM 32-bit integer divide uses a helper call :-( CORINFO_HELP_MOD, CORINFO_HELP_UDIV, CORINFO_HELP_UMOD, CORINFO_HELP_LLSH, CORINFO_HELP_LRSH, CORINFO_HELP_LRSZ, CORINFO_HELP_LMUL, CORINFO_HELP_LMUL_OVF, CORINFO_HELP_ULMUL_OVF, CORINFO_HELP_LDIV, CORINFO_HELP_LMOD, CORINFO_HELP_ULDIV, CORINFO_HELP_ULMOD, CORINFO_HELP_LNG2DBL, // Convert a signed int64 to a double CORINFO_HELP_ULNG2DBL, // Convert a unsigned int64 to a double CORINFO_HELP_DBL2INT, CORINFO_HELP_DBL2INT_OVF, CORINFO_HELP_DBL2LNG, CORINFO_HELP_DBL2LNG_OVF, CORINFO_HELP_DBL2UINT, CORINFO_HELP_DBL2UINT_OVF, CORINFO_HELP_DBL2ULNG, CORINFO_HELP_DBL2ULNG_OVF, CORINFO_HELP_FLTREM, CORINFO_HELP_DBLREM, CORINFO_HELP_FLTROUND, CORINFO_HELP_DBLROUND, /* Allocating a new object. Always use ICorClassInfo::getNewHelper() to decide which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_NEWFAST, CORINFO_HELP_NEWSFAST, // allocator for small, non-finalizer, non-array object CORINFO_HELP_NEWSFAST_FINALIZE, // allocator for small, finalizable, non-array object CORINFO_HELP_NEWSFAST_ALIGN8, // allocator for small, non-finalizer, non-array object, 8 byte aligned CORINFO_HELP_NEWSFAST_ALIGN8_VC,// allocator for small, value class, 8 byte aligned CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, // allocator for small, finalizable, non-array object, 8 byte aligned CORINFO_HELP_NEW_MDARR,// multi-dim array helper (with or without lower bounds - dimensions passed in as unmanaged array) CORINFO_HELP_NEWARR_1_DIRECT, // helper for any one dimensional array creation CORINFO_HELP_NEWARR_1_OBJ, // optimized 1-D object arrays CORINFO_HELP_NEWARR_1_VC, // optimized 1-D value class arrays CORINFO_HELP_NEWARR_1_ALIGN8, // like VC, but aligns the array start CORINFO_HELP_STRCNS, // create a new string literal CORINFO_HELP_STRCNS_CURRENT_MODULE, // create a new string literal from the current module (used by NGen code) /* Object model */ CORINFO_HELP_INITCLASS, // Initialize class if not already initialized CORINFO_HELP_INITINSTCLASS, // Initialize class for instantiated type // Use ICorClassInfo::getCastingHelper to determine // the right helper to use CORINFO_HELP_ISINSTANCEOFINTERFACE, // Optimized helper for interfaces CORINFO_HELP_ISINSTANCEOFARRAY, // Optimized helper for arrays CORINFO_HELP_ISINSTANCEOFCLASS, // Optimized helper for classes CORINFO_HELP_ISINSTANCEOFANY, // Slow helper for any type CORINFO_HELP_CHKCASTINTERFACE, CORINFO_HELP_CHKCASTARRAY, CORINFO_HELP_CHKCASTCLASS, CORINFO_HELP_CHKCASTANY, CORINFO_HELP_CHKCASTCLASS_SPECIAL, // Optimized helper for classes. Assumes that the trivial cases // has been taken care of by the inlined check CORINFO_HELP_ISINSTANCEOF_EXCEPTION, CORINFO_HELP_BOX, // Fast box helper. Only possible exception is OutOfMemory CORINFO_HELP_BOX_NULLABLE, // special form of boxing for Nullable CORINFO_HELP_UNBOX, CORINFO_HELP_UNBOX_NULLABLE, // special form of unboxing for Nullable CORINFO_HELP_GETREFANY, // Extract the byref from a TypedReference, checking that it is the expected type CORINFO_HELP_ARRADDR_ST, // assign to element of object array with type-checking CORINFO_HELP_LDELEMA_REF, // does a precise type comparison and returns address /* Exceptions */ CORINFO_HELP_THROW, // Throw an exception object CORINFO_HELP_RETHROW, // Rethrow the currently active exception CORINFO_HELP_USER_BREAKPOINT, // For a user program to break to the debugger CORINFO_HELP_RNGCHKFAIL, // array bounds check failed CORINFO_HELP_OVERFLOW, // throw an overflow exception CORINFO_HELP_THROWDIVZERO, // throw a divide by zero exception CORINFO_HELP_THROWNULLREF, // throw a null reference exception CORINFO_HELP_VERIFICATION, // Throw a VerificationException CORINFO_HELP_FAIL_FAST, // Kill the process avoiding any exceptions or stack and data dependencies (use for GuardStack unsafe buffer checks) CORINFO_HELP_METHOD_ACCESS_EXCEPTION,//Throw an access exception due to a failed member/class access check. CORINFO_HELP_FIELD_ACCESS_EXCEPTION, CORINFO_HELP_CLASS_ACCESS_EXCEPTION, CORINFO_HELP_ENDCATCH, // call back into the EE at the end of a catch block /* Synchronization */ CORINFO_HELP_MON_ENTER, CORINFO_HELP_MON_EXIT, CORINFO_HELP_MON_ENTER_STATIC, CORINFO_HELP_MON_EXIT_STATIC, CORINFO_HELP_GETCLASSFROMMETHODPARAM, // Given a generics method handle, returns a class handle CORINFO_HELP_GETSYNCFROMCLASSHANDLE, // Given a generics class handle, returns the sync monitor // in its ManagedClassObject /* GC support */ CORINFO_HELP_STOP_FOR_GC, // Call GC (force a GC) CORINFO_HELP_POLL_GC, // Ask GC if it wants to collect CORINFO_HELP_STRESS_GC, // Force a GC, but then update the JITTED code to be a noop call CORINFO_HELP_CHECK_OBJ, // confirm that ECX is a valid object pointer (debugging only) /* GC Write barrier support */ CORINFO_HELP_ASSIGN_REF, // universal helpers with F_CALL_CONV calling convention CORINFO_HELP_CHECKED_ASSIGN_REF, CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, // Do the store, and ensure that the target was not in the heap. CORINFO_HELP_ASSIGN_BYREF, CORINFO_HELP_ASSIGN_STRUCT, /* Accessing fields */ // For COM object support (using COM get/set routines to update object) // and EnC and cross-context support CORINFO_HELP_GETFIELD8, CORINFO_HELP_SETFIELD8, CORINFO_HELP_GETFIELD16, CORINFO_HELP_SETFIELD16, CORINFO_HELP_GETFIELD32, CORINFO_HELP_SETFIELD32, CORINFO_HELP_GETFIELD64, CORINFO_HELP_SETFIELD64, CORINFO_HELP_GETFIELDOBJ, CORINFO_HELP_SETFIELDOBJ, CORINFO_HELP_GETFIELDSTRUCT, CORINFO_HELP_SETFIELDSTRUCT, CORINFO_HELP_GETFIELDFLOAT, CORINFO_HELP_SETFIELDFLOAT, CORINFO_HELP_GETFIELDDOUBLE, CORINFO_HELP_SETFIELDDOUBLE, CORINFO_HELP_GETFIELDADDR, CORINFO_HELP_GETSTATICFIELDADDR_TLS, // Helper for PE TLS fields // There are a variety of specialized helpers for accessing static fields. The JIT should use // ICorClassInfo::getSharedStaticsOrCCtorHelper to determine which helper to use // Helpers for regular statics CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, CORINFO_HELP_GETSHARED_GCSTATIC_BASE, CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR, CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS, CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS, // Helper to class initialize shared generic with dynamicclass, but not get static field address CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS, // Helpers for thread statics CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE, CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, /* Debugger */ CORINFO_HELP_DBG_IS_JUST_MY_CODE, // Check if this is "JustMyCode" and needs to be stepped through. /* Profiling enter/leave probe addresses */ CORINFO_HELP_PROF_FCN_ENTER, // record the entry to a method (caller) CORINFO_HELP_PROF_FCN_LEAVE, // record the completion of current method (caller) CORINFO_HELP_PROF_FCN_TAILCALL, // record the completion of current method through tailcall (caller) /* Miscellaneous */ CORINFO_HELP_BBT_FCN_ENTER, // record the entry to a method for collecting Tuning data CORINFO_HELP_PINVOKE_CALLI, // Indirect pinvoke call CORINFO_HELP_TAILCALL, // Perform a tail call CORINFO_HELP_GETCURRENTMANAGEDTHREADID, CORINFO_HELP_INIT_PINVOKE_FRAME, // initialize an inlined PInvoke Frame for the JIT-compiler CORINFO_HELP_MEMSET, // Init block of memory CORINFO_HELP_MEMCPY, // Copy block of memory CORINFO_HELP_RUNTIMEHANDLE_METHOD, // determine a type/field/method handle at run-time CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG, // determine a type/field/method handle at run-time, with IBC logging CORINFO_HELP_RUNTIMEHANDLE_CLASS, // determine a type/field/method handle at run-time CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG, // determine a type/field/method handle at run-time, with IBC logging CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, // Convert from a TypeHandle (native structure pointer) to RuntimeType at run-time CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL, // Convert from a TypeHandle (native structure pointer) to RuntimeType at run-time, the type may be null CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, // Convert from a MethodDesc (native structure pointer) to RuntimeMethodHandle at run-time CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, // Convert from a FieldDesc (native structure pointer) to RuntimeFieldHandle at run-time CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, // Convert from a TypeHandle (native structure pointer) to RuntimeTypeHandle at run-time CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, // Convert from a TypeHandle (native structure pointer) to RuntimeTypeHandle at run-time, handle might point to a null type CORINFO_HELP_ARE_TYPES_EQUIVALENT, // Check whether two TypeHandles (native structure pointers) are equivalent CORINFO_HELP_VIRTUAL_FUNC_PTR, // look up a virtual method at run-time // Not a real helpers. Instead of taking handle arguments, these helpers point to a small stub that loads the handle argument and calls the static helper. CORINFO_HELP_READYTORUN_NEW, CORINFO_HELP_READYTORUN_NEWARR_1, CORINFO_HELP_READYTORUN_ISINSTANCEOF, CORINFO_HELP_READYTORUN_CHKCAST, CORINFO_HELP_READYTORUN_STATIC_BASE, CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, CORINFO_HELP_READYTORUN_GENERIC_HANDLE, CORINFO_HELP_READYTORUN_DELEGATE_CTOR, CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, CORINFO_HELP_EE_PERSONALITY_ROUTINE,// Not real JIT helper. Used in native images. CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET,// Not real JIT helper. Used in native images to detect filter funclets. // ASSIGN_REF_EAX - CHECKED_ASSIGN_REF_EBP: NOGC_WRITE_BARRIERS JIT helper calls // // For unchecked versions EDX is required to point into GC heap. // // NOTE: these helpers are only used for x86. CORINFO_HELP_ASSIGN_REF_EAX, // EAX holds GC ptr, do a 'mov [EDX], EAX' and inform GC CORINFO_HELP_ASSIGN_REF_EBX, // EBX holds GC ptr, do a 'mov [EDX], EBX' and inform GC CORINFO_HELP_ASSIGN_REF_ECX, // ECX holds GC ptr, do a 'mov [EDX], ECX' and inform GC CORINFO_HELP_ASSIGN_REF_ESI, // ESI holds GC ptr, do a 'mov [EDX], ESI' and inform GC CORINFO_HELP_ASSIGN_REF_EDI, // EDI holds GC ptr, do a 'mov [EDX], EDI' and inform GC CORINFO_HELP_ASSIGN_REF_EBP, // EBP holds GC ptr, do a 'mov [EDX], EBP' and inform GC CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, // These are the same as ASSIGN_REF above ... CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, // ... but also check if EDX points into heap. CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR, // Return the reference to a counter to decide to take cloned path in debug stress. CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, // Print a message that a loop cloning optimization has occurred in debug mode. CORINFO_HELP_THROW_ARGUMENTEXCEPTION, // throw ArgumentException CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION, // throw ArgumentOutOfRangeException CORINFO_HELP_THROW_NOT_IMPLEMENTED, // throw NotImplementedException CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, // throw PlatformNotSupportedException CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, // throw TypeNotSupportedException CORINFO_HELP_THROW_AMBIGUOUS_RESOLUTION_EXCEPTION, // throw AmbiguousResolutionException for failed static virtual method resolution CORINFO_HELP_JIT_PINVOKE_BEGIN, // Transition to preemptive mode before a P/Invoke, frame is the first argument CORINFO_HELP_JIT_PINVOKE_END, // Transition to cooperative mode after a P/Invoke, frame is the first argument CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, // Transition to cooperative mode in reverse P/Invoke prolog, frame is the first argument CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS, // Transition to cooperative mode and track transitions in reverse P/Invoke prolog. CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, // Transition to preemptive mode in reverse P/Invoke epilog, frame is the first argument CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT_TRACK_TRANSITIONS, // Transition to preemptive mode and track transitions in reverse P/Invoke prolog. CORINFO_HELP_GVMLOOKUP_FOR_SLOT, // Resolve a generic virtual method target from this pointer and runtime method handle CORINFO_HELP_STACK_PROBE, // Probes each page of the allocated stack frame CORINFO_HELP_PATCHPOINT, // Notify runtime that code has reached a patchpoint CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, // Notify runtime that code has reached a part of the method that wasn't originally jitted. CORINFO_HELP_CLASSPROFILE32, // Update 32-bit class profile for a call site CORINFO_HELP_CLASSPROFILE64, // Update 64-bit class profile for a call site CORINFO_HELP_DELEGATEPROFILE32, // Update 32-bit method profile for a delegate call site CORINFO_HELP_DELEGATEPROFILE64, // Update 64-bit method profile for a delegate call site CORINFO_HELP_VTABLEPROFILE32, // Update 32-bit method profile for a vtable call site CORINFO_HELP_VTABLEPROFILE64, // Update 64-bit method profile for a vtable call site CORINFO_HELP_VALIDATE_INDIRECT_CALL, // CFG: Validate function pointer CORINFO_HELP_DISPATCH_INDIRECT_CALL, // CFG: Validate and dispatch to pointer CORINFO_HELP_COUNT, }; //This describes the signature for a helper method. enum CorInfoHelpSig { CORINFO_HELP_SIG_UNDEF, CORINFO_HELP_SIG_NO_ALIGN_STUB, CORINFO_HELP_SIG_NO_UNWIND_STUB, CORINFO_HELP_SIG_REG_ONLY, CORINFO_HELP_SIG_4_STACK, CORINFO_HELP_SIG_8_STACK, CORINFO_HELP_SIG_12_STACK, CORINFO_HELP_SIG_16_STACK, CORINFO_HELP_SIG_EBPCALL, //special calling convention that uses EDX and //EBP as arguments CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB, CORINFO_HELP_SIG_COUNT }; // The enumeration is returned in 'getSig','getType', getArgType methods enum CorInfoType { CORINFO_TYPE_UNDEF = 0x0, CORINFO_TYPE_VOID = 0x1, CORINFO_TYPE_BOOL = 0x2, CORINFO_TYPE_CHAR = 0x3, CORINFO_TYPE_BYTE = 0x4, CORINFO_TYPE_UBYTE = 0x5, CORINFO_TYPE_SHORT = 0x6, CORINFO_TYPE_USHORT = 0x7, CORINFO_TYPE_INT = 0x8, CORINFO_TYPE_UINT = 0x9, CORINFO_TYPE_LONG = 0xa, CORINFO_TYPE_ULONG = 0xb, CORINFO_TYPE_NATIVEINT = 0xc, CORINFO_TYPE_NATIVEUINT = 0xd, CORINFO_TYPE_FLOAT = 0xe, CORINFO_TYPE_DOUBLE = 0xf, CORINFO_TYPE_STRING = 0x10, // Not used, should remove CORINFO_TYPE_PTR = 0x11, CORINFO_TYPE_BYREF = 0x12, CORINFO_TYPE_VALUECLASS = 0x13, CORINFO_TYPE_CLASS = 0x14, CORINFO_TYPE_REFANY = 0x15, // CORINFO_TYPE_VAR is for a generic type variable. // Generic type variables only appear when the JIT is doing // verification (not NOT compilation) of generic code // for the EE, in which case we're running // the JIT in "import only" mode. CORINFO_TYPE_VAR = 0x16, CORINFO_TYPE_COUNT, // number of jit types }; enum CorInfoTypeWithMod { CORINFO_TYPE_MASK = 0x3F, // lower 6 bits are type mask CORINFO_TYPE_MOD_PINNED = 0x40, // can be applied to CLASS, or BYREF to indicate pinned }; inline CorInfoType strip(CorInfoTypeWithMod val) { return CorInfoType(val & CORINFO_TYPE_MASK); } // The enumeration is returned in 'getSig' enum CorInfoCallConv { // These correspond to CorCallingConvention CORINFO_CALLCONV_DEFAULT = 0x0, // Instead of using the below values, use the CorInfoCallConvExtension enum for unmanaged calling conventions. // CORINFO_CALLCONV_C = 0x1, // CORINFO_CALLCONV_STDCALL = 0x2, // CORINFO_CALLCONV_THISCALL = 0x3, // CORINFO_CALLCONV_FASTCALL = 0x4, CORINFO_CALLCONV_VARARG = 0x5, CORINFO_CALLCONV_FIELD = 0x6, CORINFO_CALLCONV_LOCAL_SIG = 0x7, CORINFO_CALLCONV_PROPERTY = 0x8, CORINFO_CALLCONV_UNMANAGED = 0x9, CORINFO_CALLCONV_NATIVEVARARG = 0xb, // used ONLY for IL stub PInvoke vararg calls CORINFO_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits CORINFO_CALLCONV_GENERIC = 0x10, CORINFO_CALLCONV_HASTHIS = 0x20, CORINFO_CALLCONV_EXPLICITTHIS=0x40, CORINFO_CALLCONV_PARAMTYPE = 0x80, // Passed last. Same as CORINFO_GENERICS_CTXT_FROM_PARAMTYPEARG }; // Represents the calling conventions supported with the extensible calling convention syntax // as well as the original metadata-encoded calling conventions. enum class CorInfoCallConvExtension { Managed, C, Stdcall, Thiscall, Fastcall, // New calling conventions supported with the extensible calling convention encoding go here. CMemberFunction, StdcallMemberFunction, FastcallMemberFunction }; #ifdef TARGET_X86 inline bool IsCallerPop(CorInfoCallConvExtension callConv) { #ifdef UNIX_X86_ABI return callConv == CorInfoCallConvExtension::Managed || callConv == CorInfoCallConvExtension::C || callConv == CorInfoCallConvExtension::CMemberFunction; #else return callConv == CorInfoCallConvExtension::C || callConv == CorInfoCallConvExtension::CMemberFunction; #endif // UNIX_X86_ABI } #endif // Determines whether or not this calling convention is an instance method calling convention. inline bool callConvIsInstanceMethodCallConv(CorInfoCallConvExtension callConv) { return callConv == CorInfoCallConvExtension::Thiscall || callConv == CorInfoCallConvExtension::CMemberFunction || callConv == CorInfoCallConvExtension::StdcallMemberFunction || callConv == CorInfoCallConvExtension::FastcallMemberFunction; } // These are returned from getMethodOptions enum CorInfoOptions { CORINFO_OPT_INIT_LOCALS = 0x00000010, // zero initialize all variables CORINFO_GENERICS_CTXT_FROM_THIS = 0x00000020, // is this shared generic code that access the generic context from the this pointer? If so, then if the method has SEH then the 'this' pointer must always be reported and kept alive. CORINFO_GENERICS_CTXT_FROM_METHODDESC = 0x00000040, // is this shared generic code that access the generic context from the ParamTypeArg(that is a MethodDesc)? If so, then if the method has SEH then the 'ParamTypeArg' must always be reported and kept alive. Same as CORINFO_CALLCONV_PARAMTYPE CORINFO_GENERICS_CTXT_FROM_METHODTABLE = 0x00000080, // is this shared generic code that access the generic context from the ParamTypeArg(that is a MethodTable)? If so, then if the method has SEH then the 'ParamTypeArg' must always be reported and kept alive. Same as CORINFO_CALLCONV_PARAMTYPE CORINFO_GENERICS_CTXT_MASK = (CORINFO_GENERICS_CTXT_FROM_THIS | CORINFO_GENERICS_CTXT_FROM_METHODDESC | CORINFO_GENERICS_CTXT_FROM_METHODTABLE), CORINFO_GENERICS_CTXT_KEEP_ALIVE = 0x00000100, // Keep the generics context alive throughout the method even if there is no explicit use, and report its location to the CLR }; // // what type of code region we are in // enum CorInfoRegionKind { CORINFO_REGION_NONE, CORINFO_REGION_HOT, CORINFO_REGION_COLD, CORINFO_REGION_JIT, }; // these are the attribute flags for fields and methods (getMethodAttribs) enum CorInfoFlag { // CORINFO_FLG_UNUSED = 0x00000001, // CORINFO_FLG_UNUSED = 0x00000002, CORINFO_FLG_PROTECTED = 0x00000004, CORINFO_FLG_STATIC = 0x00000008, CORINFO_FLG_FINAL = 0x00000010, CORINFO_FLG_SYNCH = 0x00000020, CORINFO_FLG_VIRTUAL = 0x00000040, // CORINFO_FLG_UNUSED = 0x00000080, CORINFO_FLG_NATIVE = 0x00000100, CORINFO_FLG_INTRINSIC_TYPE = 0x00000200, // This type is marked by [Intrinsic] CORINFO_FLG_ABSTRACT = 0x00000400, CORINFO_FLG_EnC = 0x00000800, // member was added by Edit'n'Continue // These are internal flags that can only be on methods CORINFO_FLG_FORCEINLINE = 0x00010000, // The method should be inlined if possible. CORINFO_FLG_SHAREDINST = 0x00020000, // the code for this method is shared between different generic instantiations (also set on classes/types) CORINFO_FLG_DELEGATE_INVOKE = 0x00040000, // "Delegate CORINFO_FLG_PINVOKE = 0x00080000, // Is a P/Invoke call // CORINFO_FLG_UNUSED = 0x00100000, CORINFO_FLG_NOGCCHECK = 0x00200000, // This method is FCALL that has no GC check. Don't put alone in loops CORINFO_FLG_INTRINSIC = 0x00400000, // This method MAY have an intrinsic ID CORINFO_FLG_CONSTRUCTOR = 0x00800000, // This method is an instance or type initializer CORINFO_FLG_AGGRESSIVE_OPT = 0x01000000, // The method may contain hot code and should be aggressively optimized if possible CORINFO_FLG_DISABLE_TIER0_FOR_LOOPS = 0x02000000, // Indicates that tier 0 JIT should not be used for a method that contains a loop // CORINFO_FLG_UNUSED = 0x04000000, // CORINFO_FLG_UNUSED = 0x08000000, CORINFO_FLG_DONT_INLINE = 0x10000000, // The method should not be inlined CORINFO_FLG_DONT_INLINE_CALLER = 0x20000000, // The method should not be inlined, nor should its callers. It cannot be tail called. // CORINFO_FLG_UNUSED = 0x40000000, // These are internal flags that can only be on Classes CORINFO_FLG_VALUECLASS = 0x00010000, // is the class a value class // This flag is define din the Methods section, but is also valid on classes. // CORINFO_FLG_SHAREDINST = 0x00020000, // This class is satisfies TypeHandle::IsCanonicalSubtype CORINFO_FLG_VAROBJSIZE = 0x00040000, // the object size varies depending of constructor args CORINFO_FLG_ARRAY = 0x00080000, // class is an array class (initialized differently) CORINFO_FLG_OVERLAPPING_FIELDS = 0x00100000, // struct or class has fields that overlap (aka union) CORINFO_FLG_INTERFACE = 0x00200000, // it is an interface CORINFO_FLG_DONT_DIG_FIELDS = 0x00400000, // don't ask field info, AOT can't rely on it (used for types outside of AOT compilation version bubble) CORINFO_FLG_CUSTOMLAYOUT = 0x00800000, // does this struct have custom layout? CORINFO_FLG_CONTAINS_GC_PTR = 0x01000000, // does the class contain a gc ptr ? CORINFO_FLG_DELEGATE = 0x02000000, // is this a subclass of delegate or multicast delegate ? // CORINFO_FLG_UNUSED = 0x04000000, CORINFO_FLG_BYREF_LIKE = 0x08000000, // it is byref-like value type CORINFO_FLG_VARIANCE = 0x10000000, // MethodTable::HasVariance (sealed does *not* mean uncast-able) CORINFO_FLG_BEFOREFIELDINIT = 0x20000000, // Additional flexibility for when to run .cctor (see code:#ClassConstructionFlags) CORINFO_FLG_GENERIC_TYPE_VARIABLE = 0x40000000, // This is really a handle for a variable type CORINFO_FLG_UNSAFE_VALUECLASS = 0x80000000, // Unsafe (C++'s /GS) value type }; // Flags computed by a runtime compiler enum CorInfoMethodRuntimeFlags { CORINFO_FLG_BAD_INLINEE = 0x00000001, // The method is not suitable for inlining // unused = 0x00000002, // unused = 0x00000004, CORINFO_FLG_SWITCHED_TO_MIN_OPT = 0x00000008, // The JIT decided to switch to MinOpt for this method, when it was not requested CORINFO_FLG_SWITCHED_TO_OPTIMIZED = 0x00000010, // The JIT decided to switch to tier 1 for this method, when a different tier was requested }; enum CORINFO_ACCESS_FLAGS { CORINFO_ACCESS_ANY = 0x0000, // Normal access CORINFO_ACCESS_THIS = 0x0001, // Accessed via the this reference // UNUSED = 0x0002, CORINFO_ACCESS_NONNULL = 0x0004, // Instance is guaranteed non-null CORINFO_ACCESS_LDFTN = 0x0010, // Accessed via ldftn // Field access flags CORINFO_ACCESS_GET = 0x0100, // Field get (ldfld) CORINFO_ACCESS_SET = 0x0200, // Field set (stfld) CORINFO_ACCESS_ADDRESS = 0x0400, // Field address (ldflda) CORINFO_ACCESS_INIT_ARRAY = 0x0800, // Field use for InitializeArray // UNUSED = 0x4000, CORINFO_ACCESS_INLINECHECK= 0x8000, // Return fieldFlags and fieldAccessor only. Used by JIT64 during inlining. }; // These are the flags set on an CORINFO_EH_CLAUSE enum CORINFO_EH_CLAUSE_FLAGS { CORINFO_EH_CLAUSE_NONE = 0, CORINFO_EH_CLAUSE_FILTER = 0x0001, // If this bit is on, then this EH entry is for a filter CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause CORINFO_EH_CLAUSE_DUPLICATE = 0x0008, // Duplicated clause. This clause was duplicated to a funclet which was pulled out of line CORINFO_EH_CLAUSE_SAMETRY = 0x0010, // This clause covers same try block as the previous one. (Used by NativeAOT ABI.) }; // This enumeration is passed to InternalThrow enum CorInfoException { CORINFO_NullReferenceException, CORINFO_DivideByZeroException, CORINFO_InvalidCastException, CORINFO_IndexOutOfRangeException, CORINFO_OverflowException, CORINFO_SynchronizationLockException, CORINFO_ArrayTypeMismatchException, CORINFO_RankException, CORINFO_ArgumentNullException, CORINFO_ArgumentException, CORINFO_Exception_Count, }; // These are used to detect array methods as NamedIntrinsic in JIT importer, // which otherwise don't have a name. enum class CorInfoArrayIntrinsic { GET = 0, SET = 1, ADDRESS = 2, ILLEGAL }; // Can a value be accessed directly from JITed code. enum InfoAccessType { IAT_VALUE, // The info value is directly available IAT_PVALUE, // The value needs to be accessed via an indirection IAT_PPVALUE, // The value needs to be accessed via a double indirection IAT_RELPVALUE // The value needs to be accessed via a relative indirection }; enum CorInfoGCType { TYPE_GC_NONE, // no embedded objectrefs TYPE_GC_REF, // Is an object ref TYPE_GC_BYREF, // Is an interior pointer - promote it but don't scan it TYPE_GC_OTHER // requires type-specific treatment }; enum CorInfoClassId { CLASSID_SYSTEM_OBJECT, CLASSID_TYPED_BYREF, CLASSID_TYPE_HANDLE, CLASSID_FIELD_HANDLE, CLASSID_METHOD_HANDLE, CLASSID_STRING, CLASSID_ARGUMENT_HANDLE, CLASSID_RUNTIME_TYPE, }; enum CorInfoInline { INLINE_PASS = 0, // Inlining OK INLINE_PREJIT_SUCCESS = 1, // Inline check for prejit checking usage succeeded INLINE_CHECK_CAN_INLINE_SUCCESS = 2, // JIT detected it is permitted to try to actually inline INLINE_CHECK_CAN_INLINE_VMFAIL = 3, // VM specified that inline must fail via the CanInline api // failures are negative INLINE_FAIL = -1, // Inlining not OK for this case only INLINE_NEVER = -2, // This method should never be inlined, regardless of context }; enum CorInfoInlineTypeCheck { CORINFO_INLINE_TYPECHECK_NONE = 0x00000000, // It's not okay to compare type's vtable with a native type handle CORINFO_INLINE_TYPECHECK_PASS = 0x00000001, // It's okay to compare type's vtable with a native type handle CORINFO_INLINE_TYPECHECK_USE_HELPER = 0x00000002, // Use a specialized helper to compare type's vtable with native type handle }; enum CorInfoInlineTypeCheckSource { CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE = 0x00000000, // Type handle comes from the vtable CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN = 0x00000001, // Type handle comes from an ldtoken }; // If you add more values here, keep it in sync with TailCallTypeMap in ..\vm\ClrEtwAll.man // and the string enum in CEEInfo::reportTailCallDecision in ..\vm\JITInterface.cpp enum CorInfoTailCall { TAILCALL_OPTIMIZED = 0, // Optimized tail call (epilog + jmp) TAILCALL_RECURSIVE = 1, // Optimized into a loop (only when a method tail calls itself) TAILCALL_HELPER = 2, // Helper assisted tail call (call to JIT_TailCall) // failures are negative TAILCALL_FAIL = -1, // Couldn't do a tail call }; enum CorInfoInitClassResult { CORINFO_INITCLASS_NOT_REQUIRED = 0x00, // No class initialization required, but the class is not actually initialized yet // (e.g. we are guaranteed to run the static constructor in method prolog) CORINFO_INITCLASS_INITIALIZED = 0x01, // Class initialized CORINFO_INITCLASS_USE_HELPER = 0x02, // The JIT must insert class initialization helper call. CORINFO_INITCLASS_DONT_INLINE = 0x04, // The JIT should not inline the method requesting the class initialization. The class // initialization requires helper class now, but will not require initialization // if the method is compiled standalone. Or the method cannot be inlined due to some // requirement around class initialization such as shared generics. }; // Reason codes for making indirect calls #define INDIRECT_CALL_REASONS() \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_UNKNOWN) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_EXOTIC) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_PINVOKE) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_GENERIC) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_NO_CODE) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_FIXUPS) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_STUB) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_REMOTING) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_CER) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE_METHOD) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE_FIRST_CALL) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE_VALUE_TYPE) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_RESTORE) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_CANT_PATCH) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_PROFILING) \ INDIRECT_CALL_REASON_FUNC(CORINFO_INDIRECT_CALL_OTHER_LOADER_MODULE) \ enum CorInfoIndirectCallReason { #undef INDIRECT_CALL_REASON_FUNC #define INDIRECT_CALL_REASON_FUNC(x) x, INDIRECT_CALL_REASONS() #undef INDIRECT_CALL_REASON_FUNC CORINFO_INDIRECT_CALL_COUNT }; inline bool dontInline(CorInfoInline val) { return(val < 0); } // Patchpoint info is passed back and forth across the interface // but is opaque. struct PatchpointInfo; // Cookie types consumed by the code generator (these are opaque values // not inspected by the code generator): typedef struct CORINFO_ASSEMBLY_STRUCT_* CORINFO_ASSEMBLY_HANDLE; typedef struct CORINFO_MODULE_STRUCT_* CORINFO_MODULE_HANDLE; typedef struct CORINFO_DEPENDENCY_STRUCT_* CORINFO_DEPENDENCY_HANDLE; typedef struct CORINFO_CLASS_STRUCT_* CORINFO_CLASS_HANDLE; typedef struct CORINFO_METHOD_STRUCT_* CORINFO_METHOD_HANDLE; typedef struct CORINFO_FIELD_STRUCT_* CORINFO_FIELD_HANDLE; typedef struct CORINFO_OBJECT_STRUCT_* CORINFO_OBJECT_HANDLE; typedef struct CORINFO_ARG_LIST_STRUCT_* CORINFO_ARG_LIST_HANDLE; // represents a list of argument types typedef struct CORINFO_JUST_MY_CODE_HANDLE_*CORINFO_JUST_MY_CODE_HANDLE; typedef struct CORINFO_PROFILING_STRUCT_* CORINFO_PROFILING_HANDLE; // a handle guaranteed to be unique per process typedef struct CORINFO_GENERIC_STRUCT_* CORINFO_GENERIC_HANDLE; // a generic handle (could be any of the above) // what is actually passed on the varargs call typedef struct CORINFO_VarArgInfo * CORINFO_VARARGS_HANDLE; // Generic tokens are resolved with respect to a context, which is usually the method // being compiled. The CORINFO_CONTEXT_HANDLE indicates which exact instantiation // (or the open instantiation) is being referred to. typedef struct CORINFO_CONTEXT_STRUCT_* CORINFO_CONTEXT_HANDLE; // MethodSignatureInfo is an opaque handle for passing method signature information across the Jit/EE interface struct MethodSignatureInfo; typedef struct CORINFO_DEPENDENCY_STRUCT_ { CORINFO_MODULE_HANDLE moduleFrom; CORINFO_MODULE_HANDLE moduleTo; } CORINFO_DEPENDENCY; // Bit-twiddling of contexts assumes word-alignment of method handles and type handles // If this ever changes, some other encoding will be needed enum CorInfoContextFlags { CORINFO_CONTEXTFLAGS_METHOD = 0x00, // CORINFO_CONTEXT_HANDLE is really a CORINFO_METHOD_HANDLE CORINFO_CONTEXTFLAGS_CLASS = 0x01, // CORINFO_CONTEXT_HANDLE is really a CORINFO_CLASS_HANDLE CORINFO_CONTEXTFLAGS_MASK = 0x01 }; #define METHOD_BEING_COMPILED_CONTEXT() ((CORINFO_CONTEXT_HANDLE)1) #define MAKE_CLASSCONTEXT(c) (CORINFO_CONTEXT_HANDLE((size_t) (c) | CORINFO_CONTEXTFLAGS_CLASS)) #define MAKE_METHODCONTEXT(m) (CORINFO_CONTEXT_HANDLE((size_t) (m) | CORINFO_CONTEXTFLAGS_METHOD)) enum CorInfoSigInfoFlags { CORINFO_SIGFLAG_IS_LOCAL_SIG = 0x01, CORINFO_SIGFLAG_IL_STUB = 0x02, // unused = 0x04, CORINFO_SIGFLAG_FAT_CALL = 0x08, }; struct CORINFO_SIG_INST { unsigned classInstCount; CORINFO_CLASS_HANDLE * classInst; // (representative, not exact) instantiation for class type variables in signature unsigned methInstCount; CORINFO_CLASS_HANDLE * methInst; // (representative, not exact) instantiation for method type variables in signature }; struct CORINFO_SIG_INFO { CorInfoCallConv callConv; CORINFO_CLASS_HANDLE retTypeClass; // if the return type is a value class, this is its handle (enums are normalized) CORINFO_CLASS_HANDLE retTypeSigClass;// returns the value class as it is in the sig (enums are not converted to primitives) CorInfoType retType : 8; unsigned flags : 8; // used by IL stubs code unsigned numArgs : 16; struct CORINFO_SIG_INST sigInst; // information about how type variables are being instantiated in generic code CORINFO_ARG_LIST_HANDLE args; PCCOR_SIGNATURE pSig; unsigned cbSig; MethodSignatureInfo* methodSignature;// used in place of pSig and cbSig to reference a method signature object handle CORINFO_MODULE_HANDLE scope; // passed to getArgClass mdToken token; CorInfoCallConv getCallConv() { return CorInfoCallConv((callConv & CORINFO_CALLCONV_MASK)); } bool hasThis() { return ((callConv & CORINFO_CALLCONV_HASTHIS) != 0); } bool hasExplicitThis() { return ((callConv & CORINFO_CALLCONV_EXPLICITTHIS) != 0); } unsigned totalILArgs() { return (numArgs + (hasThis() ? 1 : 0)); } bool isVarArg() { return ((getCallConv() == CORINFO_CALLCONV_VARARG) || (getCallConv() == CORINFO_CALLCONV_NATIVEVARARG)); } bool hasTypeArg() { return ((callConv & CORINFO_CALLCONV_PARAMTYPE) != 0); } }; struct CORINFO_METHOD_INFO { CORINFO_METHOD_HANDLE ftn; CORINFO_MODULE_HANDLE scope; uint8_t * ILCode; unsigned ILCodeSize; unsigned maxStack; unsigned EHcount; CorInfoOptions options; CorInfoRegionKind regionKind; CORINFO_SIG_INFO args; CORINFO_SIG_INFO locals; }; //---------------------------------------------------------------------------- // Looking up handles and addresses. // // When the JIT requests a handle, the EE may direct the JIT that it must // access the handle in a variety of ways. These are packed as // CORINFO_CONST_LOOKUP // or CORINFO_LOOKUP (contains either a CORINFO_CONST_LOOKUP or a CORINFO_RUNTIME_LOOKUP) // // Constant Lookups v. Runtime Lookups (i.e. when will Runtime Lookups be generated?) // ----------------------------------------------------------------------------------- // // CORINFO_LOOKUP_KIND is part of the result type of embedGenericHandle, // getVirtualCallInfo and any other functions that may require a // runtime lookup when compiling shared generic code. // // CORINFO_LOOKUP_KIND indicates whether a particular token in the instruction stream can be: // (a) Mapped to a handle (type, field or method) at compile-time (!needsRuntimeLookup) // (b) Must be looked up at run-time, and if so which runtime lookup technique should be used (see below) // // If the JIT or EE does not support code sharing for generic code, then // all CORINFO_LOOKUP results will be "constant lookups", i.e. // the needsRuntimeLookup of CORINFO_LOOKUP.lookupKind.needsRuntimeLookup // will be false. // // Constant Lookups // ---------------- // // Constant Lookups are either: // IAT_VALUE: immediate (relocatable) values, // IAT_PVALUE: immediate values access via an indirection through an immediate (relocatable) address // IAT_RELPVALUE: immediate values access via a relative indirection through an immediate offset // IAT_PPVALUE: immediate values access via a double indirection through an immediate (relocatable) address // // Runtime Lookups // --------------- // // CORINFO_LOOKUP_KIND is part of the result type of embedGenericHandle, // getVirtualCallInfo and any other functions that may require a // runtime lookup when compiling shared generic code. // // CORINFO_LOOKUP_KIND indicates whether a particular token in the instruction stream can be: // (a) Mapped to a handle (type, field or method) at compile-time (!needsRuntimeLookup) // (b) Must be looked up at run-time using the class dictionary // stored in the vtable of the this pointer (needsRuntimeLookup && THISOBJ) // (c) Must be looked up at run-time using the method dictionary // stored in the method descriptor parameter passed to a generic // method (needsRuntimeLookup && METHODPARAM) // (d) Must be looked up at run-time using the class dictionary stored // in the vtable parameter passed to a method in a generic // struct (needsRuntimeLookup && CLASSPARAM) struct CORINFO_CONST_LOOKUP { // If the handle is obtained at compile-time, then this handle is the "exact" handle (class, method, or field) // Otherwise, it's a representative... // If accessType is // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle // IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle InfoAccessType accessType; union { CORINFO_GENERIC_HANDLE handle; void * addr; }; }; enum CORINFO_RUNTIME_LOOKUP_KIND { CORINFO_LOOKUP_THISOBJ, CORINFO_LOOKUP_METHODPARAM, CORINFO_LOOKUP_CLASSPARAM, CORINFO_LOOKUP_NOT_SUPPORTED, // Returned for attempts to inline dictionary lookups }; struct CORINFO_LOOKUP_KIND { bool needsRuntimeLookup; CORINFO_RUNTIME_LOOKUP_KIND runtimeLookupKind; // The 'runtimeLookupFlags' and 'runtimeLookupArgs' fields // are just for internal VM / ZAP communication, not to be used by the JIT. uint16_t runtimeLookupFlags; void * runtimeLookupArgs; } ; // CORINFO_RUNTIME_LOOKUP indicates the details of the runtime lookup // operation to be performed. // // CORINFO_MAXINDIRECTIONS is the maximum number of // indirections used by runtime lookups. // This accounts for up to 2 indirections to get at a dictionary followed by a possible spill slot // #define CORINFO_MAXINDIRECTIONS 4 #define CORINFO_USEHELPER ((uint16_t) 0xffff) #define CORINFO_NO_SIZE_CHECK ((uint16_t) 0xffff) struct CORINFO_RUNTIME_LOOKUP { // This is signature you must pass back to the runtime lookup helper void* signature; // Here is the helper you must call. It is one of CORINFO_HELP_RUNTIMEHANDLE_* helpers. CorInfoHelpFunc helper; // Number of indirections to get there // CORINFO_USEHELPER = don't know how to get it, so use helper function at run-time instead // 0 = use the this pointer itself (e.g. token is C inside code in sealed class C) // or method desc itself (e.g. token is method void M::mymeth() inside code in M::mymeth) // Otherwise, follow each byte-offset stored in the "offsets[]" array (may be negative) uint16_t indirections; // If set, test for null and branch to helper if null bool testForNull; // If set, test the lowest bit and dereference if set (see code:FixupPointer) bool testForFixup; uint16_t sizeOffset; size_t offsets[CORINFO_MAXINDIRECTIONS]; // If set, first offset is indirect. // 0 means that value stored at first offset (offsets[0]) from pointer is next pointer, to which the next offset // (offsets[1]) is added and so on. // 1 means that value stored at first offset (offsets[0]) from pointer is offset1, and the next pointer is // stored at pointer+offsets[0]+offset1. bool indirectFirstOffset; // If set, second offset is indirect. // 0 means that value stored at second offset (offsets[1]) from pointer is next pointer, to which the next offset // (offsets[2]) is added and so on. // 1 means that value stored at second offset (offsets[1]) from pointer is offset2, and the next pointer is // stored at pointer+offsets[1]+offset2. bool indirectSecondOffset; } ; // Result of calling embedGenericHandle struct CORINFO_LOOKUP { CORINFO_LOOKUP_KIND lookupKind; union { // If kind.needsRuntimeLookup then this indicates how to do the lookup CORINFO_RUNTIME_LOOKUP runtimeLookup; // If the handle is obtained at compile-time, then this handle is the "exact" handle (class, method, or field) // Otherwise, it's a representative... If accessType is // IAT_VALUE --> "handle" stores the real handle or "addr " stores the computed address // IAT_PVALUE --> "addr" stores a pointer to a location which will hold the real handle // IAT_RELPVALUE --> "addr" stores a relative pointer to a location which will hold the real handle // IAT_PPVALUE --> "addr" stores a double indirection to a location which will hold the real handle CORINFO_CONST_LOOKUP constLookup; }; }; enum CorInfoGenericHandleType { CORINFO_HANDLETYPE_UNKNOWN, CORINFO_HANDLETYPE_CLASS, CORINFO_HANDLETYPE_METHOD, CORINFO_HANDLETYPE_FIELD }; //---------------------------------------------------------------------------- // Embedding type, method and field handles (for "ldtoken" or to pass back to helpers) // Result of calling embedGenericHandle struct CORINFO_GENERICHANDLE_RESULT { CORINFO_LOOKUP lookup; // compileTimeHandle is guaranteed to be either NULL or a handle that is usable during compile time. // It must not be embedded in the code because it might not be valid at run-time. CORINFO_GENERIC_HANDLE compileTimeHandle; // Type of the result CorInfoGenericHandleType handleType; }; #define CORINFO_ACCESS_ALLOWED_MAX_ARGS 4 enum CorInfoAccessAllowedHelperArgType { CORINFO_HELPER_ARG_TYPE_Invalid = 0, CORINFO_HELPER_ARG_TYPE_Field = 1, CORINFO_HELPER_ARG_TYPE_Method = 2, CORINFO_HELPER_ARG_TYPE_Class = 3, CORINFO_HELPER_ARG_TYPE_Module = 4, CORINFO_HELPER_ARG_TYPE_Const = 5, }; struct CORINFO_HELPER_ARG { union { CORINFO_FIELD_HANDLE fieldHandle; CORINFO_METHOD_HANDLE methodHandle; CORINFO_CLASS_HANDLE classHandle; CORINFO_MODULE_HANDLE moduleHandle; size_t constant; }; CorInfoAccessAllowedHelperArgType argType; void Set(CORINFO_METHOD_HANDLE handle) { argType = CORINFO_HELPER_ARG_TYPE_Method; methodHandle = handle; } void Set(CORINFO_FIELD_HANDLE handle) { argType = CORINFO_HELPER_ARG_TYPE_Field; fieldHandle = handle; } void Set(CORINFO_CLASS_HANDLE handle) { argType = CORINFO_HELPER_ARG_TYPE_Class; classHandle = handle; } void Set(size_t value) { argType = CORINFO_HELPER_ARG_TYPE_Const; constant = value; } }; struct CORINFO_HELPER_DESC { CorInfoHelpFunc helperNum; unsigned numArgs; CORINFO_HELPER_ARG args[CORINFO_ACCESS_ALLOWED_MAX_ARGS]; }; //---------------------------------------------------------------------------- // getCallInfo and CORINFO_CALL_INFO: The EE instructs the JIT about how to make a call // // callKind // -------- // // CORINFO_CALL : // Indicates that the JIT can use getFunctionEntryPoint to make a call, // i.e. there is nothing abnormal about the call. The JITs know what to do if they get this. // Except in the case of constraint calls (see below), [targetMethodHandle] will hold // the CORINFO_METHOD_HANDLE that a call to findMethod would // have returned. // This flag may be combined with nullInstanceCheck=TRUE for uses of callvirt on methods that can // be resolved at compile-time (non-virtual, final or sealed). // // CORINFO_CALL_CODE_POINTER (shared generic code only) : // Indicates that the JIT should do an indirect call to the entrypoint given by address, which may be specified // as a runtime lookup by CORINFO_CALL_INFO::codePointerLookup. // [targetMethodHandle] will not hold a valid value. // This flag may be combined with nullInstanceCheck=TRUE for uses of callvirt on methods whose target method can // be resolved at compile-time but whose instantiation can be resolved only through runtime lookup. // // CORINFO_VIRTUALCALL_STUB (interface calls) : // Indicates that the EE supports "stub dispatch" and request the JIT to make a // "stub dispatch" call (an indirect call through CORINFO_CALL_INFO::stubLookup, // similar to CORINFO_CALL_CODE_POINTER). // "Stub dispatch" is a specialized calling sequence (that may require use of NOPs) // which allow the runtime to determine the call-site after the call has been dispatched. // If the call is too complex for the JIT (e.g. because // fetching the dispatch stub requires a runtime lookup, i.e. lookupKind.needsRuntimeLookup // is set) then the JIT is allowed to implement the call as if it were CORINFO_VIRTUALCALL_LDVIRTFTN // [targetMethodHandle] will hold the CORINFO_METHOD_HANDLE that a call to findMethod would // have returned. // This flag is always accompanied by nullInstanceCheck=TRUE. // // CORINFO_VIRTUALCALL_LDVIRTFTN (virtual generic methods) : // Indicates that the EE provides no way to implement the call directly and // that the JIT should use a LDVIRTFTN sequence (as implemented by CORINFO_HELP_VIRTUAL_FUNC_PTR) // followed by an indirect call. // [targetMethodHandle] will hold the CORINFO_METHOD_HANDLE that a call to findMethod would // have returned. // This flag is always accompanied by nullInstanceCheck=TRUE though typically the null check will // be implicit in the access through the instance pointer. // // CORINFO_VIRTUALCALL_VTABLE (regular virtual methods) : // Indicates that the EE supports vtable dispatch and that the JIT should use getVTableOffset etc. // to implement the call. // [targetMethodHandle] will hold the CORINFO_METHOD_HANDLE that a call to findMethod would // have returned. // This flag is always accompanied by nullInstanceCheck=TRUE though typically the null check will // be implicit in the access through the instance pointer. // // thisTransform and constraint calls // ---------------------------------- // // For everything besides "constrained." calls "thisTransform" is set to // CORINFO_NO_THIS_TRANSFORM. // // For "constrained." calls the EE attempts to resolve the call at compile // time to a more specific method, or (shared generic code only) to a runtime lookup // for a code pointer for the more specific method. // // In order to permit this, the "this" pointer supplied for a "constrained." call // is a byref to an arbitrary type (see the IL spec). The "thisTransform" field // will indicate how the JIT must transform the "this" pointer in order // to be able to call the resolved method: // // CORINFO_NO_THIS_TRANSFORM --> Leave it as a byref to an unboxed value type // CORINFO_BOX_THIS --> Box it to produce an object // CORINFO_DEREF_THIS --> Deref the byref to get an object reference // // In addition, the "kind" field will be set as follows for constraint calls: // // CORINFO_CALL --> the call was resolved at compile time, and // can be compiled like a normal call. // CORINFO_CALL_CODE_POINTER --> the call was resolved, but the target address will be // computed at runtime. Only returned for shared generic code. // CORINFO_VIRTUALCALL_STUB, // CORINFO_VIRTUALCALL_LDVIRTFTN, // CORINFO_VIRTUALCALL_VTABLE --> usual values indicating that a virtual call must be made enum CORINFO_CALL_KIND { CORINFO_CALL, CORINFO_CALL_CODE_POINTER, CORINFO_VIRTUALCALL_STUB, CORINFO_VIRTUALCALL_LDVIRTFTN, CORINFO_VIRTUALCALL_VTABLE }; // Indicates that the CORINFO_VIRTUALCALL_VTABLE lookup needn't do a chunk indirection #define CORINFO_VIRTUALCALL_NO_CHUNK 0xFFFFFFFF enum CORINFO_THIS_TRANSFORM { CORINFO_NO_THIS_TRANSFORM, CORINFO_BOX_THIS, CORINFO_DEREF_THIS }; enum CORINFO_CALLINFO_FLAGS { CORINFO_CALLINFO_NONE = 0x0000, CORINFO_CALLINFO_ALLOWINSTPARAM = 0x0001, // Can the compiler generate code to pass an instantiation parameters? Simple compilers should not use this flag CORINFO_CALLINFO_CALLVIRT = 0x0002, // Is it a virtual call? CORINFO_CALLINFO_KINDONLY = 0x0004, // This is set to only query the kind of call to perform, without getting any other information CORINFO_CALLINFO_VERIFICATION = 0x0008, // Gets extra verification information. CORINFO_CALLINFO_SECURITYCHECKS = 0x0010, // Perform security checks. CORINFO_CALLINFO_LDFTN = 0x0020, // Resolving target of LDFTN // UNUSED = 0x0040, }; enum CorInfoIsAccessAllowedResult { CORINFO_ACCESS_ALLOWED = 0, // Call allowed CORINFO_ACCESS_ILLEGAL = 1, // Call not allowed }; // This enum is used for JIT to tell EE where this token comes from. // E.g. Depending on different opcodes, we might allow/disallow certain types of tokens or // return different types of handles (e.g. boxed vs. regular entrypoints) enum CorInfoTokenKind { CORINFO_TOKENKIND_Class = 0x01, CORINFO_TOKENKIND_Method = 0x02, CORINFO_TOKENKIND_Field = 0x04, CORINFO_TOKENKIND_Mask = 0x07, // token comes from CEE_LDTOKEN CORINFO_TOKENKIND_Ldtoken = 0x10 | CORINFO_TOKENKIND_Class | CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field, // token comes from CEE_CASTCLASS or CEE_ISINST CORINFO_TOKENKIND_Casting = 0x20 | CORINFO_TOKENKIND_Class, // token comes from CEE_NEWARR CORINFO_TOKENKIND_Newarr = 0x40 | CORINFO_TOKENKIND_Class, // token comes from CEE_BOX CORINFO_TOKENKIND_Box = 0x80 | CORINFO_TOKENKIND_Class, // token comes from CEE_CONSTRAINED CORINFO_TOKENKIND_Constrained = 0x100 | CORINFO_TOKENKIND_Class, // token comes from CEE_NEWOBJ CORINFO_TOKENKIND_NewObj = 0x200 | CORINFO_TOKENKIND_Method, // token comes from CEE_LDVIRTFTN CORINFO_TOKENKIND_Ldvirtftn = 0x400 | CORINFO_TOKENKIND_Method, // token comes from devirtualizing a method CORINFO_TOKENKIND_DevirtualizedMethod = 0x800 | CORINFO_TOKENKIND_Method, }; struct CORINFO_RESOLVED_TOKEN { // // [In] arguments of resolveToken // CORINFO_CONTEXT_HANDLE tokenContext; //Context for resolution of generic arguments CORINFO_MODULE_HANDLE tokenScope; mdToken token; //The source token CorInfoTokenKind tokenType; // // [Out] arguments of resolveToken. // - Type handle is always non-NULL. // - At most one of method and field handles is non-NULL (according to the token type). // - Method handle is an instantiating stub only for generic methods. Type handle // is required to provide the full context for methods in generic types. // CORINFO_CLASS_HANDLE hClass; CORINFO_METHOD_HANDLE hMethod; CORINFO_FIELD_HANDLE hField; // // [Out] TypeSpec and MethodSpec signatures for generics. NULL otherwise. // PCCOR_SIGNATURE pTypeSpec; uint32_t cbTypeSpec; PCCOR_SIGNATURE pMethodSpec; uint32_t cbMethodSpec; }; struct CORINFO_CALL_INFO { CORINFO_METHOD_HANDLE hMethod; //target method handle unsigned methodFlags; //flags for the target method unsigned classFlags; //flags for CORINFO_RESOLVED_TOKEN::hClass CORINFO_SIG_INFO sig; //Verification information unsigned verMethodFlags; // flags for CORINFO_RESOLVED_TOKEN::hMethod CORINFO_SIG_INFO verSig; //All of the regular method data is the same... hMethod might not be the same as CORINFO_RESOLVED_TOKEN::hMethod //If set to: // - CORINFO_ACCESS_ALLOWED - The access is allowed. // - CORINFO_ACCESS_ILLEGAL - This access cannot be allowed (i.e. it is public calling private). The // JIT may either insert the callsiteCalloutHelper into the code (as per a verification error) or // call throwExceptionFromHelper on the callsiteCalloutHelper. In this case callsiteCalloutHelper // is guaranteed not to return. CorInfoIsAccessAllowedResult accessAllowed; CORINFO_HELPER_DESC callsiteCalloutHelper; // See above section on constraintCalls to understand when these are set to unusual values. CORINFO_THIS_TRANSFORM thisTransform; CORINFO_CALL_KIND kind; bool nullInstanceCheck; // Context for inlining and hidden arg CORINFO_CONTEXT_HANDLE contextHandle; bool exactContextNeedsRuntimeLookup; // Set if contextHandle is approx handle. Runtime lookup is required to get the exact handle. // If kind.CORINFO_VIRTUALCALL_STUB then stubLookup will be set. // If kind.CORINFO_CALL_CODE_POINTER then entryPointLookup will be set. union { CORINFO_LOOKUP stubLookup; CORINFO_LOOKUP codePointerLookup; }; CORINFO_CONST_LOOKUP instParamLookup; // Used by Ready-to-Run bool wrapperDelegateInvoke; }; enum CORINFO_DEVIRTUALIZATION_DETAIL { CORINFO_DEVIRTUALIZATION_UNKNOWN, // no details available CORINFO_DEVIRTUALIZATION_SUCCESS, // devirtualization was successful CORINFO_DEVIRTUALIZATION_FAILED_CANON, // object class was canonical CORINFO_DEVIRTUALIZATION_FAILED_COM, // object class was com CORINFO_DEVIRTUALIZATION_FAILED_CAST, // object class could not be cast to interface class CORINFO_DEVIRTUALIZATION_FAILED_LOOKUP, // interface method could not be found CORINFO_DEVIRTUALIZATION_FAILED_DIM, // interface method was default interface method CORINFO_DEVIRTUALIZATION_FAILED_SUBCLASS, // object not subclass of base class CORINFO_DEVIRTUALIZATION_FAILED_SLOT, // virtual method installed via explicit override CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE, // devirtualization crossed version bubble CORINFO_DEVIRTUALIZATION_MULTIPLE_IMPL, // object has multiple implementations of interface class CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_CLASS_DECL, // decl method is defined on class and decl method not in version bubble, and decl method not in closest to version bubble CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_INTERFACE_DECL, // decl method is defined on interface and not in version bubble, and implementation type not entirely defined in bubble CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_IMPL, // object class not defined within version bubble CORINFO_DEVIRTUALIZATION_FAILED_BUBBLE_IMPL_NOT_REFERENCEABLE, // object class cannot be referenced from R2R code due to missing tokens CORINFO_DEVIRTUALIZATION_FAILED_DUPLICATE_INTERFACE, // crossgen2 virtual method algorithm and runtime algorithm differ in the presence of duplicate interface implementations CORINFO_DEVIRTUALIZATION_FAILED_DECL_NOT_REPRESENTABLE, // Decl method cannot be represented in R2R image CORINFO_DEVIRTUALIZATION_COUNT, // sentinel for maximum value }; struct CORINFO_DEVIRTUALIZATION_INFO { // // [In] arguments of resolveVirtualMethod // CORINFO_METHOD_HANDLE virtualMethod; CORINFO_CLASS_HANDLE objClass; CORINFO_CONTEXT_HANDLE context; CORINFO_RESOLVED_TOKEN *pResolvedTokenVirtualMethod; // // [Out] results of resolveVirtualMethod. // - devirtualizedMethod is set to MethodDesc of devirt'ed method iff we were able to devirtualize. // invariant is `resolveVirtualMethod(...) == (devirtualizedMethod != nullptr)`. // - requiresInstMethodTableArg is set to TRUE if the devirtualized method requires a type handle arg. // - exactContext is set to wrapped CORINFO_CLASS_HANDLE of devirt'ed method table. // - details on the computation done by the jit host // - If pResolvedTokenDevirtualizedMethod is not set to NULL and targeting an R2R image // use it as the parameter to getCallInfo // CORINFO_METHOD_HANDLE devirtualizedMethod; bool requiresInstMethodTableArg; CORINFO_CONTEXT_HANDLE exactContext; CORINFO_DEVIRTUALIZATION_DETAIL detail; CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedMethod; CORINFO_RESOLVED_TOKEN resolvedTokenDevirtualizedUnboxedMethod; }; //---------------------------------------------------------------------------- // getFieldInfo and CORINFO_FIELD_INFO: The EE instructs the JIT about how to access a field enum CORINFO_FIELD_ACCESSOR { CORINFO_FIELD_INSTANCE, // regular instance field at given offset from this-ptr CORINFO_FIELD_INSTANCE_WITH_BASE, // instance field with base offset (used by Ready-to-Run) CORINFO_FIELD_INSTANCE_HELPER, // instance field accessed using helper (arguments are this, FieldDesc * and the value) CORINFO_FIELD_INSTANCE_ADDR_HELPER, // instance field accessed using address-of helper (arguments are this and FieldDesc *) CORINFO_FIELD_STATIC_ADDRESS, // field at given address CORINFO_FIELD_STATIC_RVA_ADDRESS, // RVA field at given address CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER, // static field accessed using the "shared static" helper (arguments are ModuleID + ClassID) CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER, // static field access using the "generic static" helper (argument is MethodTable *) CORINFO_FIELD_STATIC_ADDR_HELPER, // static field accessed using address-of helper (argument is FieldDesc *) CORINFO_FIELD_STATIC_TLS, // unmanaged TLS access CORINFO_FIELD_STATIC_READYTORUN_HELPER, // static field access using a runtime lookup helper CORINFO_FIELD_INTRINSIC_ZERO, // intrinsic zero (IntPtr.Zero, UIntPtr.Zero) CORINFO_FIELD_INTRINSIC_EMPTY_STRING, // intrinsic emptry string (String.Empty) CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN, // intrinsic BitConverter.IsLittleEndian }; // Set of flags returned in CORINFO_FIELD_INFO::fieldFlags enum CORINFO_FIELD_FLAGS { CORINFO_FLG_FIELD_STATIC = 0x00000001, CORINFO_FLG_FIELD_UNMANAGED = 0x00000002, // RVA field CORINFO_FLG_FIELD_FINAL = 0x00000004, CORINFO_FLG_FIELD_STATIC_IN_HEAP = 0x00000008, // See code:#StaticFields. This static field is in the GC heap as a boxed object CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN = 0x00000010, // Field can be returned safely (has GC heap lifetime) CORINFO_FLG_FIELD_INITCLASS = 0x00000020, // initClass has to be called before accessing the field CORINFO_FLG_FIELD_PROTECTED = 0x00000040, }; struct CORINFO_FIELD_INFO { CORINFO_FIELD_ACCESSOR fieldAccessor; unsigned fieldFlags; // Helper to use if the field access requires it CorInfoHelpFunc helper; // Field offset if there is one uint32_t offset; CorInfoType fieldType; CORINFO_CLASS_HANDLE structType; //possibly null //See CORINFO_CALL_INFO.accessAllowed CorInfoIsAccessAllowedResult accessAllowed; CORINFO_HELPER_DESC accessCalloutHelper; CORINFO_CONST_LOOKUP fieldLookup; // Used by Ready-to-Run }; //---------------------------------------------------------------------------- // Exception handling struct CORINFO_EH_CLAUSE { CORINFO_EH_CLAUSE_FLAGS Flags; uint32_t TryOffset; uint32_t TryLength; uint32_t HandlerOffset; uint32_t HandlerLength; union { uint32_t ClassToken; // use for type-based exception handlers uint32_t FilterOffset; // use for filter-based exception handlers (COR_ILEXCEPTION_FILTER is set) }; }; enum CORINFO_OS { CORINFO_WINNT, CORINFO_UNIX, CORINFO_MACOS, }; struct CORINFO_CPU { uint32_t dwCPUType; uint32_t dwFeatures; uint32_t dwExtendedFeatures; }; enum CORINFO_RUNTIME_ABI { CORINFO_DESKTOP_ABI = 0x100, CORINFO_CORECLR_ABI = 0x200, CORINFO_NATIVEAOT_ABI = 0x300, }; // For some highly optimized paths, the JIT must generate code that directly // manipulates internal EE data structures. The getEEInfo() helper returns // this structure containing the needed offsets and values. struct CORINFO_EE_INFO { // Information about the InlinedCallFrame structure layout struct InlinedCallFrameInfo { // Size of the Frame structure unsigned size; unsigned offsetOfGSCookie; unsigned offsetOfFrameVptr; unsigned offsetOfFrameLink; unsigned offsetOfCallSiteSP; unsigned offsetOfCalleeSavedFP; unsigned offsetOfCallTarget; unsigned offsetOfReturnAddress; // This offset is used only for ARM unsigned offsetOfSPAfterProlog; } inlinedCallFrameInfo; // Offsets into the Thread structure unsigned offsetOfThreadFrame; // offset of the current Frame unsigned offsetOfGCState; // offset of the preemptive/cooperative state of the Thread // Delegate offsets unsigned offsetOfDelegateInstance; unsigned offsetOfDelegateFirstTarget; // Wrapper delegate offsets unsigned offsetOfWrapperDelegateIndirectCell; // Reverse PInvoke offsets unsigned sizeOfReversePInvokeFrame; // OS Page size size_t osPageSize; // Null object offset size_t maxUncheckedOffsetForNullObject; // Target ABI. Combined with target architecture and OS to determine // GC, EH, and unwind styles. CORINFO_RUNTIME_ABI targetAbi; CORINFO_OS osType; }; // Flags passed from JIT to runtime. enum CORINFO_GET_TAILCALL_HELPERS_FLAGS { // The callsite is a callvirt instruction. CORINFO_TAILCALL_IS_CALLVIRT = 0x00000001, CORINFO_TAILCALL_THIS_ARG_IS_BYREF = 0x00000002, }; // Flags passed from runtime to JIT. enum CORINFO_TAILCALL_HELPERS_FLAGS { // The StoreArgs stub needs to be passed the target function pointer as the // first argument. CORINFO_TAILCALL_STORE_TARGET = 0x00000001, }; struct CORINFO_TAILCALL_HELPERS { CORINFO_TAILCALL_HELPERS_FLAGS flags; CORINFO_METHOD_HANDLE hStoreArgs; CORINFO_METHOD_HANDLE hCallTarget; CORINFO_METHOD_HANDLE hDispatcher; }; // This is used to indicate that a finally has been called // "locally" by the try block enum { LCL_FINALLY_MARK = 0xFC }; // FC = "Finally Call" /********************************************************************************** * The following is the internal structure of an object that the compiler knows about * when it generates code **********************************************************************************/ typedef void* CORINFO_MethodPtr; // a generic method pointer struct CORINFO_Object { CORINFO_MethodPtr *methTable; // the vtable for the object }; struct CORINFO_String : public CORINFO_Object { unsigned stringLen; char16_t chars[1]; // actually of variable size }; struct CORINFO_Array : public CORINFO_Object { unsigned length; #ifdef HOST_64BIT unsigned alignpad; #endif // HOST_64BIT #if 0 // Multi-dimensional arrays have the dimension lengths and bounds here. // The element count of these arrays is the array rank (the number of dimensions in the // multi-dimensional array). So, there is one element for each dimension. The upper bound // of a dimension is `dimBound[d] + dimLength[d] - 1`. int dimLength[rank]; // Number of array elements in each dimension. int dimBound[rank]; // Lower bound of each dimension (possibly negative). #endif union { int8_t i1Elems[1]; // actually of variable size uint8_t u1Elems[1]; int16_t i2Elems[1]; uint16_t u2Elems[1]; int32_t i4Elems[1]; uint32_t u4Elems[1]; float r4Elems[1]; }; }; struct CORINFO_Array8 : public CORINFO_Object { unsigned length; #ifdef HOST_64BIT unsigned alignpad; #endif // HOST_64BIT union { double r8Elems[1]; int64_t i8Elems[1]; uint64_t u8Elems[1]; }; }; struct CORINFO_RefArray : public CORINFO_Object { unsigned length; #ifdef HOST_64BIT unsigned alignpad; #endif // HOST_64BIT #if 0 /* Multi-dimensional arrays have the lengths and bounds here */ unsigned dimLength[length]; unsigned dimBound[length]; #endif CORINFO_Object* refElems[1]; // actually of variable size; }; struct CORINFO_RefAny { void * dataPtr; CORINFO_CLASS_HANDLE type; }; // The jit assumes the CORINFO_VARARGS_HANDLE is a pointer to a subclass of this struct CORINFO_VarArgInfo { unsigned argBytes; // number of bytes the arguments take up. // (The CORINFO_VARARGS_HANDLE counts as an arg) }; #define SIZEOF__CORINFO_Object TARGET_POINTER_SIZE /* methTable */ #define CORINFO_Array_MaxLength 0x7FFFFFC7 #define CORINFO_String_MaxLength 0x3FFFFFDF #define OFFSETOF__CORINFO_Array__length SIZEOF__CORINFO_Object #ifdef TARGET_64BIT #define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(uint32_t) /* length */ + sizeof(uint32_t) /* alignpad */) #else #define OFFSETOF__CORINFO_Array__data (OFFSETOF__CORINFO_Array__length + sizeof(uint32_t) /* length */) #endif #define OFFSETOF__CORINFO_TypedReference__dataPtr 0 #define OFFSETOF__CORINFO_TypedReference__type (OFFSETOF__CORINFO_TypedReference__dataPtr + TARGET_POINTER_SIZE /* dataPtr */) #define OFFSETOF__CORINFO_String__stringLen SIZEOF__CORINFO_Object #define OFFSETOF__CORINFO_String__chars (OFFSETOF__CORINFO_String__stringLen + sizeof(uint32_t) /* stringLen */) #define OFFSETOF__CORINFO_NullableOfT__hasValue 0 /* data to optimize delegate construction */ struct DelegateCtorArgs { void * pMethod; void * pArg3; void * pArg4; void * pArg5; }; // use offsetof to get the offset of the fields above #include // offsetof // Guard-stack cookie for preventing against stack buffer overruns typedef size_t GSCookie; #include "cordebuginfo.h" /**********************************************************************************/ // Some compilers cannot arbitrarily allow the handler nesting level to grow // arbitrarily during Edit'n'Continue. // This is the maximum nesting level that a compiler needs to support for EnC const int MAX_EnC_HANDLER_NESTING_LEVEL = 6; // Results from type comparison queries enum class TypeCompareState { MustNot = -1, // types are not equal May = 0, // types may be equal (must test at runtime) Must = 1, // type are equal }; // // This interface is logically split into sections for each class of information // (ICorMethodInfo, ICorModuleInfo, etc.). This split used to exist physically as well // using virtual inheritance, but was eliminated to improve efficiency of the JIT-EE // interface calls. // class ICorStaticInfo { public: /**********************************************************************************/ // // ICorMethodInfo // /**********************************************************************************/ // Quick check whether the method is a jit intrinsic. Returns the same value as getMethodAttribs(ftn) & CORINFO_FLG_INTRINSIC, except faster. virtual bool isIntrinsic(CORINFO_METHOD_HANDLE ftn) = 0; // return flags (a bitfield of CorInfoFlags values) virtual uint32_t getMethodAttribs ( CORINFO_METHOD_HANDLE ftn /* IN */ ) = 0; // sets private JIT flags, which can be, retrieved using getAttrib. virtual void setMethodAttribs ( CORINFO_METHOD_HANDLE ftn, /* IN */ CorInfoMethodRuntimeFlags attribs /* IN */ ) = 0; // Given a method descriptor ftnHnd, extract signature information into sigInfo // // 'memberParent' is typically only set when verifying. It should be the // result of calling getMemberParent. virtual void getMethodSig ( CORINFO_METHOD_HANDLE ftn, /* IN */ CORINFO_SIG_INFO *sig, /* OUT */ CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ ) = 0; /********************************************************************* * Note the following methods can only be used on functions known * to be IL. This includes the method being compiled and any method * that 'getMethodInfo' returns true for *********************************************************************/ // return information about a method private to the implementation // returns false if method is not IL, or is otherwise unavailable. // This method is used to fetch data needed to inline functions virtual bool getMethodInfo ( CORINFO_METHOD_HANDLE ftn, /* IN */ CORINFO_METHOD_INFO* info /* OUT */ ) = 0; // Decides if you have any limitations for inlining. If everything's OK, it will return // INLINE_PASS. // // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls) // // The inlined method need not be verified virtual CorInfoInline canInline ( CORINFO_METHOD_HANDLE callerHnd, /* IN */ CORINFO_METHOD_HANDLE calleeHnd /* IN */ ) = 0; // Report that an inlining related process has begun. This will always be paired with // a call to reportInliningDecision unless the jit fails. virtual void beginInlining (CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd) = 0; // Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the // JIT. virtual void reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char * reason) = 0; // Returns false if the call is across security boundaries thus we cannot tailcall // // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls) virtual bool canTailCall ( CORINFO_METHOD_HANDLE callerHnd, /* IN */ CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */ CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */ bool fIsTailPrefix /* IN */ ) = 0; // Reports whether or not a method can be tail called, and why. // canTailCall is responsible for reporting all results when it returns // false. All other results are reported by the JIT. virtual void reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char * reason) = 0; // get individual exception handler virtual void getEHinfo( CORINFO_METHOD_HANDLE ftn, /* IN */ unsigned EHnumber, /* IN */ CORINFO_EH_CLAUSE* clause /* OUT */ ) = 0; // return class it belongs to virtual CORINFO_CLASS_HANDLE getMethodClass ( CORINFO_METHOD_HANDLE method ) = 0; // return module it belongs to virtual CORINFO_MODULE_HANDLE getMethodModule ( CORINFO_METHOD_HANDLE method ) = 0; // This function returns the offset of the specified method in the // vtable of it's owning class or interface. virtual void getMethodVTableOffset ( CORINFO_METHOD_HANDLE method, /* IN */ unsigned* offsetOfIndirection, /* OUT */ unsigned* offsetAfterIndirection, /* OUT */ bool* isRelative /* OUT */ ) = 0; // Finds the virtual method in info->objClass that overrides info->virtualMethod, // or the method in info->objClass that implements the interface method // represented by info->virtualMethod. // // Returns false if devirtualization is not possible. virtual bool resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info) = 0; // Get the unboxed entry point for a method, if possible. virtual CORINFO_METHOD_HANDLE getUnboxedEntry( CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg ) = 0; // Given T, return the type of the default Comparer. // Returns null if the type can't be determined exactly. virtual CORINFO_CLASS_HANDLE getDefaultComparerClass( CORINFO_CLASS_HANDLE elemType ) = 0; // Given T, return the type of the default EqualityComparer. // Returns null if the type can't be determined exactly. virtual CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass( CORINFO_CLASS_HANDLE elemType ) = 0; // Given resolved token that corresponds to an intrinsic classified to // get a raw handle (NI_System_Activator_AllocatorOf etc.), fetch the // handle associated with the token. If this is not possible at // compile-time (because the current method's code is shared and the // token contains generic parameters) then indicate how the handle // should be looked up at runtime. virtual void expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_GENERICHANDLE_RESULT * pResult) = 0; // Is the given type in System.Private.Corelib and marked with IntrinsicAttribute? // This defaults to false. virtual bool isIntrinsicType( CORINFO_CLASS_HANDLE classHnd ) { return false; } // return the entry point calling convention for any of the following // - a P/Invoke // - a method marked with UnmanagedCallersOnly // - a function pointer with the CORINFO_CALLCONV_UNMANAGED calling convention. virtual CorInfoCallConvExtension getUnmanagedCallConv( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig, bool* pSuppressGCTransition /* OUT */ ) = 0; // return if any marshaling is required for PInvoke methods. Note that // method == 0 => calli. The call site sig is only needed for the varargs or calli case virtual bool pInvokeMarshalingRequired( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig ) = 0; // Check constraints on method type arguments (only). // The parent class should be checked separately using satisfiesClassConstraints(parent). virtual bool satisfiesMethodConstraints( CORINFO_CLASS_HANDLE parent, // the exact parent of the method CORINFO_METHOD_HANDLE method ) = 0; // Given a delegate target class, a target method parent class, a target method, // a delegate class, check if the method signature is compatible with the Invoke method of the delegate // (under the typical instantiation of any free type variables in the memberref signatures). virtual bool isCompatibleDelegate( CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */ CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */ CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */ CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */ bool *pfIsOpenDelegate /* is the delegate open */ ) = 0; // load and restore the method virtual void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method ) = 0; virtual CORINFO_METHOD_HANDLE mapMethodDeclToMethodImpl( CORINFO_METHOD_HANDLE method ) = 0; // Returns the global cookie for the /GS unsafe buffer checks // The cookie might be a constant value (JIT), or a handle to memory location (Ngen) virtual void getGSCookie( GSCookie * pCookieVal, // OUT GSCookie ** ppCookieVal // OUT ) = 0; // Provide patchpoint info for the method currently being jitted. virtual void setPatchpointInfo( PatchpointInfo* patchpointInfo ) = 0; // Get patchpoint info and il offset for the method currently being jitted. virtual PatchpointInfo* getOSRInfo( unsigned *ilOffset // [OUT] il offset of OSR entry point ) = 0; /**********************************************************************************/ // // ICorModuleInfo // /**********************************************************************************/ // Resolve metadata token into runtime method handles. This function may not // return normally (e.g. it may throw) if it encounters invalid metadata or other // failures during token resolution. virtual void resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0; // Attempt to resolve a metadata token into a runtime method handle. Returns true // if resolution succeeded and false otherwise (e.g. if it encounters invalid metadata // during token reoslution). This method should be used instead of `resolveToken` in // situations that need to be resilient to invalid metadata. virtual bool tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken) = 0; // Signature information about the call sig virtual void findSig ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned sigTOK, /* IN */ CORINFO_CONTEXT_HANDLE context, /* IN */ CORINFO_SIG_INFO *sig /* OUT */ ) = 0; // for Varargs, the signature at the call site may differ from // the signature at the definition. Thus we need a way of // fetching the call site information virtual void findCallSiteSig ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned methTOK, /* IN */ CORINFO_CONTEXT_HANDLE context, /* IN */ CORINFO_SIG_INFO *sig /* OUT */ ) = 0; virtual CORINFO_CLASS_HANDLE getTokenTypeAsHandle ( CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */) = 0; // Checks if the given metadata token is valid virtual bool isValidToken ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK /* IN */ ) = 0; // Checks if the given metadata token is valid StringRef virtual bool isValidStringRef ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK /* IN */ ) = 0; // Returns (sub)string length and content (can be null for dynamic context) // for given metaTOK and module, length `-1` means input is incorrect virtual int getStringLiteral ( CORINFO_MODULE_HANDLE module, /* IN */ unsigned metaTOK, /* IN */ char16_t* buffer, /* OUT */ int bufferSize, /* IN */ int startIndex = 0 /* IN */ ) = 0; //------------------------------------------------------------------------------ // printObjectDescription: Prints a (possibly truncated) textual UTF8 representation of the given // object to a preallocated buffer. It's intended to be used only for debug/diagnostic // purposes such as JitDisasm. The buffer is null-terminated (even if truncated). // // Arguments: // handle - Direct object handle // buffer - Pointer to buffer. Can be nullptr. // bufferSize - Buffer size (in bytes). // pRequiredBufferSize - Full length of the textual UTF8 representation, in bytes. // Includes the null terminator, so the value is always at least 1, // where 1 indicates an empty string. // Can be used to call this API again with a bigger buffer to get the full // string. // // Return Value: // Bytes written to the buffer, excluding the null terminator. The range is [0..bufferSize). // If bufferSize is 0, returns 0. // // Remarks: // buffer and bufferSize can be respectively nullptr and 0 to query just the required buffer size. // // If the return value is less than bufferSize - 1 then the full string was written. In this case // it is guaranteed that return value == *pRequiredBufferSize - 1. // virtual size_t printObjectDescription ( CORINFO_OBJECT_HANDLE handle, /* IN */ char* buffer, /* OUT */ size_t bufferSize, /* IN */ size_t* pRequiredBufferSize = nullptr /* OUT */ ) = 0; /**********************************************************************************/ // // ICorClassInfo // /**********************************************************************************/ // If the value class 'cls' is isomorphic to a primitive type it will // return that type, otherwise it will return CORINFO_TYPE_VALUECLASS virtual CorInfoType asCorInfoType ( CORINFO_CLASS_HANDLE cls ) = 0; // Return class name as in metadata, or nullptr if there is none. // Suitable for non-debugging use. virtual const char* getClassNameFromMetadata ( CORINFO_CLASS_HANDLE cls, const char **namespaceName /* OUT */ ) = 0; // Return the type argument of the instantiated generic class, // which is specified by the index virtual CORINFO_CLASS_HANDLE getTypeInstantiationArgument( CORINFO_CLASS_HANDLE cls, unsigned index ) = 0; // Prints the name for a specified class including namespaces and enclosing // classes. // See printObjectDescription for documentation for the parameters. virtual size_t printClassName( CORINFO_CLASS_HANDLE cls, /* IN */ char* buffer, /* OUT */ size_t bufferSize, /* IN */ size_t* pRequiredBufferSize = nullptr /* OUT */ ) = 0; // Quick check whether the type is a value class. Returns the same value as getClassAttribs(cls) & CORINFO_FLG_VALUECLASS, except faster. virtual bool isValueClass(CORINFO_CLASS_HANDLE cls) = 0; // Decides how the JIT should do the optimization to inline the check for // GetTypeFromHandle(handle) == obj.GetType() (for CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE) // GetTypeFromHandle(X) == GetTypeFromHandle(Y) (for CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN) virtual CorInfoInlineTypeCheck canInlineTypeCheck(CORINFO_CLASS_HANDLE cls, CorInfoInlineTypeCheckSource source) = 0; // return flags (a bitfield of CorInfoFlags values) virtual uint32_t getClassAttribs ( CORINFO_CLASS_HANDLE cls ) = 0; virtual CORINFO_MODULE_HANDLE getClassModule ( CORINFO_CLASS_HANDLE cls ) = 0; // Returns the assembly that contains the module "mod". virtual CORINFO_ASSEMBLY_HANDLE getModuleAssembly ( CORINFO_MODULE_HANDLE mod ) = 0; // Returns the name of the assembly "assem". virtual const char* getAssemblyName ( CORINFO_ASSEMBLY_HANDLE assem ) = 0; // Allocate and delete process-lifetime objects. Should only be // referred to from static fields, lest a leak occur. // Note that "LongLifetimeFree" does not execute destructors, if "obj" // is an array of a struct type with a destructor. virtual void* LongLifetimeMalloc(size_t sz) = 0; virtual void LongLifetimeFree(void* obj) = 0; virtual size_t getClassModuleIdForStatics ( CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection ) = 0; // return the number of bytes needed by an instance of the class virtual unsigned getClassSize ( CORINFO_CLASS_HANDLE cls ) = 0; // return the number of bytes needed by an instance of the class allocated on the heap virtual unsigned getHeapClassSize( CORINFO_CLASS_HANDLE cls ) = 0; virtual bool canAllocateOnStack( CORINFO_CLASS_HANDLE cls ) = 0; virtual unsigned getClassAlignmentRequirement ( CORINFO_CLASS_HANDLE cls, bool fDoubleAlignHint = false ) = 0; // This is only called for Value classes. It returns a boolean array // in representing of 'cls' from a GC perspective. The class is // assumed to be an array of machine words // (of length // getClassSize(cls) / TARGET_POINTER_SIZE), // 'gcPtrs' is a pointer to an array of uint8_ts of this length. // getClassGClayout fills in this array so that gcPtrs[i] is set // to one of the CorInfoGCType values which is the GC type of // the i-th machine word of an object of type 'cls' // returns the number of GC pointers in the array virtual unsigned getClassGClayout ( CORINFO_CLASS_HANDLE cls, /* IN */ uint8_t *gcPtrs /* OUT */ ) = 0; // returns the number of instance fields in a class virtual unsigned getClassNumInstanceFields ( CORINFO_CLASS_HANDLE cls /* IN */ ) = 0; virtual CORINFO_FIELD_HANDLE getFieldInClass( CORINFO_CLASS_HANDLE clsHnd, int32_t num ) = 0; virtual bool checkMethodModifier( CORINFO_METHOD_HANDLE hMethod, const char * modifier, bool fOptional ) = 0; // returns the "NEW" helper optimized for "newCls." virtual CorInfoHelpFunc getNewHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, bool * pHasSideEffects ) = 0; // returns the newArr (1-Dim array) helper optimized for "arrayCls." virtual CorInfoHelpFunc getNewArrHelper( CORINFO_CLASS_HANDLE arrayCls ) = 0; // returns the optimized "IsInstanceOf" or "ChkCast" helper virtual CorInfoHelpFunc getCastingHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing ) = 0; // returns helper to trigger static constructor virtual CorInfoHelpFunc getSharedCCtorHelper( CORINFO_CLASS_HANDLE clsHnd ) = 0; // This is not pretty. Boxing nullable actually returns // a boxed not a boxed Nullable. This call allows the verifier // to call back to the EE on the 'box' instruction and get the transformed // type to use for verification. virtual CORINFO_CLASS_HANDLE getTypeForBox( CORINFO_CLASS_HANDLE cls ) = 0; // returns the correct box helper for a particular class. Note // that if this returns CORINFO_HELP_BOX, the JIT can assume // 'standard' boxing (allocate object and copy), and optimize virtual CorInfoHelpFunc getBoxHelper( CORINFO_CLASS_HANDLE cls ) = 0; // returns the unbox helper. If 'helperCopies' points to a true // value it means the JIT is requesting a helper that unboxes the // value into a particular location and thus has the signature // void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj) // Otherwise (it is null or points at a FALSE value) it is requesting // a helper that returns a pointer to the unboxed data // void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj) // The EE has the option of NOT returning the copy style helper // (But must be able to always honor the non-copy style helper) // The EE set 'helperCopies' on return to indicate what kind of // helper has been created. virtual CorInfoHelpFunc getUnBoxHelper( CORINFO_CLASS_HANDLE cls ) = 0; virtual CORINFO_OBJECT_HANDLE getRuntimeTypePointer( CORINFO_CLASS_HANDLE cls ) = 0; //------------------------------------------------------------------------------ // isObjectImmutable: checks whether given object is known to be immutable or not // // Arguments: // objPtr - Direct object handle // // Return Value: // Returns true if object is known to be immutable // virtual bool isObjectImmutable( CORINFO_OBJECT_HANDLE objPtr ) = 0; //------------------------------------------------------------------------------ // getStringChar: returns char at the given index if the given object handle // represents String and index is not out of bounds. // // Arguments: // strObj - object handle // index - index of the char to return // value - output char // // Return Value: // Returns true if value was successfully obtained // virtual bool getStringChar( CORINFO_OBJECT_HANDLE strObj, int index, uint16_t* value) = 0; //------------------------------------------------------------------------------ // getObjectType: obtains type handle for given object // // Arguments: // objPtr - Direct object handle // // Return Value: // Returns CORINFO_CLASS_HANDLE handle that represents given object's type // virtual CORINFO_CLASS_HANDLE getObjectType( CORINFO_OBJECT_HANDLE objPtr ) = 0; virtual bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP * pLookup ) = 0; virtual void getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP * pLookup ) = 0; // This function tries to initialize the class (run the class constructor). // this function returns whether the JIT must insert helper calls before // accessing static field or method. // // See code:ICorClassInfo#ClassConstruction. virtual CorInfoInitClassResult initClass( CORINFO_FIELD_HANDLE field, // Non-NULL - inquire about cctor trigger before static field access // NULL - inquire about cctor trigger in method prolog CORINFO_METHOD_HANDLE method, // Method referencing the field or prolog // NULL - method being compiled CORINFO_CONTEXT_HANDLE context // Exact context of method ) = 0; // This used to be called "loadClass". This records the fact // that the class must be loaded (including restored if necessary) before we execute the // code that we are currently generating. When jitting code // the function loads the class immediately. When zapping code // the zapper will if necessary use the call to record the fact that we have // to do a fixup/restore before running the method currently being generated. // // This is typically used to ensure value types are loaded before zapped // code that manipulates them is executed, so that the GC can access information // about those value types. virtual void classMustBeLoadedBeforeCodeIsRun( CORINFO_CLASS_HANDLE cls ) = 0; // returns the class handle for the special builtin classes virtual CORINFO_CLASS_HANDLE getBuiltinClass ( CorInfoClassId classId ) = 0; // "System.Int32" ==> CORINFO_TYPE_INT.. virtual CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls ) = 0; // "System.Int32" ==> CORINFO_TYPE_INT.. // "System.UInt32" ==> CORINFO_TYPE_UINT.. virtual CorInfoType getTypeForPrimitiveNumericClass( CORINFO_CLASS_HANDLE cls ) = 0; // TRUE if child is a subtype of parent // if parent is an interface, then does child implement / extend parent virtual bool canCast( CORINFO_CLASS_HANDLE child, // subtype (extends parent) CORINFO_CLASS_HANDLE parent // base type ) = 0; // TRUE if cls1 and cls2 are considered equivalent types. virtual bool areTypesEquivalent( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2 ) = 0; // See if a cast from fromClass to toClass will succeed, fail, or needs // to be resolved at runtime. virtual TypeCompareState compareTypesForCast( CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass ) = 0; // See if types represented by cls1 and cls2 compare equal, not // equal, or the comparison needs to be resolved at runtime. virtual TypeCompareState compareTypesForEquality( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2 ) = 0; // Returns the intersection of cls1 and cls2. virtual CORINFO_CLASS_HANDLE mergeClasses( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2 ) = 0; // Returns true if cls2 is known to be a more specific type // than cls1 (a subtype or more restrictive shared type) // for purposes of jit type tracking. This is a hint to the // jit for optimization; it does not have correctness // implications. virtual bool isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2 ) = 0; // Returns TypeCompareState::Must if cls is known to be an enum. // For enums with known exact type returns the underlying // type in underlyingType when the provided pointer is // non-NULL. // Returns TypeCompareState::May when a runtime check is required. virtual TypeCompareState isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType ) = 0; // Given a class handle, returns the Parent type. // For COMObjectType, it returns Class Handle of System.Object. // Returns 0 if System.Object is passed in. virtual CORINFO_CLASS_HANDLE getParentType ( CORINFO_CLASS_HANDLE cls ) = 0; // Returns the CorInfoType of the "child type". If the child type is // not a primitive type, *clsRet will be set. // Given an Array of Type Foo, returns Foo. // Given BYREF Foo, returns Foo virtual CorInfoType getChildType ( CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE *clsRet ) = 0; // Check constraints on type arguments of this class and parent classes virtual bool satisfiesClassConstraints( CORINFO_CLASS_HANDLE cls ) = 0; // Check if this is a single dimensional array type virtual bool isSDArray( CORINFO_CLASS_HANDLE cls ) = 0; // Get the numbmer of dimensions in an array virtual unsigned getArrayRank( CORINFO_CLASS_HANDLE cls ) = 0; // Get the index of runtime provided array method virtual CorInfoArrayIntrinsic getArrayIntrinsicID( CORINFO_METHOD_HANDLE ftn ) = 0; // Get static field data for an array virtual void * getArrayInitializationData( CORINFO_FIELD_HANDLE field, uint32_t size ) = 0; // Check Visibility rules. virtual CorInfoIsAccessAllowedResult canAccessClass( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_HELPER_DESC *pAccessHelper /* If canAccessMethod returns something other than ALLOWED, then this is filled in. */ ) = 0; /**********************************************************************************/ // // ICorFieldInfo // /**********************************************************************************/ // Prints the name of a field into a buffer. See printObjectDescription for more documentation. virtual size_t printFieldName( CORINFO_FIELD_HANDLE field, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize = nullptr ) = 0; // return class it belongs to virtual CORINFO_CLASS_HANDLE getFieldClass ( CORINFO_FIELD_HANDLE field ) = 0; // Return the field's type, if it is CORINFO_TYPE_VALUECLASS 'structType' is set // the field's value class (if 'structType' == 0, then don't bother // the structure info). // // 'memberParent' is typically only set when verifying. It should be the // result of calling getMemberParent. virtual CorInfoType getFieldType( CORINFO_FIELD_HANDLE field, CORINFO_CLASS_HANDLE *structType = NULL, CORINFO_CLASS_HANDLE memberParent = NULL /* IN */ ) = 0; // return the data member's instance offset virtual unsigned getFieldOffset( CORINFO_FIELD_HANDLE field ) = 0; virtual void getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO *pResult ) = 0; // Returns true iff "fldHnd" represents a static field. virtual bool isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) = 0; // Returns Length of an Array or of a String object, otherwise -1. // objHnd must not be null. virtual int getArrayOrStringLength(CORINFO_OBJECT_HANDLE objHnd) = 0; /*********************************************************************************/ // // ICorDebugInfo // /*********************************************************************************/ // Query the EE to find out where interesting break points // in the code are. The native compiler will ensure that these places // have a corresponding break point in native code. // // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. virtual void getBoundaries( CORINFO_METHOD_HANDLE ftn, // [IN] method of interest unsigned int *cILOffsets, // [OUT] size of pILOffsets uint32_t **pILOffsets, // [OUT] IL offsets of interest // jit MUST free with freeArray! ICorDebugInfo::BoundaryTypes *implicitBoundaries // [OUT] tell jit, all boundaries of this type ) = 0; // Report back the mapping from IL to native code, // this map should include all boundaries that 'getBoundaries' // reported as interesting to the debugger. // Note that debugger (and profiler) is assuming that all of the // offsets form a contiguous block of memory, and that the // OffsetMapping is sorted in order of increasing native offset. virtual void setBoundaries( CORINFO_METHOD_HANDLE ftn, // [IN] method of interest uint32_t cMap, // [IN] size of pMap ICorDebugInfo::OffsetMapping *pMap // [IN] map including all points of interest. // jit allocated with allocateArray, EE frees ) = 0; // Query the EE to find out the scope of local variables. // normally the JIT would trash variables after last use, but // under debugging, the JIT needs to keep them live over their // entire scope so that they can be inspected. // // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will // be used only as a hint and the native compiler should not change its // code generation. virtual void getVars( CORINFO_METHOD_HANDLE ftn, // [IN] method of interest uint32_t *cVars, // [OUT] size of 'vars' ICorDebugInfo::ILVarInfo **vars, // [OUT] scopes of variables of interest // jit MUST free with freeArray! bool *extendOthers // [OUT] it TRUE, then assume the scope // of unmentioned vars is entire method ) = 0; // Report back to the EE the location of every variable. // note that the JIT might split lifetimes into different // locations etc. virtual void setVars( CORINFO_METHOD_HANDLE ftn, // [IN] method of interest uint32_t cVars, // [IN] size of 'vars' ICorDebugInfo::NativeVarInfo *vars // [IN] map telling where local vars are stored at what points // jit allocated with allocateArray, EE frees ) = 0; // Report inline tree and rich offset mappings to EE. // The arrays are expected to be allocated with allocateArray // and ownership is transferred to the EE with this call. virtual void reportRichMappings( ICorDebugInfo::InlineTreeNode* inlineTreeNodes, // [IN] Nodes of the inline tree uint32_t numInlineTreeNodes, // [IN] Number of nodes in the inline tree ICorDebugInfo::RichOffsetMapping* mappings, // [IN] Rich mappings uint32_t numMappings // [IN] Number of rich mappings ) = 0; /*-------------------------- Misc ---------------------------------------*/ // Used to allocate memory that needs to handed to the EE. // For eg, use this to allocated memory for reporting debug info, // which will be handed to the EE by setVars() and setBoundaries() virtual void * allocateArray( size_t cBytes ) = 0; // JitCompiler will free arrays passed by the EE using this // For eg, The EE returns memory in getVars() and getBoundaries() // to the JitCompiler, which the JitCompiler should release using // freeArray() virtual void freeArray( void *array ) = 0; /*********************************************************************************/ // // ICorArgInfo // /*********************************************************************************/ // advance the pointer to the argument list. // a ptr of 0, is special and always means the first argument virtual CORINFO_ARG_LIST_HANDLE getArgNext ( CORINFO_ARG_LIST_HANDLE args /* IN */ ) = 0; // Get the type of a particular argument // CORINFO_TYPE_UNDEF is returned when there are no more arguments // If the type returned is a primitive type (or an enum) *vcTypeRet set to NULL // otherwise it is set to the TypeHandle associted with the type // Enumerations will always look their underlying type (probably should fix this) // Otherwise vcTypeRet is the type as would be seen by the IL, // The return value is the type that is used for calling convention purposes // (Thus if the EE wants a value class to be passed like an int, then it will // return CORINFO_TYPE_INT virtual CorInfoTypeWithMod getArgType ( CORINFO_SIG_INFO* sig, /* IN */ CORINFO_ARG_LIST_HANDLE args, /* IN */ CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */ ) = 0; // Obtains a list of exact classes for a given base type. Returns 0 if the number of // the exact classes is greater than maxExactClasses or if more types might be loaded // in future. virtual int getExactClasses( CORINFO_CLASS_HANDLE baseType, /* IN */ int maxExactClasses, /* IN */ CORINFO_CLASS_HANDLE* exactClsRet /* OUT */ ) = 0; // If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it virtual CORINFO_CLASS_HANDLE getArgClass ( CORINFO_SIG_INFO* sig, /* IN */ CORINFO_ARG_LIST_HANDLE args /* IN */ ) = 0; // Returns type of HFA for valuetype virtual CorInfoHFAElemType getHFAType ( CORINFO_CLASS_HANDLE hClass ) = 0; /***************************************************************************** * ICorErrorInfo contains methods to deal with SEH exceptions being thrown * from the corinfo interface. These methods may be called when an exception * with code EXCEPTION_COMPLUS is caught. *****************************************************************************/ // Returns the HRESULT of the current exception virtual JITINTERFACE_HRESULT GetErrorHRESULT( struct _EXCEPTION_POINTERS *pExceptionPointers ) = 0; // Fetches the message of the current exception // Returns the size of the message (including terminating null). This can be // greater than bufferLength if the buffer is insufficient. virtual uint32_t GetErrorMessage( _Inout_updates_(bufferLength) char16_t *buffer, uint32_t bufferLength ) = 0; // returns EXCEPTION_EXECUTE_HANDLER if it is OK for the compile to handle the // exception, abort some work (like the inlining) and continue compilation // returns EXCEPTION_CONTINUE_SEARCH if exception must always be handled by the EE // things like ThreadStoppedException ... // returns EXCEPTION_CONTINUE_EXECUTION if exception is fixed up by the EE // Only used as a contract between the Zapper and the VM. virtual int FilterException( struct _EXCEPTION_POINTERS *pExceptionPointers ) = 0; virtual void ThrowExceptionForJitResult( JITINTERFACE_HRESULT result) = 0; //Throws an exception defined by the given throw helper. virtual void ThrowExceptionForHelper( const CORINFO_HELPER_DESC * throwHelper) = 0; // Runs the given function under an error trap. This allows the JIT to make calls // to interface functions that may throw exceptions without needing to be aware of // the EH ABI, exception types, etc. Returns true if the given function completed // successfully and false otherwise. typedef void (*errorTrapFunction)(void*); virtual bool runWithErrorTrap( errorTrapFunction function, // The function to run void* parameter // The context parameter that will be passed to the function and the handler ) = 0; // Runs the given function under an error trap. This allows the JIT to make calls // to interface functions that may throw exceptions without needing to be aware of // the EH ABI, exception types, etc. Returns true if the given function completed // successfully and false otherwise. This error trap checks for SuperPMI exceptions virtual bool runWithSPMIErrorTrap( errorTrapFunction function, // The function to run void* parameter // The context parameter that will be passed to the function and the handler ) = 0; /***************************************************************************** * ICorStaticInfo contains EE interface methods which return values that are * constant from invocation to invocation. Thus they may be embedded in * persisted information like statically generated code. (This is of course * assuming that all code versions are identical each time.) *****************************************************************************/ // Return details about EE internal data structures virtual void getEEInfo( CORINFO_EE_INFO *pEEInfoOut ) = 0; // Returns name of the JIT timer log virtual const char16_t *getJitTimeLogFilename() = 0; /*********************************************************************************/ // // Diagnostic methods // /*********************************************************************************/ // this function is for debugging only. Returns method token. // Returns mdMethodDefNil for dynamic methods. virtual mdMethodDef getMethodDefFromMethod( CORINFO_METHOD_HANDLE hMethod ) = 0; // This is similar to getMethodNameFromMetadata except that it also returns // reasonable names for functions without metadata. // See printObjectDescription for documentation of parameters. virtual size_t printMethodName( CORINFO_METHOD_HANDLE ftn, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize = nullptr) = 0; // Return method name as in metadata, or nullptr if there is none, // and optionally return the class, enclosing class, and namespace names // as in metadata. // Suitable for non-debugging use. virtual const char* getMethodNameFromMetadata( CORINFO_METHOD_HANDLE ftn, /* IN */ const char **className, /* OUT */ const char **namespaceName, /* OUT */ const char **enclosingClassName /* OUT */ ) = 0; // this function is for debugging only. It returns a value that // is will always be the same for a given method. It is used // to implement the 'jitRange' functionality virtual unsigned getMethodHash ( CORINFO_METHOD_HANDLE ftn /* IN */ ) = 0; // this function is for debugging only. virtual size_t findNameOfToken ( CORINFO_MODULE_HANDLE module, /* IN */ mdToken metaTOK, /* IN */ _Out_writes_ (FQNameCapacity) char * szFQName, /* OUT */ size_t FQNameCapacity /* IN */ ) = 0; // returns whether the struct is enregisterable. Only valid on a System V VM. Returns true on success, false on failure. virtual bool getSystemVAmd64PassStructInRegisterDescriptor( /* IN */ CORINFO_CLASS_HANDLE structHnd, /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr ) = 0; virtual uint32_t getLoongArch64PassStructInRegisterFlags(CORINFO_CLASS_HANDLE cls) = 0; }; /***************************************************************************** * ICorDynamicInfo contains EE interface methods which return values that may * change from invocation to invocation. They cannot be embedded in persisted * data; they must be requeried each time the EE is run. *****************************************************************************/ class ICorDynamicInfo : public ICorStaticInfo { public: // // These methods return values to the JIT which are not constant // from session to session. // // These methods take an extra parameter : void **ppIndirection. // If a JIT supports generation of prejit code (install-o-jit), it // must pass a non-null value for this parameter, and check the // resulting value. If *ppIndirection is NULL, code should be // generated normally. If non-null, then the value of // *ppIndirection is an address in the cookie table, and the code // generator needs to generate an indirection through the table to // get the resulting value. In this case, the return result of the // function must NOT be directly embedded in the generated code. // // Note that if a JIT does not support prejit code generation, it // may ignore the extra parameter & pass the default of NULL - the // prejit ICorDynamicInfo implementation will see this & generate // an error if the jitter is used in a prejit scenario. // // Return details about EE internal data structures virtual uint32_t getThreadTLSIndex( void **ppIndirection = NULL ) = 0; virtual const void * getInlinedCallFrameVptr( void **ppIndirection = NULL ) = 0; virtual int32_t * getAddrOfCaptureThreadGlobal( void **ppIndirection = NULL ) = 0; // return the native entry point to an EE helper (see CorInfoHelpFunc) virtual void* getHelperFtn ( CorInfoHelpFunc ftnNum, void **ppIndirection = NULL ) = 0; // return a callable address of the function (native code). This function // may return a different value (depending on whether the method has // been JITed or not. virtual void getFunctionEntryPoint( CORINFO_METHOD_HANDLE ftn, /* IN */ CORINFO_CONST_LOOKUP * pResult, /* OUT */ CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY) = 0; // return a directly callable address. This can be used similarly to the // value returned by getFunctionEntryPoint() except that it is // guaranteed to be multi callable entrypoint. virtual void getFunctionFixedEntryPoint( CORINFO_METHOD_HANDLE ftn, bool isUnsafeFunctionPointer, CORINFO_CONST_LOOKUP * pResult) = 0; // get the synchronization handle that is passed to monXstatic function virtual void* getMethodSync( CORINFO_METHOD_HANDLE ftn, void **ppIndirection = NULL ) = 0; // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used. virtual CorInfoHelpFunc getLazyStringLiteralHelper( CORINFO_MODULE_HANDLE handle ) = 0; virtual CORINFO_MODULE_HANDLE embedModuleHandle( CORINFO_MODULE_HANDLE handle, void **ppIndirection = NULL ) = 0; virtual CORINFO_CLASS_HANDLE embedClassHandle( CORINFO_CLASS_HANDLE handle, void **ppIndirection = NULL ) = 0; virtual CORINFO_METHOD_HANDLE embedMethodHandle( CORINFO_METHOD_HANDLE handle, void **ppIndirection = NULL ) = 0; virtual CORINFO_FIELD_HANDLE embedFieldHandle( CORINFO_FIELD_HANDLE handle, void **ppIndirection = NULL ) = 0; // Given a module scope (module), a method handle (context) and // a metadata token (metaTOK), fetch the handle // (type, field or method) associated with the token. // If this is not possible at compile-time (because the current method's // code is shared and the token contains generic parameters) // then indicate how the handle should be looked up at run-time. // virtual void embedGenericHandle( CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fEmbedParent, // TRUE - embeds parent type handle of the field/method handle CORINFO_GENERICHANDLE_RESULT * pResult) = 0; // Return information used to locate the exact enclosing type of the current method. // Used only to invoke .cctor method from code shared across generic instantiations // !needsRuntimeLookup statically known (enclosing type of method itself) // needsRuntimeLookup: // CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param // CORINFO_LOOKUP_CLASSPARAM use vtable hidden param // CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param virtual void getLocationOfThisType( CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* pLookupKind ) = 0; // return the address of the PInvoke target. May be a fixup area in the // case of late-bound PInvoke calls. virtual void getAddressOfPInvokeTarget( CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup ) = 0; // Generate a cookie based on the signature that would needs to be passed // to CORINFO_HELP_PINVOKE_CALLI virtual void* GetCookieForPInvokeCalliSig( CORINFO_SIG_INFO* szMetaSig, void ** ppIndirection = NULL ) = 0; // returns true if a VM cookie can be generated for it (might be false due to cross-module // inlining, in which case the inlining should be aborted) virtual bool canGetCookieForPInvokeCalliSig( CORINFO_SIG_INFO* szMetaSig ) = 0; // Gets a handle that is checked to see if the current method is // included in "JustMyCode" virtual CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle( CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE**ppIndirection = NULL ) = 0; // Gets a method handle that can be used to correlate profiling data. // This is the IP of a native method, or the address of the descriptor struct // for IL. Always guaranteed to be unique per process, and not to move. */ virtual void GetProfilingHandle( bool *pbHookFunction, void **pProfilerHandle, bool *pbIndirectedHandles ) = 0; // Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values. virtual void getCallInfo( // Token info CORINFO_RESOLVED_TOKEN * pResolvedToken, //Generics info CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, //Security info CORINFO_METHOD_HANDLE callerHandle, //Jit info CORINFO_CALLINFO_FLAGS flags, //out params CORINFO_CALL_INFO *pResult ) = 0; virtual bool canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType) = 0; // Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class // except reflection emitted classes and generics) virtual bool isRIDClassDomainID(CORINFO_CLASS_HANDLE cls) = 0; // returns the class's domain ID for accessing shared statics virtual unsigned getClassDomainID ( CORINFO_CLASS_HANDLE cls, void **ppIndirection = NULL ) = 0; // return the data's address (for static fields only) virtual void* getFieldAddress( CORINFO_FIELD_HANDLE field, void **ppIndirection = NULL ) = 0; //------------------------------------------------------------------------------ // getReadonlyStaticFieldValue: returns true and the actual field's value if the given // field represents a statically initialized readonly field of any type. // // Arguments: // field - field handle // buffer - buffer field's value will be stored to // bufferSize - size of buffer // ignoreMovableObjects - ignore movable reference types or not // // Return Value: // Returns true if field's constant value was available and successfully copied to buffer // virtual bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, uint8_t *buffer, int bufferSize, int valueOffset = 0, bool ignoreMovableObjects = true ) = 0; // If pIsSpeculative is NULL, return the class handle for the value of ref-class typed // static readonly fields, if there is a unique location for the static and the class // is already initialized. // // If pIsSpeculative is not NULL, fetch the class handle for the value of all ref-class // typed static fields, if there is a unique location for the static and the field is // not null. // // Set *pIsSpeculative true if this type may change over time (field is not readonly or // is readonly but class has not yet finished initialization). Set *pIsSpeculative false // if this type will not change. virtual CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool *pIsSpeculative = NULL ) = 0; // registers a vararg sig & returns a VM cookie for it (which can contain other stuff) virtual CORINFO_VARARGS_HANDLE getVarArgsHandle( CORINFO_SIG_INFO *pSig, void **ppIndirection = NULL ) = 0; // returns true if a VM cookie can be generated for it (might be false due to cross-module // inlining, in which case the inlining should be aborted) virtual bool canGetVarArgsHandle( CORINFO_SIG_INFO *pSig ) = 0; // Allocate a string literal on the heap and return a handle to it virtual InfoAccessType constructStringLiteral( CORINFO_MODULE_HANDLE module, mdToken metaTok, void **ppValue ) = 0; virtual InfoAccessType emptyStringLiteral( void **ppValue ) = 0; // (static fields only) given that 'field' refers to thread local store, // return the ID (TLS index), which is used to find the beginning of the // TLS data area for the particular DLL 'field' is associated with. virtual uint32_t getFieldThreadLocalStoreID ( CORINFO_FIELD_HANDLE field, void **ppIndirection = NULL ) = 0; // Adds an active dependency from the context method's module to the given module // This is internal callback for the EE. JIT should not call it directly. virtual void addActiveDependency( CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo ) = 0; virtual CORINFO_METHOD_HANDLE GetDelegateCtor( CORINFO_METHOD_HANDLE methHnd, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE targetMethodHnd, DelegateCtorArgs * pCtorData ) = 0; virtual void MethodCompileComplete( CORINFO_METHOD_HANDLE methHnd ) = 0; // Obtain tailcall help for the specified call site. virtual bool getTailCallHelpers( // The resolved token for the call. Can be null for calli. CORINFO_RESOLVED_TOKEN* callToken, // The signature at the callsite. CORINFO_SIG_INFO* sig, // Flags for the tailcall site. CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, // The resulting help. CORINFO_TAILCALL_HELPERS* pResult) = 0; // Optionally, convert calli to regular method call. This is for PInvoke argument marshalling. virtual bool convertPInvokeCalliToCall( CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fMustConvert ) = 0; // Notify EE about intent to use or not to use instruction set in the method. Returns true if the instruction set is supported unconditionally. virtual bool notifyInstructionSetUsage( CORINFO_InstructionSet instructionSet, bool supportEnabled ) = 0; // Notify EE that JIT needs an entry-point that is tail-callable. // This is used for AOT on x64 to support delay loaded fast tailcalls. // Normally the indirection cell is retrieved from the return address, // but for tailcalls, the contract is that JIT leaves the indirection cell in // a register during tailcall. virtual void updateEntryPointForTailCall(CORINFO_CONST_LOOKUP* entryPoint) = 0; }; /**********************************************************************************/ // It would be nicer to use existing IMAGE_REL_XXX constants instead of defining our own here... #define IMAGE_REL_BASED_REL32 0x10 #define IMAGE_REL_BASED_THUMB_BRANCH24 0x13 // The identifier for ARM32-specific PC-relative address // computation corresponds to the following instruction // sequence: // l0: movw rX, #imm_lo // 4 byte // l4: movt rX, #imm_hi // 4 byte // l8: add rX, pc <- after this instruction rX = relocTarget // // Program counter at l8 is address of l8 + 4 // Address of relocated movw/movt is l0 // So, imm should be calculated as the following: // imm = relocTarget - (l8 + 4) = relocTarget - (l0 + 8 + 4) = relocTarget - (l_0 + 12) // So, the value of offset correction is 12 // #define IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL 0x14 /**********************************************************************************/ #ifdef TARGET_64BIT #define USE_PER_FRAME_PINVOKE_INIT #endif #endif // _COR_INFO_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corinfoinstructionset.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // DO NOT EDIT THIS FILE! IT IS AUTOGENERATED // FROM /src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt // using /src/coreclr/tools/Common/JitInterface/ThunkGenerator/gen.bat #ifndef CORINFOINSTRUCTIONSET_H #define CORINFOINSTRUCTIONSET_H #include "readytoruninstructionset.h" #include enum CORINFO_InstructionSet { InstructionSet_ILLEGAL = 0, InstructionSet_NONE = 63, #ifdef TARGET_ARM64 InstructionSet_ArmBase=1, InstructionSet_AdvSimd=2, InstructionSet_Aes=3, InstructionSet_Crc32=4, InstructionSet_Dp=5, InstructionSet_Rdm=6, InstructionSet_Sha1=7, InstructionSet_Sha256=8, InstructionSet_Atomics=9, InstructionSet_Vector64=10, InstructionSet_Vector128=11, InstructionSet_Dczva=12, InstructionSet_Rcpc=13, InstructionSet_ArmBase_Arm64=14, InstructionSet_AdvSimd_Arm64=15, InstructionSet_Aes_Arm64=16, InstructionSet_Crc32_Arm64=17, InstructionSet_Dp_Arm64=18, InstructionSet_Rdm_Arm64=19, InstructionSet_Sha1_Arm64=20, InstructionSet_Sha256_Arm64=21, #endif // TARGET_ARM64 #ifdef TARGET_AMD64 InstructionSet_X86Base=1, InstructionSet_SSE=2, InstructionSet_SSE2=3, InstructionSet_SSE3=4, InstructionSet_SSSE3=5, InstructionSet_SSE41=6, InstructionSet_SSE42=7, InstructionSet_AVX=8, InstructionSet_AVX2=9, InstructionSet_AES=10, InstructionSet_BMI1=11, InstructionSet_BMI2=12, InstructionSet_FMA=13, InstructionSet_LZCNT=14, InstructionSet_PCLMULQDQ=15, InstructionSet_POPCNT=16, InstructionSet_Vector128=17, InstructionSet_Vector256=18, InstructionSet_AVXVNNI=19, InstructionSet_MOVBE=20, InstructionSet_X86Serialize=21, InstructionSet_AVX512F=22, InstructionSet_AVX512F_VL=23, InstructionSet_AVX512BW=24, InstructionSet_AVX512BW_VL=25, InstructionSet_AVX512CD=26, InstructionSet_AVX512CD_VL=27, InstructionSet_AVX512DQ=28, InstructionSet_AVX512DQ_VL=29, InstructionSet_X86Base_X64=30, InstructionSet_SSE_X64=31, InstructionSet_SSE2_X64=32, InstructionSet_SSE3_X64=33, InstructionSet_SSSE3_X64=34, InstructionSet_SSE41_X64=35, InstructionSet_SSE42_X64=36, InstructionSet_AVX_X64=37, InstructionSet_AVX2_X64=38, InstructionSet_AES_X64=39, InstructionSet_BMI1_X64=40, InstructionSet_BMI2_X64=41, InstructionSet_FMA_X64=42, InstructionSet_LZCNT_X64=43, InstructionSet_PCLMULQDQ_X64=44, InstructionSet_POPCNT_X64=45, InstructionSet_AVXVNNI_X64=46, InstructionSet_MOVBE_X64=47, InstructionSet_X86Serialize_X64=48, InstructionSet_AVX512F_X64=49, InstructionSet_AVX512F_VL_X64=50, InstructionSet_AVX512BW_X64=51, InstructionSet_AVX512BW_VL_X64=52, InstructionSet_AVX512CD_X64=53, InstructionSet_AVX512CD_VL_X64=54, InstructionSet_AVX512DQ_X64=55, InstructionSet_AVX512DQ_VL_X64=56, #endif // TARGET_AMD64 #ifdef TARGET_X86 InstructionSet_X86Base=1, InstructionSet_SSE=2, InstructionSet_SSE2=3, InstructionSet_SSE3=4, InstructionSet_SSSE3=5, InstructionSet_SSE41=6, InstructionSet_SSE42=7, InstructionSet_AVX=8, InstructionSet_AVX2=9, InstructionSet_AES=10, InstructionSet_BMI1=11, InstructionSet_BMI2=12, InstructionSet_FMA=13, InstructionSet_LZCNT=14, InstructionSet_PCLMULQDQ=15, InstructionSet_POPCNT=16, InstructionSet_Vector128=17, InstructionSet_Vector256=18, InstructionSet_AVXVNNI=19, InstructionSet_MOVBE=20, InstructionSet_X86Serialize=21, InstructionSet_AVX512F=22, InstructionSet_AVX512F_VL=23, InstructionSet_AVX512BW=24, InstructionSet_AVX512BW_VL=25, InstructionSet_AVX512CD=26, InstructionSet_AVX512CD_VL=27, InstructionSet_AVX512DQ=28, InstructionSet_AVX512DQ_VL=29, InstructionSet_X86Base_X64=30, InstructionSet_SSE_X64=31, InstructionSet_SSE2_X64=32, InstructionSet_SSE3_X64=33, InstructionSet_SSSE3_X64=34, InstructionSet_SSE41_X64=35, InstructionSet_SSE42_X64=36, InstructionSet_AVX_X64=37, InstructionSet_AVX2_X64=38, InstructionSet_AES_X64=39, InstructionSet_BMI1_X64=40, InstructionSet_BMI2_X64=41, InstructionSet_FMA_X64=42, InstructionSet_LZCNT_X64=43, InstructionSet_PCLMULQDQ_X64=44, InstructionSet_POPCNT_X64=45, InstructionSet_AVXVNNI_X64=46, InstructionSet_MOVBE_X64=47, InstructionSet_X86Serialize_X64=48, InstructionSet_AVX512F_X64=49, InstructionSet_AVX512F_VL_X64=50, InstructionSet_AVX512BW_X64=51, InstructionSet_AVX512BW_VL_X64=52, InstructionSet_AVX512CD_X64=53, InstructionSet_AVX512CD_VL_X64=54, InstructionSet_AVX512DQ_X64=55, InstructionSet_AVX512DQ_VL_X64=56, #endif // TARGET_X86 }; struct CORINFO_InstructionSetFlags { private: static const int32_t FlagsFieldCount = 1; static const int32_t BitsPerFlagsField = sizeof(uint64_t) * 8; uint64_t _flags[FlagsFieldCount] = { }; static uint32_t GetFlagsFieldIndex(CORINFO_InstructionSet instructionSet) { uint32_t bitIndex = (uint32_t)instructionSet; return (uint32_t)(bitIndex / (uint32_t)BitsPerFlagsField); } static uint64_t GetRelativeBitMask(CORINFO_InstructionSet instructionSet) { return ((uint64_t)1) << (instructionSet & 0x3F); } public: const int GetInstructionFlagsFieldCount() const { return FlagsFieldCount; } void AddInstructionSet(CORINFO_InstructionSet instructionSet) { uint32_t index = GetFlagsFieldIndex(instructionSet); _flags[index] |= GetRelativeBitMask(instructionSet); } void RemoveInstructionSet(CORINFO_InstructionSet instructionSet) { uint32_t index = GetFlagsFieldIndex(instructionSet); uint64_t bitIndex = GetRelativeBitMask(instructionSet); _flags[index] &= ~bitIndex; } bool HasInstructionSet(CORINFO_InstructionSet instructionSet) const { uint32_t index = GetFlagsFieldIndex(instructionSet); uint64_t bitIndex = GetRelativeBitMask(instructionSet); return ((_flags[index] & bitIndex) != 0); } bool Equals(CORINFO_InstructionSetFlags other) const { for (int i = 0; i < FlagsFieldCount; i++) { if (_flags[i] != other._flags[i]) { return false; } } return true; } void Add(CORINFO_InstructionSetFlags other) { for (int i = 0; i < FlagsFieldCount; i++) { _flags[i] |= other._flags[i]; } } bool IsEmpty() const { for (int i = 0; i < FlagsFieldCount; i++) { if (_flags[i] != 0) { return false; } } return true; } void Reset() { for (int i = 0; i < FlagsFieldCount; i++) { _flags[i] = 0; } } void Set64BitInstructionSetVariants() { #ifdef TARGET_ARM64 if (HasInstructionSet(InstructionSet_ArmBase)) AddInstructionSet(InstructionSet_ArmBase_Arm64); if (HasInstructionSet(InstructionSet_AdvSimd)) AddInstructionSet(InstructionSet_AdvSimd_Arm64); if (HasInstructionSet(InstructionSet_Aes)) AddInstructionSet(InstructionSet_Aes_Arm64); if (HasInstructionSet(InstructionSet_Crc32)) AddInstructionSet(InstructionSet_Crc32_Arm64); if (HasInstructionSet(InstructionSet_Dp)) AddInstructionSet(InstructionSet_Dp_Arm64); if (HasInstructionSet(InstructionSet_Rdm)) AddInstructionSet(InstructionSet_Rdm_Arm64); if (HasInstructionSet(InstructionSet_Sha1)) AddInstructionSet(InstructionSet_Sha1_Arm64); if (HasInstructionSet(InstructionSet_Sha256)) AddInstructionSet(InstructionSet_Sha256_Arm64); #endif // TARGET_ARM64 #ifdef TARGET_AMD64 if (HasInstructionSet(InstructionSet_X86Base)) AddInstructionSet(InstructionSet_X86Base_X64); if (HasInstructionSet(InstructionSet_SSE)) AddInstructionSet(InstructionSet_SSE_X64); if (HasInstructionSet(InstructionSet_SSE2)) AddInstructionSet(InstructionSet_SSE2_X64); if (HasInstructionSet(InstructionSet_SSE3)) AddInstructionSet(InstructionSet_SSE3_X64); if (HasInstructionSet(InstructionSet_SSSE3)) AddInstructionSet(InstructionSet_SSSE3_X64); if (HasInstructionSet(InstructionSet_SSE41)) AddInstructionSet(InstructionSet_SSE41_X64); if (HasInstructionSet(InstructionSet_SSE42)) AddInstructionSet(InstructionSet_SSE42_X64); if (HasInstructionSet(InstructionSet_AVX)) AddInstructionSet(InstructionSet_AVX_X64); if (HasInstructionSet(InstructionSet_AVX2)) AddInstructionSet(InstructionSet_AVX2_X64); if (HasInstructionSet(InstructionSet_AES)) AddInstructionSet(InstructionSet_AES_X64); if (HasInstructionSet(InstructionSet_BMI1)) AddInstructionSet(InstructionSet_BMI1_X64); if (HasInstructionSet(InstructionSet_BMI2)) AddInstructionSet(InstructionSet_BMI2_X64); if (HasInstructionSet(InstructionSet_FMA)) AddInstructionSet(InstructionSet_FMA_X64); if (HasInstructionSet(InstructionSet_LZCNT)) AddInstructionSet(InstructionSet_LZCNT_X64); if (HasInstructionSet(InstructionSet_PCLMULQDQ)) AddInstructionSet(InstructionSet_PCLMULQDQ_X64); if (HasInstructionSet(InstructionSet_POPCNT)) AddInstructionSet(InstructionSet_POPCNT_X64); if (HasInstructionSet(InstructionSet_AVXVNNI)) AddInstructionSet(InstructionSet_AVXVNNI_X64); if (HasInstructionSet(InstructionSet_MOVBE)) AddInstructionSet(InstructionSet_MOVBE_X64); if (HasInstructionSet(InstructionSet_X86Serialize)) AddInstructionSet(InstructionSet_X86Serialize_X64); if (HasInstructionSet(InstructionSet_AVX512F)) AddInstructionSet(InstructionSet_AVX512F_X64); if (HasInstructionSet(InstructionSet_AVX512F_VL)) AddInstructionSet(InstructionSet_AVX512F_VL_X64); if (HasInstructionSet(InstructionSet_AVX512BW)) AddInstructionSet(InstructionSet_AVX512BW_X64); if (HasInstructionSet(InstructionSet_AVX512BW_VL)) AddInstructionSet(InstructionSet_AVX512BW_VL_X64); if (HasInstructionSet(InstructionSet_AVX512CD)) AddInstructionSet(InstructionSet_AVX512CD_X64); if (HasInstructionSet(InstructionSet_AVX512CD_VL)) AddInstructionSet(InstructionSet_AVX512CD_VL_X64); if (HasInstructionSet(InstructionSet_AVX512DQ)) AddInstructionSet(InstructionSet_AVX512DQ_X64); if (HasInstructionSet(InstructionSet_AVX512DQ_VL)) AddInstructionSet(InstructionSet_AVX512DQ_VL_X64); #endif // TARGET_AMD64 #ifdef TARGET_X86 #endif // TARGET_X86 } uint64_t* GetFlagsRaw() { return _flags; } }; inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_InstructionSetFlags input) { CORINFO_InstructionSetFlags oldflags = input; CORINFO_InstructionSetFlags resultflags = input; do { oldflags = resultflags; #ifdef TARGET_ARM64 if (resultflags.HasInstructionSet(InstructionSet_ArmBase) && !resultflags.HasInstructionSet(InstructionSet_ArmBase_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_ArmBase); if (resultflags.HasInstructionSet(InstructionSet_ArmBase_Arm64) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) resultflags.RemoveInstructionSet(InstructionSet_ArmBase_Arm64); if (resultflags.HasInstructionSet(InstructionSet_AdvSimd) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_AdvSimd); if (resultflags.HasInstructionSet(InstructionSet_AdvSimd_Arm64) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) resultflags.RemoveInstructionSet(InstructionSet_AdvSimd_Arm64); if (resultflags.HasInstructionSet(InstructionSet_Aes) && !resultflags.HasInstructionSet(InstructionSet_Aes_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_Aes); if (resultflags.HasInstructionSet(InstructionSet_Aes_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Aes)) resultflags.RemoveInstructionSet(InstructionSet_Aes_Arm64); if (resultflags.HasInstructionSet(InstructionSet_Crc32) && !resultflags.HasInstructionSet(InstructionSet_Crc32_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_Crc32); if (resultflags.HasInstructionSet(InstructionSet_Crc32_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Crc32)) resultflags.RemoveInstructionSet(InstructionSet_Crc32_Arm64); if (resultflags.HasInstructionSet(InstructionSet_Dp) && !resultflags.HasInstructionSet(InstructionSet_Dp_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_Dp); if (resultflags.HasInstructionSet(InstructionSet_Dp_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Dp)) resultflags.RemoveInstructionSet(InstructionSet_Dp_Arm64); if (resultflags.HasInstructionSet(InstructionSet_Rdm) && !resultflags.HasInstructionSet(InstructionSet_Rdm_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_Rdm); if (resultflags.HasInstructionSet(InstructionSet_Rdm_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Rdm)) resultflags.RemoveInstructionSet(InstructionSet_Rdm_Arm64); if (resultflags.HasInstructionSet(InstructionSet_Sha1) && !resultflags.HasInstructionSet(InstructionSet_Sha1_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_Sha1); if (resultflags.HasInstructionSet(InstructionSet_Sha1_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Sha1)) resultflags.RemoveInstructionSet(InstructionSet_Sha1_Arm64); if (resultflags.HasInstructionSet(InstructionSet_Sha256) && !resultflags.HasInstructionSet(InstructionSet_Sha256_Arm64)) resultflags.RemoveInstructionSet(InstructionSet_Sha256); if (resultflags.HasInstructionSet(InstructionSet_Sha256_Arm64) && !resultflags.HasInstructionSet(InstructionSet_Sha256)) resultflags.RemoveInstructionSet(InstructionSet_Sha256_Arm64); if (resultflags.HasInstructionSet(InstructionSet_AdvSimd) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) resultflags.RemoveInstructionSet(InstructionSet_AdvSimd); if (resultflags.HasInstructionSet(InstructionSet_Aes) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) resultflags.RemoveInstructionSet(InstructionSet_Aes); if (resultflags.HasInstructionSet(InstructionSet_Crc32) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) resultflags.RemoveInstructionSet(InstructionSet_Crc32); if (resultflags.HasInstructionSet(InstructionSet_Dp) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) resultflags.RemoveInstructionSet(InstructionSet_Dp); if (resultflags.HasInstructionSet(InstructionSet_Rdm) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) resultflags.RemoveInstructionSet(InstructionSet_Rdm); if (resultflags.HasInstructionSet(InstructionSet_Sha1) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) resultflags.RemoveInstructionSet(InstructionSet_Sha1); if (resultflags.HasInstructionSet(InstructionSet_Sha256) && !resultflags.HasInstructionSet(InstructionSet_ArmBase)) resultflags.RemoveInstructionSet(InstructionSet_Sha256); if (resultflags.HasInstructionSet(InstructionSet_Vector64) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) resultflags.RemoveInstructionSet(InstructionSet_Vector64); if (resultflags.HasInstructionSet(InstructionSet_Vector128) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) resultflags.RemoveInstructionSet(InstructionSet_Vector128); #endif // TARGET_ARM64 #ifdef TARGET_AMD64 if (resultflags.HasInstructionSet(InstructionSet_X86Base) && !resultflags.HasInstructionSet(InstructionSet_X86Base_X64)) resultflags.RemoveInstructionSet(InstructionSet_X86Base); if (resultflags.HasInstructionSet(InstructionSet_X86Base_X64) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_X86Base_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_SSE_X64)) resultflags.RemoveInstructionSet(InstructionSet_SSE); if (resultflags.HasInstructionSet(InstructionSet_SSE_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE)) resultflags.RemoveInstructionSet(InstructionSet_SSE_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE2_X64)) resultflags.RemoveInstructionSet(InstructionSet_SSE2); if (resultflags.HasInstructionSet(InstructionSet_SSE2_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_SSE2_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3_X64)) resultflags.RemoveInstructionSet(InstructionSet_SSE3); if (resultflags.HasInstructionSet(InstructionSet_SSE3_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) resultflags.RemoveInstructionSet(InstructionSet_SSE3_X64); if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSSE3_X64)) resultflags.RemoveInstructionSet(InstructionSet_SSSE3); if (resultflags.HasInstructionSet(InstructionSet_SSSE3_X64) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) resultflags.RemoveInstructionSet(InstructionSet_SSSE3_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSE41_X64)) resultflags.RemoveInstructionSet(InstructionSet_SSE41); if (resultflags.HasInstructionSet(InstructionSet_SSE41_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) resultflags.RemoveInstructionSet(InstructionSet_SSE41_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE42_X64)) resultflags.RemoveInstructionSet(InstructionSet_SSE42); if (resultflags.HasInstructionSet(InstructionSet_SSE42_X64) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_SSE42_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_AVX_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX); if (resultflags.HasInstructionSet(InstructionSet_AVX_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_AVX_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX2_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX2); if (resultflags.HasInstructionSet(InstructionSet_AVX2_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVX2_X64); if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_AES_X64)) resultflags.RemoveInstructionSet(InstructionSet_AES); if (resultflags.HasInstructionSet(InstructionSet_AES_X64) && !resultflags.HasInstructionSet(InstructionSet_AES)) resultflags.RemoveInstructionSet(InstructionSet_AES_X64); if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_BMI1_X64)) resultflags.RemoveInstructionSet(InstructionSet_BMI1); if (resultflags.HasInstructionSet(InstructionSet_BMI1_X64) && !resultflags.HasInstructionSet(InstructionSet_BMI1)) resultflags.RemoveInstructionSet(InstructionSet_BMI1_X64); if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_BMI2_X64)) resultflags.RemoveInstructionSet(InstructionSet_BMI2); if (resultflags.HasInstructionSet(InstructionSet_BMI2_X64) && !resultflags.HasInstructionSet(InstructionSet_BMI2)) resultflags.RemoveInstructionSet(InstructionSet_BMI2_X64); if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_FMA_X64)) resultflags.RemoveInstructionSet(InstructionSet_FMA); if (resultflags.HasInstructionSet(InstructionSet_FMA_X64) && !resultflags.HasInstructionSet(InstructionSet_FMA)) resultflags.RemoveInstructionSet(InstructionSet_FMA_X64); if (resultflags.HasInstructionSet(InstructionSet_LZCNT) && !resultflags.HasInstructionSet(InstructionSet_LZCNT_X64)) resultflags.RemoveInstructionSet(InstructionSet_LZCNT); if (resultflags.HasInstructionSet(InstructionSet_LZCNT_X64) && !resultflags.HasInstructionSet(InstructionSet_LZCNT)) resultflags.RemoveInstructionSet(InstructionSet_LZCNT_X64); if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ_X64)) resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ_X64) && !resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ)) resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ_X64); if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_POPCNT_X64)) resultflags.RemoveInstructionSet(InstructionSet_POPCNT); if (resultflags.HasInstructionSet(InstructionSet_POPCNT_X64) && !resultflags.HasInstructionSet(InstructionSet_POPCNT)) resultflags.RemoveInstructionSet(InstructionSet_POPCNT_X64); if (resultflags.HasInstructionSet(InstructionSet_AVXVNNI) && !resultflags.HasInstructionSet(InstructionSet_AVXVNNI_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet_AVXVNNI_X64) && !resultflags.HasInstructionSet(InstructionSet_AVXVNNI)) resultflags.RemoveInstructionSet(InstructionSet_AVXVNNI_X64); if (resultflags.HasInstructionSet(InstructionSet_MOVBE) && !resultflags.HasInstructionSet(InstructionSet_MOVBE_X64)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE); if (resultflags.HasInstructionSet(InstructionSet_MOVBE_X64) && !resultflags.HasInstructionSet(InstructionSet_MOVBE)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE_X64); if (resultflags.HasInstructionSet(InstructionSet_X86Serialize) && !resultflags.HasInstructionSet(InstructionSet_X86Serialize_X64)) resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet_X86Serialize_X64) && !resultflags.HasInstructionSet(InstructionSet_X86Serialize)) resultflags.RemoveInstructionSet(InstructionSet_X86Serialize_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_VL_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_VL_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_X64); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL_X64)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL_X64) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL_X64); if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_SSE); if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) resultflags.RemoveInstructionSet(InstructionSet_SSE2); if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_SSE3); if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) resultflags.RemoveInstructionSet(InstructionSet_SSSE3); if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) resultflags.RemoveInstructionSet(InstructionSet_SSE41); if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) resultflags.RemoveInstructionSet(InstructionSet_SSE42); if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_AVX); if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_AVX2); if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_AES); if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_BMI1); if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_BMI2); if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_FMA); if (resultflags.HasInstructionSet(InstructionSet_LZCNT) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_LZCNT); if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_POPCNT); if (resultflags.HasInstructionSet(InstructionSet_Vector128) && !resultflags.HasInstructionSet(InstructionSet_SSE)) resultflags.RemoveInstructionSet(InstructionSet_Vector128); if (resultflags.HasInstructionSet(InstructionSet_Vector256) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_Vector256); if (resultflags.HasInstructionSet(InstructionSet_AVXVNNI) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet_MOVBE) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE); if (resultflags.HasInstructionSet(InstructionSet_X86Serialize) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); #endif // TARGET_AMD64 #ifdef TARGET_X86 if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_SSE); if (resultflags.HasInstructionSet(InstructionSet_SSE2) && !resultflags.HasInstructionSet(InstructionSet_SSE)) resultflags.RemoveInstructionSet(InstructionSet_SSE2); if (resultflags.HasInstructionSet(InstructionSet_SSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_SSE3); if (resultflags.HasInstructionSet(InstructionSet_SSSE3) && !resultflags.HasInstructionSet(InstructionSet_SSE3)) resultflags.RemoveInstructionSet(InstructionSet_SSSE3); if (resultflags.HasInstructionSet(InstructionSet_SSE41) && !resultflags.HasInstructionSet(InstructionSet_SSSE3)) resultflags.RemoveInstructionSet(InstructionSet_SSE41); if (resultflags.HasInstructionSet(InstructionSet_SSE42) && !resultflags.HasInstructionSet(InstructionSet_SSE41)) resultflags.RemoveInstructionSet(InstructionSet_SSE42); if (resultflags.HasInstructionSet(InstructionSet_AVX) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_AVX); if (resultflags.HasInstructionSet(InstructionSet_AVX2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_AVX2); if (resultflags.HasInstructionSet(InstructionSet_AES) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_AES); if (resultflags.HasInstructionSet(InstructionSet_BMI1) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_BMI1); if (resultflags.HasInstructionSet(InstructionSet_BMI2) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_BMI2); if (resultflags.HasInstructionSet(InstructionSet_FMA) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_FMA); if (resultflags.HasInstructionSet(InstructionSet_LZCNT) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_LZCNT); if (resultflags.HasInstructionSet(InstructionSet_PCLMULQDQ) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) resultflags.RemoveInstructionSet(InstructionSet_PCLMULQDQ); if (resultflags.HasInstructionSet(InstructionSet_POPCNT) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_POPCNT); if (resultflags.HasInstructionSet(InstructionSet_Vector128) && !resultflags.HasInstructionSet(InstructionSet_SSE)) resultflags.RemoveInstructionSet(InstructionSet_Vector128); if (resultflags.HasInstructionSet(InstructionSet_Vector256) && !resultflags.HasInstructionSet(InstructionSet_AVX)) resultflags.RemoveInstructionSet(InstructionSet_Vector256); if (resultflags.HasInstructionSet(InstructionSet_AVXVNNI) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVXVNNI); if (resultflags.HasInstructionSet(InstructionSet_MOVBE) && !resultflags.HasInstructionSet(InstructionSet_SSE42)) resultflags.RemoveInstructionSet(InstructionSet_MOVBE); if (resultflags.HasInstructionSet(InstructionSet_X86Serialize) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); #endif // TARGET_X86 } while (!oldflags.Equals(resultflags)); return resultflags; } inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4065) // disable warning for switch statement with only default label. #endif switch (instructionSet) { #ifdef TARGET_ARM64 case InstructionSet_ArmBase : return "ArmBase"; case InstructionSet_ArmBase_Arm64 : return "ArmBase_Arm64"; case InstructionSet_AdvSimd : return "AdvSimd"; case InstructionSet_AdvSimd_Arm64 : return "AdvSimd_Arm64"; case InstructionSet_Aes : return "Aes"; case InstructionSet_Aes_Arm64 : return "Aes_Arm64"; case InstructionSet_Crc32 : return "Crc32"; case InstructionSet_Crc32_Arm64 : return "Crc32_Arm64"; case InstructionSet_Dp : return "Dp"; case InstructionSet_Dp_Arm64 : return "Dp_Arm64"; case InstructionSet_Rdm : return "Rdm"; case InstructionSet_Rdm_Arm64 : return "Rdm_Arm64"; case InstructionSet_Sha1 : return "Sha1"; case InstructionSet_Sha1_Arm64 : return "Sha1_Arm64"; case InstructionSet_Sha256 : return "Sha256"; case InstructionSet_Sha256_Arm64 : return "Sha256_Arm64"; case InstructionSet_Atomics : return "Atomics"; case InstructionSet_Vector64 : return "Vector64"; case InstructionSet_Vector128 : return "Vector128"; case InstructionSet_Dczva : return "Dczva"; case InstructionSet_Rcpc : return "Rcpc"; #endif // TARGET_ARM64 #ifdef TARGET_AMD64 case InstructionSet_X86Base : return "X86Base"; case InstructionSet_X86Base_X64 : return "X86Base_X64"; case InstructionSet_SSE : return "SSE"; case InstructionSet_SSE_X64 : return "SSE_X64"; case InstructionSet_SSE2 : return "SSE2"; case InstructionSet_SSE2_X64 : return "SSE2_X64"; case InstructionSet_SSE3 : return "SSE3"; case InstructionSet_SSE3_X64 : return "SSE3_X64"; case InstructionSet_SSSE3 : return "SSSE3"; case InstructionSet_SSSE3_X64 : return "SSSE3_X64"; case InstructionSet_SSE41 : return "SSE41"; case InstructionSet_SSE41_X64 : return "SSE41_X64"; case InstructionSet_SSE42 : return "SSE42"; case InstructionSet_SSE42_X64 : return "SSE42_X64"; case InstructionSet_AVX : return "AVX"; case InstructionSet_AVX_X64 : return "AVX_X64"; case InstructionSet_AVX2 : return "AVX2"; case InstructionSet_AVX2_X64 : return "AVX2_X64"; case InstructionSet_AES : return "AES"; case InstructionSet_AES_X64 : return "AES_X64"; case InstructionSet_BMI1 : return "BMI1"; case InstructionSet_BMI1_X64 : return "BMI1_X64"; case InstructionSet_BMI2 : return "BMI2"; case InstructionSet_BMI2_X64 : return "BMI2_X64"; case InstructionSet_FMA : return "FMA"; case InstructionSet_FMA_X64 : return "FMA_X64"; case InstructionSet_LZCNT : return "LZCNT"; case InstructionSet_LZCNT_X64 : return "LZCNT_X64"; case InstructionSet_PCLMULQDQ : return "PCLMULQDQ"; case InstructionSet_PCLMULQDQ_X64 : return "PCLMULQDQ_X64"; case InstructionSet_POPCNT : return "POPCNT"; case InstructionSet_POPCNT_X64 : return "POPCNT_X64"; case InstructionSet_Vector128 : return "Vector128"; case InstructionSet_Vector256 : return "Vector256"; case InstructionSet_AVXVNNI : return "AVXVNNI"; case InstructionSet_AVXVNNI_X64 : return "AVXVNNI_X64"; case InstructionSet_MOVBE : return "MOVBE"; case InstructionSet_MOVBE_X64 : return "MOVBE_X64"; case InstructionSet_X86Serialize : return "X86Serialize"; case InstructionSet_X86Serialize_X64 : return "X86Serialize_X64"; case InstructionSet_AVX512F : return "AVX512F"; case InstructionSet_AVX512F_X64 : return "AVX512F_X64"; case InstructionSet_AVX512F_VL : return "AVX512F_VL"; case InstructionSet_AVX512F_VL_X64 : return "AVX512F_VL_X64"; case InstructionSet_AVX512BW : return "AVX512BW"; case InstructionSet_AVX512BW_X64 : return "AVX512BW_X64"; case InstructionSet_AVX512BW_VL : return "AVX512BW_VL"; case InstructionSet_AVX512BW_VL_X64 : return "AVX512BW_VL_X64"; case InstructionSet_AVX512CD : return "AVX512CD"; case InstructionSet_AVX512CD_X64 : return "AVX512CD_X64"; case InstructionSet_AVX512CD_VL : return "AVX512CD_VL"; case InstructionSet_AVX512CD_VL_X64 : return "AVX512CD_VL_X64"; case InstructionSet_AVX512DQ : return "AVX512DQ"; case InstructionSet_AVX512DQ_X64 : return "AVX512DQ_X64"; case InstructionSet_AVX512DQ_VL : return "AVX512DQ_VL"; case InstructionSet_AVX512DQ_VL_X64 : return "AVX512DQ_VL_X64"; #endif // TARGET_AMD64 #ifdef TARGET_X86 case InstructionSet_X86Base : return "X86Base"; case InstructionSet_SSE : return "SSE"; case InstructionSet_SSE2 : return "SSE2"; case InstructionSet_SSE3 : return "SSE3"; case InstructionSet_SSSE3 : return "SSSE3"; case InstructionSet_SSE41 : return "SSE41"; case InstructionSet_SSE42 : return "SSE42"; case InstructionSet_AVX : return "AVX"; case InstructionSet_AVX2 : return "AVX2"; case InstructionSet_AES : return "AES"; case InstructionSet_BMI1 : return "BMI1"; case InstructionSet_BMI2 : return "BMI2"; case InstructionSet_FMA : return "FMA"; case InstructionSet_LZCNT : return "LZCNT"; case InstructionSet_PCLMULQDQ : return "PCLMULQDQ"; case InstructionSet_POPCNT : return "POPCNT"; case InstructionSet_Vector128 : return "Vector128"; case InstructionSet_Vector256 : return "Vector256"; case InstructionSet_AVXVNNI : return "AVXVNNI"; case InstructionSet_MOVBE : return "MOVBE"; case InstructionSet_X86Serialize : return "X86Serialize"; case InstructionSet_AVX512F : return "AVX512F"; case InstructionSet_AVX512F_VL : return "AVX512F_VL"; case InstructionSet_AVX512BW : return "AVX512BW"; case InstructionSet_AVX512BW_VL : return "AVX512BW_VL"; case InstructionSet_AVX512CD : return "AVX512CD"; case InstructionSet_AVX512CD_VL : return "AVX512CD_VL"; case InstructionSet_AVX512DQ : return "AVX512DQ"; case InstructionSet_AVX512DQ_VL : return "AVX512DQ_VL"; #endif // TARGET_X86 default: return "UnknownInstructionSet"; } #ifdef _MSC_VER #pragma warning(pop) #endif } inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInstructionSet r2rSet) { #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable: 4065) // disable warning for switch statement with only default label. #endif switch (r2rSet) { #ifdef TARGET_ARM64 case READYTORUN_INSTRUCTION_ArmBase: return InstructionSet_ArmBase; case READYTORUN_INSTRUCTION_AdvSimd: return InstructionSet_AdvSimd; case READYTORUN_INSTRUCTION_Aes: return InstructionSet_Aes; case READYTORUN_INSTRUCTION_Crc32: return InstructionSet_Crc32; case READYTORUN_INSTRUCTION_Dp: return InstructionSet_Dp; case READYTORUN_INSTRUCTION_Rdm: return InstructionSet_Rdm; case READYTORUN_INSTRUCTION_Sha1: return InstructionSet_Sha1; case READYTORUN_INSTRUCTION_Sha256: return InstructionSet_Sha256; case READYTORUN_INSTRUCTION_Atomics: return InstructionSet_Atomics; case READYTORUN_INSTRUCTION_Rcpc: return InstructionSet_Rcpc; #endif // TARGET_ARM64 #ifdef TARGET_AMD64 case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; case READYTORUN_INSTRUCTION_Sse: return InstructionSet_SSE; case READYTORUN_INSTRUCTION_Sse2: return InstructionSet_SSE2; case READYTORUN_INSTRUCTION_Sse3: return InstructionSet_SSE3; case READYTORUN_INSTRUCTION_Ssse3: return InstructionSet_SSSE3; case READYTORUN_INSTRUCTION_Sse41: return InstructionSet_SSE41; case READYTORUN_INSTRUCTION_Sse42: return InstructionSet_SSE42; case READYTORUN_INSTRUCTION_Avx: return InstructionSet_AVX; case READYTORUN_INSTRUCTION_Avx2: return InstructionSet_AVX2; case READYTORUN_INSTRUCTION_Aes: return InstructionSet_AES; case READYTORUN_INSTRUCTION_Bmi1: return InstructionSet_BMI1; case READYTORUN_INSTRUCTION_Bmi2: return InstructionSet_BMI2; case READYTORUN_INSTRUCTION_Fma: return InstructionSet_FMA; case READYTORUN_INSTRUCTION_Lzcnt: return InstructionSet_LZCNT; case READYTORUN_INSTRUCTION_Pclmulqdq: return InstructionSet_PCLMULQDQ; case READYTORUN_INSTRUCTION_Popcnt: return InstructionSet_POPCNT; case READYTORUN_INSTRUCTION_AvxVnni: return InstructionSet_AVXVNNI; case READYTORUN_INSTRUCTION_Movbe: return InstructionSet_MOVBE; case READYTORUN_INSTRUCTION_X86Serialize: return InstructionSet_X86Serialize; case READYTORUN_INSTRUCTION_Avx512F: return InstructionSet_AVX512F; case READYTORUN_INSTRUCTION_Avx512F_VL: return InstructionSet_AVX512F_VL; case READYTORUN_INSTRUCTION_Avx512BW: return InstructionSet_AVX512BW; case READYTORUN_INSTRUCTION_Avx512BW_VL: return InstructionSet_AVX512BW_VL; case READYTORUN_INSTRUCTION_Avx512CD: return InstructionSet_AVX512CD; case READYTORUN_INSTRUCTION_Avx512CD_VL: return InstructionSet_AVX512CD_VL; case READYTORUN_INSTRUCTION_Avx512DQ: return InstructionSet_AVX512DQ; case READYTORUN_INSTRUCTION_Avx512DQ_VL: return InstructionSet_AVX512DQ_VL; #endif // TARGET_AMD64 #ifdef TARGET_X86 case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; case READYTORUN_INSTRUCTION_Sse: return InstructionSet_SSE; case READYTORUN_INSTRUCTION_Sse2: return InstructionSet_SSE2; case READYTORUN_INSTRUCTION_Sse3: return InstructionSet_SSE3; case READYTORUN_INSTRUCTION_Ssse3: return InstructionSet_SSSE3; case READYTORUN_INSTRUCTION_Sse41: return InstructionSet_SSE41; case READYTORUN_INSTRUCTION_Sse42: return InstructionSet_SSE42; case READYTORUN_INSTRUCTION_Avx: return InstructionSet_AVX; case READYTORUN_INSTRUCTION_Avx2: return InstructionSet_AVX2; case READYTORUN_INSTRUCTION_Aes: return InstructionSet_AES; case READYTORUN_INSTRUCTION_Bmi1: return InstructionSet_BMI1; case READYTORUN_INSTRUCTION_Bmi2: return InstructionSet_BMI2; case READYTORUN_INSTRUCTION_Fma: return InstructionSet_FMA; case READYTORUN_INSTRUCTION_Lzcnt: return InstructionSet_LZCNT; case READYTORUN_INSTRUCTION_Pclmulqdq: return InstructionSet_PCLMULQDQ; case READYTORUN_INSTRUCTION_Popcnt: return InstructionSet_POPCNT; case READYTORUN_INSTRUCTION_AvxVnni: return InstructionSet_AVXVNNI; case READYTORUN_INSTRUCTION_Movbe: return InstructionSet_MOVBE; case READYTORUN_INSTRUCTION_X86Serialize: return InstructionSet_X86Serialize; case READYTORUN_INSTRUCTION_Avx512F: return InstructionSet_AVX512F; case READYTORUN_INSTRUCTION_Avx512F_VL: return InstructionSet_AVX512F_VL; case READYTORUN_INSTRUCTION_Avx512BW: return InstructionSet_AVX512BW; case READYTORUN_INSTRUCTION_Avx512BW_VL: return InstructionSet_AVX512BW_VL; case READYTORUN_INSTRUCTION_Avx512CD: return InstructionSet_AVX512CD; case READYTORUN_INSTRUCTION_Avx512CD_VL: return InstructionSet_AVX512CD_VL; case READYTORUN_INSTRUCTION_Avx512DQ: return InstructionSet_AVX512DQ; case READYTORUN_INSTRUCTION_Avx512DQ_VL: return InstructionSet_AVX512DQ_VL; #endif // TARGET_X86 default: return InstructionSet_ILLEGAL; } #ifdef _MSC_VER #pragma warning(pop) #endif } #endif // CORINFOINSTRUCTIONSET_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corjit.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*****************************************************************************\ * * * CorJit.h - EE / JIT interface * * * * Version 1.0 * ******************************************************************************* * * * * * * \*****************************************************************************/ ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // // The JIT/EE interface is versioned. By "interface", we mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _COR_JIT_H_ #define _COR_JIT_H_ #include "corinfo.h" #include #include "corjitflags.h" #ifndef MAKE_HRESULT // If this header is included without including the windows or PAL headers, then define // MAKE_HRESULT, and associated macros /******************* HRESULT types ****************************************/ #define FACILITY_WINDOWS 8 #define FACILITY_URT 19 #define FACILITY_UMI 22 #define FACILITY_SXS 23 #define FACILITY_STORAGE 3 #define FACILITY_SSPI 9 #define FACILITY_SCARD 16 #define FACILITY_SETUPAPI 15 #define FACILITY_SECURITY 9 #define FACILITY_RPC 1 #define FACILITY_WIN32 7 #define FACILITY_CONTROL 10 #define FACILITY_NULL 0 #define FACILITY_MSMQ 14 #define FACILITY_MEDIASERVER 13 #define FACILITY_INTERNET 12 #define FACILITY_ITF 4 #define FACILITY_DPLAY 21 #define FACILITY_DISPATCH 2 #define FACILITY_COMPLUS 17 #define FACILITY_CERT 11 #define FACILITY_ACS 20 #define FACILITY_AAF 18 #define NO_ERROR 0L #define SEVERITY_SUCCESS 0 #define SEVERITY_ERROR 1 #define SUCCEEDED(Status) ((JITINTERFACE_HRESULT)(Status) >= 0) #define FAILED(Status) ((JITINTERFACE_HRESULT)(Status)<0) #define IS_ERROR(Status) ((uint32_t)(Status) >> 31 == SEVERITY_ERROR) // diff from win32 #define HRESULT_CODE(hr) ((hr) & 0xFFFF) #define SCODE_CODE(sc) ((sc) & 0xFFFF) #define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff) #define SCODE_FACILITY(sc) (((sc) >> 16) & 0x1fff) #define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1) #define SCODE_SEVERITY(sc) (((sc) >> 31) & 0x1) // both macros diff from Win32 #define MAKE_HRESULT(sev,fac,code) \ ((JITINTERFACE_HRESULT) (((uint32_t)(sev)<<31) | ((uint32_t)(fac)<<16) | ((uint32_t)(code))) ) #define MAKE_SCODE(sev,fac,code) \ ((SCODE) (((uint32_t)(sev)<<31) | ((uint32_t)(fac)<<16) | ((LONG)(code))) ) #define FACILITY_NT_BIT 0x10000000 #define HRESULT_FROM_WIN32(x) ((JITINTERFACE_HRESULT)(x) <= 0 ? ((JITINTERFACE_HRESULT)(x)) : ((JITINTERFACE_HRESULT) (((x) & 0x0000FFFF) | (FACILITY_WIN32 << 16) | 0x80000000))) #define __HRESULT_FROM_WIN32(x) HRESULT_FROM_WIN32(x) #define HRESULT_FROM_NT(x) ((JITINTERFACE_HRESULT) ((x) | FACILITY_NT_BIT)) #endif // MAKE_HRESULT /*****************************************************************************/ // These are error codes returned by CompileMethod enum CorJitResult { // Note that I dont use FACILITY_NULL for the facility number, // we may want to get a 'real' facility number CORJIT_OK = NO_ERROR, CORJIT_BADCODE = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 1), CORJIT_OUTOFMEM = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 2), CORJIT_INTERNALERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 3), CORJIT_SKIPPED = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 4), CORJIT_RECOVERABLEERROR = MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 5), CORJIT_IMPLLIMITATION= MAKE_HRESULT(SEVERITY_ERROR,FACILITY_NULL, 6), }; /*****************************************************************************/ // These are flags passed to ICorJitInfo::allocMem // to guide the memory allocation for the code, readonly data, and read-write data enum CorJitAllocMemFlag { CORJIT_ALLOCMEM_DEFAULT_CODE_ALIGN = 0x00000000, // The code will use the normal alignment CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN = 0x00000001, // The code will be 16-byte aligned CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN = 0x00000002, // The read-only data will be 16-byte aligned CORJIT_ALLOCMEM_FLG_32BYTE_ALIGN = 0x00000004, // The code will be 32-byte aligned CORJIT_ALLOCMEM_FLG_RODATA_32BYTE_ALIGN = 0x00000008, // The read-only data will be 32-byte aligned }; inline CorJitAllocMemFlag operator |(CorJitAllocMemFlag a, CorJitAllocMemFlag b) { return static_cast(static_cast(a) | static_cast(b)); } enum CorJitFuncKind { CORJIT_FUNC_ROOT, // The main/root function (always id==0) CORJIT_FUNC_HANDLER, // a funclet associated with an EH handler (finally, fault, catch, filter handler) CORJIT_FUNC_FILTER // a funclet associated with an EH filter }; // We have a performance-investigation mode (defined by the FEATURE_USE_ASM_GC_WRITE_BARRIERS and // FEATURE_COUNT_GC_WRITE_BARRIER preprocessor symbols) in which the JIT adds an argument of this // enumeration to checked write barrier calls in order to classify them. enum CheckedWriteBarrierKinds { CWBKind_Unclassified, // Not one of the ones below. CWBKind_RetBuf, // Store through a return buffer pointer argument. CWBKind_ByRefArg, // Store through a by-ref argument (not an implicit return buffer). CWBKind_OtherByRefLocal, // Store through a by-ref local variable. CWBKind_AddrOfLocal, // Store through the address of a local (arguably a bug that this happens at all). }; struct AllocMemArgs { // Input arguments uint32_t hotCodeSize; uint32_t coldCodeSize; uint32_t roDataSize; uint32_t xcptnsCount; CorJitAllocMemFlag flag; // Output arguments void* hotCodeBlock; void* hotCodeBlockRW; void* coldCodeBlock; void* coldCodeBlockRW; void* roDataBlock; void* roDataBlockRW; }; #include "corjithost.h" extern "C" void jitStartup(ICorJitHost* host); class ICorJitCompiler; class ICorJitInfo; extern "C" ICorJitCompiler* getJit(); // #EEToJitInterface // ICorJitCompiler is the interface that the EE uses to get IL bytecode converted to native code. Note that // to accomplish this the JIT has to call back to the EE to get symbolic information. The code:ICorJitInfo // type passed as 'comp' to compileMethod is the mechanism to get this information. This is often the more // interesting interface. // // class ICorJitCompiler { public: // compileMethod is the main routine to ask the JIT Compiler to create native code for a method. The // method to be compiled is passed in the 'info' parameter, and the code:ICorJitInfo is used to allow the // JIT to resolve tokens, and make any other callbacks needed to create the code. nativeEntry, and // nativeSizeOfCode are just for convenience because the JIT asks the EE for the memory to emit code into // (see code:ICorJitInfo.allocMem), so really the EE already knows where the method starts and how big // it is (in fact, it could be in more than one chunk). // // * In the 32 bit jit this is implemented by code:CILJit.compileMethod // * For the 64 bit jit this is implemented by code:PreJit.compileMethod // Note: setTargetOS must be called before this api is used. virtual CorJitResult compileMethod ( ICorJitInfo *comp, /* IN */ struct CORINFO_METHOD_INFO *info, /* IN */ unsigned /* code:CorJitFlag */ flags, /* IN */ uint8_t **nativeEntry, /* OUT */ uint32_t *nativeSizeOfCode /* OUT */ ) = 0; // Do any appropriate work at process shutdown. Default impl is to do nothing. virtual void ProcessShutdownWork(ICorStaticInfo* info) {}; // The EE asks the JIT for a "version identifier". This represents the version of the JIT/EE interface. // If the JIT doesn't implement the same JIT/EE interface expected by the EE (because the JIT doesn't // return the version identifier that the EE expects), then the EE fails to load the JIT. // virtual void getVersionIdentifier( GUID* versionIdentifier /* OUT */ ) = 0; // When the EE loads the System.Numerics.Vectors assembly, it asks the JIT what length (in bytes) of // SIMD vector it supports as an intrinsic type. Zero means that the JIT does not support SIMD // intrinsics, so the EE should use the default size (i.e. the size of the IL implementation). virtual unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags) { return 0; } // Some JIT's may support multiple OSs. This api provides a means to specify to the JIT what OS it should // be trying to compile. This api does not produce any errors, any errors are to be generated by the // the compileMethod call, which will call back into the VM to ensure bits are correctly setup. // // Note: this api MUST be called before the compileMethod is called for the first time in the process. virtual void setTargetOS(CORINFO_OS os) = 0; }; //------------------------------------------------------------------------------------------ // #JitToEEInterface // // ICorJitInfo is the main interface that the JIT uses to call back to the EE and get information. It is // the companion to code:ICorJitCompiler#EEToJitInterface. The concrete implementation of this in the // runtime is the code:CEEJitInfo type. There is also a version of this for the NGEN case. // // See code:ICorMethodInfo#EEJitContractDetails for subtle conventions used by this interface. // // There is more information on the JIT in the book of the runtime entry // http://devdiv/sites/CLR/Product%20Documentation/2.0/BookOfTheRuntime/JIT/JIT%20Design.doc // class ICorJitInfo : public ICorDynamicInfo { public: // get a block of memory for the code, readonly data, and read-write data virtual void allocMem ( AllocMemArgs *pArgs ) = 0; // Reserve memory for the method/funclet's unwind information. // Note that this must be called before allocMem. It should be // called once for the main method, once for every funclet, and // once for every block of cold code for which allocUnwindInfo // will be called. // // This is necessary because jitted code must allocate all the // memory needed for the unwindInfo at the allocMem call. // For prejitted code we split up the unwinding information into // separate sections .rdata and .pdata. // virtual void reserveUnwindInfo ( bool isFunclet, /* IN */ bool isColdCode, /* IN */ uint32_t unwindSize /* IN */ ) = 0; // Allocate and initialize the .rdata and .pdata for this method or // funclet, and get the block of memory needed for the machine-specific // unwind information (the info for crawling the stack frame). // Note that allocMem must be called first. // // Parameters: // // pHotCode main method code buffer, always filled in // pColdCode cold code buffer, only filled in if this is cold code, // null otherwise // startOffset start of code block, relative to appropriate code buffer // (e.g. pColdCode if cold, pHotCode if hot). // endOffset end of code block, relative to appropriate code buffer // unwindSize size of unwind info pointed to by pUnwindBlock // pUnwindBlock pointer to unwind info // funcKind type of funclet (main method code, handler, filter) // virtual void allocUnwindInfo ( uint8_t * pHotCode, /* IN */ uint8_t * pColdCode, /* IN */ uint32_t startOffset, /* IN */ uint32_t endOffset, /* IN */ uint32_t unwindSize, /* IN */ uint8_t * pUnwindBlock, /* IN */ CorJitFuncKind funcKind /* IN */ ) = 0; // Get a block of memory needed for the code manager information, // (the info for enumerating the GC pointers while crawling the // stack frame). // Note that allocMem must be called first virtual void * allocGCInfo ( size_t size /* IN */ ) = 0; // Indicate how many exception handler blocks are to be returned. // This is guaranteed to be called before any 'setEHinfo' call. // Note that allocMem must be called before this method can be called. virtual void setEHcount ( unsigned cEH /* IN */ ) = 0; // Set the values for one particular exception handler block. // // Handler regions should be lexically contiguous. // This is because FinallyIsUnwinding() uses lexicality to // determine if a "finally" clause is executing. virtual void setEHinfo ( unsigned EHnumber, /* IN */ const CORINFO_EH_CLAUSE *clause /* IN */ ) = 0; // Level -> fatalError, Level 2 -> Error, Level 3 -> Warning // Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ... // returns non-zero if the logging succeeded virtual bool logMsg(unsigned level, const char* fmt, va_list args) = 0; // do an assert. will return true if the code should retry (DebugBreak) // returns false, if the assert should be ignored. virtual int doAssert(const char* szFile, int iLine, const char* szExpr) = 0; virtual void reportFatalError(CorJitResult result) = 0; struct BlockCounts // Also defined by: CORBBTPROF_BLOCK_DATA { uint32_t ILOffset; uint32_t ExecutionCount; }; // Data structure for a single class probe using 32-bit count. // // CLASS_FLAG, INTERFACE_FLAG and DELEGATE_FLAG are placed into the Other field in the schema. // If CLASS_FLAG is set the handle table consists of type handles, and otherwise method handles. // // Count is the number of times a call was made at that call site. // // SIZE is the number of entries in the table. // // SAMPLE_INTERVAL must be >= SIZE. SAMPLE_INTERVAL / SIZE // gives the average number of calls between table updates. // struct HandleHistogram32 { enum { SIZE = 8, SAMPLE_INTERVAL = 32, CLASS_FLAG = 0x80000000, INTERFACE_FLAG = 0x40000000, DELEGATE_FLAG = 0x20000000, OFFSET_MASK = 0x0FFFFFFF }; uint32_t Count; void* HandleTable[SIZE]; }; struct HandleHistogram64 { uint64_t Count; void* HandleTable[HandleHistogram32::SIZE]; }; enum class PgoInstrumentationKind { // This must be kept in sync with PgoInstrumentationKind in PgoFormat.cs // Schema data types None = 0, FourByte = 1, EightByte = 2, TypeHandle = 3, MethodHandle = 4, // Mask of all schema data types MarshalMask = 0xF, // ExcessAlignment Align4Byte = 0x10, Align8Byte = 0x20, AlignPointer = 0x30, // Mask of all schema alignment types AlignMask = 0x30, DescriptorMin = 0x40, Done = None, // All instrumentation schemas must end with a record which is "Done" BasicBlockIntCount = (DescriptorMin * 1) | FourByte, // basic block counter using unsigned 4 byte int BasicBlockLongCount = (DescriptorMin * 1) | EightByte, // basic block counter using unsigned 8 byte int HandleHistogramIntCount = (DescriptorMin * 2) | FourByte | AlignPointer, // 4 byte counter that is part of a type histogram. Aligned to match HandleHistogram32's alignment. HandleHistogramLongCount = (DescriptorMin * 2) | EightByte, // 8 byte counter that is part of a type histogram HandleHistogramTypes = (DescriptorMin * 3) | TypeHandle, // Histogram of type handles HandleHistogramMethods = (DescriptorMin * 3) | MethodHandle, // Histogram of method handles Version = (DescriptorMin * 4) | None, // Version is encoded in the Other field of the schema NumRuns = (DescriptorMin * 5) | None, // Number of runs is encoded in the Other field of the schema EdgeIntCount = (DescriptorMin * 6) | FourByte, // edge counter using unsigned 4 byte int EdgeLongCount = (DescriptorMin * 6) | EightByte, // edge counter using unsigned 8 byte int GetLikelyClass = (DescriptorMin * 7) | TypeHandle, // Compressed get likely class data GetLikelyMethod = (DescriptorMin * 7) | MethodHandle, // Compressed get likely method data }; struct PgoInstrumentationSchema { size_t Offset; PgoInstrumentationKind InstrumentationKind; int32_t ILOffset; int32_t Count; int32_t Other; }; enum class PgoSource { Unknown = 0, // PGO data source unknown Static = 1, // PGO data comes from embedded R2R profile data Dynamic = 2, // PGO data comes from current run Blend = 3, // PGO data comes from blend of prior runs and current run Text = 4, // PGO data comes from text file IBC = 5, // PGO data from classic IBC Sampling= 6, // PGO data derived from sampling }; #define DEFAULT_UNKNOWN_HANDLE 1 #define UNKNOWN_HANDLE_MIN 1 #define UNKNOWN_HANDLE_MAX 33 static inline bool IsUnknownHandle(intptr_t handle) { return ((handle >= UNKNOWN_HANDLE_MIN) && (handle <= UNKNOWN_HANDLE_MAX)); } // get profile information to be used for optimizing a current method. The format // of the buffer is the same as the format the JIT passes to allocPgoInstrumentationBySchema. virtual JITINTERFACE_HRESULT getPgoInstrumentationResults( CORINFO_METHOD_HANDLE ftnHnd, PgoInstrumentationSchema **pSchema, // OUT: pointer to the schema table (array) which describes the instrumentation results // (pointer will not remain valid after jit completes). uint32_t * pCountSchemaItems, // OUT: pointer to the count of schema items in `pSchema` array. uint8_t ** pInstrumentationData, // OUT: `*pInstrumentationData` is set to the address of the instrumentation data // (pointer will not remain valid after jit completes). PgoSource * pPgoSource // OUT: value describing source of pgo data ) = 0; // Allocate a profile buffer for use in the current process // The JIT shall call this api with the schema entries other than Offset filled in. // The VM is responsible for allocating the buffer, and computing the various offsets // The offset calculation shall obey the following rules // 1. All data fields shall be naturally aligned. // 2. The first offset may be arbitrarily large. // 3. The JIT may mark a schema item with an alignment flag. This may be used to increase the alignment of a field. // 4. Each data entry shall be laid out without extra padding. // // The intention here is that it becomes possible to describe a C data structure with the alignment for ease of use with // instrumentation helper functions virtual JITINTERFACE_HRESULT allocPgoInstrumentationBySchema( CORINFO_METHOD_HANDLE ftnHnd, PgoInstrumentationSchema *pSchema, // IN OUT: pointer to the schema table (array) which describes the instrumentation results. `Offset` field // is filled in by VM; other fields are set and passed in by caller. uint32_t countSchemaItems, // IN: count of schema items in `pSchema` array. uint8_t ** pInstrumentationData // OUT: `*pInstrumentationData` is set to the address of the instrumentation data. ) = 0; // Associates a native call site, identified by its offset in the native code stream, with // the signature information and method handle the JIT used to lay out the call site. If // the call site has no signature information (e.g. a helper call) or has no method handle // (e.g. a CALLI P/Invoke), then null should be passed instead. virtual void recordCallSite( uint32_t instrOffset, /* IN */ CORINFO_SIG_INFO * callSig, /* IN */ CORINFO_METHOD_HANDLE methodHandle /* IN */ ) = 0; // A relocation is recorded if we are pre-jitting. // A jump thunk may be inserted if we are jitting virtual void recordRelocation( void * location, /* IN */ void * locationRW, /* IN */ void * target, /* IN */ uint16_t fRelocType, /* IN */ uint16_t slotNum = 0, /* IN */ int32_t addlDelta = 0 /* IN */ ) = 0; virtual uint16_t getRelocTypeHint(void * target) = 0; // For what machine does the VM expect the JIT to generate code? The VM // returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM // is cross-compiling (such as the case for crossgen), it will return a // different value than if it was compiling for the host architecture. // virtual uint32_t getExpectedTargetArchitecture() = 0; // Fetches extended flags for a particular compilation instance. Returns // the number of bytes written to the provided buffer. virtual uint32_t getJitFlags( CORJIT_FLAGS* flags, /* IN: Points to a buffer that will hold the extended flags. */ uint32_t sizeInBytes /* IN: The size of the buffer. Note that this is effectively a version number for the CORJIT_FLAGS value. */ ) = 0; }; /**********************************************************************************/ #endif // _COR_CORJIT_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corjitflags.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // // The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _COR_JIT_FLAGS_H_ #define _COR_JIT_FLAGS_H_ #include "corinfoinstructionset.h" class CORJIT_FLAGS { public: enum CorJitFlag { CORJIT_FLAG_CALL_GETJITFLAGS = 0xffffffff, // Indicates that the JIT should retrieve flags in the form of a // pointer to a CORJIT_FLAGS value via ICorJitInfo::getJitFlags(). CORJIT_FLAG_SPEED_OPT = 0, CORJIT_FLAG_SIZE_OPT = 1, CORJIT_FLAG_DEBUG_CODE = 2, // generate "debuggable" code (no code-mangling optimizations) CORJIT_FLAG_DEBUG_EnC = 3, // We are in Edit-n-Continue mode CORJIT_FLAG_DEBUG_INFO = 4, // generate line and local-var info CORJIT_FLAG_MIN_OPT = 5, // disable all jit optimizations (not necessarily debuggable code) CORJIT_FLAG_ENABLE_CFG = 6, // generate control-flow guard checks CORJIT_FLAG_MCJIT_BACKGROUND = 7, // Calling from multicore JIT background thread, do not call JitComplete #if defined(TARGET_X86) CORJIT_FLAG_PINVOKE_RESTORE_ESP = 8, // Restore ESP after returning from inlined PInvoke CORJIT_FLAG_TARGET_P4 = 9, CORJIT_FLAG_USE_FCOMI = 10, // Generated code may use fcomi(p) instruction CORJIT_FLAG_USE_CMOV = 11, // Generated code may use cmov instruction #else // !defined(TARGET_X86) CORJIT_FLAG_UNUSED2 = 8, CORJIT_FLAG_UNUSED3 = 9, CORJIT_FLAG_UNUSED4 = 10, CORJIT_FLAG_UNUSED5 = 11, CORJIT_FLAG_UNUSED6 = 12, #endif // !defined(TARGET_X86) CORJIT_FLAG_OSR = 13, // Generate alternate method for On Stack Replacement CORJIT_FLAG_ALT_JIT = 14, // JIT should consider itself an ALT_JIT CORJIT_FLAG_UNUSED8 = 15, CORJIT_FLAG_UNUSED9 = 16, CORJIT_FLAG_UNUSED10 = 17, CORJIT_FLAG_MAKEFINALCODE = 18, // Use the final code generator, i.e., not the interpreter. CORJIT_FLAG_READYTORUN = 19, // Use version-resilient code generation CORJIT_FLAG_PROF_ENTERLEAVE = 20, // Instrument prologues/epilogues CORJIT_FLAG_UNUSED11 = 21, CORJIT_FLAG_PROF_NO_PINVOKE_INLINE = 22, // Disables PInvoke inlining CORJIT_FLAG_SKIP_VERIFICATION = 23, // (lazy) skip verification - determined without doing a full resolve. See comment below CORJIT_FLAG_PREJIT = 24, // jit or prejit is the execution engine. CORJIT_FLAG_RELOC = 25, // Generate relocatable code CORJIT_FLAG_IMPORT_ONLY = 26, // Only import the function CORJIT_FLAG_IL_STUB = 27, // method is an IL stub CORJIT_FLAG_PROCSPLIT = 28, // JIT should separate code into hot and cold sections CORJIT_FLAG_BBINSTR = 29, // Collect basic block profile information CORJIT_FLAG_BBOPT = 30, // Optimize method based on profile information CORJIT_FLAG_FRAMED = 31, // All methods have an EBP frame CORJIT_FLAG_UNUSED12 = 32, CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) CORJIT_FLAG_UNUSED13 = 34, CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the REVERSE_PINVOKE helper variants that track transitions. CORJIT_FLAG_TIER0 = 39, // This is the initial tier for tiered compilation which should generate code as quickly as possible CORJIT_FLAG_TIER1 = 40, // This is the final tier (for now) for tiered compilation which should generate high quality code #if defined(TARGET_ARM) CORJIT_FLAG_RELATIVE_CODE_RELOCS = 41, // JIT should generate PC-relative address computations instead of EE relocation records #else // !defined(TARGET_ARM) CORJIT_FLAG_UNUSED15 = 41, #endif // !defined(TARGET_ARM) CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method #if defined(TARGET_ARM) CORJIT_FLAG_SOFTFP_ABI = 43, // On ARM should enable armel calling convention #else // !defined(TARGET_ARM) CORJIT_FLAG_UNUSED16 = 43, #endif // !defined(TARGET_ARM) CORJIT_FLAG_UNUSED17 = 44, CORJIT_FLAG_UNUSED18 = 45, CORJIT_FLAG_UNUSED19 = 46, CORJIT_FLAG_UNUSED20 = 47, CORJIT_FLAG_UNUSED21 = 48, CORJIT_FLAG_UNUSED22 = 49, CORJIT_FLAG_UNUSED23 = 50, CORJIT_FLAG_UNUSED24 = 51, CORJIT_FLAG_UNUSED25 = 52, CORJIT_FLAG_UNUSED26 = 53, CORJIT_FLAG_UNUSED27 = 54, CORJIT_FLAG_UNUSED28 = 55, CORJIT_FLAG_UNUSED29 = 56, CORJIT_FLAG_UNUSED30 = 57, CORJIT_FLAG_UNUSED31 = 58, CORJIT_FLAG_UNUSED32 = 59, CORJIT_FLAG_UNUSED33 = 60, CORJIT_FLAG_UNUSED34 = 61, CORJIT_FLAG_UNUSED35 = 62, CORJIT_FLAG_UNUSED36 = 63 }; CORJIT_FLAGS() : corJitFlags(0) { // empty } // Convenience constructor to set exactly one flag. CORJIT_FLAGS(CorJitFlag flag) : corJitFlags(0) { Set(flag); } CORJIT_FLAGS(const CORJIT_FLAGS& other) { corJitFlags = other.corJitFlags; instructionSetFlags = other.instructionSetFlags; } void Reset() { corJitFlags = 0; instructionSetFlags.Reset(); } void Set(CORINFO_InstructionSet instructionSet) { instructionSetFlags.AddInstructionSet(instructionSet); } bool IsSet(CORINFO_InstructionSet instructionSet) const { return instructionSetFlags.HasInstructionSet(instructionSet); } void Clear(CORINFO_InstructionSet instructionSet) { instructionSetFlags.RemoveInstructionSet(instructionSet); } void Set64BitInstructionSetVariants() { instructionSetFlags.Set64BitInstructionSetVariants(); } void Set(CorJitFlag flag) { corJitFlags |= 1ULL << (uint64_t)flag; } void Clear(CorJitFlag flag) { corJitFlags &= ~(1ULL << (uint64_t)flag); } bool IsSet(CorJitFlag flag) const { return (corJitFlags & (1ULL << (uint64_t)flag)) != 0; } void Add(const CORJIT_FLAGS& other) { corJitFlags |= other.corJitFlags; instructionSetFlags.Add(other.instructionSetFlags); } bool IsEmpty() const { return corJitFlags == 0 && instructionSetFlags.IsEmpty(); } void EnsureValidInstructionSetSupport() { instructionSetFlags = EnsureInstructionSetFlagsAreValid(instructionSetFlags); } // DO NOT USE THIS FUNCTION! (except in very restricted special cases) uint64_t GetFlagsRaw() { return corJitFlags; } // DO NOT USE THIS FUNCTION! (except in very restricted special cases) uint64_t* GetInstructionSetFlagsRaw() { return instructionSetFlags.GetFlagsRaw(); } CORINFO_InstructionSetFlags GetInstructionSetFlags() { return instructionSetFlags; } const int GetInstructionFlagsFieldCount() { return instructionSetFlags.GetInstructionFlagsFieldCount(); } private: uint64_t corJitFlags; CORINFO_InstructionSetFlags instructionSetFlags; }; #endif // _COR_JIT_FLAGS_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corjithost.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __CORJITHOST_H__ #define __CORJITHOST_H__ // ICorJitHost // // ICorJitHost provides the interface that the JIT uses to access some functionality that // would normally be provided by the operating system. This is intended to allow for // host-specific policies re: memory allocation, configuration value access, etc. It is // expected that the `ICorJitHost` value provided to `jitStartup` lives at least as // long as the JIT itself. class ICorJitHost { public: // Allocate memory of the given size in bytes. virtual void* allocateMemory(size_t size) = 0; // Frees memory previous obtained by a call to `ICorJitHost::allocateMemory`. virtual void freeMemory(void* block) = 0; // Return an integer config value for the given key, if any exists. virtual int getIntConfigValue( const WCHAR* name, int defaultValue ) = 0; // Return a string config value for the given key, if any exists. virtual const WCHAR* getStringConfigValue( const WCHAR* name ) = 0; // Free a string ConfigValue returned by the runtime. // JITs using the getStringConfigValue query are required // to return the string values to the runtime for deletion. // This avoids leaking the memory in the JIT. virtual void freeStringConfigValue( const WCHAR* value ) = 0; // Allocate memory slab of the given size in bytes. The host is expected to pool // these for a good performance. virtual void* allocateSlab(size_t size, size_t* pActualSize) { *pActualSize = size; return allocateMemory(size); } // Free memory slab of the given size in bytes. virtual void freeSlab(void* slab, size_t actualSize) { freeMemory(slab); } }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corpriv.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== // File: CORPRIV.H // // =========================================================================== #ifndef _CORPRIV_H_ #define _CORPRIV_H_ #if _MSC_VER >= 1000 #pragma once #endif // _MSC_VER >= 1000 // %%Includes: --------------------------------------------------------------- // avoid taking DLL import hit on intra-DLL calls #define NODLLIMPORT #include #include "cor.h" #include "corimage.h" #include "metadata.h" #include // interface IAssemblyName; class UTSemReadWrite; // Helper function to get a pointer to the Dispenser interface. STDAPI MetaDataGetDispenser( // Return HRESULT REFCLSID rclsid, // The class to desired. REFIID riid, // Interface wanted on class factory. LPVOID FAR *ppv); // Return interface pointer here. BOOL RuntimeFileNotFound(HRESULT hr); // Helper function to get an Internal interface with an in-memory metadata section STDAPI GetMetaDataInternalInterface( LPVOID pData, // [IN] in memory metadata section ULONG cbData, // [IN] size of the metadata section DWORD flags, // [IN] CorOpenFlags REFIID riid, // [IN] desired interface void **ppv); // [OUT] returned interface // Helper function to get an internal scopeless interface given a scope. STDAPI GetMetaDataInternalInterfaceFromPublic( IUnknown *pv, // [IN] Given interface REFIID riid, // [IN] desired interface void **ppv); // [OUT] returned interface // Helper function to get an internal scopeless interface given a scope. STDAPI GetMetaDataPublicInterfaceFromInternal( void *pv, // [IN] Given interface REFIID riid, // [IN] desired interface void **ppv); // [OUT] returned interface // Converts an internal MD import API into the read/write version of this API. // This could support edit and continue, or modification of the metadata at // runtime (say for profiling). STDAPI ConvertMDInternalImport( // S_OK or error. IMDInternalImport *pIMD, // [IN] The metadata to be updated. IMDInternalImport **ppIMD); // [OUT] Put RW interface here. STDAPI GetAssemblyMDInternalImport( // Return code. LPCWSTR szFileName, // [IN] The scope to open. REFIID riid, // [IN] The interface desired. IUnknown **ppIUnk); // [OUT] Return interface on success. STDAPI GetAssemblyMDInternalImportByStream( // Return code. IStream *pIStream, // [IN] The IStream for the file UINT64 AssemblyId, // [IN] Unique Id for the assembly REFIID riid, // [IN] The interface desired. IUnknown **ppIUnk); // [OUT] Return interface on success. enum MDInternalImportFlags { MDInternalImport_Default = 0, MDInternalImport_NoCache = 1, // Do not share/cached the results of opening the image // unused = 2, // unused = 4, MDInternalImport_OnlyLookInCache =0x20, // Only look in the cache. (If the cache does not have the image already loaded, return NULL) }; // enum MDInternalImportFlags STDAPI GetAssemblyMDInternalImportEx( // Return code. LPCWSTR szFileName, // [IN] The scope to open. REFIID riid, // [IN] The interface desired. MDInternalImportFlags flags, // [in] Flags to control opening the assembly IUnknown **ppIUnk, // [OUT] Return interface on success. HANDLE hFile = INVALID_HANDLE_VALUE); STDAPI GetAssemblyMDInternalImportByStreamEx( // Return code. IStream *pIStream, // [IN] The IStream for the file UINT64 AssemblyId, // [IN] Unique Id for the assembly REFIID riid, // [IN] The interface desired. MDInternalImportFlags flags, // [in] Flags to control opening the assembly IUnknown **ppIUnk); // [OUT] Return interface on success. // Returns part of the "Zap string" which describes the properties of a native image __success(SUCCEEDED(return)) STDAPI GetNativeImageDescription( _In_z_ LPCWSTR wzCustomString, // [IN] Custom string of the native image DWORD dwConfigMask, // [IN] Config mask of the native image _Out_writes_to_opt_(*pdwLength,*pdwLength) LPWSTR pwzZapInfo,// [OUT] The description string. Can be NULL to find the size of buffer to allocate LPDWORD pdwLength); // [IN/OUT] Length of the pwzZapInfo buffer on IN. // Number of WCHARs (including termintating NULL) on OUT class CQuickBytes; // predefined constant for parent token for global functions #define COR_GLOBAL_PARENT_TOKEN TokenFromRid(1, mdtTypeDef) ////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////// // %%Interfaces: ------------------------------------------------------------- // interface IMetaDataHelper // {AD93D71D-E1F2-11d1-9409-0000F8083460} EXTERN_GUID(IID_IMetaDataHelper, 0xad93d71d, 0xe1f2, 0x11d1, 0x94, 0x9, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); #undef INTERFACE #define INTERFACE IMetaDataHelper DECLARE_INTERFACE_(IMetaDataHelper, IUnknown) { // helper functions // This function is exposing the ability to translate signature from a given // source scope to a given target scope. // STDMETHOD(TranslateSigWithScope)( IMetaDataAssemblyImport *pAssemImport, // [IN] importing assembly interface const void *pbHashValue, // [IN] Hash Blob for Assembly. ULONG cbHashValue, // [IN] Count of bytes. IMetaDataImport *import, // [IN] importing interface PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope ULONG cbSigBlob, // [IN] count of bytes of signature IMetaDataAssemblyEmit *pAssemEmit, // [IN] emit assembly interface IMetaDataEmit *emit, // [IN] emit interface PCOR_SIGNATURE pvTranslatedSig, // [OUT] buffer to hold translated signature ULONG cbTranslatedSigMax, ULONG *pcbTranslatedSig) PURE;// [OUT] count of bytes in the translated signature STDMETHOD(GetMetadata)( ULONG ulSelect, // [IN] Selector. void **ppData) PURE; // [OUT] Put pointer to data here. STDMETHOD_(IUnknown *, GetCachedInternalInterface)(BOOL fWithLock) PURE; // S_OK or error STDMETHOD(SetCachedInternalInterface)(IUnknown * pUnk) PURE; // S_OK or error STDMETHOD_(UTSemReadWrite*, GetReaderWriterLock)() PURE; // return the reader writer lock STDMETHOD(SetReaderWriterLock)(UTSemReadWrite * pSem) PURE; }; // IMetaDataHelper EXTERN_GUID(IID_IMetaDataEmitHelper, 0x5c240ae4, 0x1e09, 0x11d3, 0x94, 0x24, 0x0, 0x0, 0xf8, 0x8, 0x34, 0x60); #undef INTERFACE #define INTERFACE IMetaDataEmitHelper DECLARE_INTERFACE_(IMetaDataEmitHelper, IUnknown) { // emit helper functions STDMETHOD(DefineMethodSemanticsHelper)( mdToken tkAssociation, // [IN] property or event token DWORD dwFlags, // [IN] semantics mdMethodDef md) PURE; // [IN] method to associated with STDMETHOD(SetFieldLayoutHelper)( // Return hresult. mdFieldDef fd, // [IN] field to associate the layout info ULONG ulOffset) PURE; // [IN] the offset for the field STDMETHOD(DefineEventHelper) ( mdTypeDef td, // [IN] the class/interface on which the event is being defined LPCWSTR szEvent, // [IN] Name of the event DWORD dwEventFlags, // [IN] CorEventAttr mdToken tkEventType, // [IN] a reference (mdTypeRef or mdTypeRef) to the Event class mdEvent *pmdEvent) PURE; // [OUT] output event token STDMETHOD(AddDeclarativeSecurityHelper) ( mdToken tk, // [IN] Parent token (typedef/methoddef) DWORD dwAction, // [IN] Security action (CorDeclSecurity) void const *pValue, // [IN] Permission set blob DWORD cbValue, // [IN] Byte count of permission set blob mdPermission*pmdPermission) PURE; // [OUT] Output permission token STDMETHOD(SetResolutionScopeHelper)( // Return hresult. mdTypeRef tr, // [IN] TypeRef record to update mdToken rs) PURE; // [IN] new ResolutionScope STDMETHOD(SetManifestResourceOffsetHelper)( // Return hresult. mdManifestResource mr, // [IN] The manifest token ULONG ulOffset) PURE; // [IN] new offset STDMETHOD(SetTypeParent)( // Return hresult. mdTypeDef td, // [IN] Type definition mdToken tkExtends) PURE; // [IN] parent type STDMETHOD(AddInterfaceImpl)( // Return hresult. mdTypeDef td, // [IN] Type definition mdToken tkInterface) PURE; // [IN] interface type }; // IMetaDataEmitHelper ////////////////////////////////////////////////////////////////////////////// // enum CorElementTypeZapSig defines some additional internal ELEMENT_TYPE's // values that are only used by ZapSig signatures. ////////////////////////////////////////////////////////////////////////////// typedef enum CorElementTypeZapSig { // ZapSig encoding for ELEMENT_TYPE_VAR and ELEMENT_TYPE_MVAR. It is always followed // by the RID of a GenericParam token, encoded as a compressed integer. ELEMENT_TYPE_VAR_ZAPSIG = 0x3b, // UNUSED = 0x3c, // ZapSig encoding for native value types in IL stubs. IL stub signatures may contain // ELEMENT_TYPE_INTERNAL followed by ParamTypeDesc with ELEMENT_TYPE_VALUETYPE element // type. It acts like a modifier to the underlying structure making it look like its // unmanaged view (size determined by unmanaged layout, blittable, no GC pointers). // // ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG is used when encoding such types to NGEN images. // The signature looks like this: ET_NATIVE_VALUETYPE_ZAPSIG ET_VALUETYPE . // See code:ZapSig.GetSignatureForTypeHandle and code:SigPointer.GetTypeHandleThrowing // where the encoding/decoding takes place. ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG = 0x3d, ELEMENT_TYPE_CANON_ZAPSIG = 0x3e, // zapsig encoding for System.__Canon ELEMENT_TYPE_MODULE_ZAPSIG = 0x3f, // zapsig encoding for external module id# } CorElementTypeZapSig; typedef enum CorCallingConventionInternal { // IL stub signatures containing types that need to be restored have the highest // bit of the calling convention set. IMAGE_CEE_CS_CALLCONV_NEEDSRESTORE = 0x80, } CorCallingConventionInternal; ////////////////////////////////////////////////////////////////////////// // Obsoleted ELEMENT_TYPE values which are not supported anymore. // They are not part of CLI ECMA spec, they were only experimental before v1.0 RTM. // They are needed for indexing arrays initialized using file:corTypeInfo.h // 0x17 ... VALUEARRAY // 0x1a ... CPU native floating-point type ////////////////////////////////////////////////////////////////////////// #define ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED ((CorElementType) 0x17) #define ELEMENT_TYPE_R_UNSUPPORTED ((CorElementType) 0x1a) // Use this guid in the SetOption if Reflection.Emit wants to control size of the initially allocated // MetaData. See values: code:CorMetaDataInitialSize. // // {2675b6bf-f504-4cb4-a4d5-084eea770ddc} EXTERN_GUID(MetaDataInitialSize, 0x2675b6bf, 0xf504, 0x4cb4, 0xa4, 0xd5, 0x08, 0x4e, 0xea, 0x77, 0x0d, 0xdc); // Allowed values for code:MetaDataInitialSize option. typedef enum CorMetaDataInitialSize { MDInitialSizeDefault = 0, MDInitialSizeMinimal = 1 } CorMetaDataInitialSize; // Internal extension of open flags code:CorOpenFlags typedef enum CorOpenFlagsInternal { #ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES // Flag code:ofTrustedImage is used by mscordbi.dll, therefore defined in file:CorPriv.h ofTrustedImage = ofReserved3 // We trust this PE file (we are willing to do a LoadLibrary on it). // It is optional and only an (VM) optimization - typically for NGEN images // opened by debugger. #endif } CorOpenFlagsInternal; #ifdef FEATURE_METADATA_LOAD_TRUSTED_IMAGES #define IsOfTrustedImage(x) ((x) & ofTrustedImage) #endif // %%Classes: ---------------------------------------------------------------- #define COR_MODULE_CLASS "" #define COR_WMODULE_CLASS W("") //***************************************************************************** //***************************************************************************** // // CeeGen interfaces for generating in-memory Common Language Runtime files // //***************************************************************************** //***************************************************************************** typedef void* HCEESECTION; typedef enum { sdNone = 0, sdReadOnly = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_INITIALIZED_DATA, sdReadWrite = sdReadOnly | IMAGE_SCN_MEM_WRITE, sdExecute = IMAGE_SCN_MEM_READ | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE } CeeSectionAttr; // // Relocation types. // typedef enum { // generate only a section-relative reloc, nothing into .reloc section srRelocAbsolute, // generate a .reloc for a pointer sized location, // This is transformed into BASED_HIGHLOW or BASED_DIR64 based on the platform srRelocHighLow = 3, // generate a .reloc for the top 16-bits of a 32 bit number, where the // bottom 16 bits are included in the next word in the .reloc table srRelocHighAdj, // Never Used // generate a token map relocation, nothing into .reloc section srRelocMapToken, // relative address fixup srRelocRelative, // Generate only a section-relative reloc, nothing into .reloc // section. This reloc is relative to the file position of the // section, not the section's virtual address. srRelocFilePos, // code relative address fixup srRelocCodeRelative, // generate a .reloc for a 64 bit address in an ia64 movl instruction srRelocIA64Imm64, // generate a .reloc for a 64 bit address srRelocDir64, // generate a .reloc for a 25-bit PC relative address in an ia64 br.call instruction srRelocIA64PcRel25, // generate a .reloc for a 64-bit PC relative address in an ia64 brl.call instruction srRelocIA64PcRel64, // generate a 30-bit section-relative reloc, used for tagged pointer values srRelocAbsoluteTagged, // A sentinel value to help ensure any additions to this enum are reflected // in PEWriter.cpp's RelocName array. srRelocSentinel, // Flags that can be used with the above reloc types // do not emit base reloc srNoBaseReloc = 0x4000, // pre-fixup contents of memory are ptr rather than a section offset srRelocPtr = 0x8000, // legal enums which include the Ptr flag srRelocAbsolutePtr = srRelocPtr + srRelocAbsolute, srRelocHighLowPtr = srRelocPtr + srRelocHighLow, srRelocRelativePtr = srRelocPtr + srRelocRelative, srRelocIA64Imm64Ptr = srRelocPtr + srRelocIA64Imm64, srRelocDir64Ptr = srRelocPtr + srRelocDir64, } CeeSectionRelocType; typedef union { USHORT highAdj; } CeeSectionRelocExtra; //------------------------------------- //--- ICeeGenInternal //------------------------------------- // {8C26FC02-BE39-476D-B835-E17EDD120246} EXTERN_GUID(IID_ICeeGenInternal, 0x8c26fc02, 0xbe39, 0x476d, 0xb8, 0x35, 0xe1, 0x7e, 0xdd, 0x12, 0x2, 0x46); #undef INTERFACE #define INTERFACE ICeeGenInternal DECLARE_INTERFACE_(ICeeGenInternal, IUnknown) { STDMETHOD(EmitString) ( _In_ LPWSTR lpString, // [IN] String to emit ULONG * RVA) PURE; // [OUT] RVA for string emitted string STDMETHOD(GetString) ( ULONG RVA, // [IN] RVA for string to return _Out_opt_ LPWSTR * lpString) PURE; // [OUT] Returned string STDMETHOD(AllocateMethodBuffer) ( ULONG cchBuffer, // [IN] Length of buffer to create UCHAR * *lpBuffer, // [OUT] Returned buffer ULONG * RVA) PURE; // [OUT] RVA for method STDMETHOD(GetMethodBuffer) ( ULONG RVA, // [IN] RVA for method to return UCHAR * *lpBuffer) PURE; // [OUT] Returned buffer STDMETHOD(GetIMapTokenIface) ( IUnknown * *pIMapToken) PURE; STDMETHOD(GenerateCeeFile) () PURE; STDMETHOD(GetIlSection) ( HCEESECTION * section) PURE; STDMETHOD(GetStringSection) ( HCEESECTION * section) PURE; STDMETHOD(AddSectionReloc) ( HCEESECTION section, ULONG offset, HCEESECTION relativeTo, CeeSectionRelocType relocType) PURE; // use these only if you have special section requirements not handled // by other APIs STDMETHOD(GetSectionCreate) ( const char* name, DWORD flags, HCEESECTION * section) PURE; STDMETHOD(GetSectionDataLen) ( HCEESECTION section, ULONG * dataLen) PURE; STDMETHOD(GetSectionBlock) ( HCEESECTION section, ULONG len, ULONG align = 1, void** ppBytes = 0) PURE; STDMETHOD(ComputePointer) ( HCEESECTION section, ULONG RVA, // [IN] RVA for method to return UCHAR * *lpBuffer) PURE; // [OUT] Returned buffer STDMETHOD(SetInitialGrowth) (DWORD growth) PURE; }; // // IGetIMDInternalImport // // Private interface exposed by // AssemblyMDInternalImport - gives us access to the internally stored IMDInternalImport*. // // RegMeta - supports the internal GetMetaDataInternalInterfaceFromPublic() "api". // // {92B2FEF9-F7F5-420d-AD42-AECEEE10A1EF} EXTERN_GUID(IID_IGetIMDInternalImport, 0x92b2fef9, 0xf7f5, 0x420d, 0xad, 0x42, 0xae, 0xce, 0xee, 0x10, 0xa1, 0xef); #undef INTERFACE #define INTERFACE IGetIMDInternalImport DECLARE_INTERFACE_(IGetIMDInternalImport, IUnknown) { STDMETHOD(GetIMDInternalImport) ( IMDInternalImport ** ppIMDInternalImport // [OUT] Buffer to receive IMDInternalImport* ) PURE; }; #endif // _CORPRIV_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corprof.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /************************************************************************************** ** ** ** Corprof.idl - CLR Profiling interfaces. ** ** ** **************************************************************************************/ /* -------------------------------------------------------------------------- * * Imported types * -------------------------------------------------------------------------- */ #if !DEFINITIONS_FROM_NON_IMPORTABLE_PLACES cpp_quote("#if 0") import "unknwn.idl"; typedef LONG32 mdToken; typedef mdToken mdModule; typedef mdToken mdTypeDef; typedef mdToken mdMethodDef; typedef mdToken mdFieldDef; typedef ULONG CorElementType; // Forward declaration of enum in CorHdr.h enum CorElementType; // Forward declaration of structs in Cor.h typedef struct { DWORD dwOSPlatformId; // Operating system platform. DWORD dwOSMajorVersion; // OS Major version. DWORD dwOSMinorVersion; // OS Minor version. } OSINFO; typedef struct { USHORT usMajorVersion; // Major Version. USHORT usMinorVersion; // Minor Version. USHORT usBuildNumber; // Build Number. USHORT usRevisionNumber; // Revision Number. LPWSTR szLocale; // Locale. ULONG cbLocale; // [IN/OUT] Size of the buffer in wide chars/Actual size. DWORD *rProcessor; // Processor ID array. ULONG ulProcessor; // [IN/OUT] Size of the Processor ID array/Actual # of entries filled in. OSINFO *rOS; // OSINFO array. ULONG ulOS; // [IN/OUT]Size of the OSINFO array/Actual # of entries filled in. } ASSEMBLYMETADATA; cpp_quote("#endif") typedef const BYTE *LPCBYTE; typedef BYTE *LPBYTE; typedef BYTE COR_SIGNATURE; typedef COR_SIGNATURE* PCOR_SIGNATURE; typedef const COR_SIGNATURE* PCCOR_SIGNATURE; #endif cpp_quote("#ifndef _COR_IL_MAP") cpp_quote("#define _COR_IL_MAP") #ifdef INTERNAL_DOCS // Note that this structure is also defined in CorDebug.idl - PROPAGATE CHANGES // BOTH WAYS, or this'll become a really insidious bug some day. #endif typedef struct _COR_IL_MAP { ULONG32 oldOffset; // Old IL offset relative to beginning of function ULONG32 newOffset; // New IL offset relative to beginning of function BOOL fAccurate; //put here for compatibility with the Debugger structure. } COR_IL_MAP; cpp_quote("#endif //_COR_IL_MAP") cpp_quote("#ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_") cpp_quote("#define _COR_DEBUG_IL_TO_NATIVE_MAP_") /* ICorProfilerInfo:: GetILToNativeMapping returns an array of * COR_DEBUG_IL_TO_NATIVE_MAP structures. In order to convey that certain * ranges of native instructions correspond to special regions of code (for * example, the prolog), an entry in the array may have it's ilOffset field set * to one of these values. */ typedef enum CorDebugIlToNativeMappingTypes { NO_MAPPING = -1, PROLOG = -2, EPILOG = -3 } CorDebugIlToNativeMappingTypes; typedef struct COR_DEBUG_IL_TO_NATIVE_MAP { ULONG32 ilOffset; ULONG32 nativeStartOffset; ULONG32 nativeEndOffset; } COR_DEBUG_IL_TO_NATIVE_MAP; cpp_quote("#endif // _COR_DEBUG_IL_TO_NATIVE_MAP_") cpp_quote("#ifndef _COR_FIELD_OFFSET_") cpp_quote("#define _COR_FIELD_OFFSET_") typedef struct _COR_FIELD_OFFSET { mdFieldDef ridOfField; // fieldDef token of the field ULONG ulOffset; // offset (from the ObjectID pointer) of the field } COR_FIELD_OFFSET; cpp_quote("#endif // _COR_FIELD_OFFSET_") #ifndef DO_NO_IMPORTS import "wtypes.idl"; import "unknwn.idl"; #endif #define STDMETHODCALLTYPE typedef UINT_PTR ProcessID; typedef UINT_PTR AssemblyID; typedef UINT_PTR AppDomainID; typedef UINT_PTR ModuleID; typedef UINT_PTR ClassID; typedef UINT_PTR ThreadID; typedef UINT_PTR ContextID; typedef UINT_PTR FunctionID; typedef UINT_PTR ObjectID; typedef UINT_PTR GCHandleID; typedef UINT_PTR COR_PRF_ELT_INFO; typedef UINT_PTR ReJITID; typedef union {FunctionID functionID; UINT_PTR clientID;} FunctionIDOrClientID; /* * The FunctionIDMapper type definition is used by the * ICorProfilerInfo::SetFunctionIDMapper method to specify * a function that will be called to map FunctionIDs to alternative * values that will be passed to the function entry and function exit * callbacks supplied to the ICorProfilerInfo::SetEnterLeaveFunctionHooks * method. The mapper can be set only once and it is recommended to do so * in the Initialize callback. * * NOTE: There is a known bug in this API that must be worked around. * The return value of FunctionIDMapper cannot be NULL (unless the boolean * value in pbHookTheFunction is FALSE). All other values are treated as * opaque data to be passed to the entry/exit callback functions. The use * of a NULL return value will produce unpredictable results, including * possibly halting the process. * * NOTE: Profilers should be tolerant of cases where multiple threads of * a profiled app are calling the same method simultaneously. In such * cases, the profiler may receive multiple FunctionIDMapper callbacks * for the same functionId. The profiler should be certain to return * the same values from this callback when it is called multiple times * with the same functionId. * */ typedef UINT_PTR __stdcall FunctionIDMapper( FunctionID funcId, BOOL *pbHookFunction); typedef UINT_PTR __stdcall FunctionIDMapper2( FunctionID funcId, void *clientData, BOOL *pbHookFunction); /* * Enum for specifying how much data to pass back with a stack snapshot */ typedef enum _COR_PRF_SNAPSHOT_INFO { COR_PRF_SNAPSHOT_DEFAULT = 0x0, // Return a register context for each frame COR_PRF_SNAPSHOT_REGISTER_CONTEXT = 0x1, // Use a quicker stack walk algorithm based on the EBP frame chain. This is available // on x86 only. COR_PRF_SNAPSHOT_X86_OPTIMIZED = 0x2, } COR_PRF_SNAPSHOT_INFO; /* * Opaque handle that represents information about a given stack frame. It is only * valid during the callback to which it is passed. */ typedef UINT_PTR COR_PRF_FRAME_INFO; /* * Describes a range of function arguments stored contiguously in left-to-right * order in memory. */ typedef struct _COR_PRF_FUNCTION_ARGUMENT_RANGE { UINT_PTR startAddress; // start address of the range ULONG length; // contiguous length of the range } COR_PRF_FUNCTION_ARGUMENT_RANGE; /* * Describes the locations in memory of a function's arguments, in * left-to-right order. Note that arguments stored in registers are * spilled to memory to build these structures. */ typedef struct _COR_PRF_FUNCTION_ARGUMENT_INFO { ULONG numRanges; // number of chunks of arguments ULONG totalArgumentSize; // total size of arguments COR_PRF_FUNCTION_ARGUMENT_RANGE ranges[1]; // chunks } COR_PRF_FUNCTION_ARGUMENT_INFO; /* * Represents one contiguous chunk of native code */ typedef struct _COR_PRF_CODE_INFO { UINT_PTR startAddress; SIZE_T size; } COR_PRF_CODE_INFO; /* * Enum for describing the type of static a field is. These may be bit-wise * or'ed with each other if the field is multiple types. */ typedef enum { COR_PRF_FIELD_NOT_A_STATIC = 0x0, COR_PRF_FIELD_APP_DOMAIN_STATIC = 0x1, COR_PRF_FIELD_THREAD_STATIC = 0x2, COR_PRF_FIELD_CONTEXT_STATIC = 0x4, COR_PRF_FIELD_RVA_STATIC = 0x8 } COR_PRF_STATIC_TYPE; /* * Represents a function uniquely by combining the FunctionID * with a ReJITID. */ typedef struct _COR_PRF_FUNCTION { FunctionID functionId; ReJITID reJitId; } COR_PRF_FUNCTION; /* * Structure populated by profiler when declaring additional assembly references * that the CLR should consider when performing an assembly reference closure * walk. See ICorProfilerCallback6::GetAssemblyReferences and * ICorProfilerAssemblyReferenceProvider::AddAssemblyReference */ typedef struct _COR_PRF_ASSEMBLY_REFERENCE_INFO { void *pbPublicKeyOrToken; // Public key or token of the assembly. ULONG cbPublicKeyOrToken; // Count of bytes in the public key or token. LPCWSTR szName; // Name of the assembly being referenced. ASSEMBLYMETADATA * pMetaData; // Assembly MetaData, as defined in cor.h void *pbHashValue; // Hash Blob. ULONG cbHashValue; // Count of bytes in the Hash Blob. DWORD dwAssemblyRefFlags; // Flags. } COR_PRF_ASSEMBLY_REFERENCE_INFO; /* * Represents a IL methods uniquely by combining the module ID and method token. */ typedef struct _COR_PRF_METHOD { ModuleID moduleId; mdMethodDef methodId; } COR_PRF_METHOD; /* * NOTE!!! * * The following applies to ALL FunctionEnter[2,3], FunctionLeave[2,3], * FunctionTailcall[2,3] hooks below: * * It is VERY IMPORTANT to note that these function implementations must be * __declspec(naked), since the EE is not saving any registers before calling * any of them. YOU MUST SAVE ALL REGISTERS YOU USE, INCLUDING FPU REGISTERS * IF THE FPU STACK IS NOT EMPTY AND YOU INTEND TO USE IT. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ /* * NOTE: DEPRECATED IN V2 * * These functions are considered deprecated in V2 and higher. They will * continue to work, but incur a performance penalty for usage. For equivalent * functionality, use the FunctionEnter3/Leave3/Tailcall3 callbacks with * bits cleared for COR_PRF_ENABLE_FRAME_INFO, COR_PRF_ENABLE_FUNCTION_RETVAL * and COR_PRF_ENABLE_FUNCTION_ARGS. */ typedef void STDMETHODCALLTYPE FunctionEnter( FunctionID funcID); typedef void STDMETHODCALLTYPE FunctionLeave( FunctionID funcID); typedef void STDMETHODCALLTYPE FunctionTailcall( FunctionID funcID); /* * NOTE: DEPRECATED IN V4 * * These functions are considered deprecated in V4 and higher. They will * continue to work, but incur a performance penalty for usage. For equivalent * functionality, use the FunctionEnter3/Leave3/Tailcall3 callbacks. */ typedef void STDMETHODCALLTYPE FunctionEnter2( FunctionID funcId, UINT_PTR clientData, COR_PRF_FRAME_INFO func, COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo); typedef void STDMETHODCALLTYPE FunctionLeave2( FunctionID funcId, UINT_PTR clientData, COR_PRF_FRAME_INFO func, COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange); typedef void STDMETHODCALLTYPE FunctionTailcall2( FunctionID funcId, UINT_PTR clientData, COR_PRF_FRAME_INFO func); /* * When you are not interested in inspecting arguments or return values, then * use these to be notified as functions are called and return. Use * SetEnterLeaveFunctionHooks3 to register your implementations of these * functions. * * functionIDOrClientID: if the profiler returned a remapped value from * FunctionIDMapper[2], then this is that remapped value; else it is the * true FunctionID of the function. */ typedef void STDMETHODCALLTYPE FunctionEnter3( FunctionIDOrClientID functionIDOrClientID); typedef void STDMETHODCALLTYPE FunctionLeave3( FunctionIDOrClientID functionIDOrClientID); typedef void STDMETHODCALLTYPE FunctionTailcall3( FunctionIDOrClientID functionIDOrClientID); /* * When you are interested in inspecting arguments and return values, then * use these to be notified as functions are called and return. Use * SetEnterLeaveFunctionHooks3WithInfo to register your implementations of these * functions. * * functionIDOrClientID: if the profiler returned a remapped value from * FunctionIDMapper[2], then this is that remapped value; else it is the * true FunctionID of the function. * * eltInfo is an opaque handle that represents information about a given stack frame. * It is only valid during the callback to which it is passed. */ typedef void STDMETHODCALLTYPE FunctionEnter3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); typedef void STDMETHODCALLTYPE FunctionLeave3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); typedef void STDMETHODCALLTYPE FunctionTailcall3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); /* * Stack snapshot callback definition. * * This callback is called once per managed frame or run of unmanaged frames. * * funcID is the FunctionID of the managed function. If funcID == 0, the callback is * for a run of unmanaged frames. The profiler may either ignore the frame, or use * the register context to perform its own unmanaged stackwalk. * * ip is the native IP in the frame * * frameInfo is the COR_PRF_FRAME_INFO for this frame. It is only valid for * use during this callback. * * context is a Win32 CONTEXT struct for the current platform (size given in * contextSize). It will only be valid if the COR_PRF_SNAPSHOT_CONTEXT flag * was passed to DoStackSnapshot. * * clientData is a void* passed straight through from DoStackSnapshot * * NOTE: One must limit the complexity of work done in StackSnapshotCallback. * For example, particularly when using DoStackSnapshot in an asynchronous manner, * the target thread may be holding locks. Executing code within StackSnapshotCallback * that requires the same locks could lead to deadlock. */ typedef HRESULT __stdcall StackSnapshotCallback( FunctionID funcId, UINT_PTR ip, COR_PRF_FRAME_INFO frameInfo, ULONG32 contextSize, BYTE context[], void *clientData); /* Callback for each object reference */ typedef BOOL STDMETHODCALLTYPE ObjectReferenceCallback(ObjectID root, ObjectID* reference, void *clientData); typedef enum { // These flags represent classes of callback events COR_PRF_MONITOR_NONE = 0x00000000, // MONITOR_FUNCTION_UNLOADS controls the // FunctionUnloadStarted callback. COR_PRF_MONITOR_FUNCTION_UNLOADS = 0x00000001, // MONITOR_CLASS_LOADS controls the ClassLoad* // and ClassUnload* callbacks. // See the comments on those callbacks for important // behavior changes in V2. COR_PRF_MONITOR_CLASS_LOADS = 0x00000002, // MONITOR_MODULE_LOADS controls the // ModuleLoad*, ModuleUnload*, and ModuleAttachedToAssembly // callbacks. COR_PRF_MONITOR_MODULE_LOADS = 0x00000004, // MONITOR_ASSEMBLY_LOADS controls the // AssemblyLoad* and AssemblyUnload* callbacks COR_PRF_MONITOR_ASSEMBLY_LOADS = 0x00000008, // MONITOR_APPDOMAIN_LOADS controls the // AppDomainCreation* and AppDomainShutdown* callbacks COR_PRF_MONITOR_APPDOMAIN_LOADS = 0x00000010, // MONITOR_JIT_COMPILATION controls the // JITCompilation*, JITFunctionPitched, and JITInlining // callbacks. COR_PRF_MONITOR_JIT_COMPILATION = 0x00000020, // MONITOR_EXCEPTIONS controls the ExceptionThrown, // ExceptionSearch*, ExceptionOSHandler*, ExceptionUnwind*, // and ExceptionCatcher* callbacks. COR_PRF_MONITOR_EXCEPTIONS = 0x00000040, // MONITOR_GC controls the GarbageCollectionStarted/Finished, // MovedReferences, SurvivingReferences, // ObjectReferences, ObjectsAllocatedByClass, // RootReferences*, HandleCreated/Destroyed, and FinalizeableObjectQueued // callbacks. COR_PRF_MONITOR_GC = 0x00000080, // MONITOR_OBJECT_ALLOCATED controls the // ObjectAllocated callback. COR_PRF_MONITOR_OBJECT_ALLOCATED = 0x00000100, // MONITOR_THREADS controls the ThreadCreated, // ThreadDestroyed, ThreadAssignedToOSThread, // and ThreadNameChanged callbacks. COR_PRF_MONITOR_THREADS = 0x00000200, // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr // MONITOR_REMOTING controls the Remoting* // callbacks. COR_PRF_MONITOR_REMOTING = 0x00000400, // MONITOR_CODE_TRANSITIONS controls the // UnmanagedToManagedTransition and // ManagedToUnmanagedTransition callbacks. COR_PRF_MONITOR_CODE_TRANSITIONS = 0x00000800, // MONITOR_ENTERLEAVE controls the // FunctionEnter*/Leave*/Tailcall* callbacks COR_PRF_MONITOR_ENTERLEAVE = 0x00001000, // MONITOR_CCW controls the COMClassicVTable* // callbacks. COR_PRF_MONITOR_CCW = 0x00002000, // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr // MONITOR_REMOTING_COOKIE controls whether // a cookie will be passed to the Remoting* callbacks COR_PRF_MONITOR_REMOTING_COOKIE = 0x00004000 | COR_PRF_MONITOR_REMOTING, // CORECLR DEPRECATION WARNING: Remoting no longer exists in coreclr // MONITOR_REMOTING_ASYNC controls whether // the Remoting* callbacks will monitor async events COR_PRF_MONITOR_REMOTING_ASYNC = 0x00008000 | COR_PRF_MONITOR_REMOTING, // MONITOR_SUSPENDS controls the RuntimeSuspend*, // RuntimeResume*, RuntimeThreadSuspended, and // RuntimeThreadResumed callbacks. COR_PRF_MONITOR_SUSPENDS = 0x00010000, // MONITOR_CACHE_SEARCHES controls the // JITCachedFunctionSearch* callbacks. // See the comments on those callbacks for important // behavior changes in V2. COR_PRF_MONITOR_CACHE_SEARCHES = 0x00020000, // NOTE: ReJIT is now supported again. The profiler must set this flag on // startup in order to use RequestReJIT or RequestRevert. If the profiler specifies // this flag, then the profiler must also specify COR_PRF_DISABLE_ALL_NGEN_IMAGES COR_PRF_ENABLE_REJIT = 0x00040000, // V2 MIGRATION WARNING: DEPRECATED // Inproc debugging is no longer supported. ENABLE_INPROC_DEBUGGING // has no effect. COR_PRF_ENABLE_INPROC_DEBUGGING = 0x00080000, // V2 MIGRATION NOTE: DEPRECATED // The runtime now always tracks IL-native maps; this flag is thus always // considered to be set. COR_PRF_ENABLE_JIT_MAPS = 0x00100000, // DISABLE_INLINING tells the runtime to disable all inlining COR_PRF_DISABLE_INLINING = 0x00200000, // DISABLE_OPTIMIZATIONS tells the runtime to disable all code optimizations COR_PRF_DISABLE_OPTIMIZATIONS = 0x00400000, // ENABLE_OBJECT_ALLOCATED tells the runtime that the profiler may want // object allocation notifications. This must be set during initialization if the profiler // ever wants object notifications (using COR_PRF_MONITOR_OBJECT_ALLOCATED) COR_PRF_ENABLE_OBJECT_ALLOCATED = 0x00800000, // MONITOR_CLR_EXCEPTIONS controls the ExceptionCLRCatcher* // callbacks. COR_PRF_MONITOR_CLR_EXCEPTIONS = 0x01000000, // All callback events are enabled with this flag COR_PRF_MONITOR_ALL = 0x0107FFFF, // ENABLE_FUNCTION_ARGS enables argument tracing through FunctionEnter2. COR_PRF_ENABLE_FUNCTION_ARGS = 0X02000000, // ENABLE_FUNCTION_RETVAL enables retval tracing through FunctionLeave2. COR_PRF_ENABLE_FUNCTION_RETVAL = 0X04000000, // ENABLE_FRAME_INFO enables retrieval of exact ClassIDs for generic functions using // GetFunctionInfo2 with a COR_PRF_FRAME_INFO obtained from FunctionEnter2. COR_PRF_ENABLE_FRAME_INFO = 0X08000000, // ENABLE_STACK_SNAPSHOT enables the used of DoStackSnapshot calls. COR_PRF_ENABLE_STACK_SNAPSHOT = 0X10000000, // USE_PROFILE_IMAGES causes the native image search to look for profiler-enhanced // images. If no profiler-enhanced image is found for a given assembly the // runtime will fallback to JIT for that assembly. COR_PRF_USE_PROFILE_IMAGES = 0x20000000, // COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST will disable security // transparency checks normally done during JIT compilation and class loading for // full trust assemblies. This can make some instrumentation easier to perform. COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST = 0x40000000, // Prevents all NGEN images (including profiler-enhanced images) from loading. If // this and COR_PRF_USE_PROFILE_IMAGES are both specified, // COR_PRF_DISABLE_ALL_NGEN_IMAGES wins. COR_PRF_DISABLE_ALL_NGEN_IMAGES = 0x80000000, // The mask for valid mask bits COR_PRF_ALL = 0x8FFFFFFF, // COR_PRF_REQUIRE_PROFILE_IMAGE represents all flags that require profiler-enhanced // images. COR_PRF_REQUIRE_PROFILE_IMAGE = COR_PRF_USE_PROFILE_IMAGES | COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_ENTERLEAVE, COR_PRF_ALLOWABLE_AFTER_ATTACH = COR_PRF_MONITOR_THREADS | COR_PRF_MONITOR_MODULE_LOADS | COR_PRF_MONITOR_ASSEMBLY_LOADS | COR_PRF_MONITOR_APPDOMAIN_LOADS | COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_MONITOR_GC | COR_PRF_MONITOR_SUSPENDS | COR_PRF_MONITOR_CLASS_LOADS | COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_MONITOR_JIT_COMPILATION | COR_PRF_ENABLE_REJIT, COR_PRF_ALLOWABLE_NOTIFICATION_PROFILER = COR_PRF_MONITOR_FUNCTION_UNLOADS | COR_PRF_MONITOR_CLASS_LOADS | COR_PRF_MONITOR_MODULE_LOADS | COR_PRF_MONITOR_ASSEMBLY_LOADS | COR_PRF_MONITOR_APPDOMAIN_LOADS | COR_PRF_MONITOR_JIT_COMPILATION | COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_MONITOR_OBJECT_ALLOCATED | COR_PRF_MONITOR_THREADS | COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_CCW | COR_PRF_MONITOR_SUSPENDS | COR_PRF_MONITOR_CACHE_SEARCHES | COR_PRF_DISABLE_INLINING | COR_PRF_DISABLE_OPTIMIZATIONS | COR_PRF_ENABLE_OBJECT_ALLOCATED | COR_PRF_MONITOR_CLR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_USE_PROFILE_IMAGES | COR_PRF_DISABLE_ALL_NGEN_IMAGES, // MONITOR_IMMUTABLE represents all flags that may only be set during initialization. // Trying to change any of these flags elsewhere will result in a // failed HRESULT. COR_PRF_MONITOR_IMMUTABLE = COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_REMOTING | COR_PRF_MONITOR_REMOTING_COOKIE | COR_PRF_MONITOR_REMOTING_ASYNC | COR_PRF_ENABLE_INPROC_DEBUGGING | COR_PRF_ENABLE_JIT_MAPS | COR_PRF_DISABLE_OPTIMIZATIONS | COR_PRF_DISABLE_INLINING | COR_PRF_ENABLE_OBJECT_ALLOCATED | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO | COR_PRF_USE_PROFILE_IMAGES | COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST | COR_PRF_DISABLE_ALL_NGEN_IMAGES } COR_PRF_MONITOR; /* * Additional flags the profiler can specify via SetEventMask2 when loading */ typedef enum { COR_PRF_HIGH_MONITOR_NONE = 0x00000000, // CORECLR DEPRECATION WARNING: This flag is no longer checked by the runtime COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES = 0x00000001, COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x00000002, COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS = 0x00000004, COR_PRF_HIGH_DISABLE_TIERED_COMPILATION = 0x00000008, COR_PRF_HIGH_BASIC_GC = 0x00000010, // Enables the MovedReferences/MovedReferences2 callback for compacting GCs only. COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS = 0x00000020, COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0, // Enables the large object allocation monitoring according to the LOH threshold. COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x00000040, COR_PRF_HIGH_MONITOR_EVENT_PIPE = 0x00000080, // Enables the pinned object allocation monitoring. COR_PRF_HIGH_MONITOR_PINNEDOBJECT_ALLOCATED = 0x00000100, COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | COR_PRF_HIGH_BASIC_GC | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED | COR_PRF_HIGH_MONITOR_EVENT_PIPE, COR_PRF_HIGH_ALLOWABLE_NOTIFICATION_PROFILER = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS | COR_PRF_HIGH_DISABLE_TIERED_COMPILATION | COR_PRF_HIGH_BASIC_GC | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED | COR_PRF_HIGH_MONITOR_EVENT_PIPE, // MONITOR_IMMUTABLE represents all flags that may only be set during initialization. // Trying to change any of these flags elsewhere will result in a // failed HRESULT. COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION, } COR_PRF_HIGH_MONITOR; /* * COR_PRF_MISC contains miscellaneous constant ID's used for special * purposes. */ typedef enum { // PROFILER_PARENT_UNKNOWN is the AssemblyID used by GetModuleInfo // when a module has not yet been attached to an assembly. PROFILER_PARENT_UNKNOWN = 0xFFFFFFFD, // PROFILER_GLOBAL_CLASS is a ClassID used for globals that belong to no class PROFILER_GLOBAL_CLASS = 0xFFFFFFFE, // PROFILER_GLOBAL_MODULE is a ModuleID used for globals that belong // to no module in particular PROFILER_GLOBAL_MODULE = 0xFFFFFFFF } COR_PRF_MISC; /* * COR_PRF_JIT_CACHE contains values used to express the result of a * cached function search. Note that FOUND is 0, and thus this is not truly * a boolean. */ typedef enum { COR_PRF_CACHED_FUNCTION_FOUND, COR_PRF_CACHED_FUNCTION_NOT_FOUND } COR_PRF_JIT_CACHE; /* * COR_PRF_TRANSITION_REASON contains values used to describe * the reason for a ManagedToUnmanaged or UnmanagedToManagedTransition * callback. */ typedef enum { COR_PRF_TRANSITION_CALL, COR_PRF_TRANSITION_RETURN } COR_PRF_TRANSITION_REASON; /* * COR_PRF_SUSPEND_REASON contains values used to describe the * reason for suspending the runtime. See the RuntimeSuspension* * callbacks for detailed descriptions of each. */ typedef enum { COR_PRF_SUSPEND_OTHER = 0, COR_PRF_SUSPEND_FOR_GC = 1, COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN = 2, COR_PRF_SUSPEND_FOR_CODE_PITCHING = 3, COR_PRF_SUSPEND_FOR_SHUTDOWN = 4, COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER = 6, COR_PRF_SUSPEND_FOR_GC_PREP = 7, COR_PRF_SUSPEND_FOR_REJIT = 8, COR_PRF_SUSPEND_FOR_PROFILER = 9, } COR_PRF_SUSPEND_REASON; /* * COR_PRF_RUNTIME_TYPE contains values used to indicate the * type of runtime. */ typedef enum { COR_PRF_DESKTOP_CLR = 0x1, COR_PRF_CORE_CLR = 0x2, } COR_PRF_RUNTIME_TYPE; /* * COR_PRF_REJIT_FLAGS contains values used to control the behavior of * RequestReJITWithInliners. */ typedef enum { // ReJITted methods will be prevented from being inlined COR_PRF_REJIT_BLOCK_INLINING = 0x1, // This flag controls whether the runtime will call GetReJITParameters // on methods that are ReJITted because they inline a method that was requested // for ReJIT COR_PRF_REJIT_INLINING_CALLBACKS = 0x2 } COR_PRF_REJIT_FLAGS; typedef UINT_PTR EVENTPIPE_PROVIDER; typedef UINT_PTR EVENTPIPE_EVENT; typedef UINT64 EVENTPIPE_SESSION; typedef enum { COR_PRF_EVENTPIPE_OBJECT = 1, // Instance that isn't a value COR_PRF_EVENTPIPE_BOOLEAN = 3, // Boolean COR_PRF_EVENTPIPE_CHAR = 4, // Unicode character COR_PRF_EVENTPIPE_SBYTE = 5, // Signed 8-bit integer COR_PRF_EVENTPIPE_BYTE = 6, // Unsigned 8-bit integer COR_PRF_EVENTPIPE_INT16 = 7, // Signed 16-bit integer COR_PRF_EVENTPIPE_UINT16 = 8, // Unsigned 16-bit integer COR_PRF_EVENTPIPE_INT32 = 9, // Signed 32-bit integer COR_PRF_EVENTPIPE_UINT32 = 10, // Unsigned 32-bit integer COR_PRF_EVENTPIPE_INT64 = 11, // Signed 64-bit integer COR_PRF_EVENTPIPE_UINT64 = 12, // Unsigned 64-bit integer COR_PRF_EVENTPIPE_SINGLE = 13, // IEEE 32-bit float COR_PRF_EVENTPIPE_DOUBLE = 14, // IEEE 64-bit double COR_PRF_EVENTPIPE_DECIMAL = 15, // Decimal COR_PRF_EVENTPIPE_DATETIME = 16, // DateTime COR_PRF_EVENTPIPE_GUID = 17, // Guid COR_PRF_EVENTPIPE_STRING = 18, // Unicode character string COR_PRF_EVENTPIPE_ARRAY = 19, // Arbitrary length array } COR_PRF_EVENTPIPE_PARAM_TYPE; typedef enum { COR_PRF_EVENTPIPE_LOGALWAYS = 0, COR_PRF_EVENTPIPE_CRITICAL = 1, COR_PRF_EVENTPIPE_ERROR = 2, COR_PRF_EVENTPIPE_WARNING = 3, COR_PRF_EVENTPIPE_INFORMATIONAL = 4, COR_PRF_EVENTPIPE_VERBOSE = 5 } COR_PRF_EVENTPIPE_LEVEL; typedef struct { const WCHAR* providerName; UINT64 keywords; UINT32 loggingLevel; // filterData expects a semicolon delimited string that defines key value pairs // such as "key1=value1;key2=value2;". Quotes can be used to escape the '=' and ';' // characters. These key value pairs will be passed in the enable callback to event // providers const WCHAR* filterData; } COR_PRF_EVENTPIPE_PROVIDER_CONFIG; typedef struct { UINT32 type; // Used if type == ArrayType UINT32 elementType; const WCHAR *name; } COR_PRF_EVENTPIPE_PARAM_DESC; typedef struct { UINT64 ptr; UINT32 size; UINT32 reserved; } COR_PRF_EVENT_DATA; typedef enum _COR_PRF_HANDLE_TYPE { COR_PRF_HANDLE_TYPE_WEAK = 0x1, COR_PRF_HANDLE_TYPE_STRONG = 0x2, COR_PRF_HANDLE_TYPE_PINNED = 0x3, } COR_PRF_HANDLE_TYPE; typedef void** ObjectHandleID; /* -------------------------------------------------------------------------- * * Forward declarations * -------------------------------------------------------------------------- */ interface ICorProfilerCallback; interface ICorProfilerCallback2; interface ICorProfilerCallback3; interface ICorProfilerCallback4; interface ICorProfilerInfo; interface ICorProfilerInfo2; interface ICorProfilerInfo3; interface ICorProfilerInfo4; interface ICorProfilerObjectEnum; interface ICorProfilerFunctionEnum; interface ICorProfilerModuleEnum; interface ICorProfilerThreadEnum; interface ICorProfilerMethodEnum; interface IMethodMalloc; interface ICorProfilerFunctionControl; interface ICorProfilerAssemblyReferenceProvider; /* -------------------------------------------------------------------------- * * User Callback interface * -------------------------------------------------------------------------- */ /* * The ICorProfilerCallback interface is used by the CLR to notify a * code profiler when events have occurred that the code profiler has registered * an in interest in receiving. This is the primary callback interface through * which the CLR communicates with the code profiler. A code profiler * must register this callback interface in the Win32 registry. This object has * several methods that receive notification from the runtime when an event is * about to occur in an executing runtime process. * * The methods implemented on this interface return S_OK on success, or E_FAIL * on failure. */ [ object, uuid(176FBED1-A55C-4796-98CA-A9DA0EF883E7), pointer_default(unique), local ] interface ICorProfilerCallback : IUnknown { /* * * STARTUP/SHUTDOWN EVENTS * */ /* * The CLR calls Initialize to setup the code profiler * whenever a new CLR application is started. The call provides * an IUnknown interface pointer that should be QI'd for an ICorProfilerInfo * interface pointer. * * NOTE: this is the only opportunity to enable callbacks that are a part * of COR_PRF_MONITOR_IMMUTABLE, since they can no longer be changed after * returning from this function. This is done through SetEventMask on the * ICorProfilerInfo object. */ HRESULT Initialize( [in] IUnknown *pICorProfilerInfoUnk); /* * The CLR calls Shutdown to notify the code profiler that * the application is exiting. This is the profiler's last opportunity to * safely call functions on the ICorProfilerInfo interface. After returning * from this function the runtime will proceed to unravel its internal data * structures and any calls to ICorProfilerInfo are undefined in their * behaviour. * * NOTE: Certain IMMUTABLE events may still occur after Shutdown. * * NOTE: Shutdown will only fire where the managed application that is being * profiled was started running managed code (i.e., the initial frame on the * process' stack is managed). If the application being profiled started * life as unmanaged code, which later 'jumped into' managed code (thereby * creating an instance of the CLR), then Shutdown will not fire. In these * cases, the profiler should include a DllMain routine in their library that * uses Win32's DLL_PROCESS_DETACH call to free any resources and perform tidy-up * processing of its data (flush traces to disk, etc) * * NOTE: The profiler must in general cope with unexpected shutdowns, such as * when the process is "killed" by Win32's TerminateProcess. * * NOTE: Sometimes the CLR will violently kill certain managed threads * (background threads) without delivering orderly destruction messages for them. */ HRESULT Shutdown(); /* * * APPLICATION DOMAIN EVENTS * */ /* * Called when an application domain creation has begun and ended. * The ID is not valid for any information request until the Finished * event is called. * * Some parts of app domain loading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of app domain creation succeeded. */ HRESULT AppDomainCreationStarted( [in] AppDomainID appDomainId); HRESULT AppDomainCreationFinished( [in] AppDomainID appDomainId, [in] HRESULT hrStatus); /* * Called before and after an app domain is unloaded from a process. * The ID is no longer valid after the Started event returns. * * Some parts of app domain unloading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of app domain unloading succeeded. */ HRESULT AppDomainShutdownStarted( [in] AppDomainID appDomainId); HRESULT AppDomainShutdownFinished( [in] AppDomainID appDomainId, [in] HRESULT hrStatus); /* * * ASSEMBLY EVENTS * */ /* * Called when an Assembly load has begun and ended. The ID is not valid * for any information request until the Finished event is called. * * Some parts of assembly loading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of assembly loading succeeded. */ HRESULT AssemblyLoadStarted( [in] AssemblyID assemblyId); HRESULT AssemblyLoadFinished( [in] AssemblyID assemblyId, [in] HRESULT hrStatus); /* * Called before and after an assembly is unloaded. * The ID is no longer valid after the Started event returns. * * Some parts of assembly unloading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of assembly unloading succeeded. */ HRESULT AssemblyUnloadStarted( [in] AssemblyID assemblyId); HRESULT AssemblyUnloadFinished( [in] AssemblyID assemblyId, [in] HRESULT hrStatus); /* * * MODULE EVENTS * */ /* * Called when a module load has begun and ended. The ID is not valid * for any information request until the Finished event is called. * * Some parts of module loading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of module loading succeeded. * * Note that when a module load is reported as finished this indicates * that the load has completed but it has not yet returned to the caller. * This is the opportunity for the profiler to note that other notifications regarding * this module may start coming afterwards however internal safeguards * protecting the runtime from recursive loading are still present and so it is * a bad time to begin inquiries on this module. The notification is informational * only. * * Note: ModuleLoadFinished is a reasonable time to interrogate MetaData via API's * like GetModuleMetadata, however APIs that create (e.g. ClassID's and FunctionID's) * are not safe to use here. Profiler writers are advised to stay in the universe of * tokens. * */ HRESULT ModuleLoadStarted( [in] ModuleID moduleId); HRESULT ModuleLoadFinished( [in] ModuleID moduleId, [in] HRESULT hrStatus); /* * Called before and after a module is unloaded. * The ID is no longer valid after the Started event returns. * * Some parts of module unloading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of module unloading succeeded. */ HRESULT ModuleUnloadStarted( [in] ModuleID moduleId); HRESULT ModuleUnloadFinished( [in] ModuleID moduleId, [in] HRESULT hrStatus); /* * A module can get loaded through legacy means (ie: IAT or LoadLibrary) or * through a metadata reference. The CLR loader therefore has many code * paths for determining what assembly a module lives in. It is therefore * possible that after a ModuleLoadFinished event, the module does not * know what assembly it is in and getting the parent AssemblyID is not possible. * This event is fired when the module is officially attached to its parent * assembly. Calling GetModuleInfo after this function is called will return the * proper parent assembly. */ HRESULT ModuleAttachedToAssembly( [in] ModuleID moduleId, [in] AssemblyID AssemblyId); /* * * CLASS EVENTS * */ /* * Called when a class load has begun and ended. The ID is not valid * for any information request until the Finished event is called. * * Some parts of class loading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of class loading succeeded. * * Note that when a class load is reported as finished this indicates * that the load has completed but it has not yet returned to the caller. * This is the opportunity for the profiler to note that other notifications regarding * this class may start coming afterwards however internal safeguards * protecting the runtime from recursive loading are still present and so it is * a bad time to begin inquiries on this class. The notification is informational * only. * */ HRESULT ClassLoadStarted( [in] ClassID classId); HRESULT ClassLoadFinished( [in] ClassID classId, [in] HRESULT hrStatus); /* * Called before and after a class is unloaded. * The ID is no longer valid after the Started event returns. * * Some parts of class unloading may take place lazily at some time * after the Finished callback. Therefore, while a failure HRESULT in * hrStatus definitely indicates a failure, a success HRESULT only indicates * that the first part of class unloading succeeded. */ HRESULT ClassUnloadStarted( [in] ClassID classId); HRESULT ClassUnloadFinished( [in] ClassID classId, [in] HRESULT hrStatus); /* * * JIT EVENTS * */ /* * The CLR calls FunctionUnloadStarted to notify the code * profiler that a function is being unloaded. After returning from this * call, the FunctionID is no longer valid. */ HRESULT FunctionUnloadStarted( [in] FunctionID functionId); /* * The CLR calls JITCompilationStarted to notify the code * profiler that the JIT compiler is starting to compile a function. * * The fIsSafeToBlock argument tells the profiler whether or not blocking * will affect the operation of the runtime. If true, blocking may cause * the runtime to wait for the calling thread to return from this callback. * Although this will not harm the runtime, it will skew the profiling * results. * * NOTE: It is possible to receive more than one JITCompilationStarted/ * JITCompilationFinished pair for each method. This is because of how * the runtime handles class constructors: method A starts to be JIT'd, * then realizes that the class ctor for class B needs to be run, so * JIT's it and runs it, and while it's running makes a call to original * method A, which causes it to be JIT'd again, and causes the original * (incomplete) JIT'ing of A to be aborted. However, both attempts to * JIT A are reported with JIT compilation events. If the profiler is * going to replace IL code for this method with SetILFunctionBody, then * it must do so for both JITCompilationStarted events, but may use the * same IL block for both. * * NOTE: A profiler should be tolerant of the sequence of JIT callbacks * received in cases where two threads are simultaneously calling a * method. For example, thread A receives JITCompilationStarted. * But before thread A receives JITCompilationFinished, thread B * receives FunctionEnter with the functionId from thread A's * JITCompilationStarted callback. It may appear that functionId should * not yet be valid because JITCompilationFinished had not yet been * received. But it is indeed valid in such a case. */ HRESULT JITCompilationStarted( [in] FunctionID functionId, [in] BOOL fIsSafeToBlock); /* * The CLR calls JITCompilationFinished to notify the code * profiler that the JIT compiler has finished compiling a function. * * The fIsSafeToBlock argument tells the profiler whether or not blocking * will affect the operation of the runtime. If true, blocking may cause * the runtime to wait for the calling thread to return from this callback. * Although this will not harm the runtime, it will skew the profiling * results. * * The FunctionID is now valid in ICorProfilerInfo APIs. * * The hrStatus provides the success or failure of the operation */ HRESULT JITCompilationFinished( [in] FunctionID functionId, [in] HRESULT hrStatus, [in] BOOL fIsSafeToBlock); /* * V2 MIGRATION WARNING: DOES NOT ALWAYS OCCUR * The JITCachedFunctionSearchStarted/Finished callbacks * will now occur only for some functions in regular NGEN images; * only profiler-optimized NGEN images will generate callbacks for * all functions in the image. Profilers which do not use these callbacks * to force a function to be JIT-compiled should move to using a lazy * strategy for gathering function information. * * This notifies the profiler when a search for a prejitted function is * starting. * * functionId: the function for which the search is being performed. * bUseCachedFunction: if true, the EE uses the cached function (if applicable) * if false, the EE jits the function instead of * using a pre-jitted version. * * NOTE: Profilers should be tolerant of cases where multiple threads of * a profiled app are calling the same method simultaneously. For example, * thread A may receive JITCachedFunctionSearchStarted (and the * profiler sets *pbUseCachedFunction=FALSE to force a JIT), thread A * then receives JITCompilationStarted/JITCompilationFinished, then * thread B receives another JITCachedFunctionSearchStarted for the same * method. It might appear odd to receive this final callback, since the * profiler already stated its intention to JIT the method. But this is * occurring because the CLR in thread B decided to send this callback * before thread A responded to JITCachedFunctionSearchStarted * with *pbUseCachedFunction=FALSE, and the thread B callback * hadn't actually been sent until now due how the threads * happened to be scheduled. In such cases where the profiler * receives duplicate JITCachedFunctionSearchStarted callbacks for * the same functionId, the profiler should be certain to set * *pbUseCachedFunction to the same value from this callback * when it is called multiple times with the same functionId. */ HRESULT JITCachedFunctionSearchStarted( [in] FunctionID functionId, [out] BOOL *pbUseCachedFunction); /* * V2 MIGRATION WARNING: DOES NOT ALWAYS OCCUR * The JITCachedFunctionSearchStarted/Finished callbacks * will now occur only for some functions in regular NGEN images; * only profiler-optimized NGEN images will generate callbacks for * all functions in the image. Profilers which do not use these callbacks * to force a function to be JIT-compiled should move to using a lazy * strategy for gathering function information. * * This notifies the profiler when a search for a cached function has been * performed. * * functionId: the function for which the search has been performed. * result: the result of the search. There are two possible results: * COR_PRF_CACHED_FUNCTION_FOUND * COR_PRF_CACHED_FUNCTION_NOT_FOUND * */ HRESULT JITCachedFunctionSearchFinished( [in] FunctionID functionId, [in] COR_PRF_JIT_CACHE result); /* * The CLR calls JITFunctionPitched to notify the profiler * that a jitted function was removed from memory. If the pitched * function is called in the future, the profiler will receive new * JIT compilation events as it is re-jitted. * * Currently the CLR JIT does not pitch functions, so this callback * will not be received. * * NOTE: the FunctionID is not valid until it is re-jitted. When it is * re-jitted, it will use the same FunctionID value. */ HRESULT JITFunctionPitched( [in] FunctionID functionId); /* * The CLR calls JITInlining to notify the profiler that the jitter * is about to inline calleeId into callerId. Set pfShouldInline to FALSE * to prevent the callee from being inlined into the caller, and set to * TRUE to allow the inline to occur. * * NOTE: Inlined functions do not provide Enter/Leave events, so if you desire * an accurate callgraph, you should set FALSE. Be aware that * setting FALSE will affect performance, since inlining typically * increases speed and reduces separate jitting events for the inlined * method. * * NOTE: It is also possible to globally disable inlining by setting the * COR_PRF_DISABLE_INLINING flag. */ HRESULT JITInlining( [in] FunctionID callerId, [in] FunctionID calleeId, [out] BOOL *pfShouldInline); /* * * THREAD EVENTS * */ /* * The CLR calls ThreadCreated to notify the code profiler * that a thread has been created. The ThreadID is valid immediately. */ HRESULT ThreadCreated( [in] ThreadID threadId); /* * The CLR calls ThreadDestroyed to notify the code profiler * that a thread has been destroyed. The ThreadID is no longer valid * at the time of this call. */ HRESULT ThreadDestroyed( [in] ThreadID threadId); /* * The CLR calls ThreadAssignedToOSThread to tell the profiler * that a managed thread is being implemented via a particular OS thread. * This callback exists so that the profiler can maintain an accurate * OS to Managed thread mapping across fibres. */ HRESULT ThreadAssignedToOSThread( [in] ThreadID managedThreadId, [in] DWORD osThreadId); /* * * REMOTING EVENTS * */ // // Client-side events // /* * NOTE: each of the following pairs of callbacks will occur on the same * thread * RemotingClientInvocationStarted & RemotingClientSendingMessage * RemotingClientReceivingReply & RemotingClientInvocationFinished * RemotingServerInvocationReturned & RemotingServerSendingReply * * There are a few issues with the remoting callbacks that should be outlined. * First, remoting function execution is not reflected by the profiler API, so * the notifications for functions that are called from the client and executed * to the server are not properly received. The actual invocation happens via a * proxy object. That creates the illusion to the profiler that certain * functions get jit-compiled but they never get used. Second, the profiler does * not receive accurate notifications for asynchronous remoting events. */ /* * The CLR calls RemotingClientInvocationStarted to notify the profiler that * a remoting call has begun. This event is the same for synchronous and * asynchronous calls. */ HRESULT RemotingClientInvocationStarted(); /* * The CLR calls RemotingClientSendingMessage to notify the profiler that * a remoting call is requiring the caller to send an invocation request through * a remoting channel. * * pCookie - if remoting GUID cookies are active, this value will correspond with the * the value provided in RemotingServerReceivingMessage, if the channel * succeeds in transmitting the message, and if GUID cookies are active on * the server-side process. This allows easy pairing of remoting calls, * and the creation of a logical call stack. * fIsAsync - is true if the call is asynchronous. */ HRESULT RemotingClientSendingMessage( [in] GUID *pCookie, [in] BOOL fIsAsync); /* * The CLR calls RemotingClientReceivingReply to notify the profiler that * the server-side portion of a remoting call has completed and that the client is * now receiving and about to process the reply. * * pCookie - if remoting GUID cookies are active, this value will correspond with the * the value provided in RemotingServerSendingReply, if the channel * succeeds in transmitting the message, and if GUID cookies are active on * the server-side process. This allows easy pairing of remoting calls. * fIsAsync - is true if the call is asynchronous. */ HRESULT RemotingClientReceivingReply( [in] GUID *pCookie, [in] BOOL fIsAsync); /* * The CLR calls RemotingClientInvocationFinished to notify the profiler that * a remoting invocation has run to completion on the client side. If the call was * synchronous, this means that it has also run to completion on the server side. If * the call was asynchronous, a reply may still be expected when the call is handled. * If the call is asynchronous, and a reply is expected, then the reply will occur in * the form of a call to RemotingClientReceivingReply and an additional call to * RemotingClientInvocationFinished to indicate the required secondary processing of * an asynchronous call. */ HRESULT RemotingClientInvocationFinished(); // // Server-side events // /* * The CLR calls RemotingServerReceivingMessage to notify the profiler that * the process has received a remote method invocation (or activation) request. If * the message request is asynchronous, then the request may be serviced by any * arbitrary thread. * * pCookie - if remoting GUID cookies are active, this value will correspond with the * the value provided in RemotingClientSendingMessage, if the channel * succeeds in transmitting the message, and if GUID cookies are active on * the client-side process. This allows easy pairing of remoting calls. * fIsAsync - is true if the call is asynchronous. */ HRESULT RemotingServerReceivingMessage( [in] GUID *pCookie, [in] BOOL fIsAsync); /* * The CLR calls RemotingServerInvocationStarted to notify the profiler that * the process is invoking a method due to a remote method invocation request. */ HRESULT RemotingServerInvocationStarted(); /* * The CLR calls RemotingServerInvocationReturned to notify the profiler that * the process has finished invoking a method due to a remote method invocation request. */ HRESULT RemotingServerInvocationReturned(); /* * The CLR calls RemotingServerSendingReply to notify the profiler that * the process has finished processing a remote method invocation request and is * about to transmit the reply through a channel. * * pCookie - if remoting GUID cookies are active, this value will correspond with the * the value provided in RemotingClientReceivingReply, if the channel * succeeds in transmitting the message, and if GUID cookies are active on * the client-side process. This allows easy pairing of remoting calls. * fIsAsync - is true if the call is asynchronous. */ HRESULT RemotingServerSendingReply( [in] GUID *pCookie, [in] BOOL fIsAsync); /* * * TRANSITION EVENTS * */ /* * The CLR calls UnmanagedToManagedTransition to notify the * code profiler that a transition from unmanaged code to managed code has * occurred. functionId is always the ID of the callee, and reason * indicates whether the transition was due to a call into managed code from * unmanaged, or a return from an unmanaged function called by a managed one. * * Note that if the reason is COR_PRF_TRANSITION_RETURN and the functionId is * non-NULL, then the functionId is that of the unmanaged function, and will * never have been jitted. Unmanaged functions still have some basic * information associated with them, such as a name, and some metadata. * * Note that if the reason is COR_PRF_TRANSITION_RETURN and the callee was * a PInvoke call indirect, then the runtime does not know the destination * of the call and functionId will be NULL. * * Note that if the reason is COR_PRF_TRANSITION_CALL then it may be possible * that the callee has not yet been JIT-compiled. */ HRESULT UnmanagedToManagedTransition( [in] FunctionID functionId, [in] COR_PRF_TRANSITION_REASON reason); /* * The CLR calls ManagedToUnmanagedTransition to notify the * code profiler that a transition from managed code to unmanaged code has * occurred. functionId is always the ID of the callee, and reason * indicates whether the transition was due to a call into unmanaged code from * managed, or a return from an managed function called by an unmanaged one. * * Note that if the reason is COR_PRF_TRANSITION_CALL, then the functionId * is that of the unmanaged function, and will never have been jitted. * Unmanaged functions still have some basic information associated with * them, such as a name, and some metadata. * * Note that if the reason is COR_PRF_TRANSITION_CALL and the callee is * a PInvoke call indirect, then the runtime does not know the destination * of the call and functionId will be NULL. */ HRESULT ManagedToUnmanagedTransition( [in] FunctionID functionId, [in] COR_PRF_TRANSITION_REASON reason); /* * * RUNTIME SUSPENSION EVENTS * */ /* * The CLR calls RuntimeSuspendStarted to notify the code profiler * that the runtime is about to suspend all of the runtime threads. * All runtime threads that are in unmanaged code are permitted to continue * running until they try to re-enter the runtime, at which point they will * also suspend until the runtime resumes. This also applies to new threads * that enter the runtime. All threads within the runtime are either * suspended immediately if they are in interruptible code, or asked to * suspend when they do reach interruptible code. * * suspendReason make be any of the following values: * COR_PRF_SUSPEND_FOR_GC * the runtime is suspending to service a GC request. The GC-related * callbacks will occur between the RuntimeSuspendFinished and * RuntimeResumeStarted events. * COR_PRF_SUSPEND_FOR_CODE_PITCHING * the runtime is suspending so that code pitching may occur. This * only occurs when the EJit is active with code pitching enabled. * Code pitching callbacks will occur between the * RuntimeSuspendFinished and RuntimeResumeStarted events. * COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN * the runtime is suspending so that an AppDomain can be shut down. * While the runtime is suspended, the runtime will determine which * threads are in the AppDomain that is being shut down, set them to * abort when they resume, and then resumes the runtime. There are * no AppDomain-specific callbacks during this suspension. * COR_PRF_SUSPEND_FOR_SHUTDOWN * the runtime is shutting down, and it must suspend all threads to * complete the operation. * COR_PRF_SUSPEND_FOR_GC_PREP * the runtime is preparing for a GC. * COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER * the runtime is suspending for in-process debugging. * COR_PRF_SUSPEND_FOR_PROFILER * the runtime is suspending because of ICorProfilerInfo10::SuspendRuntime. * COR_PRF_SUSPEND_OTHER * the runtime is suspending for a reason other than those above. */ HRESULT RuntimeSuspendStarted( [in] COR_PRF_SUSPEND_REASON suspendReason); /* * The CLR calls RuntimeSuspendFinished to notify the code profiler * that the runtime has suspended all threads needed for a runtime * suspension. Note that not all runtime threads are required to be * suspended, as described in the comment for RuntimeSuspendStarted. * * NOTE: It is guaranteed that this event will occur on the same ThreadID * as RuntimeSuspendStarted occurred on. */ HRESULT RuntimeSuspendFinished(); /* * The CLR calls RuntimeSuspendAborted to notify the code profiler * that the runtime is aborting the runtime suspension that was occurring. * This may occur if two threads simultaneously attempt to suspend the * runtime. * * NOTE: It is guaranteed that this event will occur on the same ThreadID * as the RuntimeSuspendStarted occurred on, and that only one of * RuntimeSuspendFinished and RuntimeSuspendAborted may occur on a single * thread following a RuntimeSuspendStarted event. */ HRESULT RuntimeSuspendAborted(); /* * The CLR calls RuntimeResumeStarted to notify the code profiler * that the runtime is about to resume all of the runtime threads. */ HRESULT RuntimeResumeStarted(); /* * The CLR calls RuntimeResumeFinished to notify the code profiler * that the runtime has finished resuming all of it's threads and is now * back in normal operation. * * NOTE: It is *NOT* guaranteed that this event will occur on the same * ThreadID as the RuntimeSuspendStarted occurred on, but is guaranteed * to occur on the same ThreadID as the RuntimeResumeStarted occurred on. */ HRESULT RuntimeResumeFinished(); /* * The CLR calls RuntimeThreadSuspended to notify the code profiler * that a particular thread has been suspended. * * This notification may occur any time between the RuntimeSuspendStarted * and the associated RuntimeResumeStarted. Notifications that occur * between RuntimeSuspendFinished and RuntimeResumeStarted are for * threads that had been running in unmanaged code and were suspended * upon entry to the runtime. */ HRESULT RuntimeThreadSuspended( [in] ThreadID threadId); /* * The CLR calls RuntimeThreadResumed to notify the code profiler * that a particular thread has been resumed after being suspended due to * a runtime suspension. */ HRESULT RuntimeThreadResumed( [in] ThreadID threadId); /* * * GC EVENTS * * NOTE: All of these callbacks (except ObjectAllocated) are made while the * runtime is suspended, so none of the ObjectID values can change until * the runtime resumes and another GC occurs. * * NOTE: The profiler will receive GC-related events (except ObjectAllocated) * when the profiler has been suspended for COR_PRF_SUSPEND_FOR_GC *except* * for one special case. When the runtime is shutting down, there is a * stage where it is suspended for COR_PRF_SUSPEND_FOR_SHUTDOWN reason and * is never resumed. But after this suspension a garbage collection may * occur without a COR_PRF_SUSPEND_FOR_GC suspension notification, and * the profiler will thus receive GC-related callbacks. * * NOTE: All of these callbacks (except ObjectAllocated) may be called more than * once during the same GC. These calls should be considered multiple parts of * one long report; the profiler should simply aggregate the information provided * in all of them. */ /* * The CLR calls MovedReferences with information about * object references that moved as a result of garbage collection. * * cMovedObjectIDRanges is a count of the number of ObjectID ranges that * were moved. * oldObjectIDRangeStart is an array of elements, each of which is the start * value of a range of ObjectID values before being moved. * newObjectIDRangeStart is an array of elements, each of which is the start * value of a range of ObjectID values after being moved. * cObjectIDRangeLength is an array of elements, each of which states the * size of the moved ObjectID value range. * * The last three arguments of this function are parallel arrays. * * In other words, if an ObjectID value lies within the range * oldObjectIDRangeStart[i] <= ObjectID < oldObjectIDRangeStart[i] + cObjectIDRangeLength[i] * for 0 <= i < cMovedObjectIDRanges, then the ObjectID value has changed to * ObjectID - oldObjectIDRangeStart[i] + newObjectIDRangeStart[i] * * NOTE: None of the objectIDs returned by MovedReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers * should not attempt to inspect objects during a MovedReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. * * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as UINT32_MAX * on 64-bit platforms. Use ICorProfilerCallback4::MovedReferences2 instead. */ HRESULT MovedReferences( [in] ULONG cMovedObjectIDRanges, [in, size_is(cMovedObjectIDRanges)] ObjectID oldObjectIDRangeStart[] , [in, size_is(cMovedObjectIDRanges)] ObjectID newObjectIDRangeStart[] , [in, size_is(cMovedObjectIDRanges)] ULONG cObjectIDRangeLength[] ); /* * The CLR calls ObjectAllocated to notify the code profiler * an object was allocated on the heap. This notification does not fire * for allocations from the stack, nor from unmanaged memory. * * It is possible to receive a classId that corresponds to a regular class * that has not been loaded yet. The profiler will receive a class load * callback for that class immediately after the object creation callback. */ HRESULT ObjectAllocated( [in] ObjectID objectId, [in] ClassID classId); /* * The CLR calls ObjectsAllocatedByClass to notify the code * profiler about the number of objects of a particular class that were * allocated since the previous garbage collection. The classes and the * counts are passed in parallel arrays. (Classes for which no instances * have been allocated since the previous GC are omitted entirely.) * * NOTE: This callback will not report objects allocated in the large * object heap. * * NOTE: The numbers here are only estimates. Use ObjectAllocated for * exact counts. */ HRESULT ObjectsAllocatedByClass( [in] ULONG cClassCount, [in, size_is(cClassCount)] ClassID classIds[] , [in, size_is(cClassCount)] ULONG cObjects[] ); /* * The CLR calls ObjectReferences to provide information * about objects in memory referenced by a given object. This function * is called for each object remaining in the GC heap after a collection * has completed. If the profiler returns an error from this callback, * the profiling services will discontinue invoking this callback until the * next GC. This callback can be used in conjunction with the * RootReferences callback to create a complete object reference graph for * the runtime. * * NOTE: The CLR will ensure that each object reference is reported only * once by this function. * * NOTE: None of the objectIDs returned by ObjectReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers * should not attempt to inspect objects during an ObjectReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. */ HRESULT ObjectReferences( [in] ObjectID objectId, [in] ClassID classId, [in] ULONG cObjectRefs, [in, size_is(cObjectRefs)] ObjectID objectRefIds[] ); /* * The CLR calls RootReferences with information about root * references after a garbage collection has occurred. Static object * references and references to objects on a stack are co-mingled in the * arrays. * * NOTE: It is possible to get NULL ObjectIDs in the RootReferences callback. * For example, all object references declared on the stack are treated as * roots by the GC, and will always be reported. * * NOTE: None of the objectIDs returned by RootReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers * should not attempt to inspect objects during a RootReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. */ HRESULT RootReferences( [in] ULONG cRootRefs, [in, size_is(cRootRefs)] ObjectID rootRefIds[] ); /* * * EXCEPTION EVENTS * */ // // Exception creation // /* * The CLR calls ExceptionThrown to notify the code * profiler that an exception has been thrown. * * NOTE: This function is only called if the exception reaches * managed code. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionThrown( [in] ObjectID thrownObjectId); // // Search phase // /* * The CLR calls ExceptionSearchFunctionEnter to notify the profiler * that the search phase of exception handling has entered a function. */ HRESULT ExceptionSearchFunctionEnter( [in] FunctionID functionId); /* * The CLR calls ExceptionSearchFunctionLeave to notify the profiler * that the search phase of exception handling has left a function. */ HRESULT ExceptionSearchFunctionLeave(); /* * The CLR will call ExceptionSearchFilterEnter just before excecuting * a user filter. The functionID is that of the function containing the filter. */ HRESULT ExceptionSearchFilterEnter( [in] FunctionID functionId); /* * The CLR will call ExceptionSearchFilterLeave immediately after * executing a user filter. */ HRESULT ExceptionSearchFilterLeave(); /* * The CLR will call ExceptionSearchCatcherFound when the search * phase of exception handling has located a handler for the exception that * was thrown. */ HRESULT ExceptionSearchCatcherFound( [in] FunctionID functionId); /* * DEPRECATED. It is the job of the unmanaged profiler to detect OS * handling of exceptions. */ HRESULT ExceptionOSHandlerEnter( [in] UINT_PTR __unused); /* * DEPRECATED. It is the job of the unmanaged profiler to detect OS * handling of exceptions. */ HRESULT ExceptionOSHandlerLeave( [in] UINT_PTR __unused); // // Unwind phase // /* * The CLR calls ExceptionUnwindFunctionEnter to notify the profiler * that the unwind phase of exception handling has entered a function. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionUnwindFunctionEnter( [in] FunctionID functionId); /* * The CLR calls ExceptionUnwindFunctionLeave to notify the profiler * that the unwind phase of exception handling has left a function. The * function instance and it's stack data has now been removed from the stack. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionUnwindFunctionLeave(); /* * The CLR calls ExceptionUnwindFinallyEnter to notify the profiler * that the unwind phase of exception is entering a finally clause contained * in the specified function. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionUnwindFinallyEnter( [in] FunctionID functionId); /* * The CLR calls ExceptionUnwindFinallyLeave to notify the profiler * that the unwind phase of exception is leaving a finally clause. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionUnwindFinallyLeave(); /* * The CLR calls this function just before passing control to * the appropriate catch block. Note that this is called only if the * catch point is in JIT'ed code. An exception that is caught in * unmanaged code, or in the internal code of the CLR will * not generate this notification. The ObjectID is passed again since * a GC could have moved the object since the ExceptionThrown * notification. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionCatcherEnter( [in] FunctionID functionId, [in] ObjectID objectId); /* * The CLR calls ExceptionCatcherLeave when the runtime leaves * the catcher's code. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. */ HRESULT ExceptionCatcherLeave(); /* * CLR<->COM interop vtable creation/destruction. */ /* * The CLR calls this function when an CLR<->COM interop vtable * for a particular IID and for a particular class has been created. * This provides the ClassID of the class for which this vtable has been * created, the IID it implements, the start of the vtable and how many * slots are in it. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. * * NOTE: It is possible to receive a NULL GUID if the interface is * internal only. */ HRESULT COMClassicVTableCreated( [in] ClassID wrappedClassId, [in] REFGUID implementedIID, [in] void *pVTable, [in] ULONG cSlots); /* * The CLR calls this function when a CLR<->COM interop vtable is * being destroyed. Provided are the ClassID, IID and vtable pointer for * the destroyed vtable. * * NOTE: The profiler should not block here, since the stack may not be in a * GC-friendly state and so preemptive GC cannot be enabled. If the * profiler blocks here and a GC is attempted, the runtime will block * until this callback returns. Also, the profiler may NOT call into * managed code or in any way cause a managed memory allocation. * * NOTE: It is possible to receive a NULL GUID if the interface is * internal only. * * NOTE: This callback is likely never to occur, since the destruction of * vtables occurs very close to Shutdown. */ HRESULT COMClassicVTableDestroyed( [in] ClassID wrappedClassId, [in] REFGUID implementedIID, [in] void *pVTable); /* * DEPRECATED. These callbacks are no longer delivered. */ HRESULT ExceptionCLRCatcherFound(); HRESULT ExceptionCLRCatcherExecute(); } /* * COR_PRF_GC_ROOT_KIND describes the kind of GC root exposed by * the RootReferences2 callback. */ typedef enum { COR_PRF_GC_ROOT_STACK = 1, // Variables on the stack COR_PRF_GC_ROOT_FINALIZER = 2, // Entry in the finalizer queue COR_PRF_GC_ROOT_HANDLE = 3, // GC Handle COR_PRF_GC_ROOT_OTHER = 0 //Misc. roots } COR_PRF_GC_ROOT_KIND; /* * COR_PRF_GC_ROOT_FLAGS describes properties of a GC root * exposed by the RootReferences callback. */ typedef enum { COR_PRF_GC_ROOT_PINNING = 0x1, // Prevents GC from moving the object COR_PRF_GC_ROOT_WEAKREF = 0x2, // Does not prevent collection COR_PRF_GC_ROOT_INTERIOR = 0x4, // Refers to a field of the object rather than the object itself COR_PRF_GC_ROOT_REFCOUNTED = 0x8, // Whether it prevents collection depends on a refcount - if not, // COR_PRF_GC_ROOT_WEAKREF will be set also } COR_PRF_GC_ROOT_FLAGS; /* * COR_PRF_FINALIZER_FLAGS is used by FinalizableObjectQueued to describe * the finalizer for the object. */ typedef enum { COR_PRF_FINALIZER_CRITICAL = 0x1 // Critical finalizer } COR_PRF_FINALIZER_FLAGS; /* * COR_PRF_GC_GENERATION contains the numbers used to represent each GC generation * in the GetGenerationBounds and GetObjectGeneration functions. */ typedef enum { COR_PRF_GC_GEN_0 = 0, COR_PRF_GC_GEN_1 = 1, COR_PRF_GC_GEN_2 = 2, COR_PRF_GC_LARGE_OBJECT_HEAP = 3, COR_PRF_GC_PINNED_OBJECT_HEAP= 4 } COR_PRF_GC_GENERATION; /* * COR_PRF_GC_GENERATION_RANGE describes a range of memory in the GetGenerationBounds and GetObjectGeneration functions. * Note that the rangeLength member is only guaranteed to be accurate if GetGenerationBounds or GetObjectGeneration are * called from a GarbageCollectionStarted or GarbageCollectionFinished notification */ typedef struct COR_PRF_GC_GENERATION_RANGE { COR_PRF_GC_GENERATION generation; // what generation the range of memory belongs to ObjectID rangeStart; // the start of the range UINT_PTR rangeLength; // the used length of the range UINT_PTR rangeLengthReserved; // the amount of memory reserved for the range (including rangeLength) } COR_PRF_GC_GENERATION_RANGE; /* * COR_PRF_CLAUSE_TYPE defines the various clause codes for the EX clauses */ typedef enum { COR_PRF_CLAUSE_NONE = 0, // not a real clause (only used in error cases) COR_PRF_CLAUSE_FILTER = 1, COR_PRF_CLAUSE_CATCH = 2, COR_PRF_CLAUSE_FINALLY = 3, } COR_PRF_CLAUSE_TYPE; /* * COR_PRF_EX_CLAUSE_INFO identifies a specific exception clause instance and its associated frame. * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used to get the * native address and frame information for the exception clause (catch/finally/filter) that is * about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) or has just * been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). */ typedef struct COR_PRF_EX_CLAUSE_INFO { COR_PRF_CLAUSE_TYPE clauseType; // the type of clause we just entered or left UINT_PTR programCounter; // the native entry point of the clause handler (e.g. EIP) UINT_PTR framePointer; // the logical frame pointer (e.g. EBP) for that clause handler UINT_PTR shadowStackPointer; // the shadow stack pointer (IA64 only, BSP) } COR_PRF_EX_CLAUSE_INFO; /* * COR_PRF_GC_REASON describes the reason for a given GC. */ typedef enum { COR_PRF_GC_INDUCED = 1, // Induced by GC.Collect COR_PRF_GC_OTHER = 0 // Anything else } COR_PRF_GC_REASON; /* * Bits from COR_PRF_MODULE_FLAGS are returned to the profiler in GetModuleInfo2's * pdwModuleFlags output parameter. Some combinations of 2 or more flags are possible, * though not all combinations are possible. */ typedef enum { // The module was loaded from disk COR_PRF_MODULE_DISK = 0x00000001, // The module had been generated via NGEN COR_PRF_MODULE_NGEN = 0x00000002, // The module was created via methods in the Reflection.Emit namespace COR_PRF_MODULE_DYNAMIC = 0x00000004, // The module's lifetime is managed by the garbage collector. COR_PRF_MODULE_COLLECTIBLE = 0x00000008, // The module contains no metadata and is used strictly as a resource. The managed // equivalent of this bit is the System.Reflection.Module.IsResource() method. COR_PRF_MODULE_RESOURCE = 0x00000010, // The module's layout in memory is flat, as opposed to mapped. For modules that have // this bit set, profilers that directly read information out of the PE header will // need to be careful when interpreting RVAs present in the PE header. COR_PRF_MODULE_FLAT_LAYOUT = 0x00000020, // The Windows Runtime content type flag is set in the metadata for this module's // assembly COR_PRF_MODULE_WINDOWS_RUNTIME = 0x00000040, } COR_PRF_MODULE_FLAGS; /* * The ICorProfilerCallback2 interface is used by the CLR to notify a * code profiler when events have occurred that the code profiler has registered * an in interest in receiving. These are new callbacks implemented in V2.0 * of the runtime. * * The methods implemented on this interface return S_OK on success, or E_FAIL * on failure. */ [ object, uuid(8A8CC829-CCF2-49fe-BBAE-0F022228071A), pointer_default(unique), local ] interface ICorProfilerCallback2 : ICorProfilerCallback { /* * * THREAD EVENTS * */ /* * The CLR calls ThreadNameChanged to notify the code profiler * that a thread's name has changed. * * name is not NULL terminated. * */ HRESULT ThreadNameChanged( [in] ThreadID threadId, [in] ULONG cchName, [in, annotation("_In_reads_opt_(cchName)")] WCHAR name[]); /* * * GARBAGE COLLECTION EVENTS * */ /* * The CLR calls GarbageCollectionStarted before beginning a * garbage collection. All GC callbacks pertaining to this * collection will occur between the GarbageCollectionStarted * callback and the corresponding GarbageCollectionFinished * callback. Corresponding GarbageCollectionStarted and * GarbageCollectionFinished callbacks need not occur on the same thread. * * cGenerations indicates the total number of entries in * the generationCollected array * generationCollected is an array of booleans, indexed * by COR_PRF_GC_GENERATIONS, indicating which * generations are being collected in this collection * reason indicates whether this GC was induced * by the application calling GC.Collect(). * * NOTE: It is safe to inspect objects in their original locations * during this callback. The GC will begin moving objects after * the profiler returns from this callback. Therefore, after * returning, the profiler should consider all ObjectIDs to be invalid * until it receives a GarbageCollectionFinished callback. */ HRESULT GarbageCollectionStarted( [in] int cGenerations, [in, size_is(cGenerations)] BOOL generationCollected[], [in] COR_PRF_GC_REASON reason); /* * The CLR calls SurvivingReferences with information about * object references that survived a garbage collection. * * Generally, the CLR calls SurvivingReferences for non-compacting garbage collections. * For compacting garbage collections, MovedReferences is called instead. * * The exception to this rule is that the CLR always calls SurvivingReferences for objects * in the large object heap, which is not compacted. * * Multiple calls to SurvivingReferences may be received during a particular * garbage collection, due to limited internal buffering, multiple threads reporting * in the case of server gc, and other reasons. * In the case of multiple calls, the information is cumulative - all of the references * reported in any SurvivingReferences call survive this collection. * * cSurvivingObjectIDRanges is a count of the number of ObjectID ranges that * survived. * objectIDRangeStart is an array of elements, each of which is the start * value of a range of ObjectID values that survived the collection. * cObjectIDRangeLength is an array of elements, each of which states the * size of the surviving ObjectID value range. * * The last two arguments of this function are parallel arrays. * * In other words, if an ObjectID value lies within the range * objectIDRangeStart[i] <= ObjectID < objectIDRangeStart[i] + cObjectIDRangeLength[i] * for 0 <= i < cMovedObjectIDRanges, then the ObjectID has survived the collection * * THIS CALLBACK IS OBSOLETE. It reports ranges for objects >4GB as UINT32_MAX * on 64-bit platforms. Use ICorProfilerCallback4::SurvivingReferences2 instead. */ HRESULT SurvivingReferences( [in] ULONG cSurvivingObjectIDRanges, [in, size_is(cSurvivingObjectIDRanges)] ObjectID objectIDRangeStart[] , [in, size_is(cSurvivingObjectIDRanges)] ULONG cObjectIDRangeLength[] ); /* * The CLR calls GarbageCollectionFinished after a garbage * collection has completed and all GC callbacks have been * issued for it. * * NOTE: It is now safe to inspect objects in their * final locations. */ HRESULT GarbageCollectionFinished(); /* * The CLR calls FinalizeableObjectQueued to notify the code profiler * that an object with a finalizer (destructor in C# parlance) has * just been queued to the finalizer thread for execution of its * Finalize method. * * finalizerFlags describes aspects of the finalizer, and takes its * value from COR_PRF_FINALIZER_FLAGS. * */ HRESULT FinalizeableObjectQueued( [in] DWORD finalizerFlags, [in] ObjectID objectID); /* * The CLR calls RootReferences2 with information about root * references after a garbage collection has occurred. * For each root reference in rootRefIds, there is information in * rootClassifications to classify it. Depending on the classification, * rootsIds may contain additional information. The information in * rootKinds and rootFlags contains information about the location and * properties of the reference. * * If the profiler implements ICorProfilerCallback2, both * ICorProfilerCallback::RootReferences and ICorProfilerCallback2::RootReferences2 * are called. As the information passed to RootReferences2 is a superset * of the one passed to RootReferences, profilers will normally implement * one or the other, but not both. * * If the root kind is STACK, the ID is the FunctionID of the * function containing the variable. If the FunctionID is 0, the function * is an unnamed function internal to the CLR. * * If the root kind is HANDLE, the ID is the GCHandleID. * * For the other root kinds, the ID is an opaque value and should * be ignored. * * It's possible for entries in rootRefIds to be 0 - this just * implies the corresponding root reference was null and thus did not * refer to an object on the managed heap. * * NOTE: None of the objectIDs returned by RootReferences2 are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers * should not attempt to inspect objects during a RootReferences2 call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. */ HRESULT RootReferences2( [in] ULONG cRootRefs, [in, size_is(cRootRefs)] ObjectID rootRefIds[], [in, size_is(cRootRefs)] COR_PRF_GC_ROOT_KIND rootKinds[], [in, size_is(cRootRefs)] COR_PRF_GC_ROOT_FLAGS rootFlags[], [in, size_is(cRootRefs)] UINT_PTR rootIds[]); /* * The CLR calls HandleCreated when a gc handle has been created. * */ HRESULT HandleCreated( [in] GCHandleID handleId, [in] ObjectID initialObjectId); /* * The CLR calls HandleDestroyed when a gc handle has been destroyed. * */ HRESULT HandleDestroyed( [in] GCHandleID handleId); } [ object, uuid(4FD2ED52-7731-4b8d-9469-03D2CC3086C5), pointer_default(unique), local ] interface ICorProfilerCallback3 : ICorProfilerCallback2 { HRESULT InitializeForAttach( [in] IUnknown * pCorProfilerInfoUnk, [in] void * pvClientData, [in] UINT cbClientData); HRESULT ProfilerAttachComplete(); HRESULT ProfilerDetachSucceeded(); }; [ object, uuid(7B63B2E3-107D-4d48-B2F6-F61E229470D2), pointer_default(unique), local ] interface ICorProfilerCallback4 : ICorProfilerCallback3 { /* * Similar to JITCompilationStarted, except called when rejitting a method */ HRESULT ReJITCompilationStarted( [in] FunctionID functionId, [in] ReJITID rejitId, [in] BOOL fIsSafeToBlock); /* * This is called exactly once per method (which may represent more than * one function id), to allow the code profiler to set alternate code * generation flags or a new method body. */ HRESULT GetReJITParameters( [in] ModuleID moduleId, [in] mdMethodDef methodId, [in] ICorProfilerFunctionControl *pFunctionControl); /* * Similar to JITCompilationFinished, except called when rejitting a method */ HRESULT ReJITCompilationFinished( [in] FunctionID functionId, [in] ReJITID rejitId, [in] HRESULT hrStatus, [in] BOOL fIsSafeToBlock); /* * This is called to report an error encountered while processing a ReJIT request. * This may either be called from within the RequestReJIT call itself, or called after * RequestReJIT returns, if the error was encountered later on. */ HRESULT ReJITError( [in] ModuleID moduleId, [in] mdMethodDef methodId, [in] FunctionID functionId, [in] HRESULT hrStatus); /* * The CLR calls MovedReferences with information about * object references that moved as a result of garbage collection. * * cMovedObjectIDRanges is a count of the number of ObjectID ranges that * were moved. * oldObjectIDRangeStart is an array of elements, each of which is the start * value of a range of ObjectID values before being moved. * newObjectIDRangeStart is an array of elements, each of which is the start * value of a range of ObjectID values after being moved. * cObjectIDRangeLength is an array of elements, each of which states the * size of the moved ObjectID value range. * * The last three arguments of this function are parallel arrays. * * In other words, if an ObjectID value lies within the range * oldObjectIDRangeStart[i] <= ObjectID < oldObjectIDRangeStart[i] + cObjectIDRangeLength[i] * for 0 <= i < cMovedObjectIDRanges, then the ObjectID value has changed to * ObjectID - oldObjectIDRangeStart[i] + newObjectIDRangeStart[i] * * NOTE: None of the objectIDs returned by MovedReferences are valid during the callback * itself, as the GC may be in the middle of moving objects from old to new. Thus profilers * should not attempt to inspect objects during a MovedReferences call. At * GarbageCollectionFinished, all objects have been moved to their new locations, and * inspection may be done. * * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::MovedReferences2 * is called first and ICorProfilerCallback::MovedReferences is called second but only if * ICorProfilerCallback4::MovedReferences2 returned success. Profilers can return failure * from ICorProfilerCallback4::MovedReferences2 to save some chattiness. */ HRESULT MovedReferences2( [in] ULONG cMovedObjectIDRanges, [in, size_is(cMovedObjectIDRanges)] ObjectID oldObjectIDRangeStart[] , [in, size_is(cMovedObjectIDRanges)] ObjectID newObjectIDRangeStart[] , [in, size_is(cMovedObjectIDRanges)] SIZE_T cObjectIDRangeLength[] ); /* * The CLR calls SurvivingReferences with information about * object references that survived a garbage collection. * * Generally, the CLR calls SurvivingReferences for non-compacting garbage collections. * For compacting garbage collections, MovedReferences is called instead. * * The exception to this rule is that the CLR always calls SurvivingReferences for objects * in the large object heap, which is not compacted. * * Multiple calls to SurvivingReferences may be received during a particular * garbage collection, due to limited internal buffering, multiple threads reporting * in the case of server gc, and other reasons. * In the case of multiple calls, the information is cumulative - all of the references * reported in any SurvivingReferences call survive this collection. * * cSurvivingObjectIDRanges is a count of the number of ObjectID ranges that * survived. * objectIDRangeStart is an array of elements, each of which is the start * value of a range of ObjectID values that survived the collection. * cObjectIDRangeLength is an array of elements, each of which states the * size of the surviving ObjectID value range. * * The last two arguments of this function are parallel arrays. * * In other words, if an ObjectID value lies within the range * objectIDRangeStart[i] <= ObjectID < objectIDRangeStart[i] + cObjectIDRangeLength[i] * for 0 <= i < cMovedObjectIDRanges, then the ObjectID has survived the collection * * If the profiler implements ICorProfilerCallback4, ICorProfilerCallback4::SurvivingReferences2 * is called first and ICorProfilerCallback2::SurvivingReferences is called second but only if * ICorProfilerCallback4::SurvivingReferences2 returned success. Profilers can return failure * from ICorProfilerCallback4::SurvivingReferences2 to save some chattiness. */ HRESULT SurvivingReferences2( [in] ULONG cSurvivingObjectIDRanges, [in, size_is(cSurvivingObjectIDRanges)] ObjectID objectIDRangeStart[] , [in, size_is(cSurvivingObjectIDRanges)] SIZE_T cObjectIDRangeLength[] ); }; [ object, uuid(8DFBA405-8C9F-45F8-BFFA-83B14CEF78B5), pointer_default(unique), local ] interface ICorProfilerCallback5 : ICorProfilerCallback4 { /* * The CLR calls ConditionalWeakTableElementReferences with information * about dependent handles after a garbage collection has occurred. * * For each root ID in rootIds, keyRefIds will contain the ObjectID for * the primary element in the dependent handle pair, and valueRefIds will * contain the ObjectID for the secondary element (keyRefIds[i] keeps * valueRefIds[i] alive). * * NOTE: None of the objectIDs returned by ConditionalWeakTableElementReferences * are valid during the callback itself, as the GC may be in the middle * of moving objects from old to new. Thus profilers should not attempt * to inspect objects during a ConditionalWeakTableElementReferences call. * At GarbageCollectionFinished, all objects have been moved to their new * locations, and inspection may be done. */ HRESULT ConditionalWeakTableElementReferences( [in] ULONG cRootRefs, [in, size_is(cRootRefs)] ObjectID keyRefIds[], [in, size_is(cRootRefs)] ObjectID valueRefIds[], [in, size_is(cRootRefs)] GCHandleID rootIds[]); }; [ object, uuid(FC13DF4B-4448-4F4F-950C-BA8D19D00C36), pointer_default(unique), local ] interface ICorProfilerCallback6 : ICorProfilerCallback5 { // CORECLR DEPRECATION WARNING: This callback does not occur on coreclr. // Controlled by the COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES event mask flag. // Notifies the profiler of a very early stage in the loading of an Assembly, where the CLR // performs an assembly reference closure walk. This is useful ONLY if the profiler will need // to modify the metadata of the Assembly to add AssemblyRefs (later, in ModuleLoadFinished). In // such a case, the profiler should implement this callback as well, to inform the CLR that assembly references // will be added once the module has loaded. This is useful to ensure that assembly sharing decisions // made by the CLR during this early stage remain valid even though the profiler plans to modify the metadata // assembly references later on. This can be used to avoid some instances where profiler metadata // modifications can cause the SECURITY_E_INCOMPATIBLE_SHARE error to be thrown. // // The profiler uses the ICorProfilerAssemblyReferenceProvider provided to add assembly references // to the CLR assembly reference closure walker. The ICorProfilerAssemblyReferenceProvider // should only be used from within this callback. The profiler will still need to explicitly add assembly // references via IMetaDataAssemblyEmit, from within the ModuleLoadFinished callback for the referencing assembly, // even though the profiler implements this GetAssemblyReferences callback. This callback does not result in // modified metadata; only in a modified assembly reference closure walk. // // The profiler should be prepared to receive duplicate calls to this callback for the same assembly, // and should respond identically for each such duplicate call (by making the same set of // ICorProfilerAssemblyReferenceProvider::AddAssemblyReference calls). HRESULT GetAssemblyReferences( [in, string] const WCHAR * wszAssemblyPath, [in] ICorProfilerAssemblyReferenceProvider * pAsmRefProvider); }; [ object, uuid(F76A2DBA-1D52-4539-866C-2AA518F9EFC3), pointer_default(unique), local ] interface ICorProfilerCallback7 : ICorProfilerCallback6 { // This event is triggered whenever the symbol stream associated with an // in-memory module is updated. Even when symbols are provided up-front in // a call to the managed API Assembly.Load(byte[], byte[], ...) the runtime // may not actually associate the symbolic data with the module until after // the ModuleLoadFinished callback has occurred. This event provides a later // opportunity to collect symbols for such modules. // // This event is controlled by the COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED // event mask flag. // // Note: This event is not currently raised for symbols implicitly created or // modified via Reflection.Emit APIs. HRESULT ModuleInMemorySymbolsUpdated(ModuleID moduleId); } [ object, uuid(5BED9B15-C079-4D47-BFE2-215A140C07E0), pointer_default(unique), local ] interface ICorProfilerCallback8 : ICorProfilerCallback7 { // This event is triggered whenever a dynamic method is jit compiled. // These include various IL Stubs and LCG Methods. // The goal is to provide profiler writers with enough information to identify // it to users as beyond unknown code addresses. // Note: FunctionID's provided here cannot be used to resolve to their metadata // tokens since dynamic methods have no metadata. // // Documentation Note: pILHeader is only valid during the callback HRESULT DynamicMethodJITCompilationStarted( [in] FunctionID functionId, [in] BOOL fIsSafeToBlock, [in] LPCBYTE pILHeader, [in] ULONG cbILHeader); HRESULT DynamicMethodJITCompilationFinished( [in] FunctionID functionId, [in] HRESULT hrStatus, [in] BOOL fIsSafeToBlock); } [ object, uuid(27583EC3-C8F5-482F-8052-194B8CE4705A), pointer_default(unique), local ] interface ICorProfilerCallback9 : ICorProfilerCallback8 { // This event is triggered whenever a dynamic method is garbage collected // and subsequently unloaded. HRESULT DynamicMethodUnloaded([in] FunctionID functionId); } [ object, uuid(CEC5B60E-C69C-495F-87F6-84D28EE16FFB), pointer_default(unique), local ] interface ICorProfilerCallback10 : ICorProfilerCallback9 { // This event is triggered whenever an EventPipe event is configured to be delivered. // // Documentation Note: All pointers are only valid during the callback HRESULT EventPipeEventDelivered( [in] EVENTPIPE_PROVIDER provider, [in] DWORD eventId, [in] DWORD eventVersion, [in] ULONG cbMetadataBlob, [in, size_is(cbMetadataBlob)] LPCBYTE metadataBlob, [in] ULONG cbEventData, [in, size_is(cbEventData)] LPCBYTE eventData, [in] LPCGUID pActivityId, [in] LPCGUID pRelatedActivityId, [in] ThreadID eventThread, [in] ULONG numStackFrames, [in, length_is(numStackFrames)] UINT_PTR stackFrames[]); HRESULT EventPipeProviderCreated([in] EVENTPIPE_PROVIDER provider); } [ object, uuid(42350846-AAED-47F7-B128-FD0C98881CDE), pointer_default(unique), local ] interface ICorProfilerCallback11 : ICorProfilerCallback10 { HRESULT LoadAsNotificationOnly(BOOL *pbNotificationOnly); } /* * COR_PRF_CODEGEN_FLAGS controls various flags and hooks for a specific * method. A combination of COR_PRF_CODEGEN_FLAGS is provided by the * profiler in its call to ICorProfilerFunctionControl::SetCodegenFlags() * when rejitting a method. */ typedef enum { COR_PRF_CODEGEN_DISABLE_INLINING = 0x0001, COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS = 0x0002, } COR_PRF_CODEGEN_FLAGS; /* * The CLR implements the ICorProfilerInfo interface. This interface is * used by a code profiler to communicate with the CLR to control event * monitoring and request information. The CLR passes an * ICorProfilerInfo interface to each code profiler during initialization. * * A code profiler can call methods on the ICorProfilerInfo interface to get * information about managed code being executed under the control of the CLR * * The ICorProfilerInfo interface implemented by the CLR uses the free * threaded model. * * The methods implemented on this interface return S_OK on success, or E_FAIL * on failure. * */ [ object, uuid(28B5557D-3F3F-48b4-90B2-5F9EEA2F6C48), pointer_default(unique), local ] interface ICorProfilerInfo : IUnknown { /* * The code profiler calls GetClassFromObject to obtain the ClassID of an * object given its ObjectID. */ HRESULT GetClassFromObject( [in] ObjectID objectId, [out] ClassID *pClassId); /* * V2 MIGRATION WARNING - DOES NOT WORK FOR GENERIC TYPES * * This function will be removed in a future release, so * use GetClassFromTokenAndTypeArgs for all types. */ HRESULT GetClassFromToken( [in] ModuleID moduleId, [in] mdTypeDef typeDef, [out] ClassID *pClassId); /* * V2 MIGRATION WARNING - WILL NOT WORK WITH .NET FRAMEWORK * FUNCTIONS * * This function will be removed in a future release; use GetCodeInfo2 * in all cases. */ HRESULT GetCodeInfo( [in] FunctionID functionId, [out] LPCBYTE *pStart, [out] ULONG *pcSize); /* * RECOMMENDATION: USE GetEventMask2 INSTEAD. WHILE THIS METHOD CONTINUES TO * TO WORK, GetEventMask2 PROVIDES MORE FUNCTIONALITY. * * The code profiler calls GetEventMask to obtain the current event * categories for which it is to receive event notifications from the COM+ * Runtime. */ HRESULT GetEventMask( [out] DWORD *pdwEvents); /* * The code profiler calls GetFunctionFromIP to map an instruction pointer * in managed code to a FunctionID. */ HRESULT GetFunctionFromIP( [in] LPCBYTE ip, [out] FunctionID *pFunctionId); /* * V2 MIGRATION WARNING - WILL NOT WORK FOR GENERIC FUNCTIONS OR * FUNCTIONS ON GENERIC TYPES * * This function will be removed in a future release, so use * GetFunctionFromTokenAndTypeArgs for all functions. */ HRESULT GetFunctionFromToken( [in] ModuleID moduleId, [in] mdToken token, [out] FunctionID *pFunctionId); /* * The code profiler calls GetHandleFromThread to map a ThreadID to a Win32 * thread handle. The profiler must call DuplicateHandle on the handle * before using it. */ HRESULT GetHandleFromThread( [in] ThreadID threadId, [out] HANDLE *phThread); /* * The code profiler calls GetObjectSize to obtain the size of an object. * Note that types like arrays and strings may have a different size for each object. * * THIS API IS OBSOLETE. It does not work for objects >4GB on 64-bit platforms. * Use ICorProfilerInfo4::GetObjectSize2 instead. */ HRESULT GetObjectSize( [in] ObjectID objectId, [out] ULONG *pcSize); /* * This will return S_OK if the ClassID provided is an array class, and will * fill out the information for any non-null out params. S_FALSE will be * returned if the ClassID is not an array. * * classId : the ClassID to return information about * pBaseElemType : the array's base element type * pBaseClassId : the base ClassID if the element type == ELEMENT_TYPE_CLASS * pcRank : the number of dimensions of the array */ HRESULT IsArrayClass( [in] ClassID classId, [out] CorElementType *pBaseElemType, [out] ClassID *pBaseClassId, [out] ULONG *pcRank); /* * The code profiler calls GetThreadInfo to obtain the current Win32 thread ID for * the specified thread. */ HRESULT GetThreadInfo( [in] ThreadID threadId, [out] DWORD *pdwWin32ThreadId); /* * The code profiler calls GetCurrentThreadID to get the managed thread ID * for the current thread. * * NOTE: GetCurrentThreadID may return CORPROF_E_NOT_MANAGED_THREAD if the * current thread is an internal runtime thread, and the returned value of * pThreadId will be NULL. */ HRESULT GetCurrentThreadID( [out] ThreadID *pThreadId); /* * V2 MIGRATION NOTE - More information is available for generic types * from GetClassIDInfo2. * * Returns the parent module a class is defined in, along with the * metadata token for the class. One can call GetModuleMetaData * to obtain the metadata interface for a given module. The token * can then be used to access the metadata for this class. */ HRESULT GetClassIDInfo( [in] ClassID classId, [out] ModuleID *pModuleId, [out] mdTypeDef *pTypeDefToken); /* * Return the parent class for a given function. Also return the metadata * token which can be used to read the metadata. * * V2 MIGRATION WARNING - LESS INFORMATION FOR GENERIC CLASSES * The ClassID of a function on a generic class may not be obtainable without * more context about the use of the function. In this case, *pClassId will be 0; * try using GetFunctionInfo2 with a COR_PRF_FRAME_INFO to give more context. */ HRESULT GetFunctionInfo( [in] FunctionID functionId, [out] ClassID *pClassId, [out] ModuleID *pModuleId, [out] mdToken *pToken); /* * RECOMMENDATION: USE SetEventMask2 INSTEAD. WHILE THIS METHOD CONTINUES TO * TO WORK, SetEventMask2 PROVIDES MORE FUNCTIONALITY. * * The code profiler calls SetEventMask to set the event categories for * which it is set to receive notification from the CLR. */ HRESULT SetEventMask( [in] DWORD dwEvents); /* * The code profiler calls SetFunctionHooks to specify handlers * for FunctionEnter, FunctionLeave, and FunctionTailcall. * * Note that only one set of callbacks may be active at a time. Thus, * if a profiler calls SetEnterLeaveFunctionHooks, SetEnterLeaveFunctionHooks2 * and SetEnterLeaveFunctionHooks3(WithInfo), then SetEnterLeaveFunctionHooks3(WithInfo) * wins. SetEnterLeaveFunctionHooks2 takes precedence over SetEnterLeaveFunctionHooks * when both are set. * * Each function pointer may be null to disable that callback. * * SetEnterLeaveFunctionHooks may only be called from the * profiler's Initialize() callback. */ HRESULT SetEnterLeaveFunctionHooks( [in] FunctionEnter *pFuncEnter, [in] FunctionLeave *pFuncLeave, [in] FunctionTailcall *pFuncTailcall); /* * This is used for mapping FunctionIDs to alternative values that will be * passed to the callbacks */ HRESULT SetFunctionIDMapper( [in] FunctionIDMapper *pFunc); /* * For a given function, retrieve the token value and an instance of the * meta data interface which can be used against this token. */ HRESULT GetTokenAndMetaDataFromFunction( [in] FunctionID functionId, [in] REFIID riid, [out] IUnknown **ppImport, [out] mdToken *pToken); /* * Retrieve information about a given module. * * When the module is loaded from disk, the name returned will be the filename; * otherwise, the name will be the name from the metadata Module table (i.e., * the same as the managed System.Reflection.Module.ScopeName). * * NOTE: While this function may be called as soon as the moduleId is alive, * the AssemblyID of the containing assembly will not be available until the * ModuleAttachedToAssembly callback. * * NOTE: More information is available by using ICorProfilerInfo3::GetModuleInfo2 instead. */ HRESULT GetModuleInfo( [in] ModuleID moduleId, [out] LPCBYTE *ppBaseLoadAddress, [in] ULONG cchName, [out] ULONG *pcchName, [out, annotation("_Out_writes_to_(cchName, *pcchName)")] WCHAR szName[] , [out] AssemblyID *pAssemblyId); /* * Get a metadata interface instance which maps to the given module. * One may ask for the metadata to be opened in read+write mode, but * this will result in slower metadata execution of the program, because * changes made to the metadata cannot be optimized as they were from * the compiler. * * NOTE: Some modules (such as resource modules) have no metadata. In * those cases, GetModuleMetaData will return S_FALSE, and a NULL * IUnknown. * * NOTE: the only values valid for dwOpenFlags are ofRead and ofWrite. */ HRESULT GetModuleMetaData( [in] ModuleID moduleId, [in] DWORD dwOpenFlags, [in] REFIID riid, [out] IUnknown **ppOut); /* * Retrieve a pointer to the body of a method starting at it's header. * A method is scoped by the module it lives in. Because this function * is designed to give a tool access to IL before it has been loaded * by the Runtime, it uses the metadata token of the method to find * the instance desired. * * GetILFunctionBody can return CORPROF_E_FUNCTION_NOT_IL if the methodId * points to a method without any IL (such as an abstract method, or a * P/Invoke method). */ HRESULT GetILFunctionBody( [in] ModuleID moduleId, [in] mdMethodDef methodId, [out] LPCBYTE *ppMethodHeader, [out] ULONG *pcbMethodSize); /* * IL method bodies must be located as RVA's to the loaded module, which * means they come after the module within 4 gb. In order to make it * easier for a tool to swap out the body of a method, this allocator * will ensure memory is allocated within that range. */ HRESULT GetILFunctionBodyAllocator( [in] ModuleID moduleId, [out] IMethodMalloc **ppMalloc); /* * Replaces the method body for a function in a module. This will replace * the RVA of the method in the metadata to point to this new method body, * and adjust any internal data structures as required. This function can * only be called on those methods which have never been compiled by a JITTER. * Please use the GetILFunctionAllocator to allocate space for the new method to * ensure the buffer is compatible. */ HRESULT SetILFunctionBody( [in] ModuleID moduleId, [in] mdMethodDef methodid, [in] LPCBYTE pbNewILMethodHeader); /* * Retrieve app domain information given its id. */ HRESULT GetAppDomainInfo( [in] AppDomainID appDomainId, [in] ULONG cchName, [out] ULONG *pcchName, [out, annotation("_Out_writes_to_(cchName, *pcchName)")] WCHAR szName[] , [out] ProcessID *pProcessId); /* * Retrieve information about an assembly given its ID. */ HRESULT GetAssemblyInfo( [in] AssemblyID assemblyId, [in] ULONG cchName, [out] ULONG *pcchName, [out, annotation("_Out_writes_to_(cchName, *pcchName)")] WCHAR szName[] , [out] AppDomainID *pAppDomainId, [out] ModuleID *pModuleId); /* * V2 MIGRATION WARNING: DEPRECATED. Returns E_NOTIMPL always. * * See ICorProfilerInfo4::RequestReJIT instead * */ HRESULT SetFunctionReJIT( [in] FunctionID functionId); /* * ForceGC forces a GC to occur within the runtime. * * NOTE: This method needs to be called from a thread that does not have any * profiler callbacks on its stack. The most convenient way to implement this is * to create a separate thread within the profiler and have it call ForceGC when * signalled. */ HRESULT ForceGC(); /* * * V2 MIGRATION NOTE - Calling SetILInstrumentedCodeMap on any one * of the multiple FunctionIDs that represent a generic function in a given * AppDomain will affect all instantiations of that function in the AppDomain. * * fStartJit should be set to true the first time this function is called for * a given FunctionID, and false thereafter. * * The format of the map is as follows: * The debugger will assume that each oldOffset refers to an IL offset * within the original, unmodified IL code. newOffset refers to the corresponding * IL offset within the new, instrumented code. * * The map should be sorted in increasing order. For stepping to work properly: * - Instrumented IL should not be reordered (so both old & new are sorted) * - original IL should not be removed * - the map should include entries to map all of the sequence points from the pdb. * * The map does not interpolate missing entries. So given the following map: * (0 old, 0 new) * (5 old, 10 new) * (9 old, 20 new) * - An old offset of 0,1,2,3,4 will be mapped to a new offset of 0 * - An old offset of 5,6,7, or 8 will be mapped to new offset 10. * - An old offset of 9 or higher will be mapped to new offset 20. * - A new offset of 0, 1,...8,9 will be mapped to old offset 0 * - A new offset of 10,11,...18,19 will be mapped to old offset 5. * - A new offset of 20 or higher will be mapped to old offset 9. * */ HRESULT SetILInstrumentedCodeMap( [in] FunctionID functionId, [in] BOOL fStartJit, [in] ULONG cILMapEntries, [in, size_is(cILMapEntries)] COR_IL_MAP rgILMapEntries[] ); /* * DEPRECATED. */ HRESULT GetInprocInspectionInterface( [out] IUnknown **ppicd); /* * DEPRECATED. */ HRESULT GetInprocInspectionIThisThread( [out] IUnknown **ppicd); /* * This will return the ContextID currently associated with the calling * runtime thread. This will set pContextId to NULL if the calling thread * is not a runtime thread. */ HRESULT GetThreadContext( [in] ThreadID threadId, [out] ContextID *pContextId); /* * DEPRECATED. */ HRESULT BeginInprocDebugging( [in] BOOL fThisThreadOnly, [out] DWORD *pdwProfilerContext); /* * DEPRECATED. */ HRESULT EndInprocDebugging( [in] DWORD dwProfilerContext); /* * GetILToNativeMapping returns a map from IL offsets to native * offsets for this code. An array of COR_PROF_IL_TO_NATIVE_MAP * structs will be returned, and some of the ilOffsets in this array * may be the values specified in CorDebugIlToNativeMappingTypes. */ HRESULT GetILToNativeMapping( [in] FunctionID functionId, [in] ULONG32 cMap, [out] ULONG32 *pcMap, [out, size_is(cMap), length_is(*pcMap)] COR_DEBUG_IL_TO_NATIVE_MAP map[]); } /* * The CLR implements the ICorProfilerInfo2 interface. This interface is * used by a code profiler to communicate with the CLR to control event * monitoring and request information. The CLR passes an * ICorProfilerInfo2 interface to each code profiler during initialization. * * A code profiler can call methods on the ICorProfilerInfo2 interface to get * information about managed code being executed under the control of the CLR * * The ICorProfilerInfo2 interface implemented by the CLR uses the free * threaded model. * * The methods implemented on this interface return S_OK on success, or E_FAIL * on failure. * */ [ object, uuid(CC0935CD-A518-487d-B0BB-A93214E65478), pointer_default(unique), local ] interface ICorProfilerInfo2 : ICorProfilerInfo { /* * The code profiler calls DoStackSnapshot to do sparse one-off stack snapshots. * * Passing NULL for thread yields a snapshot of the current thread. If a ThreadID * of a different thread is passed, the runtime will suspend that thread, perform * the snapshot, and resume. * * infoFlags come from the COR_PRF_SNAPSHOT_INFO enum. * * context is a platform-dependent CONTEXT structure, representing the complete * register context that the profiling API will use to seed the stack walk. If this * is non-NULL, it must point to JITd or NGENd code, or else DoStackSnapshot * will return CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX. Contexts are * only provided by profilers that hijack threads to force them to walk their * own stacks; profilers should not attempt to provide a context when walking * another thread's stack. If context is NULL, the stack walk will begin at the * last available managed frame for the target thread. * * See the definition of StackSnapshotCallback for more information. */ HRESULT DoStackSnapshot( [in] ThreadID thread, [in] StackSnapshotCallback *callback, [in] ULONG32 infoFlags, [in] void *clientData, [in, size_is(contextSize)] BYTE context[], [in] ULONG32 contextSize); /* * The code profiler calls SetFunctionHooks2 to specify handlers * for FunctionEnter2, FunctionLeave2, and FunctionTailcall2 * callbacks. * * Note that only one set of callbacks may be active at a time. Thus, * if a profiler calls SetEnterLeaveFunctionHooks, SetEnterLeaveFunctionHooks2 * and SetEnterLeaveFunctionHooks3(WithInfo), then SetEnterLeaveFunctionHooks3(WithInfo) * wins. SetEnterLeaveFunctionHooks2 takes precedence over SetEnterLeaveFunctionHooks * when both are set. * * Each pointer may be null to disable that particular callback. * * SetEnterLeaveFunctionHooks2 may only be called from the * profiler's Initialize() callback. */ HRESULT SetEnterLeaveFunctionHooks2( [in] FunctionEnter2 *pFuncEnter, [in] FunctionLeave2 *pFuncLeave, [in] FunctionTailcall2 *pFuncTailcall); /* * GetFunctionInfo2 returns the parent class of a function, plus the * function's metadata token and the ClassIDs of its type arguments * (if any). * * When a COR_PRF_FRAME_INFO obtained from a FunctionEnter2 * callback is passed, the ClassID and all type arguments will be exact. * * When a COR_PRF_FRAME_INFO from any other source is passed, or * when 0 is passed as the frameInfo argument, exact ClassID and type * arguments cannot always be determined. The value returned in pClassId * may be NULL and some type args will come back as System.Object. * */ HRESULT GetFunctionInfo2( [in] FunctionID funcId, [in] COR_PRF_FRAME_INFO frameInfo, [out] ClassID *pClassId, [out] ModuleID *pModuleId, [out] mdToken *pToken, [in] ULONG32 cTypeArgs, [out] ULONG32 *pcTypeArgs, [out] ClassID typeArgs[]); /* * GetStringLayout returns detailed information about how string objects are stored. * * *pBufferLengthOffset is the offset (from the ObjectID pointer) to a DWORD that * stores the length of the string's buffer * * *pStringLengthOffset is the offset (from the ObjectID pointer) to a DWORD that * stores the length of the string itself * * *pBufferOffset is the offset (from the ObjectID pointer) to the actual buffer * of wide characters * * Strings may or may not be null-terminated. */ HRESULT GetStringLayout( [out] ULONG *pBufferLengthOffset, [out] ULONG *pStringLengthOffset, [out] ULONG *pBufferOffset); /* * GetClassLayout returns detailed information how a specific class is stored. * It only returns the fields defined by the class itself; if the parent class * defined fields as well, the profiler must call GetClassLayout on the parent class * to obtain those fields. * * It will fail with E_INVALIDARG for string and array classes. */ HRESULT GetClassLayout( [in] ClassID classID, [in, out] COR_FIELD_OFFSET rFieldOffset[], [in] ULONG cFieldOffset, [out] ULONG *pcFieldOffset, [out] ULONG *pulClassSize); /* * Returns the parent module a class is defined in, along with the * metadata token for the class, the ClassID of its parent class, and the * ClassIDs of its type arguments (if any). * * One can call GetModuleMetaData to obtain the metadata interface for * a given module. The token can then be used to access the metadata for this * class. */ HRESULT GetClassIDInfo2( [in] ClassID classId, [out] ModuleID *pModuleId, [out] mdTypeDef *pTypeDefToken, [out] ClassID *pParentClassId, [in] ULONG32 cNumTypeArgs, [out] ULONG32 *pcNumTypeArgs, [out] ClassID typeArgs[]); /* * GetCodeInfo2 returns the extents of native code associated with the * given FunctionID. These extents are returned sorted in order of increasing * IL offset. */ HRESULT GetCodeInfo2( [in] FunctionID functionID, [in] ULONG32 cCodeInfos, [out] ULONG32 *pcCodeInfos, [out, size_is(cCodeInfos), length_is(*pcCodeInfos)] COR_PRF_CODE_INFO codeInfos[]); /* * GetClassFromTokenAndTypeArgs returns the ClassID of a type given its metadata * token (typedef) and the ClassIDs of its type arguments (if any). * * cTypeArgs must be equal to the number of type parameters for the given type * (0 for non-generic types) * typeArgs may be NULL if cTypeArgs == 0 * * Calling this function with a TypeRef token can have unpredictable results; callers * should resolve the TypeRef to a TypeDef and use that. * * If the type is not already loaded, calling this function will cause it to be. * Loading is a dangerous operation in many contexts. For example, calling * this function during loading of modules or other types could lead to an infinite * loop as the runtime attempts to circularly load things. * * In general, use of this function is discouraged. If profilers are interested in * events for a particular type, they should store the ModuleID and TypeDef of that type, * and use GetClassIDInfo2 to check whether a given ClassID is the desired type. */ HRESULT GetClassFromTokenAndTypeArgs( [in] ModuleID moduleID, [in] mdTypeDef typeDef, [in] ULONG32 cTypeArgs, [in, size_is(cTypeArgs)] ClassID typeArgs[], [out] ClassID* pClassID); /* * GetFunctionFromTokenAndTypeArgs returns the FunctionID of a function given * its metadata token (methoddef), containing class, and type args (if any). * * classID may be 0 if the containing class is not generic * typeArgs may be NULL if cTypeArgs == 0 * * Calling this function with a MethodRef token can have unpredictable results; callers * should resolve the MethodRef to a MethodDef and use that. * * If the function is not already loaded, calling this function will cause it to be. * Loading is a dangerous operation in many contexts. For example, calling * this function during loading of modules or types could lead to an infinite * loop as the runtime attempts to circularly load things. * * In general, use of this function is discouraged. If profilers are interested in * events for a particular function, they should store the ModuleID and MethodDef of that function, * and use GetFunctionInfo2 to check whether a given FunctionID is the desired function. */ HRESULT GetFunctionFromTokenAndTypeArgs( [in] ModuleID moduleID, [in] mdMethodDef funcDef, [in] ClassID classId, [in] ULONG32 cTypeArgs, [in, size_is(cTypeArgs)] ClassID typeArgs[], [out] FunctionID* pFunctionID); /* * Returns an enumerator over all frozen objects in the given module. */ HRESULT EnumModuleFrozenObjects( [in] ModuleID moduleID, [out] ICorProfilerObjectEnum** ppEnum); /* * GetArrayObjectInfo returns detailed information about an array object. * objectId is a valid array object. * cDimensions is the rank (# of dimensions). * On success: * pDimensionSizes, pDimensionLowerBounds are parallel arrays describing the size and lower bound for each dimension. * (*ppData) is a pointer to the raw buffer for the array, which is laid out according to the C++ * convention */ HRESULT GetArrayObjectInfo( [in] ObjectID objectId, [in] ULONG32 cDimensions, [out, size_is(cDimensions)] ULONG32 pDimensionSizes[], [out, size_is(cDimensions)] int pDimensionLowerBounds[], [out] BYTE **ppData); /* * GetBoxClassLayout returns information about how a particular value type is laid out * when boxed. * * *pBufferOffset is the offset (from the ObjectID pointer) to where the value type * is stored within the box. The value type's class layout may then be used to * interpret it. */ HRESULT GetBoxClassLayout( [in] ClassID classId, [out] ULONG32 *pBufferOffset); /* * GetThreadAppDomain returns the AppDomainID currently associated with\ * the given ThreadID */ HRESULT GetThreadAppDomain( [in] ThreadID threadId, [out] AppDomainID *pAppDomainId); /* * GetRVAStaticAddress gets the address of the home for the given * RVA static. It must be called from a managed thread. Otherwise, * it will return CORPROF_E_NOT_MANAGED_THREAD. */ HRESULT GetRVAStaticAddress( [in] ClassID classId, [in] mdFieldDef fieldToken, [out] void **ppAddress); /* * GetAppDomainStaticAddress gets the address of the home for the given * AppDomain static in the given AppDomain. * * This function may return CORPROF_E_DATAINCOMPLETE if the given static * has not been assigned a home in the given AppDomain. */ HRESULT GetAppDomainStaticAddress( [in] ClassID classId, [in] mdFieldDef fieldToken, [in] AppDomainID appDomainId, [out] void **ppAddress); /* * GetThreadStaticAddress gets the address of the home for the given * Thread static in the given Thread. threadId must be the current thread * ID or NULL, which means using curernt thread ID. * * This function may return CORPROF_E_DATAINCOMPLETE if the given static * has not been assigned a home in the given Thread. */ HRESULT GetThreadStaticAddress( [in] ClassID classId, [in] mdFieldDef fieldToken, [in] ThreadID threadId, [out] void **ppAddress); /* * GetContextStaticAddress gets the address of the home for the given * Context static in the given context. It must be called from a managed * thread. Otherwise, it will return CORPROF_E_NOT_MANAGED_THREAD. * * This function may return CORPROF_E_DATAINCOMPLETE if the given static * has not been assigned a home in the given Context. */ HRESULT GetContextStaticAddress( [in] ClassID classId, [in] mdFieldDef fieldToken, [in] ContextID contextId, [out] void **ppAddress); /* * GetStaticFieldInfo gets COR_PRF_STATIC_TYPE for a specific * field in a class. This information can be used to decide which * function to call to get the address of the static. * * NOTE: One should still check the metadata for a static to ensure * it is actually going to have an address. Statics that are literals * (aka constants) exist only in the metadata and do not have an address. * */ HRESULT GetStaticFieldInfo( [in] ClassID classId, [in] mdFieldDef fieldToken, [out] COR_PRF_STATIC_TYPE *pFieldInfo); /* * GetGenerationBounds returns the memory regions that make up a given * GC generation in memory. It may be called from any profiler callback as long * as a GC is not in progress. (To be exact, it may be called from any callback * except for those that occur between GarbageCollectionStarted and GarbageCollectionFinished.) * * Most shifting of generations takes place during garbage collections; between * collections generations may grow, but generally do not move around. Therefore * the most interesting places to call this function are in GarbageCollectionStarted * and Finished. * * During program startup, some objects are allocated by the CLR itself, generally * in generations 3 and 0. So by the time managed code starts executing, these * generations will already contain objects. Generations 1 and 2 will be normally * empty, except for dummy objects generated by the garbage collector (of size 12 * bytes in 32-bit implementations of the CLR, larger in 64-bit implementations). * You may also see generation 2 ranges that are inside modules generated by ngen. * These are "frozen objects" generated at ngen time rather than allocated by the * garbage collector. * * cObjectRanges is a count of the number of elements allocated by the caller for * the ranges array * pcObjectRanges is an out param for the number of ranges in the given generation * ranges is an array of elements of type COR_PRF_GC_GENERATION_RANGE, each of which * describes a range of memory used by the garbage collector */ HRESULT GetGenerationBounds( [in] ULONG cObjectRanges, [out] ULONG *pcObjectRanges, [out, size_is(cObjectRanges), length_is(*pcObjectRanges)] COR_PRF_GC_GENERATION_RANGE ranges[]); /* * GetObjectGeneration returns which generation the given object is currently in, along * with the start and length of the segment containing the object. It may be called * at any time as long as a GC is not in progress. */ HRESULT GetObjectGeneration( [in] ObjectID objectId, [out] COR_PRF_GC_GENERATION_RANGE *range); /* * When an exception notification is received, GetNotifiedExceptionClauseInfo() may be used * to get the native address and frame information for the exception clause (catch/finally/filter) * that is about to be run (ExceptionCatchEnter, ExceptionUnwindFinallyEnter, ExceptionFilterEnter) * or has just been run (ExceptionCatchLeave, ExceptionUnwindFinallyLeave, ExceptionFilterLeave). * * This call may be made at any time after one of the Enter calls above until either the matching * Leave call is received or until a nested exception throws out of the current clause in which case * there will be no Leave notification for that clause. Note it is not possible for a throw to escape * a Filter so there is always a Leave in that case. * * Return values: * S_OK indicates success * S_FALSE indicates that no exception clause is active * CORPROF_E_NOT_MANAGED_THREAD indicates an unmanaged thread. */ HRESULT GetNotifiedExceptionClauseInfo( [out] COR_PRF_EX_CLAUSE_INFO *pinfo); } /* * The CLR implements the ICorProfilerInfo3 interface. This interface is * used by a code profiler to communicate with the CLR to control event * monitoring and request information. The CLR passes an * ICorProfilerInfo3 interface to each code profiler during initialization. * * A code profiler can call methods on the ICorProfilerInfo3 interface to get * information about managed code being executed under the control of the CLR * * The ICorProfilerInfo3 interface implemented by the CLR uses the free * threaded model. * * The methods implemented on this interface return S_OK on success, or E_FAIL * on failure. * */ [ object, uuid(B555ED4F-452A-4E54-8B39-B5360BAD32A0), pointer_default(unique), local ] interface ICorProfilerInfo3 : ICorProfilerInfo2 { /* * Returns an enumerator for all previously jitted functions. May overlap with * functions previously reported via CompilationStarted callbacks. * NOTE: The returned enumeration will only include '0' for the value of the * COR_PRF_FUNCTION::reJitId field. If you require valid COR_PRF_FUNCTION::reJitId values, use * ICorProfilerInfo4::EnumJITedFunctions2. */ HRESULT EnumJITedFunctions([out] ICorProfilerFunctionEnum** ppEnum); HRESULT RequestProfilerDetach([in] DWORD dwExpectedCompletionMilliseconds); HRESULT SetFunctionIDMapper2( [in] FunctionIDMapper2 *pFunc, [in] void *clientData); /* * GetStringLayout2 returns detailed information about how string objects are stored. * * *pStringLengthOffset is the offset (from the ObjectID pointer) to a DWORD that * stores the length of the string itself * * *pBufferOffset is the offset (from the ObjectID pointer) to the actual buffer * of wide characters * * Strings may or may not be null-terminated. */ HRESULT GetStringLayout2( [out] ULONG *pStringLengthOffset, [out] ULONG *pBufferOffset); /* * The code profiler calls SetFunctionHooks3 to specify handlers * for FunctionEnter3, FunctionLeave3, and FunctionTailcall3, and calls * SetFunctionHooks3WithInfo to specify handlers for FunctionEnter3WithInfo, * FunctionLeave3WithInfo, and FunctionTailcall3WithInfo. * * Note that only one set of callbacks may be active at a time. Thus, * if a profiler calls SetEnterLeaveFunctionHooks, SetEnterLeaveFunctionHooks2 * and SetEnterLeaveFunctionHooks3(WithInfo), then SetEnterLeaveFunctionHooks3(WithInfo) * wins. SetEnterLeaveFunctionHooks2 takes precedence over SetEnterLeaveFunctionHooks * when both are set. * * Each function pointer may be null to disable that callback. * * SetEnterLeaveFunctionHooks3(WithInfo) may only be called from the * profiler's Initialize() callback. */ HRESULT SetEnterLeaveFunctionHooks3( [in] FunctionEnter3 *pFuncEnter3, [in] FunctionLeave3 *pFuncLeave3, [in] FunctionTailcall3 *pFuncTailcall3); HRESULT SetEnterLeaveFunctionHooks3WithInfo( [in] FunctionEnter3WithInfo *pFuncEnter3WithInfo, [in] FunctionLeave3WithInfo *pFuncLeave3WithInfo, [in] FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); /* * The profiler can call GetFunctionEnter3Info to gather frame info and argument info * in FunctionEnter3WithInfo callback. The profiler needs to allocate sufficient space * for COR_PRF_FUNCTION_ARGUMENT_INFO of the function it's inspecting and indicate the * size in a ULONG pointed by pcbArgumentInfo. */ HRESULT GetFunctionEnter3Info( [in] FunctionID functionId, [in] COR_PRF_ELT_INFO eltInfo, [out] COR_PRF_FRAME_INFO *pFrameInfo, [in, out] ULONG *pcbArgumentInfo, [out, size_is(*pcbArgumentInfo)] COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); /* * The profiler can call GetFunctionLeave3Info to gather frame info and return value * in FunctionLeave3WithInfo callback. */ HRESULT GetFunctionLeave3Info( [in] FunctionID functionId, [in] COR_PRF_ELT_INFO eltInfo, [out] COR_PRF_FRAME_INFO *pFrameInfo, [out] COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); /* * The profiler can call GetFunctionTailcall3Info to gather frame info in * FunctionTailcall3WithInfo callback. */ HRESULT GetFunctionTailcall3Info( [in] FunctionID functionId, [in] COR_PRF_ELT_INFO eltInfo, [out] COR_PRF_FRAME_INFO *pFrameInfo); HRESULT EnumModules([out] ICorProfilerModuleEnum** ppEnum); /* * The profiler can call GetRuntimeInformation to query CLR version information. * Passing NULL to any parameter is acceptable except pcchVersionString cannot * be NULL if szVersionString is not NULL. */ HRESULT GetRuntimeInformation([out] USHORT *pClrInstanceId, [out] COR_PRF_RUNTIME_TYPE *pRuntimeType, [out] USHORT *pMajorVersion, [out] USHORT *pMinorVersion, [out] USHORT *pBuildNumber, [out] USHORT *pQFEVersion, [in] ULONG cchVersionString, [out] ULONG *pcchVersionString, [out, annotation("_Out_writes_to_(cchVersionString, *pcchVersionString)")] WCHAR szVersionString[]); /* * GetThreadStaticAddress2 gets the address of the home for the given * Thread static in the given Thread. * * This function may return CORPROF_E_DATAINCOMPLETE if the given static * has not been assigned a home in the given Thread. */ HRESULT GetThreadStaticAddress2( [in] ClassID classId, [in] mdFieldDef fieldToken, [in] AppDomainID appDomainId, [in] ThreadID threadId, [out] void **ppAddress); /* * GetAppDomainsContainingModule returns the AppDomainIDs in which the * given module has been loaded */ HRESULT GetAppDomainsContainingModule( [in] ModuleID moduleId, [in] ULONG32 cAppDomainIds, [out] ULONG32 *pcAppDomainIds, [out, size_is(cAppDomainIds), length_is(*pcAppDomainIds)] AppDomainID appDomainIds[]); /* * Retrieve information about a given module. * * When the module is loaded from disk, the name returned will be the filename; * otherwise, the name will be the name from the metadata Module table (i.e., * the same as the managed System.Reflection.Module.ScopeName). * * *pdwModuleFlags will be filled in with a bitmask of values from COR_PRF_MODULE_FLAGS * that specify some properties of the module. * * NOTE: While this function may be called as soon as the moduleId is alive, * the AssemblyID of the containing assembly will not be available until the * ModuleAttachedToAssembly callback. * */ HRESULT GetModuleInfo2( [in] ModuleID moduleId, [out] LPCBYTE *ppBaseLoadAddress, [in] ULONG cchName, [out] ULONG *pcchName, [out, annotation("_Out_writes_to_(cchName, *pcchName)")] WCHAR szName[], [out] AssemblyID *pAssemblyId, [out] DWORD *pdwModuleFlags); } /* * This interface lets you iterate over the frozen objects from ngen images. */ [ object, uuid(2C6269BD-2D13-4321-AE12-6686365FD6AF), pointer_default(unique), local ] interface ICorProfilerObjectEnum : IUnknown { HRESULT Skip( [in] ULONG celt); HRESULT Reset(); HRESULT Clone( [out] ICorProfilerObjectEnum **ppEnum); HRESULT GetCount( [out] ULONG *pcelt); HRESULT Next( [in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ObjectID objects[], [out] ULONG *pceltFetched); } /* * This interface lets you iterate over functions in the runtime. */ [ object, uuid(FF71301A-B994-429D-A10B-B345A65280EF), pointer_default(unique), local ] interface ICorProfilerFunctionEnum : IUnknown { HRESULT Skip([in] ULONG celt); HRESULT Reset(); HRESULT Clone([out] ICorProfilerFunctionEnum **ppEnum); HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] COR_PRF_FUNCTION ids[], [out] ULONG * pceltFetched); }; /* * This interface lets you iterate over modules in the runtime. */ [ object, uuid(b0266d75-2081-4493-af7f-028ba34db891), pointer_default(unique), local ] interface ICorProfilerModuleEnum : IUnknown { HRESULT Skip([in] ULONG celt); HRESULT Reset(); HRESULT Clone([out] ICorProfilerModuleEnum **ppEnum); HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ModuleID ids[], [out] ULONG * pceltFetched); }; /* * NOTE: DEPRECATED, now you can use your any allocator. * * This is simple allocator that only allows you to allocate memory. * You may not free it. This was used in conjunction with * ICorProfilerInfo::SetILFunctionBody. */ [ object, uuid(A0EFB28B-6EE2-4d7b-B983-A75EF7BEEDB8), pointer_default(unique), local ] interface IMethodMalloc : IUnknown { /* * Tries to allocate memory above the start address of the module from * which it was created. It is important to note that this method may * fail to allocate the memory specified above the start address, and * may as a result return NULL. */ PVOID Alloc( [in] ULONG cb); } /* * The CLR implements the ICorProfilerFunctionControl interface. This interface * is used by a code profiler to communicate with the CLR to control how the * JIT should generate code when rejitting a specific method. * * The ICorProfilerFunctionControl interface implemented by the CLR uses the * free threaded model. */ [ object, uuid(F0963021-E1EA-4732-8581-E01B0BD3C0C6), pointer_default(unique), local ] interface ICorProfilerFunctionControl : IUnknown { /* * Set one or more flags from COR_PRF_CODEGEN_FLAGS to control code * generation just for this method. */ HRESULT SetCodegenFlags( [in] DWORD flags); /* * Override the method body. */ HRESULT SetILFunctionBody( [in] ULONG cbNewILMethodHeader, [in, size_is(cbNewILMethodHeader)] LPCBYTE pbNewILMethodHeader); /* * This is not currently implemented, and will return E_NOTIMPL */ HRESULT SetILInstrumentedCodeMap( [in] ULONG cILMapEntries, [in, size_is(cILMapEntries)] COR_IL_MAP rgILMapEntries[]); } /* * The CLR implements the ICorProfilerInfo4 interface. This interface is * used by a code profiler to communicate with the CLR to control event * monitoring and request information. The CLR passes an * ICorProfilerInfo4 interface to each code profiler during initialization. * * A code profiler can call methods on the ICorProfilerInfo4 interface to get * information about managed code being executed under the control of the CLR * * The ICorProfilerInfo4 interface implemented by the CLR uses the free * threaded model. * * The methods implemented on this interface return S_OK on success, or E_FAIL * on failure. * */ [ object, uuid(0d8fdcaa-6257-47bf-b1bf-94dac88466ee), pointer_default(unique), local ] interface ICorProfilerInfo4 : ICorProfilerInfo3 { HRESULT EnumThreads([out] ICorProfilerThreadEnum **ppEnum); HRESULT InitializeCurrentThread(); /* * Call RequestReJIT to have the runtime re-JIT a particular set of methods. * A code profiler can then adjust the code generated when the method is * re-JITed through the ICorProfilerFunctionControl interface. This does * not impact currently executing methods, only future invocations. * * A return code of S_OK indicates that all of the requested methods were * attempted to be rejitted. However, the profiler must implement * ICorProfilerCallback4::ReJITError to determine which of the methods were * successfully re-JITed. * * A failure return value (E_*) indicates some failure that prevents any * re-JITs. */ HRESULT RequestReJIT( [in] ULONG cFunctions, [in, size_is(cFunctions)] ModuleID moduleIds[], [in, size_is(cFunctions)] mdMethodDef methodIds[]); /* * RequestRevert will instruct the runtime to revert to using/calling the * original method (original IL and flags) rather than whatever was * ReJITed. This does not change any currently active methods, only future * invocations. * */ HRESULT RequestRevert( [in] ULONG cFunctions, [in, size_is(cFunctions)] ModuleID moduleIds[], [in, size_is(cFunctions)] mdMethodDef methodIds[], [out, size_is(cFunctions)] HRESULT status[]); /* * Same as GetCodeInfo2, except instead of always returning the code info * associated with the original IL/function, you can request the code info * for a particular re-JITed version of a function. */ HRESULT GetCodeInfo3( [in] FunctionID functionID, [in] ReJITID reJitId, [in] ULONG32 cCodeInfos, [out] ULONG32 * pcCodeInfos, [out, size_is(cCodeInfos), length_is(*pcCodeInfos)] COR_PRF_CODE_INFO codeInfos[]); /* * Same as GetFunctionFromIP, but also returns which re-JITed version is * associated with the IP address. */ HRESULT GetFunctionFromIP2( [in] LPCBYTE ip, [out] FunctionID * pFunctionId, [out] ReJITID * pReJitId); /* * GetReJITIDs can be used to find all of the re-JITed versions of the * given function. */ HRESULT GetReJITIDs( [in] FunctionID functionId, [in] ULONG cReJitIds, [out] ULONG * pcReJitIds, [out, size_is(cReJitIds), length_is(*pcReJitIds)] ReJITID reJitIds[]); /* * Same as GetILToNativeMapping, but allows the code profiler to specify * which re-JITed version it applies to. */ HRESULT GetILToNativeMapping2( [in] FunctionID functionId, [in] ReJITID reJitId, [in] ULONG32 cMap, [out] ULONG32 * pcMap, [out, size_is(cMap),length_is(*pcMap)] COR_DEBUG_IL_TO_NATIVE_MAP map[]); /* * Returns an enumerator for all previously jitted functions. May overlap with * functions previously reported via CompilationStarted callbacks. The returned * enumeration will include values for the COR_PRF_FUNCTION::reJitId field */ HRESULT EnumJITedFunctions2([out] ICorProfilerFunctionEnum** ppEnum); /* * The code profiler calls GetObjectSize to obtain the size of an object. * Note that types like arrays and strings may have a different size for each object. */ HRESULT GetObjectSize2( [in] ObjectID objectId, [out] SIZE_T *pcSize); } [ object, uuid(07602928-CE38-4B83-81E7-74ADAF781214), pointer_default(unique), local ] interface ICorProfilerInfo5 : ICorProfilerInfo4 { /* * The code profiler calls GetEventMask2 to obtain the current event * categories for which it is to receive event notifications from the CLR * * *pdwEventsLow is a bitwise combination of values from COR_PRF_MONITOR * *pdwEventsHigh is a bitwise combination of values from COR_PRF_HIGH_MONITOR */ HRESULT GetEventMask2( [out] DWORD *pdwEventsLow, [out] DWORD *pdwEventsHigh); /* * The code profiler calls SetEventMask2 to set the event categories for * which it is set to receive notification from the CLR. * * dwEventsLow is a bitwise combination of values from COR_PRF_MONITOR * dwEventsHigh is a bitwise combination of values from COR_PRF_HIGH_MONITOR */ HRESULT SetEventMask2( [in] DWORD dwEventsLow, [in] DWORD dwEventsHigh); }; [ object, uuid(F30A070D-BFFB-46A7-B1D8-8781EF7B698A), pointer_default(unique), local ] interface ICorProfilerInfo6 : ICorProfilerInfo5 { /* * Returns an enumerator for all methods that * - belong to a given NGen or R2R module (inlinersModuleId) and * - inlined a body of a given method (inlineeModuleId / inlineeMethodId). * * If incompleteData is set to TRUE after function is called, it means that the methods enumerator * doesn't contain all methods inlining a given method. * It can happen when one or more direct or indirect dependencies of inliners module haven't been loaded yet. * If profiler needs accurate data it should retry later when more modules are loaded (preferably on each module load). * * It can be used to lift limitation on inlining for ReJIT. * * NOTE: If the inlinee method is decorated with the System.Runtime.Versioning.NonVersionable attribute then * then some inliners may not ever be reported. If you need to get a full accounting you can avoid the issue * by disabling the use of all native images. * */ HRESULT EnumNgenModuleMethodsInliningThisMethod( [in] ModuleID inlinersModuleId, [in] ModuleID inlineeModuleId, [in] mdMethodDef inlineeMethodId, [out] BOOL *incompleteData, [out] ICorProfilerMethodEnum** ppEnum); }; [ object, uuid(9AEECC0D-63E0-4187-8C00-E312F503F663), pointer_default(unique), local ] interface ICorProfilerInfo7 : ICorProfilerInfo6 { /* * Applies the newly emitted Metadata. * * This method can be used to apply the newly defined metadata by IMetadataEmit::Define* methods * to the module. * * If metadata changes are made after ModuleLoadFinished callback, * it is required to call this method before using the new metadata */ HRESULT ApplyMetaData( [in] ModuleID moduleId); /* Returns the length of an in-memory symbol stream * * If the module has in-memory symbols the length of the stream will * be placed in pCountSymbolBytes. If the module doesn't have in-memory * symbols, *pCountSymbolBytes = 0 * * Returns S_OK if the length could be determined (even if it is 0) * * Note: The current implementation does not support reflection.emit. * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case. */ HRESULT GetInMemorySymbolsLength( [in] ModuleID moduleId, [out] DWORD* pCountSymbolBytes); /* Reads bytes from an in-memory symbol stream * * This function attempts to read countSymbolBytes of data starting at offset * symbolsReadOffset within the in-memory stream. The data will be copied into * pSymbolBytes which is expected to have countSymbolBytes of space available. * pCountSymbolsBytesRead contains the actual number of bytes read which * may be less than countSymbolBytes if the end of the stream is reached. * * Returns S_OK if a non-zero number of bytes were read. * * Note: The current implementation does not support reflection.emit. * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case. */ HRESULT ReadInMemorySymbols( [in] ModuleID moduleId, [in] DWORD symbolsReadOffset, [out] BYTE* pSymbolBytes, [in] DWORD countSymbolBytes, [out] DWORD* pCountSymbolBytesRead); }; [ object, uuid(C5AC80A6-782E-4716-8044-39598C60CFBF), pointer_default(unique), local ] interface ICorProfilerInfo8 : ICorProfilerInfo7 { /* * Determines if a function has associated metadata * * Certain methods like IL Stubs or LCG Methods do not have * associated metadata that can be retrieved using the IMetaDataImport APIs. * * Such methods can be encountered by profilers through instruction pointers * or by listening to ICorProfilerCallback::DynamicMethodJITCompilationStarted * * This API can be used to determine whether a FunctionID is dynamic. */ HRESULT IsFunctionDynamic( [in] FunctionID functionId, [out] BOOL *isDynamic); /* * Maps a managed code instruction pointer to a FunctionID. * * GetFunctionFromIP2 fails for dynamic methods, this method works for * both dynamic and non-dynamic methods. It is a superset of GetFunctionFromIP2 */ HRESULT GetFunctionFromIP3([in] LPCBYTE ip, [out] FunctionID *functionId, [out] ReJITID * pReJitId); /* * Retrieves information about dynamic methods * * Certain methods like IL Stubs or LCG do not have * associated metadata that can be retrieved using the IMetaDataImport APIs. * * Such methods can be encountered by profilers through instruction pointers * or by listening to ICorProfilerCallback::DynamicMethodJITCompilationStarted * * This API can be used to retrieve information about dynamic methods * including a friendly name if available. */ HRESULT GetDynamicFunctionInfo( [in] FunctionID functionId, [out] ModuleID *moduleId, [out] PCCOR_SIGNATURE *ppvSig, [out] ULONG *pbSig, [in] ULONG cchName, [out] ULONG *pcchName, [out] WCHAR wszName[]); }; [ object, uuid(008170DB-F8CC-4796-9A51-DC8AA0B47012), pointer_default(unique), local ] interface ICorProfilerInfo9 : ICorProfilerInfo8 { //Given functionId + rejitId, enumerate the native code start address of all jitted versions of this code that currently exist HRESULT GetNativeCodeStartAddresses(FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[]); //Given the native code start address, return the native->IL mapping information for this jitted version of the code HRESULT GetILToNativeMapping3(UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[]); //Given the native code start address, return the blocks of virtual memory that store this code (method code is not necessarily stored in a single contiguous memory region) HRESULT GetCodeInfo4(UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32* pcCodeInfos, COR_PRF_CODE_INFO codeInfos[]); }; [ object, uuid(2F1B5152-C869-40C9-AA5F-3ABE026BD720), pointer_default(unique), local ] interface ICorProfilerInfo10 : ICorProfilerInfo9 { // Given an ObjectID, callback and clientData, enumerates each object reference (if any). HRESULT EnumerateObjectReferences(ObjectID objectId, ObjectReferenceCallback callback, void* clientData); // Given an ObjectID, determines whether it is in a read only segment. HRESULT IsFrozenObject(ObjectID objectId, BOOL *pbFrozen); // Gets the value of the configured LOH Threshold. HRESULT GetLOHObjectSizeThreshold(DWORD *pThreshold); /* * This method will ReJIT the methods requested, as well as any inliners * of the methods requested. * * RequestReJIT does not do any tracking of inlined methods. The profiler * was expected to track inlining and call RequestReJIT for all inliners * to make sure every instance of an inlined method was ReJITted. * This poses a problem with ReJIT on attach, since the profiler was * not present to monitor inlining. This method can be called to guarantee * that the full set of inliners will be ReJITted as well. */ HRESULT RequestReJITWithInliners( [in] DWORD dwRejitFlags, [in] ULONG cFunctions, [in, size_is(cFunctions)] ModuleID moduleIds[], [in, size_is(cFunctions)] mdMethodDef methodIds[]); // Suspend the runtime without performing a GC. HRESULT SuspendRuntime(); // Restart the runtime from a previous suspension. HRESULT ResumeRuntime(); } [ object, uuid(06398876-8987-4154-B621-40A00D6E4D04), pointer_default(unique), local ] interface ICorProfilerInfo11 : ICorProfilerInfo10 { /* * Get environment variable for the running managed code. */ HRESULT GetEnvironmentVariable( [in, string] const WCHAR *szName, [in] ULONG cchValue, [out] ULONG *pcchValue, [out, annotation("_Out_writes_to_(cchValue, *pcchValue)")] WCHAR szValue[]); /* * Set environment variable for the running managed code. * * The code profiler calls this function to modify environment variables of the * current managed process. For example, it can be used in the profiler's Initialize() * or InitializeForAttach() callbacks. * * szName is the name of the environment variable, should not be NULL. * * szValue is the contents of the environment variable, or NULL if the variable should be deleted. */ HRESULT SetEnvironmentVariable( [in, string] const WCHAR *szName, [in, string] const WCHAR *szValue); } [ object, uuid(27b24ccd-1cb1-47c5-96ee-98190dc30959), pointer_default(unique), local ] interface ICorProfilerInfo12 : ICorProfilerInfo11 { HRESULT EventPipeStartSession( [in] UINT32 cProviderConfigs, [in, size_is(cProviderConfigs)] COR_PRF_EVENTPIPE_PROVIDER_CONFIG pProviderConfigs[], [in] BOOL requestRundown, [out] EVENTPIPE_SESSION* pSession); HRESULT EventPipeAddProviderToSession( [in] EVENTPIPE_SESSION session, [in] COR_PRF_EVENTPIPE_PROVIDER_CONFIG providerConfig); HRESULT EventPipeStopSession( [in] EVENTPIPE_SESSION session); HRESULT EventPipeCreateProvider( [in, string] const WCHAR *providerName, [out] EVENTPIPE_PROVIDER *pProvider); HRESULT EventPipeGetProviderInfo( [in] EVENTPIPE_PROVIDER provider, [in] ULONG cchName, [out] ULONG *pcchName, [out, annotation("_Out_writes_to_(cchName, *pcchName)")] WCHAR providerName[]); HRESULT EventPipeDefineEvent( [in] EVENTPIPE_PROVIDER provider, [in, string] const WCHAR *eventName, [in] UINT32 eventID, [in] UINT64 keywords, [in] UINT32 eventVersion, [in] UINT32 level, [in] UINT8 opcode, [in] BOOL needStack, [in] UINT32 cParamDescs, [in, size_is(cParamDescs)] COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[], [out] EVENTPIPE_EVENT *pEvent); HRESULT EventPipeWriteEvent( [in] EVENTPIPE_EVENT event, [in] UINT32 cData, [in, size_is(cData)] COR_PRF_EVENT_DATA data[], [in] LPCGUID pActivityId, [in] LPCGUID pRelatedActivityId); } [ object, uuid(6E6C7EE2-0701-4EC2-9D29-2E8733B66934), pointer_default(unique), local ] interface ICorProfilerInfo13 : ICorProfilerInfo12 { HRESULT CreateHandle( [in] ObjectID object, [in] COR_PRF_HANDLE_TYPE type, [out] ObjectHandleID* pHandle); HRESULT DestroyHandle( [in] ObjectHandleID handle); HRESULT GetObjectIDFromHandle( [in] ObjectHandleID handle, [out] ObjectID* pObject); } /* * This interface lets you iterate over methods in the runtime. */ [ object, uuid(FCCEE788-0088-454B-A811-C99F298D1942), pointer_default(unique), local ] interface ICorProfilerMethodEnum : IUnknown { HRESULT Skip([in] ULONG celt); HRESULT Reset(); HRESULT Clone([out] ICorProfilerMethodEnum **ppEnum); HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] COR_PRF_METHOD elements[], [out] ULONG * pceltFetched); } /* * This interface lets you iterate over threads in the runtime. */ [ object, uuid(571194f7-25ed-419f-aa8b-7016b3159701), pointer_default(unique), local ] interface ICorProfilerThreadEnum : IUnknown { HRESULT Skip([in] ULONG celt); HRESULT Reset(); HRESULT Clone([out] ICorProfilerThreadEnum **ppEnum); HRESULT GetCount([out] ULONG *pcelt); HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ThreadID ids[], [out] ULONG * pceltFetched); } /* * This interface is given to the profiler in the GetAssemblyReferences() callback, to * allow the profiler to inform the CLR of assembly references that the profiler plans to * add later on during ModuleLoadFinished. This improves the accuracy of the CLR assembly * reference closure walker, and its algorithms for determining whether assemblies may be shared * * This interface is valid for use only within the GetAssemblyReferences callback that passed * this interface to the profiler */ [ object, uuid(66A78C24-2EEF-4F65-B45F-DD1D8038BF3C), pointer_default(unique), local ] interface ICorProfilerAssemblyReferenceProvider : IUnknown { // The profiler calls this for each target assembly it plans to reference from the // assembly specified in the wszAssemblyPath argument of the GetAssemblyReferences callback. HRESULT AddAssemblyReference(const COR_PRF_ASSEMBLY_REFERENCE_INFO * pAssemblyRefInfo); }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corpub.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* -------------------------------------------------------------------------- * * Common Language Runtime Process Publishing Interfaces * -------------------------------------------------------------------------- */ cpp_quote("#if 0") #ifndef DO_NO_IMPORTS import "unknwn.idl"; #endif cpp_quote("#endif") typedef enum { COR_PUB_MANAGEDONLY = 0x00000001 // Must always be set, // only enumerates // managed processes } COR_PUB_ENUMPROCESS; /* -------------------------------------------------------------------------- * * Forward declarations * -------------------------------------------------------------------------- */ #pragma warning(push) #pragma warning(disable:28718) //Unable to annotate as this is not a local interface interface ICorPublish; interface ICorPublishProcess; interface ICorPublishAppDomain; interface ICorPublishProcessEnum; interface ICorPublishAppDomainEnum; #pragma warning(pop) /* ------------------------------------------------------------------------- * * Library definition * ------------------------------------------------------------------------- */ [ uuid(e97ca460-657d-11d3-8d5b-00104b35e7ef), version(1.0), helpstring("Common Language Runtime Process Publishing Library") ] library CorpubProcessLib { importlib("STDOLE2.TLB"); // CorPublish is a shared component across all version of the runtime. [ uuid(047a9a40-657e-11d3-8d5b-00104b35e7ef) ] coclass CorpubPublish { [default] interface ICorPublish; interface ICorPublishProcess; interface ICorPublishAppDomain; interface ICorPublishProcessEnum; interface ICorPublishAppDomainEnum; }; }; /* -------------------------------------------------------------------------- * * Interface definitions * -------------------------------------------------------------------------- */ /* * This interface is the top level interface for publishing of processes. */ [ object, uuid(9613A0E7-5A68-11d3-8F84-00A0C9B4D50C), pointer_default(unique), local ] interface ICorPublish : IUnknown { /* * Retrieves a list of managed processes on this machine which * the current user has permission to debug. In this version, * Type must always be equal to COR_PUB_MANAGEDONLY. * The list is based on a snapshot of the processes running when * the enum method is called. The enumerator will not reflect any * processes that start before or terminate after EnumProcesses is called. * If EnumProcesses is called more than once on this ICorPublish * instance, a new up-to-date enumeration will be returned without * affecting any previous ones. */ HRESULT EnumProcesses([in] COR_PUB_ENUMPROCESS Type, [out] ICorPublishProcessEnum **ppIEnum); /* * Gets a new ICorPublishProcess object for the managed process * with the given process ID. Returns failure if the process doesn't * exist, or isn't a managed process that can be debugged by the current * user. */ HRESULT GetProcess([in] unsigned pid, [out] ICorPublishProcess **ppProcess); } /* * An abstract enumerator. */ [ object, uuid(C0B22967-5A69-11d3-8F84-00A0C9B4D50C), pointer_default(unique), local ] interface ICorPublishEnum : IUnknown { /* * Moves the current position forward the given number of * elements. */ HRESULT Skip([in] ULONG celt); /* * Sets the position of the enumerator to the beginning of the * enumeration. */ HRESULT Reset(); /* * Creates another enumerator with the same current position * as this one. */ HRESULT Clone([out] ICorPublishEnum **ppEnum); /* * Gets the number of elements in the enumeration */ HRESULT GetCount([out] ULONG *pcelt); }; #pragma warning(push) #pragma warning(disable:28718) /* * Describes a process on a machine. */ [ object, uuid(18D87AF1-5A6A-11d3-8F84-00A0C9B4D50C), pointer_default(unique), local ] interface ICorPublishProcess : IUnknown { /* * Returns true if the process is known to have managed code * running in it. Since this version of ICorPublish only provides access * to managed processes, this method always returns true. */ HRESULT IsManaged([out] BOOL *pbManaged); /* * Enumerates the list of known application domains in this process. * This list is based on a snapshot of the existing AppDomains when * this method is called. This method may be called more than * once to create a new up-to-date list. Existing enumerations will not * be affected by calls to this method. If the process has been * terminated, this will fail with CORDBG_E_PROCESS_TERMINATED. */ HRESULT EnumAppDomains([out] ICorPublishAppDomainEnum **ppEnum); /* * Returns the OS ID for this process. */ HRESULT GetProcessID([out] unsigned *pid); /* * Get the full path of the executable for this process. * If szName is non-null, this copies up to cchName characters (including * the null terminator) into szName, and ensures it is null-terminated. * If pcchName is non-null, the actual number of characters in the name * (including the null terminator) is stored there. This method returns * S_OK regardless of how many characters were copied. */ HRESULT GetDisplayName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR *szName); } #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) /* * Provide information on an Application Domain object. */ [ object, uuid(D6315C8F-5A6A-11d3-8F84-00A0C9B4D50C), pointer_default(unique), local ] interface ICorPublishAppDomain : IUnknown { /* * Gets the identification number of this application domain. * Note that this number is unique to this AppDomain, but only * within the containing process. */ HRESULT GetID([out] ULONG32 *puId); /* * Get the name for an application domain. * If szName is non-null, this copies up to cchName characters (including * the null terminator) into szName, and ensures it is null-terminated. * If pcchName is non-null, the actual number of characters in the name * (including the null terminator) is stored there. This method returns * S_OK regardless of how many characters were copied. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR *szName); } #pragma warning(pop) /* * Enumerate a list of processes based on the filter criteria given * when the enumerator object was created. */ [ object, uuid(A37FBD41-5A69-11d3-8F84-00A0C9B4D50C), pointer_default(unique), local ] interface ICorPublishProcessEnum : ICorPublishEnum { /* * Gets the next "celt" processes in the enumeration. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorPublishProcess **objects, [out] ULONG *pceltFetched); } /* * Enumerate a list of app domains based in a process. */ [ object, uuid(9F0C98F5-5A6A-11d3-8F84-00A0C9B4D50C), pointer_default(unique), local ] interface ICorPublishAppDomainEnum : ICorPublishEnum { /* * Gets the next "celt" application domains in the enumeration. */ HRESULT Next([in] ULONG celt, [out, size_is(celt), length_is(*pceltFetched)] ICorPublishAppDomain **objects, [out] ULONG *pceltFetched); } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/corsym.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* ------------------------------------------------------------------------- * * Common Language Runtime Debugging Symbol Reader/Writer/Binder Interfaces * ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- * * Imported types * ------------------------------------------------------------------------- */ cpp_quote("#if 0") typedef UINT32 mdToken; typedef mdToken mdTypeDef; typedef mdToken mdMethodDef; typedef SIZE_T IMAGE_DEBUG_DIRECTORY; cpp_quote("#endif") cpp_quote("#ifndef __CORHDR_H__") typedef mdToken mdSignature; cpp_quote("#endif") #include "winerror.h" /* ------------------------------------------------------------------------- * * Guids for known languages, language vendors, and document types * ------------------------------------------------------------------------- */ cpp_quote("EXTERN_GUID(CorSym_LanguageType_C, 0x63a08714, 0xfc37, 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_CPlusPlus, 0x3a12d0b7, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_CSharp, 0x3f5162f8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_Basic, 0x3a12d0b8, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_Java, 0x3a12d0b4, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_Cobol, 0xaf046cd1, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_Pascal, 0xaf046cd2, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_ILAssembly, 0xaf046cd3, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_JScript, 0x3a12d0b6, 0xc26c, 0x11d0, 0xb4, 0x42, 0x00, 0xa0, 0x24, 0x4a, 0x1d, 0xd2);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_SMC, 0xd9b9f7b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd);") cpp_quote("EXTERN_GUID(CorSym_LanguageType_MCPlusPlus, 0x4b35fde8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") cpp_quote("EXTERN_GUID(CorSym_LanguageVendor_Microsoft, 0x994b45c4, 0xe6e9, 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1);") cpp_quote("EXTERN_GUID(CorSym_DocumentType_Text, 0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd);") cpp_quote("EXTERN_GUID(CorSym_DocumentType_MC, 0xeb40cb65, 0x3c1f, 0x4352, 0x9d, 0x7b, 0xba, 0xf, 0xc4, 0x7a, 0x9d, 0x77);") #ifdef INTEROPLIB module LanguageType { const LPSTR C = "{63a08714-fc37-11d2-904c-00c04fa302a1}"; const LPSTR CPlusPlus = "{3a12d0b7-c26c-11d0-b442-00a0244a1dd2}"; const LPSTR CSharp = "{3f5162f8-07c6-11d3-9053-00c04fa302a1}"; const LPSTR Basic = "{3a12d0b8-c26c-11d0-b442-00a0244a1dd2}"; const LPSTR Java = "{3a12d0b4-c26c-11d0-b442-00a0244a1dd2}"; const LPSTR Cobol = "{af046cd1-d0e1-11d2-977c-00a0c9b4d50c}"; const LPSTR Pascal = "{af046cd2-d0e1-11d2-977c-00a0c9b4d50c}"; const LPSTR ILAssembly ="{af046cd3-d0e1-11d2-977c-00a0c9b4d50c}"; const LPSTR JScript = "{3a12d0b6-c26c-11d0-b442-00a0244a1dd2}"; const LPSTR SMC = "{0d9b9f7b-6611-11d3-bd2a-0000f80849bd}"; const LPSTR MCPlusPlus ="{4b35fde8-07c6-11d3-9053-00c04fa302a1}"; } module ErrorCodes80 { const int E_SYM_DESTROYED = MAKE_HRESULT(1, FACILITY_ITF, 0xdead); } #endif // ndef INTEROPLIB /* ------------------------------------------------------------------------- * * Guids for known Source Hash Algorithms * ------------------------------------------------------------------------- */ cpp_quote("EXTERN_GUID(CorSym_SourceHash_MD5, 0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99);") cpp_quote("EXTERN_GUID(CorSym_SourceHash_SHA1, 0xff1816ec, 0xaa5e, 0x4d10, 0x87, 0xf7, 0x6f, 0x49, 0x63, 0x83, 0x34, 0x60);") /* ------------------------------------------------------------------------- * * Forward declarations * ------------------------------------------------------------------------- */ interface ISymUnmanagedDocument; interface ISymUnmanagedDocumentWriter; interface ISymUnmanagedMethod; interface ISymUnmanagedNamespace; interface ISymUnmanagedReader; interface ISymUnmanagedReaderSymbolSearchInfo; interface ISymUnmanagedScope; interface ISymUnmanagedVariable; interface ISymUnmanagedSymbolSearchInfo; interface ISymUnmanagedWriter; interface ISymUnmanagedWriter2; interface ISymUnmanagedBinder; /* ------------------------------------------------------------------------- * * CorSymAddrKind -- specifies the kinds of addresses used by the interfaces * ------------------------------------------------------------------------- */ typedef enum CorSymAddrKind { /* * ADDR_IL_OFFSET: addr1 = IL local var or param index. */ ADDR_IL_OFFSET = 1, /* * ADDR_NATIVE_RVA: addr1 = RVA into module. */ ADDR_NATIVE_RVA = 2, /* * ADDR_NATIVE_REGISTER: addr1 = register the var is stored in. */ ADDR_NATIVE_REGISTER = 3, /* * ADDR_NATIVE_REGREL: addr1 = register, addr2 = offset. */ ADDR_NATIVE_REGREL = 4, /* * ADDR_NATIVE_OFFSET: addr1 = offset from start of parent. */ ADDR_NATIVE_OFFSET = 5, /* * ADDR_NATIVE_REGREG: addr1 = reg low, addr2 = reg high. */ ADDR_NATIVE_REGREG = 6, /* * ADDR_NATIVE_REGSTK: addr1 = reg low, addr2 = reg stk, addr3 = offset. */ ADDR_NATIVE_REGSTK = 7, /* * ADDR_NATIVE_STKREG: addr1 = reg stk, addr2 = offset, addr3 = reg high. */ ADDR_NATIVE_STKREG = 8, /* * ADDR_BITFIELD: addr1 = field start, addr = field length. */ ADDR_BITFIELD = 9, /* * ADDR_NATIVE_SECTOFF: addr1 = section, addr = offset */ ADDR_NATIVE_ISECTOFFSET = 10 } CorSymAddrKind; typedef enum CorSymVarFlag { /* * VAR_IS_COMP_GEN: Variable is compiler generated. */ VAR_IS_COMP_GEN = 1 } CorSymVarFlag; /* ------------------------------------------------------------------------- * * Library definition * * Use the _SxS coclasses for tools designed to work with .NET Framework * 1.1 and above. On computers that only have version 1.0 installed, fall * back to the _deprecated coclasses if CoCreating the _SxS ones fails. * ------------------------------------------------------------------------- */ #ifndef INTEROPLIB [ uuid(7E348441-7E1F-380E-A0F6-22668F0F9E4B), version(1.0), helpstring("Common Language Runtime Symbol Store 1.0 Type Library") ] library CorSymLib { importlib("STDOLE2.TLB"); #endif // ndef INTEROPLIB [ uuid(108296C1-281E-11d3-BD22-0000F80849BD) ] coclass CorSymWriter_deprecated { [default] interface ISymUnmanagedWriter; }; [ uuid(108296C2-281E-11d3-BD22-0000F80849BD) ] coclass CorSymReader_deprecated { [default] interface ISymUnmanagedReader; }; [ uuid(AA544D41-28CB-11d3-BD22-0000F80849BD) ] coclass CorSymBinder_deprecated { [default] interface ISymUnmanagedBinder; }; [ uuid(0AE2DEB0-F901-478b-BB9F-881EE8066788) ] coclass CorSymWriter_SxS { [default] interface ISymUnmanagedWriter; }; [ uuid(0A3976C5-4529-4ef8-B0B0-42EED37082CD) ] coclass CorSymReader_SxS { [default] interface ISymUnmanagedReader; }; [ uuid(0A29FF9E-7F9C-4437-8B11-F424491E3931) ] coclass CorSymBinder_SxS { [default] interface ISymUnmanagedBinder; }; #ifndef INTEROPLIB }; #endif // ndef INTEROPLIB /* ------------------------------------------------------------------------- * * ISymUnmanagedBinder interface * ------------------------------------------------------------------------- */ [ object, uuid(AA544D42-28CB-11d3-BD22-0000F80849BD), pointer_default(unique) ] interface ISymUnmanagedBinder : IUnknown { /* * Given a metadata interface and a file name, returns the * correct ISymUnmanagedReader that will read the debugging symbols * associated with the module. * * This will only open the Pdb if it is next to the Exe. * This change has been made for security purposes * * If you need a more extensive search for the pdb * use ISymUnmanagedBinder2. */ HRESULT GetReaderForFile([in] IUnknown *importer, [in] const WCHAR *fileName, [in] const WCHAR *searchPath, [out, retval] ISymUnmanagedReader **pRetVal); /* * Given a metadata interface and a stream that contains * the symbol store, returns the correct ISymUnmanagedReader * that will read the debugging symbols from the given * symbol store. */ HRESULT GetReaderFromStream([in] IUnknown *importer, [in] IStream *pstream, [out,retval] ISymUnmanagedReader **pRetVal); }; typedef enum CorSymSearchPolicyAttributes { AllowRegistryAccess = 0x1, // query the registry for symbol search paths AllowSymbolServerAccess = 0x2, // access a symbol server AllowOriginalPathAccess = 0x4, // look at the path specified in Debug Directory AllowReferencePathAccess = 0x8 // look for PDB in the place where the exe is. } CorSymSearchPolicyAttributes; /* ------------------------------------------------------------------------- * * ISymUnmanagedBinder2 interface: QI from an ISymUnmanagedBinder * ------------------------------------------------------------------------- */ [ object, uuid(ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434), pointer_default(unique) ] interface ISymUnmanagedBinder2 : ISymUnmanagedBinder { /* * Given a metadata interface and a file name, returns the correct * ISymUnmanagedReader interface that will read the debugging symbols associated * with the module. * * This version of the function can search for the PDB in areas other than * right next to the module. * The search policy can be controlled by combining CorSymSearchPolicyAttributes * e.g AllowReferencePathAccess|AllowSymbolServerAccess will look for the pdb next * to the PE file and on a symbol server, but won't query the registry or use the path * in the PE file. * If a searchPath is provided, those directories will always be searched. */ HRESULT GetReaderForFile2([in] IUnknown *importer, [in] const WCHAR *fileName, [in] const WCHAR *searchPath, [in] ULONG32 searchPolicy, [out,retval] ISymUnmanagedReader **pRetVal); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedBinder3 interface: QI from an ISymUnmanagedBinder * ------------------------------------------------------------------------- */ [ object, uuid(28AD3D43-B601-4d26-8A1B-25F9165AF9D7), pointer_default(unique) ] interface ISymUnmanagedBinder3 : ISymUnmanagedBinder2 { /* * GetReaderFromCallback allows the user to implement supply via callback either an * IID_IDiaReadExeAtRVACallback or IID_IDiaReadExeAtOffsetCallback to obtain the * Debug directory information from memory. */ HRESULT GetReaderFromCallback([in] IUnknown *importer, [in] const WCHAR *fileName, [in] const WCHAR *searchPath, [in] ULONG32 searchPolicy, [in] IUnknown *callback, [out,retval] ISymUnmanagedReader **pRetVal); }; cpp_quote("static const int E_SYM_DESTROYED = MAKE_HRESULT(1, FACILITY_ITF, 0xdead);") [ object, uuid(969708D2-05E5-4861-A3B0-96E473CDF63F), pointer_default(unique) ] interface ISymUnmanagedDispose : IUnknown { /* * Calling this function will cause the underlying object to * release all internal references and return failure on any subsequent * method calls. */ HRESULT Destroy(); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedDocument interface * * Represents a document referenced by a symbol store. A document is defined * by an URL and a document type GUID. Using the URL and document type GUID, * one can locate the document however it is stored. Document source can * optionally be stored in the symbol store, and retrieved through this * interface. * ------------------------------------------------------------------------- */ [ object, uuid(40DE4037-7C81-3E1E-B022-AE1ABFF2CA08), pointer_default(unique) ] interface ISymUnmanagedDocument : IUnknown { /* * Return the URL for this document. */ HRESULT GetURL([in] ULONG32 cchUrl, [out] ULONG32 *pcchUrl, [out, size_is(cchUrl), length_is(*pcchUrl)] WCHAR szUrl[]); /* * Get the document type of this document. */ HRESULT GetDocumentType([out, retval] GUID* pRetVal); /* * Get the language id of this document. */ HRESULT GetLanguage([out, retval] GUID* pRetVal); /* * Get the language vendor of this document. */ HRESULT GetLanguageVendor([out, retval] GUID* pRetVal); /* * Get the check sum algorithm id. Returns a guid of all zeros if * there is no checksum. */ HRESULT GetCheckSumAlgorithmId([out, retval] GUID* pRetVal); /* * Get the check sum. */ HRESULT GetCheckSum([in] ULONG32 cData, [out] ULONG32 *pcData, [out, size_is(cData), length_is(*pcData)] BYTE data[]); /* * Given a line in this document that may or may not be a sequence * point, return the closest line that is a sequence point. */ HRESULT FindClosestLine([in] ULONG32 line, [out, retval] ULONG32* pRetVal); /* * Returns true if the document has source embedded in the * debugging symbols. */ HRESULT HasEmbeddedSource([out, retval] BOOL *pRetVal); /* * Returns the length, in bytes, of the embedded source. */ HRESULT GetSourceLength([out, retval] ULONG32* pRetVal); /* * Returns the embedded source into the given buffer. The buffer must * be large enough to hold the source. */ HRESULT GetSourceRange([in] ULONG32 startLine, [in] ULONG32 startColumn, [in] ULONG32 endLine, [in] ULONG32 endColumn, [in] ULONG32 cSourceBytes, [out] ULONG32 *pcSourceBytes, [out, size_is(cSourceBytes), length_is(*pcSourceBytes)] BYTE source[]); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedDocumentWriter interface * * Provides functions for writing to a document referenced by a symbol * store. * ------------------------------------------------------------------------- */ [ object, uuid(B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006), pointer_default(unique) ] interface ISymUnmanagedDocumentWriter : IUnknown { /* * Sets embedded source for a document being written. */ HRESULT SetSource([in] ULONG32 sourceSize, [in, size_is(sourceSize)] BYTE source[]); /* * Sets check sum info. */ HRESULT SetCheckSum([in] GUID algorithmId, [in] ULONG32 checkSumSize, [in, size_is(checkSumSize)] BYTE checkSum[]); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedMethod interface * * Represents a method within the symbol store. Provides access to only the * symbol-related attributes of a method, rather than type-related attributes. * ------------------------------------------------------------------------- */ [ object, uuid(B62B923C-B500-3158-A543-24F307A8B7E1), pointer_default(unique) ] interface ISymUnmanagedMethod : IUnknown { /* * Return the metadata token for this method. */ HRESULT GetToken([out, retval] mdMethodDef *pToken); /* * Get the count of sequence points within this method. */ HRESULT GetSequencePointCount([out, retval] ULONG32* pRetVal); /* * Get the root lexical scope within this method. * This scope encloses the entire method. */ HRESULT GetRootScope([out, retval] ISymUnmanagedScope** pRetVal); /* * Get the most enclosing lexical scope within this method that * encloses the given offset. This can be used to start * local variable searches. */ HRESULT GetScopeFromOffset([in] ULONG32 offset, [out, retval] ISymUnmanagedScope** pRetVal); /* * Given a position within a document, return the offset within * this method that cooresponds to the position. */ HRESULT GetOffset([in] ISymUnmanagedDocument* document, [in] ULONG32 line, [in] ULONG32 column, [out, retval] ULONG32* pRetVal); /* * Given a position in a document, return an array of start/end * offset paris that correspond to the ranges of IL that the * position covers within this method. The array is an array of * integers and is [start,end,start,end]. The number of range * pairs is the length of the array / 2. */ HRESULT GetRanges([in] ISymUnmanagedDocument* document, [in] ULONG32 line, [in] ULONG32 column, [in] ULONG32 cRanges, [out] ULONG32 *pcRanges, [out, size_is(cRanges), length_is(*pcRanges)] ULONG32 ranges[]); /* * Get the parameters for this method. The parameters are returned * in the order they are defined within the method's signature. */ HRESULT GetParameters([in] ULONG32 cParams, [out] ULONG32 *pcParams, [out, size_is(cParams), length_is(*pcParams)] ISymUnmanagedVariable* params[]); /* * Get the namespace that this method is defined within. */ HRESULT GetNamespace([out] ISymUnmanagedNamespace **pRetVal); /* * Get the start/end document positions for the source of this * method. The first array position is the start while the second * is the end. Returns true if positions were defined, false * otherwise. */ HRESULT GetSourceStartEnd([in] ISymUnmanagedDocument *docs[2], [in] ULONG32 lines[2], [in] ULONG32 columns[2], [out] BOOL *pRetVal); /* * Get all the sequence points within this method. */ HRESULT GetSequencePoints([in] ULONG32 cPoints, [out] ULONG32 *pcPoints, [in, size_is(cPoints)] ULONG32 offsets[], [in, size_is(cPoints)] ISymUnmanagedDocument* documents[], [in, size_is(cPoints)] ULONG32 lines[], [in, size_is(cPoints)] ULONG32 columns[], [in, size_is(cPoints)] ULONG32 endLines[], [in, size_is(cPoints)] ULONG32 endColumns[]); }; [ object, uuid(85E891DA-A631-4c76-ACA2-A44A39C46B8C), pointer_default(unique) ] interface ISymENCUnmanagedMethod : IUnknown { /* * Get the file name for the line associated with offset dwOffset. */ HRESULT GetFileNameFromOffset([in] ULONG32 dwOffset, [in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * Get the Line information associated with dwOffset. * If dwOffset is not a sequence point it is associated with the previous one. * pdwStartOffset provides the associated sequence point. */ HRESULT GetLineFromOffset([in] ULONG32 dwOffset, [out] ULONG32* pline, [out] ULONG32* pcolumn, [out] ULONG32* pendLine, [out] ULONG32* pendColumn, [out] ULONG32* pdwStartOffset); /* * Get the number of Documents that this method has lines in. */ HRESULT GetDocumentsForMethodCount([out, retval] ULONG32* pRetVal); /* * Get the documents this method has lines in. */ HRESULT GetDocumentsForMethod([in] ULONG32 cDocs, [out] ULONG32 *pcDocs, [in, size_is(cDocs)] ISymUnmanagedDocument* documents[]); /* * Get the smallest start line and largest end line, for the method, in a specific document. */ HRESULT GetSourceExtentInDocument([in] ISymUnmanagedDocument *document, [out] ULONG32* pstartLine, [out] ULONG32* pendLine); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedNamespace interface * * Represents a namespace. * ------------------------------------------------------------------------- */ [ object, uuid(0DFF7289-54F8-11d3-BD28-0000F80849BD), pointer_default(unique) ] interface ISymUnmanagedNamespace : IUnknown { /* * Get the name of this namespace. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * Get the children of this namespace. */ HRESULT GetNamespaces([in] ULONG32 cNameSpaces, [out] ULONG32 *pcNameSpaces, [out, size_is(cNameSpaces), length_is(*pcNameSpaces)] ISymUnmanagedNamespace* namespaces[]); /* * Return all variables defined at global scope within this namespace. */ HRESULT GetVariables([in] ULONG32 cVars, [out] ULONG32 *pcVars, [out, size_is(cVars), length_is(*pcVars)] ISymUnmanagedVariable *pVars[]); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedReader interface * * Represents a symbol reader. Provides access to documents, methods, and * variables within a symbol store. * ------------------------------------------------------------------------- */ [ object, uuid(B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5), pointer_default(unique) ] interface ISymUnmanagedReader : IUnknown { /* * Find a document. Language, vendor, and document type are optional. */ HRESULT GetDocument([in] WCHAR *url, [in] GUID language, [in] GUID languageVendor, [in] GUID documentType, [out, retval] ISymUnmanagedDocument** pRetVal); /* * Return an array of all the documents defined in the symbol store. */ HRESULT GetDocuments([in] ULONG32 cDocs, [out] ULONG32 *pcDocs, [out, size_is(cDocs), length_is(*pcDocs)] ISymUnmanagedDocument *pDocs[]); /* * Return the method that was specified as the user entry point * for the module, if any. This would be, perhaps, the user's main * method rather than compiler generated stubs before main. */ HRESULT GetUserEntryPoint([out, retval] mdMethodDef *pToken); /* * Get a symbol reader method given a method token. */ HRESULT GetMethod([in] mdMethodDef token, [out, retval] ISymUnmanagedMethod** pRetVal); /* * Get a symbol reader method given a method token and an E&C * version number. Version numbers start at 1 and are incremented * each time the method is changed due to an E&C operation. */ HRESULT GetMethodByVersion([in] mdMethodDef token, [in] int version, [out, retval] ISymUnmanagedMethod** pRetVal); /* * Return a non-local variable given its parent and name. */ HRESULT GetVariables([in] mdToken parent, [in] ULONG32 cVars, [out] ULONG32 *pcVars, [out, size_is(cVars), length_is(*pcVars)] ISymUnmanagedVariable *pVars[]); /* * Return all global variables. */ HRESULT GetGlobalVariables([in] ULONG32 cVars, [out] ULONG32 *pcVars, [out, size_is(cVars), length_is(*pcVars)] ISymUnmanagedVariable *pVars[]); /* * Given a position in a document, return the ISymUnmanagedMethod that * contains that position. */ HRESULT GetMethodFromDocumentPosition([in] ISymUnmanagedDocument* document, [in] ULONG32 line, [in] ULONG32 column, [out, retval] ISymUnmanagedMethod** pRetVal); /* * Gets a custom attribute based upon its name. Not to be * confused with Metadata custom attributes, these attributes are * held in the symbol store. */ HRESULT GetSymAttribute([in] mdToken parent, [in] WCHAR *name, [in] ULONG32 cBuffer, [out] ULONG32 *pcBuffer, [out, size_is(cBuffer), length_is(*pcBuffer)] BYTE buffer[]); /* * Get the namespaces defined at global scope within this symbol store. */ HRESULT GetNamespaces([in] ULONG32 cNameSpaces, [out] ULONG32 *pcNameSpaces, [out, size_is(cNameSpaces), length_is(*pcNameSpaces)] ISymUnmanagedNamespace* namespaces[]); /* * Initialize the symbol reader with the metadata importer interface * that this reader will be associated with, along with the filename * of the module. This can only be called once, and must be called * before any other reader methods are called. * * Note: you need only specify one of the filename or the pIStream, * not both. The searchPath parameter is optional. */ HRESULT Initialize([in] IUnknown *importer, [in] const WCHAR *filename, [in] const WCHAR *searchPath, [in] IStream *pIStream); /* * Update the existing symbol reader with a delta symbol store. This * is used in EnC scenarios as a way to update the symbol store to * match deltas to the original PE file. * * Only one of the filename or pIStream parameters need be specified. * If a filename is specified, the symbol store will be updated with * the symbols in that file. If a IStream is specified, the store will * be updated with the data from the IStream. */ HRESULT UpdateSymbolStore([in] const WCHAR *filename, [in] IStream *pIStream); /* * Update the existing symbol reader with a delta symbol * store. This is much like UpdateSymbolStore, but the given detla * acts as a complete replacement rather than an update. * * Only one of the filename or pIStream parameters need be specified. * If a filename is specified, the symbol store will be updated with * the symbols in that file. If a IStream is specified, the store will * be updated with the data from the IStream. */ HRESULT ReplaceSymbolStore([in] const WCHAR *filename, [in] IStream *pIStream); /* * Provides the on disk filename of the symbol store. */ HRESULT GetSymbolStoreFileName( [in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * Given a position in a document, return the ISymUnmanagedMethods that * contains that position. */ HRESULT GetMethodsFromDocumentPosition([in] ISymUnmanagedDocument* document, [in] ULONG32 line, [in] ULONG32 column, [in] ULONG32 cMethod, [out] ULONG32* pcMethod, [out, size_is(cMethod), length_is(*pcMethod)] ISymUnmanagedMethod* pRetVal[]); /* * Get the given version of the given document. * The document version starts at 1 and is incremented each time * the document is updated via UpdateSymbols. * bCurrent is true is this is the latest version of the document. */ HRESULT GetDocumentVersion([in] ISymUnmanagedDocument *pDoc, [out] int* version, [out] BOOL* pbCurrent); /* * The method version starts at 1 and is incremented each time * the method is recompiled. (This can happen without changes to the method.) */ HRESULT GetMethodVersion([in] ISymUnmanagedMethod* pMethod, [out] int* version); }; // // ISymUnmanagedSourceServerModule // // QI for this interface from an ISymUnmanagedReader [ object, uuid(997DD0CC-A76F-4c82-8D79-EA87559D27AD), pointer_default(unique) ] interface ISymUnmanagedSourceServerModule : IUnknown { // returns the source server data for the module // caller must free using CoTaskMemFree() HRESULT GetSourceServerData( [out] ULONG* pDataByteCount, [out, size_is (, *pDataByteCount)] BYTE** ppData); } // QI for this interface from an ISymUnmanagedReader [ object, uuid(E502D2DD-8671-4338-8F2A-FC08229628C4), pointer_default(unique) ] interface ISymUnmanagedENCUpdate : IUnknown { // UpdateSymbolStore2: // Line deltas allow a compiler to omit functions that have not been modified from // the pdb stream provided the line information meets the following condition. // The correct line information can be determined with the old pdb line info and // one delta for all lines in the function. // typedef struct _SYMLINEDELTA { mdMethodDef mdMethod; INT32 delta; } SYMLINEDELTA; HRESULT UpdateSymbolStore2([in] IStream *pIStream, [in] SYMLINEDELTA* pDeltaLines, [in] ULONG cDeltaLines); HRESULT GetLocalVariableCount([in] mdMethodDef mdMethodToken, [out] ULONG *pcLocals); HRESULT GetLocalVariables([in] mdMethodDef mdMethodToken, [in] ULONG cLocals, [out, size_is(cLocals), length_is(*pceltFetched)] ISymUnmanagedVariable *rgLocals[], [out] ULONG *pceltFetched); // Perf: Allow method boundaries to be computed before the first // UpdateSymbolStore2. HRESULT InitializeForEnc(); // // This allows updating the line info for a method that has not been recompiled, // but whose lines have moved independently. A delta for each statement is allowed. // HRESULT UpdateMethodLines([in] mdMethodDef mdMethodToken, [in, size_is(cDeltas)] INT32* pDeltas, [in] ULONG cDeltas); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedReaderSymbolSearchInfo interface * ------------------------------------------------------------------------- */ // QI for this interface from an ISymUnmanagedReader [ object, uuid(20D9645D-03CD-4e34-9C11-9848A5B084F1), pointer_default(unique) ] interface ISymUnmanagedReaderSymbolSearchInfo : IUnknown { HRESULT GetSymbolSearchInfoCount([out] ULONG32 *pcSearchInfo); HRESULT GetSymbolSearchInfo([in] ULONG32 cSearchInfo, [out] ULONG32 *pcSearchInfo, [out, size_is(cSearchInfo), length_is(*pcSearchInfo)] ISymUnmanagedSymbolSearchInfo **rgpSearchInfo); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedScope interface * * Represents a lexical scope within a method. * ------------------------------------------------------------------------- */ [ object, uuid(68005D0F-B8E0-3B01-84D5-A11A94154942), pointer_default(unique) ] interface ISymUnmanagedScope : IUnknown { /* * Get the method that contains this scope. */ HRESULT GetMethod([out, retval] ISymUnmanagedMethod** pRetVal); /* * Get the parent scope of this scope. */ HRESULT GetParent([out, retval] ISymUnmanagedScope** pRetVal); /* * Get the children of this scope. */ HRESULT GetChildren([in] ULONG32 cChildren, [out] ULONG32 *pcChildren, [out, size_is(cChildren), length_is(*pcChildren)] ISymUnmanagedScope* children[]); /* * Get the start offset for this scope, */ HRESULT GetStartOffset([out, retval] ULONG32* pRetVal); /* * Get the end offset for this scope. */ HRESULT GetEndOffset([out, retval] ULONG32* pRetVal); /* * Get a count of the number of local variables defined within this * scope. */ HRESULT GetLocalCount([out, retval] ULONG32 *pRetVal); /* * Get the local variables defined within this scope. */ HRESULT GetLocals([in] ULONG32 cLocals, [out] ULONG32 *pcLocals, [out, size_is(cLocals), length_is(*pcLocals)] ISymUnmanagedVariable* locals[]); /* * Get the namespaces that are being "used" within this scope. */ HRESULT GetNamespaces([in] ULONG32 cNameSpaces, [out] ULONG32 *pcNameSpaces, [out, size_is(cNameSpaces), length_is(*pcNameSpaces)] ISymUnmanagedNamespace* namespaces[]); }; [ object, uuid(48B25ED8-5BAD-41bc-9CEE-CD62FABC74E9), pointer_default(unique) ] interface ISymUnmanagedConstant : IUnknown { /* * Get the name of this constant. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); HRESULT GetValue(VARIANT* pValue); HRESULT GetSignature([in] ULONG32 cSig, [out] ULONG32 *pcSig, [out, size_is(cSig), length_is(*pcSig)] BYTE sig[]); }; /* * QI for this interface from an ISymUnmanagedScope. */ [ object, uuid(AE932FBA-3FD8-4dba-8232-30A2309B02DB), pointer_default(unique) ] interface ISymUnmanagedScope2 : ISymUnmanagedScope { /* * Get a count of the number of constants defined within this * scope. */ HRESULT GetConstantCount([out, retval] ULONG32 *pRetVal); /* * Get the local constants defined within this scope. */ HRESULT GetConstants([in] ULONG32 cConstants, [out] ULONG32 *pcConstants, [out, size_is(cConstants), length_is(*pcConstants)] ISymUnmanagedConstant* constants[]); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedVariable interface * * Represents a variable--a parameter, a local variable, or a field. * ------------------------------------------------------------------------- */ [ object, uuid(9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB), pointer_default(unique) ] interface ISymUnmanagedVariable : IUnknown { /* * Get the name of this variable. */ HRESULT GetName([in] ULONG32 cchName, [out] ULONG32 *pcchName, [out, size_is(cchName), length_is(*pcchName)] WCHAR szName[]); /* * Get the attribute flags for this variable. */ HRESULT GetAttributes([out, retval] ULONG32* pRetVal); /* * Get the signature of this variable. */ HRESULT GetSignature([in] ULONG32 cSig, [out] ULONG32 *pcSig, [out, size_is(cSig), length_is(*pcSig)] BYTE sig[]); /* * Get the kind of address of this variable * The retval will be one of the CorSymAddrKind constants. */ HRESULT GetAddressKind([out, retval] ULONG32* pRetVal); /* * Get the first address field for this variable. Its meaning depends * on the address kind. */ HRESULT GetAddressField1([out, retval] ULONG32* pRetVal); /* * Get the second address field for this variable. Its meaning depends * on the address kind. */ HRESULT GetAddressField2([out, retval] ULONG32* pRetVal); /* * Get the third address field for this variable. Its meaning depends * on the address kind. */ HRESULT GetAddressField3([out, retval] ULONG32* pRetVal); /* * Get the start offset of this variable within its parent. If this is * a local variable within a scope, this will fall within the offsets * defined for the scope. */ HRESULT GetStartOffset([out, retval] ULONG32* pRetVal); /* * Get the end offset of this variable within its parent. If this is * a local variable within a scope, this will fall within the offsets * defined for the scope. */ HRESULT GetEndOffset([out, retval] ULONG32* pRetVal); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedSymbolSearchInfo interface * ------------------------------------------------------------------------- */ [ object, uuid(F8B3534A-A46B-4980-B520-BEC4ACEABA8F), pointer_default(unique) ] interface ISymUnmanagedSymbolSearchInfo : IUnknown { HRESULT GetSearchPathLength([out] ULONG32 *pcchPath); HRESULT GetSearchPath([in] ULONG32 cchPath, [out] ULONG32 *pcchPath, [out, size_is(cchPath), length_is(*pcchPath)] WCHAR szPath[]); HRESULT GetHRESULT([out] HRESULT *phr); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedWriter interface * * Represents a symbol writer. Provides methods to define documents, * sequence points, lexical scopes, and variables. * ------------------------------------------------------------------------- */ [ object, uuid(ED14AA72-78E2-4884-84E2-334293AE5214), pointer_default(unique) ] interface ISymUnmanagedWriter : IUnknown { /* * Define a source document. Guid's will be provided for languages, * vendors, and document types that we currently know about. */ HRESULT DefineDocument([in] const WCHAR *url, [in] const GUID *language, [in] const GUID *languageVendor, [in] const GUID *documentType, [out, retval] ISymUnmanagedDocumentWriter** pRetVal); /* * Define the method that the user has defined as their entry point * for this module. This would be, perhaps, the user's main method * rather than compiler generated stubs before main. */ HRESULT SetUserEntryPoint([in] mdMethodDef entryMethod); /* * Open a method to emit symbol information into. The given method * becomes the current method for calls do define sequence points, * parameters and lexical scopes. There is an implicit lexical * scope around the entire method. Re-opening a method that has * been previously closed effectivley erases any previously * defined symbols for that method. * * There can be only one open method at a time. */ HRESULT OpenMethod([in] mdMethodDef method); /* * Close the current method. Once a method is closed, no more * symbols can be defined within it. */ HRESULT CloseMethod(); /* * Open a new lexical scope in the current method. The scope * becomes the new current scope and is effectivley pushed onto a * stack of scopes. startOffset is the offset, in bytes from the * beginning of the method, of the first instruction in the * lexical scope. Scopes must form a hierarchy. Siblings are not * allowed to overlap. * * OpenScope returns an opaque scope id that can be used with * SetScopeRange to define a scope's start/end offset at a later * time. In this case, the offsets passed to OpenScope and * CloseScope are ignored. * * Note: scope id's are only valid in the current method. */ HRESULT OpenScope([in] ULONG32 startOffset, [out, retval] ULONG32* pRetVal); /* * Close the current lexical scope. Once a scope is closed no more * variables can be defined within it. endOffset points past the * last instruction in the scope. */ HRESULT CloseScope([in] ULONG32 endOffset); /* * Define the offset range for a given lexical scope. */ HRESULT SetScopeRange([in] ULONG32 scopeID, [in] ULONG32 startOffset, [in] ULONG32 endOffset); /* * Define a single variable in the current lexical * scope. startOffset and endOffset are optional. If 0, then they * are ignored and the variable is defined over the entire * scope. If non-zero, then they must fall within the offsets of * the current scope. This can be called multiple times for a * variable of the same name that has multiple homes throughout a * scope. (Note: start/end offsets must not overlap in such a * case.) */ HRESULT DefineLocalVariable([in] const WCHAR *name, [in] ULONG32 attributes, [in] ULONG32 cSig, [in, size_is(cSig)] unsigned char signature[], [in] ULONG32 addrKind, [in] ULONG32 addr1, [in] ULONG32 addr2, [in] ULONG32 addr3, [in] ULONG32 startOffset, [in] ULONG32 endOffset); /* * Define a single parameter in the current method. The type of * each parameter is taken from its position (sequence) within the * method's signature. * * Note: if parameters are defined in the metadata for a given * method, then clearly one would not have to define them again * with calls to this method. The symbol readers will have to be * smart enough to check the normal metadata for these first then * fall back to the symbol store. */ HRESULT DefineParameter([in] const WCHAR *name, [in] ULONG32 attributes, [in] ULONG32 sequence, [in] ULONG32 addrKind, [in] ULONG32 addr1, [in] ULONG32 addr2, [in] ULONG32 addr3); /* * Define a single variable not within a method. This is used for * certain fields in classes, bitfields, etc. */ HRESULT DefineField([in] mdTypeDef parent, [in] const WCHAR *name, [in] ULONG32 attributes, [in] ULONG32 cSig, [in, size_is(cSig)] unsigned char signature[], [in] ULONG32 addrKind, [in] ULONG32 addr1, [in] ULONG32 addr2, [in] ULONG32 addr3); /* * Define a single global variable. */ HRESULT DefineGlobalVariable([in] const WCHAR *name, [in] ULONG32 attributes, [in] ULONG32 cSig, [in, size_is(cSig)] unsigned char signature[], [in] ULONG32 addrKind, [in] ULONG32 addr1, [in] ULONG32 addr2, [in] ULONG32 addr3); /* * Close will close the ISymUnmanagedWriter and commit the symbols * to the symbol store. The ISymUnmanagedWriter becomes invalid * after this call for further updates. */ HRESULT Close(); /* * Defines a custom attribute based upon its name. Not to be * confused with Metadata custom attributes, these attributes are * held in the symbol store. */ HRESULT SetSymAttribute([in] mdToken parent, [in] const WCHAR *name, [in] ULONG32 cData, [in, size_is(cData)] unsigned char data[]); /* * Opens a new namespace. Call this before defining methods or * variables that live within a namespace. Namespaces can be nested. */ HRESULT OpenNamespace([in] const WCHAR *name); /* * Close the most recently opened namespace. */ HRESULT CloseNamespace(); /* * Specifies that the given, fully qualified namespace name is * being used within the currently open lexical scope. Closing the * current scope will also stop using the namespace, and the * namespace will be in use in all scopes that inherit from the * currently open scope. */ HRESULT UsingNamespace([in] const WCHAR *fullName); /* * Specifies the true start and end of a method within a source * file. Use this to specify the extent of a method independently * of what sequence points exist within the method. */ HRESULT SetMethodSourceRange([in] ISymUnmanagedDocumentWriter *startDoc, [in] ULONG32 startLine, [in] ULONG32 startColumn, [in] ISymUnmanagedDocumentWriter *endDoc, [in] ULONG32 endLine, [in] ULONG32 endColumn); /* * Sets the metadata emitter interface that this writer will be * associated with. Also sets the output filename of where the * debugging symbols will be written. This can only be called once, * and must be called before any other writer methods are called. * * Some writers may require a filename, while others may not. A * filename can always be passed to this method, however, with * no ill effects on writers that do not use it. * * The pIStream parameter is optional. If specified, the symbol * writer will emit the symbols into the given IStream rather than * to the file specified in filename. * * The fFullBuild parameter indicates to the symbol writer whether * this is a full build or an incremental build. */ HRESULT Initialize([in] IUnknown *emitter, [in] const WCHAR *filename, [in] IStream *pIStream, [in] BOOL fFullBuild); /* * Returns the necessary info for a compiler to write the * necessary debug directory entry into the PE header. * * pIDD should point to a IMAGE_DEBUG_DIRECTORY that the symbol * writer will fill out. All fields except for TimeDateStamp and * PointerToRawData will be filled out by the symbol writer. (The * compiler is responsible for setting TimeDateStamp and * PointerToRawData appropiatley.) * * data should point to a buffer large enough to hold the debug * data for the symbol store. * * A compiler should call this method, then emit the data blob to * the PE file and set the PointerToRawData field in the * IMAGE_DEBUG_DIRECTORY to point to the emitted data. Then, the * IMAGE_DEBUG_DIRECTORY should be written to the PE file. The * compiler should also set the TimeDateStamp field to equal the * TimeDateStamp of the PE file being generated. */ HRESULT GetDebugInfo([in, out] IMAGE_DEBUG_DIRECTORY *pIDD, [in] DWORD cData, [out] DWORD *pcData, [out, size_is(cData), length_is(*pcData)] BYTE data[]); /* * Define a group of sequence points within the current method. * Each line/column defines the start of a statement within a * method. Each end line/column defines the end of a statement * with a method. (End line/column is optional.) The arrays should * be sorted by offset. The offset is always the offset from the * start of the method, in bytes. */ HRESULT DefineSequencePoints([in] ISymUnmanagedDocumentWriter* document, [in] ULONG32 spCount, [in, size_is(spCount)] ULONG32 offsets[], [in, size_is(spCount)] ULONG32 lines[], [in, size_is(spCount)] ULONG32 columns[], [in, size_is(spCount)] ULONG32 endLines[], [in, size_is(spCount)] ULONG32 endColumns[]); /* * This method tells the symbol writer that a metadata token has * been remapped as the metadata was emitted. If the symbol writer * has stored the old token within the symbol store, it must * either update the stored token to the new value, or persist the * map for the corresponding symbol reader to remap during the * read phase. */ HRESULT RemapToken([in] mdToken oldToken, [in] mdToken newToken); /* * Same as Initialize except that the final path name is the path string to * name the final location of the pdb file. This is used in build environments in * which the pdb is built in a temporary location and moved when the build is * complete. */ HRESULT Initialize2([in] IUnknown *emitter, [in] const WCHAR *tempfilename, [in] IStream *pIStream, [in] BOOL fFullBuild, [in] const WCHAR *finalfilename); /* * Defines a name for a constant value. */ HRESULT DefineConstant( [in] const WCHAR *name, [in] VARIANT value, [in] ULONG32 cSig, [in, size_is(cSig)] unsigned char signature[]); /* * Abort will close the ISymUnmanagedWriter without committing the symbols * to the symbol store. The ISymUnmanagedWriter becomes invalid * after this call for further updates. */ HRESULT Abort(); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedWriter2 interface * ------------------------------------------------------------------------- */ [ object, uuid(0B97726E-9E6D-4f05-9A26-424022093CAA), pointer_default(unique) ] interface ISymUnmanagedWriter2 : ISymUnmanagedWriter { /* * Define a single variable in the current lexical * scope. startOffset and endOffset are optional. If 0, then they * are ignored and the variable is defined over the entire * scope. If non-zero, then they must fall within the offsets of * the current scope. This can be called multiple times for a * variable of the same name that has multiple homes throughout a * scope. (Note: start/end offsets must not overlap in such a * case.) */ HRESULT DefineLocalVariable2([in] const WCHAR *name, [in] ULONG32 attributes, [in] mdSignature sigToken, [in] ULONG32 addrKind, [in] ULONG32 addr1, [in] ULONG32 addr2, [in] ULONG32 addr3, [in] ULONG32 startOffset, [in] ULONG32 endOffset); /* * Define a single global variable. */ HRESULT DefineGlobalVariable2([in] const WCHAR *name, [in] ULONG32 attributes, [in] mdSignature sigToken, [in] ULONG32 addrKind, [in] ULONG32 addr1, [in] ULONG32 addr2, [in] ULONG32 addr3); /* * Defines a name for a constant value. */ HRESULT DefineConstant2( [in] const WCHAR *name, [in] VARIANT value, [in] mdSignature sigToken); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedWriter3 interface * ------------------------------------------------------------------------- */ [ object, uuid(12F1E02C-1E05-4B0E-9468-EBC9D1BB040F), pointer_default(unique) ] interface ISymUnmanagedWriter3 : ISymUnmanagedWriter2 { /* * Open a method, and also provide its real section offset in image */ HRESULT OpenMethod2( [in] mdMethodDef method, [in] ULONG32 isect, [in] ULONG32 offset); /* * Commit the changes written so far to the stream */ HRESULT Commit(); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedWriter4 interface * ------------------------------------------------------------------------- */ [ object, uuid(BC7E3F53-F458-4C23-9DBD-A189E6E96594), pointer_default(unique) ] interface ISymUnmanagedWriter4 : ISymUnmanagedWriter3 { /* * Functions the same as ISymUnmanagedWriter::GetDebugInfo with the exception * that the path string is padded with zeros following the terminating null * character to make the string data a fixed size of MAX_PATH. Padding is only * given if the path string length itself is less than MAX_PATH. * * This makes writing tools that difference PE files easier. */ HRESULT GetDebugInfoWithPadding([in, out] IMAGE_DEBUG_DIRECTORY *pIDD, [in] DWORD cData, [out] DWORD *pcData, [out, size_is(cData), length_is(*pcData)] BYTE data[]); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedWriter5 interface * ------------------------------------------------------------------------- */ [ object, uuid(DCF7780D-BDE9-45DF-ACFE-21731A32000C), pointer_default(unique) ] interface ISymUnmanagedWriter5 : ISymUnmanagedWriter4 { /* * Open a special custom data section to emit token to source span mapping * information into. Opening this section while a method is already open * or vice versa is an error. */ HRESULT OpenMapTokensToSourceSpans(); /* * Close the special custom data section for token to source span mapping * information. Once it is closed no more mapping information can be added. */ HRESULT CloseMapTokensToSourceSpans(); /* * Maps the given metadata token to the given source line span in the specified * source file. * * Must be called between calls to OpenMapTokensToSourceSpans() and * CloseMapTokensToSourceSpans(). */ HRESULT MapTokenToSourceSpan([in] mdToken token, [in] ISymUnmanagedDocumentWriter* document, [in] ULONG32 line, [in] ULONG32 column, [in] ULONG32 endLine, [in] ULONG32 endColumn); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedReader interface * ------------------------------------------------------------------------- */ [ object, uuid(A09E53B2-2A57-4cca-8F63-B84F7C35D4AA), pointer_default(unique) ] interface ISymUnmanagedReader2 : ISymUnmanagedReader { /* * Get a symbol reader method given a method token and an E&C * version number. Version numbers start at 1 and are incremented * each time the method is changed due to an E&C operation. */ HRESULT GetMethodByVersionPreRemap([in] mdMethodDef token, [in] int version, [out, retval] ISymUnmanagedMethod** pRetVal); /* * Gets a custom attribute based upon its name. Not to be * confused with Metadata custom attributes, these attributes are * held in the symbol store. */ HRESULT GetSymAttributePreRemap([in] mdToken parent, [in] WCHAR *name, [in] ULONG32 cBuffer, [out] ULONG32 *pcBuffer, [out, size_is(cBuffer), length_is(*pcBuffer)] BYTE buffer[]); /* * Gets every method that has line information in the provided Document. */ HRESULT GetMethodsInDocument([in] ISymUnmanagedDocument *document, [in] ULONG32 cMethod, [out] ULONG32* pcMethod, [out, size_is(cMethod), length_is(*pcMethod)] ISymUnmanagedMethod* pRetVal[]); }; /* ------------------------------------------------------------------------- * * ISymNGenWriter interface * ------------------------------------------------------------------------- */ [ object, uuid(d682fd12-43de-411c-811b-be8404cea126), pointer_default(unique) ] interface ISymNGenWriter : IUnknown { /* * Add a new public symbol to the NGEN PDB. */ HRESULT AddSymbol([in] BSTR pSymbol, [in] USHORT iSection, [in] ULONGLONG rva); /* * Adds a new section to the NGEN PDB. */ HRESULT AddSection([in] USHORT iSection, [in] USHORT flags, [in] long offset, [in] long cb); }; /* ------------------------------------------------------------------------- * * ISymNGenWriter2 interface * ------------------------------------------------------------------------- */ [ object, local, uuid(B029E51B-4C55-4fe2-B993-9F7BC1F10DB4), pointer_default(unique) ] interface ISymNGenWriter2 : ISymNGenWriter { HRESULT OpenModW([in] LPCWSTR wszModule, [in] LPCWSTR wszObjFile, [out] BYTE** ppmod); HRESULT CloseMod([in] BYTE* pmod); HRESULT ModAddSymbols([in] BYTE* pmod, [in] BYTE* pbSym, [in] long cb); HRESULT ModAddSecContribEx( [in] BYTE* pmod, [in] USHORT isect, [in] long off, [in] long cb, [in] ULONG dwCharacteristics, [in] DWORD dwDataCrc, [in] DWORD dwRelocCrc); HRESULT QueryPDBNameExW( [out, size_is(cchMax)] WCHAR wszPDB[], [in] SIZE_T cchMax); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedAsyncPropertiesWriter interface * * Allows definition of optional async method information per method symbol. * Must use with an opened method (i.e. between calls to ISymUnmanagedWriter's * OpenMethod and CloseMethod methods). * ------------------------------------------------------------------------- */ [ object, uuid(FC073774-1739-4232-BD56-A027294BEC15), pointer_default(unique) ] interface ISymUnmanagedAsyncMethodPropertiesWriter : IUnknown { /* * Sets the starting method that initiates the async operation. * * When performing a step-out of an async method, if the caller matches * the kickoff method, we will step out synchronously. Otherwise, an * async step-out will occur. * * This works in C#/VB because there is an initial method stub that * creates the state machine object and starts if off, hence "kickoff" * Still have to determine if this will work with F#. */ HRESULT DefineKickoffMethod([in] mdToken kickoffMethod); /* * Sets the IL offset for the compiler generated catch handler that wraps * an async method. * * The IL offset of the generated catch is used by the debugger to handle * the catch as though it were non-user code even though it may occur in * a user code method. In particular it is used in response to a * CatchHandlerFound exception event. */ HRESULT DefineCatchHandlerILOffset([in] ULONG32 catchHandlerOffset); /* * Define a group of async scopes within the current method. * * Each yield offset matches an await's return instruction, * identifying a potential yield. Each breakpointMethod/breakpointOffset * pair tells us where the asynchronous operation will resume * (which may be in a different method). */ HRESULT DefineAsyncStepInfo([in] ULONG32 count, [in, size_is(count)] ULONG32 yieldOffsets[], [in, size_is(count)] ULONG32 breakpointOffset[], [in, size_is(count)] mdToken breakpointMethod[]); }; /* ------------------------------------------------------------------------- * * ISymUnmanagedAsyncMethod interface * * This interface is the reading complement to * ISymUnmanangedAsyncMethodPropertiesWriter * ------------------------------------------------------------------------- */ [ object, uuid(B20D55B3-532E-4906-87E7-25BD5734ABD2), pointer_default(unique) ] interface ISymUnmanagedAsyncMethod : IUnknown { /* * Checks if the method has asynch information or not. * * If this method returns FALSE then it is invalid to call any * other methods in this interface. They will all return * E_UNEXPECTED in this case. */ HRESULT IsAsyncMethod([out, retval] BOOL* pRetVal); /* * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineKickoffMethod */ HRESULT GetKickoffMethod([out, retval] mdToken* kickoffMethod); /* * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineCatchHandlerILOffset */ HRESULT HasCatchHandlerILOffset([out, retval] BOOL* pRetVal); /* * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineCatchHandlerILOffset */ HRESULT GetCatchHandlerILOffset([out, retval] ULONG32* pRetVal); /* * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineAsyncStepInfo */ HRESULT GetAsyncStepInfoCount([out, retval] ULONG32* pRetVal); /* * See ISymUnmanagedAsyncMethodPropertiesWriter::DefineAsyncStepInfo */ HRESULT GetAsyncStepInfo([in] ULONG32 cStepInfo, [out] ULONG32 *pcStepInfo, [in, size_is(cStepInfo)] ULONG32 yieldOffsets[], [in, size_is(cStepInfo)] ULONG32 breakpointOffset[], [in, size_is(cStepInfo)] mdToken breakpointMethod[]); }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cortypeinfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // This describes information about the COM+ primitive types // // Note: This file gets parsed by the Mono IL Linker (https://github.com/mono/linker/) which may throw an exception during parsing. // Specifically, this (https://github.com/mono/linker/blob/master/corebuild/integration/ILLink.Tasks/CreateRuntimeRootDescriptorFile.cs) will try to // parse this header, and it may throw an exception while doing that. If you edit this file and get a build failure on msbuild.exe D:\repos\coreclr\build.proj // you might want to check out the parser linked above. // #define NO_SIZE ((BYTE)-1) // TYPEINFO(type (CorElementType), namespace, class, size, gcType, isArray,isPrim, isFloat,isModifier,isGenVariable) TYPEINFO(ELEMENT_TYPE_END, NULL, NULL, NO_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x00 TYPEINFO(ELEMENT_TYPE_VOID, "System", "Void", 0, TYPE_GC_NONE, false, true, false, false, false) // 0x01 TYPEINFO(ELEMENT_TYPE_BOOLEAN, "System", "Boolean", 1, TYPE_GC_NONE, false, true, false, false, false) // 0x02 TYPEINFO(ELEMENT_TYPE_CHAR, "System", "Char", 2, TYPE_GC_NONE, false, true, false, false, false) // 0x03 TYPEINFO(ELEMENT_TYPE_I1, "System", "SByte", 1, TYPE_GC_NONE, false, true, false, false, false) // 0x04 TYPEINFO(ELEMENT_TYPE_U1, "System", "Byte", 1, TYPE_GC_NONE, false, true, false, false, false) // 0x05 TYPEINFO(ELEMENT_TYPE_I2, "System", "Int16", 2, TYPE_GC_NONE, false, true, false, false, false) // 0x06 TYPEINFO(ELEMENT_TYPE_U2, "System", "UInt16", 2, TYPE_GC_NONE, false, true, false, false, false) // 0x07 TYPEINFO(ELEMENT_TYPE_I4, "System", "Int32", 4, TYPE_GC_NONE, false, true, false, false, false) // 0x08 TYPEINFO(ELEMENT_TYPE_U4, "System", "UInt32", 4, TYPE_GC_NONE, false, true, false, false, false) // 0x09 TYPEINFO(ELEMENT_TYPE_I8, "System", "Int64", 8, TYPE_GC_NONE, false, true, false, false, false) // 0x0a TYPEINFO(ELEMENT_TYPE_U8, "System", "UInt64", 8, TYPE_GC_NONE, false, true, false, false, false) // 0x0b TYPEINFO(ELEMENT_TYPE_R4, "System", "Single", 4, TYPE_GC_NONE, false, true, true, false, false) // 0x0c TYPEINFO(ELEMENT_TYPE_R8, "System", "Double", 8, TYPE_GC_NONE, false, true, true, false, false) // 0x0d TYPEINFO(ELEMENT_TYPE_STRING, "System", "String", TARGET_POINTER_SIZE, TYPE_GC_REF, false, false, false, false, false) // 0x0e TYPEINFO(ELEMENT_TYPE_PTR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_NONE, false, false, false, true, false) // 0x0f TYPEINFO(ELEMENT_TYPE_BYREF, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_BYREF, false, false, false, true, false) // 0x10 TYPEINFO(ELEMENT_TYPE_VALUETYPE, NULL, NULL, NO_SIZE, TYPE_GC_OTHER, false, false, false, false, false) // 0x11 TYPEINFO(ELEMENT_TYPE_CLASS, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_REF, false, false, false, false, false) // 0x12 TYPEINFO(ELEMENT_TYPE_VAR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_OTHER, false, false, false, false, true) // 0x13 TYPEINFO(ELEMENT_TYPE_ARRAY, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_REF, true, false, false, true, false) // 0x14 TYPEINFO(ELEMENT_TYPE_GENERICINST, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_OTHER, false, false, false, false, false) // 0x15 TYPEINFO(ELEMENT_TYPE_TYPEDBYREF, "System", "TypedReference",2*TARGET_POINTER_SIZE,TYPE_GC_BYREF, false, false, false, false, false) // 0x16 TYPEINFO(ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED, NULL,NULL, NO_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x17 (unsupported, not in the ECMA spec) TYPEINFO(ELEMENT_TYPE_I, "System", "IntPtr", TARGET_POINTER_SIZE, TYPE_GC_NONE, false, true, false, false, false) // 0x18 TYPEINFO(ELEMENT_TYPE_U, "System", "UIntPtr", TARGET_POINTER_SIZE, TYPE_GC_NONE, false, true, false, false, false) // 0x19 TYPEINFO(ELEMENT_TYPE_R_UNSUPPORTED,NULL, NULL, NO_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x1a (unsupported, not in the ECMA spec) TYPEINFO(ELEMENT_TYPE_FNPTR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_NONE, false, false, false, false, false) // 0x1b TYPEINFO(ELEMENT_TYPE_OBJECT, "System", "Object", TARGET_POINTER_SIZE, TYPE_GC_REF, false, false, false, false, false) // 0x1c TYPEINFO(ELEMENT_TYPE_SZARRAY, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_REF, true, false, false, true, false) // 0x1d TYPEINFO(ELEMENT_TYPE_MVAR, NULL, NULL, TARGET_POINTER_SIZE, TYPE_GC_OTHER, false, false, false, false, true) // x01e TYPEINFO(ELEMENT_TYPE_CMOD_REQD, NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x1f TYPEINFO(ELEMENT_TYPE_CMOD_OPT, NULL, NULL, 0, TYPE_GC_NONE, false, false, false, false, false) // 0x20 TYPEINFO(ELEMENT_TYPE_INTERNAL, NULL, NULL, 0, TYPE_GC_OTHER, false, false, false, false, false) // 0x21 ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/crosscomp.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // crosscomp.h - cross-compilation enablement structures. // #pragma once #if (!defined(HOST_64BIT) && defined(TARGET_64BIT)) || (defined(HOST_64BIT) && !defined(TARGET_64BIT)) #define CROSSBITNESS_COMPILE #endif // Target platform-specific library naming // #ifdef TARGET_WINDOWS #define MAKE_TARGET_DLLNAME_W(name) name W(".dll") #define MAKE_TARGET_DLLNAME_A(name) name ".dll" #else // TARGET_WINDOWS #ifdef TARGET_OSX #define MAKE_TARGET_DLLNAME_W(name) W("lib") name W(".dylib") #define MAKE_TARGET_DLLNAME_A(name) "lib" name ".dylib" #else #define MAKE_TARGET_DLLNAME_W(name) W("lib") name W(".so") #define MAKE_TARGET_DLLNAME_A(name) "lib" name ".so" #endif #endif // TARGET_WINDOWS #ifdef UNICODE #define MAKE_TARGET_DLLNAME(name) MAKE_TARGET_DLLNAME_W(name) #else #define MAKE_TARGET_DLLNAME(name) MAKE_TARGET_DLLNAME_A(name) #endif #if !defined(HOST_ARM) && defined(TARGET_ARM) // Non-ARM Host managing ARM related code #ifndef CROSS_COMPILE #define CROSS_COMPILE #endif #define ARM_MAX_BREAKPOINTS 8 #define ARM_MAX_WATCHPOINTS 1 #ifndef CONTEXT_UNWOUND_TO_CALL #define CONTEXT_UNWOUND_TO_CALL 0x20000000 #endif #if !defined(HOST_ARM64) typedef struct _NEON128 { ULONGLONG Low; LONGLONG High; } NEON128, *PNEON128; #endif // !defined(HOST_ARM64) typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { // // Control flags. // DWORD ContextFlags; // // Integer registers // DWORD R0; DWORD R1; DWORD R2; DWORD R3; DWORD R4; DWORD R5; DWORD R6; DWORD R7; DWORD R8; DWORD R9; DWORD R10; DWORD R11; DWORD R12; // // Control Registers // DWORD Sp; DWORD Lr; DWORD Pc; DWORD Cpsr; // // Floating Point/NEON Registers // DWORD Fpscr; DWORD Padding; union { NEON128 Q[16]; ULONGLONG D[32]; DWORD S[32]; }; // // Debug registers // DWORD Bvr[ARM_MAX_BREAKPOINTS]; DWORD Bcr[ARM_MAX_BREAKPOINTS]; DWORD Wvr[ARM_MAX_WATCHPOINTS]; DWORD Wcr[ARM_MAX_WATCHPOINTS]; DWORD Padding2[2]; } T_CONTEXT, *PT_CONTEXT; // // Define function table entry - a function table entry is generated for // each frame function. // #if defined(HOST_WINDOWS) typedef struct _T_RUNTIME_FUNCTION { DWORD BeginAddress; DWORD UnwindData; } T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; #else // HOST_WINDOWS #define T_RUNTIME_FUNCTION RUNTIME_FUNCTION #define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION #endif // HOST_WINDOWS // // Nonvolatile context pointer record. // typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { PDWORD R4; PDWORD R5; PDWORD R6; PDWORD R7; PDWORD R8; PDWORD R9; PDWORD R10; PDWORD R11; PDWORD Lr; PULONGLONG D8; PULONGLONG D9; PULONGLONG D10; PULONGLONG D11; PULONGLONG D12; PULONGLONG D13; PULONGLONG D14; PULONGLONG D15; } T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; // // Define dynamic function table entry. // #if defined(HOST_X86) typedef PT_RUNTIME_FUNCTION (*PGET_RUNTIME_FUNCTION_CALLBACK) ( IN DWORD64 ControlPc, IN PVOID Context ); #endif // defined(HOST_X86) typedef struct _T_DISPATCHER_CONTEXT { ULONG ControlPc; ULONG ImageBase; PT_RUNTIME_FUNCTION FunctionEntry; ULONG EstablisherFrame; ULONG TargetPc; PT_CONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; PVOID HistoryTable; ULONG ScopeIndex; BOOLEAN ControlPcIsUnwound; PUCHAR NonVolatileRegisters; } T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; #elif defined(HOST_AMD64) && defined(TARGET_ARM64) // Host amd64 managing ARM64 related code #ifndef CROSS_COMPILE #define CROSS_COMPILE #endif // // Specify the number of breakpoints and watchpoints that the OS // will track. Architecturally, ARM64 supports up to 16. In practice, // however, almost no one implements more than 4 of each. // #define ARM64_MAX_BREAKPOINTS 8 #define ARM64_MAX_WATCHPOINTS 2 #define CONTEXT_UNWOUND_TO_CALL 0x20000000 typedef union _NEON128 { struct { ULONGLONG Low; LONGLONG High; }; double D[2]; float S[4]; WORD H[8]; BYTE B[16]; } NEON128, *PNEON128; typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { // // Control flags. // /* +0x000 */ DWORD ContextFlags; // // Integer registers // /* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel /* +0x008 */ union { struct { DWORD64 X0; DWORD64 X1; DWORD64 X2; DWORD64 X3; DWORD64 X4; DWORD64 X5; DWORD64 X6; DWORD64 X7; DWORD64 X8; DWORD64 X9; DWORD64 X10; DWORD64 X11; DWORD64 X12; DWORD64 X13; DWORD64 X14; DWORD64 X15; DWORD64 X16; DWORD64 X17; DWORD64 X18; DWORD64 X19; DWORD64 X20; DWORD64 X21; DWORD64 X22; DWORD64 X23; DWORD64 X24; DWORD64 X25; DWORD64 X26; DWORD64 X27; DWORD64 X28; }; DWORD64 X[29]; }; /* +0x0f0 */ DWORD64 Fp; /* +0x0f8 */ DWORD64 Lr; /* +0x100 */ DWORD64 Sp; /* +0x108 */ DWORD64 Pc; // // Floating Point/NEON Registers // /* +0x110 */ NEON128 V[32]; /* +0x310 */ DWORD Fpcr; /* +0x314 */ DWORD Fpsr; // // Debug registers // /* +0x318 */ DWORD Bcr[ARM64_MAX_BREAKPOINTS]; /* +0x338 */ DWORD64 Bvr[ARM64_MAX_BREAKPOINTS]; /* +0x378 */ DWORD Wcr[ARM64_MAX_WATCHPOINTS]; /* +0x380 */ DWORD64 Wvr[ARM64_MAX_WATCHPOINTS]; /* +0x390 */ } T_CONTEXT, *PT_CONTEXT; // _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) typedef struct _T_RUNTIME_FUNCTION { DWORD BeginAddress; union { DWORD UnwindData; struct { DWORD Flag : 2; DWORD FunctionLength : 11; DWORD RegF : 3; DWORD RegI : 4; DWORD H : 1; DWORD CR : 2; DWORD FrameSize : 9; } PackedUnwindData; }; } T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; #ifdef HOST_UNIX typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) ( PEXCEPTION_RECORD ExceptionRecord, ULONG64 EstablisherFrame, PCONTEXT ContextRecord, PVOID DispatcherContext ); #endif // // Define exception dispatch context structure. // typedef struct _T_DISPATCHER_CONTEXT { DWORD64 ControlPc; DWORD64 ImageBase; PT_RUNTIME_FUNCTION FunctionEntry; DWORD64 EstablisherFrame; DWORD64 TargetPc; PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; PVOID HistoryTable; DWORD ScopeIndex; BOOLEAN ControlPcIsUnwound; PBYTE NonVolatileRegisters; } T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; // // Nonvolatile context pointer record. // typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { PDWORD64 X19; PDWORD64 X20; PDWORD64 X21; PDWORD64 X22; PDWORD64 X23; PDWORD64 X24; PDWORD64 X25; PDWORD64 X26; PDWORD64 X27; PDWORD64 X28; PDWORD64 Fp; PDWORD64 Lr; PDWORD64 D8; PDWORD64 D9; PDWORD64 D10; PDWORD64 D11; PDWORD64 D12; PDWORD64 D13; PDWORD64 D14; PDWORD64 D15; } T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; #if defined(HOST_UNIX) && defined(TARGET_ARM64) && !defined(HOST_ARM64) enum { UNW_AARCH64_X19 = 19, UNW_AARCH64_X20 = 20, UNW_AARCH64_X21 = 21, UNW_AARCH64_X22 = 22, UNW_AARCH64_X23 = 23, UNW_AARCH64_X24 = 24, UNW_AARCH64_X25 = 25, UNW_AARCH64_X26 = 26, UNW_AARCH64_X27 = 27, UNW_AARCH64_X28 = 28, UNW_AARCH64_X29 = 29, UNW_AARCH64_X30 = 30, UNW_AARCH64_SP = 31, UNW_AARCH64_PC = 32 }; #endif // TARGET_ARM64 && !HOST_ARM64 #elif defined(HOST_AMD64) && defined(TARGET_LOONGARCH64) // Host amd64 managing LOONGARCH64 related code #ifndef CROSS_COMPILE #define CROSS_COMPILE #endif // // Specify the number of breakpoints and watchpoints that the OS // will track. Architecturally, LOONGARCH64 supports up to 16. In practice, // however, almost no one implements more than 4 of each. // #define LOONGARCH64_MAX_BREAKPOINTS 8 #define LOONGARCH64_MAX_WATCHPOINTS 2 #define CONTEXT_UNWOUND_TO_CALL 0x20000000 typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { // // Control flags. // /* +0x000 */ DWORD ContextFlags; // // Integer registers // DWORD64 R0; DWORD64 Ra; DWORD64 Tp; DWORD64 Sp; DWORD64 A0; DWORD64 A1; DWORD64 A2; DWORD64 A3; DWORD64 A4; DWORD64 A5; DWORD64 A6; DWORD64 A7; DWORD64 T0; DWORD64 T1; DWORD64 T2; DWORD64 T3; DWORD64 T4; DWORD64 T5; DWORD64 T6; DWORD64 T7; DWORD64 T8; DWORD64 X0; DWORD64 Fp; DWORD64 S0; DWORD64 S1; DWORD64 S2; DWORD64 S3; DWORD64 S4; DWORD64 S5; DWORD64 S6; DWORD64 S7; DWORD64 S8; DWORD64 Pc; // // Floating Point Registers // //TODO-LoongArch64: support the SIMD. ULONGLONG F[32]; DWORD Fcsr; } T_CONTEXT, *PT_CONTEXT; // _IMAGE_LOONGARCH64_RUNTIME_FUNCTION_ENTRY (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) typedef struct _T_RUNTIME_FUNCTION { DWORD BeginAddress; union { DWORD UnwindData; struct { DWORD Flag : 2; DWORD FunctionLength : 11; DWORD RegF : 3; DWORD RegI : 4; DWORD H : 1; DWORD CR : 2; DWORD FrameSize : 9; } PackedUnwindData; }; } T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; // // Define exception dispatch context structure. // typedef struct _T_DISPATCHER_CONTEXT { DWORD64 ControlPc; DWORD64 ImageBase; PT_RUNTIME_FUNCTION FunctionEntry; DWORD64 EstablisherFrame; DWORD64 TargetPc; PCONTEXT ContextRecord; PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; PVOID HistoryTable; DWORD ScopeIndex; BOOLEAN ControlPcIsUnwound; PBYTE NonVolatileRegisters; } T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; // // Nonvolatile context pointer record. // typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { PDWORD64 S0; PDWORD64 S1; PDWORD64 S2; PDWORD64 S3; PDWORD64 S4; PDWORD64 S5; PDWORD64 S6; PDWORD64 S7; PDWORD64 S8; PDWORD64 Fp; PDWORD64 Tp; PDWORD64 Ra; PDWORD64 F24; PDWORD64 F25; PDWORD64 F26; PDWORD64 F27; PDWORD64 F28; PDWORD64 F29; PDWORD64 F30; PDWORD64 F31; } T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; #else #define T_CONTEXT CONTEXT #define PT_CONTEXT PCONTEXT #define T_DISPATCHER_CONTEXT DISPATCHER_CONTEXT #define PT_DISPATCHER_CONTEXT PDISPATCHER_CONTEXT #define T_KNONVOLATILE_CONTEXT_POINTERS KNONVOLATILE_CONTEXT_POINTERS #define PT_KNONVOLATILE_CONTEXT_POINTERS PKNONVOLATILE_CONTEXT_POINTERS #define T_RUNTIME_FUNCTION RUNTIME_FUNCTION #define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION #endif #if defined(DACCESS_COMPILE) && defined(TARGET_UNIX) // This is a TARGET oriented copy of CRITICAL_SECTION and PAL_CS_NATIVE_DATA_SIZE // It is configured based on TARGET configuration rather than HOST configuration // There is validation code in src/coreclr/vm/crst.cpp to keep these from // getting out of sync #define T_CRITICAL_SECTION_VALIDATION_MESSAGE "T_CRITICAL_SECTION validation failed. It is not in sync with CRITICAL_SECTION" #if defined(TARGET_OSX) && defined(TARGET_X86) #define DAC_CS_NATIVE_DATA_SIZE 76 #elif defined(TARGET_OSX) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 120 #elif defined(TARGET_OSX) && defined(TARGET_ARM64) #define DAC_CS_NATIVE_DATA_SIZE 120 #elif defined(TARGET_FREEBSD) && defined(TARGET_X86) #define DAC_CS_NATIVE_DATA_SIZE 12 #elif defined(TARGET_FREEBSD) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 24 #elif defined(TARGET_LINUX) && defined(TARGET_ARM) #define DAC_CS_NATIVE_DATA_SIZE 80 #elif defined(TARGET_LINUX) && defined(TARGET_ARM64) #define DAC_CS_NATIVE_DATA_SIZE 104 #elif defined(TARGET_LINUX) && defined(TARGET_LOONGARCH64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_X86) #define DAC_CS_NATIVE_DATA_SIZE 76 #elif defined(TARGET_LINUX) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_S390X) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_LOONGARCH64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_RISCV64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_LINUX) && defined(TARGET_POWERPC64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 96 #elif defined(TARGET_NETBSD) && defined(TARGET_ARM) #define DAC_CS_NATIVE_DATA_SIZE 56 #elif defined(TARGET_NETBSD) && defined(TARGET_X86) #define DAC_CS_NATIVE_DATA_SIZE 56 #elif defined(__sun) && defined(TARGET_AMD64) #define DAC_CS_NATIVE_DATA_SIZE 48 #else #warning #error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)). #endif struct T_CRITICAL_SECTION { PVOID DebugInfo; LONG LockCount; LONG RecursionCount; HANDLE OwningThread; ULONG_PTR SpinCount; #ifdef PAL_TRACK_CRITICAL_SECTIONS_DATA BOOL bInternal; #endif // PAL_TRACK_CRITICAL_SECTIONS_DATA volatile DWORD dwInitState; union CSNativeDataStorage { BYTE rgNativeDataStorage[DAC_CS_NATIVE_DATA_SIZE]; PVOID pvAlign; // make sure the storage is machine-pointer-size aligned } csnds; }; #else #define T_CRITICAL_SECTION CRITICAL_SECTION #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/crsttypes_generated.h ================================================ // // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // #ifndef __CRST_TYPES_INCLUDED #define __CRST_TYPES_INCLUDED // **** THIS IS AN AUTOMATICALLY GENERATED HEADER FILE -- DO NOT EDIT!!! **** // This file describes the range of Crst types available and their mapping to a numeric level (used by the // runtime in debug mode to validate we're deadlock free). To modify these settings edit the // file:CrstTypes.def file and run the clr\artifacts\CrstTypeTool utility to generate a new version of this file. // Each Crst type is declared as a value in the following CrstType enum. enum CrstType { CrstAppDomainCache = 0, CrstArgBasedStubCache = 1, CrstAssemblyList = 2, CrstAssemblyLoader = 3, CrstAvailableClass = 4, CrstAvailableParamTypes = 5, CrstBaseDomain = 6, CrstCCompRC = 7, CrstClassFactInfoHash = 8, CrstClassInit = 9, CrstClrNotification = 10, CrstCodeFragmentHeap = 11, CrstCodeVersioning = 12, CrstCOMCallWrapper = 13, CrstCOMWrapperCache = 14, CrstDataTest1 = 15, CrstDataTest2 = 16, CrstDbgTransport = 17, CrstDeadlockDetection = 18, CrstDebuggerController = 19, CrstDebuggerFavorLock = 20, CrstDebuggerHeapExecMemLock = 21, CrstDebuggerHeapLock = 22, CrstDebuggerJitInfo = 23, CrstDebuggerMutex = 24, CrstDelegateToFPtrHash = 25, CrstDomainLocalBlock = 26, CrstDynamicIL = 27, CrstDynamicMT = 28, CrstEtwTypeLogHash = 29, CrstEventPipe = 30, CrstEventStore = 31, CrstException = 32, CrstExecutableAllocatorLock = 33, CrstExecuteManRangeLock = 34, CrstExternalObjectContextCache = 35, CrstFCall = 36, CrstFrozenObjectHeap = 37, CrstFuncPtrStubs = 38, CrstFusionAppCtx = 39, CrstGCCover = 40, CrstGlobalStrLiteralMap = 41, CrstHandleTable = 42, CrstIbcProfile = 43, CrstIJWFixupData = 44, CrstIJWHash = 45, CrstILStubGen = 46, CrstInlineTrackingMap = 47, CrstInstMethodHashTable = 48, CrstInterop = 49, CrstInteropData = 50, CrstIsJMCMethod = 51, CrstISymUnmanagedReader = 52, CrstJit = 53, CrstJitGenericHandleCache = 54, CrstJitInlineTrackingMap = 55, CrstJitPatchpoint = 56, CrstJitPerf = 57, CrstJumpStubCache = 58, CrstLeafLock = 59, CrstListLock = 60, CrstLoaderAllocator = 61, CrstLoaderAllocatorReferences = 62, CrstLoaderHeap = 63, CrstManagedObjectWrapperMap = 64, CrstMethodDescBackpatchInfoTracker = 65, CrstMethodTableExposedObject = 66, CrstModule = 67, CrstModuleFixup = 68, CrstModuleLookupTable = 69, CrstMulticoreJitHash = 70, CrstMulticoreJitManager = 71, CrstNativeImageEagerFixups = 72, CrstNativeImageLoad = 73, CrstNls = 74, CrstNotifyGdb = 75, CrstObjectList = 76, CrstPEImage = 77, CrstPendingTypeLoadEntry = 78, CrstPgoData = 79, CrstPinnedByrefValidation = 80, CrstPinnedHeapHandleTable = 81, CrstProfilerGCRefDataFreeList = 82, CrstProfilingAPIStatus = 83, CrstRCWCache = 84, CrstRCWCleanupList = 85, CrstReadyToRunEntryPointToMethodDescMap = 86, CrstReflection = 87, CrstReJITGlobalRequest = 88, CrstRetThunkCache = 89, CrstSavedExceptionInfo = 90, CrstSaveModuleProfileData = 91, CrstSecurityStackwalkCache = 92, CrstSigConvert = 93, CrstSingleUseLock = 94, CrstSpecialStatics = 95, CrstStackSampler = 96, CrstStressLog = 97, CrstStubCache = 98, CrstStubDispatchCache = 99, CrstStubUnwindInfoHeapSegments = 100, CrstSyncBlockCache = 101, CrstSyncHashLock = 102, CrstSystemBaseDomain = 103, CrstSystemDomain = 104, CrstSystemDomainDelayedUnloadList = 105, CrstThreadIdDispenser = 106, CrstThreadStore = 107, CrstTieredCompilation = 108, CrstTypeEquivalenceMap = 109, CrstTypeIDMap = 110, CrstUMEntryThunkCache = 111, CrstUMEntryThunkFreeListLock = 112, CrstUniqueStack = 113, CrstUnresolvedClassLock = 114, CrstUnwindInfoTableLock = 115, CrstVSDIndirectionCellLock = 116, CrstWrapperTemplate = 117, kNumberOfCrstTypes = 118 }; #endif // __CRST_TYPES_INCLUDED // Define some debug data in one module only -- vm\crst.cpp. #if defined(__IN_CRST_CPP) && defined(_DEBUG) // An array mapping CrstType to level. int g_rgCrstLevelMap[] = { 10, // CrstAppDomainCache 3, // CrstArgBasedStubCache 0, // CrstAssemblyList 12, // CrstAssemblyLoader 4, // CrstAvailableClass 5, // CrstAvailableParamTypes 7, // CrstBaseDomain -1, // CrstCCompRC 13, // CrstClassFactInfoHash 11, // CrstClassInit -1, // CrstClrNotification 6, // CrstCodeFragmentHeap 9, // CrstCodeVersioning 3, // CrstCOMCallWrapper 10, // CrstCOMWrapperCache 3, // CrstDataTest1 0, // CrstDataTest2 0, // CrstDbgTransport 0, // CrstDeadlockDetection -1, // CrstDebuggerController 3, // CrstDebuggerFavorLock 0, // CrstDebuggerHeapExecMemLock 0, // CrstDebuggerHeapLock 4, // CrstDebuggerJitInfo 10, // CrstDebuggerMutex 0, // CrstDelegateToFPtrHash 16, // CrstDomainLocalBlock 0, // CrstDynamicIL 3, // CrstDynamicMT 0, // CrstEtwTypeLogHash 18, // CrstEventPipe 0, // CrstEventStore 0, // CrstException 0, // CrstExecutableAllocatorLock 0, // CrstExecuteManRangeLock 0, // CrstExternalObjectContextCache 4, // CrstFCall -1, // CrstFrozenObjectHeap 7, // CrstFuncPtrStubs 10, // CrstFusionAppCtx 10, // CrstGCCover 15, // CrstGlobalStrLiteralMap 1, // CrstHandleTable 0, // CrstIbcProfile 8, // CrstIJWFixupData 0, // CrstIJWHash 7, // CrstILStubGen 3, // CrstInlineTrackingMap 17, // CrstInstMethodHashTable 20, // CrstInterop 5, // CrstInteropData 0, // CrstIsJMCMethod 7, // CrstISymUnmanagedReader 11, // CrstJit 0, // CrstJitGenericHandleCache 13, // CrstJitInlineTrackingMap 4, // CrstJitPatchpoint -1, // CrstJitPerf 6, // CrstJumpStubCache 0, // CrstLeafLock -1, // CrstListLock 15, // CrstLoaderAllocator 16, // CrstLoaderAllocatorReferences 3, // CrstLoaderHeap 3, // CrstManagedObjectWrapperMap 10, // CrstMethodDescBackpatchInfoTracker -1, // CrstMethodTableExposedObject 5, // CrstModule 16, // CrstModuleFixup 4, // CrstModuleLookupTable 0, // CrstMulticoreJitHash 13, // CrstMulticoreJitManager 3, // CrstNativeImageEagerFixups 0, // CrstNativeImageLoad 0, // CrstNls 0, // CrstNotifyGdb 2, // CrstObjectList 5, // CrstPEImage 19, // CrstPendingTypeLoadEntry 4, // CrstPgoData 0, // CrstPinnedByrefValidation 14, // CrstPinnedHeapHandleTable 0, // CrstProfilerGCRefDataFreeList 13, // CrstProfilingAPIStatus 4, // CrstRCWCache 0, // CrstRCWCleanupList 10, // CrstReadyToRunEntryPointToMethodDescMap 8, // CrstReflection 14, // CrstReJITGlobalRequest 4, // CrstRetThunkCache 3, // CrstSavedExceptionInfo 0, // CrstSaveModuleProfileData 0, // CrstSecurityStackwalkCache 4, // CrstSigConvert 5, // CrstSingleUseLock 0, // CrstSpecialStatics 0, // CrstStackSampler -1, // CrstStressLog 5, // CrstStubCache 0, // CrstStubDispatchCache 4, // CrstStubUnwindInfoHeapSegments 3, // CrstSyncBlockCache 0, // CrstSyncHashLock 5, // CrstSystemBaseDomain 13, // CrstSystemDomain 0, // CrstSystemDomainDelayedUnloadList 0, // CrstThreadIdDispenser 12, // CrstThreadStore 8, // CrstTieredCompilation 4, // CrstTypeEquivalenceMap 10, // CrstTypeIDMap 4, // CrstUMEntryThunkCache 3, // CrstUMEntryThunkFreeListLock 4, // CrstUniqueStack 7, // CrstUnresolvedClassLock 3, // CrstUnwindInfoTableLock 4, // CrstVSDIndirectionCellLock 3, // CrstWrapperTemplate }; // An array mapping CrstType to a stringized name. LPCSTR g_rgCrstNameMap[] = { "CrstAppDomainCache", "CrstArgBasedStubCache", "CrstAssemblyList", "CrstAssemblyLoader", "CrstAvailableClass", "CrstAvailableParamTypes", "CrstBaseDomain", "CrstCCompRC", "CrstClassFactInfoHash", "CrstClassInit", "CrstClrNotification", "CrstCodeFragmentHeap", "CrstCodeVersioning", "CrstCOMCallWrapper", "CrstCOMWrapperCache", "CrstDataTest1", "CrstDataTest2", "CrstDbgTransport", "CrstDeadlockDetection", "CrstDebuggerController", "CrstDebuggerFavorLock", "CrstDebuggerHeapExecMemLock", "CrstDebuggerHeapLock", "CrstDebuggerJitInfo", "CrstDebuggerMutex", "CrstDelegateToFPtrHash", "CrstDomainLocalBlock", "CrstDynamicIL", "CrstDynamicMT", "CrstEtwTypeLogHash", "CrstEventPipe", "CrstEventStore", "CrstException", "CrstExecutableAllocatorLock", "CrstExecuteManRangeLock", "CrstExternalObjectContextCache", "CrstFCall", "CrstFrozenObjectHeap", "CrstFuncPtrStubs", "CrstFusionAppCtx", "CrstGCCover", "CrstGlobalStrLiteralMap", "CrstHandleTable", "CrstIbcProfile", "CrstIJWFixupData", "CrstIJWHash", "CrstILStubGen", "CrstInlineTrackingMap", "CrstInstMethodHashTable", "CrstInterop", "CrstInteropData", "CrstIsJMCMethod", "CrstISymUnmanagedReader", "CrstJit", "CrstJitGenericHandleCache", "CrstJitInlineTrackingMap", "CrstJitPatchpoint", "CrstJitPerf", "CrstJumpStubCache", "CrstLeafLock", "CrstListLock", "CrstLoaderAllocator", "CrstLoaderAllocatorReferences", "CrstLoaderHeap", "CrstManagedObjectWrapperMap", "CrstMethodDescBackpatchInfoTracker", "CrstMethodTableExposedObject", "CrstModule", "CrstModuleFixup", "CrstModuleLookupTable", "CrstMulticoreJitHash", "CrstMulticoreJitManager", "CrstNativeImageEagerFixups", "CrstNativeImageLoad", "CrstNls", "CrstNotifyGdb", "CrstObjectList", "CrstPEImage", "CrstPendingTypeLoadEntry", "CrstPgoData", "CrstPinnedByrefValidation", "CrstPinnedHeapHandleTable", "CrstProfilerGCRefDataFreeList", "CrstProfilingAPIStatus", "CrstRCWCache", "CrstRCWCleanupList", "CrstReadyToRunEntryPointToMethodDescMap", "CrstReflection", "CrstReJITGlobalRequest", "CrstRetThunkCache", "CrstSavedExceptionInfo", "CrstSaveModuleProfileData", "CrstSecurityStackwalkCache", "CrstSigConvert", "CrstSingleUseLock", "CrstSpecialStatics", "CrstStackSampler", "CrstStressLog", "CrstStubCache", "CrstStubDispatchCache", "CrstStubUnwindInfoHeapSegments", "CrstSyncBlockCache", "CrstSyncHashLock", "CrstSystemBaseDomain", "CrstSystemDomain", "CrstSystemDomainDelayedUnloadList", "CrstThreadIdDispenser", "CrstThreadStore", "CrstTieredCompilation", "CrstTypeEquivalenceMap", "CrstTypeIDMap", "CrstUMEntryThunkCache", "CrstUMEntryThunkFreeListLock", "CrstUniqueStack", "CrstUnresolvedClassLock", "CrstUnwindInfoTableLock", "CrstVSDIndirectionCellLock", "CrstWrapperTemplate", }; // Define a special level constant for unordered locks. #define CRSTUNORDERED (-1) // Define inline helpers to map Crst types to names and levels. inline static int GetCrstLevel(CrstType crstType) { LIMITED_METHOD_CONTRACT; _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes); return g_rgCrstLevelMap[crstType]; } inline static LPCSTR GetCrstName(CrstType crstType) { LIMITED_METHOD_CONTRACT; _ASSERTE(crstType >= 0 && crstType < kNumberOfCrstTypes); return g_rgCrstNameMap[crstType]; } #endif // defined(__IN_CRST_CPP) && defined(_DEBUG) ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/crtwrap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // CrtWrap.h // // Wrapper code for the C runtime library. // //***************************************************************************** #ifndef __CrtWrap_h__ #define __CrtWrap_h__ #include #include #include #include "debugmacros.h" #include #include #include #include #ifdef HOST_WINDOWS // CoreCLR.dll uses linker .def files to control the exported symbols. // Define DLLEXPORT macro as empty on Windows. #define DLLEXPORT #endif #endif // __CrtWrap_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cvconst.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // cvconst.h - codeview constant definitions //----------------------------------------------------------------- // // Copyright Microsoft Corporation. All Rights Reserved. // //--------------------------------------------------------------- #ifndef _CVCONST_H_ #define _CVCONST_H_ // Enumeration for function call type typedef enum CV_call_e { CV_CALL_NEAR_C = 0x00, // near right to left push, caller pops stack CV_CALL_FAR_C = 0x01, // far right to left push, caller pops stack CV_CALL_NEAR_PASCAL = 0x02, // near left to right push, callee pops stack CV_CALL_FAR_PASCAL = 0x03, // far left to right push, callee pops stack CV_CALL_NEAR_FAST = 0x04, // near left to right push with regs, callee pops stack CV_CALL_FAR_FAST = 0x05, // far left to right push with regs, callee pops stack CV_CALL_SKIPPED = 0x06, // skipped (unused) call index CV_CALL_NEAR_STD = 0x07, // near standard call CV_CALL_FAR_STD = 0x08, // far standard call CV_CALL_NEAR_SYS = 0x09, // near sys call CV_CALL_FAR_SYS = 0x0a, // far sys call CV_CALL_THISCALL = 0x0b, // this call (this passed in register) CV_CALL_MIPSCALL = 0x0c, // Mips call CV_CALL_GENERIC = 0x0d, // Generic call sequence CV_CALL_ALPHACALL = 0x0e, // Alpha call CV_CALL_PPCCALL = 0x0f, // PPC call CV_CALL_SHCALL = 0x10, // Hitachi SuperH call CV_CALL_ARMCALL = 0x11, // ARM call CV_CALL_AM33CALL = 0x12, // AM33 call CV_CALL_TRICALL = 0x13, // TriCore Call CV_CALL_SH5CALL = 0x14, // Hitachi SuperH-5 call CV_CALL_M32RCALL = 0x15, // M32R Call CV_CALL_CLRCALL = 0x16, // clr call CV_CALL_INLINE = 0x17, // Marker for routines always inlined and thus lacking a convention CV_CALL_NEAR_VECTOR = 0x18, // near left to right push with regs, callee pops stack CV_CALL_RESERVED = 0x19 // first unused call enumeration // Do NOT add any more machine specific conventions. This is to be used for // calling conventions in the source only (e.g. __cdecl, __stdcall). } CV_call_e; // Values for the access protection of class attributes typedef enum CV_access_e { CV_private = 1, CV_protected = 2, CV_public = 3 } CV_access_e; typedef enum THUNK_ORDINAL { THUNK_ORDINAL_NOTYPE, // standard thunk THUNK_ORDINAL_ADJUSTOR, // "this" adjustor thunk THUNK_ORDINAL_VCALL, // virtual call thunk THUNK_ORDINAL_PCODE, // pcode thunk THUNK_ORDINAL_LOAD, // thunk which loads the address to jump to // via unknown means... // trampoline thunk ordinals - only for use in Trampoline thunk symbols THUNK_ORDINAL_TRAMP_INCREMENTAL, THUNK_ORDINAL_TRAMP_BRANCHISLAND, } THUNK_ORDINAL; enum CV_SourceChksum_t { CHKSUM_TYPE_NONE = 0, // indicates no checksum is available CHKSUM_TYPE_MD5, CHKSUM_TYPE_SHA1, CHKSUM_TYPE_SHA_256, }; // // DIA enums // enum SymTagEnum { SymTagNull, SymTagExe, SymTagCompiland, SymTagCompilandDetails, SymTagCompilandEnv, SymTagFunction, SymTagBlock, SymTagData, SymTagAnnotation, SymTagLabel, SymTagPublicSymbol, SymTagUDT, SymTagEnum, SymTagFunctionType, SymTagPointerType, SymTagArrayType, SymTagBaseType, SymTagTypedef, SymTagBaseClass, SymTagFriend, SymTagFunctionArgType, SymTagFuncDebugStart, SymTagFuncDebugEnd, SymTagUsingNamespace, SymTagVTableShape, SymTagVTable, SymTagCustom, SymTagThunk, SymTagCustomType, SymTagManagedType, SymTagDimension, SymTagCallSite, SymTagInlineSite, SymTagBaseInterface, SymTagVectorType, SymTagMatrixType, SymTagHLSLType, SymTagCaller, SymTagCallee, SymTagExport, SymTagHeapAllocationSite, SymTagCoffGroup, SymTagMax }; enum LocationType { LocIsNull, LocIsStatic, LocIsTLS, LocIsRegRel, LocIsThisRel, LocIsEnregistered, LocIsBitField, LocIsSlot, LocIsIlRel, LocInMetaData, LocIsConstant, LocTypeMax }; enum DataKind { DataIsUnknown, DataIsLocal, DataIsStaticLocal, DataIsParam, DataIsObjectPtr, DataIsFileStatic, DataIsGlobal, DataIsMember, DataIsStaticMember, DataIsConstant }; enum UdtKind { UdtStruct, UdtClass, UdtUnion, UdtInterface }; enum BasicType { btNoType = 0, btVoid = 1, btChar = 2, btWChar = 3, btInt = 6, btUInt = 7, btFloat = 8, btBCD = 9, btBool = 10, btLong = 13, btULong = 14, btCurrency = 25, btDate = 26, btVariant = 27, btComplex = 28, btBit = 29, btBSTR = 30, btHresult = 31, btChar16 = 32, // char16_t btChar32 = 33, // char32_t }; // enumeration for type modifier values typedef enum CV_modifier_e { // 0x0000 - 0x01ff - Reserved. CV_MOD_INVALID = 0x0000, // Standard modifiers. CV_MOD_CONST = 0x0001, CV_MOD_VOLATILE = 0x0002, CV_MOD_UNALIGNED = 0x0003, // 0x0200 - 0x03ff - HLSL modifiers. CV_MOD_HLSL_UNIFORM = 0x0200, CV_MOD_HLSL_LINE = 0x0201, CV_MOD_HLSL_TRIANGLE = 0x0202, CV_MOD_HLSL_LINEADJ = 0x0203, CV_MOD_HLSL_TRIANGLEADJ = 0x0204, CV_MOD_HLSL_LINEAR = 0x0205, CV_MOD_HLSL_CENTROID = 0x0206, CV_MOD_HLSL_CONSTINTERP = 0x0207, CV_MOD_HLSL_NOPERSPECTIVE = 0x0208, CV_MOD_HLSL_SAMPLE = 0x0209, CV_MOD_HLSL_CENTER = 0x020a, CV_MOD_HLSL_SNORM = 0x020b, CV_MOD_HLSL_UNORM = 0x020c, CV_MOD_HLSL_PRECISE = 0x020d, CV_MOD_HLSL_UAV_GLOBALLY_COHERENT = 0x020e, // 0x0400 - 0xffff - Unused. } CV_modifier_e; // built-in type kinds typedef enum CV_builtin_e { // 0x0000 - 0x01ff - Reserved. CV_BI_INVALID = 0x0000, // 0x0200 - 0x03ff - HLSL types. CV_BI_HLSL_INTERFACE_POINTER = 0x0200, CV_BI_HLSL_TEXTURE1D = 0x0201, CV_BI_HLSL_TEXTURE1D_ARRAY = 0x0202, CV_BI_HLSL_TEXTURE2D = 0x0203, CV_BI_HLSL_TEXTURE2D_ARRAY = 0x0204, CV_BI_HLSL_TEXTURE3D = 0x0205, CV_BI_HLSL_TEXTURECUBE = 0x0206, CV_BI_HLSL_TEXTURECUBE_ARRAY = 0x0207, CV_BI_HLSL_TEXTURE2DMS = 0x0208, CV_BI_HLSL_TEXTURE2DMS_ARRAY = 0x0209, CV_BI_HLSL_SAMPLER = 0x020a, CV_BI_HLSL_SAMPLERCOMPARISON = 0x020b, CV_BI_HLSL_BUFFER = 0x020c, CV_BI_HLSL_POINTSTREAM = 0x020d, CV_BI_HLSL_LINESTREAM = 0x020e, CV_BI_HLSL_TRIANGLESTREAM = 0x020f, CV_BI_HLSL_INPUTPATCH = 0x0210, CV_BI_HLSL_OUTPUTPATCH = 0x0211, CV_BI_HLSL_RWTEXTURE1D = 0x0212, CV_BI_HLSL_RWTEXTURE1D_ARRAY = 0x0213, CV_BI_HLSL_RWTEXTURE2D = 0x0214, CV_BI_HLSL_RWTEXTURE2D_ARRAY = 0x0215, CV_BI_HLSL_RWTEXTURE3D = 0x0216, CV_BI_HLSL_RWBUFFER = 0x0217, CV_BI_HLSL_BYTEADDRESS_BUFFER = 0x0218, CV_BI_HLSL_RWBYTEADDRESS_BUFFER = 0x0219, CV_BI_HLSL_STRUCTURED_BUFFER = 0x021a, CV_BI_HLSL_RWSTRUCTURED_BUFFER = 0x021b, CV_BI_HLSL_APPEND_STRUCTURED_BUFFER = 0x021c, CV_BI_HLSL_CONSUME_STRUCTURED_BUFFER= 0x021d, CV_BI_HLSL_MIN8FLOAT = 0x021e, CV_BI_HLSL_MIN10FLOAT = 0x021f, CV_BI_HLSL_MIN16FLOAT = 0x0220, CV_BI_HLSL_MIN12INT = 0x0221, CV_BI_HLSL_MIN16INT = 0x0222, CV_BI_HLSL_MIN16UINT = 0x0223, // 0x0400 - 0xffff - Unused. } CV_builtin_e; // enum describing the compile flag source language typedef enum CV_CFL_LANG { CV_CFL_C = 0x00, CV_CFL_CXX = 0x01, CV_CFL_FORTRAN = 0x02, CV_CFL_MASM = 0x03, CV_CFL_PASCAL = 0x04, CV_CFL_BASIC = 0x05, CV_CFL_COBOL = 0x06, CV_CFL_LINK = 0x07, CV_CFL_CVTRES = 0x08, CV_CFL_CVTPGD = 0x09, CV_CFL_CSHARP = 0x0A, // C# CV_CFL_VB = 0x0B, // Visual Basic CV_CFL_ILASM = 0x0C, // IL (as in CLR) ASM CV_CFL_JAVA = 0x0D, CV_CFL_JSCRIPT = 0x0E, CV_CFL_MSIL = 0x0F, // Unknown MSIL (LTCG of .NETMODULE) CV_CFL_HLSL = 0x10, // High Level Shader Language } CV_CFL_LANG; // enum describing target processor typedef enum CV_CPU_TYPE_e { CV_CFL_8080 = 0x00, CV_CFL_8086 = 0x01, CV_CFL_80286 = 0x02, CV_CFL_80386 = 0x03, CV_CFL_80486 = 0x04, CV_CFL_PENTIUM = 0x05, CV_CFL_PENTIUMII = 0x06, CV_CFL_PENTIUMPRO = CV_CFL_PENTIUMII, CV_CFL_PENTIUMIII = 0x07, CV_CFL_MIPS = 0x10, CV_CFL_MIPSR4000 = CV_CFL_MIPS, // don't break current code CV_CFL_MIPS16 = 0x11, CV_CFL_MIPS32 = 0x12, CV_CFL_MIPS64 = 0x13, CV_CFL_MIPSI = 0x14, CV_CFL_MIPSII = 0x15, CV_CFL_MIPSIII = 0x16, CV_CFL_MIPSIV = 0x17, CV_CFL_MIPSV = 0x18, CV_CFL_M68000 = 0x20, CV_CFL_M68010 = 0x21, CV_CFL_M68020 = 0x22, CV_CFL_M68030 = 0x23, CV_CFL_M68040 = 0x24, CV_CFL_ALPHA = 0x30, CV_CFL_ALPHA_21064 = 0x30, CV_CFL_ALPHA_21164 = 0x31, CV_CFL_ALPHA_21164A = 0x32, CV_CFL_ALPHA_21264 = 0x33, CV_CFL_ALPHA_21364 = 0x34, CV_CFL_PPC601 = 0x40, CV_CFL_PPC603 = 0x41, CV_CFL_PPC604 = 0x42, CV_CFL_PPC620 = 0x43, CV_CFL_PPCFP = 0x44, CV_CFL_PPCBE = 0x45, CV_CFL_SH3 = 0x50, CV_CFL_SH3E = 0x51, CV_CFL_SH3DSP = 0x52, CV_CFL_SH4 = 0x53, CV_CFL_SHMEDIA = 0x54, CV_CFL_ARM3 = 0x60, CV_CFL_ARM4 = 0x61, CV_CFL_ARM4T = 0x62, CV_CFL_ARM5 = 0x63, CV_CFL_ARM5T = 0x64, CV_CFL_ARM6 = 0x65, CV_CFL_ARM_XMAC = 0x66, CV_CFL_ARM_WMMX = 0x67, CV_CFL_ARM7 = 0x68, CV_CFL_OMNI = 0x70, CV_CFL_IA64 = 0x80, CV_CFL_IA64_1 = 0x80, CV_CFL_IA64_2 = 0x81, CV_CFL_CEE = 0x90, CV_CFL_AM33 = 0xA0, CV_CFL_M32R = 0xB0, CV_CFL_TRICORE = 0xC0, CV_CFL_X64 = 0xD0, CV_CFL_AMD64 = CV_CFL_X64, CV_CFL_EBC = 0xE0, CV_CFL_THUMB = 0xF0, CV_CFL_ARMNT = 0xF4, CV_CFL_ARM64 = 0xF6, CV_CFL_D3D11_SHADER = 0x100, } CV_CPU_TYPE_e; typedef enum CV_HREG_e { // Register subset shared by all processor types, // must not overlap with any of the ranges below, hence the high values CV_ALLREG_ERR = 30000, CV_ALLREG_TEB = 30001, CV_ALLREG_TIMER = 30002, CV_ALLREG_EFAD1 = 30003, CV_ALLREG_EFAD2 = 30004, CV_ALLREG_EFAD3 = 30005, CV_ALLREG_VFRAME= 30006, CV_ALLREG_HANDLE= 30007, CV_ALLREG_PARAMS= 30008, CV_ALLREG_LOCALS= 30009, CV_ALLREG_TID = 30010, CV_ALLREG_ENV = 30011, CV_ALLREG_CMDLN = 30012, // Register set for the Intel 80x86 and ix86 processor series // (plus PCODE registers) CV_REG_NONE = 0, CV_REG_AL = 1, CV_REG_CL = 2, CV_REG_DL = 3, CV_REG_BL = 4, CV_REG_AH = 5, CV_REG_CH = 6, CV_REG_DH = 7, CV_REG_BH = 8, CV_REG_AX = 9, CV_REG_CX = 10, CV_REG_DX = 11, CV_REG_BX = 12, CV_REG_SP = 13, CV_REG_BP = 14, CV_REG_SI = 15, CV_REG_DI = 16, CV_REG_EAX = 17, CV_REG_ECX = 18, CV_REG_EDX = 19, CV_REG_EBX = 20, CV_REG_ESP = 21, CV_REG_EBP = 22, CV_REG_ESI = 23, CV_REG_EDI = 24, CV_REG_ES = 25, CV_REG_CS = 26, CV_REG_SS = 27, CV_REG_DS = 28, CV_REG_FS = 29, CV_REG_GS = 30, CV_REG_IP = 31, CV_REG_FLAGS = 32, CV_REG_EIP = 33, CV_REG_EFLAGS = 34, CV_REG_TEMP = 40, // PCODE Temp CV_REG_TEMPH = 41, // PCODE TempH CV_REG_QUOTE = 42, // PCODE Quote CV_REG_PCDR3 = 43, // PCODE reserved CV_REG_PCDR4 = 44, // PCODE reserved CV_REG_PCDR5 = 45, // PCODE reserved CV_REG_PCDR6 = 46, // PCODE reserved CV_REG_PCDR7 = 47, // PCODE reserved CV_REG_CR0 = 80, // CR0 -- control registers CV_REG_CR1 = 81, CV_REG_CR2 = 82, CV_REG_CR3 = 83, CV_REG_CR4 = 84, // Pentium CV_REG_DR0 = 90, // Debug register CV_REG_DR1 = 91, CV_REG_DR2 = 92, CV_REG_DR3 = 93, CV_REG_DR4 = 94, CV_REG_DR5 = 95, CV_REG_DR6 = 96, CV_REG_DR7 = 97, CV_REG_GDTR = 110, CV_REG_GDTL = 111, CV_REG_IDTR = 112, CV_REG_IDTL = 113, CV_REG_LDTR = 114, CV_REG_TR = 115, CV_REG_PSEUDO1 = 116, CV_REG_PSEUDO2 = 117, CV_REG_PSEUDO3 = 118, CV_REG_PSEUDO4 = 119, CV_REG_PSEUDO5 = 120, CV_REG_PSEUDO6 = 121, CV_REG_PSEUDO7 = 122, CV_REG_PSEUDO8 = 123, CV_REG_PSEUDO9 = 124, CV_REG_ST0 = 128, CV_REG_ST1 = 129, CV_REG_ST2 = 130, CV_REG_ST3 = 131, CV_REG_ST4 = 132, CV_REG_ST5 = 133, CV_REG_ST6 = 134, CV_REG_ST7 = 135, CV_REG_CTRL = 136, CV_REG_STAT = 137, CV_REG_TAG = 138, CV_REG_FPIP = 139, CV_REG_FPCS = 140, CV_REG_FPDO = 141, CV_REG_FPDS = 142, CV_REG_ISEM = 143, CV_REG_FPEIP = 144, CV_REG_FPEDO = 145, CV_REG_MM0 = 146, CV_REG_MM1 = 147, CV_REG_MM2 = 148, CV_REG_MM3 = 149, CV_REG_MM4 = 150, CV_REG_MM5 = 151, CV_REG_MM6 = 152, CV_REG_MM7 = 153, CV_REG_XMM0 = 154, // KATMAI registers CV_REG_XMM1 = 155, CV_REG_XMM2 = 156, CV_REG_XMM3 = 157, CV_REG_XMM4 = 158, CV_REG_XMM5 = 159, CV_REG_XMM6 = 160, CV_REG_XMM7 = 161, CV_REG_XMM00 = 162, // KATMAI sub-registers CV_REG_XMM01 = 163, CV_REG_XMM02 = 164, CV_REG_XMM03 = 165, CV_REG_XMM10 = 166, CV_REG_XMM11 = 167, CV_REG_XMM12 = 168, CV_REG_XMM13 = 169, CV_REG_XMM20 = 170, CV_REG_XMM21 = 171, CV_REG_XMM22 = 172, CV_REG_XMM23 = 173, CV_REG_XMM30 = 174, CV_REG_XMM31 = 175, CV_REG_XMM32 = 176, CV_REG_XMM33 = 177, CV_REG_XMM40 = 178, CV_REG_XMM41 = 179, CV_REG_XMM42 = 180, CV_REG_XMM43 = 181, CV_REG_XMM50 = 182, CV_REG_XMM51 = 183, CV_REG_XMM52 = 184, CV_REG_XMM53 = 185, CV_REG_XMM60 = 186, CV_REG_XMM61 = 187, CV_REG_XMM62 = 188, CV_REG_XMM63 = 189, CV_REG_XMM70 = 190, CV_REG_XMM71 = 191, CV_REG_XMM72 = 192, CV_REG_XMM73 = 193, CV_REG_XMM0L = 194, CV_REG_XMM1L = 195, CV_REG_XMM2L = 196, CV_REG_XMM3L = 197, CV_REG_XMM4L = 198, CV_REG_XMM5L = 199, CV_REG_XMM6L = 200, CV_REG_XMM7L = 201, CV_REG_XMM0H = 202, CV_REG_XMM1H = 203, CV_REG_XMM2H = 204, CV_REG_XMM3H = 205, CV_REG_XMM4H = 206, CV_REG_XMM5H = 207, CV_REG_XMM6H = 208, CV_REG_XMM7H = 209, CV_REG_MXCSR = 211, // XMM status register CV_REG_EDXEAX = 212, // EDX:EAX pair CV_REG_EMM0L = 220, // XMM sub-registers (WNI integer) CV_REG_EMM1L = 221, CV_REG_EMM2L = 222, CV_REG_EMM3L = 223, CV_REG_EMM4L = 224, CV_REG_EMM5L = 225, CV_REG_EMM6L = 226, CV_REG_EMM7L = 227, CV_REG_EMM0H = 228, CV_REG_EMM1H = 229, CV_REG_EMM2H = 230, CV_REG_EMM3H = 231, CV_REG_EMM4H = 232, CV_REG_EMM5H = 233, CV_REG_EMM6H = 234, CV_REG_EMM7H = 235, // do not change the order of these regs, first one must be even too CV_REG_MM00 = 236, CV_REG_MM01 = 237, CV_REG_MM10 = 238, CV_REG_MM11 = 239, CV_REG_MM20 = 240, CV_REG_MM21 = 241, CV_REG_MM30 = 242, CV_REG_MM31 = 243, CV_REG_MM40 = 244, CV_REG_MM41 = 245, CV_REG_MM50 = 246, CV_REG_MM51 = 247, CV_REG_MM60 = 248, CV_REG_MM61 = 249, CV_REG_MM70 = 250, CV_REG_MM71 = 251, CV_REG_YMM0 = 252, // AVX registers CV_REG_YMM1 = 253, CV_REG_YMM2 = 254, CV_REG_YMM3 = 255, CV_REG_YMM4 = 256, CV_REG_YMM5 = 257, CV_REG_YMM6 = 258, CV_REG_YMM7 = 259, CV_REG_YMM0H = 260, CV_REG_YMM1H = 261, CV_REG_YMM2H = 262, CV_REG_YMM3H = 263, CV_REG_YMM4H = 264, CV_REG_YMM5H = 265, CV_REG_YMM6H = 266, CV_REG_YMM7H = 267, CV_REG_YMM0I0 = 268, // AVX integer registers CV_REG_YMM0I1 = 269, CV_REG_YMM0I2 = 270, CV_REG_YMM0I3 = 271, CV_REG_YMM1I0 = 272, CV_REG_YMM1I1 = 273, CV_REG_YMM1I2 = 274, CV_REG_YMM1I3 = 275, CV_REG_YMM2I0 = 276, CV_REG_YMM2I1 = 277, CV_REG_YMM2I2 = 278, CV_REG_YMM2I3 = 279, CV_REG_YMM3I0 = 280, CV_REG_YMM3I1 = 281, CV_REG_YMM3I2 = 282, CV_REG_YMM3I3 = 283, CV_REG_YMM4I0 = 284, CV_REG_YMM4I1 = 285, CV_REG_YMM4I2 = 286, CV_REG_YMM4I3 = 287, CV_REG_YMM5I0 = 288, CV_REG_YMM5I1 = 289, CV_REG_YMM5I2 = 290, CV_REG_YMM5I3 = 291, CV_REG_YMM6I0 = 292, CV_REG_YMM6I1 = 293, CV_REG_YMM6I2 = 294, CV_REG_YMM6I3 = 295, CV_REG_YMM7I0 = 296, CV_REG_YMM7I1 = 297, CV_REG_YMM7I2 = 298, CV_REG_YMM7I3 = 299, CV_REG_YMM0F0 = 300, // AVX floating-point single precise registers CV_REG_YMM0F1 = 301, CV_REG_YMM0F2 = 302, CV_REG_YMM0F3 = 303, CV_REG_YMM0F4 = 304, CV_REG_YMM0F5 = 305, CV_REG_YMM0F6 = 306, CV_REG_YMM0F7 = 307, CV_REG_YMM1F0 = 308, CV_REG_YMM1F1 = 309, CV_REG_YMM1F2 = 310, CV_REG_YMM1F3 = 311, CV_REG_YMM1F4 = 312, CV_REG_YMM1F5 = 313, CV_REG_YMM1F6 = 314, CV_REG_YMM1F7 = 315, CV_REG_YMM2F0 = 316, CV_REG_YMM2F1 = 317, CV_REG_YMM2F2 = 318, CV_REG_YMM2F3 = 319, CV_REG_YMM2F4 = 320, CV_REG_YMM2F5 = 321, CV_REG_YMM2F6 = 322, CV_REG_YMM2F7 = 323, CV_REG_YMM3F0 = 324, CV_REG_YMM3F1 = 325, CV_REG_YMM3F2 = 326, CV_REG_YMM3F3 = 327, CV_REG_YMM3F4 = 328, CV_REG_YMM3F5 = 329, CV_REG_YMM3F6 = 330, CV_REG_YMM3F7 = 331, CV_REG_YMM4F0 = 332, CV_REG_YMM4F1 = 333, CV_REG_YMM4F2 = 334, CV_REG_YMM4F3 = 335, CV_REG_YMM4F4 = 336, CV_REG_YMM4F5 = 337, CV_REG_YMM4F6 = 338, CV_REG_YMM4F7 = 339, CV_REG_YMM5F0 = 340, CV_REG_YMM5F1 = 341, CV_REG_YMM5F2 = 342, CV_REG_YMM5F3 = 343, CV_REG_YMM5F4 = 344, CV_REG_YMM5F5 = 345, CV_REG_YMM5F6 = 346, CV_REG_YMM5F7 = 347, CV_REG_YMM6F0 = 348, CV_REG_YMM6F1 = 349, CV_REG_YMM6F2 = 350, CV_REG_YMM6F3 = 351, CV_REG_YMM6F4 = 352, CV_REG_YMM6F5 = 353, CV_REG_YMM6F6 = 354, CV_REG_YMM6F7 = 355, CV_REG_YMM7F0 = 356, CV_REG_YMM7F1 = 357, CV_REG_YMM7F2 = 358, CV_REG_YMM7F3 = 359, CV_REG_YMM7F4 = 360, CV_REG_YMM7F5 = 361, CV_REG_YMM7F6 = 362, CV_REG_YMM7F7 = 363, CV_REG_YMM0D0 = 364, // AVX floating-point double precise registers CV_REG_YMM0D1 = 365, CV_REG_YMM0D2 = 366, CV_REG_YMM0D3 = 367, CV_REG_YMM1D0 = 368, CV_REG_YMM1D1 = 369, CV_REG_YMM1D2 = 370, CV_REG_YMM1D3 = 371, CV_REG_YMM2D0 = 372, CV_REG_YMM2D1 = 373, CV_REG_YMM2D2 = 374, CV_REG_YMM2D3 = 375, CV_REG_YMM3D0 = 376, CV_REG_YMM3D1 = 377, CV_REG_YMM3D2 = 378, CV_REG_YMM3D3 = 379, CV_REG_YMM4D0 = 380, CV_REG_YMM4D1 = 381, CV_REG_YMM4D2 = 382, CV_REG_YMM4D3 = 383, CV_REG_YMM5D0 = 384, CV_REG_YMM5D1 = 385, CV_REG_YMM5D2 = 386, CV_REG_YMM5D3 = 387, CV_REG_YMM6D0 = 388, CV_REG_YMM6D1 = 389, CV_REG_YMM6D2 = 390, CV_REG_YMM6D3 = 391, CV_REG_YMM7D0 = 392, CV_REG_YMM7D1 = 393, CV_REG_YMM7D2 = 394, CV_REG_YMM7D3 = 395, CV_REG_BND0 = 396, CV_REG_BND1 = 397, CV_REG_BND2 = 398, CV_REG_BND3 = 399, // registers for the 68K processors CV_R68_D0 = 0, CV_R68_D1 = 1, CV_R68_D2 = 2, CV_R68_D3 = 3, CV_R68_D4 = 4, CV_R68_D5 = 5, CV_R68_D6 = 6, CV_R68_D7 = 7, CV_R68_A0 = 8, CV_R68_A1 = 9, CV_R68_A2 = 10, CV_R68_A3 = 11, CV_R68_A4 = 12, CV_R68_A5 = 13, CV_R68_A6 = 14, CV_R68_A7 = 15, CV_R68_CCR = 16, CV_R68_SR = 17, CV_R68_USP = 18, CV_R68_MSP = 19, CV_R68_SFC = 20, CV_R68_DFC = 21, CV_R68_CACR = 22, CV_R68_VBR = 23, CV_R68_CAAR = 24, CV_R68_ISP = 25, CV_R68_PC = 26, //reserved 27 CV_R68_FPCR = 28, CV_R68_FPSR = 29, CV_R68_FPIAR = 30, //reserved 31 CV_R68_FP0 = 32, CV_R68_FP1 = 33, CV_R68_FP2 = 34, CV_R68_FP3 = 35, CV_R68_FP4 = 36, CV_R68_FP5 = 37, CV_R68_FP6 = 38, CV_R68_FP7 = 39, //reserved 40 CV_R68_MMUSR030 = 41, CV_R68_MMUSR = 42, CV_R68_URP = 43, CV_R68_DTT0 = 44, CV_R68_DTT1 = 45, CV_R68_ITT0 = 46, CV_R68_ITT1 = 47, //reserved 50 CV_R68_PSR = 51, CV_R68_PCSR = 52, CV_R68_VAL = 53, CV_R68_CRP = 54, CV_R68_SRP = 55, CV_R68_DRP = 56, CV_R68_TC = 57, CV_R68_AC = 58, CV_R68_SCC = 59, CV_R68_CAL = 60, CV_R68_TT0 = 61, CV_R68_TT1 = 62, //reserved 63 CV_R68_BAD0 = 64, CV_R68_BAD1 = 65, CV_R68_BAD2 = 66, CV_R68_BAD3 = 67, CV_R68_BAD4 = 68, CV_R68_BAD5 = 69, CV_R68_BAD6 = 70, CV_R68_BAD7 = 71, CV_R68_BAC0 = 72, CV_R68_BAC1 = 73, CV_R68_BAC2 = 74, CV_R68_BAC3 = 75, CV_R68_BAC4 = 76, CV_R68_BAC5 = 77, CV_R68_BAC6 = 78, CV_R68_BAC7 = 79, // Register set for the MIPS 4000 CV_M4_NOREG = CV_REG_NONE, CV_M4_IntZERO = 10, /* CPU REGISTER */ CV_M4_IntAT = 11, CV_M4_IntV0 = 12, CV_M4_IntV1 = 13, CV_M4_IntA0 = 14, CV_M4_IntA1 = 15, CV_M4_IntA2 = 16, CV_M4_IntA3 = 17, CV_M4_IntT0 = 18, CV_M4_IntT1 = 19, CV_M4_IntT2 = 20, CV_M4_IntT3 = 21, CV_M4_IntT4 = 22, CV_M4_IntT5 = 23, CV_M4_IntT6 = 24, CV_M4_IntT7 = 25, CV_M4_IntS0 = 26, CV_M4_IntS1 = 27, CV_M4_IntS2 = 28, CV_M4_IntS3 = 29, CV_M4_IntS4 = 30, CV_M4_IntS5 = 31, CV_M4_IntS6 = 32, CV_M4_IntS7 = 33, CV_M4_IntT8 = 34, CV_M4_IntT9 = 35, CV_M4_IntKT0 = 36, CV_M4_IntKT1 = 37, CV_M4_IntGP = 38, CV_M4_IntSP = 39, CV_M4_IntS8 = 40, CV_M4_IntRA = 41, CV_M4_IntLO = 42, CV_M4_IntHI = 43, CV_M4_Fir = 50, CV_M4_Psr = 51, CV_M4_FltF0 = 60, /* Floating point registers */ CV_M4_FltF1 = 61, CV_M4_FltF2 = 62, CV_M4_FltF3 = 63, CV_M4_FltF4 = 64, CV_M4_FltF5 = 65, CV_M4_FltF6 = 66, CV_M4_FltF7 = 67, CV_M4_FltF8 = 68, CV_M4_FltF9 = 69, CV_M4_FltF10 = 70, CV_M4_FltF11 = 71, CV_M4_FltF12 = 72, CV_M4_FltF13 = 73, CV_M4_FltF14 = 74, CV_M4_FltF15 = 75, CV_M4_FltF16 = 76, CV_M4_FltF17 = 77, CV_M4_FltF18 = 78, CV_M4_FltF19 = 79, CV_M4_FltF20 = 80, CV_M4_FltF21 = 81, CV_M4_FltF22 = 82, CV_M4_FltF23 = 83, CV_M4_FltF24 = 84, CV_M4_FltF25 = 85, CV_M4_FltF26 = 86, CV_M4_FltF27 = 87, CV_M4_FltF28 = 88, CV_M4_FltF29 = 89, CV_M4_FltF30 = 90, CV_M4_FltF31 = 91, CV_M4_FltFsr = 92, // Register set for the ALPHA AXP CV_ALPHA_NOREG = CV_REG_NONE, CV_ALPHA_FltF0 = 10, // Floating point registers CV_ALPHA_FltF1 = 11, CV_ALPHA_FltF2 = 12, CV_ALPHA_FltF3 = 13, CV_ALPHA_FltF4 = 14, CV_ALPHA_FltF5 = 15, CV_ALPHA_FltF6 = 16, CV_ALPHA_FltF7 = 17, CV_ALPHA_FltF8 = 18, CV_ALPHA_FltF9 = 19, CV_ALPHA_FltF10 = 20, CV_ALPHA_FltF11 = 21, CV_ALPHA_FltF12 = 22, CV_ALPHA_FltF13 = 23, CV_ALPHA_FltF14 = 24, CV_ALPHA_FltF15 = 25, CV_ALPHA_FltF16 = 26, CV_ALPHA_FltF17 = 27, CV_ALPHA_FltF18 = 28, CV_ALPHA_FltF19 = 29, CV_ALPHA_FltF20 = 30, CV_ALPHA_FltF21 = 31, CV_ALPHA_FltF22 = 32, CV_ALPHA_FltF23 = 33, CV_ALPHA_FltF24 = 34, CV_ALPHA_FltF25 = 35, CV_ALPHA_FltF26 = 36, CV_ALPHA_FltF27 = 37, CV_ALPHA_FltF28 = 38, CV_ALPHA_FltF29 = 39, CV_ALPHA_FltF30 = 40, CV_ALPHA_FltF31 = 41, CV_ALPHA_IntV0 = 42, // Integer registers CV_ALPHA_IntT0 = 43, CV_ALPHA_IntT1 = 44, CV_ALPHA_IntT2 = 45, CV_ALPHA_IntT3 = 46, CV_ALPHA_IntT4 = 47, CV_ALPHA_IntT5 = 48, CV_ALPHA_IntT6 = 49, CV_ALPHA_IntT7 = 50, CV_ALPHA_IntS0 = 51, CV_ALPHA_IntS1 = 52, CV_ALPHA_IntS2 = 53, CV_ALPHA_IntS3 = 54, CV_ALPHA_IntS4 = 55, CV_ALPHA_IntS5 = 56, CV_ALPHA_IntFP = 57, CV_ALPHA_IntA0 = 58, CV_ALPHA_IntA1 = 59, CV_ALPHA_IntA2 = 60, CV_ALPHA_IntA3 = 61, CV_ALPHA_IntA4 = 62, CV_ALPHA_IntA5 = 63, CV_ALPHA_IntT8 = 64, CV_ALPHA_IntT9 = 65, CV_ALPHA_IntT10 = 66, CV_ALPHA_IntT11 = 67, CV_ALPHA_IntRA = 68, CV_ALPHA_IntT12 = 69, CV_ALPHA_IntAT = 70, CV_ALPHA_IntGP = 71, CV_ALPHA_IntSP = 72, CV_ALPHA_IntZERO = 73, CV_ALPHA_Fpcr = 74, // Control registers CV_ALPHA_Fir = 75, CV_ALPHA_Psr = 76, CV_ALPHA_FltFsr = 77, CV_ALPHA_SoftFpcr = 78, // Register Set for Motorola/IBM PowerPC /* ** PowerPC General Registers ( User Level ) */ CV_PPC_GPR0 = 1, CV_PPC_GPR1 = 2, CV_PPC_GPR2 = 3, CV_PPC_GPR3 = 4, CV_PPC_GPR4 = 5, CV_PPC_GPR5 = 6, CV_PPC_GPR6 = 7, CV_PPC_GPR7 = 8, CV_PPC_GPR8 = 9, CV_PPC_GPR9 = 10, CV_PPC_GPR10 = 11, CV_PPC_GPR11 = 12, CV_PPC_GPR12 = 13, CV_PPC_GPR13 = 14, CV_PPC_GPR14 = 15, CV_PPC_GPR15 = 16, CV_PPC_GPR16 = 17, CV_PPC_GPR17 = 18, CV_PPC_GPR18 = 19, CV_PPC_GPR19 = 20, CV_PPC_GPR20 = 21, CV_PPC_GPR21 = 22, CV_PPC_GPR22 = 23, CV_PPC_GPR23 = 24, CV_PPC_GPR24 = 25, CV_PPC_GPR25 = 26, CV_PPC_GPR26 = 27, CV_PPC_GPR27 = 28, CV_PPC_GPR28 = 29, CV_PPC_GPR29 = 30, CV_PPC_GPR30 = 31, CV_PPC_GPR31 = 32, /* ** PowerPC Condition Register ( User Level ) */ CV_PPC_CR = 33, CV_PPC_CR0 = 34, CV_PPC_CR1 = 35, CV_PPC_CR2 = 36, CV_PPC_CR3 = 37, CV_PPC_CR4 = 38, CV_PPC_CR5 = 39, CV_PPC_CR6 = 40, CV_PPC_CR7 = 41, /* ** PowerPC Floating Point Registers ( User Level ) */ CV_PPC_FPR0 = 42, CV_PPC_FPR1 = 43, CV_PPC_FPR2 = 44, CV_PPC_FPR3 = 45, CV_PPC_FPR4 = 46, CV_PPC_FPR5 = 47, CV_PPC_FPR6 = 48, CV_PPC_FPR7 = 49, CV_PPC_FPR8 = 50, CV_PPC_FPR9 = 51, CV_PPC_FPR10 = 52, CV_PPC_FPR11 = 53, CV_PPC_FPR12 = 54, CV_PPC_FPR13 = 55, CV_PPC_FPR14 = 56, CV_PPC_FPR15 = 57, CV_PPC_FPR16 = 58, CV_PPC_FPR17 = 59, CV_PPC_FPR18 = 60, CV_PPC_FPR19 = 61, CV_PPC_FPR20 = 62, CV_PPC_FPR21 = 63, CV_PPC_FPR22 = 64, CV_PPC_FPR23 = 65, CV_PPC_FPR24 = 66, CV_PPC_FPR25 = 67, CV_PPC_FPR26 = 68, CV_PPC_FPR27 = 69, CV_PPC_FPR28 = 70, CV_PPC_FPR29 = 71, CV_PPC_FPR30 = 72, CV_PPC_FPR31 = 73, /* ** PowerPC Floating Point Status and Control Register ( User Level ) */ CV_PPC_FPSCR = 74, /* ** PowerPC Machine State Register ( Supervisor Level ) */ CV_PPC_MSR = 75, /* ** PowerPC Segment Registers ( Supervisor Level ) */ CV_PPC_SR0 = 76, CV_PPC_SR1 = 77, CV_PPC_SR2 = 78, CV_PPC_SR3 = 79, CV_PPC_SR4 = 80, CV_PPC_SR5 = 81, CV_PPC_SR6 = 82, CV_PPC_SR7 = 83, CV_PPC_SR8 = 84, CV_PPC_SR9 = 85, CV_PPC_SR10 = 86, CV_PPC_SR11 = 87, CV_PPC_SR12 = 88, CV_PPC_SR13 = 89, CV_PPC_SR14 = 90, CV_PPC_SR15 = 91, /* ** For all of the special purpose registers add 100 to the SPR# that the ** Motorola/IBM documentation gives with the exception of any imaginary ** registers. */ /* ** PowerPC Special Purpose Registers ( User Level ) */ CV_PPC_PC = 99, // PC (imaginary register) CV_PPC_MQ = 100, // MPC601 CV_PPC_XER = 101, CV_PPC_RTCU = 104, // MPC601 CV_PPC_RTCL = 105, // MPC601 CV_PPC_LR = 108, CV_PPC_CTR = 109, CV_PPC_COMPARE = 110, // part of XER (internal to the debugger only) CV_PPC_COUNT = 111, // part of XER (internal to the debugger only) /* ** PowerPC Special Purpose Registers ( Supervisor Level ) */ CV_PPC_DSISR = 118, CV_PPC_DAR = 119, CV_PPC_DEC = 122, CV_PPC_SDR1 = 125, CV_PPC_SRR0 = 126, CV_PPC_SRR1 = 127, CV_PPC_SPRG0 = 372, CV_PPC_SPRG1 = 373, CV_PPC_SPRG2 = 374, CV_PPC_SPRG3 = 375, CV_PPC_ASR = 280, // 64-bit implementations only CV_PPC_EAR = 382, CV_PPC_PVR = 287, CV_PPC_BAT0U = 628, CV_PPC_BAT0L = 629, CV_PPC_BAT1U = 630, CV_PPC_BAT1L = 631, CV_PPC_BAT2U = 632, CV_PPC_BAT2L = 633, CV_PPC_BAT3U = 634, CV_PPC_BAT3L = 635, CV_PPC_DBAT0U = 636, CV_PPC_DBAT0L = 637, CV_PPC_DBAT1U = 638, CV_PPC_DBAT1L = 639, CV_PPC_DBAT2U = 640, CV_PPC_DBAT2L = 641, CV_PPC_DBAT3U = 642, CV_PPC_DBAT3L = 643, /* ** PowerPC Special Purpose Registers Implementation Dependent ( Supervisor Level ) */ /* ** Doesn't appear that IBM/Motorola has finished defining these. */ CV_PPC_PMR0 = 1044, // MPC620, CV_PPC_PMR1 = 1045, // MPC620, CV_PPC_PMR2 = 1046, // MPC620, CV_PPC_PMR3 = 1047, // MPC620, CV_PPC_PMR4 = 1048, // MPC620, CV_PPC_PMR5 = 1049, // MPC620, CV_PPC_PMR6 = 1050, // MPC620, CV_PPC_PMR7 = 1051, // MPC620, CV_PPC_PMR8 = 1052, // MPC620, CV_PPC_PMR9 = 1053, // MPC620, CV_PPC_PMR10 = 1054, // MPC620, CV_PPC_PMR11 = 1055, // MPC620, CV_PPC_PMR12 = 1056, // MPC620, CV_PPC_PMR13 = 1057, // MPC620, CV_PPC_PMR14 = 1058, // MPC620, CV_PPC_PMR15 = 1059, // MPC620, CV_PPC_DMISS = 1076, // MPC603 CV_PPC_DCMP = 1077, // MPC603 CV_PPC_HASH1 = 1078, // MPC603 CV_PPC_HASH2 = 1079, // MPC603 CV_PPC_IMISS = 1080, // MPC603 CV_PPC_ICMP = 1081, // MPC603 CV_PPC_RPA = 1082, // MPC603 CV_PPC_HID0 = 1108, // MPC601, MPC603, MPC620 CV_PPC_HID1 = 1109, // MPC601 CV_PPC_HID2 = 1110, // MPC601, MPC603, MPC620 ( IABR ) CV_PPC_HID3 = 1111, // Not Defined CV_PPC_HID4 = 1112, // Not Defined CV_PPC_HID5 = 1113, // MPC601, MPC604, MPC620 ( DABR ) CV_PPC_HID6 = 1114, // Not Defined CV_PPC_HID7 = 1115, // Not Defined CV_PPC_HID8 = 1116, // MPC620 ( BUSCSR ) CV_PPC_HID9 = 1117, // MPC620 ( L2CSR ) CV_PPC_HID10 = 1118, // Not Defined CV_PPC_HID11 = 1119, // Not Defined CV_PPC_HID12 = 1120, // Not Defined CV_PPC_HID13 = 1121, // MPC604 ( HCR ) CV_PPC_HID14 = 1122, // Not Defined CV_PPC_HID15 = 1123, // MPC601, MPC604, MPC620 ( PIR ) // // JAVA VM registers // CV_JAVA_PC = 1, // // Register set for the Hitachi SH3 // CV_SH3_NOREG = CV_REG_NONE, CV_SH3_IntR0 = 10, // CPU REGISTER CV_SH3_IntR1 = 11, CV_SH3_IntR2 = 12, CV_SH3_IntR3 = 13, CV_SH3_IntR4 = 14, CV_SH3_IntR5 = 15, CV_SH3_IntR6 = 16, CV_SH3_IntR7 = 17, CV_SH3_IntR8 = 18, CV_SH3_IntR9 = 19, CV_SH3_IntR10 = 20, CV_SH3_IntR11 = 21, CV_SH3_IntR12 = 22, CV_SH3_IntR13 = 23, CV_SH3_IntFp = 24, CV_SH3_IntSp = 25, CV_SH3_Gbr = 38, CV_SH3_Pr = 39, CV_SH3_Mach = 40, CV_SH3_Macl = 41, CV_SH3_Pc = 50, CV_SH3_Sr = 51, CV_SH3_BarA = 60, CV_SH3_BasrA = 61, CV_SH3_BamrA = 62, CV_SH3_BbrA = 63, CV_SH3_BarB = 64, CV_SH3_BasrB = 65, CV_SH3_BamrB = 66, CV_SH3_BbrB = 67, CV_SH3_BdrB = 68, CV_SH3_BdmrB = 69, CV_SH3_Brcr = 70, // // Additional registers for Hitachi SH processors // CV_SH_Fpscr = 75, // floating point status/control register CV_SH_Fpul = 76, // floating point communication register CV_SH_FpR0 = 80, // Floating point registers CV_SH_FpR1 = 81, CV_SH_FpR2 = 82, CV_SH_FpR3 = 83, CV_SH_FpR4 = 84, CV_SH_FpR5 = 85, CV_SH_FpR6 = 86, CV_SH_FpR7 = 87, CV_SH_FpR8 = 88, CV_SH_FpR9 = 89, CV_SH_FpR10 = 90, CV_SH_FpR11 = 91, CV_SH_FpR12 = 92, CV_SH_FpR13 = 93, CV_SH_FpR14 = 94, CV_SH_FpR15 = 95, CV_SH_XFpR0 = 96, CV_SH_XFpR1 = 97, CV_SH_XFpR2 = 98, CV_SH_XFpR3 = 99, CV_SH_XFpR4 = 100, CV_SH_XFpR5 = 101, CV_SH_XFpR6 = 102, CV_SH_XFpR7 = 103, CV_SH_XFpR8 = 104, CV_SH_XFpR9 = 105, CV_SH_XFpR10 = 106, CV_SH_XFpR11 = 107, CV_SH_XFpR12 = 108, CV_SH_XFpR13 = 109, CV_SH_XFpR14 = 110, CV_SH_XFpR15 = 111, // // Register set for the ARM processor. // CV_ARM_NOREG = CV_REG_NONE, CV_ARM_R0 = 10, CV_ARM_R1 = 11, CV_ARM_R2 = 12, CV_ARM_R3 = 13, CV_ARM_R4 = 14, CV_ARM_R5 = 15, CV_ARM_R6 = 16, CV_ARM_R7 = 17, CV_ARM_R8 = 18, CV_ARM_R9 = 19, CV_ARM_R10 = 20, CV_ARM_R11 = 21, // Frame pointer, if allocated CV_ARM_R12 = 22, CV_ARM_SP = 23, // Stack pointer CV_ARM_LR = 24, // Link Register CV_ARM_PC = 25, // Program counter CV_ARM_CPSR = 26, // Current program status register CV_ARM_ACC0 = 27, // DSP co-processor 0 40 bit accumulator // // Registers for ARM VFP10 support // CV_ARM_FPSCR = 40, CV_ARM_FPEXC = 41, CV_ARM_FS0 = 50, CV_ARM_FS1 = 51, CV_ARM_FS2 = 52, CV_ARM_FS3 = 53, CV_ARM_FS4 = 54, CV_ARM_FS5 = 55, CV_ARM_FS6 = 56, CV_ARM_FS7 = 57, CV_ARM_FS8 = 58, CV_ARM_FS9 = 59, CV_ARM_FS10 = 60, CV_ARM_FS11 = 61, CV_ARM_FS12 = 62, CV_ARM_FS13 = 63, CV_ARM_FS14 = 64, CV_ARM_FS15 = 65, CV_ARM_FS16 = 66, CV_ARM_FS17 = 67, CV_ARM_FS18 = 68, CV_ARM_FS19 = 69, CV_ARM_FS20 = 70, CV_ARM_FS21 = 71, CV_ARM_FS22 = 72, CV_ARM_FS23 = 73, CV_ARM_FS24 = 74, CV_ARM_FS25 = 75, CV_ARM_FS26 = 76, CV_ARM_FS27 = 77, CV_ARM_FS28 = 78, CV_ARM_FS29 = 79, CV_ARM_FS30 = 80, CV_ARM_FS31 = 81, // // ARM VFP Floating Point Extra control registers // CV_ARM_FPEXTRA0 = 90, CV_ARM_FPEXTRA1 = 91, CV_ARM_FPEXTRA2 = 92, CV_ARM_FPEXTRA3 = 93, CV_ARM_FPEXTRA4 = 94, CV_ARM_FPEXTRA5 = 95, CV_ARM_FPEXTRA6 = 96, CV_ARM_FPEXTRA7 = 97, // XSCALE Concan co-processor registers CV_ARM_WR0 = 128, CV_ARM_WR1 = 129, CV_ARM_WR2 = 130, CV_ARM_WR3 = 131, CV_ARM_WR4 = 132, CV_ARM_WR5 = 133, CV_ARM_WR6 = 134, CV_ARM_WR7 = 135, CV_ARM_WR8 = 136, CV_ARM_WR9 = 137, CV_ARM_WR10 = 138, CV_ARM_WR11 = 139, CV_ARM_WR12 = 140, CV_ARM_WR13 = 141, CV_ARM_WR14 = 142, CV_ARM_WR15 = 143, // XSCALE Concan co-processor control registers CV_ARM_WCID = 144, CV_ARM_WCON = 145, CV_ARM_WCSSF = 146, CV_ARM_WCASF = 147, CV_ARM_WC4 = 148, CV_ARM_WC5 = 149, CV_ARM_WC6 = 150, CV_ARM_WC7 = 151, CV_ARM_WCGR0 = 152, CV_ARM_WCGR1 = 153, CV_ARM_WCGR2 = 154, CV_ARM_WCGR3 = 155, CV_ARM_WC12 = 156, CV_ARM_WC13 = 157, CV_ARM_WC14 = 158, CV_ARM_WC15 = 159, // // ARM VFPv3/Neon extended floating Point // CV_ARM_FS32 = 200, CV_ARM_FS33 = 201, CV_ARM_FS34 = 202, CV_ARM_FS35 = 203, CV_ARM_FS36 = 204, CV_ARM_FS37 = 205, CV_ARM_FS38 = 206, CV_ARM_FS39 = 207, CV_ARM_FS40 = 208, CV_ARM_FS41 = 209, CV_ARM_FS42 = 210, CV_ARM_FS43 = 211, CV_ARM_FS44 = 212, CV_ARM_FS45 = 213, CV_ARM_FS46 = 214, CV_ARM_FS47 = 215, CV_ARM_FS48 = 216, CV_ARM_FS49 = 217, CV_ARM_FS50 = 218, CV_ARM_FS51 = 219, CV_ARM_FS52 = 220, CV_ARM_FS53 = 221, CV_ARM_FS54 = 222, CV_ARM_FS55 = 223, CV_ARM_FS56 = 224, CV_ARM_FS57 = 225, CV_ARM_FS58 = 226, CV_ARM_FS59 = 227, CV_ARM_FS60 = 228, CV_ARM_FS61 = 229, CV_ARM_FS62 = 230, CV_ARM_FS63 = 231, // ARM double-precision floating point CV_ARM_ND0 = 300, CV_ARM_ND1 = 301, CV_ARM_ND2 = 302, CV_ARM_ND3 = 303, CV_ARM_ND4 = 304, CV_ARM_ND5 = 305, CV_ARM_ND6 = 306, CV_ARM_ND7 = 307, CV_ARM_ND8 = 308, CV_ARM_ND9 = 309, CV_ARM_ND10 = 310, CV_ARM_ND11 = 311, CV_ARM_ND12 = 312, CV_ARM_ND13 = 313, CV_ARM_ND14 = 314, CV_ARM_ND15 = 315, CV_ARM_ND16 = 316, CV_ARM_ND17 = 317, CV_ARM_ND18 = 318, CV_ARM_ND19 = 319, CV_ARM_ND20 = 320, CV_ARM_ND21 = 321, CV_ARM_ND22 = 322, CV_ARM_ND23 = 323, CV_ARM_ND24 = 324, CV_ARM_ND25 = 325, CV_ARM_ND26 = 326, CV_ARM_ND27 = 327, CV_ARM_ND28 = 328, CV_ARM_ND29 = 329, CV_ARM_ND30 = 330, CV_ARM_ND31 = 331, // ARM extended precision floating point CV_ARM_NQ0 = 400, CV_ARM_NQ1 = 401, CV_ARM_NQ2 = 402, CV_ARM_NQ3 = 403, CV_ARM_NQ4 = 404, CV_ARM_NQ5 = 405, CV_ARM_NQ6 = 406, CV_ARM_NQ7 = 407, CV_ARM_NQ8 = 408, CV_ARM_NQ9 = 409, CV_ARM_NQ10 = 410, CV_ARM_NQ11 = 411, CV_ARM_NQ12 = 412, CV_ARM_NQ13 = 413, CV_ARM_NQ14 = 414, CV_ARM_NQ15 = 415, // // Register set for ARM64 // CV_ARM64_NOREG = CV_REG_NONE, // General purpose 32-bit integer registers CV_ARM64_W0 = 10, CV_ARM64_W1 = 11, CV_ARM64_W2 = 12, CV_ARM64_W3 = 13, CV_ARM64_W4 = 14, CV_ARM64_W5 = 15, CV_ARM64_W6 = 16, CV_ARM64_W7 = 17, CV_ARM64_W8 = 18, CV_ARM64_W9 = 19, CV_ARM64_W10 = 20, CV_ARM64_W11 = 21, CV_ARM64_W12 = 22, CV_ARM64_W13 = 23, CV_ARM64_W14 = 24, CV_ARM64_W15 = 25, CV_ARM64_W16 = 26, CV_ARM64_W17 = 27, CV_ARM64_W18 = 28, CV_ARM64_W19 = 29, CV_ARM64_W20 = 30, CV_ARM64_W21 = 31, CV_ARM64_W22 = 32, CV_ARM64_W23 = 33, CV_ARM64_W24 = 34, CV_ARM64_W25 = 35, CV_ARM64_W26 = 36, CV_ARM64_W27 = 37, CV_ARM64_W28 = 38, CV_ARM64_W29 = 39, CV_ARM64_W30 = 40, CV_ARM64_WZR = 41, // General purpose 64-bit integer registers CV_ARM64_X0 = 50, CV_ARM64_X1 = 51, CV_ARM64_X2 = 52, CV_ARM64_X3 = 53, CV_ARM64_X4 = 54, CV_ARM64_X5 = 55, CV_ARM64_X6 = 56, CV_ARM64_X7 = 57, CV_ARM64_X8 = 58, CV_ARM64_X9 = 59, CV_ARM64_X10 = 60, CV_ARM64_X11 = 61, CV_ARM64_X12 = 62, CV_ARM64_X13 = 63, CV_ARM64_X14 = 64, CV_ARM64_X15 = 65, CV_ARM64_IP0 = 66, CV_ARM64_IP1 = 67, CV_ARM64_X18 = 68, CV_ARM64_X19 = 69, CV_ARM64_X20 = 70, CV_ARM64_X21 = 71, CV_ARM64_X22 = 72, CV_ARM64_X23 = 73, CV_ARM64_X24 = 74, CV_ARM64_X25 = 75, CV_ARM64_X26 = 76, CV_ARM64_X27 = 77, CV_ARM64_X28 = 78, CV_ARM64_FP = 79, CV_ARM64_LR = 80, CV_ARM64_SP = 81, CV_ARM64_ZR = 82, CV_ARM64_PC = 83, // status registers CV_ARM64_NZCV = 90, CV_ARM64_CPSR = 91, // 32-bit floating point registers CV_ARM64_S0 = 100, CV_ARM64_S1 = 101, CV_ARM64_S2 = 102, CV_ARM64_S3 = 103, CV_ARM64_S4 = 104, CV_ARM64_S5 = 105, CV_ARM64_S6 = 106, CV_ARM64_S7 = 107, CV_ARM64_S8 = 108, CV_ARM64_S9 = 109, CV_ARM64_S10 = 110, CV_ARM64_S11 = 111, CV_ARM64_S12 = 112, CV_ARM64_S13 = 113, CV_ARM64_S14 = 114, CV_ARM64_S15 = 115, CV_ARM64_S16 = 116, CV_ARM64_S17 = 117, CV_ARM64_S18 = 118, CV_ARM64_S19 = 119, CV_ARM64_S20 = 120, CV_ARM64_S21 = 121, CV_ARM64_S22 = 122, CV_ARM64_S23 = 123, CV_ARM64_S24 = 124, CV_ARM64_S25 = 125, CV_ARM64_S26 = 126, CV_ARM64_S27 = 127, CV_ARM64_S28 = 128, CV_ARM64_S29 = 129, CV_ARM64_S30 = 130, CV_ARM64_S31 = 131, // 64-bit floating point registers CV_ARM64_D0 = 140, CV_ARM64_D1 = 141, CV_ARM64_D2 = 142, CV_ARM64_D3 = 143, CV_ARM64_D4 = 144, CV_ARM64_D5 = 145, CV_ARM64_D6 = 146, CV_ARM64_D7 = 147, CV_ARM64_D8 = 148, CV_ARM64_D9 = 149, CV_ARM64_D10 = 150, CV_ARM64_D11 = 151, CV_ARM64_D12 = 152, CV_ARM64_D13 = 153, CV_ARM64_D14 = 154, CV_ARM64_D15 = 155, CV_ARM64_D16 = 156, CV_ARM64_D17 = 157, CV_ARM64_D18 = 158, CV_ARM64_D19 = 159, CV_ARM64_D20 = 160, CV_ARM64_D21 = 161, CV_ARM64_D22 = 162, CV_ARM64_D23 = 163, CV_ARM64_D24 = 164, CV_ARM64_D25 = 165, CV_ARM64_D26 = 166, CV_ARM64_D27 = 167, CV_ARM64_D28 = 168, CV_ARM64_D29 = 169, CV_ARM64_D30 = 170, CV_ARM64_D31 = 171, // 128-bit SIMD registers CV_ARM64_Q0 = 180, CV_ARM64_Q1 = 181, CV_ARM64_Q2 = 182, CV_ARM64_Q3 = 183, CV_ARM64_Q4 = 184, CV_ARM64_Q5 = 185, CV_ARM64_Q6 = 186, CV_ARM64_Q7 = 187, CV_ARM64_Q8 = 188, CV_ARM64_Q9 = 189, CV_ARM64_Q10 = 190, CV_ARM64_Q11 = 191, CV_ARM64_Q12 = 192, CV_ARM64_Q13 = 193, CV_ARM64_Q14 = 194, CV_ARM64_Q15 = 195, CV_ARM64_Q16 = 196, CV_ARM64_Q17 = 197, CV_ARM64_Q18 = 198, CV_ARM64_Q19 = 199, CV_ARM64_Q20 = 200, CV_ARM64_Q21 = 201, CV_ARM64_Q22 = 202, CV_ARM64_Q23 = 203, CV_ARM64_Q24 = 204, CV_ARM64_Q25 = 205, CV_ARM64_Q26 = 206, CV_ARM64_Q27 = 207, CV_ARM64_Q28 = 208, CV_ARM64_Q29 = 209, CV_ARM64_Q30 = 210, CV_ARM64_Q31 = 211, // Floating point status register CV_ARM64_FPSR = 220, // // Register set for Intel IA64 // CV_IA64_NOREG = CV_REG_NONE, // Branch Registers CV_IA64_Br0 = 512, CV_IA64_Br1 = 513, CV_IA64_Br2 = 514, CV_IA64_Br3 = 515, CV_IA64_Br4 = 516, CV_IA64_Br5 = 517, CV_IA64_Br6 = 518, CV_IA64_Br7 = 519, // Predicate Registers CV_IA64_P0 = 704, CV_IA64_P1 = 705, CV_IA64_P2 = 706, CV_IA64_P3 = 707, CV_IA64_P4 = 708, CV_IA64_P5 = 709, CV_IA64_P6 = 710, CV_IA64_P7 = 711, CV_IA64_P8 = 712, CV_IA64_P9 = 713, CV_IA64_P10 = 714, CV_IA64_P11 = 715, CV_IA64_P12 = 716, CV_IA64_P13 = 717, CV_IA64_P14 = 718, CV_IA64_P15 = 719, CV_IA64_P16 = 720, CV_IA64_P17 = 721, CV_IA64_P18 = 722, CV_IA64_P19 = 723, CV_IA64_P20 = 724, CV_IA64_P21 = 725, CV_IA64_P22 = 726, CV_IA64_P23 = 727, CV_IA64_P24 = 728, CV_IA64_P25 = 729, CV_IA64_P26 = 730, CV_IA64_P27 = 731, CV_IA64_P28 = 732, CV_IA64_P29 = 733, CV_IA64_P30 = 734, CV_IA64_P31 = 735, CV_IA64_P32 = 736, CV_IA64_P33 = 737, CV_IA64_P34 = 738, CV_IA64_P35 = 739, CV_IA64_P36 = 740, CV_IA64_P37 = 741, CV_IA64_P38 = 742, CV_IA64_P39 = 743, CV_IA64_P40 = 744, CV_IA64_P41 = 745, CV_IA64_P42 = 746, CV_IA64_P43 = 747, CV_IA64_P44 = 748, CV_IA64_P45 = 749, CV_IA64_P46 = 750, CV_IA64_P47 = 751, CV_IA64_P48 = 752, CV_IA64_P49 = 753, CV_IA64_P50 = 754, CV_IA64_P51 = 755, CV_IA64_P52 = 756, CV_IA64_P53 = 757, CV_IA64_P54 = 758, CV_IA64_P55 = 759, CV_IA64_P56 = 760, CV_IA64_P57 = 761, CV_IA64_P58 = 762, CV_IA64_P59 = 763, CV_IA64_P60 = 764, CV_IA64_P61 = 765, CV_IA64_P62 = 766, CV_IA64_P63 = 767, CV_IA64_Preds = 768, // Banked General Registers CV_IA64_IntH0 = 832, CV_IA64_IntH1 = 833, CV_IA64_IntH2 = 834, CV_IA64_IntH3 = 835, CV_IA64_IntH4 = 836, CV_IA64_IntH5 = 837, CV_IA64_IntH6 = 838, CV_IA64_IntH7 = 839, CV_IA64_IntH8 = 840, CV_IA64_IntH9 = 841, CV_IA64_IntH10 = 842, CV_IA64_IntH11 = 843, CV_IA64_IntH12 = 844, CV_IA64_IntH13 = 845, CV_IA64_IntH14 = 846, CV_IA64_IntH15 = 847, // Special Registers CV_IA64_Ip = 1016, CV_IA64_Umask = 1017, CV_IA64_Cfm = 1018, CV_IA64_Psr = 1019, // Banked General Registers CV_IA64_Nats = 1020, CV_IA64_Nats2 = 1021, CV_IA64_Nats3 = 1022, // General-Purpose Registers // Integer registers CV_IA64_IntR0 = 1024, CV_IA64_IntR1 = 1025, CV_IA64_IntR2 = 1026, CV_IA64_IntR3 = 1027, CV_IA64_IntR4 = 1028, CV_IA64_IntR5 = 1029, CV_IA64_IntR6 = 1030, CV_IA64_IntR7 = 1031, CV_IA64_IntR8 = 1032, CV_IA64_IntR9 = 1033, CV_IA64_IntR10 = 1034, CV_IA64_IntR11 = 1035, CV_IA64_IntR12 = 1036, CV_IA64_IntR13 = 1037, CV_IA64_IntR14 = 1038, CV_IA64_IntR15 = 1039, CV_IA64_IntR16 = 1040, CV_IA64_IntR17 = 1041, CV_IA64_IntR18 = 1042, CV_IA64_IntR19 = 1043, CV_IA64_IntR20 = 1044, CV_IA64_IntR21 = 1045, CV_IA64_IntR22 = 1046, CV_IA64_IntR23 = 1047, CV_IA64_IntR24 = 1048, CV_IA64_IntR25 = 1049, CV_IA64_IntR26 = 1050, CV_IA64_IntR27 = 1051, CV_IA64_IntR28 = 1052, CV_IA64_IntR29 = 1053, CV_IA64_IntR30 = 1054, CV_IA64_IntR31 = 1055, // Register Stack CV_IA64_IntR32 = 1056, CV_IA64_IntR33 = 1057, CV_IA64_IntR34 = 1058, CV_IA64_IntR35 = 1059, CV_IA64_IntR36 = 1060, CV_IA64_IntR37 = 1061, CV_IA64_IntR38 = 1062, CV_IA64_IntR39 = 1063, CV_IA64_IntR40 = 1064, CV_IA64_IntR41 = 1065, CV_IA64_IntR42 = 1066, CV_IA64_IntR43 = 1067, CV_IA64_IntR44 = 1068, CV_IA64_IntR45 = 1069, CV_IA64_IntR46 = 1070, CV_IA64_IntR47 = 1071, CV_IA64_IntR48 = 1072, CV_IA64_IntR49 = 1073, CV_IA64_IntR50 = 1074, CV_IA64_IntR51 = 1075, CV_IA64_IntR52 = 1076, CV_IA64_IntR53 = 1077, CV_IA64_IntR54 = 1078, CV_IA64_IntR55 = 1079, CV_IA64_IntR56 = 1080, CV_IA64_IntR57 = 1081, CV_IA64_IntR58 = 1082, CV_IA64_IntR59 = 1083, CV_IA64_IntR60 = 1084, CV_IA64_IntR61 = 1085, CV_IA64_IntR62 = 1086, CV_IA64_IntR63 = 1087, CV_IA64_IntR64 = 1088, CV_IA64_IntR65 = 1089, CV_IA64_IntR66 = 1090, CV_IA64_IntR67 = 1091, CV_IA64_IntR68 = 1092, CV_IA64_IntR69 = 1093, CV_IA64_IntR70 = 1094, CV_IA64_IntR71 = 1095, CV_IA64_IntR72 = 1096, CV_IA64_IntR73 = 1097, CV_IA64_IntR74 = 1098, CV_IA64_IntR75 = 1099, CV_IA64_IntR76 = 1100, CV_IA64_IntR77 = 1101, CV_IA64_IntR78 = 1102, CV_IA64_IntR79 = 1103, CV_IA64_IntR80 = 1104, CV_IA64_IntR81 = 1105, CV_IA64_IntR82 = 1106, CV_IA64_IntR83 = 1107, CV_IA64_IntR84 = 1108, CV_IA64_IntR85 = 1109, CV_IA64_IntR86 = 1110, CV_IA64_IntR87 = 1111, CV_IA64_IntR88 = 1112, CV_IA64_IntR89 = 1113, CV_IA64_IntR90 = 1114, CV_IA64_IntR91 = 1115, CV_IA64_IntR92 = 1116, CV_IA64_IntR93 = 1117, CV_IA64_IntR94 = 1118, CV_IA64_IntR95 = 1119, CV_IA64_IntR96 = 1120, CV_IA64_IntR97 = 1121, CV_IA64_IntR98 = 1122, CV_IA64_IntR99 = 1123, CV_IA64_IntR100 = 1124, CV_IA64_IntR101 = 1125, CV_IA64_IntR102 = 1126, CV_IA64_IntR103 = 1127, CV_IA64_IntR104 = 1128, CV_IA64_IntR105 = 1129, CV_IA64_IntR106 = 1130, CV_IA64_IntR107 = 1131, CV_IA64_IntR108 = 1132, CV_IA64_IntR109 = 1133, CV_IA64_IntR110 = 1134, CV_IA64_IntR111 = 1135, CV_IA64_IntR112 = 1136, CV_IA64_IntR113 = 1137, CV_IA64_IntR114 = 1138, CV_IA64_IntR115 = 1139, CV_IA64_IntR116 = 1140, CV_IA64_IntR117 = 1141, CV_IA64_IntR118 = 1142, CV_IA64_IntR119 = 1143, CV_IA64_IntR120 = 1144, CV_IA64_IntR121 = 1145, CV_IA64_IntR122 = 1146, CV_IA64_IntR123 = 1147, CV_IA64_IntR124 = 1148, CV_IA64_IntR125 = 1149, CV_IA64_IntR126 = 1150, CV_IA64_IntR127 = 1151, // Floating-Point Registers // Low Floating Point Registers CV_IA64_FltF0 = 2048, CV_IA64_FltF1 = 2049, CV_IA64_FltF2 = 2050, CV_IA64_FltF3 = 2051, CV_IA64_FltF4 = 2052, CV_IA64_FltF5 = 2053, CV_IA64_FltF6 = 2054, CV_IA64_FltF7 = 2055, CV_IA64_FltF8 = 2056, CV_IA64_FltF9 = 2057, CV_IA64_FltF10 = 2058, CV_IA64_FltF11 = 2059, CV_IA64_FltF12 = 2060, CV_IA64_FltF13 = 2061, CV_IA64_FltF14 = 2062, CV_IA64_FltF15 = 2063, CV_IA64_FltF16 = 2064, CV_IA64_FltF17 = 2065, CV_IA64_FltF18 = 2066, CV_IA64_FltF19 = 2067, CV_IA64_FltF20 = 2068, CV_IA64_FltF21 = 2069, CV_IA64_FltF22 = 2070, CV_IA64_FltF23 = 2071, CV_IA64_FltF24 = 2072, CV_IA64_FltF25 = 2073, CV_IA64_FltF26 = 2074, CV_IA64_FltF27 = 2075, CV_IA64_FltF28 = 2076, CV_IA64_FltF29 = 2077, CV_IA64_FltF30 = 2078, CV_IA64_FltF31 = 2079, // High Floating Point Registers CV_IA64_FltF32 = 2080, CV_IA64_FltF33 = 2081, CV_IA64_FltF34 = 2082, CV_IA64_FltF35 = 2083, CV_IA64_FltF36 = 2084, CV_IA64_FltF37 = 2085, CV_IA64_FltF38 = 2086, CV_IA64_FltF39 = 2087, CV_IA64_FltF40 = 2088, CV_IA64_FltF41 = 2089, CV_IA64_FltF42 = 2090, CV_IA64_FltF43 = 2091, CV_IA64_FltF44 = 2092, CV_IA64_FltF45 = 2093, CV_IA64_FltF46 = 2094, CV_IA64_FltF47 = 2095, CV_IA64_FltF48 = 2096, CV_IA64_FltF49 = 2097, CV_IA64_FltF50 = 2098, CV_IA64_FltF51 = 2099, CV_IA64_FltF52 = 2100, CV_IA64_FltF53 = 2101, CV_IA64_FltF54 = 2102, CV_IA64_FltF55 = 2103, CV_IA64_FltF56 = 2104, CV_IA64_FltF57 = 2105, CV_IA64_FltF58 = 2106, CV_IA64_FltF59 = 2107, CV_IA64_FltF60 = 2108, CV_IA64_FltF61 = 2109, CV_IA64_FltF62 = 2110, CV_IA64_FltF63 = 2111, CV_IA64_FltF64 = 2112, CV_IA64_FltF65 = 2113, CV_IA64_FltF66 = 2114, CV_IA64_FltF67 = 2115, CV_IA64_FltF68 = 2116, CV_IA64_FltF69 = 2117, CV_IA64_FltF70 = 2118, CV_IA64_FltF71 = 2119, CV_IA64_FltF72 = 2120, CV_IA64_FltF73 = 2121, CV_IA64_FltF74 = 2122, CV_IA64_FltF75 = 2123, CV_IA64_FltF76 = 2124, CV_IA64_FltF77 = 2125, CV_IA64_FltF78 = 2126, CV_IA64_FltF79 = 2127, CV_IA64_FltF80 = 2128, CV_IA64_FltF81 = 2129, CV_IA64_FltF82 = 2130, CV_IA64_FltF83 = 2131, CV_IA64_FltF84 = 2132, CV_IA64_FltF85 = 2133, CV_IA64_FltF86 = 2134, CV_IA64_FltF87 = 2135, CV_IA64_FltF88 = 2136, CV_IA64_FltF89 = 2137, CV_IA64_FltF90 = 2138, CV_IA64_FltF91 = 2139, CV_IA64_FltF92 = 2140, CV_IA64_FltF93 = 2141, CV_IA64_FltF94 = 2142, CV_IA64_FltF95 = 2143, CV_IA64_FltF96 = 2144, CV_IA64_FltF97 = 2145, CV_IA64_FltF98 = 2146, CV_IA64_FltF99 = 2147, CV_IA64_FltF100 = 2148, CV_IA64_FltF101 = 2149, CV_IA64_FltF102 = 2150, CV_IA64_FltF103 = 2151, CV_IA64_FltF104 = 2152, CV_IA64_FltF105 = 2153, CV_IA64_FltF106 = 2154, CV_IA64_FltF107 = 2155, CV_IA64_FltF108 = 2156, CV_IA64_FltF109 = 2157, CV_IA64_FltF110 = 2158, CV_IA64_FltF111 = 2159, CV_IA64_FltF112 = 2160, CV_IA64_FltF113 = 2161, CV_IA64_FltF114 = 2162, CV_IA64_FltF115 = 2163, CV_IA64_FltF116 = 2164, CV_IA64_FltF117 = 2165, CV_IA64_FltF118 = 2166, CV_IA64_FltF119 = 2167, CV_IA64_FltF120 = 2168, CV_IA64_FltF121 = 2169, CV_IA64_FltF122 = 2170, CV_IA64_FltF123 = 2171, CV_IA64_FltF124 = 2172, CV_IA64_FltF125 = 2173, CV_IA64_FltF126 = 2174, CV_IA64_FltF127 = 2175, // Application Registers CV_IA64_ApKR0 = 3072, CV_IA64_ApKR1 = 3073, CV_IA64_ApKR2 = 3074, CV_IA64_ApKR3 = 3075, CV_IA64_ApKR4 = 3076, CV_IA64_ApKR5 = 3077, CV_IA64_ApKR6 = 3078, CV_IA64_ApKR7 = 3079, CV_IA64_AR8 = 3080, CV_IA64_AR9 = 3081, CV_IA64_AR10 = 3082, CV_IA64_AR11 = 3083, CV_IA64_AR12 = 3084, CV_IA64_AR13 = 3085, CV_IA64_AR14 = 3086, CV_IA64_AR15 = 3087, CV_IA64_RsRSC = 3088, CV_IA64_RsBSP = 3089, CV_IA64_RsBSPSTORE = 3090, CV_IA64_RsRNAT = 3091, CV_IA64_AR20 = 3092, CV_IA64_StFCR = 3093, CV_IA64_AR22 = 3094, CV_IA64_AR23 = 3095, CV_IA64_EFLAG = 3096, CV_IA64_CSD = 3097, CV_IA64_SSD = 3098, CV_IA64_CFLG = 3099, CV_IA64_StFSR = 3100, CV_IA64_StFIR = 3101, CV_IA64_StFDR = 3102, CV_IA64_AR31 = 3103, CV_IA64_ApCCV = 3104, CV_IA64_AR33 = 3105, CV_IA64_AR34 = 3106, CV_IA64_AR35 = 3107, CV_IA64_ApUNAT = 3108, CV_IA64_AR37 = 3109, CV_IA64_AR38 = 3110, CV_IA64_AR39 = 3111, CV_IA64_StFPSR = 3112, CV_IA64_AR41 = 3113, CV_IA64_AR42 = 3114, CV_IA64_AR43 = 3115, CV_IA64_ApITC = 3116, CV_IA64_AR45 = 3117, CV_IA64_AR46 = 3118, CV_IA64_AR47 = 3119, CV_IA64_AR48 = 3120, CV_IA64_AR49 = 3121, CV_IA64_AR50 = 3122, CV_IA64_AR51 = 3123, CV_IA64_AR52 = 3124, CV_IA64_AR53 = 3125, CV_IA64_AR54 = 3126, CV_IA64_AR55 = 3127, CV_IA64_AR56 = 3128, CV_IA64_AR57 = 3129, CV_IA64_AR58 = 3130, CV_IA64_AR59 = 3131, CV_IA64_AR60 = 3132, CV_IA64_AR61 = 3133, CV_IA64_AR62 = 3134, CV_IA64_AR63 = 3135, CV_IA64_RsPFS = 3136, CV_IA64_ApLC = 3137, CV_IA64_ApEC = 3138, CV_IA64_AR67 = 3139, CV_IA64_AR68 = 3140, CV_IA64_AR69 = 3141, CV_IA64_AR70 = 3142, CV_IA64_AR71 = 3143, CV_IA64_AR72 = 3144, CV_IA64_AR73 = 3145, CV_IA64_AR74 = 3146, CV_IA64_AR75 = 3147, CV_IA64_AR76 = 3148, CV_IA64_AR77 = 3149, CV_IA64_AR78 = 3150, CV_IA64_AR79 = 3151, CV_IA64_AR80 = 3152, CV_IA64_AR81 = 3153, CV_IA64_AR82 = 3154, CV_IA64_AR83 = 3155, CV_IA64_AR84 = 3156, CV_IA64_AR85 = 3157, CV_IA64_AR86 = 3158, CV_IA64_AR87 = 3159, CV_IA64_AR88 = 3160, CV_IA64_AR89 = 3161, CV_IA64_AR90 = 3162, CV_IA64_AR91 = 3163, CV_IA64_AR92 = 3164, CV_IA64_AR93 = 3165, CV_IA64_AR94 = 3166, CV_IA64_AR95 = 3167, CV_IA64_AR96 = 3168, CV_IA64_AR97 = 3169, CV_IA64_AR98 = 3170, CV_IA64_AR99 = 3171, CV_IA64_AR100 = 3172, CV_IA64_AR101 = 3173, CV_IA64_AR102 = 3174, CV_IA64_AR103 = 3175, CV_IA64_AR104 = 3176, CV_IA64_AR105 = 3177, CV_IA64_AR106 = 3178, CV_IA64_AR107 = 3179, CV_IA64_AR108 = 3180, CV_IA64_AR109 = 3181, CV_IA64_AR110 = 3182, CV_IA64_AR111 = 3183, CV_IA64_AR112 = 3184, CV_IA64_AR113 = 3185, CV_IA64_AR114 = 3186, CV_IA64_AR115 = 3187, CV_IA64_AR116 = 3188, CV_IA64_AR117 = 3189, CV_IA64_AR118 = 3190, CV_IA64_AR119 = 3191, CV_IA64_AR120 = 3192, CV_IA64_AR121 = 3193, CV_IA64_AR122 = 3194, CV_IA64_AR123 = 3195, CV_IA64_AR124 = 3196, CV_IA64_AR125 = 3197, CV_IA64_AR126 = 3198, CV_IA64_AR127 = 3199, // CPUID Registers CV_IA64_CPUID0 = 3328, CV_IA64_CPUID1 = 3329, CV_IA64_CPUID2 = 3330, CV_IA64_CPUID3 = 3331, CV_IA64_CPUID4 = 3332, // Control Registers CV_IA64_ApDCR = 4096, CV_IA64_ApITM = 4097, CV_IA64_ApIVA = 4098, CV_IA64_CR3 = 4099, CV_IA64_CR4 = 4100, CV_IA64_CR5 = 4101, CV_IA64_CR6 = 4102, CV_IA64_CR7 = 4103, CV_IA64_ApPTA = 4104, CV_IA64_ApGPTA = 4105, CV_IA64_CR10 = 4106, CV_IA64_CR11 = 4107, CV_IA64_CR12 = 4108, CV_IA64_CR13 = 4109, CV_IA64_CR14 = 4110, CV_IA64_CR15 = 4111, CV_IA64_StIPSR = 4112, CV_IA64_StISR = 4113, CV_IA64_CR18 = 4114, CV_IA64_StIIP = 4115, CV_IA64_StIFA = 4116, CV_IA64_StITIR = 4117, CV_IA64_StIIPA = 4118, CV_IA64_StIFS = 4119, CV_IA64_StIIM = 4120, CV_IA64_StIHA = 4121, CV_IA64_CR26 = 4122, CV_IA64_CR27 = 4123, CV_IA64_CR28 = 4124, CV_IA64_CR29 = 4125, CV_IA64_CR30 = 4126, CV_IA64_CR31 = 4127, CV_IA64_CR32 = 4128, CV_IA64_CR33 = 4129, CV_IA64_CR34 = 4130, CV_IA64_CR35 = 4131, CV_IA64_CR36 = 4132, CV_IA64_CR37 = 4133, CV_IA64_CR38 = 4134, CV_IA64_CR39 = 4135, CV_IA64_CR40 = 4136, CV_IA64_CR41 = 4137, CV_IA64_CR42 = 4138, CV_IA64_CR43 = 4139, CV_IA64_CR44 = 4140, CV_IA64_CR45 = 4141, CV_IA64_CR46 = 4142, CV_IA64_CR47 = 4143, CV_IA64_CR48 = 4144, CV_IA64_CR49 = 4145, CV_IA64_CR50 = 4146, CV_IA64_CR51 = 4147, CV_IA64_CR52 = 4148, CV_IA64_CR53 = 4149, CV_IA64_CR54 = 4150, CV_IA64_CR55 = 4151, CV_IA64_CR56 = 4152, CV_IA64_CR57 = 4153, CV_IA64_CR58 = 4154, CV_IA64_CR59 = 4155, CV_IA64_CR60 = 4156, CV_IA64_CR61 = 4157, CV_IA64_CR62 = 4158, CV_IA64_CR63 = 4159, CV_IA64_SaLID = 4160, CV_IA64_SaIVR = 4161, CV_IA64_SaTPR = 4162, CV_IA64_SaEOI = 4163, CV_IA64_SaIRR0 = 4164, CV_IA64_SaIRR1 = 4165, CV_IA64_SaIRR2 = 4166, CV_IA64_SaIRR3 = 4167, CV_IA64_SaITV = 4168, CV_IA64_SaPMV = 4169, CV_IA64_SaCMCV = 4170, CV_IA64_CR75 = 4171, CV_IA64_CR76 = 4172, CV_IA64_CR77 = 4173, CV_IA64_CR78 = 4174, CV_IA64_CR79 = 4175, CV_IA64_SaLRR0 = 4176, CV_IA64_SaLRR1 = 4177, CV_IA64_CR82 = 4178, CV_IA64_CR83 = 4179, CV_IA64_CR84 = 4180, CV_IA64_CR85 = 4181, CV_IA64_CR86 = 4182, CV_IA64_CR87 = 4183, CV_IA64_CR88 = 4184, CV_IA64_CR89 = 4185, CV_IA64_CR90 = 4186, CV_IA64_CR91 = 4187, CV_IA64_CR92 = 4188, CV_IA64_CR93 = 4189, CV_IA64_CR94 = 4190, CV_IA64_CR95 = 4191, CV_IA64_CR96 = 4192, CV_IA64_CR97 = 4193, CV_IA64_CR98 = 4194, CV_IA64_CR99 = 4195, CV_IA64_CR100 = 4196, CV_IA64_CR101 = 4197, CV_IA64_CR102 = 4198, CV_IA64_CR103 = 4199, CV_IA64_CR104 = 4200, CV_IA64_CR105 = 4201, CV_IA64_CR106 = 4202, CV_IA64_CR107 = 4203, CV_IA64_CR108 = 4204, CV_IA64_CR109 = 4205, CV_IA64_CR110 = 4206, CV_IA64_CR111 = 4207, CV_IA64_CR112 = 4208, CV_IA64_CR113 = 4209, CV_IA64_CR114 = 4210, CV_IA64_CR115 = 4211, CV_IA64_CR116 = 4212, CV_IA64_CR117 = 4213, CV_IA64_CR118 = 4214, CV_IA64_CR119 = 4215, CV_IA64_CR120 = 4216, CV_IA64_CR121 = 4217, CV_IA64_CR122 = 4218, CV_IA64_CR123 = 4219, CV_IA64_CR124 = 4220, CV_IA64_CR125 = 4221, CV_IA64_CR126 = 4222, CV_IA64_CR127 = 4223, // Protection Key Registers CV_IA64_Pkr0 = 5120, CV_IA64_Pkr1 = 5121, CV_IA64_Pkr2 = 5122, CV_IA64_Pkr3 = 5123, CV_IA64_Pkr4 = 5124, CV_IA64_Pkr5 = 5125, CV_IA64_Pkr6 = 5126, CV_IA64_Pkr7 = 5127, CV_IA64_Pkr8 = 5128, CV_IA64_Pkr9 = 5129, CV_IA64_Pkr10 = 5130, CV_IA64_Pkr11 = 5131, CV_IA64_Pkr12 = 5132, CV_IA64_Pkr13 = 5133, CV_IA64_Pkr14 = 5134, CV_IA64_Pkr15 = 5135, // Region Registers CV_IA64_Rr0 = 6144, CV_IA64_Rr1 = 6145, CV_IA64_Rr2 = 6146, CV_IA64_Rr3 = 6147, CV_IA64_Rr4 = 6148, CV_IA64_Rr5 = 6149, CV_IA64_Rr6 = 6150, CV_IA64_Rr7 = 6151, // Performance Monitor Data Registers CV_IA64_PFD0 = 7168, CV_IA64_PFD1 = 7169, CV_IA64_PFD2 = 7170, CV_IA64_PFD3 = 7171, CV_IA64_PFD4 = 7172, CV_IA64_PFD5 = 7173, CV_IA64_PFD6 = 7174, CV_IA64_PFD7 = 7175, CV_IA64_PFD8 = 7176, CV_IA64_PFD9 = 7177, CV_IA64_PFD10 = 7178, CV_IA64_PFD11 = 7179, CV_IA64_PFD12 = 7180, CV_IA64_PFD13 = 7181, CV_IA64_PFD14 = 7182, CV_IA64_PFD15 = 7183, CV_IA64_PFD16 = 7184, CV_IA64_PFD17 = 7185, // Performance Monitor Config Registers CV_IA64_PFC0 = 7424, CV_IA64_PFC1 = 7425, CV_IA64_PFC2 = 7426, CV_IA64_PFC3 = 7427, CV_IA64_PFC4 = 7428, CV_IA64_PFC5 = 7429, CV_IA64_PFC6 = 7430, CV_IA64_PFC7 = 7431, CV_IA64_PFC8 = 7432, CV_IA64_PFC9 = 7433, CV_IA64_PFC10 = 7434, CV_IA64_PFC11 = 7435, CV_IA64_PFC12 = 7436, CV_IA64_PFC13 = 7437, CV_IA64_PFC14 = 7438, CV_IA64_PFC15 = 7439, // Instruction Translation Registers CV_IA64_TrI0 = 8192, CV_IA64_TrI1 = 8193, CV_IA64_TrI2 = 8194, CV_IA64_TrI3 = 8195, CV_IA64_TrI4 = 8196, CV_IA64_TrI5 = 8197, CV_IA64_TrI6 = 8198, CV_IA64_TrI7 = 8199, // Data Translation Registers CV_IA64_TrD0 = 8320, CV_IA64_TrD1 = 8321, CV_IA64_TrD2 = 8322, CV_IA64_TrD3 = 8323, CV_IA64_TrD4 = 8324, CV_IA64_TrD5 = 8325, CV_IA64_TrD6 = 8326, CV_IA64_TrD7 = 8327, // Instruction Breakpoint Registers CV_IA64_DbI0 = 8448, CV_IA64_DbI1 = 8449, CV_IA64_DbI2 = 8450, CV_IA64_DbI3 = 8451, CV_IA64_DbI4 = 8452, CV_IA64_DbI5 = 8453, CV_IA64_DbI6 = 8454, CV_IA64_DbI7 = 8455, // Data Breakpoint Registers CV_IA64_DbD0 = 8576, CV_IA64_DbD1 = 8577, CV_IA64_DbD2 = 8578, CV_IA64_DbD3 = 8579, CV_IA64_DbD4 = 8580, CV_IA64_DbD5 = 8581, CV_IA64_DbD6 = 8582, CV_IA64_DbD7 = 8583, // // Register set for the TriCore processor. // CV_TRI_NOREG = CV_REG_NONE, // General Purpose Data Registers CV_TRI_D0 = 10, CV_TRI_D1 = 11, CV_TRI_D2 = 12, CV_TRI_D3 = 13, CV_TRI_D4 = 14, CV_TRI_D5 = 15, CV_TRI_D6 = 16, CV_TRI_D7 = 17, CV_TRI_D8 = 18, CV_TRI_D9 = 19, CV_TRI_D10 = 20, CV_TRI_D11 = 21, CV_TRI_D12 = 22, CV_TRI_D13 = 23, CV_TRI_D14 = 24, CV_TRI_D15 = 25, // General Purpose Address Registers CV_TRI_A0 = 26, CV_TRI_A1 = 27, CV_TRI_A2 = 28, CV_TRI_A3 = 29, CV_TRI_A4 = 30, CV_TRI_A5 = 31, CV_TRI_A6 = 32, CV_TRI_A7 = 33, CV_TRI_A8 = 34, CV_TRI_A9 = 35, CV_TRI_A10 = 36, CV_TRI_A11 = 37, CV_TRI_A12 = 38, CV_TRI_A13 = 39, CV_TRI_A14 = 40, CV_TRI_A15 = 41, // Extended (64-bit) data registers CV_TRI_E0 = 42, CV_TRI_E2 = 43, CV_TRI_E4 = 44, CV_TRI_E6 = 45, CV_TRI_E8 = 46, CV_TRI_E10 = 47, CV_TRI_E12 = 48, CV_TRI_E14 = 49, // Extended (64-bit) address registers CV_TRI_EA0 = 50, CV_TRI_EA2 = 51, CV_TRI_EA4 = 52, CV_TRI_EA6 = 53, CV_TRI_EA8 = 54, CV_TRI_EA10 = 55, CV_TRI_EA12 = 56, CV_TRI_EA14 = 57, CV_TRI_PSW = 58, CV_TRI_PCXI = 59, CV_TRI_PC = 60, CV_TRI_FCX = 61, CV_TRI_LCX = 62, CV_TRI_ISP = 63, CV_TRI_ICR = 64, CV_TRI_BIV = 65, CV_TRI_BTV = 66, CV_TRI_SYSCON = 67, CV_TRI_DPRx_0 = 68, CV_TRI_DPRx_1 = 69, CV_TRI_DPRx_2 = 70, CV_TRI_DPRx_3 = 71, CV_TRI_CPRx_0 = 68, CV_TRI_CPRx_1 = 69, CV_TRI_CPRx_2 = 70, CV_TRI_CPRx_3 = 71, CV_TRI_DPMx_0 = 68, CV_TRI_DPMx_1 = 69, CV_TRI_DPMx_2 = 70, CV_TRI_DPMx_3 = 71, CV_TRI_CPMx_0 = 68, CV_TRI_CPMx_1 = 69, CV_TRI_CPMx_2 = 70, CV_TRI_CPMx_3 = 71, CV_TRI_DBGSSR = 72, CV_TRI_EXEVT = 73, CV_TRI_SWEVT = 74, CV_TRI_CREVT = 75, CV_TRI_TRnEVT = 76, CV_TRI_MMUCON = 77, CV_TRI_ASI = 78, CV_TRI_TVA = 79, CV_TRI_TPA = 80, CV_TRI_TPX = 81, CV_TRI_TFA = 82, // // Register set for the AM33 and related processors. // CV_AM33_NOREG = CV_REG_NONE, // "Extended" (general purpose integer) registers CV_AM33_E0 = 10, CV_AM33_E1 = 11, CV_AM33_E2 = 12, CV_AM33_E3 = 13, CV_AM33_E4 = 14, CV_AM33_E5 = 15, CV_AM33_E6 = 16, CV_AM33_E7 = 17, // Address registers CV_AM33_A0 = 20, CV_AM33_A1 = 21, CV_AM33_A2 = 22, CV_AM33_A3 = 23, // Integer data registers CV_AM33_D0 = 30, CV_AM33_D1 = 31, CV_AM33_D2 = 32, CV_AM33_D3 = 33, // (Single-precision) floating-point registers CV_AM33_FS0 = 40, CV_AM33_FS1 = 41, CV_AM33_FS2 = 42, CV_AM33_FS3 = 43, CV_AM33_FS4 = 44, CV_AM33_FS5 = 45, CV_AM33_FS6 = 46, CV_AM33_FS7 = 47, CV_AM33_FS8 = 48, CV_AM33_FS9 = 49, CV_AM33_FS10 = 50, CV_AM33_FS11 = 51, CV_AM33_FS12 = 52, CV_AM33_FS13 = 53, CV_AM33_FS14 = 54, CV_AM33_FS15 = 55, CV_AM33_FS16 = 56, CV_AM33_FS17 = 57, CV_AM33_FS18 = 58, CV_AM33_FS19 = 59, CV_AM33_FS20 = 60, CV_AM33_FS21 = 61, CV_AM33_FS22 = 62, CV_AM33_FS23 = 63, CV_AM33_FS24 = 64, CV_AM33_FS25 = 65, CV_AM33_FS26 = 66, CV_AM33_FS27 = 67, CV_AM33_FS28 = 68, CV_AM33_FS29 = 69, CV_AM33_FS30 = 70, CV_AM33_FS31 = 71, // Special purpose registers // Stack pointer CV_AM33_SP = 80, // Program counter CV_AM33_PC = 81, // Multiply-divide/accumulate registers CV_AM33_MDR = 82, CV_AM33_MDRQ = 83, CV_AM33_MCRH = 84, CV_AM33_MCRL = 85, CV_AM33_MCVF = 86, // CPU status words CV_AM33_EPSW = 87, CV_AM33_FPCR = 88, // Loop buffer registers CV_AM33_LIR = 89, CV_AM33_LAR = 90, // // Register set for the Mitsubishi M32R // CV_M32R_NOREG = CV_REG_NONE, CV_M32R_R0 = 10, CV_M32R_R1 = 11, CV_M32R_R2 = 12, CV_M32R_R3 = 13, CV_M32R_R4 = 14, CV_M32R_R5 = 15, CV_M32R_R6 = 16, CV_M32R_R7 = 17, CV_M32R_R8 = 18, CV_M32R_R9 = 19, CV_M32R_R10 = 20, CV_M32R_R11 = 21, CV_M32R_R12 = 22, // Gloabal Pointer, if used CV_M32R_R13 = 23, // Frame Pointer, if allocated CV_M32R_R14 = 24, // Link Register CV_M32R_R15 = 25, // Stack Pointer CV_M32R_PSW = 26, // Preocessor Status Register CV_M32R_CBR = 27, // Condition Bit Register CV_M32R_SPI = 28, // Interrupt Stack Pointer CV_M32R_SPU = 29, // User Stack Pointer CV_M32R_SPO = 30, // OS Stack Pointer CV_M32R_BPC = 31, // Backup Program Counter CV_M32R_ACHI = 32, // Accumulator High CV_M32R_ACLO = 33, // Accumulator Low CV_M32R_PC = 34, // Program Counter // // Register set for the SuperH SHMedia processor including compact // mode // // Integer - 64 bit general registers CV_SHMEDIA_NOREG = CV_REG_NONE, CV_SHMEDIA_R0 = 10, CV_SHMEDIA_R1 = 11, CV_SHMEDIA_R2 = 12, CV_SHMEDIA_R3 = 13, CV_SHMEDIA_R4 = 14, CV_SHMEDIA_R5 = 15, CV_SHMEDIA_R6 = 16, CV_SHMEDIA_R7 = 17, CV_SHMEDIA_R8 = 18, CV_SHMEDIA_R9 = 19, CV_SHMEDIA_R10 = 20, CV_SHMEDIA_R11 = 21, CV_SHMEDIA_R12 = 22, CV_SHMEDIA_R13 = 23, CV_SHMEDIA_R14 = 24, CV_SHMEDIA_R15 = 25, CV_SHMEDIA_R16 = 26, CV_SHMEDIA_R17 = 27, CV_SHMEDIA_R18 = 28, CV_SHMEDIA_R19 = 29, CV_SHMEDIA_R20 = 30, CV_SHMEDIA_R21 = 31, CV_SHMEDIA_R22 = 32, CV_SHMEDIA_R23 = 33, CV_SHMEDIA_R24 = 34, CV_SHMEDIA_R25 = 35, CV_SHMEDIA_R26 = 36, CV_SHMEDIA_R27 = 37, CV_SHMEDIA_R28 = 38, CV_SHMEDIA_R29 = 39, CV_SHMEDIA_R30 = 40, CV_SHMEDIA_R31 = 41, CV_SHMEDIA_R32 = 42, CV_SHMEDIA_R33 = 43, CV_SHMEDIA_R34 = 44, CV_SHMEDIA_R35 = 45, CV_SHMEDIA_R36 = 46, CV_SHMEDIA_R37 = 47, CV_SHMEDIA_R38 = 48, CV_SHMEDIA_R39 = 49, CV_SHMEDIA_R40 = 50, CV_SHMEDIA_R41 = 51, CV_SHMEDIA_R42 = 52, CV_SHMEDIA_R43 = 53, CV_SHMEDIA_R44 = 54, CV_SHMEDIA_R45 = 55, CV_SHMEDIA_R46 = 56, CV_SHMEDIA_R47 = 57, CV_SHMEDIA_R48 = 58, CV_SHMEDIA_R49 = 59, CV_SHMEDIA_R50 = 60, CV_SHMEDIA_R51 = 61, CV_SHMEDIA_R52 = 62, CV_SHMEDIA_R53 = 63, CV_SHMEDIA_R54 = 64, CV_SHMEDIA_R55 = 65, CV_SHMEDIA_R56 = 66, CV_SHMEDIA_R57 = 67, CV_SHMEDIA_R58 = 68, CV_SHMEDIA_R59 = 69, CV_SHMEDIA_R60 = 70, CV_SHMEDIA_R61 = 71, CV_SHMEDIA_R62 = 72, CV_SHMEDIA_R63 = 73, // Target Registers - 32 bit CV_SHMEDIA_TR0 = 74, CV_SHMEDIA_TR1 = 75, CV_SHMEDIA_TR2 = 76, CV_SHMEDIA_TR3 = 77, CV_SHMEDIA_TR4 = 78, CV_SHMEDIA_TR5 = 79, CV_SHMEDIA_TR6 = 80, CV_SHMEDIA_TR7 = 81, CV_SHMEDIA_TR8 = 82, // future-proof CV_SHMEDIA_TR9 = 83, // future-proof CV_SHMEDIA_TR10 = 84, // future-proof CV_SHMEDIA_TR11 = 85, // future-proof CV_SHMEDIA_TR12 = 86, // future-proof CV_SHMEDIA_TR13 = 87, // future-proof CV_SHMEDIA_TR14 = 88, // future-proof CV_SHMEDIA_TR15 = 89, // future-proof // Single - 32 bit fp registers CV_SHMEDIA_FR0 = 128, CV_SHMEDIA_FR1 = 129, CV_SHMEDIA_FR2 = 130, CV_SHMEDIA_FR3 = 131, CV_SHMEDIA_FR4 = 132, CV_SHMEDIA_FR5 = 133, CV_SHMEDIA_FR6 = 134, CV_SHMEDIA_FR7 = 135, CV_SHMEDIA_FR8 = 136, CV_SHMEDIA_FR9 = 137, CV_SHMEDIA_FR10 = 138, CV_SHMEDIA_FR11 = 139, CV_SHMEDIA_FR12 = 140, CV_SHMEDIA_FR13 = 141, CV_SHMEDIA_FR14 = 142, CV_SHMEDIA_FR15 = 143, CV_SHMEDIA_FR16 = 144, CV_SHMEDIA_FR17 = 145, CV_SHMEDIA_FR18 = 146, CV_SHMEDIA_FR19 = 147, CV_SHMEDIA_FR20 = 148, CV_SHMEDIA_FR21 = 149, CV_SHMEDIA_FR22 = 150, CV_SHMEDIA_FR23 = 151, CV_SHMEDIA_FR24 = 152, CV_SHMEDIA_FR25 = 153, CV_SHMEDIA_FR26 = 154, CV_SHMEDIA_FR27 = 155, CV_SHMEDIA_FR28 = 156, CV_SHMEDIA_FR29 = 157, CV_SHMEDIA_FR30 = 158, CV_SHMEDIA_FR31 = 159, CV_SHMEDIA_FR32 = 160, CV_SHMEDIA_FR33 = 161, CV_SHMEDIA_FR34 = 162, CV_SHMEDIA_FR35 = 163, CV_SHMEDIA_FR36 = 164, CV_SHMEDIA_FR37 = 165, CV_SHMEDIA_FR38 = 166, CV_SHMEDIA_FR39 = 167, CV_SHMEDIA_FR40 = 168, CV_SHMEDIA_FR41 = 169, CV_SHMEDIA_FR42 = 170, CV_SHMEDIA_FR43 = 171, CV_SHMEDIA_FR44 = 172, CV_SHMEDIA_FR45 = 173, CV_SHMEDIA_FR46 = 174, CV_SHMEDIA_FR47 = 175, CV_SHMEDIA_FR48 = 176, CV_SHMEDIA_FR49 = 177, CV_SHMEDIA_FR50 = 178, CV_SHMEDIA_FR51 = 179, CV_SHMEDIA_FR52 = 180, CV_SHMEDIA_FR53 = 181, CV_SHMEDIA_FR54 = 182, CV_SHMEDIA_FR55 = 183, CV_SHMEDIA_FR56 = 184, CV_SHMEDIA_FR57 = 185, CV_SHMEDIA_FR58 = 186, CV_SHMEDIA_FR59 = 187, CV_SHMEDIA_FR60 = 188, CV_SHMEDIA_FR61 = 189, CV_SHMEDIA_FR62 = 190, CV_SHMEDIA_FR63 = 191, // Double - 64 bit synonyms for 32bit fp register pairs // subtract 128 to find first base single register CV_SHMEDIA_DR0 = 256, CV_SHMEDIA_DR2 = 258, CV_SHMEDIA_DR4 = 260, CV_SHMEDIA_DR6 = 262, CV_SHMEDIA_DR8 = 264, CV_SHMEDIA_DR10 = 266, CV_SHMEDIA_DR12 = 268, CV_SHMEDIA_DR14 = 270, CV_SHMEDIA_DR16 = 272, CV_SHMEDIA_DR18 = 274, CV_SHMEDIA_DR20 = 276, CV_SHMEDIA_DR22 = 278, CV_SHMEDIA_DR24 = 280, CV_SHMEDIA_DR26 = 282, CV_SHMEDIA_DR28 = 284, CV_SHMEDIA_DR30 = 286, CV_SHMEDIA_DR32 = 288, CV_SHMEDIA_DR34 = 290, CV_SHMEDIA_DR36 = 292, CV_SHMEDIA_DR38 = 294, CV_SHMEDIA_DR40 = 296, CV_SHMEDIA_DR42 = 298, CV_SHMEDIA_DR44 = 300, CV_SHMEDIA_DR46 = 302, CV_SHMEDIA_DR48 = 304, CV_SHMEDIA_DR50 = 306, CV_SHMEDIA_DR52 = 308, CV_SHMEDIA_DR54 = 310, CV_SHMEDIA_DR56 = 312, CV_SHMEDIA_DR58 = 314, CV_SHMEDIA_DR60 = 316, CV_SHMEDIA_DR62 = 318, // Vector - 128 bit synonyms for 32bit fp register quads // subtract 384 to find first base single register CV_SHMEDIA_FV0 = 512, CV_SHMEDIA_FV4 = 516, CV_SHMEDIA_FV8 = 520, CV_SHMEDIA_FV12 = 524, CV_SHMEDIA_FV16 = 528, CV_SHMEDIA_FV20 = 532, CV_SHMEDIA_FV24 = 536, CV_SHMEDIA_FV28 = 540, CV_SHMEDIA_FV32 = 544, CV_SHMEDIA_FV36 = 548, CV_SHMEDIA_FV40 = 552, CV_SHMEDIA_FV44 = 556, CV_SHMEDIA_FV48 = 560, CV_SHMEDIA_FV52 = 564, CV_SHMEDIA_FV56 = 568, CV_SHMEDIA_FV60 = 572, // Matrix - 512 bit synonyms for 16 adjacent 32bit fp registers // subtract 896 to find first base single register CV_SHMEDIA_MTRX0 = 1024, CV_SHMEDIA_MTRX16 = 1040, CV_SHMEDIA_MTRX32 = 1056, CV_SHMEDIA_MTRX48 = 1072, // Control - Implementation defined 64bit control registers CV_SHMEDIA_CR0 = 2000, CV_SHMEDIA_CR1 = 2001, CV_SHMEDIA_CR2 = 2002, CV_SHMEDIA_CR3 = 2003, CV_SHMEDIA_CR4 = 2004, CV_SHMEDIA_CR5 = 2005, CV_SHMEDIA_CR6 = 2006, CV_SHMEDIA_CR7 = 2007, CV_SHMEDIA_CR8 = 2008, CV_SHMEDIA_CR9 = 2009, CV_SHMEDIA_CR10 = 2010, CV_SHMEDIA_CR11 = 2011, CV_SHMEDIA_CR12 = 2012, CV_SHMEDIA_CR13 = 2013, CV_SHMEDIA_CR14 = 2014, CV_SHMEDIA_CR15 = 2015, CV_SHMEDIA_CR16 = 2016, CV_SHMEDIA_CR17 = 2017, CV_SHMEDIA_CR18 = 2018, CV_SHMEDIA_CR19 = 2019, CV_SHMEDIA_CR20 = 2020, CV_SHMEDIA_CR21 = 2021, CV_SHMEDIA_CR22 = 2022, CV_SHMEDIA_CR23 = 2023, CV_SHMEDIA_CR24 = 2024, CV_SHMEDIA_CR25 = 2025, CV_SHMEDIA_CR26 = 2026, CV_SHMEDIA_CR27 = 2027, CV_SHMEDIA_CR28 = 2028, CV_SHMEDIA_CR29 = 2029, CV_SHMEDIA_CR30 = 2030, CV_SHMEDIA_CR31 = 2031, CV_SHMEDIA_CR32 = 2032, CV_SHMEDIA_CR33 = 2033, CV_SHMEDIA_CR34 = 2034, CV_SHMEDIA_CR35 = 2035, CV_SHMEDIA_CR36 = 2036, CV_SHMEDIA_CR37 = 2037, CV_SHMEDIA_CR38 = 2038, CV_SHMEDIA_CR39 = 2039, CV_SHMEDIA_CR40 = 2040, CV_SHMEDIA_CR41 = 2041, CV_SHMEDIA_CR42 = 2042, CV_SHMEDIA_CR43 = 2043, CV_SHMEDIA_CR44 = 2044, CV_SHMEDIA_CR45 = 2045, CV_SHMEDIA_CR46 = 2046, CV_SHMEDIA_CR47 = 2047, CV_SHMEDIA_CR48 = 2048, CV_SHMEDIA_CR49 = 2049, CV_SHMEDIA_CR50 = 2050, CV_SHMEDIA_CR51 = 2051, CV_SHMEDIA_CR52 = 2052, CV_SHMEDIA_CR53 = 2053, CV_SHMEDIA_CR54 = 2054, CV_SHMEDIA_CR55 = 2055, CV_SHMEDIA_CR56 = 2056, CV_SHMEDIA_CR57 = 2057, CV_SHMEDIA_CR58 = 2058, CV_SHMEDIA_CR59 = 2059, CV_SHMEDIA_CR60 = 2060, CV_SHMEDIA_CR61 = 2061, CV_SHMEDIA_CR62 = 2062, CV_SHMEDIA_CR63 = 2063, CV_SHMEDIA_FPSCR = 2064, // Compact mode synonyms CV_SHMEDIA_GBR = CV_SHMEDIA_R16, CV_SHMEDIA_MACL = 90, // synonym for lower 32bits of media R17 CV_SHMEDIA_MACH = 91, // synonym for upper 32bits of media R17 CV_SHMEDIA_PR = CV_SHMEDIA_R18, CV_SHMEDIA_T = 92, // synonym for lowest bit of media R19 CV_SHMEDIA_FPUL = CV_SHMEDIA_FR32, CV_SHMEDIA_PC = 93, CV_SHMEDIA_SR = CV_SHMEDIA_CR0, // // AMD64 registers // CV_AMD64_AL = 1, CV_AMD64_CL = 2, CV_AMD64_DL = 3, CV_AMD64_BL = 4, CV_AMD64_AH = 5, CV_AMD64_CH = 6, CV_AMD64_DH = 7, CV_AMD64_BH = 8, CV_AMD64_AX = 9, CV_AMD64_CX = 10, CV_AMD64_DX = 11, CV_AMD64_BX = 12, CV_AMD64_SP = 13, CV_AMD64_BP = 14, CV_AMD64_SI = 15, CV_AMD64_DI = 16, CV_AMD64_EAX = 17, CV_AMD64_ECX = 18, CV_AMD64_EDX = 19, CV_AMD64_EBX = 20, CV_AMD64_ESP = 21, CV_AMD64_EBP = 22, CV_AMD64_ESI = 23, CV_AMD64_EDI = 24, CV_AMD64_ES = 25, CV_AMD64_CS = 26, CV_AMD64_SS = 27, CV_AMD64_DS = 28, CV_AMD64_FS = 29, CV_AMD64_GS = 30, CV_AMD64_FLAGS = 32, CV_AMD64_RIP = 33, CV_AMD64_EFLAGS = 34, // Control registers CV_AMD64_CR0 = 80, CV_AMD64_CR1 = 81, CV_AMD64_CR2 = 82, CV_AMD64_CR3 = 83, CV_AMD64_CR4 = 84, CV_AMD64_CR8 = 88, // Debug registers CV_AMD64_DR0 = 90, CV_AMD64_DR1 = 91, CV_AMD64_DR2 = 92, CV_AMD64_DR3 = 93, CV_AMD64_DR4 = 94, CV_AMD64_DR5 = 95, CV_AMD64_DR6 = 96, CV_AMD64_DR7 = 97, CV_AMD64_DR8 = 98, CV_AMD64_DR9 = 99, CV_AMD64_DR10 = 100, CV_AMD64_DR11 = 101, CV_AMD64_DR12 = 102, CV_AMD64_DR13 = 103, CV_AMD64_DR14 = 104, CV_AMD64_DR15 = 105, CV_AMD64_GDTR = 110, CV_AMD64_GDTL = 111, CV_AMD64_IDTR = 112, CV_AMD64_IDTL = 113, CV_AMD64_LDTR = 114, CV_AMD64_TR = 115, CV_AMD64_ST0 = 128, CV_AMD64_ST1 = 129, CV_AMD64_ST2 = 130, CV_AMD64_ST3 = 131, CV_AMD64_ST4 = 132, CV_AMD64_ST5 = 133, CV_AMD64_ST6 = 134, CV_AMD64_ST7 = 135, CV_AMD64_CTRL = 136, CV_AMD64_STAT = 137, CV_AMD64_TAG = 138, CV_AMD64_FPIP = 139, CV_AMD64_FPCS = 140, CV_AMD64_FPDO = 141, CV_AMD64_FPDS = 142, CV_AMD64_ISEM = 143, CV_AMD64_FPEIP = 144, CV_AMD64_FPEDO = 145, CV_AMD64_MM0 = 146, CV_AMD64_MM1 = 147, CV_AMD64_MM2 = 148, CV_AMD64_MM3 = 149, CV_AMD64_MM4 = 150, CV_AMD64_MM5 = 151, CV_AMD64_MM6 = 152, CV_AMD64_MM7 = 153, CV_AMD64_XMM0 = 154, // KATMAI registers CV_AMD64_XMM1 = 155, CV_AMD64_XMM2 = 156, CV_AMD64_XMM3 = 157, CV_AMD64_XMM4 = 158, CV_AMD64_XMM5 = 159, CV_AMD64_XMM6 = 160, CV_AMD64_XMM7 = 161, CV_AMD64_XMM0_0 = 162, // KATMAI sub-registers CV_AMD64_XMM0_1 = 163, CV_AMD64_XMM0_2 = 164, CV_AMD64_XMM0_3 = 165, CV_AMD64_XMM1_0 = 166, CV_AMD64_XMM1_1 = 167, CV_AMD64_XMM1_2 = 168, CV_AMD64_XMM1_3 = 169, CV_AMD64_XMM2_0 = 170, CV_AMD64_XMM2_1 = 171, CV_AMD64_XMM2_2 = 172, CV_AMD64_XMM2_3 = 173, CV_AMD64_XMM3_0 = 174, CV_AMD64_XMM3_1 = 175, CV_AMD64_XMM3_2 = 176, CV_AMD64_XMM3_3 = 177, CV_AMD64_XMM4_0 = 178, CV_AMD64_XMM4_1 = 179, CV_AMD64_XMM4_2 = 180, CV_AMD64_XMM4_3 = 181, CV_AMD64_XMM5_0 = 182, CV_AMD64_XMM5_1 = 183, CV_AMD64_XMM5_2 = 184, CV_AMD64_XMM5_3 = 185, CV_AMD64_XMM6_0 = 186, CV_AMD64_XMM6_1 = 187, CV_AMD64_XMM6_2 = 188, CV_AMD64_XMM6_3 = 189, CV_AMD64_XMM7_0 = 190, CV_AMD64_XMM7_1 = 191, CV_AMD64_XMM7_2 = 192, CV_AMD64_XMM7_3 = 193, CV_AMD64_XMM0L = 194, CV_AMD64_XMM1L = 195, CV_AMD64_XMM2L = 196, CV_AMD64_XMM3L = 197, CV_AMD64_XMM4L = 198, CV_AMD64_XMM5L = 199, CV_AMD64_XMM6L = 200, CV_AMD64_XMM7L = 201, CV_AMD64_XMM0H = 202, CV_AMD64_XMM1H = 203, CV_AMD64_XMM2H = 204, CV_AMD64_XMM3H = 205, CV_AMD64_XMM4H = 206, CV_AMD64_XMM5H = 207, CV_AMD64_XMM6H = 208, CV_AMD64_XMM7H = 209, CV_AMD64_MXCSR = 211, // XMM status register CV_AMD64_EMM0L = 220, // XMM sub-registers (WNI integer) CV_AMD64_EMM1L = 221, CV_AMD64_EMM2L = 222, CV_AMD64_EMM3L = 223, CV_AMD64_EMM4L = 224, CV_AMD64_EMM5L = 225, CV_AMD64_EMM6L = 226, CV_AMD64_EMM7L = 227, CV_AMD64_EMM0H = 228, CV_AMD64_EMM1H = 229, CV_AMD64_EMM2H = 230, CV_AMD64_EMM3H = 231, CV_AMD64_EMM4H = 232, CV_AMD64_EMM5H = 233, CV_AMD64_EMM6H = 234, CV_AMD64_EMM7H = 235, // do not change the order of these regs, first one must be even too CV_AMD64_MM00 = 236, CV_AMD64_MM01 = 237, CV_AMD64_MM10 = 238, CV_AMD64_MM11 = 239, CV_AMD64_MM20 = 240, CV_AMD64_MM21 = 241, CV_AMD64_MM30 = 242, CV_AMD64_MM31 = 243, CV_AMD64_MM40 = 244, CV_AMD64_MM41 = 245, CV_AMD64_MM50 = 246, CV_AMD64_MM51 = 247, CV_AMD64_MM60 = 248, CV_AMD64_MM61 = 249, CV_AMD64_MM70 = 250, CV_AMD64_MM71 = 251, // Extended KATMAI registers CV_AMD64_XMM8 = 252, // KATMAI registers CV_AMD64_XMM9 = 253, CV_AMD64_XMM10 = 254, CV_AMD64_XMM11 = 255, CV_AMD64_XMM12 = 256, CV_AMD64_XMM13 = 257, CV_AMD64_XMM14 = 258, CV_AMD64_XMM15 = 259, CV_AMD64_XMM8_0 = 260, // KATMAI sub-registers CV_AMD64_XMM8_1 = 261, CV_AMD64_XMM8_2 = 262, CV_AMD64_XMM8_3 = 263, CV_AMD64_XMM9_0 = 264, CV_AMD64_XMM9_1 = 265, CV_AMD64_XMM9_2 = 266, CV_AMD64_XMM9_3 = 267, CV_AMD64_XMM10_0 = 268, CV_AMD64_XMM10_1 = 269, CV_AMD64_XMM10_2 = 270, CV_AMD64_XMM10_3 = 271, CV_AMD64_XMM11_0 = 272, CV_AMD64_XMM11_1 = 273, CV_AMD64_XMM11_2 = 274, CV_AMD64_XMM11_3 = 275, CV_AMD64_XMM12_0 = 276, CV_AMD64_XMM12_1 = 277, CV_AMD64_XMM12_2 = 278, CV_AMD64_XMM12_3 = 279, CV_AMD64_XMM13_0 = 280, CV_AMD64_XMM13_1 = 281, CV_AMD64_XMM13_2 = 282, CV_AMD64_XMM13_3 = 283, CV_AMD64_XMM14_0 = 284, CV_AMD64_XMM14_1 = 285, CV_AMD64_XMM14_2 = 286, CV_AMD64_XMM14_3 = 287, CV_AMD64_XMM15_0 = 288, CV_AMD64_XMM15_1 = 289, CV_AMD64_XMM15_2 = 290, CV_AMD64_XMM15_3 = 291, CV_AMD64_XMM8L = 292, CV_AMD64_XMM9L = 293, CV_AMD64_XMM10L = 294, CV_AMD64_XMM11L = 295, CV_AMD64_XMM12L = 296, CV_AMD64_XMM13L = 297, CV_AMD64_XMM14L = 298, CV_AMD64_XMM15L = 299, CV_AMD64_XMM8H = 300, CV_AMD64_XMM9H = 301, CV_AMD64_XMM10H = 302, CV_AMD64_XMM11H = 303, CV_AMD64_XMM12H = 304, CV_AMD64_XMM13H = 305, CV_AMD64_XMM14H = 306, CV_AMD64_XMM15H = 307, CV_AMD64_EMM8L = 308, // XMM sub-registers (WNI integer) CV_AMD64_EMM9L = 309, CV_AMD64_EMM10L = 310, CV_AMD64_EMM11L = 311, CV_AMD64_EMM12L = 312, CV_AMD64_EMM13L = 313, CV_AMD64_EMM14L = 314, CV_AMD64_EMM15L = 315, CV_AMD64_EMM8H = 316, CV_AMD64_EMM9H = 317, CV_AMD64_EMM10H = 318, CV_AMD64_EMM11H = 319, CV_AMD64_EMM12H = 320, CV_AMD64_EMM13H = 321, CV_AMD64_EMM14H = 322, CV_AMD64_EMM15H = 323, // Low byte forms of some standard registers CV_AMD64_SIL = 324, CV_AMD64_DIL = 325, CV_AMD64_BPL = 326, CV_AMD64_SPL = 327, // 64-bit regular registers CV_AMD64_RAX = 328, CV_AMD64_RBX = 329, CV_AMD64_RCX = 330, CV_AMD64_RDX = 331, CV_AMD64_RSI = 332, CV_AMD64_RDI = 333, CV_AMD64_RBP = 334, CV_AMD64_RSP = 335, // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D) CV_AMD64_R8 = 336, CV_AMD64_R9 = 337, CV_AMD64_R10 = 338, CV_AMD64_R11 = 339, CV_AMD64_R12 = 340, CV_AMD64_R13 = 341, CV_AMD64_R14 = 342, CV_AMD64_R15 = 343, CV_AMD64_R8B = 344, CV_AMD64_R9B = 345, CV_AMD64_R10B = 346, CV_AMD64_R11B = 347, CV_AMD64_R12B = 348, CV_AMD64_R13B = 349, CV_AMD64_R14B = 350, CV_AMD64_R15B = 351, CV_AMD64_R8W = 352, CV_AMD64_R9W = 353, CV_AMD64_R10W = 354, CV_AMD64_R11W = 355, CV_AMD64_R12W = 356, CV_AMD64_R13W = 357, CV_AMD64_R14W = 358, CV_AMD64_R15W = 359, CV_AMD64_R8D = 360, CV_AMD64_R9D = 361, CV_AMD64_R10D = 362, CV_AMD64_R11D = 363, CV_AMD64_R12D = 364, CV_AMD64_R13D = 365, CV_AMD64_R14D = 366, CV_AMD64_R15D = 367, // AVX registers 256 bits CV_AMD64_YMM0 = 368, CV_AMD64_YMM1 = 369, CV_AMD64_YMM2 = 370, CV_AMD64_YMM3 = 371, CV_AMD64_YMM4 = 372, CV_AMD64_YMM5 = 373, CV_AMD64_YMM6 = 374, CV_AMD64_YMM7 = 375, CV_AMD64_YMM8 = 376, CV_AMD64_YMM9 = 377, CV_AMD64_YMM10 = 378, CV_AMD64_YMM11 = 379, CV_AMD64_YMM12 = 380, CV_AMD64_YMM13 = 381, CV_AMD64_YMM14 = 382, CV_AMD64_YMM15 = 383, // AVX registers upper 128 bits CV_AMD64_YMM0H = 384, CV_AMD64_YMM1H = 385, CV_AMD64_YMM2H = 386, CV_AMD64_YMM3H = 387, CV_AMD64_YMM4H = 388, CV_AMD64_YMM5H = 389, CV_AMD64_YMM6H = 390, CV_AMD64_YMM7H = 391, CV_AMD64_YMM8H = 392, CV_AMD64_YMM9H = 393, CV_AMD64_YMM10H = 394, CV_AMD64_YMM11H = 395, CV_AMD64_YMM12H = 396, CV_AMD64_YMM13H = 397, CV_AMD64_YMM14H = 398, CV_AMD64_YMM15H = 399, //Lower/upper 8 bytes of XMM registers. Unlike CV_AMD64_XMM, these //values reprsesent the bit patterns of the registers as 64-bit integers, not //the representation of these registers as a double. CV_AMD64_XMM0IL = 400, CV_AMD64_XMM1IL = 401, CV_AMD64_XMM2IL = 402, CV_AMD64_XMM3IL = 403, CV_AMD64_XMM4IL = 404, CV_AMD64_XMM5IL = 405, CV_AMD64_XMM6IL = 406, CV_AMD64_XMM7IL = 407, CV_AMD64_XMM8IL = 408, CV_AMD64_XMM9IL = 409, CV_AMD64_XMM10IL = 410, CV_AMD64_XMM11IL = 411, CV_AMD64_XMM12IL = 412, CV_AMD64_XMM13IL = 413, CV_AMD64_XMM14IL = 414, CV_AMD64_XMM15IL = 415, CV_AMD64_XMM0IH = 416, CV_AMD64_XMM1IH = 417, CV_AMD64_XMM2IH = 418, CV_AMD64_XMM3IH = 419, CV_AMD64_XMM4IH = 420, CV_AMD64_XMM5IH = 421, CV_AMD64_XMM6IH = 422, CV_AMD64_XMM7IH = 423, CV_AMD64_XMM8IH = 424, CV_AMD64_XMM9IH = 425, CV_AMD64_XMM10IH = 426, CV_AMD64_XMM11IH = 427, CV_AMD64_XMM12IH = 428, CV_AMD64_XMM13IH = 429, CV_AMD64_XMM14IH = 430, CV_AMD64_XMM15IH = 431, CV_AMD64_YMM0I0 = 432, // AVX integer registers CV_AMD64_YMM0I1 = 433, CV_AMD64_YMM0I2 = 434, CV_AMD64_YMM0I3 = 435, CV_AMD64_YMM1I0 = 436, CV_AMD64_YMM1I1 = 437, CV_AMD64_YMM1I2 = 438, CV_AMD64_YMM1I3 = 439, CV_AMD64_YMM2I0 = 440, CV_AMD64_YMM2I1 = 441, CV_AMD64_YMM2I2 = 442, CV_AMD64_YMM2I3 = 443, CV_AMD64_YMM3I0 = 444, CV_AMD64_YMM3I1 = 445, CV_AMD64_YMM3I2 = 446, CV_AMD64_YMM3I3 = 447, CV_AMD64_YMM4I0 = 448, CV_AMD64_YMM4I1 = 449, CV_AMD64_YMM4I2 = 450, CV_AMD64_YMM4I3 = 451, CV_AMD64_YMM5I0 = 452, CV_AMD64_YMM5I1 = 453, CV_AMD64_YMM5I2 = 454, CV_AMD64_YMM5I3 = 455, CV_AMD64_YMM6I0 = 456, CV_AMD64_YMM6I1 = 457, CV_AMD64_YMM6I2 = 458, CV_AMD64_YMM6I3 = 459, CV_AMD64_YMM7I0 = 460, CV_AMD64_YMM7I1 = 461, CV_AMD64_YMM7I2 = 462, CV_AMD64_YMM7I3 = 463, CV_AMD64_YMM8I0 = 464, CV_AMD64_YMM8I1 = 465, CV_AMD64_YMM8I2 = 466, CV_AMD64_YMM8I3 = 467, CV_AMD64_YMM9I0 = 468, CV_AMD64_YMM9I1 = 469, CV_AMD64_YMM9I2 = 470, CV_AMD64_YMM9I3 = 471, CV_AMD64_YMM10I0 = 472, CV_AMD64_YMM10I1 = 473, CV_AMD64_YMM10I2 = 474, CV_AMD64_YMM10I3 = 475, CV_AMD64_YMM11I0 = 476, CV_AMD64_YMM11I1 = 477, CV_AMD64_YMM11I2 = 478, CV_AMD64_YMM11I3 = 479, CV_AMD64_YMM12I0 = 480, CV_AMD64_YMM12I1 = 481, CV_AMD64_YMM12I2 = 482, CV_AMD64_YMM12I3 = 483, CV_AMD64_YMM13I0 = 484, CV_AMD64_YMM13I1 = 485, CV_AMD64_YMM13I2 = 486, CV_AMD64_YMM13I3 = 487, CV_AMD64_YMM14I0 = 488, CV_AMD64_YMM14I1 = 489, CV_AMD64_YMM14I2 = 490, CV_AMD64_YMM14I3 = 491, CV_AMD64_YMM15I0 = 492, CV_AMD64_YMM15I1 = 493, CV_AMD64_YMM15I2 = 494, CV_AMD64_YMM15I3 = 495, CV_AMD64_YMM0F0 = 496, // AVX floating-point single precise registers CV_AMD64_YMM0F1 = 497, CV_AMD64_YMM0F2 = 498, CV_AMD64_YMM0F3 = 499, CV_AMD64_YMM0F4 = 500, CV_AMD64_YMM0F5 = 501, CV_AMD64_YMM0F6 = 502, CV_AMD64_YMM0F7 = 503, CV_AMD64_YMM1F0 = 504, CV_AMD64_YMM1F1 = 505, CV_AMD64_YMM1F2 = 506, CV_AMD64_YMM1F3 = 507, CV_AMD64_YMM1F4 = 508, CV_AMD64_YMM1F5 = 509, CV_AMD64_YMM1F6 = 510, CV_AMD64_YMM1F7 = 511, CV_AMD64_YMM2F0 = 512, CV_AMD64_YMM2F1 = 513, CV_AMD64_YMM2F2 = 514, CV_AMD64_YMM2F3 = 515, CV_AMD64_YMM2F4 = 516, CV_AMD64_YMM2F5 = 517, CV_AMD64_YMM2F6 = 518, CV_AMD64_YMM2F7 = 519, CV_AMD64_YMM3F0 = 520, CV_AMD64_YMM3F1 = 521, CV_AMD64_YMM3F2 = 522, CV_AMD64_YMM3F3 = 523, CV_AMD64_YMM3F4 = 524, CV_AMD64_YMM3F5 = 525, CV_AMD64_YMM3F6 = 526, CV_AMD64_YMM3F7 = 527, CV_AMD64_YMM4F0 = 528, CV_AMD64_YMM4F1 = 529, CV_AMD64_YMM4F2 = 530, CV_AMD64_YMM4F3 = 531, CV_AMD64_YMM4F4 = 532, CV_AMD64_YMM4F5 = 533, CV_AMD64_YMM4F6 = 534, CV_AMD64_YMM4F7 = 535, CV_AMD64_YMM5F0 = 536, CV_AMD64_YMM5F1 = 537, CV_AMD64_YMM5F2 = 538, CV_AMD64_YMM5F3 = 539, CV_AMD64_YMM5F4 = 540, CV_AMD64_YMM5F5 = 541, CV_AMD64_YMM5F6 = 542, CV_AMD64_YMM5F7 = 543, CV_AMD64_YMM6F0 = 544, CV_AMD64_YMM6F1 = 545, CV_AMD64_YMM6F2 = 546, CV_AMD64_YMM6F3 = 547, CV_AMD64_YMM6F4 = 548, CV_AMD64_YMM6F5 = 549, CV_AMD64_YMM6F6 = 550, CV_AMD64_YMM6F7 = 551, CV_AMD64_YMM7F0 = 552, CV_AMD64_YMM7F1 = 553, CV_AMD64_YMM7F2 = 554, CV_AMD64_YMM7F3 = 555, CV_AMD64_YMM7F4 = 556, CV_AMD64_YMM7F5 = 557, CV_AMD64_YMM7F6 = 558, CV_AMD64_YMM7F7 = 559, CV_AMD64_YMM8F0 = 560, CV_AMD64_YMM8F1 = 561, CV_AMD64_YMM8F2 = 562, CV_AMD64_YMM8F3 = 563, CV_AMD64_YMM8F4 = 564, CV_AMD64_YMM8F5 = 565, CV_AMD64_YMM8F6 = 566, CV_AMD64_YMM8F7 = 567, CV_AMD64_YMM9F0 = 568, CV_AMD64_YMM9F1 = 569, CV_AMD64_YMM9F2 = 570, CV_AMD64_YMM9F3 = 571, CV_AMD64_YMM9F4 = 572, CV_AMD64_YMM9F5 = 573, CV_AMD64_YMM9F6 = 574, CV_AMD64_YMM9F7 = 575, CV_AMD64_YMM10F0 = 576, CV_AMD64_YMM10F1 = 577, CV_AMD64_YMM10F2 = 578, CV_AMD64_YMM10F3 = 579, CV_AMD64_YMM10F4 = 580, CV_AMD64_YMM10F5 = 581, CV_AMD64_YMM10F6 = 582, CV_AMD64_YMM10F7 = 583, CV_AMD64_YMM11F0 = 584, CV_AMD64_YMM11F1 = 585, CV_AMD64_YMM11F2 = 586, CV_AMD64_YMM11F3 = 587, CV_AMD64_YMM11F4 = 588, CV_AMD64_YMM11F5 = 589, CV_AMD64_YMM11F6 = 590, CV_AMD64_YMM11F7 = 591, CV_AMD64_YMM12F0 = 592, CV_AMD64_YMM12F1 = 593, CV_AMD64_YMM12F2 = 594, CV_AMD64_YMM12F3 = 595, CV_AMD64_YMM12F4 = 596, CV_AMD64_YMM12F5 = 597, CV_AMD64_YMM12F6 = 598, CV_AMD64_YMM12F7 = 599, CV_AMD64_YMM13F0 = 600, CV_AMD64_YMM13F1 = 601, CV_AMD64_YMM13F2 = 602, CV_AMD64_YMM13F3 = 603, CV_AMD64_YMM13F4 = 604, CV_AMD64_YMM13F5 = 605, CV_AMD64_YMM13F6 = 606, CV_AMD64_YMM13F7 = 607, CV_AMD64_YMM14F0 = 608, CV_AMD64_YMM14F1 = 609, CV_AMD64_YMM14F2 = 610, CV_AMD64_YMM14F3 = 611, CV_AMD64_YMM14F4 = 612, CV_AMD64_YMM14F5 = 613, CV_AMD64_YMM14F6 = 614, CV_AMD64_YMM14F7 = 615, CV_AMD64_YMM15F0 = 616, CV_AMD64_YMM15F1 = 617, CV_AMD64_YMM15F2 = 618, CV_AMD64_YMM15F3 = 619, CV_AMD64_YMM15F4 = 620, CV_AMD64_YMM15F5 = 621, CV_AMD64_YMM15F6 = 622, CV_AMD64_YMM15F7 = 623, CV_AMD64_YMM0D0 = 624, // AVX floating-point double precise registers CV_AMD64_YMM0D1 = 625, CV_AMD64_YMM0D2 = 626, CV_AMD64_YMM0D3 = 627, CV_AMD64_YMM1D0 = 628, CV_AMD64_YMM1D1 = 629, CV_AMD64_YMM1D2 = 630, CV_AMD64_YMM1D3 = 631, CV_AMD64_YMM2D0 = 632, CV_AMD64_YMM2D1 = 633, CV_AMD64_YMM2D2 = 634, CV_AMD64_YMM2D3 = 635, CV_AMD64_YMM3D0 = 636, CV_AMD64_YMM3D1 = 637, CV_AMD64_YMM3D2 = 638, CV_AMD64_YMM3D3 = 639, CV_AMD64_YMM4D0 = 640, CV_AMD64_YMM4D1 = 641, CV_AMD64_YMM4D2 = 642, CV_AMD64_YMM4D3 = 643, CV_AMD64_YMM5D0 = 644, CV_AMD64_YMM5D1 = 645, CV_AMD64_YMM5D2 = 646, CV_AMD64_YMM5D3 = 647, CV_AMD64_YMM6D0 = 648, CV_AMD64_YMM6D1 = 649, CV_AMD64_YMM6D2 = 650, CV_AMD64_YMM6D3 = 651, CV_AMD64_YMM7D0 = 652, CV_AMD64_YMM7D1 = 653, CV_AMD64_YMM7D2 = 654, CV_AMD64_YMM7D3 = 655, CV_AMD64_YMM8D0 = 656, CV_AMD64_YMM8D1 = 657, CV_AMD64_YMM8D2 = 658, CV_AMD64_YMM8D3 = 659, CV_AMD64_YMM9D0 = 660, CV_AMD64_YMM9D1 = 661, CV_AMD64_YMM9D2 = 662, CV_AMD64_YMM9D3 = 663, CV_AMD64_YMM10D0 = 664, CV_AMD64_YMM10D1 = 665, CV_AMD64_YMM10D2 = 666, CV_AMD64_YMM10D3 = 667, CV_AMD64_YMM11D0 = 668, CV_AMD64_YMM11D1 = 669, CV_AMD64_YMM11D2 = 670, CV_AMD64_YMM11D3 = 671, CV_AMD64_YMM12D0 = 672, CV_AMD64_YMM12D1 = 673, CV_AMD64_YMM12D2 = 674, CV_AMD64_YMM12D3 = 675, CV_AMD64_YMM13D0 = 676, CV_AMD64_YMM13D1 = 677, CV_AMD64_YMM13D2 = 678, CV_AMD64_YMM13D3 = 679, CV_AMD64_YMM14D0 = 680, CV_AMD64_YMM14D1 = 681, CV_AMD64_YMM14D2 = 682, CV_AMD64_YMM14D3 = 683, CV_AMD64_YMM15D0 = 684, CV_AMD64_YMM15D1 = 685, CV_AMD64_YMM15D2 = 686, CV_AMD64_YMM15D3 = 687 // Note: Next set of platform registers need to go into a new enum... // this one is above 44K now. } CV_HREG_e; typedef enum CV_HLSLREG_e { CV_HLSLREG_TEMP = 0, CV_HLSLREG_INPUT = 1, CV_HLSLREG_OUTPUT = 2, CV_HLSLREG_INDEXABLE_TEMP = 3, CV_HLSLREG_IMMEDIATE32 = 4, CV_HLSLREG_IMMEDIATE64 = 5, CV_HLSLREG_SAMPLER = 6, CV_HLSLREG_RESOURCE = 7, CV_HLSLREG_CONSTANT_BUFFER = 8, CV_HLSLREG_IMMEDIATE_CONSTANT_BUFFER = 9, CV_HLSLREG_LABEL = 10, CV_HLSLREG_INPUT_PRIMITIVEID = 11, CV_HLSLREG_OUTPUT_DEPTH = 12, CV_HLSLREG_NULL = 13, CV_HLSLREG_RASTERIZER = 14, CV_HLSLREG_OUTPUT_COVERAGE_MASK = 15, CV_HLSLREG_STREAM = 16, CV_HLSLREG_FUNCTION_BODY = 17, CV_HLSLREG_FUNCTION_TABLE = 18, CV_HLSLREG_INTERFACE = 19, CV_HLSLREG_FUNCTION_INPUT = 20, CV_HLSLREG_FUNCTION_OUTPUT = 21, CV_HLSLREG_OUTPUT_CONTROL_POINT_ID = 22, CV_HLSLREG_INPUT_FORK_INSTANCE_ID = 23, CV_HLSLREG_INPUT_JOIN_INSTANCE_ID = 24, CV_HLSLREG_INPUT_CONTROL_POINT = 25, CV_HLSLREG_OUTPUT_CONTROL_POINT = 26, CV_HLSLREG_INPUT_PATCH_CONSTANT = 27, CV_HLSLREG_INPUT_DOMAIN_POINT = 28, CV_HLSLREG_THIS_POINTER = 29, CV_HLSLREG_UNORDERED_ACCESS_VIEW = 30, CV_HLSLREG_THREAD_GROUP_SHARED_MEMORY = 31, CV_HLSLREG_INPUT_THREAD_ID = 32, CV_HLSLREG_INPUT_THREAD_GROUP_ID = 33, CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP = 34, CV_HLSLREG_INPUT_COVERAGE_MASK = 35, CV_HLSLREG_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, CV_HLSLREG_INPUT_GS_INSTANCE_ID = 37, CV_HLSLREG_OUTPUT_DEPTH_GREATER_EQUAL = 38, CV_HLSLREG_OUTPUT_DEPTH_LESS_EQUAL = 39, CV_HLSLREG_CYCLE_COUNTER = 40, } CV_HLSLREG_e; enum StackFrameTypeEnum { FrameTypeFPO, // Frame pointer omitted, FPO info available FrameTypeTrap, // Kernel Trap frame FrameTypeTSS, // Kernel Trap frame FrameTypeStandard, // Standard EBP stackframe FrameTypeFrameData, // Frame pointer omitted, FrameData info available FrameTypeUnknown = -1, // Frame which does not have any debug info }; enum MemoryTypeEnum { MemTypeCode, // Read only code memory MemTypeData, // Read only data/stack memory MemTypeStack, // Read only stack memory MemTypeCodeOnHeap, // Read only memory for code generated on heap by runtime MemTypeAny = -1, }; typedef enum CV_HLSLMemorySpace_e { // HLSL specific memory spaces CV_HLSL_MEMSPACE_DATA = 0x00, CV_HLSL_MEMSPACE_SAMPLER = 0x01, CV_HLSL_MEMSPACE_RESOURCE = 0x02, CV_HLSL_MEMSPACE_RWRESOURCE = 0x03, CV_HLSL_MEMSPACE_MAX = 0x0F, } CV_HLSLMemorySpace_e; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cvinfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*** cvinfo.h - Generic CodeView information definitions * * Structures, constants, etc. for accessing and interpreting * CodeView information. * */ /*** The master copy of this file resides in the langapi project. * All Microsoft projects are required to use the master copy without * modification. Modification of the master version or a copy * without consultation with all parties concerned is extremely * risky. * */ #pragma once #include "cvconst.h" #ifndef _CV_INFO_INCLUDED #define _CV_INFO_INCLUDED #ifdef __cplusplus #pragma warning ( disable: 4200 ) #endif #ifndef __INLINE #ifdef __cplusplus #define __INLINE inline #else #define __INLINE __inline #endif #endif #pragma pack ( push, 1 ) typedef unsigned long CV_uoff32_t; typedef long CV_off32_t; typedef unsigned short CV_uoff16_t; typedef short CV_off16_t; typedef unsigned short CV_typ16_t; typedef unsigned long CV_typ_t; typedef unsigned long CV_pubsymflag_t; // must be same as CV_typ_t. typedef unsigned short _2BYTEPAD; typedef unsigned long CV_tkn_t; #if !defined (CV_ZEROLEN) #define CV_ZEROLEN #endif #if !defined (FLOAT10) #if defined(_M_I86) // 16 bit x86 supporting long double typedef long double FLOAT10; #else // 32 bit w/o long double support typedef struct FLOAT10 { char b[10]; } FLOAT10; #endif #endif #define CV_SIGNATURE_C6 0L // Actual signature is >64K #define CV_SIGNATURE_C7 1L // First explicit signature #define CV_SIGNATURE_C11 2L // C11 (vc5.x) 32-bit types #define CV_SIGNATURE_C13 4L // C13 (vc7.x) zero terminated names #define CV_SIGNATURE_RESERVED 5L // All signatures from 5 to 64K are reserved #define CV_MAXOFFSET 0xffffffff #ifndef GUID_DEFINED #define GUID_DEFINED typedef struct _GUID { // size is 16 unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[8]; } GUID; #endif // !GUID_DEFINED typedef GUID SIG70; // new to 7.0 are 16-byte guid-like signatures typedef SIG70 * PSIG70; typedef const SIG70 * PCSIG70; /** CodeView Symbol and Type OMF type information is broken up into two * ranges. Type indices less than 0x1000 describe type information * that is frequently used. Type indices above 0x1000 are used to * describe more complex features such as functions, arrays and * structures. */ /** Primitive types have predefined meaning that is encoded in the * values of the various bit fields in the value. * * A CodeView primitive type is defined as: * * 1 1 * 1 089 7654 3 210 * r mode type r sub * * Where * mode is the pointer mode * type is a type indicator * sub is a subtype enumeration * r is a reserved field * * See Microsoft Symbol and Type OMF (Version 4.0) for more * information. */ #define CV_MMASK 0x700 // mode mask #define CV_TMASK 0x0f0 // type mask // can we use the reserved bit ?? #define CV_SMASK 0x00f // subtype mask #define CV_MSHIFT 8 // primitive mode right shift count #define CV_TSHIFT 4 // primitive type right shift count #define CV_SSHIFT 0 // primitive subtype right shift count // macros to extract primitive mode, type and size #define CV_MODE(typ) (((typ) & CV_MMASK) >> CV_MSHIFT) #define CV_TYPE(typ) (((typ) & CV_TMASK) >> CV_TSHIFT) #define CV_SUBT(typ) (((typ) & CV_SMASK) >> CV_SSHIFT) // macros to insert new primitive mode, type and size #define CV_NEWMODE(typ, nm) ((CV_typ_t)(((typ) & ~CV_MMASK) | ((nm) << CV_MSHIFT))) #define CV_NEWTYPE(typ, nt) (((typ) & ~CV_TMASK) | ((nt) << CV_TSHIFT)) #define CV_NEWSUBT(typ, ns) (((typ) & ~CV_SMASK) | ((ns) << CV_SSHIFT)) // pointer mode enumeration values typedef enum CV_prmode_e { CV_TM_DIRECT = 0, // mode is not a pointer CV_TM_NPTR = 1, // mode is a near pointer CV_TM_FPTR = 2, // mode is a far pointer CV_TM_HPTR = 3, // mode is a huge pointer CV_TM_NPTR32 = 4, // mode is a 32 bit near pointer CV_TM_FPTR32 = 5, // mode is a 32 bit far pointer CV_TM_NPTR64 = 6, // mode is a 64 bit near pointer CV_TM_NPTR128 = 7, // mode is a 128 bit near pointer } CV_prmode_e; // type enumeration values typedef enum CV_type_e { CV_SPECIAL = 0x00, // special type size values CV_SIGNED = 0x01, // signed integral size values CV_UNSIGNED = 0x02, // unsigned integral size values CV_BOOLEAN = 0x03, // Boolean size values CV_REAL = 0x04, // real number size values CV_COMPLEX = 0x05, // complex number size values CV_SPECIAL2 = 0x06, // second set of special types CV_INT = 0x07, // integral (int) values CV_CVRESERVED = 0x0f, } CV_type_e; // subtype enumeration values for CV_SPECIAL typedef enum CV_special_e { CV_SP_NOTYPE = 0x00, CV_SP_ABS = 0x01, CV_SP_SEGMENT = 0x02, CV_SP_VOID = 0x03, CV_SP_CURRENCY = 0x04, CV_SP_NBASICSTR = 0x05, CV_SP_FBASICSTR = 0x06, CV_SP_NOTTRANS = 0x07, CV_SP_HRESULT = 0x08, } CV_special_e; // subtype enumeration values for CV_SPECIAL2 typedef enum CV_special2_e { CV_S2_BIT = 0x00, CV_S2_PASCHAR = 0x01, // Pascal CHAR CV_S2_BOOL32FF = 0x02, // 32-bit BOOL where true is 0xffffffff } CV_special2_e; // subtype enumeration values for CV_SIGNED, CV_UNSIGNED and CV_BOOLEAN typedef enum CV_integral_e { CV_IN_1BYTE = 0x00, CV_IN_2BYTE = 0x01, CV_IN_4BYTE = 0x02, CV_IN_8BYTE = 0x03, CV_IN_16BYTE = 0x04 } CV_integral_e; // subtype enumeration values for CV_REAL and CV_COMPLEX typedef enum CV_real_e { CV_RC_REAL32 = 0x00, CV_RC_REAL64 = 0x01, CV_RC_REAL80 = 0x02, CV_RC_REAL128 = 0x03, CV_RC_REAL48 = 0x04, CV_RC_REAL32PP = 0x05, // 32-bit partial precision real CV_RC_REAL16 = 0x06, } CV_real_e; // subtype enumeration values for CV_INT (really int) typedef enum CV_int_e { CV_RI_CHAR = 0x00, CV_RI_INT1 = 0x00, CV_RI_WCHAR = 0x01, CV_RI_UINT1 = 0x01, CV_RI_INT2 = 0x02, CV_RI_UINT2 = 0x03, CV_RI_INT4 = 0x04, CV_RI_UINT4 = 0x05, CV_RI_INT8 = 0x06, CV_RI_UINT8 = 0x07, CV_RI_INT16 = 0x08, CV_RI_UINT16 = 0x09, CV_RI_CHAR16 = 0x0a, // char16_t CV_RI_CHAR32 = 0x0b, // char32_t } CV_int_e; // macros to check the type of a primitive #define CV_TYP_IS_DIRECT(typ) (CV_MODE(typ) == CV_TM_DIRECT) #define CV_TYP_IS_PTR(typ) (CV_MODE(typ) != CV_TM_DIRECT) #define CV_TYP_IS_NPTR(typ) (CV_MODE(typ) == CV_TM_NPTR) #define CV_TYP_IS_FPTR(typ) (CV_MODE(typ) == CV_TM_FPTR) #define CV_TYP_IS_HPTR(typ) (CV_MODE(typ) == CV_TM_HPTR) #define CV_TYP_IS_NPTR32(typ) (CV_MODE(typ) == CV_TM_NPTR32) #define CV_TYP_IS_FPTR32(typ) (CV_MODE(typ) == CV_TM_FPTR32) #define CV_TYP_IS_SIGNED(typ) (((CV_TYPE(typ) == CV_SIGNED) && CV_TYP_IS_DIRECT(typ)) || \ (typ == T_INT1) || \ (typ == T_INT2) || \ (typ == T_INT4) || \ (typ == T_INT8) || \ (typ == T_INT16) || \ (typ == T_RCHAR)) #define CV_TYP_IS_UNSIGNED(typ) (((CV_TYPE(typ) == CV_UNSIGNED) && CV_TYP_IS_DIRECT(typ)) || \ (typ == T_UINT1) || \ (typ == T_UINT2) || \ (typ == T_UINT4) || \ (typ == T_UINT8) || \ (typ == T_UINT16)) #define CV_TYP_IS_REAL(typ) ((CV_TYPE(typ) == CV_REAL) && CV_TYP_IS_DIRECT(typ)) #define CV_FIRST_NONPRIM 0x1000 #define CV_IS_PRIMITIVE(typ) ((typ) < CV_FIRST_NONPRIM) #define CV_TYP_IS_COMPLEX(typ) ((CV_TYPE(typ) == CV_COMPLEX) && CV_TYP_IS_DIRECT(typ)) #define CV_IS_INTERNAL_PTR(typ) (CV_IS_PRIMITIVE(typ) && \ CV_TYPE(typ) == CV_CVRESERVED && \ CV_TYP_IS_PTR(typ)) // selected values for type_index - for a more complete definition, see // Microsoft Symbol and Type OMF document // Special Types typedef enum TYPE_ENUM_e { // Special Types T_NOTYPE = 0x0000, // uncharacterized type (no type) T_ABS = 0x0001, // absolute symbol T_SEGMENT = 0x0002, // segment type T_VOID = 0x0003, // void T_HRESULT = 0x0008, // OLE/COM HRESULT T_32PHRESULT = 0x0408, // OLE/COM HRESULT __ptr32 * T_64PHRESULT = 0x0608, // OLE/COM HRESULT __ptr64 * T_PVOID = 0x0103, // near pointer to void T_PFVOID = 0x0203, // far pointer to void T_PHVOID = 0x0303, // huge pointer to void T_32PVOID = 0x0403, // 32 bit pointer to void T_32PFVOID = 0x0503, // 16:32 pointer to void T_64PVOID = 0x0603, // 64 bit pointer to void T_CURRENCY = 0x0004, // BASIC 8 byte currency value T_NBASICSTR = 0x0005, // Near BASIC string T_FBASICSTR = 0x0006, // Far BASIC string T_NOTTRANS = 0x0007, // type not translated by cvpack T_BIT = 0x0060, // bit T_PASCHAR = 0x0061, // Pascal CHAR T_BOOL32FF = 0x0062, // 32-bit BOOL where true is 0xffffffff // Character types T_CHAR = 0x0010, // 8 bit signed T_PCHAR = 0x0110, // 16 bit pointer to 8 bit signed T_PFCHAR = 0x0210, // 16:16 far pointer to 8 bit signed T_PHCHAR = 0x0310, // 16:16 huge pointer to 8 bit signed T_32PCHAR = 0x0410, // 32 bit pointer to 8 bit signed T_32PFCHAR = 0x0510, // 16:32 pointer to 8 bit signed T_64PCHAR = 0x0610, // 64 bit pointer to 8 bit signed T_UCHAR = 0x0020, // 8 bit unsigned T_PUCHAR = 0x0120, // 16 bit pointer to 8 bit unsigned T_PFUCHAR = 0x0220, // 16:16 far pointer to 8 bit unsigned T_PHUCHAR = 0x0320, // 16:16 huge pointer to 8 bit unsigned T_32PUCHAR = 0x0420, // 32 bit pointer to 8 bit unsigned T_32PFUCHAR = 0x0520, // 16:32 pointer to 8 bit unsigned T_64PUCHAR = 0x0620, // 64 bit pointer to 8 bit unsigned // really a character types T_RCHAR = 0x0070, // really a char T_PRCHAR = 0x0170, // 16 bit pointer to a real char T_PFRCHAR = 0x0270, // 16:16 far pointer to a real char T_PHRCHAR = 0x0370, // 16:16 huge pointer to a real char T_32PRCHAR = 0x0470, // 32 bit pointer to a real char T_32PFRCHAR = 0x0570, // 16:32 pointer to a real char T_64PRCHAR = 0x0670, // 64 bit pointer to a real char // really a wide character types T_WCHAR = 0x0071, // wide char T_PWCHAR = 0x0171, // 16 bit pointer to a wide char T_PFWCHAR = 0x0271, // 16:16 far pointer to a wide char T_PHWCHAR = 0x0371, // 16:16 huge pointer to a wide char T_32PWCHAR = 0x0471, // 32 bit pointer to a wide char T_32PFWCHAR = 0x0571, // 16:32 pointer to a wide char T_64PWCHAR = 0x0671, // 64 bit pointer to a wide char // really a 16-bit unicode char T_CHAR16 = 0x007a, // 16-bit unicode char T_PCHAR16 = 0x017a, // 16 bit pointer to a 16-bit unicode char T_PFCHAR16 = 0x027a, // 16:16 far pointer to a 16-bit unicode char T_PHCHAR16 = 0x037a, // 16:16 huge pointer to a 16-bit unicode char T_32PCHAR16 = 0x047a, // 32 bit pointer to a 16-bit unicode char T_32PFCHAR16 = 0x057a, // 16:32 pointer to a 16-bit unicode char T_64PCHAR16 = 0x067a, // 64 bit pointer to a 16-bit unicode char // really a 32-bit unicode char T_CHAR32 = 0x007b, // 32-bit unicode char T_PCHAR32 = 0x017b, // 16 bit pointer to a 32-bit unicode char T_PFCHAR32 = 0x027b, // 16:16 far pointer to a 32-bit unicode char T_PHCHAR32 = 0x037b, // 16:16 huge pointer to a 32-bit unicode char T_32PCHAR32 = 0x047b, // 32 bit pointer to a 32-bit unicode char T_32PFCHAR32 = 0x057b, // 16:32 pointer to a 32-bit unicode char T_64PCHAR32 = 0x067b, // 64 bit pointer to a 32-bit unicode char // 8 bit int types T_INT1 = 0x0068, // 8 bit signed int T_PINT1 = 0x0168, // 16 bit pointer to 8 bit signed int T_PFINT1 = 0x0268, // 16:16 far pointer to 8 bit signed int T_PHINT1 = 0x0368, // 16:16 huge pointer to 8 bit signed int T_32PINT1 = 0x0468, // 32 bit pointer to 8 bit signed int T_32PFINT1 = 0x0568, // 16:32 pointer to 8 bit signed int T_64PINT1 = 0x0668, // 64 bit pointer to 8 bit signed int T_UINT1 = 0x0069, // 8 bit unsigned int T_PUINT1 = 0x0169, // 16 bit pointer to 8 bit unsigned int T_PFUINT1 = 0x0269, // 16:16 far pointer to 8 bit unsigned int T_PHUINT1 = 0x0369, // 16:16 huge pointer to 8 bit unsigned int T_32PUINT1 = 0x0469, // 32 bit pointer to 8 bit unsigned int T_32PFUINT1 = 0x0569, // 16:32 pointer to 8 bit unsigned int T_64PUINT1 = 0x0669, // 64 bit pointer to 8 bit unsigned int // 16 bit short types T_SHORT = 0x0011, // 16 bit signed T_PSHORT = 0x0111, // 16 bit pointer to 16 bit signed T_PFSHORT = 0x0211, // 16:16 far pointer to 16 bit signed T_PHSHORT = 0x0311, // 16:16 huge pointer to 16 bit signed T_32PSHORT = 0x0411, // 32 bit pointer to 16 bit signed T_32PFSHORT = 0x0511, // 16:32 pointer to 16 bit signed T_64PSHORT = 0x0611, // 64 bit pointer to 16 bit signed T_USHORT = 0x0021, // 16 bit unsigned T_PUSHORT = 0x0121, // 16 bit pointer to 16 bit unsigned T_PFUSHORT = 0x0221, // 16:16 far pointer to 16 bit unsigned T_PHUSHORT = 0x0321, // 16:16 huge pointer to 16 bit unsigned T_32PUSHORT = 0x0421, // 32 bit pointer to 16 bit unsigned T_32PFUSHORT = 0x0521, // 16:32 pointer to 16 bit unsigned T_64PUSHORT = 0x0621, // 64 bit pointer to 16 bit unsigned // 16 bit int types T_INT2 = 0x0072, // 16 bit signed int T_PINT2 = 0x0172, // 16 bit pointer to 16 bit signed int T_PFINT2 = 0x0272, // 16:16 far pointer to 16 bit signed int T_PHINT2 = 0x0372, // 16:16 huge pointer to 16 bit signed int T_32PINT2 = 0x0472, // 32 bit pointer to 16 bit signed int T_32PFINT2 = 0x0572, // 16:32 pointer to 16 bit signed int T_64PINT2 = 0x0672, // 64 bit pointer to 16 bit signed int T_UINT2 = 0x0073, // 16 bit unsigned int T_PUINT2 = 0x0173, // 16 bit pointer to 16 bit unsigned int T_PFUINT2 = 0x0273, // 16:16 far pointer to 16 bit unsigned int T_PHUINT2 = 0x0373, // 16:16 huge pointer to 16 bit unsigned int T_32PUINT2 = 0x0473, // 32 bit pointer to 16 bit unsigned int T_32PFUINT2 = 0x0573, // 16:32 pointer to 16 bit unsigned int T_64PUINT2 = 0x0673, // 64 bit pointer to 16 bit unsigned int // 32 bit long types T_LONG = 0x0012, // 32 bit signed T_ULONG = 0x0022, // 32 bit unsigned T_PLONG = 0x0112, // 16 bit pointer to 32 bit signed T_PULONG = 0x0122, // 16 bit pointer to 32 bit unsigned T_PFLONG = 0x0212, // 16:16 far pointer to 32 bit signed T_PFULONG = 0x0222, // 16:16 far pointer to 32 bit unsigned T_PHLONG = 0x0312, // 16:16 huge pointer to 32 bit signed T_PHULONG = 0x0322, // 16:16 huge pointer to 32 bit unsigned T_32PLONG = 0x0412, // 32 bit pointer to 32 bit signed T_32PULONG = 0x0422, // 32 bit pointer to 32 bit unsigned T_32PFLONG = 0x0512, // 16:32 pointer to 32 bit signed T_32PFULONG = 0x0522, // 16:32 pointer to 32 bit unsigned T_64PLONG = 0x0612, // 64 bit pointer to 32 bit signed T_64PULONG = 0x0622, // 64 bit pointer to 32 bit unsigned // 32 bit int types T_INT4 = 0x0074, // 32 bit signed int T_PINT4 = 0x0174, // 16 bit pointer to 32 bit signed int T_PFINT4 = 0x0274, // 16:16 far pointer to 32 bit signed int T_PHINT4 = 0x0374, // 16:16 huge pointer to 32 bit signed int T_32PINT4 = 0x0474, // 32 bit pointer to 32 bit signed int T_32PFINT4 = 0x0574, // 16:32 pointer to 32 bit signed int T_64PINT4 = 0x0674, // 64 bit pointer to 32 bit signed int T_UINT4 = 0x0075, // 32 bit unsigned int T_PUINT4 = 0x0175, // 16 bit pointer to 32 bit unsigned int T_PFUINT4 = 0x0275, // 16:16 far pointer to 32 bit unsigned int T_PHUINT4 = 0x0375, // 16:16 huge pointer to 32 bit unsigned int T_32PUINT4 = 0x0475, // 32 bit pointer to 32 bit unsigned int T_32PFUINT4 = 0x0575, // 16:32 pointer to 32 bit unsigned int T_64PUINT4 = 0x0675, // 64 bit pointer to 32 bit unsigned int // 64 bit quad types T_QUAD = 0x0013, // 64 bit signed T_PQUAD = 0x0113, // 16 bit pointer to 64 bit signed T_PFQUAD = 0x0213, // 16:16 far pointer to 64 bit signed T_PHQUAD = 0x0313, // 16:16 huge pointer to 64 bit signed T_32PQUAD = 0x0413, // 32 bit pointer to 64 bit signed T_32PFQUAD = 0x0513, // 16:32 pointer to 64 bit signed T_64PQUAD = 0x0613, // 64 bit pointer to 64 bit signed T_UQUAD = 0x0023, // 64 bit unsigned T_PUQUAD = 0x0123, // 16 bit pointer to 64 bit unsigned T_PFUQUAD = 0x0223, // 16:16 far pointer to 64 bit unsigned T_PHUQUAD = 0x0323, // 16:16 huge pointer to 64 bit unsigned T_32PUQUAD = 0x0423, // 32 bit pointer to 64 bit unsigned T_32PFUQUAD = 0x0523, // 16:32 pointer to 64 bit unsigned T_64PUQUAD = 0x0623, // 64 bit pointer to 64 bit unsigned // 64 bit int types T_INT8 = 0x0076, // 64 bit signed int T_PINT8 = 0x0176, // 16 bit pointer to 64 bit signed int T_PFINT8 = 0x0276, // 16:16 far pointer to 64 bit signed int T_PHINT8 = 0x0376, // 16:16 huge pointer to 64 bit signed int T_32PINT8 = 0x0476, // 32 bit pointer to 64 bit signed int T_32PFINT8 = 0x0576, // 16:32 pointer to 64 bit signed int T_64PINT8 = 0x0676, // 64 bit pointer to 64 bit signed int T_UINT8 = 0x0077, // 64 bit unsigned int T_PUINT8 = 0x0177, // 16 bit pointer to 64 bit unsigned int T_PFUINT8 = 0x0277, // 16:16 far pointer to 64 bit unsigned int T_PHUINT8 = 0x0377, // 16:16 huge pointer to 64 bit unsigned int T_32PUINT8 = 0x0477, // 32 bit pointer to 64 bit unsigned int T_32PFUINT8 = 0x0577, // 16:32 pointer to 64 bit unsigned int T_64PUINT8 = 0x0677, // 64 bit pointer to 64 bit unsigned int // 128 bit octet types T_OCT = 0x0014, // 128 bit signed T_POCT = 0x0114, // 16 bit pointer to 128 bit signed T_PFOCT = 0x0214, // 16:16 far pointer to 128 bit signed T_PHOCT = 0x0314, // 16:16 huge pointer to 128 bit signed T_32POCT = 0x0414, // 32 bit pointer to 128 bit signed T_32PFOCT = 0x0514, // 16:32 pointer to 128 bit signed T_64POCT = 0x0614, // 64 bit pointer to 128 bit signed T_UOCT = 0x0024, // 128 bit unsigned T_PUOCT = 0x0124, // 16 bit pointer to 128 bit unsigned T_PFUOCT = 0x0224, // 16:16 far pointer to 128 bit unsigned T_PHUOCT = 0x0324, // 16:16 huge pointer to 128 bit unsigned T_32PUOCT = 0x0424, // 32 bit pointer to 128 bit unsigned T_32PFUOCT = 0x0524, // 16:32 pointer to 128 bit unsigned T_64PUOCT = 0x0624, // 64 bit pointer to 128 bit unsigned // 128 bit int types T_INT16 = 0x0078, // 128 bit signed int T_PINT16 = 0x0178, // 16 bit pointer to 128 bit signed int T_PFINT16 = 0x0278, // 16:16 far pointer to 128 bit signed int T_PHINT16 = 0x0378, // 16:16 huge pointer to 128 bit signed int T_32PINT16 = 0x0478, // 32 bit pointer to 128 bit signed int T_32PFINT16 = 0x0578, // 16:32 pointer to 128 bit signed int T_64PINT16 = 0x0678, // 64 bit pointer to 128 bit signed int T_UINT16 = 0x0079, // 128 bit unsigned int T_PUINT16 = 0x0179, // 16 bit pointer to 128 bit unsigned int T_PFUINT16 = 0x0279, // 16:16 far pointer to 128 bit unsigned int T_PHUINT16 = 0x0379, // 16:16 huge pointer to 128 bit unsigned int T_32PUINT16 = 0x0479, // 32 bit pointer to 128 bit unsigned int T_32PFUINT16 = 0x0579, // 16:32 pointer to 128 bit unsigned int T_64PUINT16 = 0x0679, // 64 bit pointer to 128 bit unsigned int // 16 bit real types T_REAL16 = 0x0046, // 16 bit real T_PREAL16 = 0x0146, // 16 bit pointer to 16 bit real T_PFREAL16 = 0x0246, // 16:16 far pointer to 16 bit real T_PHREAL16 = 0x0346, // 16:16 huge pointer to 16 bit real T_32PREAL16 = 0x0446, // 32 bit pointer to 16 bit real T_32PFREAL16 = 0x0546, // 16:32 pointer to 16 bit real T_64PREAL16 = 0x0646, // 64 bit pointer to 16 bit real // 32 bit real types T_REAL32 = 0x0040, // 32 bit real T_PREAL32 = 0x0140, // 16 bit pointer to 32 bit real T_PFREAL32 = 0x0240, // 16:16 far pointer to 32 bit real T_PHREAL32 = 0x0340, // 16:16 huge pointer to 32 bit real T_32PREAL32 = 0x0440, // 32 bit pointer to 32 bit real T_32PFREAL32 = 0x0540, // 16:32 pointer to 32 bit real T_64PREAL32 = 0x0640, // 64 bit pointer to 32 bit real // 32 bit partial-precision real types T_REAL32PP = 0x0045, // 32 bit PP real T_PREAL32PP = 0x0145, // 16 bit pointer to 32 bit PP real T_PFREAL32PP = 0x0245, // 16:16 far pointer to 32 bit PP real T_PHREAL32PP = 0x0345, // 16:16 huge pointer to 32 bit PP real T_32PREAL32PP = 0x0445, // 32 bit pointer to 32 bit PP real T_32PFREAL32PP = 0x0545, // 16:32 pointer to 32 bit PP real T_64PREAL32PP = 0x0645, // 64 bit pointer to 32 bit PP real // 48 bit real types T_REAL48 = 0x0044, // 48 bit real T_PREAL48 = 0x0144, // 16 bit pointer to 48 bit real T_PFREAL48 = 0x0244, // 16:16 far pointer to 48 bit real T_PHREAL48 = 0x0344, // 16:16 huge pointer to 48 bit real T_32PREAL48 = 0x0444, // 32 bit pointer to 48 bit real T_32PFREAL48 = 0x0544, // 16:32 pointer to 48 bit real T_64PREAL48 = 0x0644, // 64 bit pointer to 48 bit real // 64 bit real types T_REAL64 = 0x0041, // 64 bit real T_PREAL64 = 0x0141, // 16 bit pointer to 64 bit real T_PFREAL64 = 0x0241, // 16:16 far pointer to 64 bit real T_PHREAL64 = 0x0341, // 16:16 huge pointer to 64 bit real T_32PREAL64 = 0x0441, // 32 bit pointer to 64 bit real T_32PFREAL64 = 0x0541, // 16:32 pointer to 64 bit real T_64PREAL64 = 0x0641, // 64 bit pointer to 64 bit real // 80 bit real types T_REAL80 = 0x0042, // 80 bit real T_PREAL80 = 0x0142, // 16 bit pointer to 80 bit real T_PFREAL80 = 0x0242, // 16:16 far pointer to 80 bit real T_PHREAL80 = 0x0342, // 16:16 huge pointer to 80 bit real T_32PREAL80 = 0x0442, // 32 bit pointer to 80 bit real T_32PFREAL80 = 0x0542, // 16:32 pointer to 80 bit real T_64PREAL80 = 0x0642, // 64 bit pointer to 80 bit real // 128 bit real types T_REAL128 = 0x0043, // 128 bit real T_PREAL128 = 0x0143, // 16 bit pointer to 128 bit real T_PFREAL128 = 0x0243, // 16:16 far pointer to 128 bit real T_PHREAL128 = 0x0343, // 16:16 huge pointer to 128 bit real T_32PREAL128 = 0x0443, // 32 bit pointer to 128 bit real T_32PFREAL128 = 0x0543, // 16:32 pointer to 128 bit real T_64PREAL128 = 0x0643, // 64 bit pointer to 128 bit real // 32 bit complex types T_CPLX32 = 0x0050, // 32 bit complex T_PCPLX32 = 0x0150, // 16 bit pointer to 32 bit complex T_PFCPLX32 = 0x0250, // 16:16 far pointer to 32 bit complex T_PHCPLX32 = 0x0350, // 16:16 huge pointer to 32 bit complex T_32PCPLX32 = 0x0450, // 32 bit pointer to 32 bit complex T_32PFCPLX32 = 0x0550, // 16:32 pointer to 32 bit complex T_64PCPLX32 = 0x0650, // 64 bit pointer to 32 bit complex // 64 bit complex types T_CPLX64 = 0x0051, // 64 bit complex T_PCPLX64 = 0x0151, // 16 bit pointer to 64 bit complex T_PFCPLX64 = 0x0251, // 16:16 far pointer to 64 bit complex T_PHCPLX64 = 0x0351, // 16:16 huge pointer to 64 bit complex T_32PCPLX64 = 0x0451, // 32 bit pointer to 64 bit complex T_32PFCPLX64 = 0x0551, // 16:32 pointer to 64 bit complex T_64PCPLX64 = 0x0651, // 64 bit pointer to 64 bit complex // 80 bit complex types T_CPLX80 = 0x0052, // 80 bit complex T_PCPLX80 = 0x0152, // 16 bit pointer to 80 bit complex T_PFCPLX80 = 0x0252, // 16:16 far pointer to 80 bit complex T_PHCPLX80 = 0x0352, // 16:16 huge pointer to 80 bit complex T_32PCPLX80 = 0x0452, // 32 bit pointer to 80 bit complex T_32PFCPLX80 = 0x0552, // 16:32 pointer to 80 bit complex T_64PCPLX80 = 0x0652, // 64 bit pointer to 80 bit complex // 128 bit complex types T_CPLX128 = 0x0053, // 128 bit complex T_PCPLX128 = 0x0153, // 16 bit pointer to 128 bit complex T_PFCPLX128 = 0x0253, // 16:16 far pointer to 128 bit complex T_PHCPLX128 = 0x0353, // 16:16 huge pointer to 128 bit real T_32PCPLX128 = 0x0453, // 32 bit pointer to 128 bit complex T_32PFCPLX128 = 0x0553, // 16:32 pointer to 128 bit complex T_64PCPLX128 = 0x0653, // 64 bit pointer to 128 bit complex // boolean types T_BOOL08 = 0x0030, // 8 bit boolean T_PBOOL08 = 0x0130, // 16 bit pointer to 8 bit boolean T_PFBOOL08 = 0x0230, // 16:16 far pointer to 8 bit boolean T_PHBOOL08 = 0x0330, // 16:16 huge pointer to 8 bit boolean T_32PBOOL08 = 0x0430, // 32 bit pointer to 8 bit boolean T_32PFBOOL08 = 0x0530, // 16:32 pointer to 8 bit boolean T_64PBOOL08 = 0x0630, // 64 bit pointer to 8 bit boolean T_BOOL16 = 0x0031, // 16 bit boolean T_PBOOL16 = 0x0131, // 16 bit pointer to 16 bit boolean T_PFBOOL16 = 0x0231, // 16:16 far pointer to 16 bit boolean T_PHBOOL16 = 0x0331, // 16:16 huge pointer to 16 bit boolean T_32PBOOL16 = 0x0431, // 32 bit pointer to 18 bit boolean T_32PFBOOL16 = 0x0531, // 16:32 pointer to 16 bit boolean T_64PBOOL16 = 0x0631, // 64 bit pointer to 18 bit boolean T_BOOL32 = 0x0032, // 32 bit boolean T_PBOOL32 = 0x0132, // 16 bit pointer to 32 bit boolean T_PFBOOL32 = 0x0232, // 16:16 far pointer to 32 bit boolean T_PHBOOL32 = 0x0332, // 16:16 huge pointer to 32 bit boolean T_32PBOOL32 = 0x0432, // 32 bit pointer to 32 bit boolean T_32PFBOOL32 = 0x0532, // 16:32 pointer to 32 bit boolean T_64PBOOL32 = 0x0632, // 64 bit pointer to 32 bit boolean T_BOOL64 = 0x0033, // 64 bit boolean T_PBOOL64 = 0x0133, // 16 bit pointer to 64 bit boolean T_PFBOOL64 = 0x0233, // 16:16 far pointer to 64 bit boolean T_PHBOOL64 = 0x0333, // 16:16 huge pointer to 64 bit boolean T_32PBOOL64 = 0x0433, // 32 bit pointer to 64 bit boolean T_32PFBOOL64 = 0x0533, // 16:32 pointer to 64 bit boolean T_64PBOOL64 = 0x0633, // 64 bit pointer to 64 bit boolean // ??? T_NCVPTR = 0x01f0, // CV Internal type for created near pointers T_FCVPTR = 0x02f0, // CV Internal type for created far pointers T_HCVPTR = 0x03f0, // CV Internal type for created huge pointers T_32NCVPTR = 0x04f0, // CV Internal type for created near 32-bit pointers T_32FCVPTR = 0x05f0, // CV Internal type for created far 32-bit pointers T_64NCVPTR = 0x06f0, // CV Internal type for created near 64-bit pointers } TYPE_ENUM_e; /** No leaf index can have a value of 0x0000. The leaf indices are * separated into ranges depending upon the use of the type record. * The second range is for the type records that are directly referenced * in symbols. The first range is for type records that are not * referenced by symbols but instead are referenced by other type * records. All type records must have a starting leaf index in these * first two ranges. The third range of leaf indices are used to build * up complex lists such as the field list of a class type record. No * type record can begin with one of the leaf indices. The fourth ranges * of type indices are used to represent numeric data in a symbol or * type record. These leaf indices are greater than 0x8000. At the * point that type or symbol processor is expecting a numeric field, the * next two bytes in the type record are examined. If the value is less * than 0x8000, then the two bytes contain the numeric value. If the * value is greater than 0x8000, then the data follows the leaf index in * a format specified by the leaf index. The final range of leaf indices * are used to force alignment of subfields within a complex type record.. */ typedef enum LEAF_ENUM_e { // leaf indices starting records but referenced from symbol records LF_MODIFIER_16t = 0x0001, LF_POINTER_16t = 0x0002, LF_ARRAY_16t = 0x0003, LF_CLASS_16t = 0x0004, LF_STRUCTURE_16t = 0x0005, LF_UNION_16t = 0x0006, LF_ENUM_16t = 0x0007, LF_PROCEDURE_16t = 0x0008, LF_MFUNCTION_16t = 0x0009, LF_VTSHAPE = 0x000a, LF_COBOL0_16t = 0x000b, LF_COBOL1 = 0x000c, LF_BARRAY_16t = 0x000d, LF_LABEL = 0x000e, LF_NULL = 0x000f, LF_NOTTRAN = 0x0010, LF_DIMARRAY_16t = 0x0011, LF_VFTPATH_16t = 0x0012, LF_PRECOMP_16t = 0x0013, // not referenced from symbol LF_ENDPRECOMP = 0x0014, // not referenced from symbol LF_OEM_16t = 0x0015, // oem definable type string LF_TYPESERVER_ST = 0x0016, // not referenced from symbol // leaf indices starting records but referenced only from type records LF_SKIP_16t = 0x0200, LF_ARGLIST_16t = 0x0201, LF_DEFARG_16t = 0x0202, LF_LIST = 0x0203, LF_FIELDLIST_16t = 0x0204, LF_DERIVED_16t = 0x0205, LF_BITFIELD_16t = 0x0206, LF_METHODLIST_16t = 0x0207, LF_DIMCONU_16t = 0x0208, LF_DIMCONLU_16t = 0x0209, LF_DIMVARU_16t = 0x020a, LF_DIMVARLU_16t = 0x020b, LF_REFSYM = 0x020c, LF_BCLASS_16t = 0x0400, LF_VBCLASS_16t = 0x0401, LF_IVBCLASS_16t = 0x0402, LF_ENUMERATE_ST = 0x0403, LF_FRIENDFCN_16t = 0x0404, LF_INDEX_16t = 0x0405, LF_MEMBER_16t = 0x0406, LF_STMEMBER_16t = 0x0407, LF_METHOD_16t = 0x0408, LF_NESTTYPE_16t = 0x0409, LF_VFUNCTAB_16t = 0x040a, LF_FRIENDCLS_16t = 0x040b, LF_ONEMETHOD_16t = 0x040c, LF_VFUNCOFF_16t = 0x040d, // 32-bit type index versions of leaves, all have the 0x1000 bit set // LF_TI16_MAX = 0x1000, LF_MODIFIER = 0x1001, LF_POINTER = 0x1002, LF_ARRAY_ST = 0x1003, LF_CLASS_ST = 0x1004, LF_STRUCTURE_ST = 0x1005, LF_UNION_ST = 0x1006, LF_ENUM_ST = 0x1007, LF_PROCEDURE = 0x1008, LF_MFUNCTION = 0x1009, LF_COBOL0 = 0x100a, LF_BARRAY = 0x100b, LF_DIMARRAY_ST = 0x100c, LF_VFTPATH = 0x100d, LF_PRECOMP_ST = 0x100e, // not referenced from symbol LF_OEM = 0x100f, // oem definable type string LF_ALIAS_ST = 0x1010, // alias (typedef) type LF_OEM2 = 0x1011, // oem definable type string // leaf indices starting records but referenced only from type records LF_SKIP = 0x1200, LF_ARGLIST = 0x1201, LF_DEFARG_ST = 0x1202, LF_FIELDLIST = 0x1203, LF_DERIVED = 0x1204, LF_BITFIELD = 0x1205, LF_METHODLIST = 0x1206, LF_DIMCONU = 0x1207, LF_DIMCONLU = 0x1208, LF_DIMVARU = 0x1209, LF_DIMVARLU = 0x120a, LF_BCLASS = 0x1400, LF_VBCLASS = 0x1401, LF_IVBCLASS = 0x1402, LF_FRIENDFCN_ST = 0x1403, LF_INDEX = 0x1404, LF_MEMBER_ST = 0x1405, LF_STMEMBER_ST = 0x1406, LF_METHOD_ST = 0x1407, LF_NESTTYPE_ST = 0x1408, LF_VFUNCTAB = 0x1409, LF_FRIENDCLS = 0x140a, LF_ONEMETHOD_ST = 0x140b, LF_VFUNCOFF = 0x140c, LF_NESTTYPEEX_ST = 0x140d, LF_MEMBERMODIFY_ST = 0x140e, LF_MANAGED_ST = 0x140f, // Types w/ SZ names LF_ST_MAX = 0x1500, LF_TYPESERVER = 0x1501, // not referenced from symbol LF_ENUMERATE = 0x1502, LF_ARRAY = 0x1503, LF_CLASS = 0x1504, LF_STRUCTURE = 0x1505, LF_UNION = 0x1506, LF_ENUM = 0x1507, LF_DIMARRAY = 0x1508, LF_PRECOMP = 0x1509, // not referenced from symbol LF_ALIAS = 0x150a, // alias (typedef) type LF_DEFARG = 0x150b, LF_FRIENDFCN = 0x150c, LF_MEMBER = 0x150d, LF_STMEMBER = 0x150e, LF_METHOD = 0x150f, LF_NESTTYPE = 0x1510, LF_ONEMETHOD = 0x1511, LF_NESTTYPEEX = 0x1512, LF_MEMBERMODIFY = 0x1513, LF_MANAGED = 0x1514, LF_TYPESERVER2 = 0x1515, LF_STRIDED_ARRAY = 0x1516, // same as LF_ARRAY, but with stride between adjacent elements LF_HLSL = 0x1517, LF_MODIFIER_EX = 0x1518, LF_INTERFACE = 0x1519, LF_BINTERFACE = 0x151a, LF_VECTOR = 0x151b, LF_MATRIX = 0x151c, LF_VFTABLE = 0x151d, // a virtual function table LF_ENDOFLEAFRECORD = LF_VFTABLE, LF_TYPE_LAST, // one greater than the last type record LF_TYPE_MAX = LF_TYPE_LAST - 1, LF_FUNC_ID = 0x1601, // global func ID LF_MFUNC_ID = 0x1602, // member func ID LF_BUILDINFO = 0x1603, // build info: tool, version, command line, src/pdb file LF_SUBSTR_LIST = 0x1604, // similar to LF_ARGLIST, for list of sub strings LF_STRING_ID = 0x1605, // string ID LF_UDT_SRC_LINE = 0x1606, // source and line on where an UDT is defined // only generated by compiler LF_UDT_MOD_SRC_LINE = 0x1607, // module, source and line on where an UDT is defined // only generated by linker LF_ID_LAST, // one greater than the last ID record LF_ID_MAX = LF_ID_LAST - 1, LF_NUMERIC = 0x8000, LF_CHAR = 0x8000, LF_SHORT = 0x8001, LF_USHORT = 0x8002, LF_LONG = 0x8003, LF_ULONG = 0x8004, LF_REAL32 = 0x8005, LF_REAL64 = 0x8006, LF_REAL80 = 0x8007, LF_REAL128 = 0x8008, LF_QUADWORD = 0x8009, LF_UQUADWORD = 0x800a, LF_REAL48 = 0x800b, LF_COMPLEX32 = 0x800c, LF_COMPLEX64 = 0x800d, LF_COMPLEX80 = 0x800e, LF_COMPLEX128 = 0x800f, LF_VARSTRING = 0x8010, LF_OCTWORD = 0x8017, LF_UOCTWORD = 0x8018, LF_DECIMAL = 0x8019, LF_DATE = 0x801a, LF_UTF8STRING = 0x801b, LF_REAL16 = 0x801c, LF_PAD0 = 0xf0, LF_PAD1 = 0xf1, LF_PAD2 = 0xf2, LF_PAD3 = 0xf3, LF_PAD4 = 0xf4, LF_PAD5 = 0xf5, LF_PAD6 = 0xf6, LF_PAD7 = 0xf7, LF_PAD8 = 0xf8, LF_PAD9 = 0xf9, LF_PAD10 = 0xfa, LF_PAD11 = 0xfb, LF_PAD12 = 0xfc, LF_PAD13 = 0xfd, LF_PAD14 = 0xfe, LF_PAD15 = 0xff, } LEAF_ENUM_e; // end of leaf indices // Type enum for pointer records // Pointers can be one of the following types typedef enum CV_ptrtype_e { CV_PTR_NEAR = 0x00, // 16 bit pointer CV_PTR_FAR = 0x01, // 16:16 far pointer CV_PTR_HUGE = 0x02, // 16:16 huge pointer CV_PTR_BASE_SEG = 0x03, // based on segment CV_PTR_BASE_VAL = 0x04, // based on value of base CV_PTR_BASE_SEGVAL = 0x05, // based on segment value of base CV_PTR_BASE_ADDR = 0x06, // based on address of base CV_PTR_BASE_SEGADDR = 0x07, // based on segment address of base CV_PTR_BASE_TYPE = 0x08, // based on type CV_PTR_BASE_SELF = 0x09, // based on self CV_PTR_NEAR32 = 0x0a, // 32 bit pointer CV_PTR_FAR32 = 0x0b, // 16:32 pointer CV_PTR_64 = 0x0c, // 64 bit pointer CV_PTR_UNUSEDPTR = 0x0d // first unused pointer type } CV_ptrtype_e; // Mode enum for pointers // Pointers can have one of the following modes // // To support for l-value and r-value reference, we added CV_PTR_MODE_LVREF // and CV_PTR_MODE_RVREF. CV_PTR_MODE_REF should be removed at some point. // We keep it now so that old code that uses it won't be broken. // typedef enum CV_ptrmode_e { CV_PTR_MODE_PTR = 0x00, // "normal" pointer CV_PTR_MODE_REF = 0x01, // "old" reference CV_PTR_MODE_LVREF = 0x01, // l-value reference CV_PTR_MODE_PMEM = 0x02, // pointer to data member CV_PTR_MODE_PMFUNC = 0x03, // pointer to member function CV_PTR_MODE_RVREF = 0x04, // r-value reference CV_PTR_MODE_RESERVED= 0x05 // first unused pointer mode } CV_ptrmode_e; // enumeration for pointer-to-member types typedef enum CV_pmtype_e { CV_PMTYPE_Undef = 0x00, // not specified (pre VC8) CV_PMTYPE_D_Single = 0x01, // member data, single inheritance CV_PMTYPE_D_Multiple= 0x02, // member data, multiple inheritance CV_PMTYPE_D_Virtual = 0x03, // member data, virtual inheritance CV_PMTYPE_D_General = 0x04, // member data, most general CV_PMTYPE_F_Single = 0x05, // member function, single inheritance CV_PMTYPE_F_Multiple= 0x06, // member function, multiple inheritance CV_PMTYPE_F_Virtual = 0x07, // member function, virtual inheritance CV_PMTYPE_F_General = 0x08, // member function, most general } CV_pmtype_e; // enumeration for method properties typedef enum CV_methodprop_e { CV_MTvanilla = 0x00, CV_MTvirtual = 0x01, CV_MTstatic = 0x02, CV_MTfriend = 0x03, CV_MTintro = 0x04, CV_MTpurevirt = 0x05, CV_MTpureintro = 0x06 } CV_methodprop_e; // enumeration for virtual shape table entries typedef enum CV_VTS_desc_e { CV_VTS_near = 0x00, CV_VTS_far = 0x01, CV_VTS_thin = 0x02, CV_VTS_outer = 0x03, CV_VTS_meta = 0x04, CV_VTS_near32 = 0x05, CV_VTS_far32 = 0x06, CV_VTS_unused = 0x07 } CV_VTS_desc_e; // enumeration for LF_LABEL address modes typedef enum CV_LABEL_TYPE_e { CV_LABEL_NEAR = 0, // near return CV_LABEL_FAR = 4 // far return } CV_LABEL_TYPE_e; // enumeration for LF_MODIFIER values typedef struct CV_modifier_t { unsigned short MOD_const :1; unsigned short MOD_volatile :1; unsigned short MOD_unaligned :1; unsigned short MOD_unused :13; } CV_modifier_t; // enumeration for HFA kinds typedef enum CV_HFA_e { CV_HFA_none = 0, CV_HFA_float = 1, CV_HFA_double = 2, CV_HFA_other = 3 } CV_HFA_e; // enumeration for MoCOM UDT kinds typedef enum CV_MOCOM_UDT_e { CV_MOCOM_UDT_none = 0, CV_MOCOM_UDT_ref = 1, CV_MOCOM_UDT_value = 2, CV_MOCOM_UDT_interface = 3 } CV_MOCOM_UDT_e; // bit field structure describing class/struct/union/enum properties typedef struct CV_prop_t { unsigned short packed :1; // true if structure is packed unsigned short ctor :1; // true if constructors or destructors present unsigned short ovlops :1; // true if overloaded operators present unsigned short isnested :1; // true if this is a nested class unsigned short cnested :1; // true if this class contains nested types unsigned short opassign :1; // true if overloaded assignment (=) unsigned short opcast :1; // true if casting methods unsigned short fwdref :1; // true if forward reference (incomplete defn) unsigned short scoped :1; // scoped definition unsigned short hasuniquename :1; // true if there is a decorated name following the regular name unsigned short sealed :1; // true if class cannot be used as a base class unsigned short hfa :2; // CV_HFA_e unsigned short intrinsic :1; // true if class is an intrinsic type (e.g. __m128d) unsigned short mocom :2; // CV_MOCOM_UDT_e } CV_prop_t; // class field attribute typedef struct CV_fldattr_t { unsigned short access :2; // access protection CV_access_t unsigned short mprop :3; // method properties CV_methodprop_t unsigned short pseudo :1; // compiler generated fcn and does not exist unsigned short noinherit :1; // true if class cannot be inherited unsigned short noconstruct :1; // true if class cannot be constructed unsigned short compgenx :1; // compiler generated fcn and does exist unsigned short sealed :1; // true if method cannot be overridden unsigned short unused :6; // unused } CV_fldattr_t; // function flags typedef struct CV_funcattr_t { unsigned char cxxreturnudt :1; // true if C++ style ReturnUDT unsigned char ctor :1; // true if func is an instance constructor unsigned char ctorvbase :1; // true if func is an instance constructor of a class with virtual bases unsigned char unused :5; // unused } CV_funcattr_t; // matrix flags typedef struct CV_matrixattr_t { unsigned char row_major :1; // true if matrix has row-major layout (column-major is default) unsigned char unused :7; // unused } CV_matrixattr_t; // Structures to access to the type records typedef struct TYPTYPE { unsigned short len; unsigned short leaf; unsigned char data[CV_ZEROLEN]; } TYPTYPE; // general types record __INLINE char *NextType ( _In_ char * pType) { return (pType + ((TYPTYPE *)pType)->len + sizeof(unsigned short)); } typedef enum CV_PMEMBER { CV_PDM16_NONVIRT = 0x00, // 16:16 data no virtual fcn or base CV_PDM16_VFCN = 0x01, // 16:16 data with virtual functions CV_PDM16_VBASE = 0x02, // 16:16 data with virtual bases CV_PDM32_NVVFCN = 0x03, // 16:32 data w/wo virtual functions CV_PDM32_VBASE = 0x04, // 16:32 data with virtual bases CV_PMF16_NEARNVSA = 0x05, // 16:16 near method nonvirtual single address point CV_PMF16_NEARNVMA = 0x06, // 16:16 near method nonvirtual multiple address points CV_PMF16_NEARVBASE = 0x07, // 16:16 near method virtual bases CV_PMF16_FARNVSA = 0x08, // 16:16 far method nonvirtual single address point CV_PMF16_FARNVMA = 0x09, // 16:16 far method nonvirtual multiple address points CV_PMF16_FARVBASE = 0x0a, // 16:16 far method virtual bases CV_PMF32_NVSA = 0x0b, // 16:32 method nonvirtual single address point CV_PMF32_NVMA = 0x0c, // 16:32 method nonvirtual multiple address point CV_PMF32_VBASE = 0x0d // 16:32 method virtual bases } CV_PMEMBER; // memory representation of pointer to member. These representations are // indexed by the enumeration above in the LF_POINTER record // representation of a 16:16 pointer to data for a class with no // virtual functions or virtual bases struct CV_PDMR16_NONVIRT { CV_off16_t mdisp; // displacement to data (NULL = -1) }; // representation of a 16:16 pointer to data for a class with virtual // functions struct CV_PMDR16_VFCN { CV_off16_t mdisp; // displacement to data ( NULL = 0) }; // representation of a 16:16 pointer to data for a class with // virtual bases struct CV_PDMR16_VBASE { CV_off16_t mdisp; // displacement to data CV_off16_t pdisp; // this pointer displacement to vbptr CV_off16_t vdisp; // displacement within vbase table // NULL = (,,0xffff) }; // representation of a 32 bit pointer to data for a class with // or without virtual functions and no virtual bases struct CV_PDMR32_NVVFCN { CV_off32_t mdisp; // displacement to data (NULL = 0x80000000) }; // representation of a 32 bit pointer to data for a class // with virtual bases struct CV_PDMR32_VBASE { CV_off32_t mdisp; // displacement to data CV_off32_t pdisp; // this pointer displacement CV_off32_t vdisp; // vbase table displacement // NULL = (,,0xffffffff) }; // representation of a 16:16 pointer to near member function for a // class with no virtual functions or bases and a single address point struct CV_PMFR16_NEARNVSA { CV_uoff16_t off; // near address of function (NULL = 0) }; // representation of a 16 bit pointer to member functions of a // class with no virtual bases and multiple address points struct CV_PMFR16_NEARNVMA { CV_uoff16_t off; // offset of function (NULL = 0,x) signed short disp; }; // representation of a 16 bit pointer to member function of a // class with virtual bases struct CV_PMFR16_NEARVBASE { CV_uoff16_t off; // offset of function (NULL = 0,x,x,x) CV_off16_t mdisp; // displacement to data CV_off16_t pdisp; // this pointer displacement CV_off16_t vdisp; // vbase table displacement }; // representation of a 16:16 pointer to far member function for a // class with no virtual bases and a single address point struct CV_PMFR16_FARNVSA { CV_uoff16_t off; // offset of function (NULL = 0:0) unsigned short seg; // segment of function }; // representation of a 16:16 far pointer to member functions of a // class with no virtual bases and multiple address points struct CV_PMFR16_FARNVMA { CV_uoff16_t off; // offset of function (NULL = 0:0,x) unsigned short seg; signed short disp; }; // representation of a 16:16 far pointer to member function of a // class with virtual bases struct CV_PMFR16_FARVBASE { CV_uoff16_t off; // offset of function (NULL = 0:0,x,x,x) unsigned short seg; CV_off16_t mdisp; // displacement to data CV_off16_t pdisp; // this pointer displacement CV_off16_t vdisp; // vbase table displacement }; // representation of a 32 bit pointer to member function for a // class with no virtual bases and a single address point struct CV_PMFR32_NVSA { CV_uoff32_t off; // near address of function (NULL = 0L) }; // representation of a 32 bit pointer to member function for a // class with no virtual bases and multiple address points struct CV_PMFR32_NVMA { CV_uoff32_t off; // near address of function (NULL = 0L,x) CV_off32_t disp; }; // representation of a 32 bit pointer to member function for a // class with virtual bases struct CV_PMFR32_VBASE { CV_uoff32_t off; // near address of function (NULL = 0L,x,x,x) CV_off32_t mdisp; // displacement to data CV_off32_t pdisp; // this pointer displacement CV_off32_t vdisp; // vbase table displacement }; // Easy leaf - used for generic casting to reference leaf field // of a subfield of a complex list typedef struct lfEasy { unsigned short leaf; // LF_... } lfEasy; /** The following type records are basically variant records of the * above structure. The "unsigned short leaf" of the above structure and * the "unsigned short leaf" of the following type definitions are the same * symbol. When the OMF record is locked via the MHOMFLock API * call, the address of the "unsigned short leaf" is returned */ /** Notes on alignment * Alignment of the fields in most of the type records is done on the * basis of the TYPTYPE record base. That is why in most of the lf* * records that the CV_typ_t (32-bit types) is located on what appears to * be a offset mod 4 == 2 boundary. The exception to this rule are those * records that are in a list (lfFieldList, lfMethodList), which are * aligned to their own bases since they don't have the length field */ /**** Change log for 16-bit to 32-bit type and symbol records Record type Change (f == field arrangement, p = padding added) ---------------------------------------------------------------------- lfModifier f lfPointer fp lfClass f lfStructure f lfUnion f lfEnum f lfVFTPath p lfPreComp p lfOEM p lfArgList p lfDerived p mlMethod p (method list member) lfBitField f lfDimCon f lfDimVar p lfIndex p (field list member) lfBClass f (field list member) lfVBClass f (field list member) lfFriendCls p (field list member) lfFriendFcn p (field list member) lfMember f (field list member) lfSTMember f (field list member) lfVFuncTab p (field list member) lfVFuncOff p (field list member) lfNestType p (field list member) DATASYM32 f PROCSYM32 f VPATHSYM32 f REGREL32 f THREADSYM32 f PROCSYMMIPS f */ // Type record for LF_MODIFIER typedef struct lfModifier_16t { unsigned short leaf; // LF_MODIFIER_16t CV_modifier_t attr; // modifier attribute modifier_t CV_typ16_t type; // modified type } lfModifier_16t; typedef struct lfModifier { unsigned short leaf; // LF_MODIFIER CV_typ_t type; // modified type CV_modifier_t attr; // modifier attribute modifier_t } lfModifier; // type record for LF_POINTER #ifndef __cplusplus typedef struct lfPointer_16t { #endif struct lfPointerBody_16t { unsigned short leaf; // LF_POINTER_16t struct lfPointerAttr_16t { unsigned char ptrtype :5; // ordinal specifying pointer type (CV_ptrtype_e) unsigned char ptrmode :3; // ordinal specifying pointer mode (CV_ptrmode_e) unsigned char isflat32 :1; // true if 0:32 pointer unsigned char isvolatile :1; // TRUE if volatile pointer unsigned char isconst :1; // TRUE if const pointer unsigned char isunaligned :1; // TRUE if unaligned pointer unsigned char unused :4; } attr; CV_typ16_t utype; // type index of the underlying type #if (defined(__cplusplus) || defined(_MSC_VER)) // for C++ and MS compilers that support unnamed unions }; #else } u; #endif #ifdef __cplusplus typedef struct lfPointer_16t : public lfPointerBody_16t { #endif union { struct { CV_typ16_t pmclass; // index of containing class for pointer to member unsigned short pmenum; // enumeration specifying pm format (CV_pmtype_e) } pm; unsigned short bseg; // base segment if PTR_BASE_SEG unsigned char Sym[1]; // copy of base symbol record (including length) struct { CV_typ16_t index; // type index if CV_PTR_BASE_TYPE unsigned char name[1]; // name of base type } btype; } pbase; } lfPointer_16t; #ifndef __cplusplus typedef struct lfPointer { #endif struct lfPointerBody { unsigned short leaf; // LF_POINTER CV_typ_t utype; // type index of the underlying type struct lfPointerAttr { unsigned long ptrtype :5; // ordinal specifying pointer type (CV_ptrtype_e) unsigned long ptrmode :3; // ordinal specifying pointer mode (CV_ptrmode_e) unsigned long isflat32 :1; // true if 0:32 pointer unsigned long isvolatile :1; // TRUE if volatile pointer unsigned long isconst :1; // TRUE if const pointer unsigned long isunaligned :1; // TRUE if unaligned pointer unsigned long isrestrict :1; // TRUE if restricted pointer (allow agressive opts) unsigned long size :6; // size of pointer (in bytes) unsigned long ismocom :1; // TRUE if it is a MoCOM pointer (^ or %) unsigned long islref :1; // TRUE if it is this pointer of member function with & ref-qualifier unsigned long isrref :1; // TRUE if it is this pointer of member function with && ref-qualifier unsigned long unused :10;// pad out to 32-bits for following cv_typ_t's } attr; #if (defined(__cplusplus) || defined(_MSC_VER)) // for C++ and MS compilers that support unnamed unions }; #else } u; #endif #ifdef __cplusplus typedef struct lfPointer : public lfPointerBody { #endif union { struct { CV_typ_t pmclass; // index of containing class for pointer to member unsigned short pmenum; // enumeration specifying pm format (CV_pmtype_e) } pm; unsigned short bseg; // base segment if PTR_BASE_SEG unsigned char Sym[1]; // copy of base symbol record (including length) struct { CV_typ_t index; // type index if CV_PTR_BASE_TYPE unsigned char name[1]; // name of base type } btype; } pbase; } lfPointer; // type record for LF_ARRAY typedef struct lfArray_16t { unsigned short leaf; // LF_ARRAY_16t CV_typ16_t elemtype; // type index of element type CV_typ16_t idxtype; // type index of indexing type unsigned char data[CV_ZEROLEN]; // variable length data specifying // size in bytes and name } lfArray_16t; typedef struct lfArray { unsigned short leaf; // LF_ARRAY CV_typ_t elemtype; // type index of element type CV_typ_t idxtype; // type index of indexing type unsigned char data[CV_ZEROLEN]; // variable length data specifying // size in bytes and name } lfArray; typedef struct lfStridedArray { unsigned short leaf; // LF_STRIDED_ARRAY CV_typ_t elemtype; // type index of element type CV_typ_t idxtype; // type index of indexing type unsigned long stride; unsigned char data[CV_ZEROLEN]; // variable length data specifying // size in bytes and name } lfStridedArray; // type record for LF_VECTOR typedef struct lfVector { unsigned short leaf; // LF_VECTOR CV_typ_t elemtype; // type index of element type unsigned long count; // number of elements in the vector unsigned char data[CV_ZEROLEN]; // variable length data specifying // size in bytes and name } lfVector; // type record for LF_MATRIX typedef struct lfMatrix { unsigned short leaf; // LF_MATRIX CV_typ_t elemtype; // type index of element type unsigned long rows; // number of rows unsigned long cols; // number of columns unsigned long majorStride; CV_matrixattr_t matattr; // attributes unsigned char data[CV_ZEROLEN]; // variable length data specifying // size in bytes and name } lfMatrix; // type record for LF_CLASS, LF_STRUCTURE typedef struct lfClass_16t { unsigned short leaf; // LF_CLASS_16t, LF_STRUCT_16t unsigned short count; // count of number of elements in class CV_typ16_t field; // type index of LF_FIELD descriptor list CV_prop_t property; // property attribute field (prop_t) CV_typ16_t derived; // type index of derived from list if not zero CV_typ16_t vshape; // type index of vshape table for this class unsigned char data[CV_ZEROLEN]; // data describing length of structure in // bytes and name } lfClass_16t; typedef lfClass_16t lfStructure_16t; typedef struct lfClass { unsigned short leaf; // LF_CLASS, LF_STRUCT, LF_INTERFACE unsigned short count; // count of number of elements in class CV_prop_t property; // property attribute field (prop_t) CV_typ_t field; // type index of LF_FIELD descriptor list CV_typ_t derived; // type index of derived from list if not zero CV_typ_t vshape; // type index of vshape table for this class unsigned char data[CV_ZEROLEN]; // data describing length of structure in // bytes and name } lfClass; typedef lfClass lfStructure; typedef lfClass lfInterface; // type record for LF_UNION typedef struct lfUnion_16t { unsigned short leaf; // LF_UNION_16t unsigned short count; // count of number of elements in class CV_typ16_t field; // type index of LF_FIELD descriptor list CV_prop_t property; // property attribute field unsigned char data[CV_ZEROLEN]; // variable length data describing length of // structure and name } lfUnion_16t; typedef struct lfUnion { unsigned short leaf; // LF_UNION unsigned short count; // count of number of elements in class CV_prop_t property; // property attribute field CV_typ_t field; // type index of LF_FIELD descriptor list unsigned char data[CV_ZEROLEN]; // variable length data describing length of // structure and name } lfUnion; // type record for LF_ALIAS typedef struct lfAlias { unsigned short leaf; // LF_ALIAS CV_typ_t utype; // underlying type unsigned char Name[1]; // alias name } lfAlias; // Item Id is a stricter typeindex which may referenced from symbol stream. // The code item always had a name. typedef CV_typ_t CV_ItemId; typedef struct lfFuncId { unsigned short leaf; // LF_FUNC_ID CV_ItemId scopeId; // parent scope of the ID, 0 if global CV_typ_t type; // function type unsigned char name[CV_ZEROLEN]; } lfFuncId; typedef struct lfMFuncId { unsigned short leaf; // LF_MFUNC_ID CV_typ_t parentType; // type index of parent CV_typ_t type; // function type unsigned char name[CV_ZEROLEN]; } lfMFuncId; typedef struct lfStringId { unsigned short leaf; // LF_STRING_ID CV_ItemId id; // ID to list of sub string IDs unsigned char name[CV_ZEROLEN]; } lfStringId; typedef struct lfUdtSrcLine { unsigned short leaf; // LF_UDT_SRC_LINE CV_typ_t type; // UDT's type index CV_ItemId src; // index to LF_STRING_ID record where source file name is saved unsigned long line; // line number } lfUdtSrcLine; typedef struct lfUdtModSrcLine { unsigned short leaf; // LF_UDT_MOD_SRC_LINE CV_typ_t type; // UDT's type index CV_ItemId src; // index into string table where source file name is saved unsigned long line; // line number unsigned short imod; // module that contributes this UDT definition } lfUdtModSrcLine; typedef enum CV_BuildInfo_e { CV_BuildInfo_CurrentDirectory = 0, CV_BuildInfo_BuildTool = 1, // Cl.exe CV_BuildInfo_SourceFile = 2, // foo.cpp CV_BuildInfo_ProgramDatabaseFile = 3, // foo.pdb CV_BuildInfo_CommandArguments = 4, // -I etc CV_BUILDINFO_KNOWN } CV_BuildInfo_e; // type record for build information typedef struct lfBuildInfo { unsigned short leaf; // LF_BUILDINFO unsigned short count; // number of arguments CV_ItemId arg[CV_BUILDINFO_KNOWN]; // arguments as CodeItemId } lfBuildInfo; // type record for LF_MANAGED typedef struct lfManaged { unsigned short leaf; // LF_MANAGED unsigned char Name[1]; // utf8, zero terminated managed type name } lfManaged; // type record for LF_ENUM typedef struct lfEnum_16t { unsigned short leaf; // LF_ENUM_16t unsigned short count; // count of number of elements in class CV_typ16_t utype; // underlying type of the enum CV_typ16_t field; // type index of LF_FIELD descriptor list CV_prop_t property; // property attribute field unsigned char Name[1]; // length prefixed name of enum } lfEnum_16t; typedef struct lfEnum { unsigned short leaf; // LF_ENUM unsigned short count; // count of number of elements in class CV_prop_t property; // property attribute field CV_typ_t utype; // underlying type of the enum CV_typ_t field; // type index of LF_FIELD descriptor list unsigned char Name[1]; // length prefixed name of enum } lfEnum; // Type record for LF_PROCEDURE typedef struct lfProc_16t { unsigned short leaf; // LF_PROCEDURE_16t CV_typ16_t rvtype; // type index of return value unsigned char calltype; // calling convention (CV_call_t) CV_funcattr_t funcattr; // attributes unsigned short parmcount; // number of parameters CV_typ16_t arglist; // type index of argument list } lfProc_16t; typedef struct lfProc { unsigned short leaf; // LF_PROCEDURE CV_typ_t rvtype; // type index of return value unsigned char calltype; // calling convention (CV_call_t) CV_funcattr_t funcattr; // attributes unsigned short parmcount; // number of parameters CV_typ_t arglist; // type index of argument list } lfProc; // Type record for member function typedef struct lfMFunc_16t { unsigned short leaf; // LF_MFUNCTION_16t CV_typ16_t rvtype; // type index of return value CV_typ16_t classtype; // type index of containing class CV_typ16_t thistype; // type index of this pointer (model specific) unsigned char calltype; // calling convention (call_t) CV_funcattr_t funcattr; // attributes unsigned short parmcount; // number of parameters CV_typ16_t arglist; // type index of argument list long thisadjust; // this adjuster (long because pad required anyway) } lfMFunc_16t; typedef struct lfMFunc { unsigned short leaf; // LF_MFUNCTION CV_typ_t rvtype; // type index of return value CV_typ_t classtype; // type index of containing class CV_typ_t thistype; // type index of this pointer (model specific) unsigned char calltype; // calling convention (call_t) CV_funcattr_t funcattr; // attributes unsigned short parmcount; // number of parameters CV_typ_t arglist; // type index of argument list long thisadjust; // this adjuster (long because pad required anyway) } lfMFunc; // type record for virtual function table shape typedef struct lfVTShape { unsigned short leaf; // LF_VTSHAPE unsigned short count; // number of entries in vfunctable unsigned char desc[CV_ZEROLEN]; // 4 bit (CV_VTS_desc) descriptors } lfVTShape; // type record for a virtual function table typedef struct lfVftable { unsigned short leaf; // LF_VFTABLE CV_typ_t type; // class/structure that owns the vftable CV_typ_t baseVftable; // vftable from which this vftable is derived unsigned long offsetInObjectLayout; // offset of the vfptr to this table, relative to the start of the object layout. unsigned long len; // length of the Names array below in bytes. unsigned char Names[1]; // array of names. // The first is the name of the vtable. // The others are the names of the methods. // TS-TODO: replace a name with a NamedCodeItem once Weiping is done, to // avoid duplication of method names. } lfVftable; // type record for cobol0 typedef struct lfCobol0_16t { unsigned short leaf; // LF_COBOL0_16t CV_typ16_t type; // parent type record index unsigned char data[CV_ZEROLEN]; } lfCobol0_16t; typedef struct lfCobol0 { unsigned short leaf; // LF_COBOL0 CV_typ_t type; // parent type record index unsigned char data[CV_ZEROLEN]; } lfCobol0; // type record for cobol1 typedef struct lfCobol1 { unsigned short leaf; // LF_COBOL1 unsigned char data[CV_ZEROLEN]; } lfCobol1; // type record for basic array typedef struct lfBArray_16t { unsigned short leaf; // LF_BARRAY_16t CV_typ16_t utype; // type index of underlying type } lfBArray_16t; typedef struct lfBArray { unsigned short leaf; // LF_BARRAY CV_typ_t utype; // type index of underlying type } lfBArray; // type record for assembler labels typedef struct lfLabel { unsigned short leaf; // LF_LABEL unsigned short mode; // addressing mode of label } lfLabel; // type record for dimensioned arrays typedef struct lfDimArray_16t { unsigned short leaf; // LF_DIMARRAY_16t CV_typ16_t utype; // underlying type of the array CV_typ16_t diminfo; // dimension information unsigned char name[1]; // length prefixed name } lfDimArray_16t; typedef struct lfDimArray { unsigned short leaf; // LF_DIMARRAY CV_typ_t utype; // underlying type of the array CV_typ_t diminfo; // dimension information unsigned char name[1]; // length prefixed name } lfDimArray; // type record describing path to virtual function table typedef struct lfVFTPath_16t { unsigned short leaf; // LF_VFTPATH_16t unsigned short count; // count of number of bases in path CV_typ16_t base[1]; // bases from root to leaf } lfVFTPath_16t; typedef struct lfVFTPath { unsigned short leaf; // LF_VFTPATH unsigned long count; // count of number of bases in path CV_typ_t base[1]; // bases from root to leaf } lfVFTPath; // type record describing inclusion of precompiled types typedef struct lfPreComp_16t { unsigned short leaf; // LF_PRECOMP_16t unsigned short start; // starting type index included unsigned short count; // number of types in inclusion unsigned long signature; // signature unsigned char name[CV_ZEROLEN]; // length prefixed name of included type file } lfPreComp_16t; typedef struct lfPreComp { unsigned short leaf; // LF_PRECOMP unsigned long start; // starting type index included unsigned long count; // number of types in inclusion unsigned long signature; // signature unsigned char name[CV_ZEROLEN]; // length prefixed name of included type file } lfPreComp; // type record describing end of precompiled types that can be // included by another file typedef struct lfEndPreComp { unsigned short leaf; // LF_ENDPRECOMP unsigned long signature; // signature } lfEndPreComp; // type record for OEM definable type strings typedef struct lfOEM_16t { unsigned short leaf; // LF_OEM_16t unsigned short cvOEM; // MS assigned OEM identified unsigned short recOEM; // OEM assigned type identifier unsigned short count; // count of type indices to follow CV_typ16_t index[CV_ZEROLEN]; // array of type indices followed // by OEM defined data } lfOEM_16t; typedef struct lfOEM { unsigned short leaf; // LF_OEM unsigned short cvOEM; // MS assigned OEM identified unsigned short recOEM; // OEM assigned type identifier unsigned long count; // count of type indices to follow CV_typ_t index[CV_ZEROLEN]; // array of type indices followed // by OEM defined data } lfOEM; #define OEM_MS_FORTRAN90 0xF090 #define OEM_ODI 0x0010 #define OEM_THOMSON_SOFTWARE 0x5453 #define OEM_ODI_REC_BASELIST 0x0000 typedef struct lfOEM2 { unsigned short leaf; // LF_OEM2 unsigned char idOem[16]; // an oem ID (GUID) unsigned long count; // count of type indices to follow CV_typ_t index[CV_ZEROLEN]; // array of type indices followed // by OEM defined data } lfOEM2; // type record describing using of a type server typedef struct lfTypeServer { unsigned short leaf; // LF_TYPESERVER unsigned long signature; // signature unsigned long age; // age of database used by this module unsigned char name[CV_ZEROLEN]; // length prefixed name of PDB } lfTypeServer; // type record describing using of a type server with v7 (GUID) signatures typedef struct lfTypeServer2 { unsigned short leaf; // LF_TYPESERVER2 SIG70 sig70; // guid signature unsigned long age; // age of database used by this module unsigned char name[CV_ZEROLEN]; // length prefixed name of PDB } lfTypeServer2; // description of type records that can be referenced from // type records referenced by symbols // type record for skip record typedef struct lfSkip_16t { unsigned short leaf; // LF_SKIP_16t CV_typ16_t type; // next valid index unsigned char data[CV_ZEROLEN]; // pad data } lfSkip_16t; typedef struct lfSkip { unsigned short leaf; // LF_SKIP CV_typ_t type; // next valid index unsigned char data[CV_ZEROLEN]; // pad data } lfSkip; // argument list leaf typedef struct lfArgList_16t { unsigned short leaf; // LF_ARGLIST_16t unsigned short count; // number of arguments CV_typ16_t arg[CV_ZEROLEN]; // number of arguments } lfArgList_16t; typedef struct lfArgList { unsigned short leaf; // LF_ARGLIST, LF_SUBSTR_LIST unsigned long count; // number of arguments CV_typ_t arg[CV_ZEROLEN]; // number of arguments } lfArgList; // derived class list leaf typedef struct lfDerived_16t { unsigned short leaf; // LF_DERIVED_16t unsigned short count; // number of arguments CV_typ16_t drvdcls[CV_ZEROLEN]; // type indices of derived classes } lfDerived_16t; typedef struct lfDerived { unsigned short leaf; // LF_DERIVED unsigned long count; // number of arguments CV_typ_t drvdcls[CV_ZEROLEN]; // type indices of derived classes } lfDerived; // leaf for default arguments typedef struct lfDefArg_16t { unsigned short leaf; // LF_DEFARG_16t CV_typ16_t type; // type of resulting expression unsigned char expr[CV_ZEROLEN]; // length prefixed expression string } lfDefArg_16t; typedef struct lfDefArg { unsigned short leaf; // LF_DEFARG CV_typ_t type; // type of resulting expression unsigned char expr[CV_ZEROLEN]; // length prefixed expression string } lfDefArg; // list leaf // This list should no longer be used because the utilities cannot // verify the contents of the list without knowing what type of list // it is. New specific leaf indices should be used instead. typedef struct lfList { unsigned short leaf; // LF_LIST char data[CV_ZEROLEN]; // data format specified by indexing type } lfList; // field list leaf // This is the header leaf for a complex list of class and structure // subfields. typedef struct lfFieldList_16t { unsigned short leaf; // LF_FIELDLIST_16t char data[CV_ZEROLEN]; // field list sub lists } lfFieldList_16t; typedef struct lfFieldList { unsigned short leaf; // LF_FIELDLIST char data[CV_ZEROLEN]; // field list sub lists } lfFieldList; // type record for non-static methods and friends in overloaded method list typedef struct mlMethod_16t { CV_fldattr_t attr; // method attribute CV_typ16_t index; // index to type record for procedure unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if intro virtual } mlMethod_16t; typedef struct mlMethod { CV_fldattr_t attr; // method attribute _2BYTEPAD pad0; // internal padding, must be 0 CV_typ_t index; // index to type record for procedure unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if intro virtual } mlMethod; typedef struct lfMethodList_16t { unsigned short leaf; unsigned char mList[CV_ZEROLEN]; // really a mlMethod_16t type } lfMethodList_16t; typedef struct lfMethodList { unsigned short leaf; unsigned char mList[CV_ZEROLEN]; // really a mlMethod type } lfMethodList; // type record for LF_BITFIELD typedef struct lfBitfield_16t { unsigned short leaf; // LF_BITFIELD_16t unsigned char length; unsigned char position; CV_typ16_t type; // type of bitfield } lfBitfield_16t; typedef struct lfBitfield { unsigned short leaf; // LF_BITFIELD CV_typ_t type; // type of bitfield unsigned char length; unsigned char position; } lfBitfield; // type record for dimensioned array with constant bounds typedef struct lfDimCon_16t { unsigned short leaf; // LF_DIMCONU_16t or LF_DIMCONLU_16t unsigned short rank; // number of dimensions CV_typ16_t typ; // type of index unsigned char dim[CV_ZEROLEN]; // array of dimension information with // either upper bounds or lower/upper bound } lfDimCon_16t; typedef struct lfDimCon { unsigned short leaf; // LF_DIMCONU or LF_DIMCONLU CV_typ_t typ; // type of index unsigned short rank; // number of dimensions unsigned char dim[CV_ZEROLEN]; // array of dimension information with // either upper bounds or lower/upper bound } lfDimCon; // type record for dimensioned array with variable bounds typedef struct lfDimVar_16t { unsigned short leaf; // LF_DIMVARU_16t or LF_DIMVARLU_16t unsigned short rank; // number of dimensions CV_typ16_t typ; // type of index CV_typ16_t dim[CV_ZEROLEN]; // array of type indices for either // variable upper bound or variable // lower/upper bound. The referenced // types must be LF_REFSYM or T_VOID } lfDimVar_16t; typedef struct lfDimVar { unsigned short leaf; // LF_DIMVARU or LF_DIMVARLU unsigned long rank; // number of dimensions CV_typ_t typ; // type of index CV_typ_t dim[CV_ZEROLEN]; // array of type indices for either // variable upper bound or variable // lower/upper bound. The count of type // indices is rank or rank*2 depending on // whether it is LFDIMVARU or LF_DIMVARLU. // The referenced types must be // LF_REFSYM or T_VOID } lfDimVar; // type record for referenced symbol typedef struct lfRefSym { unsigned short leaf; // LF_REFSYM unsigned char Sym[1]; // copy of referenced symbol record // (including length) } lfRefSym; // type record for generic HLSL type typedef struct lfHLSL { unsigned short leaf; // LF_HLSL CV_typ_t subtype; // sub-type index, if any unsigned short kind; // kind of built-in type from CV_builtin_e unsigned short numprops : 4; // number of numeric properties unsigned short unused : 12; // padding, must be 0 unsigned char data[CV_ZEROLEN]; // variable-length array of numeric properties // followed by byte size } lfHLSL; // type record for a generalized built-in type modifier typedef struct lfModifierEx { unsigned short leaf; // LF_MODIFIER_EX CV_typ_t type; // type being modified unsigned short count; // count of modifier values unsigned short mods[CV_ZEROLEN]; // modifiers from CV_modifier_e } lfModifierEx; /** the following are numeric leaves. They are used to indicate the * size of the following variable length data. When the numeric * data is a single byte less than 0x8000, then the data is output * directly. If the data is more the 0x8000 or is a negative value, * then the data is preceded by the proper index. */ // signed character leaf typedef struct lfChar { unsigned short leaf; // LF_CHAR signed char val; // signed 8-bit value } lfChar; // signed short leaf typedef struct lfShort { unsigned short leaf; // LF_SHORT short val; // signed 16-bit value } lfShort; // unsigned short leaf typedef struct lfUShort { unsigned short leaf; // LF_unsigned short unsigned short val; // unsigned 16-bit value } lfUShort; // signed long leaf typedef struct lfLong { unsigned short leaf; // LF_LONG long val; // signed 32-bit value } lfLong; // unsigned long leaf typedef struct lfULong { unsigned short leaf; // LF_ULONG unsigned long val; // unsigned 32-bit value } lfULong; // signed quad leaf typedef struct lfQuad { unsigned short leaf; // LF_QUAD unsigned char val[8]; // signed 64-bit value } lfQuad; // unsigned quad leaf typedef struct lfUQuad { unsigned short leaf; // LF_UQUAD unsigned char val[8]; // unsigned 64-bit value } lfUQuad; // signed int128 leaf typedef struct lfOct { unsigned short leaf; // LF_OCT unsigned char val[16]; // signed 128-bit value } lfOct; // unsigned int128 leaf typedef struct lfUOct { unsigned short leaf; // LF_UOCT unsigned char val[16]; // unsigned 128-bit value } lfUOct; // real 16-bit leaf typedef struct lfReal16 { unsigned short leaf; // LF_REAL16 unsigned short val; // 16-bit real value } lfReal16; // real 32-bit leaf typedef struct lfReal32 { unsigned short leaf; // LF_REAL32 float val; // 32-bit real value } lfReal32; // real 48-bit leaf typedef struct lfReal48 { unsigned short leaf; // LF_REAL48 unsigned char val[6]; // 48-bit real value } lfReal48; // real 64-bit leaf typedef struct lfReal64 { unsigned short leaf; // LF_REAL64 double val; // 64-bit real value } lfReal64; // real 80-bit leaf typedef struct lfReal80 { unsigned short leaf; // LF_REAL80 FLOAT10 val; // real 80-bit value } lfReal80; // real 128-bit leaf typedef struct lfReal128 { unsigned short leaf; // LF_REAL128 char val[16]; // real 128-bit value } lfReal128; // complex 32-bit leaf typedef struct lfCmplx32 { unsigned short leaf; // LF_COMPLEX32 float val_real; // real component float val_imag; // imaginary component } lfCmplx32; // complex 64-bit leaf typedef struct lfCmplx64 { unsigned short leaf; // LF_COMPLEX64 double val_real; // real component double val_imag; // imaginary component } flCmplx64; // complex 80-bit leaf typedef struct lfCmplx80 { unsigned short leaf; // LF_COMPLEX80 FLOAT10 val_real; // real component FLOAT10 val_imag; // imaginary component } lfCmplx80; // complex 128-bit leaf typedef struct lfCmplx128 { unsigned short leaf; // LF_COMPLEX128 char val_real[16]; // real component char val_imag[16]; // imaginary component } lfCmplx128; // variable length numeric field typedef struct lfVarString { unsigned short leaf; // LF_VARSTRING unsigned short len; // length of value in bytes unsigned char value[CV_ZEROLEN]; // value } lfVarString; //*********************************************************************** // index leaf - contains type index of another leaf // a major use of this leaf is to allow the compilers to emit a // long complex list (LF_FIELD) in smaller pieces. typedef struct lfIndex_16t { unsigned short leaf; // LF_INDEX_16t CV_typ16_t index; // type index of referenced leaf } lfIndex_16t; typedef struct lfIndex { unsigned short leaf; // LF_INDEX _2BYTEPAD pad0; // internal padding, must be 0 CV_typ_t index; // type index of referenced leaf } lfIndex; // subfield record for base class field typedef struct lfBClass_16t { unsigned short leaf; // LF_BCLASS_16t CV_typ16_t index; // type index of base class CV_fldattr_t attr; // attribute unsigned char offset[CV_ZEROLEN]; // variable length offset of base within class } lfBClass_16t; typedef struct lfBClass { unsigned short leaf; // LF_BCLASS, LF_BINTERFACE CV_fldattr_t attr; // attribute CV_typ_t index; // type index of base class unsigned char offset[CV_ZEROLEN]; // variable length offset of base within class } lfBClass; typedef lfBClass lfBInterface; // subfield record for direct and indirect virtual base class field typedef struct lfVBClass_16t { unsigned short leaf; // LF_VBCLASS_16t | LV_IVBCLASS_16t CV_typ16_t index; // type index of direct virtual base class CV_typ16_t vbptr; // type index of virtual base pointer CV_fldattr_t attr; // attribute unsigned char vbpoff[CV_ZEROLEN]; // virtual base pointer offset from address point // followed by virtual base offset from vbtable } lfVBClass_16t; typedef struct lfVBClass { unsigned short leaf; // LF_VBCLASS | LV_IVBCLASS CV_fldattr_t attr; // attribute CV_typ_t index; // type index of direct virtual base class CV_typ_t vbptr; // type index of virtual base pointer unsigned char vbpoff[CV_ZEROLEN]; // virtual base pointer offset from address point // followed by virtual base offset from vbtable } lfVBClass; // subfield record for friend class typedef struct lfFriendCls_16t { unsigned short leaf; // LF_FRIENDCLS_16t CV_typ16_t index; // index to type record of friend class } lfFriendCls_16t; typedef struct lfFriendCls { unsigned short leaf; // LF_FRIENDCLS _2BYTEPAD pad0; // internal padding, must be 0 CV_typ_t index; // index to type record of friend class } lfFriendCls; // subfield record for friend function typedef struct lfFriendFcn_16t { unsigned short leaf; // LF_FRIENDFCN_16t CV_typ16_t index; // index to type record of friend function unsigned char Name[1]; // name of friend function } lfFriendFcn_16t; typedef struct lfFriendFcn { unsigned short leaf; // LF_FRIENDFCN _2BYTEPAD pad0; // internal padding, must be 0 CV_typ_t index; // index to type record of friend function unsigned char Name[1]; // name of friend function } lfFriendFcn; // subfield record for non-static data members typedef struct lfMember_16t { unsigned short leaf; // LF_MEMBER_16t CV_typ16_t index; // index of type record for field CV_fldattr_t attr; // attribute mask unsigned char offset[CV_ZEROLEN]; // variable length offset of field followed // by length prefixed name of field } lfMember_16t; typedef struct lfMember { unsigned short leaf; // LF_MEMBER CV_fldattr_t attr; // attribute mask CV_typ_t index; // index of type record for field unsigned char offset[CV_ZEROLEN]; // variable length offset of field followed // by length prefixed name of field } lfMember; // type record for static data members typedef struct lfSTMember_16t { unsigned short leaf; // LF_STMEMBER_16t CV_typ16_t index; // index of type record for field CV_fldattr_t attr; // attribute mask unsigned char Name[1]; // length prefixed name of field } lfSTMember_16t; typedef struct lfSTMember { unsigned short leaf; // LF_STMEMBER CV_fldattr_t attr; // attribute mask CV_typ_t index; // index of type record for field unsigned char Name[1]; // length prefixed name of field } lfSTMember; // subfield record for virtual function table pointer typedef struct lfVFuncTab_16t { unsigned short leaf; // LF_VFUNCTAB_16t CV_typ16_t type; // type index of pointer } lfVFuncTab_16t; typedef struct lfVFuncTab { unsigned short leaf; // LF_VFUNCTAB _2BYTEPAD pad0; // internal padding, must be 0 CV_typ_t type; // type index of pointer } lfVFuncTab; // subfield record for virtual function table pointer with offset typedef struct lfVFuncOff_16t { unsigned short leaf; // LF_VFUNCOFF_16t CV_typ16_t type; // type index of pointer CV_off32_t offset; // offset of virtual function table pointer } lfVFuncOff_16t; typedef struct lfVFuncOff { unsigned short leaf; // LF_VFUNCOFF _2BYTEPAD pad0; // internal padding, must be 0. CV_typ_t type; // type index of pointer CV_off32_t offset; // offset of virtual function table pointer } lfVFuncOff; // subfield record for overloaded method list typedef struct lfMethod_16t { unsigned short leaf; // LF_METHOD_16t unsigned short count; // number of occurrences of function CV_typ16_t mList; // index to LF_METHODLIST record unsigned char Name[1]; // length prefixed name of method } lfMethod_16t; typedef struct lfMethod { unsigned short leaf; // LF_METHOD unsigned short count; // number of occurrences of function CV_typ_t mList; // index to LF_METHODLIST record unsigned char Name[1]; // length prefixed name of method } lfMethod; // subfield record for nonoverloaded method typedef struct lfOneMethod_16t { unsigned short leaf; // LF_ONEMETHOD_16t CV_fldattr_t attr; // method attribute CV_typ16_t index; // index to type record for procedure unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if // intro virtual followed by // length prefixed name of method } lfOneMethod_16t; typedef struct lfOneMethod { unsigned short leaf; // LF_ONEMETHOD CV_fldattr_t attr; // method attribute CV_typ_t index; // index to type record for procedure unsigned long vbaseoff[CV_ZEROLEN]; // offset in vfunctable if // intro virtual followed by // length prefixed name of method } lfOneMethod; // subfield record for enumerate typedef struct lfEnumerate { unsigned short leaf; // LF_ENUMERATE CV_fldattr_t attr; // access unsigned char value[CV_ZEROLEN]; // variable length value field followed // by length prefixed name } lfEnumerate; // type record for nested (scoped) type definition typedef struct lfNestType_16t { unsigned short leaf; // LF_NESTTYPE_16t CV_typ16_t index; // index of nested type definition unsigned char Name[1]; // length prefixed type name } lfNestType_16t; typedef struct lfNestType { unsigned short leaf; // LF_NESTTYPE _2BYTEPAD pad0; // internal padding, must be 0 CV_typ_t index; // index of nested type definition unsigned char Name[1]; // length prefixed type name } lfNestType; // type record for nested (scoped) type definition, with attributes // new records for vC v5.0, no need to have 16-bit ti versions. typedef struct lfNestTypeEx { unsigned short leaf; // LF_NESTTYPEEX CV_fldattr_t attr; // member access CV_typ_t index; // index of nested type definition unsigned char Name[1]; // length prefixed type name } lfNestTypeEx; // type record for modifications to members typedef struct lfMemberModify { unsigned short leaf; // LF_MEMBERMODIFY CV_fldattr_t attr; // the new attributes CV_typ_t index; // index of base class type definition unsigned char Name[1]; // length prefixed member name } lfMemberModify; // type record for pad leaf typedef struct lfPad { unsigned char leaf; } SYM_PAD; // Symbol definitions typedef enum SYM_ENUM_e { S_COMPILE = 0x0001, // Compile flags symbol S_REGISTER_16t = 0x0002, // Register variable S_CONSTANT_16t = 0x0003, // constant symbol S_UDT_16t = 0x0004, // User defined type S_SSEARCH = 0x0005, // Start Search S_END = 0x0006, // Block, procedure, "with" or thunk end S_SKIP = 0x0007, // Reserve symbol space in $$Symbols table S_CVRESERVE = 0x0008, // Reserved symbol for CV internal use S_OBJNAME_ST = 0x0009, // path to object file name S_ENDARG = 0x000a, // end of argument/return list S_COBOLUDT_16t = 0x000b, // special UDT for cobol that does not symbol pack S_MANYREG_16t = 0x000c, // multiple register variable S_RETURN = 0x000d, // return description symbol S_ENTRYTHIS = 0x000e, // description of this pointer on entry S_BPREL16 = 0x0100, // BP-relative S_LDATA16 = 0x0101, // Module-local symbol S_GDATA16 = 0x0102, // Global data symbol S_PUB16 = 0x0103, // a public symbol S_LPROC16 = 0x0104, // Local procedure start S_GPROC16 = 0x0105, // Global procedure start S_THUNK16 = 0x0106, // Thunk Start S_BLOCK16 = 0x0107, // block start S_WITH16 = 0x0108, // with start S_LABEL16 = 0x0109, // code label S_CEXMODEL16 = 0x010a, // change execution model S_VFTABLE16 = 0x010b, // address of virtual function table S_REGREL16 = 0x010c, // register relative address S_BPREL32_16t = 0x0200, // BP-relative S_LDATA32_16t = 0x0201, // Module-local symbol S_GDATA32_16t = 0x0202, // Global data symbol S_PUB32_16t = 0x0203, // a public symbol (CV internal reserved) S_LPROC32_16t = 0x0204, // Local procedure start S_GPROC32_16t = 0x0205, // Global procedure start S_THUNK32_ST = 0x0206, // Thunk Start S_BLOCK32_ST = 0x0207, // block start S_WITH32_ST = 0x0208, // with start S_LABEL32_ST = 0x0209, // code label S_CEXMODEL32 = 0x020a, // change execution model S_VFTABLE32_16t = 0x020b, // address of virtual function table S_REGREL32_16t = 0x020c, // register relative address S_LTHREAD32_16t = 0x020d, // local thread storage S_GTHREAD32_16t = 0x020e, // global thread storage S_SLINK32 = 0x020f, // static link for MIPS EH implementation S_LPROCMIPS_16t = 0x0300, // Local procedure start S_GPROCMIPS_16t = 0x0301, // Global procedure start // if these ref symbols have names following then the names are in ST format S_PROCREF_ST = 0x0400, // Reference to a procedure S_DATAREF_ST = 0x0401, // Reference to data S_ALIGN = 0x0402, // Used for page alignment of symbols S_LPROCREF_ST = 0x0403, // Local Reference to a procedure S_OEM = 0x0404, // OEM defined symbol // sym records with 32-bit types embedded instead of 16-bit // all have 0x1000 bit set for easy identification // only do the 32-bit target versions since we don't really // care about 16-bit ones anymore. S_TI16_MAX = 0x1000, S_REGISTER_ST = 0x1001, // Register variable S_CONSTANT_ST = 0x1002, // constant symbol S_UDT_ST = 0x1003, // User defined type S_COBOLUDT_ST = 0x1004, // special UDT for cobol that does not symbol pack S_MANYREG_ST = 0x1005, // multiple register variable S_BPREL32_ST = 0x1006, // BP-relative S_LDATA32_ST = 0x1007, // Module-local symbol S_GDATA32_ST = 0x1008, // Global data symbol S_PUB32_ST = 0x1009, // a public symbol (CV internal reserved) S_LPROC32_ST = 0x100a, // Local procedure start S_GPROC32_ST = 0x100b, // Global procedure start S_VFTABLE32 = 0x100c, // address of virtual function table S_REGREL32_ST = 0x100d, // register relative address S_LTHREAD32_ST = 0x100e, // local thread storage S_GTHREAD32_ST = 0x100f, // global thread storage S_LPROCMIPS_ST = 0x1010, // Local procedure start S_GPROCMIPS_ST = 0x1011, // Global procedure start S_FRAMEPROC = 0x1012, // extra frame and proc information S_COMPILE2_ST = 0x1013, // extended compile flags and info // new symbols necessary for 16-bit enumerates of IA64 registers // and IA64 specific symbols S_MANYREG2_ST = 0x1014, // multiple register variable S_LPROCIA64_ST = 0x1015, // Local procedure start (IA64) S_GPROCIA64_ST = 0x1016, // Global procedure start (IA64) // Local symbols for IL S_LOCALSLOT_ST = 0x1017, // local IL sym with field for local slot index S_PARAMSLOT_ST = 0x1018, // local IL sym with field for parameter slot index S_ANNOTATION = 0x1019, // Annotation string literals // symbols to support managed code debugging S_GMANPROC_ST = 0x101a, // Global proc S_LMANPROC_ST = 0x101b, // Local proc S_RESERVED1 = 0x101c, // reserved S_RESERVED2 = 0x101d, // reserved S_RESERVED3 = 0x101e, // reserved S_RESERVED4 = 0x101f, // reserved S_LMANDATA_ST = 0x1020, S_GMANDATA_ST = 0x1021, S_MANFRAMEREL_ST= 0x1022, S_MANREGISTER_ST= 0x1023, S_MANSLOT_ST = 0x1024, S_MANMANYREG_ST = 0x1025, S_MANREGREL_ST = 0x1026, S_MANMANYREG2_ST= 0x1027, S_MANTYPREF = 0x1028, // Index for type referenced by name from metadata S_UNAMESPACE_ST = 0x1029, // Using namespace // Symbols w/ SZ name fields. All name fields contain utf8 encoded strings. S_ST_MAX = 0x1100, // starting point for SZ name symbols S_OBJNAME = 0x1101, // path to object file name S_THUNK32 = 0x1102, // Thunk Start S_BLOCK32 = 0x1103, // block start S_WITH32 = 0x1104, // with start S_LABEL32 = 0x1105, // code label S_REGISTER = 0x1106, // Register variable S_CONSTANT = 0x1107, // constant symbol S_UDT = 0x1108, // User defined type S_COBOLUDT = 0x1109, // special UDT for cobol that does not symbol pack S_MANYREG = 0x110a, // multiple register variable S_BPREL32 = 0x110b, // BP-relative S_LDATA32 = 0x110c, // Module-local symbol S_GDATA32 = 0x110d, // Global data symbol S_PUB32 = 0x110e, // a public symbol (CV internal reserved) S_LPROC32 = 0x110f, // Local procedure start S_GPROC32 = 0x1110, // Global procedure start S_REGREL32 = 0x1111, // register relative address S_LTHREAD32 = 0x1112, // local thread storage S_GTHREAD32 = 0x1113, // global thread storage S_LPROCMIPS = 0x1114, // Local procedure start S_GPROCMIPS = 0x1115, // Global procedure start S_COMPILE2 = 0x1116, // extended compile flags and info S_MANYREG2 = 0x1117, // multiple register variable S_LPROCIA64 = 0x1118, // Local procedure start (IA64) S_GPROCIA64 = 0x1119, // Global procedure start (IA64) S_LOCALSLOT = 0x111a, // local IL sym with field for local slot index S_SLOT = S_LOCALSLOT, // alias for LOCALSLOT S_PARAMSLOT = 0x111b, // local IL sym with field for parameter slot index // symbols to support managed code debugging S_LMANDATA = 0x111c, S_GMANDATA = 0x111d, S_MANFRAMEREL = 0x111e, S_MANREGISTER = 0x111f, S_MANSLOT = 0x1120, S_MANMANYREG = 0x1121, S_MANREGREL = 0x1122, S_MANMANYREG2 = 0x1123, S_UNAMESPACE = 0x1124, // Using namespace // ref symbols with name fields S_PROCREF = 0x1125, // Reference to a procedure S_DATAREF = 0x1126, // Reference to data S_LPROCREF = 0x1127, // Local Reference to a procedure S_ANNOTATIONREF = 0x1128, // Reference to an S_ANNOTATION symbol S_TOKENREF = 0x1129, // Reference to one of the many MANPROCSYM's // continuation of managed symbols S_GMANPROC = 0x112a, // Global proc S_LMANPROC = 0x112b, // Local proc // short, light-weight thunks S_TRAMPOLINE = 0x112c, // trampoline thunks S_MANCONSTANT = 0x112d, // constants with metadata type info // native attributed local/parms S_ATTR_FRAMEREL = 0x112e, // relative to virtual frame ptr S_ATTR_REGISTER = 0x112f, // stored in a register S_ATTR_REGREL = 0x1130, // relative to register (alternate frame ptr) S_ATTR_MANYREG = 0x1131, // stored in >1 register // Separated code (from the compiler) support S_SEPCODE = 0x1132, S_LOCAL_2005 = 0x1133, // defines a local symbol in optimized code S_DEFRANGE_2005 = 0x1134, // defines a single range of addresses in which symbol can be evaluated S_DEFRANGE2_2005 = 0x1135, // defines ranges of addresses in which symbol can be evaluated S_SECTION = 0x1136, // A COFF section in a PE executable S_COFFGROUP = 0x1137, // A COFF group S_EXPORT = 0x1138, // A export S_CALLSITEINFO = 0x1139, // Indirect call site information S_FRAMECOOKIE = 0x113a, // Security cookie information S_DISCARDED = 0x113b, // Discarded by LINK /OPT:REF (experimental, see richards) S_COMPILE3 = 0x113c, // Replacement for S_COMPILE2 S_ENVBLOCK = 0x113d, // Environment block split off from S_COMPILE2 S_LOCAL = 0x113e, // defines a local symbol in optimized code S_DEFRANGE = 0x113f, // defines a single range of addresses in which symbol can be evaluated S_DEFRANGE_SUBFIELD = 0x1140, // ranges for a subfield S_DEFRANGE_REGISTER = 0x1141, // ranges for en-registered symbol S_DEFRANGE_FRAMEPOINTER_REL = 0x1142, // range for stack symbol. S_DEFRANGE_SUBFIELD_REGISTER = 0x1143, // ranges for en-registered field of symbol S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE = 0x1144, // range for stack symbol span valid full scope of function body, gap might apply. S_DEFRANGE_REGISTER_REL = 0x1145, // range for symbol address as register + offset. // S_PROC symbols that reference ID instead of type S_LPROC32_ID = 0x1146, S_GPROC32_ID = 0x1147, S_LPROCMIPS_ID = 0x1148, S_GPROCMIPS_ID = 0x1149, S_LPROCIA64_ID = 0x114a, S_GPROCIA64_ID = 0x114b, S_BUILDINFO = 0x114c, // build information. S_INLINESITE = 0x114d, // inlined function callsite. S_INLINESITE_END = 0x114e, S_PROC_ID_END = 0x114f, S_DEFRANGE_HLSL = 0x1150, S_GDATA_HLSL = 0x1151, S_LDATA_HLSL = 0x1152, S_FILESTATIC = 0x1153, #if defined(CC_DP_CXX) && CC_DP_CXX S_LOCAL_DPC_GROUPSHARED = 0x1154, // DPC groupshared variable S_LPROC32_DPC = 0x1155, // DPC local procedure start S_LPROC32_DPC_ID = 0x1156, S_DEFRANGE_DPC_PTR_TAG = 0x1157, // DPC pointer tag definition range S_DPC_SYM_TAG_MAP = 0x1158, // DPC pointer tag value to symbol record map #endif // CC_DP_CXX S_ARMSWITCHTABLE = 0x1159, S_CALLEES = 0x115a, S_CALLERS = 0x115b, S_POGODATA = 0x115c, S_INLINESITE2 = 0x115d, // extended inline site information S_HEAPALLOCSITE = 0x115e, // heap allocation site S_MOD_TYPEREF = 0x115f, // only generated at link time S_REF_MINIPDB = 0x1160, // only generated at link time for mini PDB S_PDBMAP = 0x1161, // only generated at link time for mini PDB S_GDATA_HLSL32 = 0x1162, S_LDATA_HLSL32 = 0x1163, S_GDATA_HLSL32_EX = 0x1164, S_LDATA_HLSL32_EX = 0x1165, S_RECTYPE_MAX, // one greater than last S_RECTYPE_LAST = S_RECTYPE_MAX - 1, S_RECTYPE_PAD = S_RECTYPE_MAX + 0x100 // Used *only* to verify symbol record types so that current PDB code can potentially read // future PDBs (assuming no format change, etc). } SYM_ENUM_e; // enum describing compile flag ambient data model typedef enum CV_CFL_DATA { CV_CFL_DNEAR = 0x00, CV_CFL_DFAR = 0x01, CV_CFL_DHUGE = 0x02 } CV_CFL_DATA; // enum describing compile flag ambiant code model typedef enum CV_CFL_CODE_e { CV_CFL_CNEAR = 0x00, CV_CFL_CFAR = 0x01, CV_CFL_CHUGE = 0x02 } CV_CFL_CODE_e; // enum describing compile flag target floating point package typedef enum CV_CFL_FPKG_e { CV_CFL_NDP = 0x00, CV_CFL_EMU = 0x01, CV_CFL_ALT = 0x02 } CV_CFL_FPKG_e; // enum describing function return method typedef struct CV_PROCFLAGS { union { unsigned char bAll; unsigned char grfAll; struct { unsigned char CV_PFLAG_NOFPO :1; // frame pointer present unsigned char CV_PFLAG_INT :1; // interrupt return unsigned char CV_PFLAG_FAR :1; // far return unsigned char CV_PFLAG_NEVER :1; // function does not return unsigned char CV_PFLAG_NOTREACHED:1; // label isn't fallen into unsigned char CV_PFLAG_CUST_CALL :1; // custom calling convention unsigned char CV_PFLAG_NOINLINE :1; // function marked as noinline unsigned char CV_PFLAG_OPTDBGINFO:1; // function has debug information for optimized code }; }; } CV_PROCFLAGS; // Extended proc flags // typedef struct CV_EXPROCFLAGS { CV_PROCFLAGS cvpf; union { unsigned char grfAll; struct { unsigned char __reserved_byte :8; // must be zero }; }; } CV_EXPROCFLAGS; // local variable flags typedef struct CV_LVARFLAGS { unsigned short fIsParam :1; // variable is a parameter unsigned short fAddrTaken :1; // address is taken unsigned short fCompGenx :1; // variable is compiler generated unsigned short fIsAggregate :1; // the symbol is splitted in temporaries, // which are treated by compiler as // independent entities unsigned short fIsAggregated :1; // Counterpart of fIsAggregate - tells // that it is a part of a fIsAggregate symbol unsigned short fIsAliased :1; // variable has multiple simultaneous lifetimes unsigned short fIsAlias :1; // represents one of the multiple simultaneous lifetimes unsigned short fIsRetValue :1; // represents a function return value unsigned short fIsOptimizedOut :1; // variable has no lifetimes unsigned short fIsEnregGlob :1; // variable is an enregistered global unsigned short fIsEnregStat :1; // variable is an enregistered static unsigned short unused :5; // must be zero } CV_LVARFLAGS; // extended attributes common to all local variables typedef struct CV_lvar_attr { CV_uoff32_t off; // first code address where var is live unsigned short seg; CV_LVARFLAGS flags; // local var flags } CV_lvar_attr; // This is max length of a lexical linear IP range. // The upper number are reserved for seeded and flow based range #define CV_LEXICAL_RANGE_MAX 0xF000 // represents an address range, used for optimized code debug info typedef struct CV_LVAR_ADDR_RANGE { // defines a range of addresses CV_uoff32_t offStart; unsigned short isectStart; unsigned short cbRange; } CV_LVAR_ADDR_RANGE; // Represents the holes in overall address range, all address is pre-bbt. // it is for compress and reduce the amount of relocations need. typedef struct CV_LVAR_ADDR_GAP { unsigned short gapStartOffset; // relative offset from the beginning of the live range. unsigned short cbRange; // length of this gap. } CV_LVAR_ADDR_GAP; #if defined(CC_DP_CXX) && CC_DP_CXX // Represents a mapping from a DPC pointer tag value to the corresponding symbol record typedef struct CV_DPC_SYM_TAG_MAP_ENTRY { unsigned int tagValue; // address taken symbol's pointer tag value. CV_off32_t symRecordOffset; // offset of the symbol record from the S_LPROC32_DPC record it is nested within } CV_DPC_SYM_TAG_MAP_ENTRY; #endif // CC_DP_CXX // enum describing function data return method typedef enum CV_GENERIC_STYLE_e { CV_GENERIC_VOID = 0x00, // void return type CV_GENERIC_REG = 0x01, // return data is in registers CV_GENERIC_ICAN = 0x02, // indirect caller allocated near CV_GENERIC_ICAF = 0x03, // indirect caller allocated far CV_GENERIC_IRAN = 0x04, // indirect returnee allocated near CV_GENERIC_IRAF = 0x05, // indirect returnee allocated far CV_GENERIC_UNUSED = 0x06 // first unused } CV_GENERIC_STYLE_e; typedef struct CV_GENERIC_FLAG { unsigned short cstyle :1; // true push varargs right to left unsigned short rsclean :1; // true if returnee stack cleanup unsigned short unused :14; // unused } CV_GENERIC_FLAG; // flag bitfields for separated code attributes typedef struct CV_SEPCODEFLAGS { unsigned long fIsLexicalScope : 1; // S_SEPCODE doubles as lexical scope unsigned long fReturnsToParent : 1; // code frag returns to parent unsigned long pad : 30; // must be zero } CV_SEPCODEFLAGS; // Generic layout for symbol records typedef struct SYMTYPE { unsigned short reclen; // Record length unsigned short rectyp; // Record type char data[CV_ZEROLEN]; } SYMTYPE; __INLINE SYMTYPE *NextSym (SYMTYPE * pSym) { return (SYMTYPE *) ((char *)pSym + pSym->reclen + sizeof(unsigned short)); } // non-model specific symbol types typedef struct REGSYM_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_REGISTER_16t CV_typ16_t typind; // Type index unsigned short reg; // register enumerate unsigned char name[1]; // Length-prefixed name } REGSYM_16t; typedef struct REGSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_REGISTER CV_typ_t typind; // Type index or Metadata token unsigned short reg; // register enumerate unsigned char name[1]; // Length-prefixed name } REGSYM; typedef struct ATTRREGSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_MANREGISTER | S_ATTR_REGISTER CV_typ_t typind; // Type index or Metadata token CV_lvar_attr attr; // local var attributes unsigned short reg; // register enumerate unsigned char name[1]; // Length-prefixed name } ATTRREGSYM; typedef struct MANYREGSYM_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_MANYREG_16t CV_typ16_t typind; // Type index unsigned char count; // count of number of registers unsigned char reg[1]; // count register enumerates followed by // length-prefixed name. Registers are // most significant first. } MANYREGSYM_16t; typedef struct MANYREGSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_MANYREG CV_typ_t typind; // Type index or metadata token unsigned char count; // count of number of registers unsigned char reg[1]; // count register enumerates followed by // length-prefixed name. Registers are // most significant first. } MANYREGSYM; typedef struct MANYREGSYM2 { unsigned short reclen; // Record length unsigned short rectyp; // S_MANYREG2 CV_typ_t typind; // Type index or metadata token unsigned short count; // count of number of registers unsigned short reg[1]; // count register enumerates followed by // length-prefixed name. Registers are // most significant first. } MANYREGSYM2; typedef struct ATTRMANYREGSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_MANMANYREG CV_typ_t typind; // Type index or metadata token CV_lvar_attr attr; // local var attributes unsigned char count; // count of number of registers unsigned char reg[1]; // count register enumerates followed by // length-prefixed name. Registers are // most significant first. unsigned char name[CV_ZEROLEN]; // utf-8 encoded zero terminate name } ATTRMANYREGSYM; typedef struct ATTRMANYREGSYM2 { unsigned short reclen; // Record length unsigned short rectyp; // S_MANMANYREG2 | S_ATTR_MANYREG CV_typ_t typind; // Type index or metadata token CV_lvar_attr attr; // local var attributes unsigned short count; // count of number of registers unsigned short reg[1]; // count register enumerates followed by // length-prefixed name. Registers are // most significant first. unsigned char name[CV_ZEROLEN]; // utf-8 encoded zero terminate name } ATTRMANYREGSYM2; typedef struct CONSTSYM_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_CONSTANT_16t CV_typ16_t typind; // Type index (containing enum if enumerate) unsigned short value; // numeric leaf containing value unsigned char name[CV_ZEROLEN]; // Length-prefixed name } CONSTSYM_16t; typedef struct CONSTSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_CONSTANT or S_MANCONSTANT CV_typ_t typind; // Type index (containing enum if enumerate) or metadata token unsigned short value; // numeric leaf containing value unsigned char name[CV_ZEROLEN]; // Length-prefixed name } CONSTSYM; typedef struct UDTSYM_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_UDT_16t | S_COBOLUDT_16t CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } UDTSYM_16t; typedef struct UDTSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_UDT | S_COBOLUDT CV_typ_t typind; // Type index unsigned char name[1]; // Length-prefixed name } UDTSYM; typedef struct MANTYPREF { unsigned short reclen; // Record length unsigned short rectyp; // S_MANTYPREF CV_typ_t typind; // Type index } MANTYPREF; typedef struct SEARCHSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_SSEARCH unsigned long startsym; // offset of the procedure unsigned short seg; // segment of symbol } SEARCHSYM; typedef struct CFLAGSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_COMPILE unsigned char machine; // target processor struct { unsigned char language :8; // language index unsigned char pcode :1; // true if pcode present unsigned char floatprec :2; // floating precision unsigned char floatpkg :2; // float package unsigned char ambdata :3; // ambient data model unsigned char ambcode :3; // ambient code model unsigned char mode32 :1; // true if compiled 32 bit mode unsigned char pad :4; // reserved } flags; unsigned char ver[1]; // Length-prefixed compiler version string } CFLAGSYM; typedef struct COMPILESYM { unsigned short reclen; // Record length unsigned short rectyp; // S_COMPILE2 struct { unsigned long iLanguage : 8; // language index unsigned long fEC : 1; // compiled for E/C unsigned long fNoDbgInfo : 1; // not compiled with debug info unsigned long fLTCG : 1; // compiled with LTCG unsigned long fNoDataAlign : 1; // compiled with -Bzalign unsigned long fManagedPresent : 1; // managed code/data present unsigned long fSecurityChecks : 1; // compiled with /GS unsigned long fHotPatch : 1; // compiled with /hotpatch unsigned long fCVTCIL : 1; // converted with CVTCIL unsigned long fMSILModule : 1; // MSIL netmodule unsigned long pad : 15; // reserved, must be 0 } flags; unsigned short machine; // target processor unsigned short verFEMajor; // front end major version # unsigned short verFEMinor; // front end minor version # unsigned short verFEBuild; // front end build version # unsigned short verMajor; // back end major version # unsigned short verMinor; // back end minor version # unsigned short verBuild; // back end build version # unsigned char verSt[1]; // Length-prefixed compiler version string, followed // by an optional block of zero terminated strings // terminated with a double zero. } COMPILESYM; typedef struct COMPILESYM3 { unsigned short reclen; // Record length unsigned short rectyp; // S_COMPILE3 struct { unsigned long iLanguage : 8; // language index unsigned long fEC : 1; // compiled for E/C unsigned long fNoDbgInfo : 1; // not compiled with debug info unsigned long fLTCG : 1; // compiled with LTCG unsigned long fNoDataAlign : 1; // compiled with -Bzalign unsigned long fManagedPresent : 1; // managed code/data present unsigned long fSecurityChecks : 1; // compiled with /GS unsigned long fHotPatch : 1; // compiled with /hotpatch unsigned long fCVTCIL : 1; // converted with CVTCIL unsigned long fMSILModule : 1; // MSIL netmodule unsigned long fSdl : 1; // compiled with /sdl unsigned long fPGO : 1; // compiled with /ltcg:pgo or pgu unsigned long fExp : 1; // .exp module unsigned long pad : 12; // reserved, must be 0 } flags; unsigned short machine; // target processor unsigned short verFEMajor; // front end major version # unsigned short verFEMinor; // front end minor version # unsigned short verFEBuild; // front end build version # unsigned short verFEQFE; // front end QFE version # unsigned short verMajor; // back end major version # unsigned short verMinor; // back end minor version # unsigned short verBuild; // back end build version # unsigned short verQFE; // back end QFE version # char verSz[1]; // Zero terminated compiler version string } COMPILESYM3; typedef struct ENVBLOCKSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_ENVBLOCK struct { unsigned char rev : 1; // reserved unsigned char pad : 7; // reserved, must be 0 } flags; unsigned char rgsz[1]; // Sequence of zero-terminated strings } ENVBLOCKSYM; typedef struct OBJNAMESYM { unsigned short reclen; // Record length unsigned short rectyp; // S_OBJNAME unsigned long signature; // signature unsigned char name[1]; // Length-prefixed name } OBJNAMESYM; typedef struct ENDARGSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_ENDARG } ENDARGSYM; typedef struct RETURNSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_RETURN CV_GENERIC_FLAG flags; // flags unsigned char style; // CV_GENERIC_STYLE_e return style // followed by return method data } RETURNSYM; typedef struct ENTRYTHISSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_ENTRYTHIS unsigned char thissym; // symbol describing this pointer on entry } ENTRYTHISSYM; // symbol types for 16:16 memory model typedef struct BPRELSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_BPREL16 CV_off16_t off; // BP-relative offset CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } BPRELSYM16; typedef struct DATASYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_LDATA or S_GDATA CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } DATASYM16; typedef DATASYM16 PUBSYM16; typedef struct PROCSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROC16 or S_LPROC16 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned short len; // Proc length unsigned short DbgStart; // Debug start offset unsigned short DbgEnd; // Debug end offset CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol CV_typ16_t typind; // Type index CV_PROCFLAGS flags; // Proc flags unsigned char name[1]; // Length-prefixed name } PROCSYM16; typedef struct THUNKSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_THUNK unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol unsigned short len; // length of thunk unsigned char ord; // THUNK_ORDINAL specifying type of thunk unsigned char name[1]; // name of thunk unsigned char variant[CV_ZEROLEN]; // variant portion of thunk } THUNKSYM16; typedef struct LABELSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_LABEL16 CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol CV_PROCFLAGS flags; // flags unsigned char name[1]; // Length-prefixed name } LABELSYM16; typedef struct BLOCKSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_BLOCK16 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned short len; // Block length CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol unsigned char name[1]; // Length-prefixed name } BLOCKSYM16; typedef struct WITHSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_WITH16 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned short len; // Block length CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol unsigned char expr[1]; // Length-prefixed expression } WITHSYM16; typedef enum CEXM_MODEL_e { CEXM_MDL_table = 0x00, // not executable CEXM_MDL_jumptable = 0x01, // Compiler generated jump table CEXM_MDL_datapad = 0x02, // Data padding for alignment CEXM_MDL_native = 0x20, // native (actually not-pcode) CEXM_MDL_cobol = 0x21, // cobol CEXM_MDL_codepad = 0x22, // Code padding for alignment CEXM_MDL_code = 0x23, // code CEXM_MDL_sql = 0x30, // sql CEXM_MDL_pcode = 0x40, // pcode CEXM_MDL_pcode32Mac = 0x41, // macintosh 32 bit pcode CEXM_MDL_pcode32MacNep = 0x42, // macintosh 32 bit pcode native entry point CEXM_MDL_javaInt = 0x50, CEXM_MDL_unknown = 0xff } CEXM_MODEL_e; // use the correct enumerate name #define CEXM_MDL_SQL CEXM_MDL_sql typedef enum CV_COBOL_e { CV_COBOL_dontstop, CV_COBOL_pfm, CV_COBOL_false, CV_COBOL_extcall } CV_COBOL_e; typedef struct CEXMSYM16 { unsigned short reclen; // Record length unsigned short rectyp; // S_CEXMODEL16 CV_uoff16_t off; // offset of symbol unsigned short seg; // segment of symbol unsigned short model; // execution model union { struct { CV_uoff16_t pcdtable; // offset to pcode function table CV_uoff16_t pcdspi; // offset to segment pcode information } pcode; struct { unsigned short subtype; // see CV_COBOL_e above unsigned short flag; } cobol; }; } CEXMSYM16; typedef struct VPATHSYM16 { unsigned short reclen; // record length unsigned short rectyp; // S_VFTPATH16 CV_uoff16_t off; // offset of virtual function table unsigned short seg; // segment of virtual function table CV_typ16_t root; // type index of the root of path CV_typ16_t path; // type index of the path record } VPATHSYM16; typedef struct REGREL16 { unsigned short reclen; // Record length unsigned short rectyp; // S_REGREL16 CV_uoff16_t off; // offset of symbol unsigned short reg; // register index CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } REGREL16; typedef struct BPRELSYM32_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_BPREL32_16t CV_off32_t off; // BP-relative offset CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } BPRELSYM32_16t; typedef struct BPRELSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_BPREL32 CV_off32_t off; // BP-relative offset CV_typ_t typind; // Type index or Metadata token unsigned char name[1]; // Length-prefixed name } BPRELSYM32; typedef struct FRAMERELSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_MANFRAMEREL | S_ATTR_FRAMEREL CV_off32_t off; // Frame relative offset CV_typ_t typind; // Type index or Metadata token CV_lvar_attr attr; // local var attributes unsigned char name[1]; // Length-prefixed name } FRAMERELSYM; typedef FRAMERELSYM ATTRFRAMERELSYM; typedef struct SLOTSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_LOCALSLOT or S_PARAMSLOT unsigned long iSlot; // slot index CV_typ_t typind; // Type index or Metadata token unsigned char name[1]; // Length-prefixed name } SLOTSYM32; typedef struct ATTRSLOTSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_MANSLOT unsigned long iSlot; // slot index CV_typ_t typind; // Type index or Metadata token CV_lvar_attr attr; // local var attributes unsigned char name[1]; // Length-prefixed name } ATTRSLOTSYM; typedef struct ANNOTATIONSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_ANNOTATION CV_uoff32_t off; unsigned short seg; unsigned short csz; // Count of zero terminated annotation strings unsigned char rgsz[1]; // Sequence of zero terminated annotation strings } ANNOTATIONSYM; typedef struct DATASYM32_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_LDATA32_16t, S_GDATA32_16t or S_PUB32_16t CV_uoff32_t off; unsigned short seg; CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } DATASYM32_16t; typedef DATASYM32_16t PUBSYM32_16t; typedef struct DATASYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA CV_typ_t typind; // Type index, or Metadata token if a managed symbol CV_uoff32_t off; unsigned short seg; unsigned char name[1]; // Length-prefixed name } DATASYM32; typedef struct DATASYMHLSL { unsigned short reclen; // Record length unsigned short rectyp; // S_GDATA_HLSL, S_LDATA_HLSL CV_typ_t typind; // Type index unsigned short regType; // register type from CV_HLSLREG_e unsigned short dataslot; // Base data (cbuffer, groupshared, etc.) slot unsigned short dataoff; // Base data byte offset start unsigned short texslot; // Texture slot start unsigned short sampslot; // Sampler slot start unsigned short uavslot; // UAV slot start unsigned char name[1]; // name } DATASYMHLSL; typedef struct DATASYMHLSL32 { unsigned short reclen; // Record length unsigned short rectyp; // S_GDATA_HLSL32, S_LDATA_HLSL32 CV_typ_t typind; // Type index unsigned long dataslot; // Base data (cbuffer, groupshared, etc.) slot unsigned long dataoff; // Base data byte offset start unsigned long texslot; // Texture slot start unsigned long sampslot; // Sampler slot start unsigned long uavslot; // UAV slot start unsigned short regType; // register type from CV_HLSLREG_e unsigned char name[1]; // name } DATASYMHLSL32; typedef struct DATASYMHLSL32_EX { unsigned short reclen; // Record length unsigned short rectyp; // S_GDATA_HLSL32_EX, S_LDATA_HLSL32_EX CV_typ_t typind; // Type index unsigned long regID; // Register index unsigned long dataoff; // Base data byte offset start unsigned long bindSpace; // Binding space unsigned long bindSlot; // Lower bound in binding space unsigned short regType; // register type from CV_HLSLREG_e unsigned char name[1]; // name } DATASYMHLSL32_EX; typedef enum CV_PUBSYMFLAGS_e { cvpsfNone = 0, cvpsfCode = 0x00000001, cvpsfFunction = 0x00000002, cvpsfManaged = 0x00000004, cvpsfMSIL = 0x00000008, } CV_PUBSYMFLAGS_e; typedef union CV_PUBSYMFLAGS { CV_pubsymflag_t grfFlags; struct { CV_pubsymflag_t fCode : 1; // set if public symbol refers to a code address CV_pubsymflag_t fFunction : 1; // set if public symbol is a function CV_pubsymflag_t fManaged : 1; // set if managed code (native or IL) CV_pubsymflag_t fMSIL : 1; // set if managed IL code CV_pubsymflag_t __unused : 28; // must be zero }; } CV_PUBSYMFLAGS; typedef struct PUBSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_PUB32 CV_PUBSYMFLAGS pubsymflags; CV_uoff32_t off; unsigned short seg; unsigned char name[1]; // Length-prefixed name } PUBSYM32; typedef struct PROCSYM32_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROC32_16t or S_LPROC32_16t unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset CV_uoff32_t off; unsigned short seg; CV_typ16_t typind; // Type index CV_PROCFLAGS flags; // Proc flags unsigned char name[1]; // Length-prefixed name } PROCSYM32_16t; typedef struct PROCSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or S_LPROC32_DPC_ID unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset CV_typ_t typind; // Type index or ID CV_uoff32_t off; unsigned short seg; CV_PROCFLAGS flags; // Proc flags unsigned char name[1]; // Length-prefixed name } PROCSYM32; typedef struct MANPROCSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_GMANPROC, S_LMANPROC, S_GMANPROCIA64 or S_LMANPROCIA64 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset CV_tkn_t token; // COM+ metadata token for method CV_uoff32_t off; unsigned short seg; CV_PROCFLAGS flags; // Proc flags unsigned short retReg; // Register return value is in (may not be used for all archs) unsigned char name[1]; // optional name field } MANPROCSYM; typedef struct MANPROCSYMMIPS { unsigned short reclen; // Record length unsigned short rectyp; // S_GMANPROCMIPS or S_LMANPROCMIPS unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset unsigned long regSave; // int register save mask unsigned long fpSave; // fp register save mask CV_uoff32_t intOff; // int register save offset CV_uoff32_t fpOff; // fp register save offset CV_tkn_t token; // COM+ token type CV_uoff32_t off; unsigned short seg; unsigned char retReg; // Register return value is in unsigned char frameReg; // Frame pointer register unsigned char name[1]; // optional name field } MANPROCSYMMIPS; typedef struct THUNKSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_THUNK32 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol CV_uoff32_t off; unsigned short seg; unsigned short len; // length of thunk unsigned char ord; // THUNK_ORDINAL specifying type of thunk unsigned char name[1]; // Length-prefixed name unsigned char variant[CV_ZEROLEN]; // variant portion of thunk } THUNKSYM32; typedef enum TRAMP_e { // Trampoline subtype trampIncremental, // incremental thunks trampBranchIsland, // Branch island thunks } TRAMP_e; typedef struct TRAMPOLINESYM { // Trampoline thunk symbol unsigned short reclen; // Record length unsigned short rectyp; // S_TRAMPOLINE unsigned short trampType; // trampoline sym subtype unsigned short cbThunk; // size of the thunk CV_uoff32_t offThunk; // offset of the thunk CV_uoff32_t offTarget; // offset of the target of the thunk unsigned short sectThunk; // section index of the thunk unsigned short sectTarget; // section index of the target of the thunk } TRAMPOLINE; typedef struct LABELSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_LABEL32 CV_uoff32_t off; unsigned short seg; CV_PROCFLAGS flags; // flags unsigned char name[1]; // Length-prefixed name } LABELSYM32; typedef struct BLOCKSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_BLOCK32 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long len; // Block length CV_uoff32_t off; // Offset in code segment unsigned short seg; // segment of label unsigned char name[1]; // Length-prefixed name } BLOCKSYM32; typedef struct WITHSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_WITH32 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long len; // Block length CV_uoff32_t off; // Offset in code segment unsigned short seg; // segment of label unsigned char expr[1]; // Length-prefixed expression string } WITHSYM32; typedef struct CEXMSYM32 { unsigned short reclen; // Record length unsigned short rectyp; // S_CEXMODEL32 CV_uoff32_t off; // offset of symbol unsigned short seg; // segment of symbol unsigned short model; // execution model union { struct { CV_uoff32_t pcdtable; // offset to pcode function table CV_uoff32_t pcdspi; // offset to segment pcode information } pcode; struct { unsigned short subtype; // see CV_COBOL_e above unsigned short flag; } cobol; struct { CV_uoff32_t calltableOff; // offset to function table unsigned short calltableSeg; // segment of function table } pcode32Mac; }; } CEXMSYM32; typedef struct VPATHSYM32_16t { unsigned short reclen; // record length unsigned short rectyp; // S_VFTABLE32_16t CV_uoff32_t off; // offset of virtual function table unsigned short seg; // segment of virtual function table CV_typ16_t root; // type index of the root of path CV_typ16_t path; // type index of the path record } VPATHSYM32_16t; typedef struct VPATHSYM32 { unsigned short reclen; // record length unsigned short rectyp; // S_VFTABLE32 CV_typ_t root; // type index of the root of path CV_typ_t path; // type index of the path record CV_uoff32_t off; // offset of virtual function table unsigned short seg; // segment of virtual function table } VPATHSYM32; typedef struct REGREL32_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_REGREL32_16t CV_uoff32_t off; // offset of symbol unsigned short reg; // register index for symbol CV_typ16_t typind; // Type index unsigned char name[1]; // Length-prefixed name } REGREL32_16t; typedef struct REGREL32 { unsigned short reclen; // Record length unsigned short rectyp; // S_REGREL32 CV_uoff32_t off; // offset of symbol CV_typ_t typind; // Type index or metadata token unsigned short reg; // register index for symbol unsigned char name[1]; // Length-prefixed name } REGREL32; typedef struct ATTRREGREL { unsigned short reclen; // Record length unsigned short rectyp; // S_MANREGREL | S_ATTR_REGREL CV_uoff32_t off; // offset of symbol CV_typ_t typind; // Type index or metadata token unsigned short reg; // register index for symbol CV_lvar_attr attr; // local var attributes unsigned char name[1]; // Length-prefixed name } ATTRREGREL; typedef ATTRREGREL ATTRREGRELSYM; typedef struct THREADSYM32_16t { unsigned short reclen; // record length unsigned short rectyp; // S_LTHREAD32_16t | S_GTHREAD32_16t CV_uoff32_t off; // offset into thread storage unsigned short seg; // segment of thread storage CV_typ16_t typind; // type index unsigned char name[1]; // length prefixed name } THREADSYM32_16t; typedef struct THREADSYM32 { unsigned short reclen; // record length unsigned short rectyp; // S_LTHREAD32 | S_GTHREAD32 CV_typ_t typind; // type index CV_uoff32_t off; // offset into thread storage unsigned short seg; // segment of thread storage unsigned char name[1]; // length prefixed name } THREADSYM32; typedef struct SLINK32 { unsigned short reclen; // record length unsigned short rectyp; // S_SLINK32 unsigned long framesize; // frame size of parent procedure CV_off32_t off; // signed offset where the static link was saved relative to the value of reg unsigned short reg; } SLINK32; typedef struct PROCSYMMIPS_16t { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROCMIPS_16t or S_LPROCMIPS_16t unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset unsigned long regSave; // int register save mask unsigned long fpSave; // fp register save mask CV_uoff32_t intOff; // int register save offset CV_uoff32_t fpOff; // fp register save offset CV_uoff32_t off; // Symbol offset unsigned short seg; // Symbol segment CV_typ16_t typind; // Type index unsigned char retReg; // Register return value is in unsigned char frameReg; // Frame pointer register unsigned char name[1]; // Length-prefixed name } PROCSYMMIPS_16t; typedef struct PROCSYMMIPS { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROCMIPS or S_LPROCMIPS unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset unsigned long regSave; // int register save mask unsigned long fpSave; // fp register save mask CV_uoff32_t intOff; // int register save offset CV_uoff32_t fpOff; // fp register save offset CV_typ_t typind; // Type index CV_uoff32_t off; // Symbol offset unsigned short seg; // Symbol segment unsigned char retReg; // Register return value is in unsigned char frameReg; // Frame pointer register unsigned char name[1]; // Length-prefixed name } PROCSYMMIPS; typedef struct PROCSYMIA64 { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROCIA64 or S_LPROCIA64 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol unsigned long len; // Proc length unsigned long DbgStart; // Debug start offset unsigned long DbgEnd; // Debug end offset CV_typ_t typind; // Type index CV_uoff32_t off; // Symbol offset unsigned short seg; // Symbol segment unsigned short retReg; // Register return value is in CV_PROCFLAGS flags; // Proc flags unsigned char name[1]; // Length-prefixed name } PROCSYMIA64; typedef struct REFSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_PROCREF_ST, S_DATAREF_ST, or S_LPROCREF_ST unsigned long sumName; // SUC of the name unsigned long ibSym; // Offset of actual symbol in $$Symbols unsigned short imod; // Module containing the actual symbol unsigned short usFill; // align this record } REFSYM; typedef struct REFSYM2 { unsigned short reclen; // Record length unsigned short rectyp; // S_PROCREF, S_DATAREF, or S_LPROCREF unsigned long sumName; // SUC of the name unsigned long ibSym; // Offset of actual symbol in $$Symbols unsigned short imod; // Module containing the actual symbol unsigned char name[1]; // hidden name made a first class member } REFSYM2; typedef struct ALIGNSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_ALIGN } ALIGNSYM; typedef struct OEMSYMBOL { unsigned short reclen; // Record length unsigned short rectyp; // S_OEM unsigned char idOem[16]; // an oem ID (GUID) CV_typ_t typind; // Type index unsigned long rgl[]; // user data, force 4-byte alignment } OEMSYMBOL; // generic block definition symbols // these are similar to the equivalent 16:16 or 16:32 symbols but // only define the length, type and linkage fields typedef struct PROCSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_GPROC16 or S_LPROC16 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol } PROCSYM; typedef struct THUNKSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_THUNK unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end unsigned long pNext; // pointer to next symbol } THUNKSYM; typedef struct BLOCKSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_BLOCK16 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end } BLOCKSYM; typedef struct WITHSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_WITH16 unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this blocks end } WITHSYM; typedef struct FRAMEPROCSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_FRAMEPROC unsigned long cbFrame; // count of bytes of total frame of procedure unsigned long cbPad; // count of bytes of padding in the frame CV_uoff32_t offPad; // offset (relative to frame poniter) to where // padding starts unsigned long cbSaveRegs; // count of bytes of callee save registers CV_uoff32_t offExHdlr; // offset of exception handler unsigned short sectExHdlr; // section id of exception handler struct { unsigned long fHasAlloca : 1; // function uses _alloca() unsigned long fHasSetJmp : 1; // function uses setjmp() unsigned long fHasLongJmp : 1; // function uses longjmp() unsigned long fHasInlAsm : 1; // function uses inline asm unsigned long fHasEH : 1; // function has EH states unsigned long fInlSpec : 1; // function was speced as inline unsigned long fHasSEH : 1; // function has SEH unsigned long fNaked : 1; // function is __declspec(naked) unsigned long fSecurityChecks : 1; // function has buffer security check introduced by /GS. unsigned long fAsyncEH : 1; // function compiled with /EHa unsigned long fGSNoStackOrdering : 1; // function has /GS buffer checks, but stack ordering couldn't be done unsigned long fWasInlined : 1; // function was inlined within another function unsigned long fGSCheck : 1; // function is __declspec(strict_gs_check) unsigned long fSafeBuffers : 1; // function is __declspec(safebuffers) unsigned long encodedLocalBasePointer : 2; // record function's local pointer explicitly. unsigned long encodedParamBasePointer : 2; // record function's parameter pointer explicitly. unsigned long fPogoOn : 1; // function was compiled with PGO/PGU unsigned long fValidCounts : 1; // Do we have valid Pogo counts? unsigned long fOptSpeed : 1; // Did we optimize for speed? unsigned long fGuardCF : 1; // function contains CFG checks (and no write checks) unsigned long fGuardCFW : 1; // function contains CFW checks and/or instrumentation unsigned long pad : 9; // must be zero } flags; } FRAMEPROCSYM; #ifdef __cplusplus namespace CodeViewInfo { __inline unsigned short ExpandEncodedBasePointerReg(unsigned machineType, unsigned encodedFrameReg) { static const unsigned short rgFramePointerRegX86[] = { CV_REG_NONE, CV_ALLREG_VFRAME, CV_REG_EBP, CV_REG_EBX}; static const unsigned short rgFramePointerRegX64[] = { CV_REG_NONE, CV_AMD64_RSP, CV_AMD64_RBP, CV_AMD64_R13}; static const unsigned short rgFramePointerRegArm[] = { CV_REG_NONE, CV_ARM_SP, CV_ARM_R7, CV_REG_NONE}; if (encodedFrameReg >= 4) { return CV_REG_NONE; } switch (machineType) { case CV_CFL_8080 : case CV_CFL_8086 : case CV_CFL_80286 : case CV_CFL_80386 : case CV_CFL_80486 : case CV_CFL_PENTIUM : case CV_CFL_PENTIUMII : case CV_CFL_PENTIUMIII : return rgFramePointerRegX86[encodedFrameReg]; case CV_CFL_AMD64 : return rgFramePointerRegX64[encodedFrameReg]; case CV_CFL_ARMNT : return rgFramePointerRegArm[encodedFrameReg]; default: return CV_REG_NONE; } } } #endif typedef struct UNAMESPACE { unsigned short reclen; // Record length unsigned short rectyp; // S_UNAMESPACE unsigned char name[1]; // name } UNAMESPACE; typedef struct SEPCODESYM { unsigned short reclen; // Record length unsigned short rectyp; // S_SEPCODE unsigned long pParent; // pointer to the parent unsigned long pEnd; // pointer to this block's end unsigned long length; // count of bytes of this block CV_SEPCODEFLAGS scf; // flags CV_uoff32_t off; // sect:off of the separated code CV_uoff32_t offParent; // sectParent:offParent of the enclosing scope unsigned short sect; // (proc, block, or sepcode) unsigned short sectParent; } SEPCODESYM; typedef struct BUILDINFOSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_BUILDINFO CV_ItemId id; // CV_ItemId of Build Info. } BUILDINFOSYM; typedef struct INLINESITESYM { unsigned short reclen; // Record length unsigned short rectyp; // S_INLINESITE unsigned long pParent; // pointer to the inliner unsigned long pEnd; // pointer to this block's end CV_ItemId inlinee; // CV_ItemId of inlinee unsigned char binaryAnnotations[CV_ZEROLEN]; // an array of compressed binary annotations. } INLINESITESYM; typedef struct INLINESITESYM2 { unsigned short reclen; // Record length unsigned short rectyp; // S_INLINESITE2 unsigned long pParent; // pointer to the inliner unsigned long pEnd; // pointer to this block's end CV_ItemId inlinee; // CV_ItemId of inlinee unsigned long invocations; // entry count unsigned char binaryAnnotations[CV_ZEROLEN]; // an array of compressed binary annotations. } INLINESITESYM2; // Defines a locals and it is live range, how to evaluate. // S_DEFRANGE modifies previous local S_LOCAL, it has to consecutive. typedef struct LOCALSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_LOCAL CV_typ_t typind; // type index CV_LVARFLAGS flags; // local var flags unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters. } LOCALSYM; typedef struct FILESTATICSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_FILESTATIC CV_typ_t typind; // type index CV_uoff32_t modOffset; // index of mod filename in stringtable CV_LVARFLAGS flags; // local var flags unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters } FILESTATICSYM; typedef struct DEFRANGESYM { // A live range of sub field of variable unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE CV_uoff32_t program; // DIA program to evaluate the value of the symbol CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYM; typedef struct DEFRANGESYMSUBFIELD { // A live range of sub field of variable. like locala.i unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_SUBFIELD CV_uoff32_t program; // DIA program to evaluate the value of the symbol CV_uoff32_t offParent; // Offset in parent variable. CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMSUBFIELD; typedef struct CV_RANGEATTR { unsigned short maybe : 1; // May have no user name on one of control flow path. unsigned short padding : 15; // Padding for future use. } CV_RANGEATTR; typedef struct DEFRANGESYMREGISTER { // A live range of en-registed variable unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_REGISTER unsigned short reg; // Register to hold the value of the symbol CV_RANGEATTR attr; // Attribute of the register range. CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMREGISTER; typedef struct DEFRANGESYMFRAMEPOINTERREL { // A live range of frame variable unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_FRAMEPOINTER_REL CV_off32_t offFramePointer; // offset to frame pointer CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMFRAMEPOINTERREL; typedef struct DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE { // A frame variable valid in all function scope unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_FRAMEPOINTER_REL CV_off32_t offFramePointer; // offset to frame pointer } DEFRANGESYMFRAMEPOINTERREL_FULL_SCOPE; #define CV_OFFSET_PARENT_LENGTH_LIMIT 12 // Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. typedef struct DEFRANGESYMSUBFIELDREGISTER { // A live range of sub field of variable. like locala.i unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_SUBFIELD_REGISTER unsigned short reg; // Register to hold the value of the symbol CV_RANGEATTR attr; // Attribute of the register range. CV_uoff32_t offParent : CV_OFFSET_PARENT_LENGTH_LIMIT; // Offset in parent variable. CV_uoff32_t padding : 20; // Padding for future use. CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMSUBFIELDREGISTER; // Note DEFRANGESYMREGISTERREL and DEFRANGESYMSUBFIELDREGISTER had same layout. // Used when /GS Copy parameter as local variable or other variable don't cover by FRAMERELATIVE. typedef struct DEFRANGESYMREGISTERREL { // A live range of variable related to a register. unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_REGISTER_REL unsigned short baseReg; // Register to hold the base pointer of the symbol unsigned short spilledUdtMember : 1; // Spilled member for s.i. unsigned short padding : 3; // Padding for future use. unsigned short offsetParent : CV_OFFSET_PARENT_LENGTH_LIMIT; // Offset in parent variable. CV_off32_t offBasePointer; // offset to register CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid CV_LVAR_ADDR_GAP gaps[CV_ZEROLEN]; // The value is not available in following gaps. } DEFRANGESYMREGISTERREL; typedef struct DEFRANGESYMHLSL { // A live range of variable related to a symbol in HLSL code. unsigned short reclen; // Record length unsigned short rectyp; // S_DEFRANGE_HLSL or S_DEFRANGE_DPC_PTR_TAG unsigned short regType; // register type from CV_HLSLREG_e unsigned short regIndices : 2; // 0, 1 or 2, dimensionality of register space unsigned short spilledUdtMember : 1; // this is a spilled member unsigned short memorySpace : 4; // memory space unsigned short padding : 9; // for future use unsigned short offsetParent; // Offset in parent variable. unsigned short sizeInParent; // Size of enregistered portion CV_LVAR_ADDR_RANGE range; // Range of addresses where this program is valid unsigned char data[CV_ZEROLEN]; // variable length data specifying gaps where the value is not available // followed by multi-dimensional offset of variable location in register // space (see CV_DEFRANGESYMHLSL_* macros below) } DEFRANGESYMHLSL; #define CV_DEFRANGESYM_GAPS_COUNT(x) \ (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYM)) / sizeof(CV_LVAR_ADDR_GAP)) #define CV_DEFRANGESYMSUBFIELD_GAPS_COUNT(x) \ (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMSUBFIELD)) / sizeof(CV_LVAR_ADDR_GAP)) #define CV_DEFRANGESYMHLSL_GAPS_COUNT(x) \ (((x)->reclen + sizeof((x)->reclen) - sizeof(DEFRANGESYMHLSL) - (x)->regIndices * sizeof(CV_uoff32_t)) / sizeof(CV_LVAR_ADDR_GAP)) #define CV_DEFRANGESYMHLSL_GAPS_PTR_BASE(x, t) reinterpret_cast((x)->data) #define CV_DEFRANGESYMHLSL_GAPS_CONST_PTR(x) \ CV_DEFRANGESYMHLSL_GAPS_PTR_BASE(x, const CV_LVAR_ADDR_GAP*) #define CV_DEFRANGESYMHLSL_GAPS_PTR(x) \ CV_DEFRANGESYMHLSL_GAPS_PTR_BASE(x, CV_LVAR_ADDR_GAP*) #define CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, t) \ reinterpret_cast(((CV_LVAR_ADDR_GAP*)(x)->data) + CV_DEFRANGESYMHLSL_GAPS_COUNT(x)) #define CV_DEFRANGESYMHLSL_OFFSET_CONST_PTR(x) \ CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, const CV_uoff32_t*) #define CV_DEFRANGESYMHLSL_OFFSET_PTR(x) \ CV_DEFRANGESYMHLSL_OFFSET_PTR_BASE(x, CV_uoff32_t*) #if defined(CC_DP_CXX) && CC_DP_CXX // Defines a local DPC group shared variable and its location. typedef struct LOCALDPCGROUPSHAREDSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_LOCAL_DPC_GROUPSHARED CV_typ_t typind; // type index CV_LVARFLAGS flags; // local var flags unsigned short dataslot; // Base data (cbuffer, groupshared, etc.) slot unsigned short dataoff; // Base data byte offset start unsigned char name[CV_ZEROLEN]; // Name of this symbol, a null terminated array of UTF8 characters. } LOCALDPCGROUPSHAREDSYM; typedef struct DPCSYMTAGMAP { // A map for DPC pointer tag values to symbol records. unsigned short reclen; // Record length unsigned short rectyp; // S_DPC_SYM_TAG_MAP CV_DPC_SYM_TAG_MAP_ENTRY mapEntries[CV_ZEROLEN]; // Array of mappings from DPC pointer tag values to symbol record offsets } DPCSYMTAGMAP; #define CV_DPCSYMTAGMAP_COUNT(x) \ (((x)->reclen + sizeof((x)->reclen) - sizeof(DPCSYMTAGMAP)) / sizeof(CV_DPC_SYM_TAG_MAP_ENTRY)) #endif // CC_DP_CXX typedef enum CV_armswitchtype { CV_SWT_INT1 = 0, CV_SWT_UINT1 = 1, CV_SWT_INT2 = 2, CV_SWT_UINT2 = 3, CV_SWT_INT4 = 4, CV_SWT_UINT4 = 5, CV_SWT_POINTER = 6, CV_SWT_UINT1SHL1 = 7, CV_SWT_UINT2SHL1 = 8, CV_SWT_INT1SHL1 = 9, CV_SWT_INT2SHL1 = 10, CV_SWT_TBB = CV_SWT_UINT1SHL1, CV_SWT_TBH = CV_SWT_UINT2SHL1, } CV_armswitchtype; typedef struct FUNCTIONLIST { unsigned short reclen; // Record length unsigned short rectyp; // S_CALLERS or S_CALLEES unsigned long count; // Number of functions CV_typ_t funcs[CV_ZEROLEN]; // List of functions, dim == count // unsigned long invocations[CV_ZEROLEN]; Followed by a parallel array of // invocation counts. Counts > reclen are assumed to be zero } FUNCTIONLIST; typedef struct POGOINFO { unsigned short reclen; // Record length unsigned short rectyp; // S_POGODATA unsigned long invocations; // Number of times function was called __int64 dynCount; // Dynamic instruction count unsigned long numInstrs; // Static instruction count unsigned long staInstLive; // Final static instruction count (post inlining) } POGOINFO; typedef struct ARMSWITCHTABLE { unsigned short reclen; // Record length unsigned short rectyp; // S_ARMSWITCHTABLE CV_uoff32_t offsetBase; // Section-relative offset to the base for switch offsets unsigned short sectBase; // Section index of the base for switch offsets unsigned short switchType; // type of each entry CV_uoff32_t offsetBranch; // Section-relative offset to the table branch instruction CV_uoff32_t offsetTable; // Section-relative offset to the start of the table unsigned short sectBranch; // Section index of the table branch instruction unsigned short sectTable; // Section index of the table unsigned long cEntries; // number of switch table entries } ARMSWITCHTABLE; typedef struct MODTYPEREF { unsigned short reclen; // Record length unsigned short rectyp; // S_MOD_TYPEREF unsigned long fNone : 1; // module doesn't reference any type unsigned long fRefTMPCT : 1; // reference /Z7 PCH types unsigned long fOwnTMPCT : 1; // module contains /Z7 PCH types unsigned long fOwnTMR : 1; // module contains type info (/Z7) unsigned long fOwnTM : 1; // module contains type info (/Zi or /ZI) unsigned long fRefTM : 1; // module references type info owned by other module unsigned long reserved : 9; unsigned short word0; // these two words contain SN or module index depending unsigned short word1; // on above flags } MODTYPEREF; typedef struct SECTIONSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_SECTION unsigned short isec; // Section number unsigned char align; // Alignment of this section (power of 2) unsigned char bReserved; // Reserved. Must be zero. unsigned long rva; unsigned long cb; unsigned long characteristics; unsigned char name[1]; // name } SECTIONSYM; typedef struct COFFGROUPSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_COFFGROUP unsigned long cb; unsigned long characteristics; CV_uoff32_t off; // Symbol offset unsigned short seg; // Symbol segment unsigned char name[1]; // name } COFFGROUPSYM; typedef struct EXPORTSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_EXPORT unsigned short ordinal; unsigned short fConstant : 1; // CONSTANT unsigned short fData : 1; // DATA unsigned short fPrivate : 1; // PRIVATE unsigned short fNoName : 1; // NONAME unsigned short fOrdinal : 1; // Ordinal was explicitly assigned unsigned short fForwarder : 1; // This is a forwarder unsigned short reserved : 10; // Reserved. Must be zero. unsigned char name[1]; // name of } EXPORTSYM; // // Symbol for describing indirect calls when they are using // a function pointer cast on some other type or temporary. // Typical content will be an LF_POINTER to an LF_PROCEDURE // type record that should mimic an actual variable with the // function pointer type in question. // // Since the compiler can sometimes tail-merge a function call // through a function pointer, there may be more than one // S_CALLSITEINFO record at an address. This is similar to what // you could do in your own code by: // // if (expr) // pfn = &function1; // else // pfn = &function2; // // (*pfn)(arg list); // typedef struct CALLSITEINFO { unsigned short reclen; // Record length unsigned short rectyp; // S_CALLSITEINFO CV_off32_t off; // offset of call site unsigned short sect; // section index of call site unsigned short __reserved_0; // alignment padding field, must be zero CV_typ_t typind; // type index describing function signature } CALLSITEINFO; typedef struct HEAPALLOCSITE { unsigned short reclen; // Record length unsigned short rectyp; // S_HEAPALLOCSITE CV_off32_t off; // offset of call site unsigned short sect; // section index of call site unsigned short cbInstr; // length of heap allocation call instruction CV_typ_t typind; // type index describing function signature } HEAPALLOCSITE; // Frame cookie information typedef enum CV_cookietype_e { CV_COOKIETYPE_COPY = 0, CV_COOKIETYPE_XOR_SP, CV_COOKIETYPE_XOR_BP, CV_COOKIETYPE_XOR_R13, } CV_cookietype_e; // Symbol for describing security cookie's position and type // (raw, xor'd with esp, xor'd with ebp). typedef struct FRAMECOOKIE { unsigned short reclen; // Record length unsigned short rectyp; // S_FRAMECOOKIE CV_off32_t off; // Frame relative offset unsigned short reg; // Register index CV_cookietype_e cookietype; // Type of the cookie unsigned char flags; // Flags describing this cookie } FRAMECOOKIE; typedef enum CV_DISCARDED_e { CV_DISCARDED_UNKNOWN, CV_DISCARDED_NOT_SELECTED, CV_DISCARDED_NOT_REFERENCED, } CV_DISCARDED_e; typedef struct DISCARDEDSYM { unsigned short reclen; // Record length unsigned short rectyp; // S_DISCARDED unsigned long discarded : 8; // CV_DISCARDED_e unsigned long reserved : 24; // Unused unsigned long fileid; // First FILEID if line number info present unsigned long linenum; // First line number char data[CV_ZEROLEN]; // Original record(s) with invalid type indices } DISCARDEDSYM; typedef struct REFMINIPDB { unsigned short reclen; // Record length unsigned short rectyp; // S_REF_MINIPDB union { unsigned long isectCoff; // coff section CV_typ_t typind; // type index }; unsigned short imod; // mod index unsigned short fLocal : 1; // reference to local (vs. global) func or data unsigned short fData : 1; // reference to data (vs. func) unsigned short fUDT : 1; // reference to UDT unsigned short fLabel : 1; // reference to label unsigned short fConst : 1; // reference to const unsigned short reserved : 11; // reserved, must be zero unsigned char name[1]; // zero terminated name string } REFMINIPDB; typedef struct PDBMAP { unsigned short reclen; // Record length unsigned short rectyp; // S_PDBMAP unsigned char name[CV_ZEROLEN]; // zero terminated source PDB filename followed by zero // terminated destination PDB filename, both in wchar_t } PDBMAP; // // V7 line number data types // enum DEBUG_S_SUBSECTION_TYPE { DEBUG_S_IGNORE = 0x80000000, // if this bit is set in a subsection type then ignore the subsection contents DEBUG_S_SYMBOLS = 0xf1, DEBUG_S_LINES, DEBUG_S_STRINGTABLE, DEBUG_S_FILECHKSMS, DEBUG_S_FRAMEDATA, DEBUG_S_INLINEELINES, DEBUG_S_CROSSSCOPEIMPORTS, DEBUG_S_CROSSSCOPEEXPORTS, DEBUG_S_IL_LINES, DEBUG_S_FUNC_MDTOKEN_MAP, DEBUG_S_TYPE_MDTOKEN_MAP, DEBUG_S_MERGED_ASSEMBLYINPUT, DEBUG_S_COFF_SYMBOL_RVA, }; struct CV_DebugSSubsectionHeader_t { enum DEBUG_S_SUBSECTION_TYPE type; CV_off32_t cbLen; }; struct CV_DebugSLinesHeader_t { CV_off32_t offCon; unsigned short segCon; unsigned short flags; CV_off32_t cbCon; }; struct CV_DebugSLinesFileBlockHeader_t { CV_off32_t offFile; CV_off32_t nLines; CV_off32_t cbBlock; // CV_Line_t lines[nLines]; // CV_Column_t columns[nColumns]; }; // // Line flags (data present) // #define CV_LINES_HAVE_COLUMNS 0x0001 struct CV_Line_t { unsigned long offset; // Offset to start of code bytes for line number unsigned long linenumStart:24; // line where statement/expression starts unsigned long deltaLineEnd:7; // delta to line where statement ends (optional) unsigned long fStatement:1; // true if a statement linenumber, else an expression line num }; typedef unsigned short CV_columnpos_t; // byte offset in a source line struct CV_Column_t { CV_columnpos_t offColumnStart; CV_columnpos_t offColumnEnd; }; struct tagFRAMEDATA { unsigned long ulRvaStart; unsigned long cbBlock; unsigned long cbLocals; unsigned long cbParams; unsigned long cbStkMax; unsigned long frameFunc; unsigned short cbProlog; unsigned short cbSavedRegs; unsigned long fHasSEH:1; unsigned long fHasEH:1; unsigned long fIsFunctionStart:1; unsigned long reserved:29; }; typedef struct tagFRAMEDATA FRAMEDATA, * PFRAMEDATA; typedef struct tagXFIXUP_DATA { unsigned short wType; unsigned short wExtra; unsigned long rva; unsigned long rvaTarget; } XFIXUP_DATA; // Those cross scope IDs are private convention, // it used to delay the ID merging for frontend and backend even linker. // It is transparent for DIA client. // Use those ID will let DIA run a litter slower and but // avoid the copy type tree in some scenarios. #ifdef __cplusplus namespace CodeViewInfo { typedef struct ComboID { static const unsigned int IndexBitWidth = 20; static const unsigned int ImodBitWidth = 12; ComboID(unsigned short imod, unsigned int index) { m_comboID = (((unsigned int) imod) << IndexBitWidth) | index; } ComboID(unsigned int comboID) { m_comboID = comboID; } operator unsigned int() { return m_comboID; } unsigned short GetModIndex() { return (unsigned short) (m_comboID >> IndexBitWidth); } unsigned int GetIndex() { return (m_comboID & ((1 << IndexBitWidth) - 1)); } private: unsigned int m_comboID; } ComboID; typedef struct CrossScopeId { static const unsigned int LocalIdBitWidth = 20; static const unsigned int IdScopeBitWidth = 11; static const unsigned int StartCrossScopeId = (unsigned int) (1 << (LocalIdBitWidth + IdScopeBitWidth)); static const unsigned int LocalIdMask = (1 << LocalIdBitWidth) - 1; static const unsigned int ScopeIdMask = StartCrossScopeId - (1 << LocalIdBitWidth); // Compilation unit at most reference 1M constructed type. static const unsigned int MaxLocalId = (1 << LocalIdBitWidth) - 1; // Compilation unit at most reference to another 2K compilation units. static const unsigned int MaxScopeId = (1 << IdScopeBitWidth) - 1; CrossScopeId(unsigned short aIdScopeId, unsigned int aLocalId) { crossScopeId = StartCrossScopeId | (aIdScopeId << LocalIdBitWidth) | aLocalId; } operator unsigned int() { return crossScopeId; } unsigned int GetLocalId() { return crossScopeId & LocalIdMask; } unsigned int GetIdScopeId() { return (crossScopeId & ScopeIdMask) >> LocalIdBitWidth; } static bool IsCrossScopeId(unsigned int i) { return (StartCrossScopeId & i) != 0; } static CrossScopeId Decode(unsigned int i) { CrossScopeId retval; retval.crossScopeId = i; return retval; } private: CrossScopeId() {} unsigned int crossScopeId; } CrossScopeId; // Combined encoding of TI or FuncId, In compiler implementation // Id prefixed by 1 if it is function ID. typedef struct DecoratedItemId { DecoratedItemId(bool isFuncId, CV_ItemId inputId) { if (isFuncId) { decoratedItemId = 0x80000000 | inputId; } else { decoratedItemId = inputId; } } DecoratedItemId(CV_ItemId encodedId) { decoratedItemId = encodedId; } operator unsigned int() { return decoratedItemId; } bool IsFuncId() { return (decoratedItemId & 0x80000000) == 0x80000000; } CV_ItemId GetItemId() { return decoratedItemId & 0x7fffffff; } private: unsigned int decoratedItemId; } DecoratedItemId; // Compilation Unit object file path include library name // Or compile time PDB full path typedef struct tagPdbIdScope { CV_off32_t offObjectFilePath; } PdbIdScope; // An array of all imports by import module. // List all cross reference for a specific ID scope. // Format of DEBUG_S_CROSSSCOPEIMPORTS subsection is typedef struct tagCrossScopeReferences { PdbIdScope externalScope; // Module of definition Scope. unsigned int countOfCrossReferences; // Count of following array. CV_ItemId referenceIds[CV_ZEROLEN]; // CV_ItemId in another compilation unit. } CrossScopeReferences; // An array of all exports in this module. // Format of DEBUG_S_CROSSSCOPEEXPORTS subsection is typedef struct tagLocalIdAndGlobalIdPair { CV_ItemId localId; // local id inside the compile time PDB scope. 0 based CV_ItemId globalId; // global id inside the link time PDB scope, if scope are different. } LocalIdAndGlobalIdPair; // Format of DEBUG_S_INLINEELINEINFO subsection // List start source file information for an inlined function. #define CV_INLINEE_SOURCE_LINE_SIGNATURE 0x0 #define CV_INLINEE_SOURCE_LINE_SIGNATURE_EX 0x1 typedef struct tagInlineeSourceLine { CV_ItemId inlinee; // function id. CV_off32_t fileId; // offset into file table DEBUG_S_FILECHKSMS CV_off32_t sourceLineNum; // definition start line number. } InlineeSourceLine; typedef struct tagInlineeSourceLineEx { CV_ItemId inlinee; // function id CV_off32_t fileId; // offset into file table DEBUG_S_FILECHKSMS CV_off32_t sourceLineNum; // definition start line number unsigned int countOfExtraFiles; CV_off32_t extraFileId[CV_ZEROLEN]; } InlineeSourceLineEx; // BinaryAnnotations ::= BinaryAnnotationInstruction+ // BinaryAnnotationInstruction ::= BinaryAnnotationOpcode Operand+ // // The binary annotation mechanism supports recording a list of annotations // in an instruction stream. The X64 unwind code and the DWARF standard have // similar design. // // One annotation contains opcode and a number of 32bits operands. // // The initial set of annotation instructions are for line number table // encoding only. These annotations append to S_INLINESITE record, and // operands are unsigned except for BA_OP_ChangeLineOffset. enum BinaryAnnotationOpcode { BA_OP_Invalid, // link time pdb contains PADDINGs BA_OP_CodeOffset, // param : start offset BA_OP_ChangeCodeOffsetBase, // param : nth separated code chunk (main code chunk == 0) BA_OP_ChangeCodeOffset, // param : delta of offset BA_OP_ChangeCodeLength, // param : length of code, default next start BA_OP_ChangeFile, // param : fileId BA_OP_ChangeLineOffset, // param : line offset (signed) BA_OP_ChangeLineEndDelta, // param : how many lines, default 1 BA_OP_ChangeRangeKind, // param : either 1 (default, for statement) // or 0 (for expression) BA_OP_ChangeColumnStart, // param : start column number, 0 means no column info BA_OP_ChangeColumnEndDelta, // param : end column number delta (signed) // Combo opcodes for smaller encoding size. BA_OP_ChangeCodeOffsetAndLineOffset, // param : ((sourceDelta << 4) | CodeDelta) BA_OP_ChangeCodeLengthAndCodeOffset, // param : codeLength, codeOffset BA_OP_ChangeColumnEnd, // param : end column number }; inline int BinaryAnnotationInstructionOperandCount(BinaryAnnotationOpcode op) { return (op == BA_OP_ChangeCodeLengthAndCodeOffset) ? 2 : 1; } /////////////////////////////////////////////////////////////////////////////// // // This routine a simplified variant from cor.h. // // Compress an unsigned integer (iLen) and store the result into pDataOut. // // Return value is the number of bytes that the compressed data occupies. It // is caller's responsibilityt to ensure *pDataOut has at least 4 bytes to be // written to. // // Note that this function returns -1 if iLen is too big to be compressed. // We currently can only encode numbers no larger than 0x1FFFFFFF. // /////////////////////////////////////////////////////////////////////////////// typedef unsigned __int8 UInt8; typedef unsigned __int32 UInt32; typedef UInt8 CompressedAnnotation; typedef CompressedAnnotation* PCompressedAnnotation; inline UInt32 CVCompressData( UInt32 iLen, // [IN] given uncompressed data void * pDataOut) // [OUT] buffer for the compressed data { UInt8 *pBytes = reinterpret_cast(pDataOut); if (iLen <= 0x7F) { *pBytes = UInt8(iLen); return 1; } if (iLen <= 0x3FFF) { *pBytes = UInt8((iLen >> 8) | 0x80); *(pBytes+1) = UInt8(iLen & 0xff); return 2; } if (iLen <= 0x1FFFFFFF) { *pBytes = UInt8((iLen >> 24) | 0xC0); *(pBytes+1) = UInt8((iLen >> 16) & 0xff); *(pBytes+2) = UInt8((iLen >> 8) & 0xff); *(pBytes+3) = UInt8(iLen & 0xff); return 4; } return (UInt32) -1; } /////////////////////////////////////////////////////////////////////////////// // // Uncompress the data in pData and store the result into pDataOut. // // Return value is the uncompressed unsigned integer. pData is incremented to // point to the next piece of uncompressed data. // // Returns -1 if what is passed in is incorrectly compressed data, such as // (*pBytes & 0xE0) == 0xE0. // /////////////////////////////////////////////////////////////////////////////// inline UInt32 CVUncompressData( PCompressedAnnotation & pData) // [IN,OUT] compressed data { UInt32 res = (UInt32)(-1); if ((*pData & 0x80) == 0x00) { // 0??? ???? res = (UInt32)(*pData++); } else if ((*pData & 0xC0) == 0x80) { // 10?? ???? res = (UInt32)((*pData++ & 0x3f) << 8); res |= *pData++; } else if ((*pData & 0xE0) == 0xC0) { // 110? ???? res = (*pData++ & 0x1f) << 24; res |= *pData++ << 16; res |= *pData++ << 8; res |= *pData++; } return res; } // Encode smaller absolute numbers with smaller buffer. // // General compression only work for input < 0x1FFFFFFF // algorithm will not work on 0x80000000 inline unsigned __int32 EncodeSignedInt32(__int32 input) { unsigned __int32 rotatedInput; if (input >= 0) { rotatedInput = input << 1; } else { rotatedInput = ((-input) << 1) | 1; } return rotatedInput; } inline __int32 DecodeSignedInt32(unsigned __int32 input) { __int32 rotatedInput; if (input & 1) { rotatedInput = - (int)(input >> 1); } else { rotatedInput = input >> 1; } return rotatedInput; } } #endif #pragma pack ( pop ) #endif /* CV_INFO_INCLUDED */ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/cycletimer.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // CycleTimer has methods related to getting cycle timer values. // It uses an all-statics class as a namespace mechanism. // #ifndef _CYCLETIMER_H_ #define _CYCLETIMER_H_ #include "windef.h" class CycleTimer { // This returns the value of the *non-thread-virtualized* cycle counter. static unsigned __int64 GetCycleCount64(); // This wraps GetCycleCount64 in the signature of QueryThreadCycleTime -- but note // that it ignores the "thrd" argument. static BOOL WINAPI DefaultQueryThreadCycleTime(_In_ HANDLE thrd, _Out_ PULONG64 cyclesPtr); // The function pointer type for QueryThreadCycleTime. typedef BOOL (WINAPI *QueryThreadCycleTimeSig)(_In_ HANDLE, _Out_ PULONG64); // Returns a function pointer for QueryThreadCycleTime, or else BadFPtr. static QueryThreadCycleTimeSig GetQueryThreadCycleTime(); // Initialized once from NULL to either BadFPtr or QueryThreadCycleTime. static QueryThreadCycleTimeSig s_QueryThreadCycleTimeFPtr; public: // This method computes the number of cycles/sec for the current machine. The cycles are those counted // by GetThreadCycleTime; we assume that these are of equal duration, though that is not necessarily true. // If any OS interaction fails, returns 0.0. static double CyclesPerSecond(); // Does a large number of queries, and returns the average of their overhead, so other measurements // can adjust for this. static unsigned __int64 QueryOverhead(); // There's no "native" atomic add for 64 bit, so we have this convenience function. static void InterlockedAddU64(unsigned __int64* loc, unsigned __int64 amount); // Attempts to query the cycle counter of the current thread. If successful, returns "true" and sets // *cycles to the cycle counter value. Otherwise, returns false. Note that the value returned is (currently) // virtualized to the current thread only on Windows; on non-windows x86/x64 platforms, directly reads // the cycle counter and returns that value. static bool GetThreadCyclesS(unsigned __int64* cycles); }; #endif // _CYCLETIMER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/daccess.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // File: daccess.h // // // Support for external access of runtime data structures. These // macros and templates hide the details of pointer and data handling // so that data structures and code can be compiled to work both // in-process and through a special memory access layer. // // This code assumes the existence of two different pieces of code, // the target, the runtime code that is going to be examined, and // the host, the code that's doing the examining. Access to the // target is abstracted so the target may be a live process on the // same machine, a live process on a different machine, a dump file // or whatever. No assumptions should be made about accessibility // of the target. // // This code assumes that the data in the target is static. Any // time the target's data changes the interfaces must be reset so // that potentially stale data is discarded. // // This code is intended for read access and there is no // way to write data back currently. // // DAC-ized code: // - is read-only (non-invasive). So DACized codepaths can not trigger a GC. // - has no Thread* object. In reality, DAC-ized codepaths are // ReadProcessMemory calls from out-of-process. Conceptually, they // are like a pure-native (preemptive) thread. //// // This means that in particular, you cannot DACize a GCTRIGGERS function. // Neither can you DACize a function that throws if this will involve // allocating a new exception object. There may be // exceptions to these rules if you can guarantee that the DACized // part of the code path cannot cause a garbage collection (see // EditAndContinueModule::ResolveField for an example). // If you need to DACize a function that may trigger // a GC, it is probably best to refactor the function so that the DACized // part of the code path is in a separate function. For instance, // functions with GetOrCreate() semantics are hard to DAC-ize because // they the Create portion is inherently invasive. Instead, consider refactoring // into a GetOrFail() function that DAC can call; and then make GetOrCreate() // a wrapper around that. // // This code works by hiding the details of access to target memory. // Access is divided into two types: // 1. DPTR - access to a piece of data. // 2. VPTR - access to a class with a vtable. The class can only have // a single vtable pointer at the beginning of the class instance. // Things only need to be declared as VPTRs when it is necessary to // call virtual functions in the host. In that case the access layer // must do extra work to provide a host vtable for the object when // it is retrieved so that virtual functions can be called. // // When compiling with DACCESS_COMPILE the macros turn into templates // which replace pointers with smart pointers that know how to fetch // data from the target process and provide a host process version of it. // Normal data structure access will transparently receive a host copy // of the data and proceed, so code such as // typedef DPTR(Class) PTR_Class; // PTR_Class cls; // int val = cls->m_Int; // will work without modification. The appropriate operators are overloaded // to provide transparent access, such as the -> operator in this case. // Note that the convention is to create an appropriate typedef for // each type that will be accessed. This hides the particular details // of the type declaration and makes the usage look more like regular code. // // The ?PTR classes also have an implicit base type cast operator to // produce a host-pointer instance of the given type. For example // Class* cls = PTR_Class(addr); // works by implicit conversion from the PTR_Class created by wrapping // to a host-side Class instance. Again, this means that existing code // can work without modification. // // Code Example: // // typedef struct _rangesection // { // PTR_IJitManager pjit; // PTR_RangeSection pright; // PTR_RangeSection pleft; // ... Other fields omitted ... // } RangeSection; // // RangeSection* pRS = m_RangeTree; // // while (pRS != NULL) // { // if (currentPC < pRS->LowAddress) // pRS=pRS->pleft; // else if (currentPC > pRS->HighAddress) // pRS=pRS->pright; // else // { // return pRS->pjit; // } // } // // This code does not require any modifications. The global reference // provided by m_RangeTree will be a host version of the RangeSection // instantiated by conversion. The references to pRS->pleft and // pRS->pright will refer to DPTRs due to the modified declaration. // In the assignment statement the compiler will automatically use // the implicit conversion from PTR_RangeSection to RangeSection*, // causing a host instance to be created. Finally, if an appropriate // section is found the use of pRS->pjit will cause an implicit // conversion from PTR_IJitManager to IJitManager. The VPTR code // will look at target memory to determine the actual derived class // for the JitManager and instantiate the right class in the host so // that host virtual functions can be used just as they would in // the target. // // There are situations where code modifications are required, though. // // 1. Any time the actual value of an address matters, such as using // it as a search key in a tree, the target address must be used. // // An example of this is the RangeSection tree used to locate JIT // managers. A portion of this code is shown above. Each // RangeSection node in the tree describes a range of addresses // managed by the JitMan. These addresses are just being used as // values, not to dereference through, so there are not DPTRs. When // searching the range tree for an address the address used in the // search must be a target address as that's what values are kept in // the RangeSections. In the code shown above, currentPC must be a // target address as the RangeSections in the tree are all target // addresses. Use dac_cast to retrieve the target address // of a ?PTR, as well as to convert a host address to the // target address used to retrieve that particular instance. Do not // use dac_cast with any raw target pointer types (such as BYTE*). // // 2. Any time an address is modified, such as by address arithmetic, // the arithmetic must be performed on the target address. // // When a host instance is created it is created for the type in use. // There is no particular relation to any other instance, so address // arithmetic cannot be used to get from one instance to any other // part of memory. For example // char* Func(Class* cls) // { // // String follows the basic Class data. // return (char*)(cls + 1); // } // does not work with external access because the Class* used would // have retrieved only a Class worth of data. There is no string // following the host instance. Instead, this code should use // dac_cast to get the target address of the Class // instance, add sizeof(*cls) and then create a new ?PTR to access // the desired data. Note that the newly retrieved data will not // be contiguous with the Class instance, so address arithmetic // will still not work. // // Previous Code: // // BOOL IsTarget(LPVOID ip) // { // StubCallInstrs* pStubCallInstrs = GetStubCallInstrs(); // // if (ip == (LPVOID) &(pStubCallInstrs->m_op)) // { // return TRUE; // } // // Modified Code: // // BOOL IsTarget(LPVOID ip) // { // StubCallInstrs* pStubCallInstrs = GetStubCallInstrs(); // // if ((TADDR)ip == dac_cast(pStubCallInstrs) + // (TADDR)offsetof(StubCallInstrs, m_op)) // { // return TRUE; // } // // The parameter ip is a target address, so the host pStubCallInstrs // cannot be used to derive an address from. The member & reference // has to be replaced with a conversion from host to target address // followed by explicit offsetting for the field. // // PTR_HOST_MEMBER_TADDR is a convenience macro that encapsulates // these two operations, so the above code could also be: // // if ((TADDR)ip == // PTR_HOST_MEMBER_TADDR(StubCallInstrs, pStubCallInstrs, m_op)) // // 3. Any time the amount of memory referenced through an address // changes, such as by casting to a different type, a new ?PTR // must be created. // // Host instances are created and stored based on both the target // address and size of access. The access code has no way of knowing // all possible ways that data will be retrieved for a given address // so if code changes the way it accesses through an address a new // ?PTR must be used, which may lead to a difference instance and // different host address. This means that pointer identity does not hold // across casts, so code like // Class* cls = PTR_Class(addr); // Class2* cls2 = PTR_Class2(addr); // return cls == cls2; // will fail because the host-side instances have no relation to each // other. That isn't a problem, since by rule #1 you shouldn't be // relying on specific host address values. // // Previous Code: // // return (ArrayClass *) m_pMethTab->GetClass(); // // Modified Code: // // return PTR_ArrayClass(m_pMethTab->GetClass()); // // The ?PTR templates have an implicit conversion from a host pointer // to a target address, so the cast above constructs a new // PTR_ArrayClass by implicitly converting the host pointer result // from GetClass() to its target address and using that as the address // of the new PTR_ArrayClass. As mentioned, the actual host-side // pointer values may not be the same. // // Host pointer identity can be assumed as long as the type of access // is the same. In the example above, if both accesses were of type // Class then the host pointer will be the same, so it is safe to // retrieve the target address of an instance and then later get // a new host pointer for the target address using the same type as // the host pointer in that case will be the same. This is enabled // by caching all of the retrieved host instances. This cache is searched // by the addr:size pair and when there's a match the existing instance // is reused. This increases performance and also allows simple // pointer identity to hold. It does mean that host memory grows // in proportion to the amount of target memory being referenced, // so retrieving extraneous data should be avoided. // The host-side data cache grows until the Flush() method is called, // at which point all host-side data is discarded. No host // instance pointers should be held across a Flush(). // // Accessing into an object can lead to some unusual behavior. For // example, the SList class relies on objects to contain an SLink // instance that it uses for list maintenance. This SLink can be // embedded anywhere in the larger object. The SList access is always // purely to an SLink, so when using the access layer it will only // retrieve an SLink's worth of data. The SList template will then // do some address arithmetic to determine the start of the real // object and cast the resulting pointer to the final object type. // When using the access layer this results in a new ?PTR being // created and used, so a new instance will result. The internal // SLink instance will have no relation to the new object instance // even though in target address terms one is embedded in the other. // The assumption of data stability means that this won't cause // a problem, but care must be taken with the address arithmetic, // as laid out in rules #2 and #3. // // 4. Global address references cannot be used. Any reference to a // global piece of code or data, such as a function address, global // variable or class static variable, must be changed. // // The external access code may load at a different base address than // the target process code. Global addresses are therefore not // meaningful and must be replaced with something else. There isn't // a single solution, so replacements must be done on a case-by-case // basis. // // The simplest case is a global or class static variable. All // declarations must be replaced with a special declaration that // compiles into a modified accessor template value when compiled for // external data access. Uses of the variable automatically are fixed // up by the template instance. Note that assignment to the global // must be independently ifdef'ed as the external access layer should // not make any modifications. // // Macros allow for simple declaration of a class static and global // values that compile into an appropriate templated value. // // Previous Code: // // static RangeSection* m_RangeTree; // RangeSection* ExecutionManager::m_RangeTree; // // extern ThreadStore* g_pThreadStore; // ThreadStore* g_pThreadStore = &StaticStore; // class SystemDomain : public BaseDomain { // ... // ArrayListStatic m_appDomainIndexList; // ... // } // // SystemDomain::m_appDomainIndexList; // // extern DWORD gThreadTLSIndex; // // DWORD gThreadTLSIndex = TLS_OUT_OF_INDEXES; // // Modified Code: // // typedef DPTR(RangeSection) PTR_RangeSection; // SPTR_DECL(RangeSection, m_RangeTree); // SPTR_IMPL(RangeSection, ExecutionManager, m_RangeTree); // // typedef DPTR(ThreadStore) PTR_ThreadStore // GPTR_DECL(ThreadStore, g_pThreadStore); // GPTR_IMPL_INIT(ThreadStore, g_pThreadStore, &StaticStore); // // class SystemDomain : public BaseDomain { // ... // SVAL_DECL(ArrayListStatic; m_appDomainIndexList); // ... // } // // SVAL_IMPL(ArrayListStatic, SystemDomain, m_appDomainIndexList); // // GVAL_DECL(DWORD, gThreadTLSIndex); // // GVAL_IMPL_INIT(DWORD, gThreadTLSIndex, TLS_OUT_OF_INDEXES); // // When declaring the variable, the first argument declares the // variable's type and the second argument declares the variable's // name. When defining the variable the arguments are similar, with // an extra class name parameter for the static class variable case. // If an initializer is needed the IMPL_INIT macro should be used. // // Things get slightly more complicated when declaring an embedded // array. In this case the data element is not a single element and // therefore cannot be represented by a ?PTR. In the case of a global // array, you should use the GARY_DECL and GARY_IMPL macros. // We durrently have no support for declaring static array data members // or initialized arrays. Array data members that are dynamically allocated // need to be treated as pointer members. To reference individual elements // you must use pointer arithmetic (see rule 2 above). An array declared // as a local variable within a function does not need to be DACized. // // // All uses of ?VAL_DECL must have a corresponding entry given in the // DacGlobals structure in src\inc\dacvars.h. For SVAL_DECL the entry // is class__name. For GVAL_DECL the entry is dac__name. You must add // these entries in dacvars.h using the DEFINE_DACVAR macro. Note that // these entries also are used for dumping memory in mini dumps and // heap dumps. If it's not appropriate to dump a variable, (e.g., // it's an array or some other value that is not important to have // in a minidump) a second macro, DEFINE_DACVAR_NO_DUMP, will allow // you to make the required entry in the DacGlobals structure without // dumping its value. If the variable is implemented with one of the VOLATILE_* macros // then the DEFINE_DACVAR_VOLATILE macro must be used. // // For convenience, here is a list of the various variable declaration and // initialization macros: // SVAL_DECL(type, name) static non-pointer data class MyClass // member declared within { // the class declaration // static int i; // SVAL_DECL(int, i); // } // // SVAL_IMPL(type, cls, name) static non-pointer data // int MyClass::i; // member defined outside SVAL_IMPL(int, MyClass, i); // the class declaration // // SVAL_IMPL_INIT(type, cls, static non-pointer data // int MyClass::i = 0; // name, val) member defined and SVAL_IMPL_INIT(int, MyClass, i, 0); // initialized outside the // class declaration // ------------------------------------------------------------------------------------------------ // VOLATILE_SVAL_DECL(type, name) static volatile class MyClass // non-pointer data { // member declared // static Volatile i; // within the class VOLATILE_SVAL_DECL(int, i); // declaration } // // VOLATILE_SVAL_IMPL(type, cls, static volatile // name) non-pointer data // Volatile MyClass::i; // member defined VOLATILE_SVAL_IMPL(int, MyClass, i); // outside the // class declaration // // VOLATILE_SVAL_IMPL_INIT( static volatile // type, cls, name) non-pointer data // Volatile MyClass::i = 0; // member defined VOLATILE_SVAL_IMPL_INIT(int, MyClass, i, 0); // and initialized // outside the // class declaration // ------------------------------------------------------------------------------------------------ // SPTR_DECL(type, name) static pointer data class MyClass // member declared within { // the class declaration // static int * pInt; // SPTR_DECL(int, pInt); // } // // SPTR_IMPL(type, cls, name) static pointer data // int * MyClass::pInt; // member defined outside SPTR_IMPL(int, MyClass, pInt); // the class declaration // // SPTR_IMPL_INIT(type, cls, static pointer data // int * MyClass::pInt = NULL; // name, val) member defined and SPTR_IMPL_INIT(int, MyClass, pInt, NULL); // initialized outside the // class declaration // ------------------------------------------------------------------------------------------------ // VOLATILE_SPTR_DECL(type, name) static volatile class MyClass // pointer data { // member declared // static Volatile i; // within the class VOLATILE_SPTR_DECL(int, i); // declaration } // // VOLATILE_SPTR_IMPL(type, cls, static volatile // name) pointer data // Volatile MyClass::i; // member defined VOLATILE_SPTR_IMPL(int, MyClass, i); // outside the // class declaration // // VOLATILE_SPTR_IMPL_INIT( static volatile // type, cls, name) pointer data // Volatile MyClass::i = 0; // member defined VOLATILE_SPTR_IMPL_INIT(int, MyClass, i, 0); // and initialized // outside the // class declaration // ------------------------------------------------------------------------------------------------ // GVAL_DECL(type, name) extern declaration of // extern int g_i // global non-pointer GVAL_DECL(int, g_i); // variable // // GVAL_IMPL(type, name) declaration of a // int g_i // global non-pointer GVAL_IMPL(int, g_i); // variable // // GVAL_IMPL_INIT (type, declaration and // int g_i = 0; // name, initialization of a GVAL_IMPL_INIT(int, g_i, 0); // val) global non-pointer // variable // ****Note**** // If you use GVAL_? to declare a global variable of a structured type and you need to // access a member of the type, you cannot use the dot operator. Instead, you must take the // address of the variable and use the arrow operator. For example: // struct // { // int x; // char ch; // } MyStruct; // GVAL_IMPL(MyStruct, g_myStruct); // int i = (&g_myStruct)->x; // ------------------------------------------------------------------------------------------------ // GPTR_DECL(type, name) extern declaration of // extern int * g_pInt // global pointer GPTR_DECL(int, g_pInt); // variable // // GPTR_IMPL(type, name) declaration of a // int * g_pInt // global pointer GPTR_IMPL(int, g_pInt); // variable // // GPTR_IMPL_INIT (type, declaration and // int * g_pInt = 0; // name, initialization of a GPTR_IMPL_INIT(int, g_pInt, NULL); // val) global pointer // variable // ------------------------------------------------------------------------------------------------ // GARY_DECL(type, name) extern declaration of // extern int g_rgIntList[MAX_ELEMENTS]; // a global array GPTR_DECL(int, g_rgIntList, MAX_ELEMENTS); // variable // // GARY_IMPL(type, name) declaration of a // int g_rgIntList[MAX_ELEMENTS]; // global pointer GPTR_IMPL(int, g_rgIntList, MAX_ELEMENTS); // variable // // // Certain pieces of code, such as the stack walker, rely on identifying // an object from its vtable address. As the target vtable addresses // do not necessarily correspond to the vtables used in the host, these // references must be translated. The access layer maintains translation // tables for all classes used with VPTR and can return the target // vtable pointer for any host vtable in the known list of VPTR classes. // // ----- Errors: // // All errors in the access layer are reported via exceptions. The // formal access layer methods catch all such exceptions and turn // them into the appropriate error, so this generally isn't visible // to users of the access layer. // // ----- DPTR Declaration: // // Create a typedef for the type with typedef DPTR(type) PTR_type; // Replace type* with PTR_type. // // ----- VPTR Declaration: // // VPTR can only be used on classes that have a single vtable // pointer at the beginning of the object. This should be true // for a normal single-inheritance object. // // All of the classes that may be instantiated need to be identified // and marked. In the base class declaration add either // VPTR_BASE_VTABLE_CLASS if the class is abstract or // VPTR_BASE_CONCRETE_VTABLE_CLASS if the class is concrete. In each // derived class add VPTR_VTABLE_CLASS. If you end up with compile or // link errors for an unresolved method called VPtrSize you missed a // derived class declaration. // // // All classes to be instantiated must be listed in src\inc\vptr_list.h. // // Create a typedef for the type with typedef VPTR(type) PTR_type; // When using a VPTR, replace Class* with PTR_Class. // // ----- Specific Macros: // // PTR_TO_TADDR(ptr) // Retrieves the raw target address for a ?PTR. // See code:dac_cast for the preferred alternative // // PTR_HOST_TO_TADDR(host) // Given a host address of an instance produced by a ?PTR reference, // return the original target address. The host address must // be an exact match for an instance. // See code:dac_cast for the preferred alternative // // PTR_HOST_INT_TO_TADDR(host) // Given a host address which resides somewhere within an instance // produced by a ?PTR reference (a host interior pointer) return the // corresponding target address. This is useful for evaluating // relative pointers (e.g. RelativePointer) where calculating the // target address requires knowledge of the target address of the // relative pointer field itself. This lookup is slower than that for // a non-interior host pointer so use it sparingly. // // VPTR_HOST_VTABLE_TO_TADDR(host) // Given the host vtable pointer for a known VPTR class, return // the target vtable pointer. // // PTR_HOST_MEMBER_TADDR(type, host, memb) // Retrieves the target address of a host instance pointer and // offsets it by the given member's offset within the type. // // PTR_HOST_INT_MEMBER_TADDR(type, host, memb) // As above but will work for interior host pointers (see the // description of PTR_HOST_INT_TO_TADDR for an explanation of host // interior pointers). // // PTR_READ(addr, size) // Reads a block of memory from the target and returns a host // pointer for it. Useful for reading blocks of data from the target // whose size is only known at runtime, such as raw code for a jitted // method. If the data being read is actually an object, use SPTR // instead to get better type semantics. // // DAC_EMPTY() // DAC_EMPTY_ERR() // DAC_EMPTY_RET(retVal) // DAC_UNEXPECTED() // Provides an empty method implementation when compiled // for DACCESS_COMPILE. For example, use to stub out methods needed // for vtable entries but otherwise unused. // // These macros are designed to turn into normal code when compiled // without DACCESS_COMPILE. // //***************************************************************************** #ifndef __daccess_h__ #define __daccess_h__ #include #include "switches.h" #include "safemath.h" #include "corerror.h" // Keep in sync with the definitions in dbgutil.cpp and createdump.h #define DACCESS_TABLE_SYMBOL "g_dacTable" #ifdef PAL_STDCPP_COMPAT #include #else #include "clr_std/type_traits" #include "crosscomp.h" #endif // Information stored in the DAC table of interest to the DAC implementation // Note that this information is shared between all instantiations of ClrDataAccess, so initialize // it just once in code:ClrDataAccess.GetDacGlobals (rather than use fields in ClrDataAccess); struct DacTableInfo { // On Windows, the first DWORD is the 32-bit timestamp read out of the runtime dll's debug directory. // The remaining 3 DWORDS must all be 0. // On Mac, this is the 16-byte UUID of the runtime dll. // It is used to validate that mscorwks is the same version as mscordacwks DWORD dwID0; DWORD dwID1; DWORD dwID2; DWORD dwID3; }; // The header of the DAC table. This includes the number of globals, the number of vptrs, and // the DacTableInfo structure. We need the DacTableInfo and DacTableHeader structs outside // of a DACCESS_COMPILE since soshost walks the Dac table headers to find the UUID of CoreCLR // in the target process. struct DacTableHeader { ULONG numGlobals; ULONG numVptrs; DacTableInfo info; }; // // This version of things wraps pointer access in // templates which understand how to retrieve data // through an access layer. In this case no assumptions // can be made that the current compilation processor or // pointer types match the target's processor or pointer types. // // Define TADDR as a non-pointer value so use of it as a pointer // will not work properly. Define it as unsigned so // pointer comparisons aren't affected by sign. // This requires special casting to ULONG64 to sign-extend if necessary. typedef ULONG_PTR TADDR; // TSIZE_T used for counts or ranges that need to span the size of a // target pointer. For cross-plat, this may be different than SIZE_T // which reflects the host pointer size. typedef SIZE_T TSIZE_T; // // The following table contains all the global information that data access needs to begin // operation. All of the values stored here are RVAs. DacGlobalBase() returns the current // base address to combine with to get a full target address. // typedef struct _DacGlobals { #ifdef _MSC_VER private: const static _DacGlobals s_dacGlobals; #else void InitializeEntries(); #endif public: static void Initialize(); // These will define all of the dac related mscorwks static and global variables #define DEFINE_DACVAR(size, id, var) TADDR id; #define DEFINE_DACVAR_VOLATILE(size, id, var) TADDR id; #define DEFINE_DACVAR_NO_DUMP(size, id, var) TADDR id; #include "dacvars.h" #undef DEFINE_DACVAR_VOLATILE #undef DEFINE_DACVAR_NODUMP #undef DEFINE_DACVAR #define DEFINE_DACGFN(func) TADDR fn__##func; #define DEFINE_DACGFN_STATIC(class, func) TADDR fn__##class##__##func; #include "gfunc_list.h" #undef DEFINE_DACGFN #undef DEFINE_DACGFN_STATIC // Vtable pointer values for all classes that must // be instanted using vtable pointers as the identity. #define VPTR_CLASS(name) TADDR name##__vtAddr; #include "vptr_list.h" #undef VPTR_CLASS } DacGlobals; #ifdef DACCESS_COMPILE #ifdef __cplusplus extern "C" { #endif // These two functions are largely just for marking code // that is not fully converted. DacWarning prints a debug // message, while DacNotImpl throws a not-implemented exception. void __cdecl DacWarning(_In_ _In_z_ char* format, ...); void DacNotImpl(void); void DacError(HRESULT err); void DECLSPEC_NORETURN DacError_NoRet(HRESULT err); TADDR DacGlobalBase(void); DacGlobals* DacGlobalValues(void); HRESULT DacReadAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx); HRESULT DacWriteAll(TADDR addr, PVOID buffer, ULONG32 size, bool throwEx); HRESULT DacAllocVirtual(TADDR addr, ULONG32 size, ULONG32 typeFlags, ULONG32 protectFlags, bool throwEx, TADDR* mem); HRESULT DacFreeVirtual(TADDR mem, ULONG32 size, ULONG32 typeFlags, bool throwEx); PVOID DacInstantiateTypeByAddress(TADDR addr, ULONG32 size, bool throwEx); PVOID DacInstantiateTypeByAddressNoReport(TADDR addr, ULONG32 size, bool throwEx); PVOID DacInstantiateClassByVTable(TADDR addr, ULONG32 minSize, bool throwEx); // Copy a null-terminated ascii or unicode string from the target to the host. // Note that most of the work here is to find the null terminator. If you know the exact length, // then you can also just call DacInstantiateTypebyAddress. PSTR DacInstantiateStringA(TADDR addr, ULONG32 maxChars, bool throwEx); PWSTR DacInstantiateStringW(TADDR addr, ULONG32 maxChars, bool throwEx); TADDR DacGetTargetAddrForHostAddr(LPCVOID ptr, bool throwEx); TADDR DacGetTargetAddrForHostInteriorAddr(LPCVOID ptr, bool throwEx); TADDR DacGetTargetVtForHostVt(LPCVOID vtHost, bool throwEx); PWSTR DacGetVtNameW(TADDR targetVtable); // Report a region of memory to the debugger bool DacEnumMemoryRegion(TADDR addr, TSIZE_T size, bool fExpectSuccess = true); // Report a region of memory to the debugger bool DacUpdateMemoryRegion(TADDR addr, TSIZE_T bufferSize, BYTE* buffer); HRESULT DacWriteHostInstance(PVOID host, bool throwEx); // This is meant to mimic the RethrowTerminalExceptions/ // SwallowAllExceptions/RethrowTransientExceptions macros to allow minidump // gathering cancelation for details see // code:ClrDataAccess.EnumMemoryRegionsWrapper extern void DacLogMessage(LPCSTR format, ...); // This is usable in EX_TRY exactly how RethrowTerminalExceptions et cetera #define RethrowCancelExceptions \ if (GET_EXCEPTION()->GetHR() == COR_E_OPERATIONCANCELED) \ { \ EX_RETHROW; \ } \ DacLogMessage("DAC exception caught at %s:%d\n", __FILE__, __LINE__); // Occasionally it's necessary to allocate some host memory for // instance data that's created on the fly and so doesn't directly // correspond to target memory. These are held and freed on flush // like other instances but can't be looked up by address. PVOID DacAllocHostOnlyInstance(ULONG32 size, bool throwEx); // Determines whether ASSERTs should be raised when inconsistencies in the target are detected bool DacTargetConsistencyAssertsEnabled(); // Host instances can be marked as they are enumerated in // order to break cycles. This function returns true if // the instance is already marked, otherwise it marks the // instance and returns false. bool DacHostPtrHasEnumMark(LPCVOID host); // Determines if EnumMemoryRegions has been called on a method descriptor. // This helps perf for minidumps of apps with large managed stacks. bool DacHasMethodDescBeenEnumerated(LPCVOID pMD); // Sets a flag indicating that EnumMemoryRegions on a method desciptor // has been successfully called. The function returns true if // this flag had been previously set. bool DacSetMethodDescEnumerated(LPCVOID pMD); // Determines if a method descriptor is valid BOOL DacValidateMD(LPCVOID pMD); // Enumerate the instructions around a call site to help debugger stack walking heuristics void DacEnumCodeForStackwalk(TADDR taCallEnd); // Given the address and the size of a memory range which is stored in the buffer, replace all the patches // in the buffer with the real opcodes. This is especially important on X64 where the unwinder needs to // disassemble the native instructions. class MemoryRange; HRESULT DacReplacePatchesInHostMemory(MemoryRange range, PVOID pBuffer); // // Convenience macros for EnumMemoryRegions implementations. // // Enumerate the given host instance and return // true if the instance hasn't already been enumerated. #define DacEnumHostDPtrMem(host) \ (!DacHostPtrHasEnumMark(host) ? \ (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), sizeof(*host)), \ true) : false) #define DacEnumHostSPtrMem(host, type) \ (!DacHostPtrHasEnumMark(host) ? \ (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), \ type::DacSize(PTR_HOST_TO_TADDR(host))), \ true) : false) #define DacEnumHostVPtrMem(host) \ (!DacHostPtrHasEnumMark(host) ? \ (DacEnumMemoryRegion(PTR_HOST_TO_TADDR(host), (host)->VPtrSize()), \ true) : false) // Check enumeration of 'this' and return if this has already been // enumerated. Making this the first line of an object's EnumMemoryRegions // method will prevent cycles. #define DAC_CHECK_ENUM_THIS() \ if (DacHostPtrHasEnumMark(this)) return #define DAC_ENUM_DTHIS() \ if (!DacEnumHostDPtrMem(this)) return #define DAC_ENUM_STHIS(type) \ if (!DacEnumHostSPtrMem(this, type)) return #define DAC_ENUM_VTHIS() \ if (!DacEnumHostVPtrMem(this)) return #ifdef __cplusplus } class ReflectionModule; interface IMDInternalImport* DacGetMDImport(const class PEAssembly* pPEAssembly, bool throwEx); interface IMDInternalImport* DacGetMDImport(const ReflectionModule* reflectionModule, bool throwEx); int DacGetIlMethodSize(TADDR methAddr); struct COR_ILMETHOD* DacGetIlMethod(TADDR methAddr); #ifdef FEATURE_EH_FUNCLETS struct _UNWIND_INFO * DacGetUnwindInfo(TADDR taUnwindInfo); // virtually unwind a CONTEXT out-of-process struct _KNONVOLATILE_CONTEXT_POINTERS; BOOL DacUnwindStackFrame(T_CONTEXT * pContext, T_KNONVOLATILE_CONTEXT_POINTERS* pContextPointers); #endif // FEATURE_EH_FUNCLETS #if defined(TARGET_UNIX) // call back through data target to unwind out-of-process HRESULT DacVirtualUnwind(ULONG32 threadId, PT_CONTEXT context, PT_KNONVOLATILE_CONTEXT_POINTERS contextPointers); #endif // TARGET_UNIX #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS class SString; void DacMdCacheAddEEName(TADDR taEE, const SString& ssEEName); bool DacMdCacheGetEEName(TADDR taEE, SString & ssEEName); #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS // // Computes (taBase + (dwIndex * dwElementSize()), with overflow checks. // // Arguments: // taBase the base TADDR value // dwIndex the index of the offset // dwElementSize the size of each element (to multiply the offset by) // // Return value: // The resulting TADDR, or throws CORDB_E_TARGET_INCONSISTENT on overlow. // // Notes: // The idea here is that overflows during address arithmetic suggest that we're operating on corrupt // pointers. It helps to improve reliability to detect the cases we can (like overflow) and fail. Note // that this is just a heuristic, not a security measure. We can't trust target data regardless - // failing on overflow is just one easy case of corruption to detect. There is no need to use checked // arithmetic everywhere in the DAC infrastructure, this is intended just for the places most likely to // help catch bugs (eg. __DPtr::operator[]). // inline TADDR DacTAddrOffset( TADDR taBase, TSIZE_T dwIndex, TSIZE_T dwElementSize ) { ClrSafeInt t(taBase); t += ClrSafeInt(dwIndex) * ClrSafeInt(dwElementSize); if( t.IsOverflow() ) { // Pointer arithmetic overflow - probably due to corrupt target data DacError(CORDBG_E_TARGET_INCONSISTENT); } return t.Value(); } // Base pointer wrapper which provides common behavior. class __TPtrBase { public: __TPtrBase(void) { // Make uninitialized pointers obvious. m_addr = (TADDR)-1; } __TPtrBase(TADDR addr) { m_addr = addr; } bool operator!() const { return m_addr == 0; } // We'd like to have an implicit conversion to bool here since the C++ // standard says all pointer types are implicitly converted to bool. // Unfortunately, that would cause ambiguous overload errors for uses // of operator== and operator!=. Instead callers will have to compare // directly against NULL. bool operator==(TADDR addr) const { return m_addr == addr; } bool operator!=(TADDR addr) const { return m_addr != addr; } bool operator<(TADDR addr) const { return m_addr < addr; } bool operator>(TADDR addr) const { return m_addr > addr; } bool operator<=(TADDR addr) const { return m_addr <= addr; } bool operator>=(TADDR addr) const { return m_addr >= addr; } TADDR GetAddr(void) const { return m_addr; } TADDR SetAddr(TADDR addr) { m_addr = addr; return addr; } protected: TADDR m_addr; }; // Pointer wrapper base class for various forms of normal data. // This has the common functionality between __DPtr and __ArrayDPtr. // The DPtrType type parameter is the actual derived type in use. This is necessary so that // inhereted functions preserve exact return types. template class __DPtrBase : public __TPtrBase { public: typedef type _Type; typedef type* _Ptr; protected: // Constructors // All protected - this type should not be used directly - use one of the derived types instead. __DPtrBase< type, DPtrType >(void) : __TPtrBase() {} __DPtrBase< type, DPtrType >(TADDR addr) : __TPtrBase(addr) {} explicit __DPtrBase< type, DPtrType >(__TPtrBase addr) { m_addr = addr.GetAddr(); } explicit __DPtrBase< type, DPtrType >(type const * host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } public: DPtrType& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return DPtrType(m_addr); } DPtrType& operator=(TADDR addr) { m_addr = addr; return DPtrType(m_addr); } type& operator*(void) const { return *(type*)DacInstantiateTypeByAddress(m_addr, sizeof(type), true); } bool operator==(const DPtrType& ptr) const { return m_addr == ptr.GetAddr(); } bool operator==(TADDR addr) const { return m_addr == addr; } bool operator!=(const DPtrType& ptr) const { return !operator==(ptr); } bool operator!=(TADDR addr) const { return m_addr != addr; } bool operator<(const DPtrType& ptr) const { return m_addr < ptr.GetAddr(); } bool operator>(const DPtrType& ptr) const { return m_addr > ptr.GetAddr(); } bool operator<=(const DPtrType& ptr) const { return m_addr <= ptr.GetAddr(); } bool operator>=(const DPtrType& ptr) const { return m_addr >= ptr.GetAddr(); } // Array index operator // we want an operator[] for all possible numeric types (rather than rely on // implicit numeric conversions on the argument) to prevent ambiguity with // DPtr's implicit conversion to type* and the built-in operator[]. // @dbgtodo : we could also use this technique to simplify other operators below. template type& operator[](indexType index) { // Compute the address of the element. TADDR elementAddr; if( index >= 0 ) { elementAddr = DacTAddrOffset(m_addr, index, sizeof(type)); } else { // Don't bother trying to do overflow checking for negative indexes - they are rare compared to // positive ones. ClrSafeInt doesn't support signed datatypes yet (although we should be able to add it // pretty easily). elementAddr = m_addr + index * sizeof(type); } // Marshal over a single instance and return a reference to it. return *(type*) DacInstantiateTypeByAddress(elementAddr, sizeof(type), true); } template type const & operator[](indexType index) const { return (*const_cast<__DPtrBase*>(this))[index]; } //------------------------------------------------------------------------- // operator+ DPtrType operator+(unsigned short val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); } #if defined(HOST_UNIX) && defined(HOST_64BIT) DPtrType operator+(unsigned long long val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); } #endif // HOST_UNIX && HOST_BIT64 DPtrType operator+(short val) { return DPtrType(m_addr + val * sizeof(type)); } // size_t is unsigned int on Win32, so we need // to ifdef here to make sure the unsigned int // and size_t overloads don't collide. size_t // is marked __w64 so a simple unsigned int // will not work on Win32, it has to be size_t. DPtrType operator+(size_t val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); } #if defined (HOST_64BIT) DPtrType operator+(unsigned int val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); } #endif DPtrType operator+(int val) { return DPtrType(m_addr + val * sizeof(type)); } // Because of the size difference between long and int on non MS compilers, // we only need to define these operators on Windows. These provide compatible // overloads for DWORD addition operations. #ifdef _MSC_VER DPtrType operator+(unsigned long val) { return DPtrType(DacTAddrOffset(m_addr, val, sizeof(type))); } DPtrType operator+(long val) { return DPtrType(m_addr + val * sizeof(type)); } #endif //------------------------------------------------------------------------- // operator- DPtrType operator-(unsigned short val) { return DPtrType(m_addr - val * sizeof(type)); } DPtrType operator-(short val) { return DPtrType(m_addr - val * sizeof(type)); } // size_t is unsigned int on Win32, so we need // to ifdef here to make sure the unsigned int // and size_t overloads don't collide. size_t // is marked __w64 so a simple unsigned int // will not work on Win32, it has to be size_t. DPtrType operator-(size_t val) { return DPtrType(m_addr - val * sizeof(type)); } #ifdef HOST_64BIT DPtrType operator-(unsigned int val) { return DPtrType(m_addr - val * sizeof(type)); } #endif DPtrType operator-(int val) { return DPtrType(m_addr - val * sizeof(type)); } // Because of the size difference between long and int on non MS compilers, // we only need to define these operators on Windows. These provide compatible // overloads for DWORD addition operations. #ifdef _MSC_VER // for now, everything else is 32 bit DPtrType operator-(unsigned long val) { return DPtrType(m_addr - val * sizeof(type)); } DPtrType operator-(long val) { return DPtrType(m_addr - val * sizeof(type)); } #endif size_t operator-(const DPtrType& val) { return (m_addr - val.m_addr) / sizeof(type); } //------------------------------------------------------------------------- DPtrType& operator+=(size_t val) { m_addr += val * sizeof(type); return static_cast(*this); } DPtrType& operator-=(size_t val) { m_addr -= val * sizeof(type); return static_cast(*this); } DPtrType& operator++() { m_addr += sizeof(type); return static_cast(*this); } DPtrType& operator--() { m_addr -= sizeof(type); return static_cast(*this); } DPtrType operator++(int postfix) { DPtrType orig = DPtrType(*this); m_addr += sizeof(type); return orig; } DPtrType operator--(int postfix) { DPtrType orig = DPtrType(*this); m_addr -= sizeof(type); return orig; } bool IsValid(void) const { return m_addr && DacInstantiateTypeByAddress(m_addr, sizeof(type), false) != NULL; } void EnumMem(void) const { DacEnumMemoryRegion(m_addr, sizeof(type)); } }; // forward declaration template class __GlobalPtr; // Pointer wrapper for objects which are just plain data // and need no special handling. template class __DPtr : public __DPtrBase > { public: // constructors - all chain to __DPtrBase constructors __DPtr< type >(void) : __DPtrBase >() {} __DPtr< type >(TADDR addr) : __DPtrBase >(addr) {} // construct const from non-const typedef typename std::remove_const::type mutable_type; __DPtr< type >(__DPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} // construct from GlobalPtr explicit __DPtr< type >(__GlobalPtr< type*, __DPtr< type > > globalPtr) : __DPtrBase >(globalPtr.GetAddr()) {} explicit __DPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} explicit __DPtr< type >(type const * host) : __DPtrBase >(host) {} operator type*() const { return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true); } type* operator->() const { return (type*)DacInstantiateTypeByAddress(this->m_addr, sizeof(type), true); } }; #define DPTR(type) __DPtr< type > // A restricted form of DPtr that doesn't have any conversions to pointer types. // This is useful for pointer types that almost always represent arrays, as opposed // to pointers to single instances (eg. PTR_BYTE). In these cases, allowing implicit // conversions to (for eg.) BYTE* would usually result in incorrect usage (eg. pointer // arithmetic and array indexing), since only a single instance has been marshalled to the host. // If you really must marshal a single instance (eg. converting T* to PTR_T is too painful for now), // then use code:DacUnsafeMarshalSingleElement so we can identify such unsafe code. template class __ArrayDPtr : public __DPtrBase > { public: // constructors - all chain to __DPtrBase constructors __ArrayDPtr< type >(void) : __DPtrBase >() {} __ArrayDPtr< type >(TADDR addr) : __DPtrBase >(addr) {} // construct const from non-const typedef typename std::remove_const::type mutable_type; __ArrayDPtr< type >(__ArrayDPtr const & rhs) : __DPtrBase >(rhs.GetAddr()) {} explicit __ArrayDPtr< type >(__TPtrBase addr) : __DPtrBase >(addr) {} // Note that there is also no explicit constructor from host instances (type*). // Going this direction is less problematic, but often still represents risky coding. }; #define ArrayDPTR(type) __ArrayDPtr< type > // Pointer wrapper for objects which are just plain data // but whose size is not the same as the base type size. // This can be used for prefetching data for arrays or // for cases where an object has a variable size. template class __SPtr : public __TPtrBase { public: typedef type _Type; typedef type* _Ptr; __SPtr< type >(void) : __TPtrBase() {} __SPtr< type >(TADDR addr) : __TPtrBase(addr) {} explicit __SPtr< type >(__TPtrBase addr) { m_addr = addr.GetAddr(); } explicit __SPtr< type >(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } __SPtr< type >& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } __SPtr< type >& operator=(TADDR addr) { m_addr = addr; return *this; } operator type*() const { if (m_addr) { return (type*)DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr), true); } else { return (type*)NULL; } } type* operator->() const { if (m_addr) { return (type*)DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr), true); } else { return (type*)NULL; } } type& operator*(void) const { if (!m_addr) { DacError(E_INVALIDARG); } return *(type*)DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr), true); } bool IsValid(void) const { return m_addr && DacInstantiateTypeByAddress(m_addr, type::DacSize(m_addr), false) != NULL; } void EnumMem(void) const { if (m_addr) { DacEnumMemoryRegion(m_addr, type::DacSize(m_addr)); } } }; #define SPTR(type) __SPtr< type > // Pointer wrapper for objects which have a single leading // vtable, such as objects in a single-inheritance tree. // The base class of all such trees must have use // VPTR_BASE_VTABLE_CLASS in their declaration and all // instantiable members of the tree must be listed in vptr_list.h. template class __VPtr : public __TPtrBase { public: // VPtr::_Type has to be a pointer as // often the type is an abstract class. // This type is not expected to be used anyway. typedef type* _Type; typedef type* _Ptr; __VPtr< type >(void) : __TPtrBase() {} __VPtr< type >(TADDR addr) : __TPtrBase(addr) {} explicit __VPtr< type >(__TPtrBase addr) { m_addr = addr.GetAddr(); } explicit __VPtr< type >(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } __VPtr< type >& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } __VPtr< type >& operator=(TADDR addr) { m_addr = addr; return *this; } operator type*() const { return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true); } type* operator->() const { return (type*)DacInstantiateClassByVTable(m_addr, sizeof(type), true); } bool operator==(const __VPtr< type >& ptr) const { return m_addr == ptr.m_addr; } bool operator==(TADDR addr) const { return m_addr == addr; } bool operator!=(const __VPtr< type >& ptr) const { return !operator==(ptr); } bool operator!=(TADDR addr) const { return m_addr != addr; } bool IsValid(void) const { return m_addr && DacInstantiateClassByVTable(m_addr, sizeof(type), false) != NULL; } void EnumMem(void) const { if (IsValid()) { DacEnumMemoryRegion(m_addr, (operator->())->VPtrSize()); } } }; #define VPTR(type) __VPtr< type > // Pointer wrapper for 8-bit strings. template class __Str8Ptr : public __DPtr { public: typedef type _Type; typedef type* _Ptr; __Str8Ptr< type, maxChars >(void) : __DPtr() {} __Str8Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} explicit __Str8Ptr< type, maxChars >(__TPtrBase addr) { m_addr = addr.GetAddr(); } explicit __Str8Ptr< type, maxChars >(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } __Str8Ptr< type, maxChars >& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } __Str8Ptr< type, maxChars >& operator=(TADDR addr) { m_addr = addr; return *this; } operator type*() const { return (type*)DacInstantiateStringA(m_addr, maxChars, true); } bool IsValid(void) const { return m_addr && DacInstantiateStringA(m_addr, maxChars, false) != NULL; } void EnumMem(void) const { char* str = DacInstantiateStringA(m_addr, maxChars, false); if (str) { DacEnumMemoryRegion(m_addr, strlen(str) + 1); } } }; #define S8PTR(type) __Str8Ptr< type > #define S8PTRMAX(type, maxChars) __Str8Ptr< type, maxChars > // Pointer wrapper for 16-bit strings. template class __Str16Ptr : public __DPtr { public: typedef type _Type; typedef type* _Ptr; __Str16Ptr< type, maxChars >(void) : __DPtr() {} __Str16Ptr< type, maxChars >(TADDR addr) : __DPtr(addr) {} explicit __Str16Ptr< type, maxChars >(__TPtrBase addr) { m_addr = addr.GetAddr(); } explicit __Str16Ptr< type, maxChars >(type* host) { m_addr = DacGetTargetAddrForHostAddr(host, true); } __Str16Ptr< type, maxChars >& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } __Str16Ptr< type, maxChars >& operator=(TADDR addr) { m_addr = addr; return *this; } operator type*() const { return (type*)DacInstantiateStringW(m_addr, maxChars, true); } bool IsValid(void) const { return m_addr && DacInstantiateStringW(m_addr, maxChars, false) != NULL; } void EnumMem(void) const { char* str = DacInstantiateStringW(m_addr, maxChars, false); if (str) { DacEnumMemoryRegion(m_addr, strlen(str) + 1); } } }; #define S16PTR(type) __Str16Ptr< type > #define S16PTRMAX(type, maxChars) __Str16Ptr< type, maxChars > template class __GlobalVal { public: __GlobalVal< type >(TADDR DacGlobals::* ptr) { m_ptr = ptr; } operator type() const { return (type)*__DPtr< type >(DacGlobalValues()->*m_ptr); } __DPtr< type > operator&() const { return __DPtr< type >(DacGlobalValues()->*m_ptr); } // @dbgtodo dac support: This updates values in the host. This seems extremely dangerous // to do silently. I'd prefer that a specific (searchable) write function // was used. Try disabling this and see what fails... __GlobalVal & operator=(const type & val) { type* ptr = __DPtr< type >(DacGlobalValues()->*m_ptr); // Update the host copy; *ptr = val; // Write back to the target. DacWriteHostInstance(ptr, true); return *this; } bool IsValid(void) const { return __DPtr< type >(DacGlobalValues()->*m_ptr).IsValid(); } void EnumMem(void) const { TADDR p = DacGlobalValues()->*m_ptr; __DPtr< type >(p).EnumMem(); } private: TADDR DacGlobals::* m_ptr; }; template class __GlobalArray { public: __GlobalArray< type, size >(TADDR DacGlobals::* ptr) { m_ptr = ptr; } __DPtr< type > operator&() const { return __DPtr< type >(DacGlobalValues()->*m_ptr); } type& operator[](unsigned int index) const { return __DPtr< type >(DacGlobalValues()->*m_ptr)[index]; } bool IsValid(void) const { // Only validates the base pointer, not the full array range. return __DPtr< type >(DacGlobalValues()->*m_ptr).IsValid(); } void EnumMem(void) const { DacEnumMemoryRegion(DacGlobalValues()->*m_ptr, sizeof(type) * size); } private: TADDR DacGlobals::* m_ptr; }; template class __GlobalPtr { public: __GlobalPtr< acc_type, store_type >(TADDR DacGlobals::* ptr) { m_ptr = ptr; } __DPtr< store_type > operator&() const { return __DPtr< store_type >(DacGlobalValues()->*m_ptr); } store_type & operator=(store_type & val) { store_type* ptr = __DPtr< store_type >(DacGlobalValues()->*m_ptr); // Update the host copy; *ptr = val; // Write back to the target. DacWriteHostInstance(ptr, true); return val; } acc_type operator->() const { return (acc_type)*__DPtr< store_type >(DacGlobalValues()->*m_ptr); } operator acc_type() const { return (acc_type)*__DPtr< store_type >(DacGlobalValues()->*m_ptr); } operator store_type() const { return *__DPtr< store_type >(DacGlobalValues()->*m_ptr); } bool operator!() const { return !*__DPtr< store_type >(DacGlobalValues()->*m_ptr); } typename store_type::_Type& operator[](int index) { return (*__DPtr< store_type >(DacGlobalValues()->*m_ptr))[index]; } typename store_type::_Type& operator[](unsigned int index) { return (*__DPtr< store_type >(DacGlobalValues()->*m_ptr))[index]; } TADDR GetAddr() const { return (*__DPtr< store_type >(DacGlobalValues()->*m_ptr)).GetAddr(); } TADDR GetAddrRaw () const { return DacGlobalValues()->*m_ptr; } // This is only testing the pointer memory is available but does not verify // the memory that it points to. // bool IsValidPtr(void) const { return __DPtr< store_type >(DacGlobalValues()->*m_ptr).IsValid(); } bool IsValid(void) const { return __DPtr< store_type >(DacGlobalValues()->*m_ptr).IsValid() && (*__DPtr< store_type >(DacGlobalValues()->*m_ptr)).IsValid(); } void EnumMem(void) const { __DPtr< store_type > ptr(DacGlobalValues()->*m_ptr); ptr.EnumMem(); if (ptr.IsValid()) { (*ptr).EnumMem(); } } TADDR DacGlobals::* m_ptr; }; template inline bool operator==(const __GlobalPtr& gptr, acc_type host) { return DacGetTargetAddrForHostAddr(host, true) == *__DPtr< TADDR >(DacGlobalValues()->*gptr.m_ptr); } template inline bool operator!=(const __GlobalPtr& gptr, acc_type host) { return !operator==(gptr, host); } template inline bool operator==(acc_type host, const __GlobalPtr& gptr) { return DacGetTargetAddrForHostAddr(host, true) == *__DPtr< TADDR >(DacGlobalValues()->*gptr.m_ptr); } template inline bool operator!=(acc_type host, const __GlobalPtr& gptr) { return !operator==(host, gptr); } // // __VoidPtr is a type that behaves like void* but for target pointers. // Behavior of PTR_VOID: // * has void* semantics. Will compile to void* in non-DAC builds (just like // other PTR types. Unlike TADDR, we want pointer semantics. // * NOT assignable from host pointer types or convertible to host pointer // types - ensures we can't confuse host and target pointers (we'll get // compiler errors if we try and cast between them). // * like void*, no pointer arithmetic or dereferencing is allowed // * like TADDR, can be used to construct any __DPtr / __VPtr instance // * representation is the same as a void* (for marshalling / casting) // // One way in which __VoidPtr is unlike void* is that it can't be cast to // pointer or integer types. On the one hand, this is a good thing as it forces // us to keep target pointers separate from other data types. On the other hand // in practice this means we have to use dac_cast in places where we used // to use a (TADDR) cast. Unfortunately C++ provides us no way to allow the // explicit cast to primitive types without also allowing implicit conversions. // // This is very similar in spirit to TADDR. The primary difference is that // PTR_VOID has pointer semantics, where TADDR has integer semantics. When // dacizing uses of void* to TADDR, casts must be inserted everywhere back to // pointer types. If we switch a use of TADDR to PTR_VOID, those casts in // DACCESS_COMPILE regions no longer compile (see above). Also, TADDR supports // pointer arithmetic, but that might not be necessary (could use PTR_BYTE // instead etc.). Ideally we'd probably have just one type for this purpose // (named TADDR but with the semantics of PTR_VOID), but outright conversion // would require too much work. // class __VoidPtr : public __TPtrBase { public: __VoidPtr(void) : __TPtrBase() {} __VoidPtr(TADDR addr) : __TPtrBase(addr) {} // Note, unlike __DPtr, this ctor form is not explicit. We allow implicit // conversions from any pointer type (just like for void*). __VoidPtr(__TPtrBase addr) { m_addr = addr.GetAddr(); } // Like TPtrBase, VoidPtrs can also be created impicitly from all GlobalPtrs template __VoidPtr(__GlobalPtr globalPtr) { m_addr = globalPtr.GetAddr(); } // Note, unlike __DPtr, there is no explicit conversion from host pointer // types. Since void* cannot be marshalled, there is no such thing as // a void* DAC instance in the host. // Also, we don't want an implicit conversion to TADDR because then the // compiler will allow pointer arithmetic (which it wouldn't allow for // void*). Instead, callers can use dac_cast if they want. // Note, unlike __DPtr, any pointer type can be assigned to a __VoidPtr // This is to mirror the assignability of any pointer type to a void* __VoidPtr& operator=(const __TPtrBase& ptr) { m_addr = ptr.GetAddr(); return *this; } __VoidPtr& operator=(TADDR addr) { m_addr = addr; return *this; } // note, no marshalling operators (type* conversion, operator ->, operator*) // A void* can't be marshalled because we don't know how much to copy // PTR_Void can be compared to any other pointer type (because conceptually, // any other pointer type should be implicitly convertible to void*) bool operator==(const __TPtrBase& ptr) const { return m_addr == ptr.GetAddr(); } bool operator==(TADDR addr) const { return m_addr == addr; } bool operator!=(const __TPtrBase& ptr) const { return !operator==(ptr); } bool operator!=(TADDR addr) const { return m_addr != addr; } bool operator<(const __TPtrBase& ptr) const { return m_addr < ptr.GetAddr(); } bool operator>(const __TPtrBase& ptr) const { return m_addr > ptr.GetAddr(); } bool operator<=(const __TPtrBase& ptr) const { return m_addr <= ptr.GetAddr(); } bool operator>=(const __TPtrBase& ptr) const { return m_addr >= ptr.GetAddr(); } }; typedef __VoidPtr PTR_VOID; typedef DPTR(PTR_VOID) PTR_PTR_VOID; // For now we treat pointers to const and non-const void the same in DAC // builds. In general, DAC is read-only anyway and so there isn't a danger of // writing to these pointers. Also, the non-dac builds will ensure // const-correctness. However, if we wanted to support true void* / const void* // behavior, we could probably build the follow functionality by templating // __VoidPtr: // * A PTR_VOID would be implicitly convertible to PTR_CVOID // * An explicit coercion (ideally const_cast) would be required to convert a // PTR_CVOID to a PTR_VOID // * Similarily, an explicit coercion would be required to convert a cost PTR // type (eg. PTR_CBYTE) to a PTR_VOID. typedef __VoidPtr PTR_CVOID; // The special empty ctor declared here allows the whole // class hierarchy to be instantiated easily by the // external access code. The actual class body will be // read externally so no members should be initialized. // // VPTR_ANY_CLASS_METHODS - Defines the following methods for all VPTR classes // // VPtrSize // Returns the size of the dynamic type of the object (as opposed to sizeof // which is based only on the static type). // // VPtrHostVTable // Returns the address of the vtable for this type. // We create a temporary instance of this type in order to read it's vtable pointer // (at offset 0). For this temporary instance, we do not want to initialize any fields, // so we use the marshalling ctor. Since we didn't initialize any fields, we also don't // wan't to run the dtor (marshaled data structures don't normally expect their destructor // or non-DAC constructors to be called in DAC builds anyway). So, rather than create a // normal stack object, or put the object on the heap, we create the temporary object // on the stack using placement-new and alloca, and don't destruct it. // #define VPTR_ANY_CLASS_METHODS(name) \ virtual ULONG32 VPtrSize(void) { SUPPORTS_DAC; return sizeof(name); } \ static PVOID VPtrHostVTable() { \ void * pBuf = _alloca(sizeof(name)); \ name * dummy = new (pBuf) name((TADDR)0, (TADDR)0); \ return *((PVOID*)dummy); } #define VPTR_CLASS_METHODS(name) \ VPTR_ANY_CLASS_METHODS(name) \ static TADDR VPtrTargetVTable() { \ SUPPORTS_DAC; \ return DacGlobalValues()->name##__vtAddr; } #define VPTR_VTABLE_CLASS(name, base) \ public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} \ VPTR_CLASS_METHODS(name) #define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \ VPTR_VTABLE_CLASS(name, base) // Used for base classes that can be instantiated directly. // The fake vfn is still used to force a vtable even when // all the normal vfns are ifdef'ed out. #define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \ public: name(TADDR addr, TADDR vtAddr) {} \ VPTR_CLASS_METHODS(name) #define VPTR_BASE_CONCRETE_VTABLE_CLASS_NO_CTOR_BODY(name) \ public: name(TADDR addr, TADDR vtAddr); \ VPTR_CLASS_METHODS(name) // The pure virtual method forces all derivations to use // VPTR_VTABLE_CLASS to compile. #define VPTR_BASE_VTABLE_CLASS(name) \ public: name(TADDR addr, TADDR vtAddr) {} \ virtual ULONG32 VPtrSize(void) = 0; #define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \ VPTR_BASE_VTABLE_CLASS(name) #define VPTR_BASE_VTABLE_CLASS_NO_CTOR_BODY(name) \ public: name(TADDR addr, TADDR vtAddr); \ virtual ULONG32 VPtrSize(void) = 0; #define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ public: name(TADDR addr, TADDR vtAddr) : base(addr, vtAddr) {} #define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) \ VPTR_ABSTRACT_VTABLE_CLASS(name, base) #define VPTR_ABSTRACT_VTABLE_CLASS_NO_CTOR_BODY(name, base) \ public: name(TADDR addr, TADDR vtAddr); // helper macro to make the vtables unique for DAC #define VPTR_UNIQUE(unique) // Safe access for retrieving the target address of a PTR. #define PTR_TO_TADDR(ptr) ((ptr).GetAddr()) #define GFN_TADDR(name) (DacGlobalValues()->fn__ ## name) #define GVAL_ADDR(g) \ ((g).operator&()) // // References to class static and global data. // These all need to be redirected through the global // data table. // #define _SPTR_DECL(acc_type, store_type, var) \ static __GlobalPtr< acc_type, store_type > var #define _SPTR_IMPL(acc_type, store_type, cls, var) \ __GlobalPtr< acc_type, store_type > cls::var(&DacGlobals::cls##__##var) #define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \ __GlobalPtr< acc_type, store_type > cls::var(&DacGlobals::cls##__##var) #define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \ __GlobalPtr< acc_type, store_type > cls::var(&DacGlobals::ns##__##cls##__##var) #define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \ __GlobalPtr< acc_type, store_type > cls::var(&DacGlobals::ns##__##cls##__##var) #define VOLATILE_SPTR_DECL(type, var) SPTR_DECL(type, var) #define VOLATILE_SPTR_IMPL(type, cls, var) SPTR_IMPL(type, cls, var) #define VOLATILE_SPTR_IMPL_INIT(type, cls, var, init) SPTR_IMPL_INIT(type, cls, var, init) #define _GPTR_DECL(acc_type, store_type, var) \ extern __GlobalPtr< acc_type, store_type > var #define _GPTR_IMPL(acc_type, store_type, var) \ __GlobalPtr< acc_type, store_type > var(&DacGlobals::dac__##var) #define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \ __GlobalPtr< acc_type, store_type > var(&DacGlobals::dac__##var) #define SVAL_DECL(type, var) \ static __GlobalVal< type > var #define SVAL_IMPL(type, cls, var) \ __GlobalVal< type > cls::var(&DacGlobals::cls##__##var) #define SVAL_IMPL_INIT(type, cls, var, init) \ __GlobalVal< type > cls::var(&DacGlobals::cls##__##var) #define SVAL_IMPL_NS(type, ns, cls, var) \ __GlobalVal< type > cls::var(&DacGlobals::ns##__##cls##__##var) #define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \ __GlobalVal< type > cls::var(&DacGlobals::ns##__##cls##__##var) #define VOLATILE_SVAL_DECL(type, var) SVAL_DECL(type, var) #define VOLATILE_SVAL_IMPL(type, cls, var) SVAL_IMPL(type, cls, var) #define VOLATILE_SVAL_IMPL_INIT(type, cls, var, init) SVAL_IMPL_INIT(type, cls, var, init) #define GVAL_DECL(type, var) \ extern __GlobalVal< type > var #define GVAL_IMPL(type, var) \ __GlobalVal< type > var(&DacGlobals::dac__##var) #define GVAL_IMPL_INIT(type, var, init) \ __GlobalVal< type > var(&DacGlobals::dac__##var) #define GARY_DECL(type, var, size) \ extern __GlobalArray< type, size > var #define GARY_IMPL(type, var, size) \ __GlobalArray< type, size > var(&DacGlobals::dac__##var) // Translation from a host pointer back to the target address // that was used to retrieve the data for the host pointer. #define PTR_HOST_TO_TADDR(host) DacGetTargetAddrForHostAddr(host, true) // Translation from a host interior pointer back to the corresponding // target address. The host address must reside within a previously // retrieved instance. #define PTR_HOST_INT_TO_TADDR(host) DacGetTargetAddrForHostInteriorAddr(host, true) // Translation from a host vtable pointer to a target vtable pointer. #define VPTR_HOST_VTABLE_TO_TADDR(host) DacGetTargetVtForHostVt(host, true) // Construct a pointer to a member of the given type. #define PTR_HOST_MEMBER_TADDR(type, host, memb) \ (PTR_HOST_TO_TADDR(host) + (TADDR)offsetof(type, memb)) // Construct a pointer to a member of the given type given an interior // host address. #define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) \ (PTR_HOST_INT_TO_TADDR(host) + (TADDR)offsetof(type, memb)) #define PTR_TO_MEMBER_TADDR(type, ptr, memb) \ (PTR_TO_TADDR(ptr) + (TADDR)offsetof(type, memb)) // Constructs an arbitrary data instance for a piece of // memory in the target. #define PTR_READ(addr, size) \ DacInstantiateTypeByAddress(addr, size, true) // This value is used to intiailize target pointers to NULL. We want this to be TADDR type // (as opposed to, say, __TPtrBase) so that it can be used in the non-explicit ctor overloads, // eg. as an argument default value. // We can't always just use NULL because that's 0 which (in C++) can be any integer or pointer // type (causing an ambiguous overload compiler error when used in explicit ctor forms). #define PTR_NULL ((TADDR)0) // Provides an empty method implementation when compiled // for DACCESS_COMPILE. For example, use to stub out methods needed // for vtable entries but otherwise unused. // Note that these functions are explicitly NOT marked SUPPORTS_DAC so that we'll get a // DacCop warning if any calls to them are detected. // @dbgtodo : It's probably almost always wrong to call any such function, so // we should probably throw a better error (DacNotImpl), and ideally mark the function // DECLSPEC_NORETURN so we don't have to deal with fabricating return values and we can // get compiler warnings (unreachable code) anytime functions marked this way are called. #define DAC_EMPTY() { LIMITED_METHOD_CONTRACT; } #define DAC_EMPTY_ERR() { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); } #define DAC_EMPTY_RET(retVal) { LIMITED_METHOD_CONTRACT; DacError(E_UNEXPECTED); return retVal; } #define DAC_UNEXPECTED() { LIMITED_METHOD_CONTRACT; DacError_NoRet(E_UNEXPECTED); } #endif // #ifdef __cplusplus // Implementation details for dac_cast, should never be accessed directly. // See code:dac_cast for details and discussion. namespace dac_imp { // Helper functions to get the target address of specific types inline TADDR getTaddr(TADDR addr) { return addr; } inline TADDR getTaddr(__TPtrBase const &tptr) { return PTR_TO_TADDR(tptr); } inline TADDR getTaddr(void const * host) { return PTR_HOST_TO_TADDR((void *)host); } template inline TADDR getTaddr(__GlobalPtr const &gptr) { return PTR_TO_TADDR(gptr); } // It is an error to try dac_cast on a __GlobalVal or a __GlobalArray. Declare // but do not define the methods so that a compile-time error results. template TADDR getTaddr(__GlobalVal const &gval); template TADDR getTaddr(__GlobalArray const &garr); // Helper class to instantiate DAC instances from a TADDR // The default implementation assumes we want to create an instance of a PTR type template struct makeDacInst { static inline T fromTaddr(TADDR addr) { static_assert((std::is_base_of<__TPtrBase, T>::value), "is_base_of constraint violation"); return T(addr); } }; // Partial specialization for creating TADDRs // This is the only other way to create a DAC type instance other than PTR types (above) template<> struct makeDacInst { static inline TADDR fromTaddr(TADDR addr) { return addr; } }; } // namespace dac_imp // DacCop in-line exclusion mechanism // Warnings - official home is DacCop\Shared\Warnings.cs, but we want a way for users to indicate // warning codes in a way that is descriptive to readers (not just code numbers). The names here // don't matter - DacCop just looks at the value enum DacCopWarningCode { // General Rules FieldAccess = 1, PointerArith = 2, PointerComparison = 3, InconsistentMarshalling = 4, CastBetweenAddressSpaces = 5, CastOfMarshalledType = 6, VirtualCallToNonVPtr = 7, UndacizedGlobalVariable = 8, // Function graph related CallUnknown = 701, CallNonDac = 702, CallVirtualUnknown = 704, CallVirtualNonDac = 705, }; // DACCOP_IGNORE is a mechanism to suppress DacCop violations from within the source-code. // See the DacCop wiki for guidance on how best to use this: http://mswikis/clr/dev/Pages/DacCop.aspx // // DACCOP_IGNORE will suppress a DacCop violation for the following (non-compound) statement. // For example: // // The "dual-mode DAC problem" occurs in a few places where a class is used both // // in the host, and marshalled from the target ... // DACCOP_IGNORE(CastBetweenAddressSpaces,"SBuffer has the dual-mode DAC problem"); // TADDR bufAddr = (TADDR)m_buffer; // // A call to DACCOP_IGNORE must occur as it's own statement, and can apply only to following // single-statements (not to compound statement blocks). Occasionally it is necessary to hoist // violation-inducing code out to its own statement (e.g., if it occurs in the conditional of an // if). // // Arguments: // code: a literal value from DacCopWarningCode indicating which violation should be suppressed. // szReasonString: a short description of why this exclusion is necessary. This is intended just // to help readers of the code understand the source of the problem, and what would be required // to fix it. More details can be provided in comments if desired. // inline void DACCOP_IGNORE(DacCopWarningCode code, const char * szReasonString) { // DacCop detects calls to this function. No implementation is necessary. } #else // #ifdef DACCESS_COMPILE // // This version of the macros turns into normal pointers // for unmodified in-proc compilation. // ******************************************************* // !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!! // // Please search this file for the type name to find the // DAC versions of these definitions // // !!!!!!!!!!!!!!!!!!!!!!!!!NOTE!!!!!!!!!!!!!!!!!!!!!!!!!! // ******************************************************* // Declare TADDR as a non-pointer type so that arithmetic // can be done on it directly, as with the DACCESS_COMPILE definition. // This also helps expose pointer usage that may need to be changed. typedef ULONG_PTR TADDR; typedef void* PTR_VOID; typedef LPVOID* PTR_PTR_VOID; typedef const void* PTR_CVOID; #define DPTR(type) type* #define ArrayDPTR(type) type* #define SPTR(type) type* #define VPTR(type) type* #define S8PTR(type) type* #define S8PTRMAX(type, maxChars) type* #define S16PTR(type) type* #define S16PTRMAX(type, maxChars) type* #if defined(TARGET_UNIX) #define VPTR_VTABLE_CLASS(name, base) \ friend struct _DacGlobals; \ public: name(int dummy) : base(dummy) {} #define VPTR_VTABLE_CLASS_AND_CTOR(name, base) \ VPTR_VTABLE_CLASS(name, base) \ name() : base() {} #define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) \ friend struct _DacGlobals; \ public: name(int dummy) {} #define VPTR_BASE_VTABLE_CLASS(name) \ friend struct _DacGlobals; \ public: name(int dummy) {} #define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) \ VPTR_BASE_VTABLE_CLASS(name) \ name() {} #define VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ friend struct _DacGlobals; \ public: name(int dummy) : base(dummy) {} #define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) \ VPTR_ABSTRACT_VTABLE_CLASS(name, base) \ name() : base() {} #else // TARGET_UNIX #define VPTR_VTABLE_CLASS(name, base) friend struct _DacGlobals; #define VPTR_VTABLE_CLASS_AND_CTOR(name, base) #define VPTR_BASE_CONCRETE_VTABLE_CLASS(name) friend struct _DacGlobals; #define VPTR_BASE_VTABLE_CLASS(name) friend struct _DacGlobals; #define VPTR_BASE_VTABLE_CLASS_AND_CTOR(name) #define VPTR_ABSTRACT_VTABLE_CLASS(name, base) friend struct _DacGlobals; #define VPTR_ABSTRACT_VTABLE_CLASS_AND_CTOR(name, base) #endif // TARGET_UNIX // helper macro to make the vtables unique for DAC #define VPTR_UNIQUE(unique) virtual int MakeVTableUniqueForDAC() { return unique; } #define VPTR_UNIQUE_BaseDomain (100000) #define VPTR_UNIQUE_SystemDomain (VPTR_UNIQUE_BaseDomain + 1) #define VPTR_UNIQUE_ComMethodFrame (VPTR_UNIQUE_SystemDomain + 1) #define VPTR_UNIQUE_RedirectedThreadFrame (VPTR_UNIQUE_ComMethodFrame + 1) #define VPTR_UNIQUE_HijackFrame (VPTR_UNIQUE_RedirectedThreadFrame + 1) #define PTR_TO_TADDR(ptr) ((TADDR)(ptr)) #define GFN_TADDR(name) ((TADDR)(name)) #define GVAL_ADDR(g) (&(g)) #define _SPTR_DECL(acc_type, store_type, var) \ static store_type var #define _SPTR_IMPL(acc_type, store_type, cls, var) \ store_type cls::var #define _SPTR_IMPL_INIT(acc_type, store_type, cls, var, init) \ store_type cls::var = init #define _SPTR_IMPL_NS(acc_type, store_type, ns, cls, var) \ store_type cls::var #define _SPTR_IMPL_NS_INIT(acc_type, store_type, ns, cls, var, init) \ store_type cls::var = init #define VOLATILE_SPTR_DECL(type, var) _SPTR_DECL(type*, Volatile, var) #define VOLATILE_SPTR_IMPL(type, cls, var) _SPTR_IMPL(type*, Volatile, cls, var) #define VOLATILE_SPTR_IMPL_INIT(type, cls, var, init) _SPTR_IMPL_INIT(type*, Volatile, cls, var, init) #define _GPTR_DECL(acc_type, store_type, var) \ extern store_type var #define _GPTR_IMPL(acc_type, store_type, var) \ store_type var #define _GPTR_IMPL_INIT(acc_type, store_type, var, init) \ store_type var = init #define SVAL_DECL(type, var) \ static type var #define SVAL_IMPL(type, cls, var) \ type cls::var #define SVAL_IMPL_INIT(type, cls, var, init) \ type cls::var = init #define VOLATILE_SVAL_DECL(type, var) \ static Volatile var #define VOLATILE_SVAL_IMPL(type, cls, var) \ Volatile cls::var #define VOLATILE_SVAL_IMPL_INIT(type, cls, var, init) \ Volatile cls::var = init #define SVAL_IMPL_NS(type, ns, cls, var) \ type cls::var #define SVAL_IMPL_NS_INIT(type, ns, cls, var, init) \ type cls::var = init #define GVAL_DECL(type, var) \ extern type var #define GVAL_IMPL(type, var) \ type var #define GVAL_IMPL_INIT(type, var, init) \ type var = init #define GARY_DECL(type, var, size) \ extern type var[size] #define GARY_IMPL(type, var, size) \ type var[size] #define PTR_HOST_TO_TADDR(host) ((TADDR)(host)) #define PTR_HOST_INT_TO_TADDR(host) ((TADDR)(host)) #define VPTR_HOST_VTABLE_TO_TADDR(host) ((TADDR)(host)) #define PTR_HOST_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb) #define PTR_HOST_INT_MEMBER_TADDR(type, host, memb) ((TADDR)&(host)->memb) #define PTR_TO_MEMBER_TADDR(type, ptr, memb) ((TADDR)&((ptr)->memb)) #define PTR_READ(addr, size) ((PVOID)(addr)) #define PTR_NULL NULL #define DAC_EMPTY() #define DAC_EMPTY_ERR() #define DAC_EMPTY_RET(retVal) #define DAC_UNEXPECTED() #define DACCOP_IGNORE(warningCode, reasonString) #endif // #ifdef DACCESS_COMPILE //---------------------------------------------------------------------------- // dac_cast // Casting utility, to be used for casting one class pointer type to another. // Use as you would use static_cast // // dac_cast is designed to act just as static_cast does when // dealing with pointers and their DAC abstractions. Specifically, // it handles these coversions: // // dac_cast(SourceTypeVal) // // where TargetType <- SourceTypeVal are // // ?PTR(Tgt) <- TADDR - Create PTR type (DPtr etc.) from TADDR // ?PTR(Tgt) <- ?PTR(Src) - Convert one PTR type to another // ?PTR(Tgt) <- Src * - Create PTR type from dac host object instance // TADDR <- ?PTR(Src) - Get TADDR of PTR object (DPtr etc.) // TADDR <- Src * - Get TADDR of dac host object instance // // Note that there is no direct conversion to other host-pointer types (because we don't // know if you want a DPTR or VPTR etc.). However, due to the implicit DAC conversions, // you can just use dac_cast and assign that to a Foo*. // // The beauty of this syntax is that it is consistent regardless // of source and target casting types. You just use dac_cast // and the partial template specialization will do the right thing. // // One important thing to realise is that all "Foo *" types are // assumed to be pointers to host instances that were marshalled by DAC. This should // fail at runtime if it's not the case. // // Some examples would be: // // - Host pointer of one type to a related host pointer of another // type, i.e., MethodDesc * <-> InstantiatedMethodDesc * // Syntax: with MethodDesc *pMD, InstantiatedMethodDesc *pInstMD // pInstMd = dac_cast(pMD) // pMD = dac_cast(pInstMD) // // - (D|V)PTR of one encapsulated pointer type to a (D|V)PTR of // another type, i.e., PTR_AppDomain <-> PTR_BaseDomain // Syntax: with PTR_AppDomain pAD, PTR_BaseDomain pBD // dac_cast(pBD) // dac_cast(pAD) // // Example comparisons of some old and new syntax, where // h is a host pointer, such as "Foo *h;" // p is a DPTR, such as "PTR_Foo p;" // // PTR_HOST_TO_TADDR(h) ==> dac_cast(h) // PTR_TO_TADDR(p) ==> dac_cast(p) // PTR_Foo(PTR_HOST_TO_TADDR(h)) ==> dac_cast(h) // //---------------------------------------------------------------------------- template inline Tgt dac_cast(Src src) { #ifdef DACCESS_COMPILE // In DAC builds, first get a TADDR for the source, then create the // appropriate destination instance. TADDR addr = dac_imp::getTaddr(src); return dac_imp::makeDacInst::fromTaddr(addr); #else // In non-DAC builds, dac_cast is the same as a C-style cast because we need to support: // - casting away const // - conversions between pointers and TADDR // Perhaps we should more precisely restrict it's usage, but we get the precise // restrictions in DAC builds, so it wouldn't buy us much. return (Tgt)(src); #endif } //---------------------------------------------------------------------------- // // Convenience macros which work for either mode. // //---------------------------------------------------------------------------- #define SPTR_DECL(type, var) _SPTR_DECL(type*, PTR_##type, var) #define SPTR_IMPL(type, cls, var) _SPTR_IMPL(type*, PTR_##type, cls, var) #define SPTR_IMPL_INIT(type, cls, var, init) _SPTR_IMPL_INIT(type*, PTR_##type, cls, var, init) #define SPTR_IMPL_NS(type, ns, cls, var) _SPTR_IMPL_NS(type*, PTR_##type, ns, cls, var) #define SPTR_IMPL_NS_INIT(type, ns, cls, var, init) _SPTR_IMPL_NS_INIT(type*, PTR_##type, ns, cls, var, init) #define GPTR_DECL(type, var) _GPTR_DECL(type*, PTR_##type, var) #define GPTR_IMPL(type, var) _GPTR_IMPL(type*, PTR_##type, var) #define GPTR_IMPL_INIT(type, var, init) _GPTR_IMPL_INIT(type*, PTR_##type, var, init) // If you want to marshal a single instance of an ArrayDPtr over to the host and // return a pointer to it, you can use this function. However, this is unsafe because // users of value may assume they can do pointer arithmetic on it. This is exactly // the bugs ArrayDPtr is designed to prevent. See code:__ArrayDPtr for details. template inline type* DacUnsafeMarshalSingleElement( ArrayDPTR(type) arrayPtr ) { return (DPTR(type))(arrayPtr); } //---------------------------------------------------------------------------- // // Forward typedefs for system types. This is a convenient place // to declare things for system types, plus it gives us a central // place to look at when deciding what types may cause issues for // cross-platform compilation. // //---------------------------------------------------------------------------- typedef ArrayDPTR(BYTE) PTR_BYTE; typedef ArrayDPTR(uint8_t) PTR_uint8_t; typedef DPTR(PTR_BYTE) PTR_PTR_BYTE; typedef DPTR(PTR_uint8_t) PTR_PTR_uint8_t; typedef DPTR(PTR_PTR_BYTE) PTR_PTR_PTR_BYTE; typedef ArrayDPTR(signed char) PTR_SBYTE; typedef ArrayDPTR(const BYTE) PTR_CBYTE; typedef DPTR(INT8) PTR_INT8; typedef DPTR(INT16) PTR_INT16; typedef DPTR(UINT16) PTR_UINT16; typedef DPTR(WORD) PTR_WORD; typedef DPTR(USHORT) PTR_USHORT; typedef DPTR(DWORD) PTR_DWORD; typedef DPTR(uint32_t) PTR_uint32_t; typedef DPTR(LONG) PTR_LONG; typedef DPTR(ULONG) PTR_ULONG; typedef DPTR(INT32) PTR_INT32; typedef DPTR(UINT32) PTR_UINT32; typedef DPTR(ULONG64) PTR_ULONG64; typedef DPTR(INT64) PTR_INT64; typedef DPTR(UINT64) PTR_UINT64; typedef DPTR(SIZE_T) PTR_SIZE_T; typedef DPTR(size_t) PTR_size_t; typedef DPTR(TADDR) PTR_TADDR; typedef DPTR(int) PTR_int; typedef DPTR(BOOL) PTR_BOOL; typedef DPTR(unsigned) PTR_unsigned; typedef S8PTR(char) PTR_STR; typedef S8PTR(const char) PTR_CSTR; typedef S8PTR(char) PTR_UTF8; typedef S8PTR(const char) PTR_CUTF8; typedef S16PTR(WCHAR) PTR_WSTR; typedef S16PTR(const WCHAR) PTR_CWSTR; typedef DPTR(T_CONTEXT) PTR_CONTEXT; typedef DPTR(PTR_CONTEXT) PTR_PTR_CONTEXT; typedef DPTR(struct _EXCEPTION_POINTERS) PTR_EXCEPTION_POINTERS; typedef DPTR(struct _EXCEPTION_RECORD) PTR_EXCEPTION_RECORD; typedef DPTR(struct _EXCEPTION_REGISTRATION_RECORD) PTR_EXCEPTION_REGISTRATION_RECORD; typedef DPTR(struct IMAGE_COR_VTABLEFIXUP) PTR_IMAGE_COR_VTABLEFIXUP; typedef DPTR(IMAGE_DATA_DIRECTORY) PTR_IMAGE_DATA_DIRECTORY; typedef DPTR(IMAGE_DEBUG_DIRECTORY) PTR_IMAGE_DEBUG_DIRECTORY; typedef DPTR(IMAGE_DOS_HEADER) PTR_IMAGE_DOS_HEADER; typedef DPTR(IMAGE_NT_HEADERS) PTR_IMAGE_NT_HEADERS; typedef DPTR(IMAGE_NT_HEADERS32) PTR_IMAGE_NT_HEADERS32; typedef DPTR(IMAGE_NT_HEADERS64) PTR_IMAGE_NT_HEADERS64; typedef DPTR(IMAGE_SECTION_HEADER) PTR_IMAGE_SECTION_HEADER; typedef DPTR(IMAGE_EXPORT_DIRECTORY) PTR_IMAGE_EXPORT_DIRECTORY; typedef DPTR(IMAGE_TLS_DIRECTORY) PTR_IMAGE_TLS_DIRECTORY; #if defined(DACCESS_COMPILE) #include #include #include #endif #if defined(TARGET_X86) && defined(TARGET_UNIX) typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO; #endif #ifdef TARGET_64BIT typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; typedef DPTR(struct _UNWIND_INFO) PTR_UNWIND_INFO; #if defined(TARGET_AMD64) typedef DPTR(union _UNWIND_CODE) PTR_UNWIND_CODE; #endif // TARGET_AMD64 #endif // TARGET_64BIT #ifdef TARGET_ARM typedef DPTR(T_RUNTIME_FUNCTION) PTR_RUNTIME_FUNCTION; #endif //---------------------------------------------------------------------------- // // A PCODE is a valid PC/IP value -- a pointer to an instruction, possibly including some processor mode bits. // (On ARM, for example, a PCODE value should have the low-order THUMB_CODE bit set if the code should // be executed in that mode.) // typedef TADDR PCODE; typedef DPTR(PCODE) PTR_PCODE; typedef DPTR(PTR_PCODE) PTR_PTR_PCODE; // There is another concept we should have, "pointer to the start of an instruction" -- a PCODE with any mode bits masked off. // Attempts to introduce this concept, and classify uses of PCODE as one or the other, // turned out to be too hard: either name choice required *many* code changes, and decisions in unfamiliar code. So despite the // the comment above, the PCODE is currently sometimes used for the PINSTR concept. // See PCODEToPINSTR in utilcode.h for conversion from PCODE to PINSTR. //---------------------------------------------------------------------------- // // The access code compile must compile data structures that exactly // match the real structures for access to work. The access code // doesn't want all of the debugging validation code, though, so // distinguish between _DEBUG, for declaring general debugging data // and always-on debug code, and _DEBUG_IMPL, for debugging code // which will be disabled when compiling for external access. // //---------------------------------------------------------------------------- #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif // Helper macro for tracking EnumMemoryRegions progress. #if 0 #define EMEM_OUT(args) DacLogMessage args #else #define EMEM_OUT(args) #endif // Macros like MAIN_CLR_MODULE_NAME* for the DAC module #define MAIN_DAC_MODULE_NAME_W W("mscordaccore") #define MAIN_DAC_MODULE_DLL_NAME_W W("mscordaccore.dll") // TARGET_CONSISTENCY_CHECK represents a condition that should not fail unless the DAC target is corrupt. // This is in contrast to ASSERTs in DAC infrastructure code which shouldn't fail regardless of the memory // read from the target. At the moment we treat these the same, but in the future we will want a mechanism // for disabling just the target consistency checks (eg. for tests that intentionally use corrupted targets). // @dbgtodo : Separating asserts and target consistency checks is tracked by DevDiv Bugs 31674 #define TARGET_CONSISTENCY_CHECK(expr,msg) _ASSERTE_MSG(expr,msg) // For cross compilation, controlling type layout is important // We add a simple macro here which defines DAC_ALIGNAS to the C++11 alignas operator // This helps force the alignment of the next member // For most cross compilation cases the layout of types simply works // There are a few cases (where this macro is helpful) which are not consistent across platforms: // - Base class whose size is padded to its align size. On Linux the gcc/clang // layouts will reuse this padding in the derived class for the first member // - Class with an vtable pointer and an alignment greater than the pointer size. // The Windows compilers will align the first member to the alignment size of the // class. Linux will align the first member to its natural alignment #define DAC_ALIGNAS(a) alignas(a) #endif // #ifndef __daccess_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/dacprivate.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // // Internal data access functionality. // //***************************************************************************** #ifndef _DACPRIVATE_H_ #define _DACPRIVATE_H_ #include #include #include #include #ifndef TARGET_UNIX // It is unfortunate having to include this header just to get the definition of GenericModeBlock #include #endif // TARGET_UNIX // // Whenever a structure is marshalled between different platforms, we need to ensure the // layout is the same in both cases. We tell GCC to use the MSVC-style packing with // the following attribute. The main thing this appears to control is whether // 8-byte values are aligned at 4-bytes (GCC default) or 8-bytes (MSVC default). // This attribute affects only the immediate struct it is applied to, you must also apply // it to any nested structs if you want their layout affected as well. You also must // apply this to unions embedded in other structures, since it can influence the starting // alignment. // // Note that there doesn't appear to be any disadvantage to applying this a little // more agressively than necessary, so we generally use it on all classes / structures // defined in a file that defines marshalled data types (eg. DacDbiStructures.h) // The -mms-bitfields compiler option also does this for the whole file, but we don't // want to go changing the layout of, for example, structures defined in OS header files // so we explicitly opt-in with this attribute. // #if defined(__GNUC__) && defined(HOST_X86) #define MSLAYOUT __attribute__((__ms_struct__)) #else #define MSLAYOUT #endif #include //---------------------------------------------------------------------------- // // Internal CLRData requests. // //---------------------------------------------------------------------------- // Private requests for DataModules enum { DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR = 0xf0000000, DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA = 0xf0000001 }; // Private requests for stack walkers. enum { DACSTACKPRIV_REQUEST_FRAME_DATA = 0xf0000000 }; enum DacpObjectType { OBJ_STRING=0,OBJ_FREE,OBJ_OBJECT,OBJ_ARRAY,OBJ_OTHER }; struct MSLAYOUT DacpObjectData { CLRDATA_ADDRESS MethodTable = 0; DacpObjectType ObjectType = DacpObjectType::OBJ_STRING; ULONG64 Size = 0; CLRDATA_ADDRESS ElementTypeHandle = 0; CorElementType ElementType = CorElementType::ELEMENT_TYPE_END; DWORD dwRank = 0; ULONG64 dwNumComponents = 0; ULONG64 dwComponentSize = 0; CLRDATA_ADDRESS ArrayDataPtr = 0; CLRDATA_ADDRESS ArrayBoundsPtr = 0; CLRDATA_ADDRESS ArrayLowerBoundsPtr = 0; CLRDATA_ADDRESS RCW = 0; CLRDATA_ADDRESS CCW = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetObjectData(addr, this); } }; struct MSLAYOUT DacpExceptionObjectData { CLRDATA_ADDRESS Message = 0; CLRDATA_ADDRESS InnerException = 0; CLRDATA_ADDRESS StackTrace = 0; CLRDATA_ADDRESS WatsonBuckets = 0; CLRDATA_ADDRESS StackTraceString = 0; CLRDATA_ADDRESS RemoteStackTraceString = 0; INT32 HResult = 0; INT32 XCode = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { HRESULT hr; ISOSDacInterface2 *psos2 = NULL; if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), (void**) &psos2))) { hr = psos2->GetObjectExceptionData(addr, this); psos2->Release(); } return hr; } }; struct MSLAYOUT DacpUsefulGlobalsData { CLRDATA_ADDRESS ArrayMethodTable = 0; CLRDATA_ADDRESS StringMethodTable = 0; CLRDATA_ADDRESS ObjectMethodTable = 0; CLRDATA_ADDRESS ExceptionMethodTable = 0; CLRDATA_ADDRESS FreeMethodTable = 0; }; struct MSLAYOUT DacpFieldDescData { CorElementType Type = CorElementType::ELEMENT_TYPE_END; CorElementType sigType = CorElementType::ELEMENT_TYPE_END; // ELEMENT_TYPE_XXX from signature. We need this to disply pretty name for String in minidump's case CLRDATA_ADDRESS MTOfType = 0; // NULL if Type is not loaded CLRDATA_ADDRESS ModuleOfType = 0; mdTypeDef TokenOfType = 0; mdFieldDef mb = 0; CLRDATA_ADDRESS MTOfEnclosingClass = 0; DWORD dwOffset = 0; BOOL bIsThreadLocal = FALSE; BOOL bIsContextLocal = FALSE; BOOL bIsStatic = FALSE; CLRDATA_ADDRESS NextField = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetFieldDescData(addr, this); } }; struct MSLAYOUT DacpMethodTableFieldData { WORD wNumInstanceFields = 0; WORD wNumStaticFields = 0; WORD wNumThreadStaticFields = 0; CLRDATA_ADDRESS FirstField = 0; // If non-null, you can retrieve more WORD wContextStaticOffset = 0; WORD wContextStaticsSize = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodTableFieldData(addr, this); } }; struct MSLAYOUT DacpMethodTableCollectibleData { CLRDATA_ADDRESS LoaderAllocatorObjectHandle = 0; BOOL bCollectible = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { HRESULT hr; ISOSDacInterface6 *pSOS6 = NULL; if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface6), (void**)&pSOS6))) { hr = pSOS6->GetMethodTableCollectibleData(addr, this); pSOS6->Release(); } return hr; } }; struct MSLAYOUT DacpMethodTableTransparencyData { BOOL bHasCriticalTransparentInfo = FALSE; BOOL bIsCritical = FALSE; BOOL bIsTreatAsSafe = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodTableTransparencyData(addr, this); } }; struct MSLAYOUT DacpDomainLocalModuleData { // These two parameters are used as input params when calling the // no-argument form of Request below. CLRDATA_ADDRESS appDomainAddr = 0; ULONG64 ModuleID = 0; CLRDATA_ADDRESS pClassData = 0; CLRDATA_ADDRESS pDynamicClassTable = 0; CLRDATA_ADDRESS pGCStaticDataStart = 0; CLRDATA_ADDRESS pNonGCStaticDataStart = 0; // Called when you have a pointer to the DomainLocalModule HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetDomainLocalModuleData(addr, this); } }; struct MSLAYOUT DacpThreadLocalModuleData { // These two parameters are used as input params when calling the // no-argument form of Request below. CLRDATA_ADDRESS threadAddr = 0; ULONG64 ModuleIndex = 0; CLRDATA_ADDRESS pClassData = 0; CLRDATA_ADDRESS pDynamicClassTable = 0; CLRDATA_ADDRESS pGCStaticDataStart = 0; CLRDATA_ADDRESS pNonGCStaticDataStart = 0; }; struct MSLAYOUT DacpModuleData { CLRDATA_ADDRESS Address = 0; CLRDATA_ADDRESS PEAssembly = 0; // A PEAssembly addr CLRDATA_ADDRESS ilBase = 0; CLRDATA_ADDRESS metadataStart = 0; ULONG64 metadataSize = 0; CLRDATA_ADDRESS Assembly = 0; // Assembly pointer BOOL bIsReflection = FALSE; BOOL bIsPEFile = FALSE; ULONG64 dwBaseClassIndex = 0; ULONG64 dwModuleID = 0; DWORD dwTransientFlags = 0; CLRDATA_ADDRESS TypeDefToMethodTableMap = 0; CLRDATA_ADDRESS TypeRefToMethodTableMap = 0; CLRDATA_ADDRESS MethodDefToDescMap = 0; CLRDATA_ADDRESS FieldDefToDescMap = 0; CLRDATA_ADDRESS MemberRefToDescMap = 0; CLRDATA_ADDRESS FileReferencesMap = 0; CLRDATA_ADDRESS ManifestModuleReferencesMap = 0; CLRDATA_ADDRESS pLookupTableHeap = 0; CLRDATA_ADDRESS pThunkHeap = 0; ULONG64 dwModuleIndex = 0; DacpModuleData() { } HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetModuleData(addr, this); } private: // Ensure that this data structure is not copied. DacpModuleData(const DacpModuleData&); void operator=(const DacpModuleData&); }; struct MSLAYOUT DacpMethodTableData { BOOL bIsFree = FALSE; // everything else is NULL if this is true. CLRDATA_ADDRESS Module = 0; CLRDATA_ADDRESS Class = 0; CLRDATA_ADDRESS ParentMethodTable = 0; WORD wNumInterfaces = 0; WORD wNumMethods = 0; WORD wNumVtableSlots = 0; WORD wNumVirtuals = 0; DWORD BaseSize = 0; DWORD ComponentSize = 0; mdTypeDef cl = 0; // Metadata token DWORD dwAttrClass = 0; // cached metadata BOOL bIsShared = FALSE; // Always false, preserved for backward compatibility BOOL bIsDynamic = FALSE; BOOL bContainsPointers = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodTableData(addr, this); } }; // Copied from util.hpp, for DacpThreadStoreData.fHostConfig below. #define CLRMEMORYHOSTED 0x1 #define CLRTASKHOSTED 0x2 #define CLRSYNCHOSTED 0x4 #define CLRTHREADPOOLHOSTED 0x8 #define CLRIOCOMPLETIONHOSTED 0x10 #define CLRASSEMBLYHOSTED 0x20 #define CLRGCHOSTED 0x40 #define CLRSECURITYHOSTED 0x80 #define CLRHOSTED 0x80000000 struct MSLAYOUT DacpThreadStoreData { LONG threadCount = 0; LONG unstartedThreadCount = 0; LONG backgroundThreadCount = 0; LONG pendingThreadCount = 0; LONG deadThreadCount = 0; CLRDATA_ADDRESS firstThread = 0; CLRDATA_ADDRESS finalizerThread = 0; CLRDATA_ADDRESS gcThread = 0; DWORD fHostConfig = 0; // Uses hosting flags defined above HRESULT Request(ISOSDacInterface *sos) { return sos->GetThreadStoreData(this); } }; struct MSLAYOUT DacpAppDomainStoreData { CLRDATA_ADDRESS sharedDomain = 0; CLRDATA_ADDRESS systemDomain = 0; LONG DomainCount = 0; HRESULT Request(ISOSDacInterface *sos) { return sos->GetAppDomainStoreData(this); } }; struct MSLAYOUT DacpCOMInterfacePointerData { CLRDATA_ADDRESS methodTable = 0; CLRDATA_ADDRESS interfacePtr = 0; CLRDATA_ADDRESS comContext = 0; }; struct MSLAYOUT DacpRCWData { CLRDATA_ADDRESS identityPointer = 0; CLRDATA_ADDRESS unknownPointer = 0; CLRDATA_ADDRESS managedObject = 0; CLRDATA_ADDRESS jupiterObject = 0; CLRDATA_ADDRESS vtablePtr = 0; CLRDATA_ADDRESS creatorThread = 0; CLRDATA_ADDRESS ctxCookie = 0; LONG refCount = 0; LONG interfaceCount = 0; BOOL isJupiterObject = FALSE; BOOL supportsIInspectable = FALSE; BOOL isAggregated = FALSE; BOOL isContained = FALSE; BOOL isFreeThreaded = FALSE; BOOL isDisconnected = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw) { return sos->GetRCWData(rcw, this); } HRESULT IsDCOMProxy(ISOSDacInterface *sos, CLRDATA_ADDRESS rcw, BOOL* isDCOMProxy) { ISOSDacInterface2 *pSOS2 = nullptr; HRESULT hr = sos->QueryInterface(__uuidof(ISOSDacInterface2), reinterpret_cast(&pSOS2)); if (SUCCEEDED(hr)) { hr = pSOS2->IsRCWDCOMProxy(rcw, isDCOMProxy); pSOS2->Release(); } return hr; } }; struct MSLAYOUT DacpCCWData { CLRDATA_ADDRESS outerIUnknown = 0; CLRDATA_ADDRESS managedObject = 0; CLRDATA_ADDRESS handle = 0; CLRDATA_ADDRESS ccwAddress = 0; LONG refCount = 0; LONG interfaceCount = 0; BOOL isNeutered = FALSE; LONG jupiterRefCount = 0; BOOL isPegged = FALSE; BOOL isGlobalPegged = FALSE; BOOL hasStrongRef = FALSE; BOOL isExtendsCOMObject = FALSE; BOOL isAggregated = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS ccw) { return sos->GetCCWData(ccw, this); } }; enum DacpAppDomainDataStage { STAGE_CREATING, STAGE_READYFORMANAGEDCODE, STAGE_ACTIVE, STAGE_OPEN, STAGE_UNLOAD_REQUESTED, STAGE_EXITING, STAGE_EXITED, STAGE_FINALIZING, STAGE_FINALIZED, STAGE_HANDLETABLE_NOACCESS, STAGE_CLEARED, STAGE_COLLECTED, STAGE_CLOSED }; // Information about a BaseDomain (AppDomain, SharedDomain or SystemDomain). // For types other than AppDomain, some fields (like dwID, DomainLocalBlock, etc.) will be 0/null. struct MSLAYOUT DacpAppDomainData { // The pointer to the BaseDomain (not necessarily an AppDomain). // It's useful to keep this around in the structure CLRDATA_ADDRESS AppDomainPtr = 0; CLRDATA_ADDRESS AppSecDesc = 0; CLRDATA_ADDRESS pLowFrequencyHeap = 0; CLRDATA_ADDRESS pHighFrequencyHeap = 0; CLRDATA_ADDRESS pStubHeap = 0; CLRDATA_ADDRESS DomainLocalBlock = 0; CLRDATA_ADDRESS pDomainLocalModules = 0; // The creation sequence number of this app domain (starting from 1) DWORD dwId = 0; LONG AssemblyCount = 0; LONG FailedAssemblyCount = 0; DacpAppDomainDataStage appDomainStage = DacpAppDomainDataStage::STAGE_CREATING; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetAppDomainData(addr, this); } }; struct MSLAYOUT DacpAssemblyData { CLRDATA_ADDRESS AssemblyPtr = 0; //useful to have CLRDATA_ADDRESS ClassLoader = 0; CLRDATA_ADDRESS ParentDomain = 0; CLRDATA_ADDRESS BaseDomainPtr = 0; CLRDATA_ADDRESS AssemblySecDesc = 0; BOOL isDynamic = FALSE; UINT ModuleCount = FALSE; UINT LoadContext = FALSE; BOOL isDomainNeutral = FALSE; // Always false, preserved for backward compatibility DWORD dwLocationFlags = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS baseDomainPtr) { return sos->GetAssemblyData(baseDomainPtr, addr, this); } HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return Request(sos, addr, NULL); } }; struct MSLAYOUT DacpThreadData { DWORD corThreadId = 0; DWORD osThreadId = 0; int state = 0; ULONG preemptiveGCDisabled = 0; CLRDATA_ADDRESS allocContextPtr = 0; CLRDATA_ADDRESS allocContextLimit = 0; CLRDATA_ADDRESS context = 0; CLRDATA_ADDRESS domain = 0; CLRDATA_ADDRESS pFrame = 0; DWORD lockCount = 0; CLRDATA_ADDRESS firstNestedException = 0; // Pass this pointer to DacpNestedExceptionInfo CLRDATA_ADDRESS teb = 0; CLRDATA_ADDRESS fiberData = 0; CLRDATA_ADDRESS lastThrownObjectHandle = 0; CLRDATA_ADDRESS nextThread = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetThreadData(addr, this); } }; struct MSLAYOUT DacpReJitData { enum Flags { kUnknown, kRequested, kActive, kReverted, }; CLRDATA_ADDRESS rejitID = 0; Flags flags = Flags::kUnknown; CLRDATA_ADDRESS NativeCodeAddr = 0; }; struct MSLAYOUT DacpReJitData2 { enum Flags { kUnknown, kRequested, kActive, kReverted, }; ULONG rejitID = 0; Flags flags = Flags::kUnknown; CLRDATA_ADDRESS il = 0; CLRDATA_ADDRESS ilCodeVersionNodePtr = 0; }; struct MSLAYOUT DacpProfilerILData { enum ModificationType { Unmodified, ILModified, ReJITModified, }; ModificationType type = ModificationType::Unmodified; CLRDATA_ADDRESS il = 0; ULONG rejitID = 0; }; struct MSLAYOUT DacpMethodDescData { BOOL bHasNativeCode = FALSE; BOOL bIsDynamic = FALSE; WORD wSlotNumber = 0; CLRDATA_ADDRESS NativeCodeAddr = 0; // Useful for breaking when a method is jitted. CLRDATA_ADDRESS AddressOfNativeCodeSlot = 0; CLRDATA_ADDRESS MethodDescPtr = 0; CLRDATA_ADDRESS MethodTablePtr = 0; CLRDATA_ADDRESS ModulePtr = 0; mdToken MDToken = 0; CLRDATA_ADDRESS GCInfo = 0; CLRDATA_ADDRESS GCStressCodeCopy = 0; // This is only valid if bIsDynamic is true CLRDATA_ADDRESS managedDynamicMethodObject = 0; CLRDATA_ADDRESS requestedIP = 0; // Gives info for the single currently active version of a method DacpReJitData rejitDataCurrent = {}; // Gives info corresponding to requestedIP (for !ip2md) DacpReJitData rejitDataRequested = {}; // Total number of rejit versions that have been jitted ULONG cJittedRejitVersions = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodDescData( addr, NULL, // IP address this, 0, // cRejitData NULL, // rejitData[] NULL // pcNeededRejitData ); } }; struct MSLAYOUT DacpMethodDescTransparencyData { BOOL bHasCriticalTransparentInfo = FALSE; BOOL bIsCritical = FALSE; BOOL bIsTreatAsSafe = FALSE; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetMethodDescTransparencyData(addr, this); } }; struct MSLAYOUT DacpTieredVersionData { enum OptimizationTier { OptimizationTier_Unknown, OptimizationTier_MinOptJitted, OptimizationTier_Optimized, OptimizationTier_QuickJitted, OptimizationTier_OptimizedTier1, OptimizationTier_ReadyToRun, OptimizationTier_OptimizedTier1OSR, OptimizationTier_QuickJittedInstrumented, OptimizationTier_OptimizedTier1Instrumented, }; CLRDATA_ADDRESS NativeCodeAddr; OptimizationTier OptimizationTier; CLRDATA_ADDRESS NativeCodeVersionNodePtr; }; // for JITType enum JITTypes {TYPE_UNKNOWN=0,TYPE_JIT,TYPE_PJIT}; struct MSLAYOUT DacpCodeHeaderData { CLRDATA_ADDRESS GCInfo = 0; JITTypes JITType = JITTypes::TYPE_UNKNOWN; CLRDATA_ADDRESS MethodDescPtr = 0; CLRDATA_ADDRESS MethodStart = 0; DWORD MethodSize = 0; CLRDATA_ADDRESS ColdRegionStart = 0; DWORD ColdRegionSize = 0; DWORD HotRegionSize = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS IPAddr) { return sos->GetCodeHeaderData(IPAddr, this); } }; struct MSLAYOUT DacpWorkRequestData { CLRDATA_ADDRESS Function = 0; CLRDATA_ADDRESS Context = 0; CLRDATA_ADDRESS NextWorkRequest = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetWorkRequestData(addr, this); } }; struct MSLAYOUT DacpHillClimbingLogEntry { DWORD TickCount = 0; int Transition = 0; int NewControlSetting = 0; int LastHistoryCount = 0; double LastHistoryMean = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS entry) { return sos->GetHillClimbingLogEntry(entry, this); } }; // Used for CLR versions >= 4.0 struct MSLAYOUT DacpThreadpoolData { LONG cpuUtilization = 0; int NumIdleWorkerThreads = 0; int NumWorkingWorkerThreads = 0; int NumRetiredWorkerThreads = 0; LONG MinLimitTotalWorkerThreads = 0; LONG MaxLimitTotalWorkerThreads = 0; CLRDATA_ADDRESS FirstUnmanagedWorkRequest = 0; CLRDATA_ADDRESS HillClimbingLog = 0; int HillClimbingLogFirstIndex = 0; int HillClimbingLogSize = 0; DWORD NumTimers = 0; // TODO: Add support to enumerate timers too. LONG NumCPThreads = 0; LONG NumFreeCPThreads = 0; LONG MaxFreeCPThreads = 0; LONG NumRetiredCPThreads = 0; LONG MaxLimitTotalCPThreads = 0; LONG CurrentLimitTotalCPThreads = 0; LONG MinLimitTotalCPThreads = 0; CLRDATA_ADDRESS AsyncTimerCallbackCompletionFPtr = 0; HRESULT Request(ISOSDacInterface *sos) { return sos->GetThreadpoolData(this); } }; struct MSLAYOUT DacpGenerationData { CLRDATA_ADDRESS start_segment = 0; CLRDATA_ADDRESS allocation_start = 0; // These are examined only for generation 0, otherwise NULL CLRDATA_ADDRESS allocContextPtr = 0; CLRDATA_ADDRESS allocContextLimit = 0; }; #define DAC_NUMBERGENERATIONS 4 struct MSLAYOUT DacpAllocData { CLRDATA_ADDRESS allocBytes = 0; CLRDATA_ADDRESS allocBytesLoh = 0; }; struct MSLAYOUT DacpGenerationAllocData { DacpAllocData allocData[DAC_NUMBERGENERATIONS] = {}; }; struct MSLAYOUT DacpGcHeapDetails { CLRDATA_ADDRESS heapAddr = 0; // Only filled in server mode, otherwise NULL CLRDATA_ADDRESS alloc_allocated = 0; CLRDATA_ADDRESS mark_array = 0; CLRDATA_ADDRESS current_c_gc_state = 0; CLRDATA_ADDRESS next_sweep_obj = 0; CLRDATA_ADDRESS saved_sweep_ephemeral_seg = 0; CLRDATA_ADDRESS saved_sweep_ephemeral_start = 0; CLRDATA_ADDRESS background_saved_lowest_address = 0; CLRDATA_ADDRESS background_saved_highest_address = 0; DacpGenerationData generation_table [DAC_NUMBERGENERATIONS] = {}; CLRDATA_ADDRESS ephemeral_heap_segment = 0; CLRDATA_ADDRESS finalization_fill_pointers [DAC_NUMBERGENERATIONS + 3] = {}; CLRDATA_ADDRESS lowest_address = 0; CLRDATA_ADDRESS highest_address = 0; CLRDATA_ADDRESS card_table = 0; // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE). HRESULT Request(ISOSDacInterface *sos) { return sos->GetGCHeapStaticData(this); } // Use this for Server mode, as there are multiple heaps, // and you need to pass a heap address in addr. HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetGCHeapDetails(addr, this); } }; struct MSLAYOUT DacpGcHeapData { BOOL bServerMode = FALSE; BOOL bGcStructuresValid = FALSE; UINT HeapCount = 0; UINT g_max_generation = 0; HRESULT Request(ISOSDacInterface *sos) { return sos->GetGCHeapData(this); } }; struct MSLAYOUT DacpHeapSegmentData { CLRDATA_ADDRESS segmentAddr = 0; CLRDATA_ADDRESS allocated = 0; CLRDATA_ADDRESS committed = 0; CLRDATA_ADDRESS reserved = 0; CLRDATA_ADDRESS used = 0; CLRDATA_ADDRESS mem = 0; // pass this to request if non-null to get the next segments. CLRDATA_ADDRESS next = 0; CLRDATA_ADDRESS gc_heap = 0; // only filled in server mode, otherwise NULL // computed field: if this is the ephemeral segment highMark includes the ephemeral generation CLRDATA_ADDRESS highAllocMark = 0; size_t flags = 0; CLRDATA_ADDRESS background_allocated = 0; HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr, const DacpGcHeapDetails& heap) { // clear this here to make sure we don't get stale values this->highAllocMark = 0; HRESULT hr = sos->GetHeapSegmentData(addr, this); // if this is the start segment, and the Dac hasn't set highAllocMark, set it here. if (SUCCEEDED(hr) && this->highAllocMark == 0) { if (this->segmentAddr == heap.ephemeral_heap_segment) highAllocMark = heap.alloc_allocated; else highAllocMark = allocated; } return hr; } }; struct MSLAYOUT DacpOomData { int reason = 0; ULONG64 alloc_size = 0; ULONG64 available_pagefile_mb = 0; ULONG64 gc_index = 0; int fgm = 0; ULONG64 size = 0; BOOL loh_p = FALSE; HRESULT Request(ISOSDacInterface *sos) { return sos->GetOOMStaticData(this); } // Use this for Server mode, as there are multiple heaps, // and you need to pass a heap address in addr. HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetOOMData(addr, this); } }; #define DAC_NUM_GC_DATA_POINTS 9 #define DAC_MAX_COMPACT_REASONS_COUNT 11 #define DAC_MAX_EXPAND_MECHANISMS_COUNT 6 #define DAC_MAX_GC_MECHANISM_BITS_COUNT 2 #define DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT 6 struct MSLAYOUT DacpGCInterestingInfoData { size_t interestingDataPoints[DAC_NUM_GC_DATA_POINTS] = {}; size_t compactReasons[DAC_MAX_COMPACT_REASONS_COUNT] = {}; size_t expandMechanisms[DAC_MAX_EXPAND_MECHANISMS_COUNT] = {}; size_t bitMechanisms[DAC_MAX_GC_MECHANISM_BITS_COUNT] = {}; size_t globalMechanisms[DAC_MAX_GLOBAL_GC_MECHANISMS_COUNT] = {}; HRESULT RequestGlobal(ISOSDacInterface *sos) { HRESULT hr; ISOSDacInterface3 *psos3 = NULL; if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3))) { hr = psos3->GetGCGlobalMechanisms(globalMechanisms); psos3->Release(); } return hr; } HRESULT Request(ISOSDacInterface *sos) { HRESULT hr; ISOSDacInterface3 *psos3 = NULL; if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3))) { hr = psos3->GetGCInterestingInfoStaticData(this); psos3->Release(); } return hr; } // Use this for Server mode, as there are multiple heaps, // and you need to pass a heap address in addr. HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { HRESULT hr; ISOSDacInterface3 *psos3 = NULL; if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3))) { hr = psos3->GetGCInterestingInfoData(addr, this); psos3->Release(); } return hr; } }; struct MSLAYOUT DacpGcHeapAnalyzeData { CLRDATA_ADDRESS heapAddr = 0; // Only filled in server mode, otherwise NULL CLRDATA_ADDRESS internal_root_array = 0; ULONG64 internal_root_array_index = 0; BOOL heap_analyze_success = FALSE; // Use this for workstation mode (DacpGcHeapDat.bServerMode==FALSE). HRESULT Request(ISOSDacInterface *sos) { return sos->GetHeapAnalyzeStaticData(this); } // Use this for Server mode, as there are multiple heaps, // and you need to pass a heap address in addr. HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr) { return sos->GetHeapAnalyzeData(addr, this); } }; #define SYNCBLOCKDATA_COMFLAGS_CCW 1 #define SYNCBLOCKDATA_COMFLAGS_RCW 2 #define SYNCBLOCKDATA_COMFLAGS_CF 4 struct MSLAYOUT DacpSyncBlockData { CLRDATA_ADDRESS Object = 0; BOOL bFree = FALSE; // if set, no other fields are useful // fields below provide data from this, so it's just for display CLRDATA_ADDRESS SyncBlockPointer = 0; DWORD COMFlags = 0; UINT MonitorHeld = 0; UINT Recursion = 0; CLRDATA_ADDRESS HoldingThread = 0; UINT AdditionalThreadCount = 0; CLRDATA_ADDRESS appDomainPtr = 0; // SyncBlockCount will always be filled in with the number of SyncBlocks. // SyncBlocks may be requested from [1,SyncBlockCount] UINT SyncBlockCount = 0; // SyncBlockNumber must be from [1,SyncBlockCount] // If there are no SyncBlocks, a call to Request with SyncBlockCount = 1 // will return E_FAIL. HRESULT Request(ISOSDacInterface *sos, UINT SyncBlockNumber) { return sos->GetSyncBlockData(SyncBlockNumber, this); } }; struct MSLAYOUT DacpSyncBlockCleanupData { CLRDATA_ADDRESS SyncBlockPointer = 0; CLRDATA_ADDRESS nextSyncBlock = 0; CLRDATA_ADDRESS blockRCW = 0; CLRDATA_ADDRESS blockClassFactory = 0; CLRDATA_ADDRESS blockCCW = 0; // Pass NULL on the first request to start a traversal. HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS psyncBlock) { return sos->GetSyncBlockCleanupData(psyncBlock, this); } }; /////////////////////////////////////////////////////////////////////////// enum EHClauseType {EHFault, EHFinally, EHFilter, EHTyped, EHUnknown}; struct MSLAYOUT DACEHInfo { EHClauseType clauseType = EHClauseType::EHFault; CLRDATA_ADDRESS tryStartOffset = 0; CLRDATA_ADDRESS tryEndOffset = 0; CLRDATA_ADDRESS handlerStartOffset = 0; CLRDATA_ADDRESS handlerEndOffset = 0; BOOL isDuplicateClause = FALSE; CLRDATA_ADDRESS filterOffset = 0; // valid when clauseType is EHFilter BOOL isCatchAllHandler = FALSE; // valid when clauseType is EHTyped CLRDATA_ADDRESS moduleAddr = 0; // when == 0 mtCatch contains a MethodTable, when != 0 tokCatch contains a type token CLRDATA_ADDRESS mtCatch = 0; // the method table of the TYPED clause type mdToken tokCatch = 0; // the type token of the TYPED clause type }; struct MSLAYOUT DacpGetModuleAddress { CLRDATA_ADDRESS ModulePtr = 0; HRESULT Request(IXCLRDataModule* pDataModule) { return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR, 0, NULL, sizeof(*this), (PBYTE) this); } }; struct MSLAYOUT DacpGetModuleData { BOOL IsDynamic = FALSE; BOOL IsInMemory = FALSE; BOOL IsFileLayout = FALSE; CLRDATA_ADDRESS PEAssembly = 0; CLRDATA_ADDRESS LoadedPEAddress = 0; ULONG64 LoadedPESize = 0; CLRDATA_ADDRESS InMemoryPdbAddress = 0; ULONG64 InMemoryPdbSize = 0; HRESULT Request(IXCLRDataModule* pDataModule) { return pDataModule->Request(DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA, 0, NULL, sizeof(*this), (PBYTE) this); } }; struct MSLAYOUT DacpFrameData { CLRDATA_ADDRESS frameAddr = 0; // Could also be implemented for IXCLRDataFrame if desired. HRESULT Request(IXCLRDataStackWalk* dac) { return dac->Request(DACSTACKPRIV_REQUEST_FRAME_DATA, 0, NULL, sizeof(*this), (PBYTE)this); } }; struct MSLAYOUT DacpJitManagerInfo { CLRDATA_ADDRESS managerAddr = 0; DWORD codeType = 0; // for union below CLRDATA_ADDRESS ptrHeapList = 0; // A HeapList * if IsMiIL(codeType) }; enum CodeHeapType {CODEHEAP_LOADER=0,CODEHEAP_HOST,CODEHEAP_UNKNOWN}; struct MSLAYOUT DacpJitCodeHeapInfo { DWORD codeHeapType = 0; // for union below union { CLRDATA_ADDRESS LoaderHeap = 0; // if CODEHEAP_LOADER struct MSLAYOUT { CLRDATA_ADDRESS baseAddr = 0; // if CODEHEAP_HOST CLRDATA_ADDRESS currentAddr = 0; } HostData; }; DacpJitCodeHeapInfo() : codeHeapType(0), LoaderHeap(0) {} }; #include "static_assert.h" /* DAC datastructures are frozen as of dev11 shipping. Do NOT add fields, remove fields, or change the fields of * these structs in any way. The correct way to get new data out of the runtime is to create a new struct and * add a new function to the latest Dac<-->SOS interface to produce this data. */ static_assert(sizeof(DacpAllocData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpGenerationAllocData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpSyncBlockCleanupData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpThreadStoreData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpAppDomainStoreData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpAppDomainData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpAssemblyData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpThreadData) == 0x68, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpMethodDescData) == 0x98, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpCodeHeaderData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpThreadpoolData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpObjectData) == 0x60, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpMethodTableData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpWorkRequestData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpFieldDescData) == 0x40, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpModuleData) == 0xa0, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpGcHeapData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpJitManagerInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpHeapSegmentData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpDomainLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpUsefulGlobalsData) == 0x28, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DACEHInfo) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpRCWData) == 0x58, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpCCWData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpMethodTableFieldData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpMethodTableTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpThreadLocalModuleData) == 0x30, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpCOMInterfacePointerData) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpMethodDescTransparencyData) == 0xc, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpHillClimbingLogEntry) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpGenerationData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpGcHeapDetails) == 0x120, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpOomData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpGcHeapAnalyzeData) == 0x20, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpSyncBlockData) == 0x48, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpGetModuleAddress) == 0x8, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpFrameData) == 0x8, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpJitCodeHeapInfo) == 0x18, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpExceptionObjectData) == 0x38, "Dacp structs cannot be modified due to backwards compatibility."); static_assert(sizeof(DacpMethodTableCollectibleData) == 0x10, "Dacp structs cannot be modified due to backwards compatibility."); #endif // _DACPRIVATE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/dacvars.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // This file contains the globals and statics that are visible to DAC. // It is used for the following: // 1. in daccess.h to build the table of DAC globals // 2. in enummem.cpp to dump out the related memory of static and globals // in a mini dump or heap dump // 3. in DacUpdateDll and tools\DacTablenGen\main.cs // // To use this functionality for other tools or purposes, define the // DEFINE_DACVAR macro & include dacvars.h like so (see enummem.cpp and/or // daccess.h for examples): // // #define DEFINE_DACVAR(type, size, id, var) type id; //this defn. discards // //the size // #include "dacvars.h" // // @dbgtodo: // Ideally we may be able to build a tool that generates this automatically. // At the least, we should automatically verify that the contents of this file // are consistent with the uses of all the macros like SVAL_DECL and GARY_DECL. // //================================================= // INSTRUCTIONS FOR ADDING VARIABLES TO THIS FILE //================================================= // You need to add a global or static declared with DAC macros, such as SPTR_* // GPTR_*, SVAL_*, GVAL_*, or GARY_*, only if the global or static is actually used // in a DACized code path. If you have declared a static or global that way just // because you were pattern-matching or because you anticipate that the variable // may eventually be used in a DACized code path, you don't need to add it here, // although in that case, you should not really use the DAC macro when you declare // the global or static. // * * * // The FIRST ARGUMENT should always be specified as ULONG. This is the type of // the offsets for the corresponding id in the _DacGlobals table. // @dbgtodo: // We should get rid of the ULONG argument since it's always the same. We would // also need to modify DacTablenGen\main.cs. // * * * // The SECOND ARGUMENT, "true_type," is used to calculate the true size of the // static/global variable. It is currently used only in enummem.cpp to write out // theproper size of memory for dumps. // * * * // The THIRD ARGUMENT should be a qualified name. If the variable is a static data // member, the name should be __. If the variable is a // global, the name should be __. // * * * // The FOURTH ARGUMENT should be the actual name of the static/global variable. If // static data the should be [::]::. If global, // it should look like . // * * * // If you need to add an entry to this file, your type may not be visible when // this file is compiled. In that case, you need to do one of two things: // - If the type is a pointer type, you can simply use UNKNOWN_POINTER_TYPE as the // "true type." It may be useful to specify the non-visible type in a comment. // - If the type is a composite/user-defined type, you must #include the header // file that defines the type in enummem.cpp. Do NOT #include it in daccess.h // Array types may be dumped via an explicit call to enumMem, so they should // be declared with DEFINE_DACVAR_NO_DUMP. The size in this case is immaterial, since // nothing will be dumped. #ifndef DEFINE_DACVAR #define DEFINE_DACVAR(true_type, id, var) #endif // Use this macro to define a static var that is known to the DAC and uses Volatile for storage in the runtime #ifndef DEFINE_DACVAR_VOLATILE #define DEFINE_DACVAR_VOLATILE(true_type, id, var) #endif // Use this macro to define a static var that is known to DAC, but not captured in a dump. #ifndef DEFINE_DACVAR_NO_DUMP #define DEFINE_DACVAR_NO_DUMP(true_type, id, var) #endif #define UNKNOWN_POINTER_TYPE SIZE_T DEFINE_DACVAR_VOLATILE(PTR_RangeSection, ExecutionManager__m_CodeRangeList, ExecutionManager::m_CodeRangeList) DEFINE_DACVAR(PTR_EECodeManager, ExecutionManager__m_pDefaultCodeMan, ExecutionManager::m_pDefaultCodeMan) DEFINE_DACVAR_VOLATILE(LONG, ExecutionManager__m_dwReaderCount, ExecutionManager::m_dwReaderCount) DEFINE_DACVAR_VOLATILE(LONG, ExecutionManager__m_dwWriterLock, ExecutionManager::m_dwWriterLock) DEFINE_DACVAR(PTR_EEJitManager, ExecutionManager__m_pEEJitManager, ExecutionManager::m_pEEJitManager) #ifdef FEATURE_READYTORUN DEFINE_DACVAR(PTR_ReadyToRunJitManager, ExecutionManager__m_pReadyToRunJitManager, ExecutionManager::m_pReadyToRunJitManager) #endif DEFINE_DACVAR_NO_DUMP(VMHELPDEF *, dac__hlpFuncTable, ::hlpFuncTable) DEFINE_DACVAR(VMHELPDEF *, dac__hlpDynamicFuncTable, ::hlpDynamicFuncTable) DEFINE_DACVAR(PTR_StubManager, StubManager__g_pFirstManager, StubManager::g_pFirstManager) DEFINE_DACVAR(PTR_PrecodeStubManager, PrecodeStubManager__g_pManager, PrecodeStubManager::g_pManager) DEFINE_DACVAR(PTR_StubLinkStubManager, StubLinkStubManager__g_pManager, StubLinkStubManager::g_pManager) DEFINE_DACVAR(PTR_ThunkHeapStubManager, ThunkHeapStubManager__g_pManager, ThunkHeapStubManager::g_pManager) DEFINE_DACVAR(PTR_JumpStubStubManager, JumpStubStubManager__g_pManager, JumpStubStubManager::g_pManager) DEFINE_DACVAR(PTR_RangeSectionStubManager, RangeSectionStubManager__g_pManager, RangeSectionStubManager::g_pManager) DEFINE_DACVAR(PTR_DelegateInvokeStubManager, DelegateInvokeStubManager__g_pManager, DelegateInvokeStubManager::g_pManager) DEFINE_DACVAR(PTR_VirtualCallStubManagerManager, VirtualCallStubManagerManager__g_pManager, VirtualCallStubManagerManager::g_pManager) DEFINE_DACVAR(PTR_CallCountingStubManager, CallCountingStubManager__g_pManager, CallCountingStubManager::g_pManager) DEFINE_DACVAR(PTR_ThreadStore, ThreadStore__s_pThreadStore, ThreadStore::s_pThreadStore) DEFINE_DACVAR(PTR_Thread, dac__g_pFinalizerThread, ::g_pFinalizerThread) DEFINE_DACVAR(PTR_Thread, dac__g_pSuspensionThread, ::g_pSuspensionThread) DEFINE_DACVAR(DWORD, dac__g_heap_type, g_heap_type) DEFINE_DACVAR(PTR_GcDacVars, dac__g_gcDacGlobals, g_gcDacGlobals) DEFINE_DACVAR(PTR_AppDomain, AppDomain__m_pTheAppDomain, AppDomain::m_pTheAppDomain) DEFINE_DACVAR(PTR_SystemDomain, SystemDomain__m_pSystemDomain, SystemDomain::m_pSystemDomain) #ifdef FEATURE_INTEROP_DEBUGGING DEFINE_DACVAR(DWORD, dac__g_debuggerWordTLSIndex, g_debuggerWordTLSIndex) #endif DEFINE_DACVAR(DWORD, dac__g_TlsIndex, g_TlsIndex) DEFINE_DACVAR(PTR_SString, SString__s_Empty, SString::s_Empty) DEFINE_DACVAR(INT32, ArrayBase__s_arrayBoundsZero, ArrayBase::s_arrayBoundsZero) DEFINE_DACVAR(BOOL, StackwalkCache__s_Enabled, StackwalkCache::s_Enabled) DEFINE_DACVAR(PTR_JITNotification, dac__g_pNotificationTable, ::g_pNotificationTable) DEFINE_DACVAR(ULONG32, dac__g_dacNotificationFlags, ::g_dacNotificationFlags) DEFINE_DACVAR(PTR_GcNotification, dac__g_pGcNotificationTable, ::g_pGcNotificationTable) DEFINE_DACVAR(PTR_EEConfig, dac__g_pConfig, ::g_pConfig) DEFINE_DACVAR(CoreLibBinder, dac__g_CoreLib, ::g_CoreLib) #if defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA) DEFINE_DACVAR(ProfControlBlock, dac__g_profControlBlock, ::g_profControlBlock) #endif // defined(PROFILING_SUPPORTED) || defined(PROFILING_SUPPORTED_DATA) DEFINE_DACVAR(PTR_DWORD, dac__g_card_table, ::g_card_table) DEFINE_DACVAR(PTR_BYTE, dac__g_lowest_address, ::g_lowest_address) DEFINE_DACVAR(PTR_BYTE, dac__g_highest_address, ::g_highest_address) DEFINE_DACVAR(gc_alloc_context, dac__g_global_alloc_context, ::g_global_alloc_context) DEFINE_DACVAR(IGCHeap, dac__g_pGCHeap, ::g_pGCHeap) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pThinLockThreadIdDispenser, ::g_pThinLockThreadIdDispenser) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pModuleIndexDispenser, ::g_pModuleIndexDispenser) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pObjectClass, ::g_pObjectClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pRuntimeTypeClass, ::g_pRuntimeTypeClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pCanonMethodTableClass, ::g_pCanonMethodTableClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pStringClass, ::g_pStringClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pArrayClass, ::g_pArrayClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pSZArrayHelperClass, ::g_pSZArrayHelperClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pNullableClass, ::g_pNullableClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pExceptionClass, ::g_pExceptionClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pThreadAbortExceptionClass, ::g_pThreadAbortExceptionClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pOutOfMemoryExceptionClass, ::g_pOutOfMemoryExceptionClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pStackOverflowExceptionClass, ::g_pStackOverflowExceptionClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pExecutionEngineExceptionClass, ::g_pExecutionEngineExceptionClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pDelegateClass, ::g_pDelegateClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pMulticastDelegateClass, ::g_pMulticastDelegateClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pFreeObjectMethodTable, ::g_pFreeObjectMethodTable) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pValueTypeClass, ::g_pValueTypeClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEnumClass, ::g_pEnumClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pThreadClass, ::g_pThreadClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pPredefinedArrayTypes, ::g_pPredefinedArrayTypes) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_TypedReferenceMT, ::g_TypedReferenceMT) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pWeakReferenceClass, ::g_pWeakReferenceClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pWeakReferenceOfTClass, ::g_pWeakReferenceOfTClass) #ifdef FEATURE_COMINTEROP DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pBaseCOMObject, ::g_pBaseCOMObject) #endif DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pIDynamicInterfaceCastableInterface, ::g_pIDynamicInterfaceCastableInterface) #ifdef FEATURE_ICASTABLE DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pICastableInterface, ::g_pICastableInterface) #endif // FEATURE_ICASTABLE DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pObjectFinalizerMD, ::g_pObjectFinalizerMD) DEFINE_DACVAR(bool, dac__g_fProcessDetach, ::g_fProcessDetach) DEFINE_DACVAR(DWORD, dac__g_fEEShutDown, ::g_fEEShutDown) DEFINE_DACVAR(ULONG, dac__g_CORDebuggerControlFlags, ::g_CORDebuggerControlFlags) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pDebugger, ::g_pDebugger) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pDebugInterface, ::g_pDebugInterface) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEEDbgInterfaceImpl, ::g_pEEDbgInterfaceImpl) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEEInterface, ::g_pEEInterface) DEFINE_DACVAR(ULONG, dac__CLRJitAttachState, ::CLRJitAttachState) DEFINE_DACVAR(BOOL, Debugger__s_fCanChangeNgenFlags, Debugger::s_fCanChangeNgenFlags) DEFINE_DACVAR(PTR_DebuggerPatchTable, DebuggerController__g_patches, DebuggerController::g_patches) DEFINE_DACVAR(BOOL, DebuggerController__g_patchTableValid, DebuggerController::g_patchTableValid) DEFINE_DACVAR(SIZE_T, dac__gLowestFCall, ::gLowestFCall) DEFINE_DACVAR(SIZE_T, dac__gHighestFCall, ::gHighestFCall) DEFINE_DACVAR(SIZE_T, dac__gFCallMethods, ::gFCallMethods) DEFINE_DACVAR(PTR_SyncTableEntry, dac__g_pSyncTable, ::g_pSyncTable) #ifdef FEATURE_COMINTEROP DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pRCWCleanupList, ::g_pRCWCleanupList) #endif // FEATURE_COMINTEROP #ifndef TARGET_UNIX DEFINE_DACVAR(SIZE_T, dac__g_runtimeLoadedBaseAddress, ::g_runtimeLoadedBaseAddress) DEFINE_DACVAR(SIZE_T, dac__g_runtimeVirtualSize, ::g_runtimeVirtualSize) #endif // !TARGET_UNIX DEFINE_DACVAR(SyncBlockCache *, SyncBlockCache__s_pSyncBlockCache, SyncBlockCache::s_pSyncBlockCache) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pStressLog, ::g_pStressLog) DEFINE_DACVAR(SIZE_T, dac__s_gsCookie, ::s_gsCookie) DEFINE_DACVAR_NO_DUMP(SIZE_T, dac__g_FCDynamicallyAssignedImplementations, ::g_FCDynamicallyAssignedImplementations) #ifndef TARGET_UNIX DEFINE_DACVAR(HANDLE, dac__g_hContinueStartupEvent, ::g_hContinueStartupEvent) #endif // !TARGET_UNIX DEFINE_DACVAR(DWORD, CorHost2__m_dwStartupFlags, CorHost2::m_dwStartupFlags) DEFINE_DACVAR(HRESULT, dac__g_hrFatalError, ::g_hrFatalError) #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS DEFINE_DACVAR(DWORD, dac__g_MiniMetaDataBuffMaxSize, ::g_MiniMetaDataBuffMaxSize) DEFINE_DACVAR(TADDR, dac__g_MiniMetaDataBuffAddress, ::g_MiniMetaDataBuffAddress) #endif // FEATURE_MINIMETADATA_IN_TRIAGEDUMPS DEFINE_DACVAR(SIZE_T, dac__g_clrNotificationArguments, ::g_clrNotificationArguments) #ifdef EnC_SUPPORTED DEFINE_DACVAR(bool, dac__g_metadataUpdatesApplied, ::g_metadataUpdatesApplied) #endif #undef DEFINE_DACVAR #undef DEFINE_DACVAR_NO_DUMP ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/dbgenginemetrics.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // DbgEngineMetrics.h // // This file contains the definition of CLR_ENGINE_METRICS. This struct is used for Silverlight debugging. // // ====================================================================================== #ifndef __DbgEngineMetrics_h__ #define __DbgEngineMetrics_h__ //--------------------------------------------------------------------------------------- // // This struct contains information necessary for Silverlight debugging. coreclr.dll has a static struct // of this type. It is read by dbgshim.dll to help synchronize the debugger and coreclr.dll in launch // and early attach scenarios. // typedef struct tagCLR_ENGINE_METRICS { DWORD cbSize; // the size of the struct; also identifies the format of the struct DWORD dwDbiVersion; // the version of the debugging interface expected by this CoreCLR LPVOID phContinueStartupEvent; // pointer to the continue startup event handle } CLR_ENGINE_METRICS; #endif // __DbgEngineMetrics_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/dbgmeta.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* ------------------------------------------------------------------------- * * DbgMeta.h - header file for debugger metadata routines * ------------------------------------------------------------------------- */ #ifndef _DbgMeta_h_ #define _DbgMeta_h_ #include /* ------------------------------------------------------------------------- * * Structs to support line numbers and variables * ------------------------------------------------------------------------- */ class DebuggerLexicalScope; // // DebuggerVarInfo // // Holds basic information about local variables, method arguments, // and class static and instance variables. // struct DebuggerVarInfo { LPCSTR name; PCCOR_SIGNATURE sig; unsigned int varNumber; // placement info for IL code DebuggerLexicalScope* scope; // containing scope DebuggerVarInfo() : name(NULL), sig(NULL), varNumber(0), scope(NULL) {} }; #endif /* _DbgMeta_h_ */ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/dbgportable.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __DBG_PORTABLE_INCLUDED #define __DBG_PORTABLE_INCLUDED // // This header defines the template class Portable which is designed to wrap primitive types in such a way // that their physical representation is in a canonical format that can be safely transferred between hosts on // different platforms. // // This is achieved by storing the wrapped datum in little-endian format (since most of our platforms are // little-endian this makes the most sense from a performance perspective). On little-endian platforms the // wrapper code will become a no-op and get optimized away by the compiler. On big-endian platforms // assignments to a Portable value will reverse the order of the bytes in the T value and reverse them back // again on a read. // // Portable is typically used to wrap the fields of structures sent directly over a network channel. In // this fashion many of the values that would otherwise require manual endian-ness fixups are now marshalled // and unmarshalled transparent right at the network transition. // // Care must be taken to identify any code that takes the address of a Portable, since this is not // generally safe (it could expose naive code to the network encoded form of the datum). In such situations // the code is normally re-written to create a temporary instance of T on the stack, initialized to the // correct host value by reading from the Portable field. The address of this variable can now be taken // safely (assuming its value is required only for some lexically scoped operation). Once the value is no // longer being used, and if there is a possibility that the value may have been updated, the new value can be // copied back into the Portable field. // // Note that this header uses very basic data types only as it is included from both Win32/PAL code and native // Mac code. // #if BIGENDIAN || __BIG_ENDIAN__ #define DBG_BYTE_SWAP_REQUIRED #endif #if defined(_ASSERTE) #define _PASSERT(_expr) _ASSERTE(_expr) #elif defined(assert) #define _PASSERT(_expr) assert(_expr) #else #define _PASSERT(_expr) #endif // Lowest level helper used to reverse the order of a sequence of bytes, either as an in-place operation or as // part of a copy. inline void ByteSwapPrimitive(const void *pSrc, void *pDst, unsigned int cbSize) { _PASSERT(cbSize == 2 || cbSize == 4 || cbSize == 8); unsigned char *pbSrc = (unsigned char*)pSrc; unsigned char *pbDst = (unsigned char*)pDst; for (unsigned int i = 0; i < (cbSize / 2); i++) { unsigned int j = cbSize - i - 1; unsigned char bTemp = pbSrc[i]; pbDst[i] = pbSrc[j]; pbDst[j] = bTemp; } } template class Portable { T m_data; public: // No constructors -- this will be used in unions. // Convert data to portable format on assignment. T operator = (T value) { _PASSERT(sizeof(value) <= sizeof(double)); #ifdef DBG_BYTE_SWAP_REQUIRED m_data = ByteSwap(value); #else // DBG_BYTE_SWAP_REQUIRED m_data = value; #endif // DBG_BYTE_SWAP_REQUIRED return value; } // Return data in native format on access. operator T () const { #ifdef DBG_BYTE_SWAP_REQUIRED return ByteSwap(m_data); #else // DBG_BYTE_SWAP_REQUIRED return m_data; #endif // DBG_BYTE_SWAP_REQUIRED } bool operator == (T other) const { #ifdef DBG_BYTE_SWAP_REQUIRED return ByteSwap(m_data) == other; #else // DBG_BYTE_SWAP_REQUIRED return m_data == other; #endif // DBG_BYTE_SWAP_REQUIRED } bool operator != (T other) const { #ifdef DBG_BYTE_SWAP_REQUIRED return ByteSwap(m_data) != other; #else // DBG_BYTE_SWAP_REQUIRED return m_data != other; #endif // DBG_BYTE_SWAP_REQUIRED } T Unwrap() { #ifdef DBG_BYTE_SWAP_REQUIRED return ByteSwap(m_data); #else // DBG_BYTE_SWAP_REQUIRED return m_data; #endif // DBG_BYTE_SWAP_REQUIRED } private: #ifdef DBG_BYTE_SWAP_REQUIRED // Big endian helper routine to swap the order of bytes of an arbitrary sized type // (though obviously this type must be an integral primitive for this to make any // sense). static T ByteSwap(T inval) { if (sizeof(T) > 1) { T outval; ByteSwapPrimitive(&inval, &outval, sizeof(T)); return outval; } else return inval; } #endif // DBG_BYTE_SWAP_REQUIRED }; #endif // !__DBG_PORTABLE_INCLUDED ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/debugmacros.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // DebugMacros.h // // Wrappers for Debugging purposes. // //***************************************************************************** #ifndef __DebugMacros_h__ #define __DebugMacros_h__ #include "stacktrace.h" #include "debugmacrosext.h" #include "palclr.h" #undef _ASSERTE #undef VERIFY #ifdef __cplusplus extern "C" { #endif // __cplusplus #if defined(_DEBUG) class SString; bool GetStackTraceAtContext(SString & s, struct _CONTEXT * pContext); bool _DbgBreakCheck(LPCSTR szFile, int iLine, LPCSTR szExpr, BOOL fConstrained = FALSE); extern VOID ANALYZER_NORETURN DbgAssertDialog(const char *szFile, int iLine, const char *szExpr); #define PRE_ASSERTE /* if you need to change modes before doing asserts override */ #define POST_ASSERTE /* put it back */ #if !defined(_ASSERTE_MSG) #define _ASSERTE_MSG(expr, msg) \ do { \ if (!(expr)) { \ PRE_ASSERTE \ DbgAssertDialog(__FILE__, __LINE__, msg); \ POST_ASSERTE \ } \ } while (0) #endif // _ASSERTE_MSG #if !defined(_ASSERTE) #define _ASSERTE(expr) _ASSERTE_MSG(expr, #expr) #endif // !_ASSERTE #define VERIFY(stmt) _ASSERTE((stmt)) #define _ASSERTE_ALL_BUILDS(expr) _ASSERTE((expr)) #else // !_DEBUG #define _ASSERTE(expr) ((void)0) #define _ASSERTE_MSG(expr, msg) ((void)0) #define VERIFY(stmt) (void)(stmt) // At this point, EEPOLICY_HANDLE_FATAL_ERROR may or may not be defined. It will be defined // if we are building the VM folder, but outside VM, its not necessarily defined. // // Thus, if EEPOLICY_HANDLE_FATAL_ERROR is not defined, we will call into __FreeBuildAssertFail, // but if it is defined, we will use it. // // Failing here implies an error in the runtime - hence we use COR_E_EXECUTIONENGINE. #ifdef EEPOLICY_HANDLE_FATAL_ERROR #define _ASSERTE_ALL_BUILDS(expr) if (!(expr)) EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); #else // !EEPOLICY_HANDLE_FATAL_ERROR void DECLSPEC_NORETURN __FreeBuildAssertFail(const char *szFile, int iLine, const char *szExpr); #define _ASSERTE_ALL_BUILDS(expr) if (!(expr)) __FreeBuildAssertFail(__FILE__, __LINE__, #expr); #endif // EEPOLICY_HANDLE_FATAL_ERROR #endif #define ASSERT_AND_CHECK(x) { \ BOOL bResult = x; \ if (!bResult) \ { \ _ASSERTE(x); \ return FALSE; \ } \ } #ifdef _DEBUG_IMPL #define _ASSERTE_IMPL(expr) _ASSERTE((expr)) #if defined(_M_IX86) #if defined(_MSC_VER) #define _DbgBreak() __asm { int 3 } #elif defined(__GNUC__) #define _DbgBreak() __asm__ ("int $3"); #else #error Unknown compiler #endif #else #define _DbgBreak() DebugBreak() #endif extern VOID DebBreakHr(HRESULT hr); #ifndef IfFailGoto #define IfFailGoto(EXPR, LABEL) \ do { hr = (EXPR); if(FAILED(hr)) { DebBreakHr(hr); goto LABEL; } } while (0) #endif #ifndef IfFailRet #define IfFailRet(EXPR) \ do { hr = (EXPR); if(FAILED(hr)) { DebBreakHr(hr); return (hr); } } while (0) #endif #ifndef IfFailWin32Ret #define IfFailWin32Ret(EXPR) \ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBreakHr(hr); return hr;} } while (0) #endif #ifndef IfFailWin32Goto #define IfFailWin32Goto(EXPR, LABEL) \ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); DebBreakHr(hr); goto LABEL; } } while (0) #endif #ifndef IfFailGo #define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit) #endif #ifndef IfFailWin32Go #define IfFailWin32Go(EXPR) IfFailWin32Goto(EXPR, ErrExit) #endif #else // _DEBUG_IMPL #define _DbgBreak() {} #define _ASSERTE_IMPL(expr) #define IfFailGoto(EXPR, LABEL) \ do { hr = (EXPR); if(FAILED(hr)) { goto LABEL; } } while (0) #define IfFailRet(EXPR) \ do { hr = (EXPR); if(FAILED(hr)) { return (hr); } } while (0) #define IfFailWin32Ret(EXPR) \ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); return hr;} } while (0) #define IfFailWin32Goto(EXPR, LABEL) \ do { hr = (EXPR); if(hr != ERROR_SUCCESS) { hr = HRESULT_FROM_WIN32(hr); goto LABEL; } } while (0) #define IfFailGo(EXPR) IfFailGoto(EXPR, ErrExit) #define IfFailWin32Go(EXPR) IfFailWin32Goto(EXPR, ErrExit) #endif // _DEBUG_IMPL #define IfNullGoto(EXPR, LABEL) \ do { if ((EXPR) == NULL) { OutOfMemory(); IfFailGoto(E_OUTOFMEMORY, LABEL); } } while (false) #ifndef IfNullRet #define IfNullRet(EXPR) \ do { if ((EXPR) == NULL) { OutOfMemory(); return E_OUTOFMEMORY; } } while (false) #endif //!IfNullRet #define IfNullGo(EXPR) IfNullGoto(EXPR, ErrExit) #ifdef __cplusplus } #endif // __cplusplus #undef assert #define assert _ASSERTE #undef _ASSERT #define _ASSERT _ASSERTE #if defined(_DEBUG) && defined(HOST_WINDOWS) // This function returns the EXE time stamp (effectively a random number) // Under retail it always returns 0. This is meant to be used in the // RandomOnExe macro unsigned DbgGetEXETimeStamp(); // returns true 'fractionOn' amount of the time using the EXE timestamp // as the random number seed. For example DbgRandomOnExe(.1) returns true 1/10 // of the time. We use the line number so that different uses of DbgRandomOnExe // will not be coorelated with each other (9973 is prime). Returns false on a retail build #define DbgRandomOnHashAndExe(hash, fractionOn) \ (((DbgGetEXETimeStamp() * __LINE__ * ((hash) ? (hash) : 1)) % 9973) < \ unsigned((fractionOn) * 9973)) #define DbgRandomOnExe(fractionOn) DbgRandomOnHashAndExe(0, fractionOn) #else #define DbgGetEXETimeStamp() 0 #define DbgRandomOnHashAndExe(hash, fractionOn) 0 #define DbgRandomOnExe(fractionOn) 0 #endif // _DEBUG && !FEATUREPAL #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/debugmacrosext.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // DebugMacrosExt.h // // Simple debugging macros that take no dependencies on CLR headers. // This header can be used from outside the CLR. // //***************************************************************************** #ifndef __DebugMacrosExt_h__ #define __DebugMacrosExt_h__ #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif #ifdef _DEBUG // A macro to execute a statement only in _DEBUG. #define DEBUG_STMT(stmt) stmt #define INDEBUG(x) x #define INDEBUG_COMMA(x) x, #define COMMA_INDEBUG(x) ,x #define NOT_DEBUG(x) #else #define DEBUG_STMT(stmt) #define INDEBUG(x) #define INDEBUG_COMMA(x) #define COMMA_INDEBUG(x) #define NOT_DEBUG(x) x #endif #ifdef _DEBUG_IMPL #define INDEBUGIMPL(x) x #define INDEBUGIMPL_COMMA(x) x, #define COMMA_INDEBUGIMPL(x) ,x #else #define INDEBUGIMPL(x) #define INDEBUGIMPL_COMMA(x) #define COMMA_INDEBUGIMPL(x) #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/debugreturn.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _DEBUGRETURN_H_ #define _DEBUGRETURN_H_ // Note that with OACR Prefast is run over checked (_DEBUG is defined) sources // so we have to first check the _PREFAST_ define followed by the _DEBUG define // #ifdef _PREFAST_ // Use prefast to detect gotos out of no-return blocks. The gotos out of no-return blocks // should be reported as memory leaks by prefast. The (nothrow) is because PREfix sees the // throw from the new statement, and doesn't like these macros used in a destructor (and // the NULL returned by failure works just fine in delete[]) #define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { char* __noReturnInThisBlock_##arg = ::new (nothrow) char[1]; #define DEBUG_ASSURE_NO_RETURN_END(arg) ::delete[] __noReturnInThisBlock_##arg; } #define DEBUG_OK_TO_RETURN_BEGIN(arg) { ::delete[] __noReturnInThisBlock_##arg; #define DEBUG_OK_TO_RETURN_END(arg) __noReturnInThisBlock_##arg = ::new (nothrow) char[1]; } #define DEBUG_ASSURE_SAFE_TO_RETURN TRUE #define return return #else // !_PREFAST_ // This is disabled in build 190024315 (a pre-release build after VS 2015 Update 3) and // earlier because those builds only support C++11 constexpr, which doesn't allow the // use of 'if' statements within the body of a constexpr function. Later builds support // C++14 constexpr. #if defined(_DEBUG) && !defined(JIT_BUILD) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) // Code to generate a compile-time error if return statements appear where they // shouldn't. // // Here's the way it works... // // We create two classes with a safe_to_return() method. The method is static, // returns void, and does nothing. One class has the method as public, the other // as private. We introduce a global scope typedef for __ReturnOK that refers to // the class with the public method. So, by default, the expression // // __ReturnOK::safe_to_return() // // quietly compiles and does nothing. When we enter a block in which we want to // inhibit returns, we introduce a new typedef that defines __ReturnOK as the // class with the private method. Inside this scope, // // __ReturnOK::safe_to_return() // // generates a compile-time error. // // To cause the method to be called, we have to #define the return keyword. // The simplest working version would be // // #define return if (0) __ReturnOK::safe_to_return(); else return // // but we've used // // #define return for (;1;__ReturnOK::safe_to_return()) return // // because it happens to generate somewhat faster code in a checked build. (They // both introduce no overhead in a fastchecked build.) // class __SafeToReturn { public: static int safe_to_return() {return 0;}; static int used() {return 0;}; }; class __YouCannotUseAReturnStatementHere { private: // If you got here, and you're wondering what you did wrong -- you're using // a return statement where it's not allowed. Likely, it's inside one of: // GCPROTECT_BEGIN ... GCPROTECT_END // HELPER_METHOD_FRAME_BEGIN ... HELPER_METHOD_FRAME_END // static int safe_to_return() {return 0;}; public: // Some compilers warn if all member functions in a class are private // or if a typedef is unused. Rather than disable the warning, we'll work // around it here. static int used() {return 0;}; }; typedef __SafeToReturn __ReturnOK; // Use this to ensure that it is safe to return from a given scope #define DEBUG_ASSURE_SAFE_TO_RETURN __ReturnOK::safe_to_return() // Unfortunately, the only way to make this work is to #define all return statements -- // even the ones at global scope. This actually generates better code that appears. // The call is dead, and does not appear in the generated code, even in a checked // build. (And, in fastchecked, there is no penalty at all.) // #ifdef _MSC_VER #define return if (0 && __ReturnOK::safe_to_return()) { } else return #else // _MSC_VER #define return for (;1;__ReturnOK::safe_to_return()) return #endif // _MSC_VER #define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { typedef __YouCannotUseAReturnStatementHere __ReturnOK; if (0 && __ReturnOK::used()) { } else { #define DEBUG_ASSURE_NO_RETURN_END(arg) } } #define DEBUG_OK_TO_RETURN_BEGIN(arg) { typedef __SafeToReturn __ReturnOK; if (0 && __ReturnOK::used()) { } else { #define DEBUG_OK_TO_RETURN_END(arg) } } #else // defined(_DEBUG) && !defined(JIT_BUILD) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) #define DEBUG_ASSURE_SAFE_TO_RETURN TRUE #define DEBUG_ASSURE_NO_RETURN_BEGIN(arg) { #define DEBUG_ASSURE_NO_RETURN_END(arg) } #define DEBUG_OK_TO_RETURN_BEGIN(arg) { #define DEBUG_OK_TO_RETURN_END(arg) } #endif // defined(_DEBUG) && !defined(JIT_BUILD) && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 190024315) #endif // !_PREFAST_ #endif // _DEBUGRETURN_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/dlwrap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // #ifndef _DLWRAP_H #define _DLWRAP_H //include this file if you get contract violation because of delayload //nothrow implementations #if defined(VER_H) && !defined (GetFileVersionInfoSizeW_NoThrow) DWORD GetFileVersionInfoSizeW_NoThrow( LPCWSTR lptstrFilename, /* Filename of version stamped file */ LPDWORD lpdwHandle ); #endif #if defined(VER_H) && !defined (GetFileVersionInfoW_NoThrow) BOOL GetFileVersionInfoW_NoThrow( LPCWSTR lptstrFilename, /* Filename of version stamped file */ DWORD dwHandle, /* Information from GetFileVersionSize */ DWORD dwLen, /* Length of buffer for info */ LPVOID lpData ); #endif #if defined(VER_H) && !defined (VerQueryValueW_NoThrow) BOOL VerQueryValueW_NoThrow( const LPVOID pBlock, LPCWSTR lpSubBlock, LPVOID * lplpBuffer, PUINT puLen ); #endif #if defined(_WININET_) && !defined (CreateUrlCacheEntryW_NoThrow) __success(return) BOOL CreateUrlCacheEntryW_NoThrow( IN LPCWSTR lpszUrlName, IN DWORD dwExpectedFileSize, IN LPCWSTR lpszFileExtension, _Out_writes_(MAX_LONGPATH+1) LPWSTR lpszFileName, IN DWORD dwReserved ); #endif #if defined(_WININET_) && !defined (CommitUrlCacheEntryW_NoThrow) BOOL CommitUrlCacheEntryW_NoThrow( IN LPCWSTR lpszUrlName, IN LPCWSTR lpszLocalFileName, IN FILETIME ExpireTime, IN FILETIME LastModifiedTime, IN DWORD CacheEntryType, IN LPCWSTR lpHeaderInfo, IN DWORD dwHeaderSize, IN LPCWSTR lpszFileExtension, IN LPCWSTR lpszOriginalUrl ); #endif #if defined(_WININET_) && !defined (InternetTimeToSystemTimeA_NoThrow) BOOL InternetTimeToSystemTimeA_NoThrow( IN LPCSTR lpszTime, // NULL terminated string OUT SYSTEMTIME *pst, // output in GMT time IN DWORD dwReserved ); #endif #if defined(__urlmon_h__) && !defined(CoInternetCreateSecurityManager_NoThrow) HRESULT CoInternetCreateSecurityManager_NoThrow( IServiceProvider *pSP, IInternetSecurityManager **ppSM, DWORD dwReserved ); #endif #if defined(__urlmon_h__) && !defined(URLDownloadToCacheFileW_NoThrow) HRESULT URLDownloadToCacheFileW_NoThrow( LPUNKNOWN lpUnkcaller, LPCWSTR szURL, _Out_writes_(dwBufLength) LPWSTR szFileName, DWORD dwBufLength, DWORD dwReserved, IBindStatusCallback *pBSC ); #endif #if defined(__urlmon_h__) && !defined(CoInternetGetSession_NoThrow) HRESULT CoInternetGetSession_NoThrow( WORD dwSessionMode, IInternetSession **ppIInternetSession, DWORD dwReserved ); #endif #if defined(__urlmon_h__) && !defined(CopyBindInfo_NoThrow) HRESULT CopyBindInfo_NoThrow( const BINDINFO * pcbiSrc, BINDINFO * pbiDest ); #endif //overrides #undef InternetTimeToSystemTimeA #undef CommitUrlCacheEntryW #undef HttpQueryInfoA #undef InternetCloseHandle #undef HttpSendRequestA #undef HttpOpenRequestA #undef InternetConnectA #undef InternetOpenA #undef InternetReadFile #undef CreateUrlCacheEntryW #undef CoInternetGetSession #undef CopyBindInfo #undef CoInternetCreateSecurityManager #undef URLDownloadToCacheFileW #undef FDICreate #undef FDIIsCabinet #undef FDICopy #undef FDIDestroy #undef VerQueryValueW #undef GetFileVersionInfoW #undef GetFileVersionInfoSizeW #undef VerQueryValueA #undef GetFileVersionInfoA #undef GetFileVersionInfoSizeA #define InternetTimeToSystemTimeA InternetTimeToSystemTimeA_NoThrow #define CommitUrlCacheEntryW CommitUrlCacheEntryW_NoThrow #define CreateUrlCacheEntryW CreateUrlCacheEntryW_NoThrow #define CoInternetGetSession CoInternetGetSession_NoThrow #define CopyBindInfo CopyBindInfo_NoThrow #define CoInternetCreateSecurityManager CoInternetCreateSecurityManager_NoThrow #define URLDownloadToCacheFileW URLDownloadToCacheFileW_NoThrow #define VerQueryValueW VerQueryValueW_NoThrow #define GetFileVersionInfoW GetFileVersionInfoW_NoThrow #define GetFileVersionInfoSizeW GetFileVersionInfoSizeW_NoThrow #define VerQueryValueA Use_VerQueryValueW #define GetFileVersionInfoA Use_GetFileVersionInfoW #define GetFileVersionInfoSizeA Use_GetFileVersionInfoSizeW #if defined(_WININET_) inline HRESULT HrCreateUrlCacheEntryW( IN LPCWSTR lpszUrlName, IN DWORD dwExpectedFileSize, IN LPCWSTR lpszFileExtension, _Out_writes_(MAX_LONGPATH+1) LPWSTR lpszFileName, IN DWORD dwReserved ) { if (!CreateUrlCacheEntryW(lpszUrlName, dwExpectedFileSize, lpszFileExtension, lpszFileName, dwReserved)) { return HRESULT_FROM_WIN32(GetLastError()); } else { return S_OK; } } inline HRESULT HrCommitUrlCacheEntryW( IN LPCWSTR lpszUrlName, IN LPCWSTR lpszLocalFileName, IN FILETIME ExpireTime, IN FILETIME LastModifiedTime, IN DWORD CacheEntryType, IN LPCWSTR lpHeaderInfo, IN DWORD dwHeaderSize, IN LPCWSTR lpszFileExtension, IN LPCWSTR lpszOriginalUrl ) { if (!CommitUrlCacheEntryW(lpszUrlName, lpszLocalFileName, ExpireTime, LastModifiedTime, CacheEntryType, lpHeaderInfo, dwHeaderSize, lpszFileExtension, lpszOriginalUrl)) { return HRESULT_FROM_WIN32(GetLastError()); } else { return S_OK; } } #endif // defined(_WININET_) #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ecmakey.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma once // The byte values of the ECMA pseudo public key and its token. const BYTE g_rbNeutralPublicKey[] = { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; const BYTE g_rbNeutralPublicKeyToken[] = { 0xb7, 0x7a, 0x5c, 0x56, 0x19, 0x34, 0xe0, 0x89 }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/eetwain.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // // EETwain.h // // This file has the definition of ICodeManager and EECodeManager. // // ICorJitCompiler compiles the IL of a method to native code, and stores // auxilliary data called as GCInfo (via ICorJitInfo::allocGCInfo()). // The data is used by the EE to manage the method's garbage collection, // exception handling, stack-walking etc. // This data can be parsed by an ICodeManager corresponding to that // ICorJitCompiler. // // EECodeManager is an implementation of ICodeManager for a default format // of GCInfo. Various ICorJitCompiler's are free to share this format so that // they do not need to provide their own implementation of ICodeManager // (though they are permitted to, if they want). // //***************************************************************************** #ifndef _EETWAIN_H #define _EETWAIN_H //***************************************************************************** #include #include "regdisp.h" #include "corjit.h" // For NativeVarInfo #include "stackwalktypes.h" #include "bitvector.h" #include "gcinfotypes.h" #if !defined(TARGET_X86) #define USE_GC_INFO_DECODER #endif #if (defined(TARGET_X86) && !defined(TARGET_UNIX)) || defined(TARGET_AMD64) #define HAS_QUICKUNWIND #endif #define CHECK_APP_DOMAIN 0 #define NO_OVERRIDE_OFFSET (DWORD)-1 struct EHContext; #ifdef DACCESS_COMPILE typedef struct _DAC_SLOT_LOCATION { int reg; int regOffset; bool targetPtr; _DAC_SLOT_LOCATION(int _reg, int _regOffset, bool _targetPtr) : reg(_reg), regOffset(_regOffset), targetPtr(_targetPtr) { } } DacSlotLocation; #endif typedef void (*GCEnumCallback)( LPVOID hCallback, // callback data OBJECTREF* pObject, // address of object-reference we are reporting uint32_t flags // is this a pinned and/or interior pointer DAC_ARG(DacSlotLocation loc) // where the reference came from ); /****************************************************************************** The stackwalker maintains some state on behalf of ICodeManager. */ const int CODEMAN_STATE_SIZE = 512; struct CodeManState { DWORD dwIsSet; // Is set to 0 by the stackwalk as appropriate BYTE stateBuf[CODEMAN_STATE_SIZE]; }; /****************************************************************************** These flags are used by some functions, although not all combinations might make sense for all functions. */ enum ICodeManagerFlags { ActiveStackFrame = 0x0001, // this is the currently active function ExecutionAborted = 0x0002, // execution of this function has been aborted // (i.e. it will not continue execution at the // current location) AbortingCall = 0x0004, // The current call will never return UpdateAllRegs = 0x0008, // update full register set CodeAltered = 0x0010, // code of that function might be altered // (e.g. by debugger), need to call EE // for original code SpeculativeStackwalk = 0x0020, // we're in the middle of a stackwalk seeded // by an untrusted source (e.g., sampling profiler) ParentOfFuncletStackFrame = 0x0040, // A funclet for this frame was previously reported NoReportUntracked = 0x0080, // EnumGCRefs/EnumerateLiveSlots should *not* include // any untracked slots }; //***************************************************************************** // // EECodeInfo is used by ICodeManager to get information about the // method whose GCInfo is being processed. // It is useful so that some information which is available elsewhere does // not need to be cached in the GCInfo. // class EECodeInfo; enum GenericParamContextType { GENERIC_PARAM_CONTEXT_NONE = 0, GENERIC_PARAM_CONTEXT_THIS = 1, GENERIC_PARAM_CONTEXT_METHODDESC = 2, GENERIC_PARAM_CONTEXT_METHODTABLE = 3 }; //***************************************************************************** // // ICodeManager is the abstract class that all CodeManagers // must inherit from. This will probably need to move into // cor.h and become a real com interface. // //***************************************************************************** class ICodeManager { VPTR_BASE_VTABLE_CLASS_AND_CTOR(ICodeManager) public: /* Last chance for the runtime support to do fixups in the context before execution continues inside a filter, catch handler, or fault/finally */ enum ContextType { FILTER_CONTEXT, CATCH_CONTEXT, FINALLY_CONTEXT }; /* Type of funclet corresponding to a shadow stack-pointer */ enum { SHADOW_SP_IN_FILTER = 0x1, SHADOW_SP_FILTER_DONE = 0x2, SHADOW_SP_BITS = 0x3 }; #ifndef DACCESS_COMPILE #ifndef FEATURE_EH_FUNCLETS virtual void FixContext(ContextType ctxType, EHContext *ctx, EECodeInfo *pCodeInfo, DWORD dwRelOffset, DWORD nestingLevel, OBJECTREF thrownObject, CodeManState *pState, size_t ** ppShadowSP, // OUT size_t ** ppEndRegion) = 0; // OUT #endif // !FEATURE_EH_FUNCLETS #endif // #ifndef DACCESS_COMPILE #ifdef TARGET_X86 /* Gets the ambient stack pointer value at the given nesting level within the method. */ virtual TADDR GetAmbientSP(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, DWORD dwRelOffset, DWORD nestingLevel, CodeManState *pState) = 0; #endif // TARGET_X86 /* Get the number of bytes used for stack parameters. This is currently only used on x86. */ virtual ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo) = 0; /* Unwind the current stack frame, i.e. update the virtual register set in pContext. This will be similar to the state after the function returns back to caller (IP points to after the call, Frame and Stack pointer has been reset, callee-saved registers restored (if UpdateAllRegs), callee-UNsaved registers are trashed) Returns success of operation. */ virtual bool UnwindStackFrame(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, unsigned flags, CodeManState *pState, StackwalkCacheUnwindInfo *pUnwindInfo) = 0; /* Is the function currently at a "GC safe point" ? Can call EnumGcRefs() successfully */ virtual bool IsGcSafe(EECodeInfo *pCodeInfo, DWORD dwRelOffset) = 0; #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) virtual bool HasTailCalls(EECodeInfo *pCodeInfo) = 0; #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 #if defined(TARGET_AMD64) && defined(_DEBUG) /* Locates the end of the last interruptible region in the given code range. Returns 0 if the entire range is uninterruptible. Returns the end point if the entire range is interruptible. */ virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset, unsigned endOffset, GCInfoToken gcInfoToken) = 0; #endif // TARGET_AMD64 && _DEBUG /* Enumerate all live object references in that function using the virtual register set. Same reference location cannot be enumerated multiple times (but all differenct references pointing to the same object have to be individually enumerated). Returns success of operation. */ virtual bool EnumGcRefs(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, unsigned flags, GCEnumCallback pCallback, LPVOID hCallBack, DWORD relOffsetOverride = NO_OVERRIDE_OFFSET) = 0; /* For a non-static method, "this" pointer is passed in as argument 0. However, if there is a "ldarga 0" or "starg 0" in the IL, JIT will create a copy of arg0 and redirect all "ldarg(a) 0" and "starg 0" to this copy. (See Compiler::lvaArg0Var for more details.) The following method returns the original "this" argument, i.e. the one that is passed in, if it is a non-static method AND the object is still alive. Returns NULL in all other cases. */ virtual OBJECTREF GetInstance(PREGDISPLAY pContext, EECodeInfo* pCodeInfo) = 0; /* Returns the extra argument passed to to shared generic code if it is still alive. Returns NULL in all other cases. */ virtual PTR_VOID GetParamTypeArg(PREGDISPLAY pContext, EECodeInfo * pCodeInfo) = 0; // Returns the type of the context parameter (this, methodtable, methoddesc, or none) virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext, EECodeInfo * pCodeInfo) = 0; /* Returns the offset of the GuardStack cookie if it exists. Returns NULL if there is no cookie. */ virtual void * GetGSCookieAddr(PREGDISPLAY pContext, EECodeInfo * pCodeInfo, CodeManState * pState) = 0; #ifndef USE_GC_INFO_DECODER /* Returns true if the given IP is in the given method's prolog or an epilog. */ virtual bool IsInPrologOrEpilog(DWORD relPCOffset, GCInfoToken gcInfoToken, size_t* prologSize) = 0; /* Returns true if the given IP is in the synchronized region of the method (valid for synchronized methods only) */ virtual bool IsInSynchronizedRegion( DWORD relOffset, GCInfoToken gcInfoToken, unsigned flags) = 0; #endif // !USE_GC_INFO_DECODER /* Returns the size of a given function as reported in the GC info (does not take procedure splitting into account). For the actual size of the hot region call IJitManager::JitTokenToMethodHotSize. */ virtual size_t GetFunctionSize(GCInfoToken gcInfoToken) = 0; /* * Get information necessary for return address hijacking of the method represented by the gcInfoToken. * If it can be hijacked, it sets the returnKind output parameter to the kind of the return value and * returns true. * If hijacking is not possible for some reason, it return false. */ virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind) = 0; #ifndef USE_GC_INFO_DECODER /* Returns the size of the frame (barring localloc) */ virtual unsigned int GetFrameSize(GCInfoToken gcInfoToken) = 0; #endif // USE_GC_INFO_DECODER #ifndef DACCESS_COMPILE /* Debugger API */ #ifndef FEATURE_EH_FUNCLETS virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)=0; virtual BOOL IsInFilter(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx, DWORD curNestLevel) = 0; virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx) = 0; virtual void LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx)=0; #endif // FEATURE_EH_FUNCLETS #ifdef EnC_SUPPORTED /* Last chance for the runtime support to do fixups in the context before execution continues inside an EnC updated function. */ virtual HRESULT FixContextForEnC(PCONTEXT pCtx, EECodeInfo * pOldCodeInfo, const ICorDebugInfo::NativeVarInfo * oldMethodVars, SIZE_T oldMethodVarsCount, EECodeInfo * pNewCodeInfo, const ICorDebugInfo::NativeVarInfo * newMethodVars, SIZE_T newMethodVarsCount) = 0; #endif // EnC_SUPPORTED #endif // #ifndef DACCESS_COMPILE #ifdef DACCESS_COMPILE virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0; #endif }; //***************************************************************************** // // EECodeManager is the EE's implementation of the ICodeManager which // supports the default format of GCInfo. // //***************************************************************************** struct hdrInfo; class EECodeManager : public ICodeManager { VPTR_VTABLE_CLASS_AND_CTOR(EECodeManager, ICodeManager) public: #ifndef DACCESS_COMPILE #ifndef FEATURE_EH_FUNCLETS /* Last chance for the runtime support to do fixups in the context before execution continues inside a filter, catch handler, or finally */ virtual void FixContext(ContextType ctxType, EHContext *ctx, EECodeInfo *pCodeInfo, DWORD dwRelOffset, DWORD nestingLevel, OBJECTREF thrownObject, CodeManState *pState, size_t ** ppShadowSP, // OUT size_t ** ppEndRegion); // OUT #endif // !FEATURE_EH_FUNCLETS #endif // #ifndef DACCESS_COMPILE #ifdef TARGET_X86 /* Gets the ambient stack pointer value at the given nesting level within the method. */ virtual TADDR GetAmbientSP(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, DWORD dwRelOffset, DWORD nestingLevel, CodeManState *pState); #endif // TARGET_X86 /* Get the number of bytes used for stack parameters. This is currently only used on x86. */ virtual ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo); /* Unwind the current stack frame, i.e. update the virtual register set in pContext. This will be similar to the state after the function returns back to caller (IP points to after the call, Frame and Stack pointer has been reset, callee-saved registers restored (if UpdateAllRegs), callee-UNsaved registers are trashed) Returns success of operation. */ virtual bool UnwindStackFrame( PREGDISPLAY pContext, EECodeInfo *pCodeInfo, unsigned flags, CodeManState *pState, StackwalkCacheUnwindInfo *pUnwindInfo); #ifdef HAS_QUICKUNWIND enum QuickUnwindFlag { UnwindCurrentStackFrame, EnsureCallerStackFrameIsValid }; /* * Light unwind the current stack frame, using provided cache entry. * only pPC and Esp of pContext are updated. And pEbp if necessary. */ static void QuickUnwindStackFrame( PREGDISPLAY pRD, StackwalkCacheEntry *pCacheEntry, QuickUnwindFlag flag); #endif // HAS_QUICKUNWIND /* Is the function currently at a "GC safe point" ? Can call EnumGcRefs() successfully */ virtual bool IsGcSafe( EECodeInfo *pCodeInfo, DWORD dwRelOffset); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) virtual bool HasTailCalls(EECodeInfo *pCodeInfo); #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 #if defined(TARGET_AMD64) && defined(_DEBUG) /* Locates the end of the last interruptible region in the given code range. Returns 0 if the entire range is uninterruptible. Returns the end point if the entire range is interruptible. */ virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset, unsigned endOffset, GCInfoToken gcInfoToken); #endif // TARGET_AMD64 && _DEBUG /* Enumerate all live object references in that function using the virtual register set. Same reference location cannot be enumerated multiple times (but all differenct references pointing to the same object have to be individually enumerated). Returns success of operation. */ virtual bool EnumGcRefs(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, unsigned flags, GCEnumCallback pCallback, LPVOID hCallBack, DWORD relOffsetOverride = NO_OVERRIDE_OFFSET); #ifdef FEATURE_CONSERVATIVE_GC // Temporary conservative collection, for testing purposes, until we have // accurate gc info from the JIT. bool EnumGcRefsConservative(PREGDISPLAY pRD, EECodeInfo *pCodeInfo, unsigned flags, GCEnumCallback pCallBack, LPVOID hCallBack); #endif // FEATURE_CONSERVATIVE_GC virtual OBJECTREF GetInstance( PREGDISPLAY pContext, EECodeInfo * pCodeInfo); /* Returns the extra argument passed to to shared generic code if it is still alive. Returns NULL in all other cases. */ virtual PTR_VOID GetParamTypeArg(PREGDISPLAY pContext, EECodeInfo * pCodeInfo); // Returns the type of the context parameter (this, methodtable, methoddesc, or none) virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext, EECodeInfo * pCodeInfo); #if defined(FEATURE_EH_FUNCLETS) && defined(USE_GC_INFO_DECODER) /* Returns the generics token. This is used by GetInstance() and GetParamTypeArg() on WIN64. */ static PTR_VOID GetExactGenericsToken(PREGDISPLAY pContext, EECodeInfo * pCodeInfo); static PTR_VOID GetExactGenericsToken(SIZE_T baseStackSlot, EECodeInfo * pCodeInfo); #endif // FEATURE_EH_FUNCLETS && USE_GC_INFO_DECODER /* Returns the offset of the GuardStack cookie if it exists. Returns NULL if there is no cookie. */ virtual void * GetGSCookieAddr(PREGDISPLAY pContext, EECodeInfo * pCodeInfo, CodeManState * pState); #ifndef USE_GC_INFO_DECODER /* Returns true if the given IP is in the given method's prolog or an epilog. */ virtual bool IsInPrologOrEpilog( DWORD relOffset, GCInfoToken gcInfoToken, size_t* prologSize); /* Returns true if the given IP is in the synchronized region of the method (valid for synchronized functions only) */ virtual bool IsInSynchronizedRegion( DWORD relOffset, GCInfoToken gcInfoToken, unsigned flags); #endif // !USE_GC_INFO_DECODER /* Returns the size of a given function. */ virtual size_t GetFunctionSize(GCInfoToken gcInfoToken); /* * Get information necessary for return address hijacking of the method represented by the gcInfoToken. * If it can be hijacked, it sets the returnKind output parameter to the kind of the return value and * returns true. * If hijacking is not possible for some reason, it return false. */ virtual bool GetReturnAddressHijackInfo(GCInfoToken gcInfoToken, ReturnKind * returnKind); #ifndef USE_GC_INFO_DECODER /* Returns the size of the frame (barring localloc) */ virtual unsigned int GetFrameSize(GCInfoToken gcInfoToken); #endif // USE_GC_INFO_DECODER #ifndef DACCESS_COMPILE #ifndef FEATURE_EH_FUNCLETS virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg); virtual BOOL IsInFilter(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx, DWORD curNestLevel); virtual BOOL LeaveFinally(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx); virtual void LeaveCatch(GCInfoToken gcInfoToken, unsigned offset, PCONTEXT pCtx); #endif // FEATURE_EH_FUNCLETS #ifdef EnC_SUPPORTED /* Last chance for the runtime support to do fixups in the context before execution continues inside an EnC updated function. */ virtual HRESULT FixContextForEnC(PCONTEXT pCtx, EECodeInfo * pOldCodeInfo, const ICorDebugInfo::NativeVarInfo * oldMethodVars, SIZE_T oldMethodVarsCount, EECodeInfo * pNewCodeInfo, const ICorDebugInfo::NativeVarInfo * newMethodVars, SIZE_T newMethodVarsCount); #endif // EnC_SUPPORTED #endif // #ifndef DACCESS_COMPILE #ifdef FEATURE_EH_FUNCLETS static void EnsureCallerContextIsValid( PREGDISPLAY pRD, StackwalkCacheEntry* pCacheEntry, EECodeInfo * pCodeInfo = NULL ); static size_t GetCallerSp( PREGDISPLAY pRD ); #ifdef TARGET_X86 static size_t GetResumeSp( PCONTEXT pContext ); #endif // TARGET_X86 #endif // FEATURE_EH_FUNCLETS #ifdef DACCESS_COMPILE virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags); #endif }; #ifdef TARGET_X86 bool UnwindStackFrame(PREGDISPLAY pContext, EECodeInfo *pCodeInfo, unsigned flags, CodeManState *pState, StackwalkCacheUnwindInfo *pUnwindInfo); size_t DecodeGCHdrInfo(GCInfoToken gcInfoToken, unsigned curOffset, hdrInfo * infoPtr); #endif /***************************************************************************** ToDo: Do we want to include JIT/IL/target.h? */ enum regNum { REGI_EAX, REGI_ECX, REGI_EDX, REGI_EBX, REGI_ESP, REGI_EBP, REGI_ESI, REGI_EDI, REGI_COUNT, REGI_NA = REGI_COUNT }; /***************************************************************************** Register masks */ enum RegMask { RM_EAX = 0x01, RM_ECX = 0x02, RM_EDX = 0x04, RM_EBX = 0x08, RM_ESP = 0x10, RM_EBP = 0x20, RM_ESI = 0x40, RM_EDI = 0x80, RM_NONE = 0x00, RM_ALL = (RM_EAX|RM_ECX|RM_EDX|RM_EBX|RM_ESP|RM_EBP|RM_ESI|RM_EDI), RM_CALLEE_SAVED = (RM_EBP|RM_EBX|RM_ESI|RM_EDI), RM_CALLEE_TRASHED = (RM_ALL & ~RM_CALLEE_SAVED), }; /***************************************************************************** * * Helper to extract basic info from a method info block. */ struct hdrInfo { unsigned int methodSize; // native code bytes unsigned int argSize; // in bytes unsigned int stackSize; // including callee saved registers unsigned int rawStkSize; // excluding callee saved registers ReturnKind returnKind; // The ReturnKind for this method. unsigned int prologSize; // Size of the epilogs in the method. // For methods which use CEE_JMP, some epilogs may end with a "ret" instruction // and some may end with a "jmp". The epilogSize reported should be for the // epilog with the smallest size. unsigned int epilogSize; unsigned char epilogCnt; bool epilogEnd; // is the epilog at the end of the method bool ebpFrame; // locals and arguments addressed relative to EBP bool doubleAlign; // is the stack double-aligned? locals addressed relative to ESP, and arguments relative to EBP bool interruptible; // intr. at all times (excluding prolog/epilog), not just call sites bool handlers; // has callable handlers bool localloc; // uses localloc bool editNcontinue; // has been compiled in EnC mode bool varargs; // is this a varargs routine bool profCallbacks; // does the method have Enter-Leave callbacks bool genericsContext;// has a reported generic context parameter bool genericsContextIsMethodDesc;// reported generic context parameter is methoddesc bool isSpeculativeStackWalk; // is the stackwalk seeded by an untrusted source (e.g., sampling profiler)? // These always includes EBP for EBP-frames and double-aligned-frames RegMask savedRegMask:8; // which callee-saved regs are saved on stack // Count of the callee-saved registers, excluding the frame pointer. // This does not include EBP for EBP-frames and double-aligned-frames. unsigned int savedRegsCountExclFP; unsigned int untrackedCnt; unsigned int varPtrTableSize; unsigned int argTabOffset; // INVALID_ARGTAB_OFFSET if argtab must be reached by stepping through ptr tables unsigned int gsCookieOffset; // INVALID_GS_COOKIE_OFFSET if there is no GuardStack cookie unsigned int syncStartOffset; // start/end code offset of the protected region in synchronized methods. unsigned int syncEndOffset; // INVALID_SYNC_OFFSET if there not synchronized method unsigned int syncEpilogStart; // The start of the epilog. Synchronized methods are guaranteed to have no more than one epilog. unsigned int revPInvokeOffset; // INVALID_REV_PINVOKE_OFFSET if there is no Reverse PInvoke frame enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 }; int prologOffs; // NOT_IN_PROLOG if not in prolog int epilogOffs; // NOT_IN_EPILOG if not in epilog. It is never 0 // // Results passed back from scanArgRegTable // regNum thisPtrResult; // register holding "this" RegMask regMaskResult; // registers currently holding GC ptrs RegMask iregMaskResult; // iptr qualifier for regMaskResult unsigned argHnumResult; PTR_CBYTE argTabResult; // Table of encoded offsets of pending ptr args unsigned argTabBytes; // Number of bytes in argTabResult[] // These next two are now large structs (i.e 132 bytes each) ptrArgTP argMaskResult; // pending arguments mask ptrArgTP iargMaskResult; // iptr qualifier for argMaskResult }; /***************************************************************************** How the stackwalkers buffer will be interpreted */ struct CodeManStateBuf { DWORD hdrInfoSize; hdrInfo hdrInfoBody; }; //***************************************************************************** #endif // _EETWAIN_H //***************************************************************************** ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/eexcp.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __eexcp_h__ #define __eexcp_h__ #include "corhlpr.h" #include "daccess.h" struct EE_ILEXCEPTION_CLAUSE; typedef DPTR(EE_ILEXCEPTION_CLAUSE) PTR_EE_ILEXCEPTION_CLAUSE; // The exception handling sub-system needs to keep track of EH clause that is handling given exception. // PTR_EXCEPTION_CLAUSE_TOKEN is opaque pointer that uniquely identifies // exception handling clause. It abstracts away encoding differences of EH clauses between JIT and NGen. typedef PTR_VOID PTR_EXCEPTION_CLAUSE_TOKEN; struct EE_ILEXCEPTION_CLAUSE { //Flags is not marked as volatile since it is always accessed // from within a critical section CorExceptionFlag Flags; DWORD TryStartPC; DWORD TryEndPC; DWORD HandlerStartPC; DWORD HandlerEndPC; union { void* TypeHandle; mdToken ClassToken; DWORD FilterOffset; }; }; struct EE_ILEXCEPTION; typedef DPTR(EE_ILEXCEPTION) PTR_EE_ILEXCEPTION; struct EE_ILEXCEPTION : public COR_ILMETHOD_SECT_FAT { EE_ILEXCEPTION_CLAUSE Clauses[1]; // actually variable size void Init(unsigned ehCount) { LIMITED_METHOD_CONTRACT; SetKind(CorILMethod_Sect_FatFormat); SetDataSize((unsigned)sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); } unsigned EHCount() const { LIMITED_METHOD_CONTRACT; return GetDataSize() / (DWORD) sizeof(EE_ILEXCEPTION_CLAUSE); } static unsigned Size(unsigned ehCount) { LIMITED_METHOD_CONTRACT; _ASSERTE(ehCount > 0); return (offsetof(EE_ILEXCEPTION, Clauses) + sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); } EE_ILEXCEPTION_CLAUSE *EHClause(unsigned i) { LIMITED_METHOD_DAC_CONTRACT; return &(PTR_EE_ILEXCEPTION_CLAUSE(PTR_HOST_MEMBER_TADDR(EE_ILEXCEPTION,this,Clauses))[i]); } }; #define COR_ILEXCEPTION_CLAUSE_CACHED_CLASS 0x10000000 inline BOOL HasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause) { _ASSERTE(sizeof(EHClause->Flags) == sizeof(DWORD)); return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_CACHED_CLASS); } inline void SetHasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause) { _ASSERTE(! HasCachedTypeHandle(EHClause)); EHClause->Flags = (CorExceptionFlag)(EHClause->Flags | COR_ILEXCEPTION_CLAUSE_CACHED_CLASS); } inline BOOL IsFinally(EE_ILEXCEPTION_CLAUSE *EHClause) { LIMITED_METHOD_CONTRACT; return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FINALLY); } inline BOOL IsFault(EE_ILEXCEPTION_CLAUSE *EHClause) { LIMITED_METHOD_CONTRACT; return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FAULT); } inline BOOL IsFaultOrFinally(EE_ILEXCEPTION_CLAUSE *EHClause) { return IsFault(EHClause) || IsFinally(EHClause); } inline BOOL IsFilterHandler(EE_ILEXCEPTION_CLAUSE *EHClause) { LIMITED_METHOD_CONTRACT; return EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER; } inline BOOL IsTypedHandler(EE_ILEXCEPTION_CLAUSE *EHClause) { return ! (IsFilterHandler(EHClause) || IsFaultOrFinally(EHClause)); } inline BOOL IsDuplicateClause(EE_ILEXCEPTION_CLAUSE* pEHClause) { return pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_DUPLICATED; } #if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Finally is the only EH construct that can be part of the execution as being fall-through. // // "Cloned" finally is a construct that represents a finally block that is used as // fall through for normal try-block execution. Such a "cloned" finally will: // // 1) Have its try-clause's Start and End PC the same as its handler's start PC (i.e. will have // zero length try block), AND // 2) Is marked duplicate // // Because of their fall-through nature, JIT guarantees that only finally constructs can be cloned, // and not catch or fault (since they cannot be fallen through but are invoked as funclets). // // The cloned finally construct is also used to mark "call to finally" thunks that are not within // the EH region protected by the finally, and also not within the enclosing region. This is done // to prevent ThreadAbortException from creating an infinite loop of calling the same finally. inline BOOL IsClonedFinally(EE_ILEXCEPTION_CLAUSE* pEHClause) { return ((pEHClause->TryStartPC == pEHClause->TryEndPC) && (pEHClause->TryStartPC == pEHClause->HandlerStartPC) && IsFinally(pEHClause) && IsDuplicateClause(pEHClause)); } #endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) #endif // __eexcp_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/eventtrace.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // File: eventtrace.h // Abstract: This module implements Event Tracing support. This includes // eventtracebase.h, and adds VM-specific ETW helpers to support features like type // logging, allocation logging, and gc heap walk logging. // // // // // #EventTracing // Windows // ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable // tracing facility provided by the Windows Operating System. ETW is available on Win2K and above. There are // four main types of components in ETW: event providers, controllers, consumers, and event trace sessions. // An event provider is a logical entity that writes events to ETW sessions. The event provider must register // a provider ID with ETW through the registration API. A provider first registers with ETW and writes events // from various points in the code by invoking the ETW logging API. When a provider is enabled dynamically by // the ETW controller application, calls to the logging API sends events to a specific trace session // designated by the controller. Each event sent by the event provider to the trace session consists of a // fixed header that includes event metadata and additional variable user-context data. CLR is an event // provider. // Mac // DTrace is similar to ETW and has been made to look like ETW at most of the places. // For convenience, it is called ETM (Event Tracing for Mac) and exists only on the Mac Leopard OS // ============================================================================ #ifndef _VMEVENTTRACE_H_ #define _VMEVENTTRACE_H_ #include "eventtracebase.h" #include "gcinterface.h" #if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) struct ProfilingScanContext : ScanContext { BOOL fProfilerPinned; void * pvEtwContext; void *pHeapId; ProfilingScanContext(BOOL fProfilerPinnedParam) : ScanContext() { LIMITED_METHOD_CONTRACT; pHeapId = NULL; fProfilerPinned = fProfilerPinnedParam; pvEtwContext = NULL; #ifdef FEATURE_CONSERVATIVE_GC // To not confuse GCScan::GcScanRoots promotion = g_pConfig->GetGCConservative(); #endif } }; #endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE) #ifndef FEATURE_NATIVEAOT namespace ETW { class LoggedTypesFromModule; // We keep a hash of these to keep track of: // * Which types have been logged through ETW (so we can avoid logging dupe Type // events), and // * GCSampledObjectAllocation stats to help with "smart sampling" which // dynamically adjusts sampling rate of objects by type. // See code:LoggedTypesFromModuleTraits struct TypeLoggingInfo { public: TypeLoggingInfo(TypeHandle thParam) { Init(thParam); } TypeLoggingInfo() { Init(TypeHandle()); } void Init(TypeHandle thParam) { th = thParam; dwTickOfCurrentTimeBucket = 0; dwAllocCountInCurrentBucket = 0; flAllocPerMSec = 0; dwAllocsToSkipPerSample = 0; dwAllocsSkippedForSample = 0; cbIgnoredSizeForSample = 0; }; // The type this TypeLoggingInfo represents TypeHandle th; // Smart sampling // These bucket values remember stats of a particular time slice that are used to // help adjust the sampling rate DWORD dwTickOfCurrentTimeBucket; DWORD dwAllocCountInCurrentBucket; float flAllocPerMSec; // The number of data points to ignore before taking a "sample" (i.e., logging a // GCSampledObjectAllocation ETW event for this type) DWORD dwAllocsToSkipPerSample; // The current number of data points actually ignored for the current sample DWORD dwAllocsSkippedForSample; // The current count of bytes of objects of this type actually allocated (and // ignored) for the current sample SIZE_T cbIgnoredSizeForSample; }; // Class to wrap all type system logic for ETW class TypeSystemLog { private: // Global type hash static AllLoggedTypes *s_pAllLoggedTypes; // An unsigned value that gets incremented whenever a global change is made. // When this occurs, threads must synchronize themselves with the global state. // Examples include unloading of modules and disabling of allocation sampling. static unsigned int s_nEpoch; // See code:ETW::TypeSystemLog::PostRegistrationInit static BOOL s_fHeapAllocEventEnabledOnStartup; static BOOL s_fHeapAllocHighEventEnabledNow; static BOOL s_fHeapAllocLowEventEnabledNow; // If DOTNET_UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec is set, then // this is used to determine the event frequency, overriding // s_nDefaultMsBetweenEvents above (regardless of which // GCSampledObjectAllocation*Keyword was used) static int s_nCustomMsBetweenEvents; public: // This customizes the type logging behavior in LogTypeAndParametersIfNecessary enum TypeLogBehavior { // Take lock, and consult hash table to see if this is the first time we've // encountered the type, in which case, log it kTypeLogBehaviorTakeLockAndLogIfFirstTime, // Don't take lock, don't consult hash table. Just log the type. (This is // used in cases when checking for dupe type logging isn't worth it, such as // when logging the finalization of an object.) kTypeLogBehaviorAlwaysLog, // When logging the type for GCSampledObjectAllocation events, // we already know we need to log the type (since we already // looked it up in the hash). But we would still need to consult the hash // for any type parameters, so kTypeLogBehaviorAlwaysLog isn't appropriate, // and this is used instead. kTypeLogBehaviorAlwaysLogTopLevelType, }; static HRESULT PreRegistrationInit(); static void PostRegistrationInit(); static BOOL IsHeapAllocEventEnabled(); static void SendObjectAllocatedEvent(Object * pObject); static CrstBase * GetHashCrst(); static VOID LogTypeAndParametersIfNecessary(BulkTypeEventLogger * pBulkTypeEventLogger, ULONGLONG thAsAddr, TypeLogBehavior typeLogBehavior); static VOID OnModuleUnload(Module * pModule); static void OnKeywordsChanged(); static void Cleanup(); static VOID DeleteTypeHashNoLock(AllLoggedTypes **ppAllLoggedTypes); static VOID FlushObjectAllocationEvents(); static UINT32 TypeLoadBegin(); static VOID TypeLoadEnd(UINT32 typeLoad, TypeHandle th, UINT16 loadLevel); private: static BOOL ShouldLogType(TypeHandle th); static TypeLoggingInfo LookupOrCreateTypeLoggingInfo(TypeHandle th, BOOL * pfCreatedNew, LoggedTypesFromModule ** ppLoggedTypesFromModule = NULL); static BOOL AddTypeToGlobalCacheIfNotExists(TypeHandle th, BOOL * pfCreatedNew); static BOOL AddOrReplaceTypeLoggingInfo(ETW::LoggedTypesFromModule * pLoggedTypesFromModule, const ETW::TypeLoggingInfo * pTypeLoggingInfo); static int GetDefaultMsBetweenEvents(); static VOID OnTypesKeywordTurnedOff(); }; #endif // FEATURE_NATIVEAOT // Class to wrap all GC logic for ETW class GCLog { private: // When WPA triggers a GC, it gives us this unique number to append to our // GCStart event so WPA can correlate the CLR's GC with the JScript GC they // triggered at the same time. // // We set this value when the GC is triggered, and then retrieve the value on the // first subsequent FireGcStart() method call for a full, induced GC, assuming // that that's the GC that WPA triggered. This is imperfect, and if we were in // the act of beginning another full, induced GC (for some other reason), then // we'll attach this sequence number to that GC instead of to the WPA-induced GC, // but who cares? When parsing ETW logs later on, it's indistinguishable if both // GCs really were induced at around the same time. #ifdef FEATURE_NATIVEAOT static volatile LONGLONG s_l64LastClientSequenceNumber; #else // FEATURE_NATIVEAOT static Volatile s_l64LastClientSequenceNumber; #endif // FEATURE_NATIVEAOT public: typedef union st_GCEventInfo { // These values are gotten from the gc_reason // in gcimpl.h typedef enum _GC_REASON { GC_ALLOC_SOH = 0, GC_INDUCED = 1, GC_LOWMEMORY = 2, GC_EMPTY = 3, GC_ALLOC_LOH = 4, GC_OOS_SOH = 5, GC_OOS_LOH = 6, GC_INDUCED_NOFORCE = 7, GC_GCSTRESS = 8, GC_LOWMEMORY_BLOCKING = 9, GC_INDUCED_COMPACTING = 10, GC_LOWMEMORY_HOST = 11 } GC_REASON; typedef enum _GC_TYPE { GC_NGC = 0, GC_BGC = 1, GC_FGC = 2 } GC_TYPE; struct { ULONG Count; ULONG Depth; GC_REASON Reason; GC_TYPE Type; } GCStart; struct { ULONG Reason; // This is only valid when SuspendEE is called by GC (ie, Reason is either // SUSPEND_FOR_GC or SUSPEND_FOR_GC_PREP. ULONG GcCount; } SuspendEE; struct { ULONGLONG SegmentSize; ULONGLONG LargeObjectSegmentSize; BOOL ServerGC; // TRUE means it's server GC; FALSE means it's workstation. } GCSettings; } ETW_GC_INFO, *PETW_GC_INFO; #ifdef FEATURE_EVENT_TRACE static VOID GCSettingsEvent(); #else static VOID GCSettingsEvent() {}; #endif // FEATURE_EVENT_TRACE static BOOL ShouldWalkHeapObjectsForEtw(); static BOOL ShouldWalkHeapRootsForEtw(); static BOOL ShouldTrackMovementForEtw(); static HRESULT ForceGCForDiagnostics(); static VOID ForceGC(LONGLONG l64ClientSequenceNumber); static VOID FireGcStart(ETW_GC_INFO * pGcInfo); static VOID RootReference( LPVOID pvHandle, Object * pRootedNode, Object * pSecondaryNodeForDependentHandle, BOOL fDependentHandle, ProfilingScanContext * profilingScanContext, DWORD dwGCFlags, DWORD rootFlags); static VOID ObjectReference( ProfilerWalkHeapContext * profilerWalkHeapContext, Object * pObjReferenceSource, ULONGLONG typeID, ULONGLONG cRefs, Object ** rgObjReferenceTargets); static BOOL ShouldWalkStaticsAndCOMForEtw(); static VOID WalkStaticsAndCOMForETW(); static VOID EndHeapDump(ProfilerWalkHeapContext * profilerWalkHeapContext); #ifdef FEATURE_EVENT_TRACE static VOID BeginMovedReferences(size_t * pProfilingContext); static VOID MovedReference(BYTE * pbMemBlockStart, BYTE * pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, BOOL fAllowProfApiNotification = TRUE); static VOID EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiNotification = TRUE); #else // TODO: Need to be implemented for PROFILING_SUPPORTED. static VOID BeginMovedReferences(size_t * pProfilingContext) {}; static VOID MovedReference(BYTE * pbMemBlockStart, BYTE * pbMemBlockEnd, ptrdiff_t cbRelocDistance, size_t profilingContext, BOOL fCompacting, BOOL fAllowProfApiNotification = TRUE) {}; static VOID EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiNotification = TRUE) {}; #endif // FEATURE_EVENT_TRACE static VOID SendFinalizeObjectEvent(MethodTable * pMT, Object * pObj); }; }; #endif //_VMEVENTTRACE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/eventtracebase.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // File: eventtracebase.h // Abstract: This module implements base Event Tracing support (excluding some of the // CLR VM-specific ETW helpers). // // // // // #EventTracing // Windows // ETW (Event Tracing for Windows) is a high-performance, low overhead and highly scalable // tracing facility provided by the Windows Operating System. ETW is available on Win2K and above. There are // four main types of components in ETW: event providers, controllers, consumers, and event trace sessions. // An event provider is a logical entity that writes events to ETW sessions. The event provider must register // a provider ID with ETW through the registration API. A provider first registers with ETW and writes events // from various points in the code by invoking the ETW logging API. When a provider is enabled dynamically by // the ETW controller application, calls to the logging API sends events to a specific trace session // designated by the controller. Each event sent by the event provider to the trace session consists of a // fixed header that includes event metadata and additional variable user-context data. CLR is an event // provider. // ============================================================================ #ifndef _ETWTRACER_HXX_ #define _ETWTRACER_HXX_ struct EventStructTypeData; void InitializeEventTracing(); class PrepareCodeConfig; // !!!!!!! NOTE !!!!!!!! // The flags must match those in the ETW manifest exactly // !!!!!!! NOTE !!!!!!!! // These flags need to be defined either when FEATURE_EVENT_TRACE is enabled or the // PROFILING_SUPPORTED is set, since they are used both by event tracing and profiling. enum EtwTypeFlags { kEtwTypeFlagsDelegate = 0x1, kEtwTypeFlagsFinalizable = 0x2, kEtwTypeFlagsExternallyImplementedCOMObject = 0x4, kEtwTypeFlagsArray = 0x8, kEtwTypeFlagsArrayRankBit0 = 0x100, kEtwTypeFlagsArrayRankBit1 = 0x200, kEtwTypeFlagsArrayRankBit2 = 0x400, kEtwTypeFlagsArrayRankBit3 = 0x800, kEtwTypeFlagsArrayRankBit4 = 0x1000, kEtwTypeFlagsArrayRankBit5 = 0x2000, kEtwTypeFlagsArrayRankMask = 0x3F00, kEtwTypeFlagsArrayRankShift = 8, kEtwTypeFlagsArrayRankMax = kEtwTypeFlagsArrayRankMask >> kEtwTypeFlagsArrayRankShift }; enum EtwThreadFlags { kEtwThreadFlagGCSpecial = 0x00000001, kEtwThreadFlagFinalizer = 0x00000002, kEtwThreadFlagThreadPoolWorker = 0x00000004, }; enum EtwGCSettingFlags { kEtwGCFlagConcurrent = 0x00000001, kEtwGCFlagLargePages = 0x00000002, kEtwGCFlagFrozenSegs = 0x00000004, kEtwGCFlagHardLimitConfig = 0x00000008, kEtwGCFlagNoAffinitize = 0x00000010, }; #ifndef FEATURE_NATIVEAOT #if defined(FEATURE_EVENT_TRACE) #if defined(FEATURE_PERFTRACING) #define EVENT_PIPE_ENABLED() (EventPipeHelper::Enabled()) #else #define EVENT_PIPE_ENABLED() (FALSE) #endif #if !defined(HOST_UNIX) // // Use this macro at the least before calling the Event Macros // #define ETW_TRACING_INITIALIZED(RegHandle) \ ((g_pEtwTracer && (RegHandle)) || EVENT_PIPE_ENABLED()) // // Use this macro to check if an event is enabled // if the fields in the event are not cheap to calculate // #define ETW_EVENT_ENABLED(Context, EventDescriptor) \ ((Context.EtwProvider->IsEnabled && McGenEventXplatEnabled(Context.EtwProvider, &EventDescriptor)) || EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword)) // // Use this macro to check if a category of events is enabled // #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) \ ((Context.EtwProvider->IsEnabled && McGenEventProviderEnabled(Context.EtwProvider, Level, Keyword)) || EventPipeHelper::IsEnabled(Context, Level, Keyword)) // This macro only checks if a provider is enabled // It does not check the flags and keywords for which it is enabled #define ETW_PROVIDER_ENABLED(ProviderSymbol) \ ((ProviderSymbol##_Context.IsEnabled) || EVENT_PIPE_ENABLED()) #else //!defined(HOST_UNIX) #if defined(FEATURE_PERFTRACING) #define ETW_INLINE #define ETWOnStartup(StartEventName, EndEventName) #define ETWFireEvent(EventName) FireEtw##EventName(GetClrInstanceId()) #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) #define ETW_EVENT_ENABLED(Context, EventDescriptor) (EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword) || \ (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword))) #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) #define ETW_TRACING_ENABLED(Context, EventDescriptor) (EventEnabled##EventDescriptor()) #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (EventPipeHelper::IsEnabled(Context, Level, Keyword) || \ (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword))) #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) #else //defined(FEATURE_PERFTRACING) #define ETW_INLINE #define ETWOnStartup(StartEventName, EndEventName) #define ETWFireEvent(EventName) #define ETW_TRACING_INITIALIZED(RegHandle) (TRUE) #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (XplatEventLogger::IsKeywordEnabled(Context, Level, Keyword)) #define ETW_EVENT_ENABLED(Context, EventDescriptor) (XplatEventLogger::IsKeywordEnabled(Context, EventDescriptor.Level, EventDescriptor.KeywordsBitmask)) #define ETW_TRACING_ENABLED(Context, EventDescriptor) (ETW_EVENT_ENABLED(Context, EventDescriptor) && EventEnabled##EventDescriptor()) #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (ETW_CATEGORY_ENABLED(Context, Level, Keyword)) #define ETW_PROVIDER_ENABLED(ProviderSymbol) (XplatEventLogger::IsProviderEnabled(Context)) #endif // defined(FEATURE_PERFTRACING) #endif // !defined(HOST_UNIX) #else // FEATURE_EVENT_TRACE #define ETWOnStartup(StartEventName, EndEventName) #define ETWFireEvent(EventName) #define ETW_TRACING_INITIALIZED(RegHandle) (FALSE) #define ETW_EVENT_ENABLED(Context, EventDescriptor) (FALSE) #define ETW_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) #define ETW_TRACING_ENABLED(Context, EventDescriptor) (FALSE) #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) (FALSE) #define ETW_PROVIDER_ENABLED(ProviderSymbol) (TRUE) #endif // FEATURE_EVENT_TRACE #endif // FEATURE_NATIVEAOT // During a heap walk, this is the storage for keeping track of all the nodes and edges // being batched up by ETW, and for remembering whether we're also supposed to call into // a profapi profiler. This is allocated toward the end of a GC and passed to us by the // GC heap walker. struct ProfilerWalkHeapContext { public: ProfilerWalkHeapContext(BOOL fProfilerPinnedParam, LPVOID pvEtwContextParam) { fProfilerPinned = fProfilerPinnedParam; pvEtwContext = pvEtwContextParam; } BOOL fProfilerPinned; LPVOID pvEtwContext; }; #ifdef FEATURE_EVENT_TRACE class Object; #if !defined(HOST_UNIX) /***************************************/ /* Tracing levels supported by CLR ETW */ /***************************************/ #define ETWMAX_TRACE_LEVEL 6 // Maximum Number of Trace Levels supported #define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination #define TRACE_LEVEL_ERROR 2 // Severe errors that need logging #define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure #define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit #define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps struct ProfilingScanContext; // // Use this macro to check if ETW is initialized and the event is enabled // #define ETW_TRACING_ENABLED(Context, EventDescriptor) \ ((Context.EtwProvider->IsEnabled && ETW_TRACING_INITIALIZED(Context.EtwProvider->RegistrationHandle) && ETW_EVENT_ENABLED(Context, EventDescriptor))|| \ EventPipeHelper::IsEnabled(Context, EventDescriptor.Level, EventDescriptor.Keyword)) // // Using KEYWORDZERO means when checking the events category ignore the keyword // #define KEYWORDZERO 0x0 // // Use this macro to check if ETW is initialized and the category is enabled // #define ETW_TRACING_CATEGORY_ENABLED(Context, Level, Keyword) \ (ETW_TRACING_INITIALIZED(Context.EtwProvider->RegistrationHandle) && ETW_CATEGORY_ENABLED(Context, Level, Keyword)) #define ETWOnStartup(StartEventName, EndEventName) \ ETWTraceStartup trace##StartEventName##(Microsoft_Windows_DotNETRuntimePrivateHandle, &StartEventName, &StartupId, &EndEventName, &StartupId); #define ETWFireEvent(EventName) FireEtw##EventName(GetClrInstanceId()) #ifndef FEATURE_NATIVEAOT // Headers #include #include #include #include #endif //!FEATURE_NATIVEAOT #endif //!defined(HOST_UNIX) #else // FEATURE_EVENT_TRACE #include "../gc/env/etmdummy.h" #endif // FEATURE_EVENT_TRACE #ifndef FEATURE_NATIVEAOT #include "corprof.h" // g_nClrInstanceId is defined in Utilcode\Util.cpp. The definition goes into Utilcode.lib. // This enables both the VM and Utilcode to raise ETW events. extern UINT32 g_nClrInstanceId; #define GetClrInstanceId() (static_cast(g_nClrInstanceId)) #if defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) #define KEYWORDZERO 0x0 #define DEF_LTTNG_KEYWORD_ENABLED 1 #ifdef FEATURE_EVENT_TRACE #include "clrproviders.h" #endif // FEATURE_EVENT_TRACE #include "clrconfig.h" #endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) #if defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) /***************************************/ /* Tracing levels supported by CLR ETW */ /***************************************/ #define MAX_TRACE_LEVEL 6 // Maximum Number of Trace Levels supported #define TRACE_LEVEL_FATAL 1 // Abnormal exit or termination #define TRACE_LEVEL_ERROR 2 // Severe errors that need logging #define TRACE_LEVEL_WARNING 3 // Warnings such as allocation failure #define TRACE_LEVEL_INFORMATION 4 // Includes non-error cases such as Entry-Exit #define TRACE_LEVEL_VERBOSE 5 // Detailed traces from intermediate steps class XplatEventLoggerConfiguration { public: XplatEventLoggerConfiguration() = default; XplatEventLoggerConfiguration(XplatEventLoggerConfiguration const & other) = delete; XplatEventLoggerConfiguration(XplatEventLoggerConfiguration && other) { _provider = std::move(other._provider); _isValid = other._isValid; _enabledKeywords = other._enabledKeywords; _level = other._level; } ~XplatEventLoggerConfiguration() { _provider = nullptr; } void Parse(LPWSTR configString) { auto providerComponent = GetNextComponentString(configString); _provider = ParseProviderName(providerComponent); if (_provider == nullptr) { _isValid = false; return; } auto keywordsComponent = GetNextComponentString(providerComponent.End + 1); _enabledKeywords = ParseEnabledKeywordsMask(keywordsComponent); auto levelComponent = GetNextComponentString(keywordsComponent.End + 1); _level = ParseLevel(levelComponent); auto argumentComponent = GetNextComponentString(levelComponent.End + 1); _argument = ParseArgument(argumentComponent); _isValid = true; } bool IsValid() const { return _isValid; } LPCWSTR GetProviderName() const { return _provider; } uint64_t GetEnabledKeywordsMask() const { return _enabledKeywords; } uint32_t GetLevel() const { return _level; } LPCWSTR GetArgument() const { return _argument; } private: struct ComponentSpan { public: ComponentSpan(LPCWSTR start, LPCWSTR end) : Start(start), End(end) { } LPCWSTR Start; LPCWSTR End; }; ComponentSpan GetNextComponentString(LPCWSTR start) const { const WCHAR ComponentDelimiter = W(':'); const WCHAR * end = wcschr(start, ComponentDelimiter); if (end == nullptr) { end = start + wcslen(start); } return ComponentSpan(start, end); } NewArrayHolder ParseProviderName(ComponentSpan const & component) const { NewArrayHolder providerName = nullptr; if ((component.End - component.Start) != 0) { auto const length = component.End - component.Start; providerName = new WCHAR[length + 1]; wcsncpy(providerName, component.Start, length); providerName[length] = '\0'; } return providerName; } uint64_t ParseEnabledKeywordsMask(ComponentSpan const & component) const { auto enabledKeywordsMask = (uint64_t)(-1); if ((component.End - component.Start) != 0) { enabledKeywordsMask = _wcstoui64(component.Start, nullptr, 16); } return enabledKeywordsMask; } uint32_t ParseLevel(ComponentSpan const & component) const { int level = TRACE_LEVEL_VERBOSE; // Verbose if ((component.End - component.Start) != 0) { level = _wtoi(component.Start); } return level; } NewArrayHolder ParseArgument(ComponentSpan const & component) const { NewArrayHolder argument = nullptr; if ((component.End - component.Start) != 0) { auto const length = component.End - component.Start; argument = new WCHAR[length + 1]; wcsncpy(argument, component.Start, length); argument[length] = '\0'; } return argument; } NewArrayHolder _provider; uint64_t _enabledKeywords; uint32_t _level; NewArrayHolder _argument; bool _isValid; }; #endif // defined(FEATURE_PERFTRACING) || defined(FEATURE_EVENTSOURCE_XPLAT) #if defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) class XplatEventLoggerController { public: static void UpdateProviderContext(XplatEventLoggerConfiguration const &config) { if (!config.IsValid()) { return; } auto providerName = config.GetProviderName(); auto enabledKeywordsMask = config.GetEnabledKeywordsMask(); auto level = config.GetLevel(); if (_wcsicmp(providerName, W("*")) == 0 && enabledKeywordsMask == (ULONGLONG)(-1) && level == TRACE_LEVEL_VERBOSE) { ActivateAllKeywordsOfAllProviders(); } #ifdef FEATURE_EVENT_TRACE else { LTTNG_TRACE_CONTEXT *provider = GetProvider(providerName); if (provider == nullptr) { return; } provider->EnabledKeywordsBitmask = enabledKeywordsMask; provider->Level = level; provider->IsEnabled = true; } #endif } static void ActivateAllKeywordsOfAllProviders() { #ifdef FEATURE_EVENT_TRACE for (LTTNG_TRACE_CONTEXT * const provider : ALL_LTTNG_PROVIDERS_CONTEXT) { provider->EnabledKeywordsBitmask = (ULONGLONG)(-1); provider->Level = TRACE_LEVEL_VERBOSE; provider->IsEnabled = true; } #endif } private: #ifdef FEATURE_EVENT_TRACE static LTTNG_TRACE_CONTEXT * const GetProvider(LPCWSTR providerName) { auto length = wcslen(providerName); for (auto provider : ALL_LTTNG_PROVIDERS_CONTEXT) { if (_wcsicmp(provider->Name, providerName) == 0) { return provider; } } return nullptr; } #endif }; class XplatEventLogger { public: inline static BOOL IsEventLoggingEnabled() { static ConfigDWORD configEventLogging; return configEventLogging.val(CLRConfig::EXTERNAL_EnableEventLog); } #ifdef FEATURE_EVENT_TRACE inline static bool IsProviderEnabled(DOTNET_TRACE_CONTEXT providerCtx) { return providerCtx.LttngProvider->IsEnabled; } inline static bool IsKeywordEnabled(DOTNET_TRACE_CONTEXT providerCtx, UCHAR level, ULONGLONG keyword) { if (!providerCtx.LttngProvider->IsEnabled) { return false; } if ((level <= providerCtx.LttngProvider->Level) || (providerCtx.LttngProvider->Level == 0)) { if ((keyword == 0) || ((keyword & providerCtx.LttngProvider->EnabledKeywordsBitmask) != 0)) { return true; } } return false; } #endif /* This method is where COMPlus_LTTngConfig environment variable is parsed and is registered with the runtime provider context structs generated by src/scripts/genEventing.py. It expects the environment variable to look like: provider:keywords:level,provider:keywords:level (Notice the "arguments" part is missing compared to EventPipe configuration) Ex) Microsoft-Windows-DotNETRuntime:deadbeefdeadbeef:4,Microsoft-Windows-DotNETRuntimePrivate:deafbeefdeadbeef:5 */ static void InitializeLogger() { if (!IsEventLoggingEnabled()) { return; } LPWSTR xplatEventConfig = NULL; CLRConfig::GetConfigValue(CLRConfig::INTERNAL_LTTngConfig, &xplatEventConfig); auto configuration = XplatEventLoggerConfiguration(); auto configToParse = xplatEventConfig; if (configToParse == nullptr || *configToParse == L'\0') { XplatEventLoggerController::ActivateAllKeywordsOfAllProviders(); return; } while (configToParse != nullptr) { const WCHAR comma = W(','); auto end = wcschr(configToParse, comma); configuration.Parse(configToParse); XplatEventLoggerController::UpdateProviderContext(configuration); if (end == nullptr) { break; } configToParse = end + 1; } } }; #endif // defined(HOST_UNIX) && (defined(FEATURE_EVENT_TRACE) || defined(FEATURE_EVENTSOURCE_XPLAT)) #if defined(FEATURE_EVENT_TRACE) #ifdef FEATURE_PERFTRACING #include "../vm/eventpipeadaptertypes.h" #endif // FEATURE_PERFTRACING VOID EventPipeEtwCallbackDotNETRuntimeStress( _In_ LPCGUID SourceId, _In_ ULONG ControlCode, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ EventFilterDescriptor* FilterData, _Inout_opt_ PVOID CallbackContext); VOID EventPipeEtwCallbackDotNETRuntime( _In_ LPCGUID SourceId, _In_ ULONG ControlCode, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ EventFilterDescriptor* FilterData, _Inout_opt_ PVOID CallbackContext); VOID EventPipeEtwCallbackDotNETRuntimeRundown( _In_ LPCGUID SourceId, _In_ ULONG ControlCode, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ EventFilterDescriptor* FilterData, _Inout_opt_ PVOID CallbackContext); VOID EventPipeEtwCallbackDotNETRuntimePrivate( _In_ LPCGUID SourceId, _In_ ULONG ControlCode, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ EventFilterDescriptor* FilterData, _Inout_opt_ PVOID CallbackContext); #ifndef HOST_UNIX // Callback and stack support #if !defined(DONOT_DEFINE_ETW_CALLBACK) && !defined(DACCESS_COMPILE) extern "C" { /* ETW control callback * Desc: This function handles the ETW control * callback. * Ret: success or failure ***********************************************/ VOID EtwCallback( _In_ LPCGUID SourceId, _In_ ULONG ControlCode, _In_ UCHAR Level, _In_ ULONGLONG MatchAnyKeyword, _In_ ULONGLONG MatchAllKeyword, _In_opt_ PEVENT_FILTER_DESCRIPTOR FilterData, _Inout_opt_ PVOID CallbackContext); } // // User defined callback // #define MCGEN_PRIVATE_ENABLE_CALLBACK(RequestCode, Context, InOutBufferSize, Buffer) \ EtwCallback(NULL /* SourceId */, ((RequestCode)==WMI_ENABLE_EVENTS) ? EVENT_CONTROL_CODE_ENABLE_PROVIDER : EVENT_CONTROL_CODE_DISABLE_PROVIDER, 0 /* Level */, 0 /* MatchAnyKeyword */, 0 /* MatchAllKeyword */, NULL /* FilterData */, Context) // // User defined callback2 // #define MCGEN_PRIVATE_ENABLE_CALLBACK_V2(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) \ EtwCallback(SourceId, ControlCode, Level, MatchAnyKeyword, MatchAllKeyword, FilterData, CallbackContext) extern "C" { /* ETW callout * Desc: This function handles the ETW callout * Ret: success or failure ***********************************************/ VOID EtwCallout( REGHANDLE RegHandle, PCEVENT_DESCRIPTOR Descriptor, ULONG ArgumentCount, PEVENT_DATA_DESCRIPTOR EventData); } // // Call user defined callout // #define MCGEN_CALLOUT(RegHandle, Descriptor, NumberOfArguments, EventData) \ EtwCallout(RegHandle, Descriptor, NumberOfArguments, EventData) #endif //!DONOT_DEFINE_ETW_CALLBACK && !DACCESS_COMPILE #endif //!HOST_UNIX #include "clretwallmain.h" #if defined(FEATURE_PERFTRACING) class EventPipeHelper { public: static bool Enabled(); static bool IsEnabled(DOTNET_TRACE_CONTEXT Context, UCHAR Level, ULONGLONG Keyword); }; #endif // defined(FEATURE_PERFTRACING) #endif // FEATURE_EVENT_TRACE /**************************/ /* CLR ETW infrastructure */ /**************************/ // #CEtwTracer // On Windows Vista, ETW has gone through a major upgrade, and one of the most significant changes is the // introduction of the unified event provider model and APIs. The older architecture used the classic ETW // events. The new ETW architecture uses the manifest based events. To support both types of events at the // same time, we use the manpp tool for generating event macros that can be directly used to fire ETW events // from various components within the CLR. // (http://diagnostics/sites/etw/Lists/Announcements/DispForm.aspx?ID=10&Source=http%3A%2F%2Fdiagnostics%2Fsites%2Fetw%2Fdefault%2Easpx) // Every ETW provider has to Register itself to the system, so that when enabled, it is capable of firing // ETW events. file:../VM/eventtrace.cpp#Registration is where the actual Provider Registration takes place. // At process shutdown, a registered provider need to be unregistered. // file:../VM/eventtrace.cpp#Unregistration. Since ETW can also be enabled at any instant after the process // has started, one may want to do something useful when that happens (e.g enumerate all the loaded modules // in the system). To enable this, we have to implement a callback routine. // file:../VM/eventtrace.cpp#EtwCallback is CLR's implementation of the callback. // #include "daccess.h" class Module; class Assembly; class MethodDesc; class MethodTable; class BaseDomain; class AppDomain; class SString; class CrawlFrame; class LoaderAllocator; class AssemblyLoaderAllocator; struct AllLoggedTypes; class CrstBase; class BulkTypeEventLogger; class TypeHandle; class Thread; template class SetSHash; template class PtrSetSHashTraits; typedef SetSHash> MethodDescSet; // All ETW helpers must be a part of this namespace // We have auto-generated macros to directly fire the events // but in some cases, gathering the event payload information involves some work // and it can be done in a relevant helper class like the one's in this namespace namespace ETW { // Class to wrap the ETW infrastructure logic #if !defined(HOST_UNIX) class CEtwTracer { #if defined(FEATURE_EVENT_TRACE) ULONG RegGuids(LPCGUID ProviderId, PENABLECALLBACK EnableCallback, PVOID CallbackContext, PREGHANDLE RegHandle); #endif public: #ifdef FEATURE_EVENT_TRACE // Registers all the Event Tracing providers HRESULT Register(); // Unregisters all the Event Tracing providers HRESULT UnRegister(); #else HRESULT Register() { return S_OK; } HRESULT UnRegister() { return S_OK; } #endif // FEATURE_EVENT_TRACE }; #endif // !defined(HOST_UNIX) class LoaderLog; class MethodLog; // Class to wrap all the enumeration logic for ETW class EnumerationLog { friend class ETW::LoaderLog; friend class ETW::MethodLog; #ifdef FEATURE_EVENT_TRACE static VOID SendThreadRundownEvent(); static VOID SendGCRundownEvent(); static VOID IterateDomain(BaseDomain *pDomain, DWORD enumerationOptions); static VOID IterateAppDomain(AppDomain * pAppDomain, DWORD enumerationOptions); static VOID IterateCollectibleLoaderAllocator(AssemblyLoaderAllocator *pLoaderAllocator, DWORD enumerationOptions); static VOID IterateAssembly(Assembly *pAssembly, DWORD enumerationOptions); static VOID IterateModule(Module *pModule, DWORD enumerationOptions); static VOID EnumerationHelper(Module *moduleFilter, BaseDomain *domainFilter, DWORD enumerationOptions); static DWORD GetEnumerationOptionsFromRuntimeKeywords(); public: typedef union _EnumerationStructs { typedef enum _EnumerationOptions { None= 0x00000000, DomainAssemblyModuleLoad= 0x00000001, DomainAssemblyModuleUnload= 0x00000002, DomainAssemblyModuleDCStart= 0x00000004, DomainAssemblyModuleDCEnd= 0x00000008, JitMethodLoad= 0x00000010, JitMethodUnload= 0x00000020, JitMethodDCStart= 0x00000040, JitMethodDCEnd= 0x00000080, NgenMethodLoad= 0x00000100, NgenMethodUnload= 0x00000200, NgenMethodDCStart= 0x00000400, NgenMethodDCEnd= 0x00000800, ModuleRangeLoad= 0x00001000, ModuleRangeDCStart= 0x00002000, ModuleRangeDCEnd= 0x00004000, ModuleRangeLoadPrivate= 0x00008000, MethodDCStartILToNativeMap= 0x00010000, MethodDCEndILToNativeMap= 0x00020000, JitMethodILToNativeMap= 0x00040000, TypeUnload= 0x00080000, JittedMethodRichDebugInfo= 0x00100000, // Helpers ModuleRangeEnabledAny = ModuleRangeLoad | ModuleRangeDCStart | ModuleRangeDCEnd | ModuleRangeLoadPrivate, JitMethodLoadOrDCStartAny = JitMethodLoad | JitMethodDCStart | MethodDCStartILToNativeMap, JitMethodUnloadOrDCEndAny = JitMethodUnload | JitMethodDCEnd | MethodDCEndILToNativeMap, }EnumerationOptions; }EnumerationStructs; static VOID ProcessShutdown(); static VOID ModuleRangeRundown(); static VOID SendOneTimeRundownEvents(); static VOID StartRundown(); static VOID EndRundown(); static VOID EnumerateForCaptureState(); #else public: static VOID ProcessShutdown() {}; static VOID StartRundown() {}; static VOID EndRundown() {}; #endif // FEATURE_EVENT_TRACE }; // Class to wrap all the sampling logic for ETW class SamplingLog { #if defined(FEATURE_EVENT_TRACE) && !defined(HOST_UNIX) public: typedef enum _EtwStackWalkStatus { Completed = 0, UnInitialized = 1, InProgress = 2 } EtwStackWalkStatus; private: static const UINT8 s_MaxStackSize=100; UINT32 m_FrameCount; SIZE_T m_EBPStack[SamplingLog::s_MaxStackSize]; VOID Append(SIZE_T currentFrame); EtwStackWalkStatus SaveCurrentStack(int skipTopNFrames=1); public: static ULONG SendStackTrace(MCGEN_TRACE_CONTEXT TraceContext, PCEVENT_DESCRIPTOR Descriptor, LPCGUID EventGuid); EtwStackWalkStatus GetCurrentThreadsCallStack(UINT32 *frameCount, PVOID **Stack); #endif // FEATURE_EVENT_TRACE && !defined(HOST_UNIX) }; // Class to wrap all Loader logic for ETW class LoaderLog { friend class ETW::EnumerationLog; #if defined(FEATURE_EVENT_TRACE) static VOID SendModuleEvent(Module *pModule, DWORD dwEventOptions, BOOL bFireDomainModuleEvents=FALSE); static ULONG SendModuleRange(_In_ Module *pModule, _In_ DWORD dwEventOptions); static VOID SendAssemblyEvent(Assembly *pAssembly, DWORD dwEventOptions); static VOID SendDomainEvent(BaseDomain *pBaseDomain, DWORD dwEventOptions, LPCWSTR wszFriendlyName=NULL); public: typedef union _LoaderStructs { typedef enum _AppDomainFlags { DefaultDomain=0x1, ExecutableDomain=0x2, SharedDomain=0x4 }AppDomainFlags; typedef enum _AssemblyFlags { DomainNeutralAssembly=0x1, DynamicAssembly=0x2, NativeAssembly=0x4, CollectibleAssembly=0x8, ReadyToRunAssembly=0x10, }AssemblyFlags; typedef enum _ModuleFlags { DomainNeutralModule=0x1, NativeModule=0x2, DynamicModule=0x4, ManifestModule=0x8, IbcOptimized=0x10, ReadyToRunModule=0x20, PartialReadyToRunModule=0x40, }ModuleFlags; typedef enum _RangeFlags { HotRange=0x0 }RangeFlags; }LoaderStructs; static VOID DomainLoadReal(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName=NULL); static VOID DomainLoad(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName = NULL) { if (ETW_PROVIDER_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER)) { DomainLoadReal(pDomain, wszFriendlyName); } } static VOID DomainUnload(AppDomain *pDomain); static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator); static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule); #else public: static VOID DomainLoad(BaseDomain *pDomain, _In_opt_ LPWSTR wszFriendlyName=NULL) {}; static VOID DomainUnload(AppDomain *pDomain) {}; static VOID CollectibleLoaderAllocatorUnload(AssemblyLoaderAllocator *pLoaderAllocator) {}; static VOID ModuleLoad(Module *pModule, LONG liReportedSharedModule) {}; #endif // FEATURE_EVENT_TRACE }; // Class to wrap all Method logic for ETW class MethodLog { friend class ETW::EnumerationLog; #ifdef FEATURE_EVENT_TRACE static VOID SendEventsForJitMethods(BaseDomain *pDomainFilter, LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions); static VOID SendEventsForJitMethodsHelper( LoaderAllocator *pLoaderAllocatorFilter, DWORD dwEventOptions, BOOL fLoadOrDCStart, BOOL fUnloadOrDCEnd, BOOL fSendMethodEvent, BOOL fSendILToNativeMapEvent, BOOL fSendRichDebugInfoEvent, BOOL fGetCodeIds); static VOID SendEventsForNgenMethods(Module *pModule, DWORD dwEventOptions); static VOID SendMethodJitStartEvent(MethodDesc *pMethodDesc, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL); static VOID SendMethodILToNativeMapEvent(MethodDesc * pMethodDesc, DWORD dwEventOptions, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId); static VOID SendMethodRichDebugInfo(MethodDesc * pMethodDesc, PCODE pNativeCodeStartAddress, DWORD nativeCodeId, ReJITID ilCodeId, MethodDescSet* sentMethodDetailsSet); static VOID SendMethodEvent(MethodDesc *pMethodDesc, DWORD dwEventOptions, BOOL bIsJit, SString *namespaceOrClassName=NULL, SString *methodName=NULL, SString *methodSignature=NULL, PCODE pNativeCodeStartAddress = 0, PrepareCodeConfig *pConfig = NULL, MethodDescSet* sentMethodDetailsSet = NULL); static VOID SendHelperEvent(ULONGLONG ullHelperStartAddress, ULONG ulHelperSize, LPCWSTR pHelperName); public: typedef union _MethodStructs { typedef enum _MethodFlags { DynamicMethod=0x1, GenericMethod=0x2, SharedGenericCode=0x4, JittedMethod=0x8, JitHelperMethod=0x10, ProfilerRejectedPrecompiledCode=0x20, ReadyToRunRejectedPrecompiledCode=0x40, // 0x80 to 0x200 are used for the optimization tier }MethodFlags; typedef enum _MethodExtent { HotSection=0x00000000, ColdSection=0x10000000 }MethodExtent; }MethodStructs; static const UINT8 MethodFlagsJitOptimizationTierShift = 7; static const unsigned int MethodFlagsJitOptimizationTierLowMask = 0x7; static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc); static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint); static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); static VOID SendMethodDetailsEvent(MethodDesc *pMethodDesc); static VOID SendNonDuplicateMethodDetailsEvent(MethodDesc* pMethodDesc, MethodDescSet* set); static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName); static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers); static VOID MethodRestored(MethodDesc * pMethodDesc); static VOID MethodTableRestored(MethodTable * pMethodTable); static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc); static VOID LogMethodInstrumentationData(MethodDesc* method, uint32_t cbData, BYTE *data, TypeHandle* pTypeHandles, uint32_t numTypeHandles, MethodDesc** pMethods, uint32_t numMethods); #else // FEATURE_EVENT_TRACE public: static VOID GetR2RGetEntryPointStart(MethodDesc *pMethodDesc) {}; static VOID GetR2RGetEntryPoint(MethodDesc *pMethodDesc, PCODE pEntryPoint) {}; static VOID MethodJitting(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature); static VOID MethodJitted(MethodDesc *pMethodDesc, SString *namespaceOrClassName, SString *methodName, SString *methodSignature, PCODE pNativeCodeStartAddress, PrepareCodeConfig *pConfig); static VOID StubInitialized(ULONGLONG ullHelperStartAddress, LPCWSTR pHelperName) {}; static VOID StubsInitialized(PVOID *pHelperStartAddress, PVOID *pHelperNames, LONG ulNoOfHelpers) {}; static VOID MethodRestored(MethodDesc * pMethodDesc) {}; static VOID MethodTableRestored(MethodTable * pMethodTable) {}; static VOID DynamicMethodDestroyed(MethodDesc *pMethodDesc) {}; static VOID LogMethodInstrumentationData(MethodDesc* method, uint32_t cbData, BYTE *data, TypeHandle* pTypeHandles, uint32_t numTypeHandles, MethodDesc** pMethods, uint32_t numMethods) {}; #endif // FEATURE_EVENT_TRACE }; // Class to wrap all Security logic for ETW class SecurityLog { #ifdef FEATURE_EVENT_TRACE public: static VOID StrongNameVerificationStart(DWORD dwInFlags, _In_ LPWSTR strFullyQualifiedAssemblyName); static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_ LPWSTR strFullyQualifiedAssemblyName); static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, LPCWSTR wszModuleName, DWORD dwAppDomain); static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsCritical, BOOL fIsTreatAsSafe); static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, LPCWSTR wszModuleName, DWORD dwAppDomain); static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsCritical, BOOL fIsTreatAsSafe); static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain); static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsAllCritical, BOOL fIsAllTransparent, BOOL fIsTreatAsSafe, BOOL fIsOpportunisticallyCritical, DWORD dwSecurityRuleSet); static void FireTokenTransparencyComputationStart(DWORD dwToken, LPCWSTR wszModuleName, DWORD dwAppDomain); static void FireTokenTransparencyComputationEnd(DWORD dwToken, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsCritical, BOOL fIsTreatAsSafe); static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, LPCWSTR wszModuleName, DWORD dwAppDomain); static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsAllCritical, BOOL fIsAllTransparent, BOOL fIsCritical, BOOL fIsTreatAsSafe); #else public: static VOID StrongNameVerificationStart(DWORD dwInFlags, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; static VOID StrongNameVerificationStop(DWORD dwInFlags,ULONG result, _In_z_ LPWSTR strFullyQualifiedAssemblyName) {}; static void FireFieldTransparencyComputationStart(LPCWSTR wszFieldName, LPCWSTR wszModuleName, DWORD dwAppDomain) {}; static void FireFieldTransparencyComputationEnd(LPCWSTR wszFieldName, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsCritical, BOOL fIsTreatAsSafe) {}; static void FireMethodTransparencyComputationStart(LPCWSTR wszMethodName, LPCWSTR wszModuleName, DWORD dwAppDomain) {}; static void FireMethodTransparencyComputationEnd(LPCWSTR wszMethodName, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsCritical, BOOL fIsTreatAsSafe) {}; static void FireModuleTransparencyComputationStart(LPCWSTR wszModuleName, DWORD dwAppDomain) {}; static void FireModuleTransparencyComputationEnd(LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsAllCritical, BOOL fIsAllTransparent, BOOL fIsTreatAsSafe, BOOL fIsOpportunisticallyCritical, DWORD dwSecurityRuleSet) {}; static void FireTokenTransparencyComputationStart(DWORD dwToken, LPCWSTR wszModuleName, DWORD dwAppDomain) {}; static void FireTokenTransparencyComputationEnd(DWORD dwToken, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsCritical, BOOL fIsTreatAsSafe) {}; static void FireTypeTransparencyComputationStart(LPCWSTR wszTypeName, LPCWSTR wszModuleName, DWORD dwAppDomain) {}; static void FireTypeTransparencyComputationEnd(LPCWSTR wszTypeName, LPCWSTR wszModuleName, DWORD dwAppDomain, BOOL fIsAllCritical, BOOL fIsAllTransparent, BOOL fIsCritical, BOOL fIsTreatAsSafe) {}; #endif // FEATURE_EVENT_TRACE }; // Class to wrap all Binder logic for ETW class BinderLog { public: typedef union _BinderStructs { typedef enum _NGENBINDREJECT_REASON { NGEN_BIND_START_BIND = 0, NGEN_BIND_NO_INDEX = 1, NGEN_BIND_SYSTEM_ASSEMBLY_NOT_AVAILABLE = 2, NGEN_BIND_NO_NATIVE_IMAGE = 3, NGEN_BIND_REJECT_CONFIG_MASK = 4, NGEN_BIND_FAIL = 5, NGEN_BIND_INDEX_CORRUPTION = 6, NGEN_BIND_REJECT_TIMESTAMP = 7, NGEN_BIND_REJECT_NATIVEIMAGE_NOT_FOUND = 8, NGEN_BIND_REJECT_IL_SIG = 9, NGEN_BIND_REJECT_LOADER_EVAL_FAIL = 10, NGEN_BIND_MISSING_FOUND = 11, NGEN_BIND_REJECT_HOSTASM = 12, NGEN_BIND_REJECT_IL_NOT_FOUND = 13, NGEN_BIND_REJECT_APPBASE_NOT_FILE = 14, NGEN_BIND_BIND_DEPEND_REJECT_REF_DEF_MISMATCH = 15, NGEN_BIND_BIND_DEPEND_REJECT_NGEN_SIG = 16, NGEN_BIND_APPLY_EXTERNAL_RELOCS_FAILED = 17, NGEN_BIND_SYSTEM_ASSEMBLY_NATIVEIMAGE_NOT_AVAILABLE = 18, NGEN_BIND_ASSEMBLY_HAS_DIFFERENT_GRANT = 19, NGEN_BIND_ASSEMBLY_NOT_DOMAIN_NEUTRAL = 20, NGEN_BIND_NATIVEIMAGE_VERSION_MISMATCH = 21, NGEN_BIND_LOADFROM_NOT_ALLOWED = 22, NGEN_BIND_DEPENDENCY_HAS_DIFFERENT_IDENTITY = 23 } NGENBINDREJECT_REASON; } BinderStructs; }; // Class to wrap all Exception logic for ETW class ExceptionLog { public: #ifdef FEATURE_EVENT_TRACE static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException); static VOID ExceptionThrownEnd(); static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); static VOID ExceptionCatchEnd(); static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); static VOID ExceptionFinallyEnd(); static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP); static VOID ExceptionFilterEnd(); #else static VOID ExceptionThrown(CrawlFrame *pCf, BOOL bIsReThrownException, BOOL bIsNewException) {}; static VOID ExceptionThrownEnd() {}; static VOID ExceptionCatchBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; static VOID ExceptionCatchEnd() {}; static VOID ExceptionFinallyBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; static VOID ExceptionFinallyEnd() {}; static VOID ExceptionFilterBegin(MethodDesc * pMethodDesc, PVOID pEntryEIP) {}; static VOID ExceptionFilterEnd() {}; #endif // FEATURE_EVENT_TRACE typedef union _ExceptionStructs { typedef enum _ExceptionThrownFlags { HasInnerException=0x1, IsNestedException=0x2, IsReThrownException=0x4, IsCSE=0x8, IsCLSCompliant=0x10 }ExceptionThrownFlags; }ExceptionStructs; }; // Class to wrap all Contention logic for ETW class ContentionLog { public: typedef union _ContentionStructs { typedef enum _ContentionFlags { ManagedContention=0, NativeContention=1 } ContentionFlags; } ContentionStructs; }; // Class to wrap all Interop logic for ETW class InteropLog { public: }; // Class to wrap all Information logic for ETW class InfoLog { public: typedef union _InfoStructs { typedef enum _StartupMode { ManagedExe=0x1, HostedCLR=0x2, IJW=0x4, COMActivated=0x8, Other=0x10 }StartupMode; typedef enum _Sku { DesktopCLR=0x1, CoreCLR=0x2, Mono=0x4 }Sku; typedef enum _EtwMode { Normal=0x0, Callback=0x1 }EtwMode; }InfoStructs; #ifdef FEATURE_EVENT_TRACE static VOID RuntimeInformation(INT32 type); #else static VOID RuntimeInformation(INT32 type) {}; #endif // FEATURE_EVENT_TRACE }; class CodeSymbolLog { public: #ifdef FEATURE_EVENT_TRACE static VOID EmitCodeSymbols(Module* pModule); static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes); static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead); #else static VOID EmitCodeSymbols(Module* pModule) {} static HRESULT GetInMemorySymbolsLength(Module* pModule, DWORD* pCountSymbolBytes) { return S_OK; } static HRESULT ReadInMemorySymbols(Module* pmodule, DWORD symbolsReadOffset, BYTE* pSymbolBytes, DWORD countSymbolBytes, DWORD* pCountSymbolBytesRead) { return S_OK; } #endif // FEATURE_EVENT_TRACE }; #define DISABLE_CONSTRUCT_COPY(T) \ T() = delete; \ T(const T &) = delete; \ T &operator =(const T &) = delete // Class to wrap all Compilation logic for ETW class CompilationLog { public: class Runtime { public: #ifdef FEATURE_EVENT_TRACE static bool IsEnabled(); #else static bool IsEnabled() { return false; } #endif DISABLE_CONSTRUCT_COPY(Runtime); }; class Rundown { public: #ifdef FEATURE_EVENT_TRACE static bool IsEnabled(); #else static bool IsEnabled() { return false; } #endif DISABLE_CONSTRUCT_COPY(Rundown); }; // Class to wrap all TieredCompilation logic for ETW class TieredCompilation { private: static void GetSettings(UINT32 *flagsRef); public: class Runtime { public: #ifdef FEATURE_EVENT_TRACE static bool IsEnabled(); static void SendSettings(); static void SendPause(); static void SendResume(UINT32 newMethodCount); static void SendBackgroundJitStart(UINT32 pendingMethodCount); static void SendBackgroundJitStop(UINT32 pendingMethodCount, UINT32 jittedMethodCount); #else static bool IsEnabled() { return false; } static void SendSettings() {} static void SendPause() {} static void SendResume(UINT32 newMethodCount) {} static void SendBackgroundJitStart(UINT32 pendingMethodCount) {} static void SendBackgroundJitStop(UINT32 pendingMethodCount, UINT32 jittedMethodCount) {} #endif DISABLE_CONSTRUCT_COPY(Runtime); }; class Rundown { public: #ifdef FEATURE_EVENT_TRACE static bool IsEnabled(); static void SendSettings(); #else static bool IsEnabled() { return false; } static void SendSettings() {} #endif DISABLE_CONSTRUCT_COPY(Rundown); }; DISABLE_CONSTRUCT_COPY(TieredCompilation); }; DISABLE_CONSTRUCT_COPY(CompilationLog); }; #undef DISABLE_CONSTRUCT_COPY }; #define ETW_IS_TRACE_ON(level) ( FALSE ) // for fusion which is eventually going to get removed #define ETW_IS_FLAG_ON(flag) ( FALSE ) // for fusion which is eventually going to get removed // Commonly used constats for ETW Assembly Loader and Assembly Binder events. #define ETWLoadContextNotAvailable (LOADCTX_TYPE_HOSTED + 1) #define ETWAppDomainIdNotAvailable 0 // Valid AppDomain IDs start from 1 #define ETWFieldUnused 0 // Indicates that a particular field in the ETW event payload template is currently unused. #define ETWLoaderLoadTypeNotAvailable 0 // Static or Dynamic Load is only valid at LoaderPhaseStart and LoaderPhaseEnd events - for other events, 0 indicates "not available" #define ETWLoaderStaticLoad 0 // Static reference load #define ETWLoaderDynamicLoad 1 // Dynamic assembly load #if defined(FEATURE_EVENT_TRACE) && !defined(HOST_UNIX) // // The ONE and only ONE global instantiation of this class // extern ETW::CEtwTracer * g_pEtwTracer; EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_DOTNET_Context; EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context; EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context; EXTERN_C DOTNET_TRACE_CONTEXT MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_DOTNET_Context; // // Special Handling of Startup events // // "mc.exe -MOF" already generates this block for XP-supported builds inside ClrEtwAll.h; // on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so // we manually place it here. ETW_INLINE ULONG CoMofTemplate_h( _In_ REGHANDLE RegHandle, _In_ PCEVENT_DESCRIPTOR Descriptor, _In_opt_ LPCGUID EventGuid, _In_ const unsigned short ClrInstanceID ) { #define ARGUMENT_COUNT_h 1 ULONG Error = ERROR_SUCCESS; typedef struct _MCGEN_TRACE_BUFFER { EVENT_TRACE_HEADER Header; EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_h]; } MCGEN_TRACE_BUFFER; MCGEN_TRACE_BUFFER TraceBuf; PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; EventDataDescCreate(&EventData[0], &ClrInstanceID, sizeof(const unsigned short) ); { Error = EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_h, EventData); } #ifdef MCGEN_CALLOUT MCGEN_CALLOUT(RegHandle, Descriptor, ARGUMENT_COUNT_h, EventData); #endif return Error; } class ETWTraceStartup { REGHANDLE TraceHandle; PCEVENT_DESCRIPTOR EventStartDescriptor; LPCGUID EventStartGuid; PCEVENT_DESCRIPTOR EventEndDescriptor; LPCGUID EventEndGuid; public: ETWTraceStartup(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventStartDescriptor, LPCGUID _EventStartGuid, PCEVENT_DESCRIPTOR _EventEndDescriptor, LPCGUID _EventEndGuid) { TraceHandle = _TraceHandle; EventStartDescriptor = _EventStartDescriptor; EventEndDescriptor = _EventEndDescriptor; EventStartGuid = _EventStartGuid; EventEndGuid = _EventEndGuid; StartupTraceEvent(TraceHandle, EventStartDescriptor, EventStartGuid); } ~ETWTraceStartup() { StartupTraceEvent(TraceHandle, EventEndDescriptor, EventEndGuid); } static void StartupTraceEvent(REGHANDLE _TraceHandle, PCEVENT_DESCRIPTOR _EventDescriptor, LPCGUID _EventGuid) { EVENT_DESCRIPTOR desc = *_EventDescriptor; if(ETW_TRACING_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context, desc)) { CoMofTemplate_h(MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_Context.RegistrationHandle, _EventDescriptor, _EventGuid, GetClrInstanceId()); } } }; // "mc.exe -MOF" already generates this block for XP-supported builds inside ClrEtwAll.h; // on Vista+ builds, mc is run without -MOF, and we still have code that depends on it, so // we manually place it here. FORCEINLINE BOOLEAN __stdcall McGenEventTracingEnabled( _In_ PMCGEN_TRACE_CONTEXT EnableInfo, _In_ PCEVENT_DESCRIPTOR EventDescriptor ) { if(!EnableInfo){ return FALSE; } // // Check if the event Level is lower than the level at which // the channel is enabled. // If the event Level is 0 or the channel is enabled at level 0, // all levels are enabled. // if ((EventDescriptor->Level <= EnableInfo->Level) || // This also covers the case of Level == 0. (EnableInfo->Level == 0)) { // // Check if Keyword is enabled // if ((EventDescriptor->Keyword == (ULONGLONG)0) || ((EventDescriptor->Keyword & EnableInfo->MatchAnyKeyword) && ((EventDescriptor->Keyword & EnableInfo->MatchAllKeyword) == EnableInfo->MatchAllKeyword))) { return TRUE; } } return FALSE; } ETW_INLINE ULONG ETW::SamplingLog::SendStackTrace( MCGEN_TRACE_CONTEXT TraceContext, PCEVENT_DESCRIPTOR Descriptor, LPCGUID EventGuid) { #define ARGUMENT_COUNT_CLRStackWalk 5 ULONG Result = ERROR_SUCCESS; typedef struct _MCGEN_TRACE_BUFFER { EVENT_TRACE_HEADER Header; EVENT_DATA_DESCRIPTOR EventData[ARGUMENT_COUNT_CLRStackWalk]; } MCGEN_TRACE_BUFFER; REGHANDLE RegHandle = TraceContext.RegistrationHandle; if(!TraceContext.IsEnabled || !McGenEventTracingEnabled(&TraceContext, Descriptor)) { return Result; } PVOID *Stack = NULL; UINT32 FrameCount = 0; ETW::SamplingLog stackObj; if(stackObj.GetCurrentThreadsCallStack(&FrameCount, &Stack) == ETW::SamplingLog::Completed) { UCHAR Reserved1=0, Reserved2=0; UINT16 ClrInstanceId = GetClrInstanceId(); MCGEN_TRACE_BUFFER TraceBuf; PEVENT_DATA_DESCRIPTOR EventData = TraceBuf.EventData; EventDataDescCreate(&EventData[0], &ClrInstanceId, sizeof(const UINT16) ); EventDataDescCreate(&EventData[1], &Reserved1, sizeof(const UCHAR) ); EventDataDescCreate(&EventData[2], &Reserved2, sizeof(const UCHAR) ); EventDataDescCreate(&EventData[3], &FrameCount, sizeof(const unsigned int) ); EventDataDescCreate(&EventData[4], Stack, sizeof(PVOID) * FrameCount ); return EventWrite(RegHandle, Descriptor, ARGUMENT_COUNT_CLRStackWalk, EventData); } return Result; }; #endif // FEATURE_EVENT_TRACE && !defined(HOST_UNIX) #ifdef FEATURE_EVENT_TRACE #ifdef TARGET_X86 struct CallStackFrame { struct CallStackFrame* m_Next; SIZE_T m_ReturnAddress; }; #endif // TARGET_X86 #endif // FEATURE_EVENT_TRACE #if defined(FEATURE_EVENT_TRACE) && !defined(HOST_UNIX) FORCEINLINE BOOLEAN __stdcall McGenEventProviderEnabled( _In_ PMCGEN_TRACE_CONTEXT Context, _In_ UCHAR Level, _In_ ULONGLONG Keyword ) { if(!Context) { return FALSE; } // // Check if the event Level is lower than the level at which // the channel is enabled. // If the event Level is 0 or the channel is enabled at level 0, // all levels are enabled. // if ((Level <= Context->Level) || // This also covers the case of Level == 0. (Context->Level == 0)) { // // Check if Keyword is enabled // if ((Keyword == (ULONGLONG)0) || ((Keyword & Context->MatchAnyKeyword) && ((Keyword & Context->MatchAllKeyword) == Context->MatchAllKeyword))) { return TRUE; } } return FALSE; } #endif // FEATURE_EVENT_TRACE && !defined(HOST_UNIX) #endif // !FEATURE_NATIVEAOT // These parts of the ETW namespace are common for both FEATURE_NATIVEAOT and // !FEATURE_NATIVEAOT builds. struct ProfilingScanContext; class Object; namespace ETW { // Class to wrap the logging of threads (runtime and rundown providers) class ThreadLog { private: static DWORD GetEtwThreadFlags(Thread * pThread); public: static VOID FireThreadCreated(Thread * pThread); static VOID FireThreadDC(Thread * pThread); }; }; #endif //_ETWTRACER_HXX_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ex.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #if !defined(_EX_H_) #define _EX_H_ #ifdef HOST_UNIX #define EX_TRY_HOLDER \ HardwareExceptionHolder \ NativeExceptionHolderCatchAll __exceptionHolder; \ __exceptionHolder.Push(); \ #else // HOST_UNIX #define EX_TRY_HOLDER #endif // HOST_UNIX #include "sstring.h" #include "crtwrap.h" #include "winwrap.h" #include "corerror.h" #include "stresslog.h" #include "staticcontract.h" #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif //=========================================================================================== // These abstractions hide the difference between legacy desktop CLR's (that don't support // side-by-side-inproc and rely on a fixed SEH code to identify managed exceptions) and // new CLR's that support side-by-side inproc. // // The new CLR's use a different set of SEH codes to avoid conflicting with the legacy CLR's. // In addition, to distinguish between EH's raised by different inproc instances of the CLR, // the module handle of the owning CLR is stored in ExceptionRecord.ExceptionInformation[4]. // // (Note: all existing SEH's use either only slot [0] or no slots at all. We are leaving // slots [1] thru [3] open for future expansion.) //=========================================================================================== // Is this exception code one of the special CLR-specific SEH codes that participate in the // instance-tagging scheme? BOOL IsInstanceTaggedSEHCode(DWORD dwExceptionCode); // This set of overloads generates the NumberParameters and ExceptionInformation[] array to // pass to RaiseException(). // // Parameters: // exceptionArgs: a fixed-size array of size INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE. // This will get filled in by this function. (The module handle goes // in the last slot if this is a side-by-side-inproc enabled build.) // // exceptionArg1... up to four arguments that go in slots [0]..[3]. These depends // the specific requirements of your exception code. // // Returns: // The NumberParameters to pass to RaiseException(). // // Basically, this is either INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE or the count of your // fixed arguments depending on whether this tagged-SEH-enabled build. // // This function is not permitted to fail. #define INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE 5 DWORD MarkAsThrownByUs(/*out*/ ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE]); DWORD MarkAsThrownByUs(/*out*/ ULONG_PTR exceptionArgs[INSTANCE_TAGGED_SEH_PARAM_ARRAY_SIZE], ULONG_PTR arg0); // (the existing system can support more overloads up to 4 fixed arguments but we don't need them at this time.) // Given an exception record, checks if it's exception code matches a specific exception code // *and* whether it was tagged by the calling instance of the CLR. // // If this is a non-tagged-SEH-enabled build, it is blindly assumed to be tagged by the // calling instance of the CLR. BOOL WasThrownByUs(const EXCEPTION_RECORD *pcER, DWORD dwExceptionCode); //----------------------------------------------------------------------------------- // The following group wraps the basic abstracts specifically for EXCEPTION_COMPLUS. //----------------------------------------------------------------------------------- BOOL IsComPlusException(const EXCEPTION_RECORD *pcER); VOID RaiseComPlusException(); //=========================================================================================== //=========================================================================================== //------------------------------------------------------------------------------------------- // This routine will generate the most descriptive possible error message for an hresult. // It will generate at minimum the hex value. It will also try to generate the symbolic name // (E_POINTER) and the friendly description (from the message tables.) // // bNoGeekStuff suppresses hex HR codes. Use this sparingly as most error strings generated by the // CLR are aimed at developers, not end-users. //------------------------------------------------------------------------------------------- void GetHRMsg(HRESULT hresult, SString &result, BOOL bNoGeekStuff = FALSE); //------------------------------------------------------------------------------------------- // Similar to GetHRMsg but phrased for top-level exception message. //------------------------------------------------------------------------------------------- void GenerateTopLevelHRExceptionMessage(HRESULT hresult, SString &result); // --------------------------------------------------------------------------- // We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid // duing exception handling. GetCurrentExceptionPointers returns the saved data. // --------------------------------------------------------------------------- void GetCurrentExceptionPointers(PEXCEPTION_POINTERS pExceptionInfo DEBUG_ARG(bool checkExceptionRecordLocation)); // --------------------------------------------------------------------------- // We save current ExceptionPointers using VectoredExceptionHandler. The save data is only valid // duing exception handling. GetCurrentExceptionCode returns the current exception code. // --------------------------------------------------------------------------- DWORD GetCurrentExceptionCode(); // --------------------------------------------------------------------------- // Standard exception hierarchy & infrastructure for library code & EE // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Exception class. Abstract root exception of our hierarchy. // --------------------------------------------------------------------------- class Exception; class SEHException; // Exception hierarchy: /* GetInstanceType Exception | |-> HRException Y | | | |-> HRMsgException | |-> COMException | |-> SEHException Y | |-> DelegatingException Y | |-> OutOfMemoryException Y | |-> CLRException Y | |-> EEException Y | | | |-> EEMessageException | | | |-> EEResourceException | | | |-> EECOMException | | | |-> EEFieldException | | | |-> EEMethodException | | | |-> EEArgumentException | | | |-> EETypeLoadException | | | |-> EEFileLoadException | |-> ObjrefException Y | |-> CLRLastThrownObjectException Y */ class Exception { friend bool DebugIsEECxxExceptionPointer(void* pv); private: static const int c_type = 0x524f4f54; // 'ROOT' static Exception * g_OOMException; static Exception * g_SOException; protected: Exception *m_innerException; public: Exception() {LIMITED_METHOD_DAC_CONTRACT; m_innerException = NULL;} virtual ~Exception() {LIMITED_METHOD_DAC_CONTRACT; if (m_innerException != NULL) Exception::Delete(m_innerException); } #ifdef DACCESS_COMPILE void * operator new(size_t size); void operator delete(void* ptr); #endif virtual BOOL IsDomainBound() {return m_innerException!=NULL && m_innerException->IsDomainBound();} ; virtual HRESULT GetHR() = 0; virtual void GetMessage(SString &s); virtual IErrorInfo *GetErrorInfo() { LIMITED_METHOD_CONTRACT; return NULL; } virtual HRESULT SetErrorInfo() { LIMITED_METHOD_CONTRACT; return S_OK; } void SetInnerException(Exception * pInnerException) { LIMITED_METHOD_CONTRACT; m_innerException = pInnerException; } // Dynamic type query for catchers static int GetType() { LIMITED_METHOD_CONTRACT; return c_type; } // !!! If GetInstanceType is implemented, IsSameInstanceType should be implemented virtual int GetInstanceType() = 0; virtual BOOL IsType(int type) {LIMITED_METHOD_CONTRACT; return type == c_type; } // This is used in CLRException::GetThrowable to detect if we are in a recursive situation. virtual BOOL IsSameInstanceType(Exception *pException) = 0; // Will create a new instance of the Exception. Note that this will // be free of app domain or thread affinity. Not every type of exception // can be cloned with full fidelity. virtual Exception *Clone(); // DomainBoundClone is a specialized form of cloning which is guaranteed // to provide full fidelity. However, the result is bound to the current // app domain and should not be leaked. Exception *DomainBoundClone(); class HandlerState { enum CaughtFlags { Caught = 1, CaughtSO = 2, CaughtCxx = 4, }; DWORD m_dwFlags; public: Exception* m_pExceptionPtr; HandlerState(); void CleanupTry(); void SetupCatch(INDEBUG_COMMA(_In_z_ const char * szFile) int lineNum); void SucceedCatch(); BOOL DidCatch() { return (m_dwFlags & Caught); } void SetCaught() { m_dwFlags |= Caught; } BOOL DidCatchCxx() { return (m_dwFlags & CaughtCxx); } void SetCaughtCxx() { m_dwFlags |= CaughtCxx; } }; // Is this exception type considered "uncatchable"? BOOL IsTerminal(); // Is this exception type considered "transient" (would a retry possibly succeed)? BOOL IsTransient(); static BOOL IsTransient(HRESULT hr); // Get an HRESULT's source representation, if known static LPCSTR GetHRSymbolicName(HRESULT hr); static Exception* GetOOMException(); // Preallocated exceptions: If there is a preallocated instance of some // subclass of Exception, override this function and return a correct // value. The default implementation returns constant FALSE virtual BOOL IsPreallocatedException(); BOOL IsPreallocatedOOMException(); static void Delete(Exception* pvMemory); protected: // This virtual method must be implemented by any non abstract Exception // derived class. It must allocate a NEW exception of the identical type and // copy all the relevant fields from the current exception to the new one. // It is NOT responsible however for copying the inner exception. This // will be handled by the base Exception class. virtual Exception *CloneHelper(); // This virtual method must be implemented by Exception subclasses whose // DomainBoundClone behavior is different than their normal clone behavior. // It must allocate a NEW exception of the identical type and // copy all the relevant fields from the current exception to the new one. // It is NOT responsible however for copying the inner exception. This // will be handled by the base Exception class. virtual Exception *DomainBoundCloneHelper() { return CloneHelper(); } }; #if 1 inline void Exception__Delete(Exception* pvMemory) { Exception::Delete(pvMemory); } using ExceptionHolder = SpecializedWrapper; #else //------------------------------------------------------------------------------ // class ExceptionHolder // // This is a very lightweight holder class for use inside the EX_TRY family // of macros. It is based on the standard Holder classes, but has been // highly specialized for this one function, so that extra code can be // removed, and the resulting code can be simple enough for all of the // non-exceptional-case code to be inlined. class ExceptionHolder { private: Exception *m_value; BOOL m_acquired; public: FORCEINLINE ExceptionHolder(Exception *pException = NULL, BOOL take = TRUE) : m_value(pException) { m_acquired = pException && take; } FORCEINLINE ~ExceptionHolder() { if (m_acquired) { Exception::Delete(m_value); } } Exception* operator->() { return m_value; } void operator=(Exception *p) { Release(); m_value = p; Acquire(); } BOOL IsNull() { return m_value == NULL; } operator Exception*() { return m_value; } Exception* GetValue() { return m_value; } void SuppressRelease() { m_acquired = FALSE; } private: void Acquire() { _ASSERTE(!m_acquired); if (!IsNull()) { m_acquired = TRUE; } } void Release() { if (m_acquired) { _ASSERTE(!IsNull()); Exception::Delete(m_value); m_acquired = FALSE; } } }; #endif // --------------------------------------------------------------------------- // HRException class. Implements exception API for exceptions generated from HRESULTs // --------------------------------------------------------------------------- class HRException : public Exception { friend bool DebugIsEECxxExceptionPointer(void* pv); protected: HRESULT m_hr; public: HRException(); HRException(HRESULT hr); static const int c_type = 0x48522020; // 'HR ' // Dynamic type query for catchers static int GetType() {LIMITED_METHOD_DAC_CONTRACT; return c_type; } virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } // Virtual overrides HRESULT GetHR(); BOOL IsSameInstanceType(Exception *pException) { WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType() && pException->GetHR() == m_hr; } protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new HRException(m_hr); } }; // --------------------------------------------------------------------------- // HRMessageException class. Implements exception API for exceptions // generated from HRESULTs, and includes in info message. // --------------------------------------------------------------------------- class HRMsgException : public HRException { friend bool DebugIsEECxxExceptionPointer(void* pv); protected: SString m_msg; public: HRMsgException(); HRMsgException(HRESULT hr, SString const &msg); // Virtual overrides void GetMessage(SString &s); protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new HRMsgException(m_hr, m_msg); } }; // --------------------------------------------------------------------------- // COMException class. Implements exception API for standard COM-based error info // --------------------------------------------------------------------------- class COMException : public HRException { friend bool DebugIsEECxxExceptionPointer(void* pv); private: IErrorInfo *m_pErrorInfo; public: COMException(); COMException(HRESULT hr) ; COMException(HRESULT hr, IErrorInfo *pErrorInfo); ~COMException(); // Virtual overrides IErrorInfo *GetErrorInfo(); #ifdef FEATURE_COMINTEROP void GetMessage(SString &result); #endif protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new COMException(m_hr, m_pErrorInfo); } }; // --------------------------------------------------------------------------- // SEHException class. Implements exception API for SEH exception info // --------------------------------------------------------------------------- class SEHException : public Exception { friend bool DebugIsEECxxExceptionPointer(void* pv); public: EXCEPTION_RECORD m_exception; SEHException(); SEHException(EXCEPTION_RECORD *pRecord, T_CONTEXT *pContext = NULL); static const int c_type = 0x53454820; // 'SEH ' // Dynamic type query for catchers static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } BOOL IsSameInstanceType(Exception *pException) { WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType() && pException->GetHR() == GetHR(); } // Virtual overrides HRESULT GetHR(); IErrorInfo *GetErrorInfo(); void GetMessage(SString &result); protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new SEHException(&m_exception); } }; // --------------------------------------------------------------------------- // DelegatingException class. Implements exception API for "foreign" exceptions. // --------------------------------------------------------------------------- class DelegatingException : public Exception { Exception *m_delegatedException; Exception* GetDelegate(); enum {DELEGATE_NOT_YET_SET = -1}; bool IsDelegateSet() {LIMITED_METHOD_DAC_CONTRACT; return m_delegatedException != (Exception*)DELEGATE_NOT_YET_SET; } bool IsDelegateValid() {LIMITED_METHOD_DAC_CONTRACT; return IsDelegateSet() && m_delegatedException != NULL; } public: DelegatingException(); ~DelegatingException(); static const int c_type = 0x44454C20; // 'DEL ' // Dynamic type query for catchers static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } virtual BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } BOOL IsSameInstanceType(Exception *pException) { WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType() && pException->GetHR() == GetHR(); } // Virtual overrides virtual BOOL IsDomainBound() {return Exception::IsDomainBound() ||(m_delegatedException!=NULL && m_delegatedException->IsDomainBound());} ; HRESULT GetHR(); IErrorInfo *GetErrorInfo(); void GetMessage(SString &result); virtual Exception *Clone(); protected: virtual Exception *CloneHelper() { WRAPPER_NO_CONTRACT; return new DelegatingException(); } }; //------------------------------------------------------------------------------ // class OutOfMemoryException // // While there could be any number of instances of this class, there is one // special instance, the pre-allocated OOM exception. Storage for that // instance is allocated in the image, so we can always obtain it, even // in low memory situations. // Note that, in fact, there is only one instance. //------------------------------------------------------------------------------ class OutOfMemoryException : public Exception { private: static const int c_type = 0x4F4F4D20; // 'OOM ' BOOL bIsPreallocated; public: OutOfMemoryException() : bIsPreallocated(FALSE) {} OutOfMemoryException(BOOL b) : bIsPreallocated(b) {} // Dynamic type query for catchers static int GetType() {LIMITED_METHOD_CONTRACT; return c_type; } virtual int GetInstanceType() { LIMITED_METHOD_CONTRACT; return c_type; } BOOL IsType(int type) { WRAPPER_NO_CONTRACT; return type == c_type || Exception::IsType(type); } BOOL IsSameInstanceType(Exception *pException) { WRAPPER_NO_CONTRACT; return pException->GetInstanceType() == GetType(); } HRESULT GetHR() {LIMITED_METHOD_DAC_CONTRACT; return E_OUTOFMEMORY; } void GetMessage(SString &result) { WRAPPER_NO_CONTRACT; result.SetASCII("Out Of Memory"); } virtual Exception *Clone(); virtual BOOL IsPreallocatedException() { return bIsPreallocated; } }; template class CAutoTryCleanup { public: DEBUG_NOINLINE CAutoTryCleanup(STATETYPE& refState) : m_refState(refState) { SCAN_SCOPE_BEGIN; STATIC_CONTRACT_THROWS; STATIC_CONTRACT_SUPPORTS_DAC; #ifdef ENABLE_CONTRACTS_IMPL // This is similar to ClrTryMarkerHolder. We're marking that its okay to throw on this thread now because // we're within a try block. We fold this into here strictly for performance reasons... we have one // stack-allocated object do the work. m_pClrDebugState = GetClrDebugState(); m_oldOkayToThrowValue = m_pClrDebugState->IsOkToThrow(); m_pClrDebugState->SetOkToThrow(); #endif } DEBUG_NOINLINE ~CAutoTryCleanup() { SCAN_SCOPE_END; WRAPPER_NO_CONTRACT; m_refState.CleanupTry(); #ifdef ENABLE_CONTRACTS_IMPL // Restore the original OkayToThrow value since we're leaving the try block. m_pClrDebugState->SetOkToThrow( m_oldOkayToThrowValue ); #endif // ENABLE_CONTRACTS_IMPL } protected: STATETYPE& m_refState; #ifdef ENABLE_CONTRACTS_DATA private: BOOL m_oldOkayToThrowValue; ClrDebugState *m_pClrDebugState; #endif }; // --------------------------------------------------------------------------- // Throw/Catch macros // // Usage: // // EX_TRY // { // EX_THROW(HRException, (E_FAIL)); // } // EX_CATCH // { // Exception *e = GET_EXCEPTION(); // EX_RETHROW; // } // EX_END_CATCH(RethrowTerminalExceptions, RethrowTransientExceptions or SwallowAllExceptions) // // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // #NO_HOST_CPP_EH_ONLY // // The EX_CATCH* macros defined below can work one of two ways: // 1. They catch all exceptions, both C++ and SEH exceptions. // 2. They catch only C++ exceptions. // // Which way they are defined depends on what sort of handling of SEH // exceptions, like AV's, you wish to have in your DLL. In general we // do not typically want to catch and swallow AV's. // // By default, the macros catch all exceptions. This is how they work when // compiled into the primary runtime DLL (clr.dll). This is reasonable for // the CLR becuase it needs to also catch managed exceptions, which are SEH // exceptions, and because that DLL also includes a vectored exception // handler that will take down the process on any AV within clr.dll. // // But for uses of these macros outside of the CLR DLL there are other // possibilities. If a DLL only uses facilities in Utilcode that throw the // C++ exceptions defined above, and never needs to catch a managed exception, // then that DLL should setup the macros to only catch C++ exceptions. That // way, AV's are not accidentally swallowed and hidden. // // On the other hand, if a DLL needs to catch managed exceptions, then it has // no choice but to also catch all SEH exceptions, including AV's. In that case // the DLL should also include a vectored handler, like CLR.dll, to take the // process down on an AV. // // The behavior difference is controled by NO_HOST_CPP_EH_ONLY. When defined, // the EX_CATCH* macros only catch C++ exceptions. When not defined, they catch // C++ and SEH exceptions. // // Note: use of NO_HOST_CPP_EH_ONLY is only valid outside the primary CLR DLLs. // Thus it is an error to attempt to define it without also defining SELF_NO_HOST. // --------------------------------------------------------------------------- #if defined(NO_HOST_CPP_EH_ONLY) && !defined(SELF_NO_HOST) #error It is incorrect to attempt to have C++-only EH macros when hosted. This is only valid for components outside the runtime DLLs. #endif //----------------------------------------------------------------------- // EX_END_CATCH has a mandatory argument which is one of "RethrowTerminalExceptions", // "RethrowTransientExceptions", or "SwallowAllExceptions". // // If an exception is considered "terminal" (e->IsTerminal()), it should normally // be allowed to proceed. Hence, most of the time, you should use RethrowTerminalExceptions. // // In some cases you will want transient exceptions (terminal plus things like // resource exhaustion) to proceed as well. Use RethrowTransientExceptions for this cas. // // If you have a good reason to use SwallowAllExceptions, (e.g. a hard COM interop boundary) // use one of the higher level macros for this if available, or consider developing one. // Otherwise, clearly document why you're swallowing terminal exceptions. Raw uses of // SwallowAllExceptions will cause the cleanup police to come knocking on your door // at some point. // // A lot of existing TRY's swallow terminals right now simply because there is // backout code following the END_CATCH that has to be executed. The solution is // to replace that backout code with holder objects. //----------------------------------------------------------------------- #define RethrowTransientExceptions \ if (GET_EXCEPTION()->IsTransient()) \ { \ EX_RETHROW; \ } \ #define SwallowAllExceptions ; // When applied to EX_END_CATCH, this policy will always rethrow Terminal exceptions if they are // encountered. #define RethrowTerminalExceptions \ if (GET_EXCEPTION()->IsTerminal()) \ { \ STATIC_CONTRACT_THROWS_TERMINAL; \ EX_RETHROW; \ } \ // Special define to be used in EEStartup that will also check for VM initialization before // commencing on a path that may use the managed thread object. #define RethrowTerminalExceptionsWithInitCheck \ if ((g_fEEStarted == TRUE) && (GetThreadNULLOk() != NULL)) \ { \ RethrowTerminalExceptions \ } #ifdef _DEBUG void ExThrowTrap(const char *fcn, const char *file, int line, const char *szType, HRESULT hr, const char *args); #define EX_THROW_DEBUG_TRAP(fcn, file, line, szType, hr, args) ExThrowTrap(fcn, file, line, szType, hr, args) #else #define EX_THROW_DEBUG_TRAP(fcn, file, line, szType, hr, args) #endif #define EX_THROW(_type, _args) \ { \ FAULT_NOT_FATAL(); \ \ _type * ___pExForExThrow = new _type _args ; \ /* don't embed file names in retail to save space and avoid IP */ \ /* a findstr /n will allow you to locate it in a pinch */ \ STRESS_LOG3(LF_EH, LL_INFO100, "EX_THROW Type = 0x%x HR = 0x%x, " \ INDEBUG(__FILE__) " line %d\n", _type::GetType(), \ ___pExForExThrow->GetHR(), __LINE__); \ EX_THROW_DEBUG_TRAP(__FUNCTION__, __FILE__, __LINE__, #_type, ___pExForExThrow->GetHR(), #_args); \ PAL_CPP_THROW(_type *, ___pExForExThrow); \ } //-------------------------------------------------------------------------------- // Clones an exception into the current domain. Also handles special cases for // OOM and other stuff. Making this a function so we don't inline all this logic // every place we call EX_THROW_WITH_INNER. //-------------------------------------------------------------------------------- Exception *ExThrowWithInnerHelper(Exception *inner); // This macro will set the m_innerException into the newly created exception // The passed in _type has to be derived from CLRException. You cannot put OOM // as the inner exception. If we are throwing in OOM case, allocate more memory (this macro will clone) // does not make any sense. // #define EX_THROW_WITH_INNER(_type, _args, _inner) \ { \ FAULT_NOT_FATAL(); \ \ Exception *_inner2 = ExThrowWithInnerHelper(_inner); \ _type *___pExForExThrow = new _type _args ; \ ___pExForExThrow->SetInnerException(_inner2); \ STRESS_LOG3(LF_EH, LL_INFO100, "EX_THROW_WITH_INNER Type = 0x%x HR = 0x%x, " \ INDEBUG(__FILE__) " line %d\n", _type::GetType(), \ ___pExForExThrow->GetHR(), __LINE__); \ EX_THROW_DEBUG_TRAP(__FUNCTION__, __FILE__, __LINE__, #_type, ___pExForExThrow->GetHR(), #_args); \ PAL_CPP_THROW(_type *, ___pExForExThrow); \ } //#define IsCLRException(ex) ((ex !=NULL) && ex->IsType(CLRException::GetType()) #define EX_TRY_IMPL EX_TRY_CUSTOM(Exception::HandlerState, , DelegatingException /* was SEHException*/) #define EX_TRY_CPP_ONLY EX_TRY_CUSTOM_CPP_ONLY(Exception::HandlerState, , DelegatingException /* was SEHException*/) #ifndef INCONTRACT #ifdef ENABLE_CONTRACTS #define INCONTRACT(x) x #else #define INCONTRACT(x) #endif #endif #define EX_TRY_CUSTOM(STATETYPE, STATEARG, DEFAULT_EXCEPTION_TYPE) \ { \ STATETYPE __state STATEARG; \ typedef DEFAULT_EXCEPTION_TYPE __defaultException_t; \ SCAN_EHMARKER(); \ PAL_CPP_TRY \ { \ SCAN_EHMARKER_TRY(); \ SCAN_EHMARKER(); \ PAL_CPP_TRY \ { \ SCAN_EHMARKER_TRY(); \ CAutoTryCleanup __autoCleanupTry(__state); \ /* prevent annotations from being dropped by optimizations in debug */ \ INDEBUG(static bool __alwayszero;) \ INDEBUG(VolatileLoad(&__alwayszero);) \ { \ /* Disallow returns to make exception handling work. */ \ /* Some work is done after the catch, see EX_ENDTRY. */ \ DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ EX_TRY_HOLDER \ #define EX_CATCH_IMPL_EX(DerivedExceptionClass) \ DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ } \ SCAN_EHMARKER_END_TRY(); \ } \ PAL_CPP_CATCH_DERIVED (DerivedExceptionClass, __pExceptionRaw) \ { \ SCAN_EHMARKER_CATCH(); \ __state.SetCaughtCxx(); \ __state.m_pExceptionPtr = __pExceptionRaw; \ SCAN_EHMARKER_END_CATCH(); \ SCAN_IGNORE_THROW_MARKER; \ PAL_CPP_RETHROW; \ } \ PAL_CPP_ENDTRY \ SCAN_EHMARKER_END_TRY(); \ } \ PAL_CPP_CATCH_ALL \ { \ SCAN_EHMARKER_CATCH(); \ __defaultException_t __defaultException; \ CHECK::ResetAssert(); \ ExceptionHolder __pException(__state.m_pExceptionPtr); \ /* work around unreachable code warning */ \ if (true) { \ DEBUG_ASSURE_NO_RETURN_BEGIN(EX_CATCH) \ /* don't embed file names in retail to save space and avoid IP */ \ /* a findstr /n will allow you to locate it in a pinch */ \ __state.SetupCatch(INDEBUG_COMMA(__FILE__) __LINE__); \ #define EX_CATCH_IMPL EX_CATCH_IMPL_EX(Exception) #define EX_TRY_CUSTOM_CPP_ONLY(STATETYPE, STATEARG, DEFAULT_EXCEPTION_TYPE) \ { \ STATETYPE __state STATEARG; \ typedef DEFAULT_EXCEPTION_TYPE __defaultException_t; \ SCAN_EHMARKER(); \ PAL_CPP_TRY \ { \ SCAN_EHMARKER_TRY(); \ CAutoTryCleanup __autoCleanupTry(__state); \ /* prevent annotations from being dropped by optimizations in debug */ \ INDEBUG(static bool __alwayszero;) \ INDEBUG(VolatileLoad(&__alwayszero);) \ { \ /* Disallow returns to make exception handling work. */ \ /* Some work is done after the catch, see EX_ENDTRY. */ \ DEBUG_ASSURE_NO_RETURN_BEGIN(EX_TRY) \ #define EX_CATCH_IMPL_CPP_ONLY \ DEBUG_ASSURE_NO_RETURN_END(EX_TRY) \ } \ SCAN_EHMARKER_END_TRY(); \ } \ PAL_CPP_CATCH_DERIVED (Exception, __pExceptionRaw) \ { \ SCAN_EHMARKER_CATCH(); \ __state.SetCaughtCxx(); \ __state.m_pExceptionPtr = __pExceptionRaw; \ SCAN_EHMARKER_END_CATCH(); \ SCAN_IGNORE_THROW_MARKER; \ __defaultException_t __defaultException; \ CHECK::ResetAssert(); \ ExceptionHolder __pException(__state.m_pExceptionPtr); \ /* work around unreachable code warning */ \ if (true) { \ DEBUG_ASSURE_NO_RETURN_BEGIN(EX_CATCH) \ /* don't embed file names in retail to save space and avoid IP */ \ /* a findstr /n will allow you to locate it in a pinch */ \ __state.SetupCatch(INDEBUG_COMMA(__FILE__) __LINE__); \ // Here we finally define the EX_CATCH* macros that will be used throughout the system. // These can catch C++ and SEH exceptions, or just C++ exceptions. // See code:NO_HOST_CPP_EH_ONLY for more details. // // Note: we make it illegal to use forms that are redundant with the basic EX_CATCH // version. I.e., in the C++ & SEH version, EX_CATCH_CPP_AND_SEH is the same as EX_CATCH. // Likewise, in the C++ only version, EX_CATCH_CPP_ONLY is redundant with EX_CATCH. #ifndef NO_HOST_CPP_EH_ONLY #define EX_TRY EX_TRY_IMPL #define EX_CATCH EX_CATCH_IMPL #define EX_CATCH_EX EX_CATCH_IMPL_EX #define EX_CATCH_CPP_ONLY EX_CATCH_IMPL_CPP_ONLY #define EX_CATCH_CPP_AND_SEH Dont_Use_EX_CATCH_CPP_AND_SEH #else #define EX_TRY EX_TRY_CPP_ONLY #define EX_CATCH EX_CATCH_IMPL_CPP_ONLY #define EX_CATCH_CPP_ONLY Dont_Use_EX_CATCH_CPP_ONLY #define EX_CATCH_CPP_AND_SEH EX_CATCH_IMPL // Note: at this time we don't have a use case for EX_CATCH_EX, and we do not have // the C++-only version of the implementation available. Thus we disallow its use at this time. // If a real use case arises then we should go ahead and enable this. #define EX_CATCH_EX Dont_Use_EX_CATCH_EX #endif #define EX_END_CATCH_UNREACHABLE \ DEBUG_ASSURE_NO_RETURN_END(EX_CATCH) \ } \ SCAN_EHMARKER_END_CATCH(); \ UNREACHABLE(); \ } \ PAL_CPP_ENDTRY \ } \ // "terminalexceptionpolicy" must be one of "RethrowTerminalExceptions", // "RethrowTransientExceptions", or "SwallowAllExceptions" #define EX_END_CATCH(terminalexceptionpolicy) \ terminalexceptionpolicy; \ __state.SucceedCatch(); \ DEBUG_ASSURE_NO_RETURN_END(EX_CATCH) \ } \ SCAN_EHMARKER_END_CATCH(); \ } \ EX_ENDTRY \ } \ #define EX_END_CATCH_FOR_HOOK \ __state.SucceedCatch(); \ DEBUG_ASSURE_NO_RETURN_END(EX_CATCH) \ ANNOTATION_HANDLER_END; \ } \ SCAN_EHMARKER_END_CATCH(); \ } \ EX_ENDTRY #define EX_ENDTRY \ PAL_CPP_ENDTRY #define EX_RETHROW \ { \ __pException.SuppressRelease(); \ PAL_CPP_RETHROW; \ } \ // Define a copy of GET_EXCEPTION() that will not be redefined by clrex.h #define GET_EXCEPTION() (__pException == NULL ? &__defaultException : __pException.GetValue()) #define EXTRACT_EXCEPTION() (__pException.Extract()) //============================================================================== // High-level macros for common uses of EX_TRY. Try using these rather // than the raw EX_TRY constructs. //============================================================================== //=================================================================================== // Macro for converting exceptions into HR internally. Unlike EX_CATCH_HRESULT, // it does not set up IErrorInfo on the current thread. // // Usage: // // HRESULT hr = S_OK; // EX_TRY // // EX_CATCH_HRESULT_NO_ERRORINFO(hr); // return hr; // // Comments: // Since IErrorInfo is not set up, this does not require COM interop to be started. //=================================================================================== #define EX_CATCH_HRESULT_NO_ERRORINFO(_hr) \ EX_CATCH \ { \ (_hr) = GET_EXCEPTION()->GetHR(); \ _ASSERTE(FAILED(_hr)); \ } \ EX_END_CATCH(SwallowAllExceptions) //=================================================================================== // Macro for catching managed exception object. // // Usage: // // OBJECTREF pThrowable = NULL; // EX_TRY // // EX_CATCH_THROWABLE(&pThrowable); // //=================================================================================== #define EX_CATCH_THROWABLE(ppThrowable) \ EX_CATCH \ { \ *ppThrowable = GET_THROWABLE(); \ } \ EX_END_CATCH(SwallowAllExceptions) #ifdef FEATURE_COMINTEROP //=================================================================================== // Macro for defining external entrypoints such as COM interop boundaries. // The boundary will catch all exceptions (including terminals) and convert // them into HR/IErrorInfo pairs as appropriate. // // Usage: // // HRESULT hr = S_OK; // EX_TRY // // EX_CATCH_HRESULT(hr); // return hr; // // Comments: // Note that IErrorInfo will automatically be set up on the thread if appropriate. //=================================================================================== #define EX_CATCH_HRESULT(_hr) \ EX_CATCH \ { \ (_hr) = GET_EXCEPTION()->GetHR(); \ _ASSERTE(FAILED(_hr)); \ IErrorInfo *pErr = GET_EXCEPTION()->GetErrorInfo(); \ if (pErr != NULL) \ { \ SetErrorInfo(0, pErr); \ pErr->Release(); \ } \ } \ EX_END_CATCH(SwallowAllExceptions) //=================================================================================== // Macro to make conditional catching more succinct. // // Usage: // // EX_TRY // ... // EX_CATCH_HRESULT_IF(IsHRESULTForExceptionKind(GET_EXCEPTION()->GetHR(), kFileNotFoundException)); //=================================================================================== #define EX_CATCH_HRESULT_IF(HR, ...) \ EX_CATCH \ { \ (HR) = GET_EXCEPTION()->GetHR(); \ \ /* Rethrow if condition is false. */ \ if (!(__VA_ARGS__)) \ EX_RETHROW; \ \ _ASSERTE(FAILED(HR)); \ IErrorInfo *pErr = GET_EXCEPTION()->GetErrorInfo(); \ if (pErr != NULL) \ { \ SetErrorInfo(0, pErr); \ pErr->Release(); \ } \ } \ EX_END_CATCH(SwallowAllExceptions) #else // FEATURE_COMINTEROP #define EX_CATCH_HRESULT(_hr) EX_CATCH_HRESULT_NO_ERRORINFO(_hr) #endif // FEATURE_COMINTEROP //=================================================================================== // Macro for containing normal exceptions but letting terminal exceptions continue to propagate. // // Usage: // // EX_TRY // { // ...your stuff... // } // EX_SWALLOW_NONTERMINAL // // Remember, terminal exceptions (such as ThreadAbort) will still throw out of this // block. So don't use this as a substitute for exception-safe cleanup! //=================================================================================== #define EX_SWALLOW_NONTERMINAL \ EX_CATCH \ { \ } \ EX_END_CATCH(RethrowTerminalExceptions) \ //=================================================================================== // Macro for containing normal exceptions but letting transient exceptions continue to propagate. // // Usage: // // EX_TRY // { // ...your stuff... // } // EX_SWALLOW_NONTRANSIENT // // Terminal exceptions (such as ThreadAbort and OutOfMemory) will still throw out of this // block. So don't use this as a substitute for exception-safe cleanup! //=================================================================================== #define EX_SWALLOW_NONTRANSIENT \ EX_CATCH \ { \ } \ EX_END_CATCH(RethrowTransientExceptions) \ //=================================================================================== // Macro for observing or wrapping exceptions in flight. // // Usage: // // EX_TRY // { // ... your stuff ... // } // EX_HOOK // { // ... your stuff ... // } // EX_END_HOOK // ... control will never get here ... // // // EX_HOOK is like EX_CATCH except that you can't prevent the // exception from being rethrown. You can throw a new exception inside the hook // (for example, if you want to wrap the exception in flight with your own). // But if control reaches the end of the hook, the original exception gets rethrown. // // Avoid using EX_HOOK for conditional backout if a destructor-based holder // will suffice. Because these macros are implemented on top of SEH, using them will // prevent the use of holders anywhere else inside the same function. That is, instead // of saying this: // // EX_TRY // DON'T DO THIS // { // thing = new Thing(); // blah // } // EX_HOOK // { // delete thing; // if it failed, we don't want to keep the Thing. // } // EX_END_HOOK // // do this: // // Holder thing = new Thing(); //DO THIS INSTEAD // blah // // If we got here, we succeeded. So tell holder we want to keep the thing. // thing.SuppressRelease(); // // We won't rethrow the exception if it is a Stack Overflow exception. Instead, we'll throw a new // exception. This will allow the stack to unwind point, and so we won't be jeopardizing a // second stack overflow. //=================================================================================== #define EX_HOOK \ EX_CATCH \ { \ #define EX_END_HOOK \ } \ ANNOTATION_HANDLER_END; \ EX_RETHROW; \ EX_END_CATCH_FOR_HOOK; \ } // --------------------------------------------------------------------------- // Inline implementations. Pay no attention to that man behind the curtain. // --------------------------------------------------------------------------- inline Exception::HandlerState::HandlerState() { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_CANNOT_TAKE_LOCK; STATIC_CONTRACT_SUPPORTS_DAC; m_dwFlags = 0; m_pExceptionPtr = NULL; #if defined(STACK_GUARDS_DEBUG) && defined(ENABLE_CONTRACTS_IMPL) // If we have a debug state, use its setting for SO tolerance. The default // is SO-tolerant if we have no debug state. Can't probe w/o debug state and // can't enter SO-interolant mode w/o probing. GetClrDebugState(); #endif } inline void Exception::HandlerState::CleanupTry() { LIMITED_METHOD_DAC_CONTRACT; } inline void Exception::HandlerState::SetupCatch(INDEBUG_COMMA(_In_z_ const char * szFile) int lineNum) { WRAPPER_NO_CONTRACT; /* don't embed file names in retail to save space and avoid IP */ /* a findstr /n will allow you to locate it in a pinch */ #ifdef _DEBUG STRESS_LOG2(LF_EH, LL_INFO100, "EX_CATCH %s line %d\n", szFile, lineNum); #else STRESS_LOG1(LF_EH, LL_INFO100, "EX_CATCH line %d\n", lineNum); #endif SetCaught(); } inline void Exception::HandlerState::SucceedCatch() { LIMITED_METHOD_DAC_CONTRACT; } inline HRException::HRException() : m_hr(E_UNEXPECTED) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; } inline HRException::HRException(HRESULT hr) : m_hr(hr) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; // Catchers assume only failing hresults _ASSERTE(FAILED(hr)); } inline HRMsgException::HRMsgException() : HRException() { LIMITED_METHOD_CONTRACT; } inline HRMsgException::HRMsgException(HRESULT hr, SString const &s) : HRException(hr), m_msg(s) { WRAPPER_NO_CONTRACT; } inline COMException::COMException() : HRException(), m_pErrorInfo(NULL) { WRAPPER_NO_CONTRACT; } inline COMException::COMException(HRESULT hr) : HRException(hr), m_pErrorInfo(NULL) { LIMITED_METHOD_CONTRACT; } inline COMException::COMException(HRESULT hr, IErrorInfo *pErrorInfo) : HRException(hr), m_pErrorInfo(pErrorInfo) { LIMITED_METHOD_CONTRACT; } inline SEHException::SEHException() { LIMITED_METHOD_CONTRACT; memset(&m_exception, 0, sizeof(EXCEPTION_RECORD)); } inline SEHException::SEHException(EXCEPTION_RECORD *pointers, T_CONTEXT *pContext) { LIMITED_METHOD_CONTRACT; memcpy(&m_exception, pointers, sizeof(EXCEPTION_RECORD)); } // The exception throwing helpers are intentionally not inlined // Exception throwing is a rare slow codepath that should be optimized for code size void DECLSPEC_NORETURN ThrowHR(HRESULT hr); void DECLSPEC_NORETURN ThrowHR(HRESULT hr, SString const &msg); void DECLSPEC_NORETURN ThrowHR(HRESULT hr, UINT uText); void DECLSPEC_NORETURN ThrowWin32(DWORD err); void DECLSPEC_NORETURN ThrowLastError(); void DECLSPEC_NORETURN ThrowOutOfMemory(); void DECLSPEC_NORETURN ThrowStackOverflow(); #undef IfFailThrow inline HRESULT IfFailThrow(HRESULT hr) { WRAPPER_NO_CONTRACT; if (FAILED(hr)) { ThrowHR(hr); } return hr; } inline HRESULT IfFailThrow(HRESULT hr, SString &msg) { WRAPPER_NO_CONTRACT; if (FAILED(hr)) { ThrowHR(hr, msg); } return hr; } inline HRESULT IfTransientFailThrow(HRESULT hr) { WRAPPER_NO_CONTRACT; if (FAILED(hr) && Exception::IsTransient(hr)) { ThrowHR(hr); } return hr; } // Set if fatal error (like stack overflow or out of memory) occurred in this process. GVAL_DECL(HRESULT, g_hrFatalError); #endif // _EX_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/executableallocator.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // Allocator and holders for double mapped executable memory // #pragma once #include "utilcode.h" #include "ex.h" #include "minipal.h" #ifndef DACCESS_COMPILE //#define LOG_EXECUTABLE_ALLOCATOR_STATISTICS // This class is responsible for allocation of all the executable memory in the runtime. class ExecutableAllocator { // RX address range block descriptor struct BlockRX { // Next block in a linked list BlockRX* next; // Base address of the block void* baseRX; // Size of the block size_t size; // Offset of the block in the shared memory size_t offset; }; // RW address range block descriptor struct BlockRW { // Next block in a linked list BlockRW* next; // Base address of the RW mapping of the block void* baseRW; // Base address of the RX mapping of the block void* baseRX; // Size of the block size_t size; // Usage reference count of the RW block. RW blocks can be reused // when multiple mappings overlap in the VA space at the same time // (even from multiple threads) size_t refCount; }; typedef void (*FatalErrorHandler)(UINT errorCode, LPCWSTR pszMessage); #ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS static int64_t g_mapTimeSum; static int64_t g_mapTimeWithLockSum; static int64_t g_unmapTimeSum; static int64_t g_unmapTimeWithLockSum; static int64_t g_mapFindRXTimeSum; static int64_t g_mapCreateTimeSum; static int64_t g_releaseCount; static int64_t g_reserveCount; #endif // Instance of the allocator static ExecutableAllocator* g_instance; // Callback to the runtime to report fatal errors static FatalErrorHandler g_fatalErrorHandler; #if USE_LAZY_PREFERRED_RANGE static BYTE* g_lazyPreferredRangeStart; // Next address to try to allocate for code in the lazy preferred region. static BYTE* g_lazyPreferredRangeHint; #endif // USE_LAZY_PREFERRED_RANGE // For PAL, this region represents the area that is eagerly reserved on // startup where executable memory and static fields are preferrably kept. // For Windows, this is the region that we lazily reserve from. static BYTE* g_preferredRangeMin; static BYTE* g_preferredRangeMax; // Caches the COMPlus_EnableWXORX setting static bool g_isWXorXEnabled; // Head of the linked list of all RX blocks that were allocated by this allocator BlockRX* m_pFirstBlockRX = NULL; // Head of the linked list of free RX blocks that were allocated by this allocator and then backed out BlockRX* m_pFirstFreeBlockRX = NULL; // Head of the linked list of currently mapped RW blocks BlockRW* m_pFirstBlockRW = NULL; // Handle of the double mapped memory mapper void *m_doubleMemoryMapperHandle = NULL; // Maximum size of executable memory this allocator can allocate size_t m_maxExecutableCodeSize; // First free offset in the underlying shared memory. It is not used // for platforms that don't use shared memory. size_t m_freeOffset = 0; // Last RW mapping cached so that it can be reused for the next mapping // request if it goes into the same range. BlockRW* m_cachedMapping = NULL; // Synchronization of the public allocator methods CRITSEC_COOKIE m_CriticalSection; // Update currently cached mapping. If the passed in block is the same as the one // in the cache, it keeps it cached. Otherwise it destroys the currently cached one // and replaces it by the passed in one. void UpdateCachedMapping(BlockRW *pBlock); // Find existing RW block that maps the whole specified range of RX memory. // Return NULL if no such block exists. void* FindRWBlock(void* baseRX, size_t size); // Add RW block to the list of existing RW blocks bool AddRWBlock(void* baseRW, void* baseRX, size_t size); // Remove RW block from the list of existing RW blocks and return the base // address and size the underlying memory was mapped at. // Return false if no existing RW block contains the passed in address. bool RemoveRWBlock(void* pRW, void** pUnmapAddress, size_t* pUnmapSize); // Find a free block with the closest size >= the requested size. // Returns NULL if no such block exists. BlockRX* FindBestFreeBlock(size_t size); // Return memory mapping granularity. static size_t Granularity(); // Allocate a block of executable memory of the specified size. // It doesn't acquire the actual virtual memory, just the // range of the underlying shared memory. BlockRX* AllocateBlock(size_t size, bool* pIsFreeBlock); // Backout the block allocated by AllocateBlock in case of an // error. void BackoutBlock(BlockRX* pBlock, bool isFreeBlock); // Allocate range of offsets in the underlying shared memory bool AllocateOffset(size_t* pOffset, size_t size); // Add RX block to the linked list of existing blocks void AddRXBlock(BlockRX *pBlock); // Return true if double mapping is enabled. static bool IsDoubleMappingEnabled(); // Initialize the allocator instance bool Initialize(); #ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS static CRITSEC_COOKIE s_LoggerCriticalSection; struct LogEntry { const char* source; const char* function; int line; int count; }; static LogEntry s_usageLog[256]; static int s_logMaxIndex; #endif public: #ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS static void LogUsage(const char* source, int line, const char* function); static void DumpHolderUsage(); #endif // Return the ExecuteAllocator singleton instance static ExecutableAllocator* Instance(); // Initialize the static members of the Executable allocator and allocate // and initialize the instance of it. static HRESULT StaticInitialize(FatalErrorHandler fatalErrorHandler); // Destroy the allocator ~ExecutableAllocator(); // Return true if W^X is enabled static bool IsWXORXEnabled(); // Use this function to initialize g_lazyPreferredRangeHint during startup. // base is runtime .dll base address, size is runtime .dll virtual size. static void InitLazyPreferredRange(size_t base, size_t size, int randomPageOffset); // Use this function to reset g_lazyPreferredRangeHint after unloading code. static void ResetLazyPreferredRangeHint(); // Use this function to initialize the preferred range of executable memory // from PAL. static void InitPreferredRange(); // Returns TRUE if p is located in near clr.dll that allows us // to use rel32 IP-relative addressing modes. static bool IsPreferredExecutableRange(void* p); // Reserve the specified amount of virtual address space for executable mapping. void* Reserve(size_t size); // Reserve the specified amount of virtual address space for executable mapping. // The reserved range must be within the loAddress and hiAddress. If it is not // possible to reserve memory in such range, the method returns NULL. void* ReserveWithinRange(size_t size, const void* loAddress, const void* hiAddress); // Reserve the specified amount of virtual address space for executable mapping // exactly at the given address. void* ReserveAt(void* baseAddressRX, size_t size); // Commit the specified range of memory. The memory can be committed as executable (RX) // or non-executable (RW) based on the passed in isExecutable flag. The non-executable // allocations are used to allocate data structures that need to be close to the // executable code due to memory addressing performance related reasons. void* Commit(void* pStart, size_t size, bool isExecutable); // Release the executable memory block starting at the passed in address that was allocated // by one of the ReserveXXX methods. void Release(void* pRX); // Map the specified block of executable memory as RW void* MapRW(void* pRX, size_t size); // Unmap the RW mapping at the specified address void UnmapRW(void* pRW); }; #define ExecutableWriterHolder ExecutableWriterHolderNoLog // Holder class to map read-execute memory as read-write so that it can be modified without using read-write-execute mapping. // At the moment the implementation is dummy, returning the same addresses for both cases and expecting them to be read-write-execute. // The class uses the move semantics to ensure proper unmapping in case of re-assigning of the holder value. template class ExecutableWriterHolder { T *m_addressRX; T *m_addressRW; void Move(ExecutableWriterHolder& other) { m_addressRX = other.m_addressRX; m_addressRW = other.m_addressRW; other.m_addressRX = NULL; other.m_addressRW = NULL; } void Unmap() { #if defined(HOST_OSX) && defined(HOST_ARM64) && !defined(DACCESS_COMPILE) if (m_addressRX != NULL) { PAL_JitWriteProtect(false); } #else if (m_addressRX != m_addressRW) { ExecutableAllocator::Instance()->UnmapRW((void*)m_addressRW); } #endif } public: ExecutableWriterHolder(const ExecutableWriterHolder& other) = delete; ExecutableWriterHolder& operator=(const ExecutableWriterHolder& other) = delete; ExecutableWriterHolder(ExecutableWriterHolder&& other) { Move(other); } ExecutableWriterHolder& operator=(ExecutableWriterHolder&& other) { Unmap(); Move(other); return *this; } ExecutableWriterHolder() : m_addressRX(nullptr), m_addressRW(nullptr) { } ExecutableWriterHolder(T* addressRX, size_t size) { m_addressRX = addressRX; #if defined(HOST_OSX) && defined(HOST_ARM64) m_addressRW = addressRX; PAL_JitWriteProtect(true); #else m_addressRW = (T *)ExecutableAllocator::Instance()->MapRW((void*)addressRX, size); #endif } ~ExecutableWriterHolder() { Unmap(); } // Get the writeable address inline T *GetRW() const { return m_addressRW; } void AssignExecutableWriterHolder(T* addressRX, size_t size) { *this = ExecutableWriterHolder(addressRX, size); } }; #ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS #undef ExecutableWriterHolder #ifdef TARGET_UNIX #define ExecutableWriterHolder ExecutableAllocator::LogUsage(__FILE__, __LINE__, __PRETTY_FUNCTION__); ExecutableWriterHolderNoLog #define AssignExecutableWriterHolder(addressRX, size) AssignExecutableWriterHolder(addressRX, size); ExecutableAllocator::LogUsage(__FILE__, __LINE__, __PRETTY_FUNCTION__); #else #define ExecutableWriterHolder ExecutableAllocator::LogUsage(__FILE__, __LINE__, __FUNCTION__); ExecutableWriterHolderNoLog #define AssignExecutableWriterHolder(addressRX, size) AssignExecutableWriterHolder(addressRX, size); ExecutableAllocator::LogUsage(__FILE__, __LINE__, __FUNCTION__); #endif #else #define ExecutableWriterHolder ExecutableWriterHolderNoLog #endif #endif // !DACCESS_COMPILE ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/factory.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _FACTORY_H_ #define _FACTORY_H_ template class Factory { public: virtual PRODUCT* Create() = 0; virtual ~Factory() {} }; template class InlineFactory : public Factory { public: InlineFactory() : m_next(NULL), m_cProduct(0) { WRAPPER_NO_CONTRACT; } ~InlineFactory() { WRAPPER_NO_CONTRACT; if (m_next) delete m_next; } PRODUCT* Create(); private: InlineFactory* GetNext() { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (m_next == NULL) { m_next = new (nothrow) InlineFactory(); } return m_next; } InlineFactory* m_next; PRODUCT m_product[MAX_FACTORY_PRODUCT]; INT32 m_cProduct; }; #include "factory.inl" #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/factory.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _FACTORY_INL_ #define _FACTORY_INL_ #include "factory.h" template PRODUCT* InlineFactory::Create() { WRAPPER_NO_CONTRACT; if (m_cProduct == MAX_FACTORY_PRODUCT) { InlineFactory* pNext = GetNext(); if (pNext) { return pNext->Create(); } else { return NULL; } } return &m_product[m_cProduct++]; } #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/formattype.cpp ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // /******************************************************************************/ /* formatType.cpp */ /******************************************************************************/ #include "formattype.h" /******************************************************************************/ char* asString(CQuickBytes *out) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; SIZE_T oldSize = out->Size(); out->ReSizeThrows(oldSize + 1); char* cur = &((char*) out->Ptr())[oldSize]; *cur = 0; out->ReSizeThrows(oldSize); // Don't count the null character return((char*) out->Ptr()); } void appendStr(CQuickBytes *out, const char* str, unsigned len) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; if(len == (unsigned)(-1)) len = (unsigned)strlen(str); SIZE_T oldSize = out->Size(); out->ReSizeThrows(oldSize + len); char* cur = &((char*) out->Ptr())[oldSize]; memcpy(cur, str, len); // Note no trailing null! } void appendChar(CQuickBytes *out, char chr) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; SIZE_T oldSize = out->Size(); out->ReSizeThrows(oldSize + 1); ((char*) out->Ptr())[oldSize] = chr; // Note no trailing null! } void insertStr(CQuickBytes *out, const char* str) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; unsigned len = (unsigned)strlen(str); SIZE_T oldSize = out->Size(); out->ReSizeThrows(oldSize + len); char* cur = &((char*) out->Ptr())[len]; memmove(cur,out->Ptr(),oldSize); memcpy(out->Ptr(), str, len); // Note no trailing null! } static void appendStrNum(CQuickBytes *out, int num) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; char buff[16]; sprintf_s(buff, ARRAY_SIZE(buff), "%d", num); appendStr(out, buff); } PCCOR_SIGNATURE PrettyPrintSignature( PCCOR_SIGNATURE typePtr, // type to convert, unsigned typeLen, // the length of 'typePtr' const char* name, // can be "", the name of the method for this sig 0 means local var sig CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig _In_opt_z_ const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity=FALSE); PCCOR_SIGNATURE PrettyPrintTypeOrDef( PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig //***************************************************************************** // Parse a length, return the length, size of the length. //***************************************************************************** ULONG GetLength( // Length or -1 on error. void const *pData, // First byte of length. int *pSizeLen) // Put size of length here, if not 0. { LIMITED_METHOD_CONTRACT; BYTE const *pBytes = reinterpret_cast(pData); if(pBytes) { if ((*pBytes & 0x80) == 0x00) // 0??? ???? { if (pSizeLen) *pSizeLen = 1; return (*pBytes & 0x7f); } if ((*pBytes & 0xC0) == 0x80) // 10?? ???? { if (pSizeLen) *pSizeLen = 2; return ((*pBytes & 0x3f) << 8 | *(pBytes+1)); } if ((*pBytes & 0xE0) == 0xC0) // 110? ???? { if (pSizeLen) *pSizeLen = 4; return ((*pBytes & 0x1f) << 24 | *(pBytes+1) << 16 | *(pBytes+2) << 8 | *(pBytes+3)); } } if(pSizeLen) *pSizeLen = 0; return 0; } /******************************************************************************/ const char* PrettyPrintSig( PCCOR_SIGNATURE typePtr, // type to convert, unsigned typeLen, // the length of 'typePtr' const char* name, // can be "", the name of the method for this sig 0 means local var sig CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity) { STATIC_CONTRACT_THROWS; EX_TRY { PrettyPrintSignature(typePtr, typeLen, name, out, pIMDI, inlabel, printTyArity); } EX_CATCH { out->Shrink(0); appendStr(out,"ERROR PARSING THE SIGNATURE"); } EX_END_CATCH(SwallowAllExceptions); return(asString(out)); } /********************************************************************************/ // Converts a com signature to a printable signature. // Note that return value is pointing at the CQuickBytes buffer, PCCOR_SIGNATURE PrettyPrintSignature( PCCOR_SIGNATURE typePtr, // type to convert, unsigned typeLen, // the length of 'typePtr' const char* name, // can be "", the name of the method for this sig 0 means local var sig CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; unsigned numArgs; unsigned numTyArgs = 0; PCCOR_SIGNATURE typeEnd = typePtr + typeLen; unsigned ixArg= 0; //arg index char argname[1024]; char label[MAX_PREFIX_SIZE]; const char* openpar = "("; const char* closepar = ")"; ParamDescriptor* pszArgName = NULL; // ptr to array of names (if provided by debug info) if(inlabel && *inlabel) // check for *inlabel is totally unnecessary, added to pacify the PREFIX { strcpy_s(label,MAX_PREFIX_SIZE,inlabel); ixArg = label[strlen(label)-1] - '0'; label[strlen(label)-1] = 0; if(label[0] == '@') // it's pointer! { #ifdef HOST_64BIT pszArgName = (ParamDescriptor*)_atoi64(&label[1]); #else // !HOST_64BIT pszArgName = (ParamDescriptor*)(size_t)atoi(&label[1]); #endif // HOST_64BIT } } // 0 means a local var sig if (name != 0) { // get the calling convention out unsigned callConv = CorSigUncompressData(typePtr); // should not be a local var sig _ASSERTE(!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG)); if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD)) { typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if (*name) { appendChar(out, ' '); appendStr(out, name); } return(typePtr); } if (callConv & IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS) appendStr(out, KEYWORD("explicit ")); if (callConv & IMAGE_CEE_CS_CALLCONV_HASTHIS) appendStr(out, KEYWORD("instance ")); if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) { openpar = LTN(); closepar = GTN(); } else { const char* const callConvUndefined = (const char*)-1; static const char* const callConvNames[16] = { "", "unmanaged cdecl ", "unmanaged stdcall ", "unmanaged thiscall ", "unmanaged fastcall ", "vararg ", callConvUndefined, // field callConvUndefined, // local sig callConvUndefined, // property "unmanaged ", callConvUndefined, callConvUndefined, callConvUndefined, callConvUndefined, callConvUndefined, callConvUndefined }; static_assert_no_msg(ARRAY_SIZE(callConvNames) == (IMAGE_CEE_CS_CALLCONV_MASK + 1)); char tmp[32]; unsigned callConvIdx = callConv & IMAGE_CEE_CS_CALLCONV_MASK; const char* name_cc = callConvNames[callConvIdx]; if (name_cc == callConvUndefined) { sprintf_s(tmp, ARRAY_SIZE(tmp), "callconv(%u) ", callConvIdx); name_cc = tmp; } appendStr(out, KEYWORD(name_cc)); } if (callConv & IMAGE_CEE_CS_CALLCONV_GENERIC) { numTyArgs = CorSigUncompressData(typePtr); } numArgs = CorSigUncompressData(typePtr); if (!isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) { // do return type if(pszArgName) { argname[0] = 0; DumpParamAttr(argname, ARRAY_SIZE(argname), pszArgName[ixArg+numArgs].attr); appendStr(out,argname); } typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if(pszArgName) { argname[0] = ' '; argname[1] = 0; DumpMarshaling(pIMDI,argname, ARRAY_SIZE(argname), pszArgName[ixArg+numArgs].tok); appendStr(out,argname); } if(*name != 0) { appendChar(out, ' '); appendStr(out, name); } if((numTyArgs != 0)&&printTyArity) { appendStr(out,LTN()); appendChar(out,'['); appendStrNum(out,numTyArgs); appendChar(out,']'); appendStr(out,GTN()); } } } else { // get the calling convention out #ifdef _DEBUG unsigned callConv = #endif CorSigUncompressData(typePtr); #ifdef _DEBUG (void)callConv; //prevent "unused variable" warning from GCC // should be a local var sig _ASSERTE(callConv == IMAGE_CEE_CS_CALLCONV_LOCAL_SIG); #endif numArgs = CorSigUncompressData(typePtr); } appendStr(out, openpar); bool needComma = false; while(typePtr < typeEnd) { if(name) // printing the arguments { PREFIX_ASSUME(typePtr != NULL); if (*typePtr == ELEMENT_TYPE_SENTINEL) { if (needComma) appendChar(out, ','); appendStr(out, "..."); typePtr++; } else { if (numArgs <= 0) break; if (needComma) appendChar(out, ','); if(pszArgName) { argname[0] = 0; DumpParamAttr(argname, ARRAY_SIZE(argname), pszArgName[ixArg].attr); appendStr(out,argname); } typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if(inlabel) { if(pszArgName) { argname[0] = ' '; argname[1] = 0; DumpMarshaling(pIMDI,argname, ARRAY_SIZE(argname), pszArgName[ixArg].tok); strcat_s(argname, ARRAY_SIZE(argname), ProperName(pszArgName[ixArg++].name)); } else sprintf_s(argname, ARRAY_SIZE(argname), " %s_%d", label,ixArg++); appendStr(out,argname); } --numArgs; } } else // printing local vars { if (numArgs <= 0) break; if(pszArgName) { if(pszArgName[ixArg].attr == 0xFFFFFFFF) { CQuickBytes fake_out; typePtr = PrettyPrintTypeOrDef(typePtr, &fake_out, pIMDI); ixArg++; numArgs--; continue; } } if (needComma) appendChar(out, ','); if(pszArgName) { sprintf_s(argname,ARRAY_SIZE(argname),"[%d] ",pszArgName[ixArg].attr); appendStr(out,argname); } typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); if(inlabel) { if(pszArgName) { sprintf_s(argname,ARRAY_SIZE(argname)," %s",ProperLocalName(pszArgName[ixArg++].name)); } else sprintf_s(argname,ARRAY_SIZE(argname)," %s_%d",label,ixArg++); appendStr(out,argname); } --numArgs; } needComma = true; } // Have we finished printing all the arguments? if (numArgs > 0) { appendStr(out, ERRORMSG(" [SIGNATURE ENDED PREMATURELY]")); } appendStr(out, closepar); return(typePtr); } /******************************************************************************/ // pretty prints 'type' or its 'typedef' to the buffer 'out' returns a pointer to the next type, // or 0 on a format failure; outside ILDASM -- simple wrapper for PrettyPrintType PCCOR_SIGNATURE PrettyPrintTypeOrDef( PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; PCCOR_SIGNATURE pBegin, pEnd=NULL; #ifdef __ILDASM__ ULONG L = (ULONG)(out->Size()); #endif pBegin = typePtr; pEnd = PrettyPrintType(typePtr,out,pIMDI); #ifdef __ILDASM__ if(pEnd > pBegin) // PrettyPrintType can return NULL { DWORD i; ULONG l = (ULONG)(pEnd - pBegin); for(i=0; i < g_NumTypedefs; i++) { if(((*g_typedefs)[i].cb == l) && (memcmp((*g_typedefs)[i].psig,pBegin,l)==0)) { out->Shrink(L); // discard output of PrettyPrintType appendStr(out, JUMPPT(ProperName((*g_typedefs)[i].szName),(*g_typedefs)[i].tkSelf)); break; } } } #endif return pEnd; } /******************************************************************************/ // pretty prints 'type' to the buffer 'out' returns a pointer to the next type, // or 0 on a format failure PCCOR_SIGNATURE PrettyPrintType( PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI) // ptr to IMDInternal class with ComSig { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; mdToken tk; const char* str; int typ; CQuickBytes tmp; CQuickBytes Appendix; BOOL Reiterate; int n; do { Reiterate = FALSE; switch(typ = *typePtr++) { case ELEMENT_TYPE_VOID : str = "void"; goto APPEND; case ELEMENT_TYPE_BOOLEAN : str = "bool"; goto APPEND; case ELEMENT_TYPE_CHAR : str = "char"; goto APPEND; case ELEMENT_TYPE_I1 : str = "int8"; goto APPEND; case ELEMENT_TYPE_U1 : str = "uint8"; goto APPEND; case ELEMENT_TYPE_I2 : str = "int16"; goto APPEND; case ELEMENT_TYPE_U2 : str = "uint16"; goto APPEND; case ELEMENT_TYPE_I4 : str = "int32"; goto APPEND; case ELEMENT_TYPE_U4 : str = "uint32"; goto APPEND; case ELEMENT_TYPE_I8 : str = "int64"; goto APPEND; case ELEMENT_TYPE_U8 : str = "uint64"; goto APPEND; case ELEMENT_TYPE_R4 : str = "float32"; goto APPEND; case ELEMENT_TYPE_R8 : str = "float64"; goto APPEND; case ELEMENT_TYPE_U : str = "native uint"; goto APPEND; case ELEMENT_TYPE_I : str = "native int"; goto APPEND; case ELEMENT_TYPE_OBJECT : str = "object"; goto APPEND; case ELEMENT_TYPE_STRING : str = "string"; goto APPEND; case ELEMENT_TYPE_TYPEDBYREF : str = "typedref"; goto APPEND; APPEND: appendStr(out, KEYWORD((char*)str)); break; case ELEMENT_TYPE_VALUETYPE : str = "valuetype "; goto DO_CLASS; case ELEMENT_TYPE_CLASS : str = "class "; goto DO_CLASS; DO_CLASS: appendStr(out, KEYWORD((char*)str)); typePtr += CorSigUncompressToken(typePtr, &tk); if(IsNilToken(tk)) { appendStr(out, "[ERROR! NIL TOKEN]"); } else PrettyPrintClass(out, tk, pIMDI); REGISTER_REF(g_tkRefUser,tk) break; case ELEMENT_TYPE_SZARRAY : insertStr(&Appendix,"[]"); Reiterate = TRUE; break; case ELEMENT_TYPE_ARRAY : { typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); PREFIX_ASSUME(typePtr != NULL); unsigned rank = CorSigUncompressData(typePtr); // what is the syntax for the rank 0 case? if (rank == 0) { appendStr(out, ERRORMSG("[BAD: RANK == 0!]")); } else { _ASSERTE(rank != 0); #ifdef _PREFAST_ #pragma prefast(push) #pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow") #endif int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); int* sizes = &lowerBounds[rank]; memset(lowerBounds, 0, sizeof(int)*2*rank); unsigned numSizes = CorSigUncompressData(typePtr); _ASSERTE(numSizes <= rank); unsigned i; for(i =0; i < numSizes; i++) sizes[i] = CorSigUncompressData(typePtr); unsigned numLowBounds = CorSigUncompressData(typePtr); _ASSERTE(numLowBounds <= rank); for(i = 0; i < numLowBounds; i++) typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]); appendChar(out, '['); if (rank == 1 && numSizes == 0 && numLowBounds == 0) appendStr(out, "..."); else { for(i = 0; i < rank; i++) { //if (sizes[i] != 0 || lowerBounds[i] != 0) { if (lowerBounds[i] == 0 && i < numSizes) appendStrNum(out, sizes[i]); else { if(i < numLowBounds) { appendStrNum(out, lowerBounds[i]); appendStr(out, "..."); if (/*sizes[i] != 0 && */i < numSizes) appendStrNum(out, lowerBounds[i] + sizes[i] - 1); } } } if (i < rank-1) appendChar(out, ','); } } appendChar(out, ']'); #ifdef _PREFAST_ #pragma prefast(pop) #endif } } break; case ELEMENT_TYPE_VAR : appendChar(out, '!'); n = CorSigUncompressData(typePtr); #ifdef __ILDASM__ if(!PrettyPrintGP(g_tkVarOwner,out,n)) #endif appendStrNum(out, n); break; case ELEMENT_TYPE_MVAR : appendChar(out, '!'); appendChar(out, '!'); n = CorSigUncompressData(typePtr); #ifdef __ILDASM__ if(!PrettyPrintGP(g_tkMVarOwner,out,n)) #endif appendStrNum(out, n); break; case ELEMENT_TYPE_FNPTR : appendStr(out, KEYWORD("method ")); typePtr = PrettyPrintSignature(typePtr, 0x7FFF, "*", out, pIMDI, NULL); break; case ELEMENT_TYPE_GENERICINST : { typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); appendStr(out, LTN()); unsigned numArgs = CorSigUncompressData(typePtr); bool needComma = false; while(numArgs--) { if (needComma) appendChar(out, ','); typePtr = PrettyPrintTypeOrDef(typePtr, out, pIMDI); needComma = true; } appendStr(out, GTN()); break; } #ifndef __ILDASM__ case ELEMENT_TYPE_INTERNAL : { // ELEMENT_TYPE_INTERNAL _ASSERTE(sizeof(TypeHandle) == sizeof(void *)); TypeHandle typeHandle; typePtr += CorSigUncompressPointer(typePtr, (void **)&typeHandle); MethodTable *pMT = NULL; if (typeHandle.IsTypeDesc()) { pMT = typeHandle.AsTypeDesc()->GetMethodTable(); if (pMT) { PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport()); // It could be a "native version" of the managed type used in interop if (typeHandle.AsTypeDesc()->IsNativeValueType()) appendStr(out, "_NativeValueType"); } else appendStr(out, "(null)"); } else { pMT = typeHandle.AsMethodTable(); if (pMT) PrettyPrintClass(out, pMT->GetCl(), pMT->GetMDImport()); else appendStr(out, "(null)"); } char sz[32]; sprintf_s(sz, ARRAY_SIZE(sz), " /* MT: 0x%p */", pMT); appendStr(out, sz); break; } #endif // Modifiers or depedent types case ELEMENT_TYPE_CMOD_OPT : str = " modopt("; goto ADDCLASSTOCMOD; case ELEMENT_TYPE_CMOD_REQD : str = " modreq("; ADDCLASSTOCMOD: typePtr += CorSigUncompressToken(typePtr, &tk); if (IsNilToken(tk)) { Debug_ReportError("Nil token in custom modifier"); } tmp.Shrink(0); appendStr(&tmp, KEYWORD((char*)str)); PrettyPrintClass(&tmp, tk, pIMDI); appendChar(&tmp,')'); str = (const char *) asString(&tmp); goto MODIFIER; case ELEMENT_TYPE_PINNED : str = " pinned"; goto MODIFIER; case ELEMENT_TYPE_PTR : str = "*"; goto MODIFIER; case ELEMENT_TYPE_BYREF : str = AMP(); goto MODIFIER; MODIFIER: insertStr(&Appendix, str); Reiterate = TRUE; break; default: case ELEMENT_TYPE_SENTINEL : case ELEMENT_TYPE_END : //_ASSERTE(!"Unknown Type"); if(typ) { char sz[64]; sprintf_s(sz,ARRAY_SIZE(sz),"/* UNKNOWN TYPE (0x%X)*/",typ); appendStr(out, ERRORMSG(sz)); } break; } // end switch } while(Reiterate); appendStr(out,asString(&Appendix)); return(typePtr); } /******************************************************************/ const char* PrettyPrintClass( CQuickBytes *out, // where to put the pretty printed string mdToken tk, // The class token to look up IMDInternalImport *pIMDI) // ptr to IMDInternalImport class with ComSig { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; if(tk == mdTokenNil) // Zero resolution scope for "somewhere here" TypeRefs { appendStr(out,"[*]"); return(asString(out)); } if(!pIMDI->IsValidToken(tk)) { char str[1024]; sprintf_s(str,ARRAY_SIZE(str)," [ERROR: INVALID TOKEN 0x%8.8X] ",tk); appendStr(out,ERRORMSG(str)); return(asString(out)); } switch(TypeFromToken(tk)) { case mdtTypeRef: case mdtTypeDef: #ifdef __ILDASM__ DWORD ix; for(ix = 0; ix < g_NumTypedefs; ix++) { if((*g_typedefs)[ix].tkTypeSpec == tk) break; } if(ix < g_NumTypedefs) { appendStr(out,JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf)); } else #endif { const char *nameSpace = 0; const char *name = 0; mdToken tkEncloser; if (TypeFromToken(tk) == mdtTypeRef) { if (FAILED(pIMDI->GetResolutionScopeOfTypeRef(tk, &tkEncloser))) { tkEncloser = mdTypeDefNil; } if (FAILED(pIMDI->GetNameOfTypeRef(tk, &nameSpace, &name))) { nameSpace = name = "Invalid TypeRef record"; } } else { if (FAILED(pIMDI->GetNestedClassProps(tk,&tkEncloser))) { tkEncloser = mdTypeDefNil; } if (FAILED(pIMDI->GetNameOfTypeDef(tk, &name, &nameSpace))) { nameSpace = name = "Invalid TypeDef record"; } } MAKE_NAME_IF_NONE(name,tk); if((tkEncloser == mdTokenNil) || RidFromToken(tkEncloser)) { PrettyPrintClass(out,tkEncloser,pIMDI); if (TypeFromToken(tkEncloser) == mdtTypeRef || TypeFromToken(tkEncloser) == mdtTypeDef) { appendChar(out, '/'); //nameSpace = ""; //don't print namespaces for nested classes! } } if(TypeFromToken(tk)==mdtTypeDef) { unsigned L = (unsigned)strlen(ProperName(name))+1; char* szFN = NULL; if(nameSpace && *nameSpace) { const char* sz = ProperName(nameSpace); L+= (unsigned)strlen(sz)+1; szFN = new char[L]; sprintf_s(szFN,L,"%s.",sz); } else { szFN = new char[L]; *szFN = 0; } strcat_s(szFN,L, ProperName(name)); appendStr(out,JUMPPT(szFN,tk)); VDELETE(szFN); } else { if (nameSpace && *nameSpace) { appendStr(out, ProperName(nameSpace)); appendChar(out, '.'); } appendStr(out, ProperName(name)); } if(g_fDumpTokens) { char tmp[16]; sprintf_s(tmp,ARRAY_SIZE(tmp),"/*%08X*/",tk); appendStr(out,COMMENT(tmp)); } } break; case mdtAssemblyRef: { LPCSTR szName = NULL; #ifdef __ILDASM__ if (rAsmRefName && (RidFromToken(tk) <= ulNumAsmRefs)) { szName = rAsmRefName[RidFromToken(tk)-1]; } else #endif { if (FAILED(pIMDI->GetAssemblyRefProps(tk,NULL,NULL,&szName,NULL,NULL,NULL,NULL))) { szName = NULL; } } if ((szName != NULL) && ((*szName) != 0 )) { appendChar(out, '['); appendStr(out,JUMPPT(ProperName(szName),tk)); if(g_fDumpTokens) { char tmp[16]; sprintf_s(tmp,ARRAY_SIZE(tmp),"/*%08X*/",tk); appendStr(out,COMMENT(tmp)); } appendChar(out, ']'); } } break; case mdtAssembly: { LPCSTR szName; if (FAILED(pIMDI->GetAssemblyProps(tk,NULL,NULL,NULL,&szName,NULL,NULL))) { szName = NULL; } if ((szName != NULL) && ((*szName) != 0)) { appendChar(out, '['); appendStr(out,JUMPPT(ProperName(szName),tk)); if(g_fDumpTokens) { char tmp[16]; sprintf_s(tmp,ARRAY_SIZE(tmp),"/* %08X */",tk); appendStr(out,COMMENT(tmp)); } appendChar(out, ']'); } } break; case mdtModuleRef: { LPCSTR szName; if (FAILED(pIMDI->GetModuleRefProps(tk, &szName))) { szName = NULL; } if ((szName != NULL) && ((*szName) != 0)) { appendChar(out, '['); appendStr(out,KEYWORD(".module ")); appendStr(out,JUMPPT(ProperName(szName),tk)); if(g_fDumpTokens) { char tmp[16]; sprintf_s(tmp,ARRAY_SIZE(tmp),"/*%08X*/",tk); appendStr(out,COMMENT(tmp)); } appendChar(out, ']'); } } break; case mdtTypeSpec: { #ifdef __ILDASM__ DWORD ix; for(ix = 0; ix < g_NumTypedefs; ix++) { if((*g_typedefs)[ix].tkTypeSpec == tk) break; } if(ix < g_NumTypedefs) { appendStr(out,JUMPPT(ProperName((*g_typedefs)[ix].szName),(*g_typedefs)[ix].tkSelf)); } else #endif { ULONG cSig; PCCOR_SIGNATURE sig; if (FAILED(pIMDI->GetSigFromToken(tk, &cSig, &sig))) { char tmp[64]; sprintf_s(tmp, ARRAY_SIZE(tmp), "/*Invalid %08X record*/", tk); appendStr(out, COMMENT(tmp)); } else { PrettyPrintType(sig, out, pIMDI); } } if(g_fDumpTokens) { char tmp[16]; sprintf_s(tmp,ARRAY_SIZE(tmp),"/*%08X*/",tk); appendStr(out,COMMENT(tmp)); } } break; case mdtModule: break; default: { char str[128]; sprintf_s(str,ARRAY_SIZE(str)," [ERROR: INVALID TOKEN TYPE 0x%8.8X] ",tk); appendStr(out,ERRORMSG(str)); } } return(asString(out)); } const char* TrySigUncompressAndDumpSimpleNativeType( PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut, // [OUT] the expanded *pData ULONG &cbCur, SString &buf) { const char* sz = NULL; ULONG ulSize = CorSigUncompressData(pData, pDataOut); if (ulSize != (ULONG)-1) { switch (*pDataOut) { case NATIVE_TYPE_VOID: sz = " void"; break; case NATIVE_TYPE_BOOLEAN: sz = " bool"; break; case NATIVE_TYPE_I1: sz = " int8"; break; case NATIVE_TYPE_U1: sz = " unsigned int8"; break; case NATIVE_TYPE_I2: sz = " int16"; break; case NATIVE_TYPE_U2: sz = " unsigned int16"; break; case NATIVE_TYPE_I4: sz = " int32"; break; case NATIVE_TYPE_U4: sz = " unsigned int32"; break; case NATIVE_TYPE_I8: sz = " int64"; break; case NATIVE_TYPE_U8: sz = " unsigned int64"; break; case NATIVE_TYPE_R4: sz = " float32"; break; case NATIVE_TYPE_R8: sz = " float64"; break; case NATIVE_TYPE_SYSCHAR: sz = " syschar"; break; case NATIVE_TYPE_VARIANT: sz = " variant"; break; case NATIVE_TYPE_CURRENCY: sz = " currency"; break; case NATIVE_TYPE_DECIMAL: sz = " decimal"; break; case NATIVE_TYPE_DATE: sz = " date"; break; case NATIVE_TYPE_BSTR: sz = " bstr"; break; case NATIVE_TYPE_LPSTR: sz = " lpstr"; break; case NATIVE_TYPE_LPWSTR: sz = " lpwstr"; break; case NATIVE_TYPE_LPTSTR: sz = " lptstr"; break; case NATIVE_TYPE_OBJECTREF: sz = " objectref"; break; case NATIVE_TYPE_STRUCT: sz = " struct"; break; case NATIVE_TYPE_ERROR: sz = " error"; break; case NATIVE_TYPE_INT: sz = " int"; break; case NATIVE_TYPE_UINT: sz = " uint"; break; case NATIVE_TYPE_NESTEDSTRUCT: sz = " nested struct"; break; case NATIVE_TYPE_BYVALSTR: sz = " byvalstr"; break; case NATIVE_TYPE_ANSIBSTR: sz = " ansi bstr"; break; case NATIVE_TYPE_TBSTR: sz = " tbstr"; break; case NATIVE_TYPE_VARIANTBOOL: sz = " variant bool"; break; case NATIVE_TYPE_FUNC: sz = " method"; break; case NATIVE_TYPE_ASANY: sz = " as any"; break; case NATIVE_TYPE_LPSTRUCT: sz = " lpstruct"; break; case NATIVE_TYPE_PTR: case NATIVE_TYPE_SAFEARRAY: case NATIVE_TYPE_ARRAY: case NATIVE_TYPE_FIXEDSYSSTRING: case NATIVE_TYPE_FIXEDARRAY: case NATIVE_TYPE_INTF: case NATIVE_TYPE_IUNKNOWN: case NATIVE_TYPE_IDISPATCH: case NATIVE_TYPE_CUSTOMMARSHALER: case NATIVE_TYPE_END: case NATIVE_TYPE_MAX: sz = ""; break; default: sz = NULL; } } if (sz) cbCur += ulSize; else buf.Clear(); return sz; } bool TrySigUncompress(PCCOR_SIGNATURE pData, // [IN] compressed data ULONG *pDataOut, // [OUT] the expanded *pData ULONG &cbCur, SString &buf) { ULONG ulSize = CorSigUncompressData(pData, pDataOut); if (ulSize == (ULONG)-1) { buf.Clear(); return false; } else { cbCur += ulSize; return true; } } #ifdef _PREFAST_ #pragma warning(push) #pragma warning(disable:21000) // Suppress PREFast warning about overly large function #endif char* DumpMarshaling(IMDInternalImport* pImport, _Inout_updates_(cchszString) char* szString, DWORD cchszString, mdToken tok) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; PCCOR_SIGNATURE pSigNativeType = NULL; ULONG cbNativeType = 0; SString buf; if (RidFromToken(tok) && SUCCEEDED(pImport->GetFieldMarshal( // return error if no native type associate with the token tok, // [IN] given fielddef &pSigNativeType, // [OUT] the native type signature &cbNativeType))) // [OUT] the count of bytes of *ppvNativeType { ULONG cbCur = 0; ULONG ulData; const char *sz = NULL; BOOL fAddAsterisk = FALSE, fAddBrackets = FALSE; buf.AppendPrintf(" %s(", KEYWORD("marshal")); while (cbCur < cbNativeType) { ulData = NATIVE_TYPE_MAX; sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf); if (!sz) goto error; if(*sz == 0) { switch (ulData) { case NATIVE_TYPE_PTR: sz = ""; fAddAsterisk = TRUE; break; case NATIVE_TYPE_SAFEARRAY: sz = ""; buf.AppendASCII(KEYWORD(" safearray")); ulData = VT_EMPTY; if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; } switch(ulData & VT_TYPEMASK) { case VT_EMPTY: sz=""; break; case VT_NULL: sz=" null"; break; case VT_VARIANT: sz=" variant"; break; case VT_CY: sz=" currency"; break; case VT_VOID: sz=" void"; break; case VT_BOOL: sz=" bool"; break; case VT_I1: sz=" int8"; break; case VT_I2: sz=" int16"; break; case VT_I4: sz=" int32"; break; case VT_I8: sz=" int64"; break; case VT_R4: sz=" float32"; break; case VT_R8: sz=" float64"; break; case VT_UI1: sz=" unsigned int8"; break; case VT_UI2: sz=" unsigned int16"; break; case VT_UI4: sz=" unsigned int32"; break; case VT_UI8: sz=" unsigned int64"; break; case VT_PTR: sz=" *"; break; case VT_DECIMAL: sz=" decimal"; break; case VT_DATE: sz=" date"; break; case VT_BSTR: sz=" bstr"; break; case VT_LPSTR: sz=" lpstr"; break; case VT_LPWSTR: sz=" lpwstr"; break; case VT_UNKNOWN: sz=" iunknown"; break; case VT_DISPATCH: sz=" idispatch"; break; case VT_SAFEARRAY: sz=" safearray"; break; case VT_INT: sz=" int"; break; case VT_UINT: sz=" unsigned int"; break; case VT_ERROR: sz=" error"; break; case VT_HRESULT: sz=" hresult"; break; case VT_CARRAY: sz=" carray"; break; case VT_USERDEFINED: sz=" userdefined"; break; case VT_RECORD: sz=" record"; break; case VT_FILETIME: sz=" filetime"; break; case VT_BLOB: sz=" blob"; break; case VT_STREAM: sz=" stream"; break; case VT_STORAGE: sz=" storage"; break; case VT_STREAMED_OBJECT: sz=" streamed_object"; break; case VT_STORED_OBJECT: sz=" stored_object"; break; case VT_BLOB_OBJECT: sz=" blob_object"; break; case VT_CF: sz=" cf"; break; case VT_CLSID: sz=" clsid"; break; default: sz=NULL; break; } if(sz) buf.AppendASCII(KEYWORD(sz)); else { // buf.AppendPrintf(ERRORMSG(" [ILLEGAL VARIANT TYPE 0x%X]"),ulData & VT_TYPEMASK); buf.Clear(); goto error; } sz=""; switch(ulData & (~VT_TYPEMASK)) { case VT_ARRAY: sz = "[]"; break; case VT_VECTOR: sz = " vector"; break; case VT_BYREF: sz = "&"; break; case VT_BYREF|VT_ARRAY: sz = "&[]"; break; case VT_BYREF|VT_VECTOR: sz = "& vector"; break; case VT_ARRAY|VT_VECTOR: sz = "[] vector"; break; case VT_BYREF|VT_ARRAY|VT_VECTOR: sz = "&[] vector"; break; } buf.AppendASCII(KEYWORD(sz)); sz=""; // Extract the user defined sub type name. if (cbCur < cbNativeType) { LPUTF8 strTemp = NULL; int strLen = 0; int ByteCountLength = 0; strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); cbCur += ByteCountLength; if(strLen) { #ifdef _PREFAST_ #pragma prefast(push) #pragma prefast(disable:22009 "Suppress PREFAST warnings about integer overflow") #endif strTemp = (LPUTF8)_alloca(strLen + 1); memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); strTemp[strLen] = 0; buf.AppendPrintf(", \"%s\"", UnquotedProperName(strTemp)); cbCur += strLen; #ifdef _PREFAST_ #pragma prefast(pop) #endif } } break; case NATIVE_TYPE_ARRAY: sz = ""; fAddBrackets = TRUE; break; case NATIVE_TYPE_FIXEDSYSSTRING: { sz = ""; buf.AppendASCII(KEYWORD(" fixed sysstring")); buf.AppendASCII(" ["); if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; buf.AppendPrintf("%d",ulData); } buf.AppendASCII("]"); } break; case NATIVE_TYPE_FIXEDARRAY: { sz = ""; buf.AppendASCII(KEYWORD(" fixed array")); buf.AppendASCII(" ["); if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; buf.AppendPrintf("%d",ulData); } buf.AppendASCII("]"); if (cbCur < cbNativeType) { sz = TrySigUncompressAndDumpSimpleNativeType(&pSigNativeType[cbCur], &ulData, cbCur, buf); if (!sz) goto error; } } break; case NATIVE_TYPE_INTF: buf.AppendASCII(KEYWORD(" interface")); goto DumpIidParamIndex; case NATIVE_TYPE_IUNKNOWN: buf.AppendASCII(KEYWORD(" iunknown")); goto DumpIidParamIndex; case NATIVE_TYPE_IDISPATCH: buf.AppendASCII(KEYWORD(" idispatch")); DumpIidParamIndex: sz = " "; if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; buf.AppendPrintf("(%s = %d)",KEYWORD("iidparam"),ulData); } break; case NATIVE_TYPE_CUSTOMMARSHALER: { LPUTF8 strTemp = NULL; int strLen = 0; int ByteCountLength = 0; BOOL fFourStrings = FALSE; sz = ""; buf.AppendASCII(KEYWORD(" custom")); buf.AppendASCII(" ("); // Extract the typelib GUID. strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); cbCur += ByteCountLength; if(strLen) { fFourStrings = TRUE; strTemp = (LPUTF8)(new char[strLen + 1]); if(strTemp) { memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); strTemp[strLen] = 0; buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp)); cbCur += strLen; VDELETE(strTemp); } } if(cbCur >= cbNativeType) { // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } else { //_ASSERTE(cbCur < cbNativeType); // Extract the name of the native type. strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); cbCur += ByteCountLength; if(fFourStrings) { if(strLen) { strTemp = (LPUTF8)(new char[strLen + 1]); if(strTemp) { memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); strTemp[strLen] = 0; buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp)); cbCur += strLen; VDELETE(strTemp); } } else buf.AppendASCII("\"\","); } if(cbCur >= cbNativeType) { // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } else { //_ASSERTE(cbCur < cbNativeType); // Extract the name of the custom marshaler. strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); cbCur += ByteCountLength; if(strLen) { strTemp = (LPUTF8)(new char[strLen + 1]); if(strTemp) { memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); strTemp[strLen] = 0; buf.AppendPrintf("\"%s\",",UnquotedProperName(strTemp)); cbCur += strLen; VDELETE(strTemp); } } else buf.AppendASCII("\"\","); if(cbCur >= cbNativeType) { // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } else { // Extract the cookie string. strLen = GetLength(&pSigNativeType[cbCur], &ByteCountLength); cbCur += ByteCountLength; if(cbCur+strLen > cbNativeType) { // buf.AppendASCII(ERRORMSG("/* INCOMPLETE MARSHALER INFO */")); buf.Clear(); goto error; } else { if(strLen) { strTemp = (LPUTF8)(new (nothrow) char[strLen + 1]); if(strTemp) { memcpy(strTemp, (LPUTF8)&pSigNativeType[cbCur], strLen); strTemp[strLen] = 0; buf.AppendASCII("\""); // Copy the cookie string and transform the embedded nulls into \0's. for (int i = 0; i < strLen - 1; i++, cbCur++) { if (strTemp[i] == 0) buf.AppendASCII("\\0"); else { buf.AppendPrintf("%c", strTemp[i]); } } buf.AppendPrintf("%c\"", strTemp[strLen - 1]); cbCur++; VDELETE(strTemp); } } else buf.AppendASCII("\"\""); //_ASSERTE(cbCur <= cbNativeType); } } } } buf.AppendASCII(")"); } break; default: { sz = ""; } } // end switch } if(*sz) { buf.AppendASCII(KEYWORD(sz)); if(fAddAsterisk) { buf.AppendASCII("*"); fAddAsterisk = FALSE; } if(fAddBrackets) { ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1; buf.AppendASCII("["); fAddBrackets = FALSE; if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; ulSizeParam = ulData; if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; ulSizeConst = ulData; if (cbCur < cbNativeType) { // retrieve flags if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; if((ulData & 1) == 0) ulSizeParam = 0xFFFFFFFF; } } } if(ulSizeConst != 0xFFFFFFFF) { buf.AppendPrintf("%d",ulSizeConst); // if(ulSizeParam == 0) ulSizeParam = 0xFFFFFFFF; // don't need +0 } if(ulSizeParam != 0xFFFFFFFF) { buf.AppendPrintf(" + %d",ulSizeParam); } buf.AppendASCII("]"); } } if (ulData >= NATIVE_TYPE_MAX) break; } // end while (cbCur < cbNativeType) // still can have outstanding asterisk or brackets if(fAddAsterisk) { buf.AppendASCII("*"); fAddAsterisk = FALSE; } if(fAddBrackets) { ULONG ulSizeParam=(ULONG)-1,ulSizeConst=(ULONG)-1; buf.AppendASCII("["); fAddBrackets = FALSE; if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; ulSizeParam = ulData; if (cbCur < cbNativeType) { if (!TrySigUncompress(&pSigNativeType[cbCur], &ulData, cbCur, buf)) goto error; ulSizeConst = ulData; } } if(ulSizeConst != 0xFFFFFFFF) { buf.AppendPrintf("%d",ulSizeConst); // if(ulSizeParam == 0) ulSizeParam = 0xFFFFFFFF; // don't need +0 } if(ulSizeParam != 0xFFFFFFFF) { buf.AppendPrintf(" + %d",ulSizeParam); } buf.AppendASCII("]"); } buf.AppendASCII(") "); }// end if(SUCCEEDED error: if (buf.IsEmpty() && cbNativeType != 0) { // There was something that we didn't grok in the signature. // Just dump out the blob as hex buf.AppendPrintf(" %s({", KEYWORD("marshal")); while (cbNativeType--) buf.AppendPrintf(" %2.2X", *pSigNativeType++); buf.AppendASCII(" }) "); char * tgt = szString + strlen(szString); int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%s", buf.GetUTF8()); if (sprintf_ret == -1) { // Hit an error. Oh well, nothing to do... return tgt; } else { return tgt + sprintf_ret; } } else { char * tgt = szString + strlen(szString); int sprintf_ret = sprintf_s(tgt, cchszString - (tgt - szString), "%s", buf.GetUTF8()); if (sprintf_ret == -1) { // There was an error, possibly with converting the Unicode characters. buf.Clear(); if (cbNativeType != 0) goto error; return tgt; // Oh well, nothing to do... } else { return tgt + sprintf_ret; } } } #ifdef _PREFAST_ #pragma warning(pop) #endif char* DumpParamAttr(_Inout_updates_(cchszString) char* szString, DWORD cchszString, DWORD dwAttr) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; char *szptr = &szString[strlen(szString)]; char *was_szptr = szptr; if(IsPdIn(dwAttr)) { szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr), KEYWORD("[in]")); } if(IsPdOut(dwAttr)) { szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr),KEYWORD("[out]")); } if(IsPdOptional(dwAttr)) { szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr),KEYWORD("[opt]")); } if(szptr != was_szptr) { szptr+=sprintf_s(szptr,cchszString - (szptr - was_szptr)," "); } return szptr; } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/formattype.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _formatType_h #define _formatType_h #include "corpriv.h" // for IMDInternalImport // ILDASM code doesn't memcpy on gc pointers, so it prefers the real // memcpy rather than GCSafeMemCpy. #if defined(_DEBUG) && !defined(DACCESS_COMPILE) #ifdef memcpy #undef memcpy #endif #endif #define MAX_PREFIX_SIZE 32 struct ParamDescriptor { char* name; mdToken tok; DWORD attr; }; char* DumpMarshaling(IMDInternalImport* pImport, _Inout_updates_(cchszString) char* szString, DWORD cchszString, mdToken tok); char* DumpParamAttr(_Inout_updates_(cchszString) char* szString, DWORD cchszString, DWORD dwAttr); void appendStr(CQuickBytes *out, const char* str, unsigned len=(unsigned)-1); void insertStr(CQuickBytes *out, const char* str); char* asString(CQuickBytes *out); const char* PrettyPrintSig( PCCOR_SIGNATURE typePtr, // type to convert, unsigned typeLen, // the length of 'typePtr' const char* name, // can be "", the name of the method for this sig 0 means local var sig CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternalImport class with ComSig _In_opt_ const char* inlabel, // prefix for names (NULL if no names required) BOOL printTyArity=FALSE); // flag to print Type Param number (MemberRefs only) PCCOR_SIGNATURE PrettyPrintType( PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig PCCOR_SIGNATURE PrettyPrintTypeOrDef( // outside ILDASM - simple wrapper of PrettyPrintType PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // ptr to IMDInternal class with ComSig const char* PrettyPrintClass( CQuickBytes *out, // where to put the pretty printed string mdToken tk, // The class token to look up IMDInternalImport *pIMDI); // ptr to IMDInternalImport class with ComSig //================= ILDASM-specific ================================================================== #ifdef __ILDASM__ #include "../ildasm/dynamicarray.h" bool IsNameToQuote(const char *name); bool IsLocalToQuote(const char *name); const char* UnquotedProperName(_In_ __nullterminated const char* name, unsigned len=(unsigned)-1); const char* ProperName(_In_ __nullterminated const char* name, bool isLocalName = false); #define ProperLocalName(x) ProperName(x, true) const char* KEYWORD(_In_opt_z_ const char* szOrig); const char* COMMENT(_In_opt_z_ const char* szOrig); const char* ERRORMSG(_In_opt_z_ const char* szOrig); const char* ANCHORPT(_In_ __nullterminated const char* szOrig, mdToken tk); const char* JUMPPT(_In_ __nullterminated const char* szOrig, mdToken tk); const char* SCOPE(void); const char* UNSCOPE(void); const char* LTN(void); const char* GTN(void); const char* AMP(void); extern BOOL g_fDumpRTF,g_fDumpHTML; // declared in FormatType.cpp //------------------------------------------------------------------------------- // Protection against null names extern const char* const szStdNamePrefix[]; //declared in formatType.cpp extern DynamicArray *g_dups; extern DWORD g_NumDups; inline BOOL IsDup(mdToken tk) { if(g_NumDups) { mdToken tktype = TypeFromToken(tk); if((tktype==mdtTypeDef)||(tktype==mdtMethodDef)||(tktype==mdtFieldDef)) { for (unsigned i=0; i>24],tk&0x00FFFFFF); psz = sz; } } struct TypeDefDescr { char* szName; mdToken tkTypeSpec; mdToken tkSelf; PCCOR_SIGNATURE psig; ULONG cb; }; extern DynamicArray *g_typedefs; extern DWORD g_NumTypedefs; //------------------------------------------------------------------------------- // Reference analysis (ILDASM) struct TokPair { mdToken tkUser; mdToken tkRef; TokPair() { tkUser = tkRef = 0; }; }; extern DynamicArray *g_refs; extern DWORD g_NumRefs; extern mdToken g_tkRefUser; // for PrettyPrintSig #define REGISTER_REF(x,y) if(g_refs && (x)){ (*g_refs)[g_NumRefs].tkUser = x; (*g_refs)[g_NumRefs++].tkRef = y;} //-------------------------------------------------------------------------------- // No-throw deallocators #define SDELETE(x) {PAL_CPP_TRY{ delete (x); } PAL_CPP_CATCH_ALL { _ASSERTE(!"AV in scalar deallocator");} PAL_CPP_ENDTRY; (x)=NULL; } #define VDELETE(x) {PAL_CPP_TRY{ delete [] (x); } PAL_CPP_CATCH_ALL { _ASSERTE(!"AV in vector deallocator");}; PAL_CPP_ENDTRY; (x)=NULL; } //-------------------------------------------------------------------------------- // Generic param names extern mdToken g_tkVarOwner; extern mdToken g_tkMVarOwner; //void SetVarOwner(mdToken tk) { g_tkVarOwner = tk; } //void SetMVarOwner(mdToken tk) { g_tkMVarOwner = tk; } BOOL PrettyPrintGP( // defined in dasm.cpp mdToken tkOwner, // Class, method or 0 CQuickBytes *out, // where to put the pretty printed generic param int n); // Index of generic param //============== End of ILDASM-specific ================================================================ #else #define IsNameToQuote(x) false #define IsLocalToQuote(x) false #define UnquotedProperName(x) x #define ProperName(x) x #define ProperLocalName(x) x #define KEYWORD(x) x #define COMMENT(x) x #define ERRORMSG(x) x #define ANCHORPT(x,y) x #define JUMPPT(x,y) x #define SCOPE() "{" #define UNSCOPE() "}" #define LTN() "<" #define GTN() ">" #define AMP() "&" #define REGISTER_REF(x,y) {} #define MAKE_NAME_IF_NONE(x,y) { } #define g_fDumpTokens false #define SDELETE(x) delete (x) #define VDELETE(x) delete [] (x) #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/fstream.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __FSTREAM_H_INCLUDED__ #define __FSTREAM_H_INCLUDED__ #include class CFileStream : public IStream { public: CFileStream(); virtual ~CFileStream(); HRESULT OpenForRead(LPCWSTR wzFilePath); HRESULT OpenForWrite(LPCWSTR wzFilePath); // IUnknown methods: STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release(); STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppvObj); // ISequentialStream methods: STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead); STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten); // IStream methods: STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize); STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); STDMETHODIMP Commit(DWORD grfCommitFlags); STDMETHODIMP Revert(); STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag); STDMETHODIMP Clone(IStream **ppIStream); private: BOOL Close(); private: LONG _cRef; HANDLE _hFile; }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/fstring.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // FString.h (Fast String) // // --------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------ // FString is fast string handling namespace // 1) Simple // 2) No C++ exception // 3) Optimized for speed #ifndef _FSTRING_H_ #define _FSTRING_H_ namespace FString { // Note: All "length" parameters do not count the space for the null terminator. // Caller of Unicode_Utf8 and Utf8_Unicode must pass in a buffer of size at least length + 1. // Scan for ASCII only string, calculate result UTF8 string length HRESULT Unicode_Utf8_Length(_In_z_ LPCWSTR pString, _Out_ bool * pAllAscii, _Out_ DWORD * pLength); // Convert UNICODE string to UTF8 string. Direct/fast conversion if ASCII HRESULT Unicode_Utf8(_In_z_ LPCWSTR pString, bool allAscii, _Out_writes_bytes_(length) LPSTR pBuffer, DWORD length); // Scan for ASCII string, calculate result UNICODE string length HRESULT Utf8_Unicode_Length(_In_z_ LPCSTR pString, _Out_ bool * pAllAscii, _Out_ DWORD * pLength); // Convert UTF8 string to UNICODE. Direct/fast conversion if ASCII HRESULT Utf8_Unicode(_In_z_ LPCSTR pString, bool allAscii, _Out_writes_bytes_(length) LPWSTR pBuffer, DWORD length); HRESULT ConvertUnicode_Utf8(_In_z_ LPCWSTR pString, _Outptr_result_z_ LPSTR * pBuffer); HRESULT ConvertUtf8_Unicode(_In_z_ LPCSTR pString, _Outptr_result_z_ LPWSTR * pBuffer); } // namespace FString #endif // _FSTRING_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcdecoder.cpp ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX XX XX GCDecode XX XX XX XX Logic to decode the JIT method header and GC pointer tables XX XX XX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ // ****************************************************************************** // WARNING!!!: This code is also used by SOS in the diagnostics repo. Should be // updated in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcdecoder.cpp // ****************************************************************************** #ifdef TARGET_X86 /* This file is shared between the VM and JIT/IL and SOS/Strike directories */ #include "gcinfotypes.h" /*****************************************************************************/ /* * This entire file depends upon GC2_ENCODING being set to 1 * *****************************************************************************/ size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* val) { LIMITED_METHOD_CONTRACT; size_t size = 1; BYTE byte = *src++; unsigned value = byte & 0x7f; while (byte & 0x80) { size++; byte = *src++; value <<= 7; value += byte & 0x7f; } *val = value; return size; } size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue) { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; unsigned delta; size_t size = decodeUnsigned(src, &delta); *value = lastValue + delta; return size; } size_t FASTCALL decodeSigned(PTR_CBYTE src, int* val) { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; size_t size = 1; BYTE byte = *src++; BYTE first = byte; int value = byte & 0x3f; while (byte & 0x80) { size++; byte = *src++; value <<= 7; value += byte & 0x7f; } if (first & 0x40) value = -value; *val = value; return size; } /*****************************************************************************/ #if defined(_MSC_VER) #ifdef HOST_X86 #pragma optimize("tgy", on) #endif #endif PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header) { LIMITED_METHOD_DAC_CONTRACT; BYTE nextByte = *table++; BYTE encoding = nextByte & 0x7f; GetInfoHdr(encoding, header); while (nextByte & MORE_BYTES_TO_FOLLOW) { nextByte = *table++; encoding = nextByte & ADJ_ENCODING_MAX; // encoding here always corresponds to codes in InfoHdrAdjust set if (encoding < NEXT_FOUR_START) { if (encoding < SET_ARGCOUNT) { header->frameSize = encoding - SET_FRAMESIZE; } else if (encoding < SET_PROLOGSIZE) { header->argCount = encoding - SET_ARGCOUNT; } else if (encoding < SET_EPILOGSIZE) { header->prologSize = encoding - SET_PROLOGSIZE; } else if (encoding < SET_EPILOGCNT) { header->epilogSize = encoding - SET_EPILOGSIZE; } else if (encoding < SET_UNTRACKED) { header->epilogCount = (encoding - SET_EPILOGCNT) / 2; header->epilogAtEnd = ((encoding - SET_EPILOGCNT) & 1) == 1; assert(!header->epilogAtEnd || (header->epilogCount == 1)); } else if (encoding < FIRST_FLIP) { header->untrackedCnt = encoding - SET_UNTRACKED; _ASSERTE(header->untrackedCnt != HAS_UNTRACKED); } else switch (encoding) { default: assert(!"Unexpected encoding"); break; case FLIP_EDI_SAVED: header->ediSaved ^= 1; break; case FLIP_ESI_SAVED: header->esiSaved ^= 1; break; case FLIP_EBX_SAVED: header->ebxSaved ^= 1; break; case FLIP_EBP_SAVED: header->ebpSaved ^= 1; break; case FLIP_EBP_FRAME: header->ebpFrame ^= 1; break; case FLIP_INTERRUPTIBLE: header->interruptible ^= 1; break; case FLIP_DOUBLE_ALIGN: header->doubleAlign ^= 1; break; case FLIP_SECURITY: header->security ^= 1; break; case FLIP_HANDLERS: header->handlers ^= 1; break; case FLIP_LOCALLOC: header->localloc ^= 1; break; case FLIP_EDITnCONTINUE: header->editNcontinue ^= 1; break; case FLIP_VAR_PTR_TABLE_SZ: header->varPtrTableSize ^= HAS_VARPTR; break; case FFFF_UNTRACKED_CNT: header->untrackedCnt = HAS_UNTRACKED; break; case FLIP_VARARGS: header->varargs ^= 1; break; case FLIP_PROF_CALLBACKS: header->profCallbacks ^= 1; break; case FLIP_HAS_GENERICS_CONTEXT: header->genericsContext ^= 1; break; case FLIP_GENERICS_CONTEXT_IS_METHODDESC: header->genericsContextIsMethodDesc ^= 1; break; case FLIP_HAS_GS_COOKIE: header->gsCookieOffset ^= HAS_GS_COOKIE_OFFSET; break; case FLIP_SYNC: header->syncStartOffset ^= HAS_SYNC_OFFSET; break; case FLIP_REV_PINVOKE_FRAME: header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET ? HAS_REV_PINVOKE_FRAME_OFFSET : INVALID_REV_PINVOKE_OFFSET; break; case NEXT_OPCODE: _ASSERTE((nextByte & MORE_BYTES_TO_FOLLOW) && "Must have another code"); nextByte = *table++; encoding = nextByte & ADJ_ENCODING_MAX; // encoding here always corresponds to codes in InfoHdrAdjust2 set _ASSERTE(encoding < SET_RET_KIND_MAX); header->returnKind = (ReturnKind)encoding; break; } } else { unsigned char lowBits; switch (encoding >> 4) { default: assert(!"Unexpected encoding"); break; case 5: assert(NEXT_FOUR_FRAMESIZE == 0x50); lowBits = encoding & 0xf; header->frameSize <<= 4; header->frameSize += lowBits; break; case 6: assert(NEXT_FOUR_ARGCOUNT == 0x60); lowBits = encoding & 0xf; header->argCount <<= 4; header->argCount += lowBits; break; case 7: if ((encoding & 0x8) == 0) { assert(NEXT_THREE_PROLOGSIZE == 0x70); lowBits = encoding & 0x7; header->prologSize <<= 3; header->prologSize += lowBits; } else { assert(NEXT_THREE_EPILOGSIZE == 0x78); lowBits = encoding & 0x7; header->epilogSize <<= 3; header->epilogSize += lowBits; } break; } } } return table; } void FASTCALL decodeCallPattern(int pattern, unsigned * argCnt, unsigned * regMask, unsigned * argMask, unsigned * codeDelta) { CONTRACTL { NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; assert((pattern>=0) && (pattern<80)); CallPattern pat; pat.val = callPatternTable[pattern]; *argCnt = pat.fld.argCnt; *regMask = pat.fld.regMask; // EBP,EBX,ESI,EDI *argMask = pat.fld.argMask; *codeDelta = pat.fld.codeDelta; } #define YES HAS_VARPTR const InfoHdrSmall infoHdrShortcut[128] = { // Prolog size // | // | Epilog size // | | // | | Epilog count // | | | // | | | Epilog at end // | | | | // | | | | EDI saved // | | | | | // | | | | | ESI saved // | | | | | | // | | | | | | EBX saved // | | | | | | | // | | | | | | | EBP saved // | | | | | | | | // | | | | | | | | EBP-frame // | | | | | | | | | // | | | | | | | | | Interruptible method // | | | | | | | | | | // | | | | | | | | | | doubleAlign // | | | | | | | | | | | // | | | | | | | | | | | security flag // | | | | | | | | | | | | // | | | | | | | | | | | | handlers // | | | | | | | | | | | | | // | | | | | | | | | | | | | localloc // | | | | | | | | | | | | | | // | | | | | | | | | | | | | | edit and continue // | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | varargs // | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | ProfCallbacks // | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | genericsContext // | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | genericsContextIsMethodDesc // | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | returnKind // | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | Arg count // | | | | | | | | | | | | | | | | | | | | | Counted occurrences // | | | | | | | | | | | | | | | | | | | | | Frame size | // | | | | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | | | untrackedCnt | Header encoding // | | | | | | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | | | | varPtrTable | | // | | | | | | | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | | | | | gsCookieOffs | | // | | | | | | | | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | | | | | | syncOffs | | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | // | | | | | | | | | | | | | | | | | | | | | | | | | | | | | // v v v v v v v v v v v v v v v v v v v v v v v v v v v v v { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1139 00 { 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 128738 01 { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3696 02 { 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 402 03 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 4259 04 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 3379 05 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 2058 06 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 728 07 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 984 08 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0 }, // 606 09 { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0 }, // 1110 0a { 0, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 1, 0 }, // 414 0b { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1553 0c { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 584 0d { 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 2182 0e { 1, 2, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3445 0f { 1, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1369 10 { 1, 2, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 515 11 { 1, 2, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 21127 12 { 1, 2, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3517 13 { 1, 2, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 750 14 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1876 15 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1665 16 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 729 17 { 1, 4, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 484 18 { 1, 4, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 331 19 { 2, 3, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 1a { 2, 3, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 964 1b { 2, 3, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3713 1c { 2, 3, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 466 1d { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1325 1e { 2, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 712 1f { 2, 3, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 588 20 { 2, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 20542 21 { 2, 3, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 3802 22 { 2, 3, 3, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 798 23 { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1900 24 { 2, 5, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 385 25 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1617 26 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1743 27 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 909 28 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 1, 0 }, // 602 29 { 2, 5, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 352 2a { 2, 6, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 657 2b { 2, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1283 2c { 2, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1286 2d { 3, 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1495 2e { 3, 4, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1989 2f { 3, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1154 30 { 3, 4, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 9300 31 { 3, 4, 2, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 392 32 { 3, 4, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1720 33 { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1246 34 { 3, 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 800 35 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1179 36 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 1368 37 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 349 38 { 3, 6, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0 }, // 505 39 { 3, 6, 2, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 629 3a { 3, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 2, YES }, // 365 3b { 4, 5, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 487 3c { 4, 5, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 1752 3d { 4, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1959 3e { 4, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 2436 3f { 4, 5, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 861 40 { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1459 41 { 4, 7, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 950 42 { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 1491 43 { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, // 879 44 { 4, 7, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0 }, // 408 45 { 5, 4, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 4870 46 { 5, 6, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 359 47 { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 915 48 { 5, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 412 49 { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1288 4a { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 1591 4b { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, YES }, // 361 4c { 5, 6, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0 }, // 623 4d { 5, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0 }, // 1239 4e { 6, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 457 4f { 6, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 606 50 { 6, 4, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1073 51 { 6, 4, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 508 52 { 6, 6, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 330 53 { 6, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 1709 54 { 6, 7, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1164 55 { 7, 4, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // 556 56 { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 529 57 { 7, 5, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 1423 58 { 7, 8, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 2455 59 { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 956 5a { 7, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, YES }, // 1399 5b { 7, 8, 2, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, YES }, // 587 5c { 7, 10, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 743 5d { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0 }, // 1004 5e { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, YES }, // 487 5f { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0 }, // 337 60 { 7, 10, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 0, YES }, // 361 61 { 8, 3, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 560 62 { 8, 6, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 1377 63 { 9, 4, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 877 64 { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0 }, // 3041 65 { 9, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 349 66 { 10, 5, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 2061 67 { 10, 5, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0 }, // 577 68 { 11, 6, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0 }, // 1195 69 { 12, 5, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, // 491 6a { 13, 8, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, YES }, // 627 6b { 13, 8, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0 }, // 1099 6c { 13, 10, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 1, YES }, // 488 6d { 14, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 574 6e { 16, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 1281 6f { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, YES }, // 1881 70 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 339 71 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0 }, // 2594 72 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0 }, // 339 73 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 2107 74 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 2372 75 { 16, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, YES }, // 1078 76 { 16, 7, 2, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, YES }, // 384 77 { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 4, 1, YES }, // 1541 78 { 16, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 4, 1, YES }, // 975 79 { 19, 7, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 546 7a { 24, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, YES }, // 675 7b { 45, 9, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }, // 902 7c { 51, 7, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, YES }, // 432 7d { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, YES }, // 361 7e { 51, 7, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0 }, // 703 7f }; bool InfoHdrSmall::isHeaderMatch(const InfoHdr& target) const { #ifdef _ASSERTE // target cannot have place-holder values. _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && target.varPtrTableSize != HAS_VARPTR && target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && target.syncStartOffset != HAS_SYNC_OFFSET && target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); #endif // compare two InfoHdr's up to but not including the untrackCnt field if (memcmp(this, &target, offsetof(InfoHdr, untrackedCnt)) != 0) return false; if (untrackedCnt != target.untrackedCnt) { if (target.untrackedCnt <= SET_UNTRACKED_MAX) return false; else if (untrackedCnt != HAS_UNTRACKED) return false; } if (varPtrTableSize != target.varPtrTableSize) { if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0)) return false; } if (target.gsCookieOffset != INVALID_GS_COOKIE_OFFSET) return false; if (target.syncStartOffset != INVALID_SYNC_OFFSET) return false; if (target.revPInvokeOffset!= INVALID_REV_PINVOKE_OFFSET) return false; return true; } const unsigned callCommonDelta[4] = { 6,8,10,12 }; /* * In the callPatternTable each 32-bit unsigned value represents four bytes: * * byte0,byte1,byte2,byte3 => codeDelta,argMask,regMask,argCnt * for example 0x0c000301 => codeDelta of 12, argMask of 0, * regMask of 0x3, argCnt of 1 * * Furthermore within the table the following maximum values are in place: * * codeDelta <= CP_MAX_CODE_DELTA // (0x23) * argCnt <= CP_MAX_ARG_CNT // (0x02) * argMask <= CP_MAX_ARG_MASK // (0x00) * * Note that ARG_CNT is the count of pushed args for a nested call site. * And since the first two arguments are always passed in registers * an ARG_CNT of 1 would mean that the nested call site had three arguments * * Note that ARG_MASK is the mask of pushed args that contain GC pointers * since the first two arguments are always passed in registers it is * a fairly rare occurrence to push a GC pointer as an argument, since it * only occurs for nested calls, when the third or later argument for the * outer call contains a GC ref. * * Additionally the encoding of the regMask uses the following bits: * EDI = 0x1, ESI = 0x2, EBX = 0x4, EBP = 0x8 * */ const unsigned callPatternTable[80] = { // # of occurrences 0x0a000200, // 30109 0x0c000200, // 22970 0x0c000201, // 19005 0x0a000300, // 12193 0x0c000300, // 10614 0x0e000200, // 10253 0x10000200, // 9746 0x0b000200, // 9698 0x0d000200, // 9625 0x08000200, // 8909 0x0c000301, // 8522 0x11000200, // 7382 0x0e000300, // 7357 0x12000200, // 7139 0x10000300, // 7062 0x11000300, // 6970 0x0a000201, // 6842 0x0a000100, // 6803 0x0f000200, // 6795 0x13000200, // 6559 0x08000300, // 6079 0x15000200, // 5874 0x0d000201, // 5492 0x0c000100, // 5193 0x0d000300, // 5165 0x23000200, // 5143 0x1b000200, // 5035 0x14000200, // 4872 0x0f000300, // 4850 0x0a000700, // 4781 0x09000200, // 4560 0x12000300, // 4496 0x16000200, // 4180 0x07000200, // 4021 0x09000300, // 4012 0x0c000700, // 3988 0x0c000600, // 3946 0x0e000100, // 3823 0x1a000200, // 3764 0x18000200, // 3744 0x17000200, // 3736 0x1f000200, // 3671 0x13000300, // 3559 0x0a000600, // 3214 0x0e000600, // 3109 0x08000201, // 2984 0x0b000300, // 2928 0x0a000301, // 2859 0x07000100, // 2826 0x13000100, // 2782 0x09000301, // 2644 0x19000200, // 2638 0x11000700, // 2618 0x21000200, // 2518 0x0d000202, // 2484 0x10000100, // 2480 0x0f000600, // 2413 0x14000300, // 2363 0x0c000500, // 2362 0x08000301, // 2285 0x20000200, // 2245 0x10000700, // 2240 0x0f000100, // 2236 0x1e000200, // 2214 0x0c000400, // 2193 0x16000300, // 2171 0x12000600, // 2132 0x22000200, // 2011 0x1d000200, // 2011 0x0c000f00, // 1996 0x0e000700, // 1971 0x0a000400, // 1970 0x09000201, // 1932 0x10000600, // 1903 0x15000300, // 1847 0x0a000101, // 1814 0x0a000b00, // 1771 0x0c000601, // 1737 0x09000700, // 1737 0x07000300, // 1684 }; #endif // TARGET_X86 ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcdump.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** * GCDump.h * * Defines functions to display the GCInfo as defined by the GC-encoding * spec. The GC information may be either dynamically created by a * Just-In-Time compiler conforming to the standard code-manager spec, * or may be persisted by a managed native code compiler conforming * to the standard code-manager spec. */ /*****************************************************************************/ #ifndef __GCDUMP_H__ #define __GCDUMP_H__ /*****************************************************************************/ #include "gcinfotypes.h" // For InfoHdr #ifndef FASTCALL #ifndef TARGET_UNIX #define FASTCALL __fastcall #else #define FASTCALL #endif #endif class GCDump { public: GCDump (UINT32 gcInfoVersion, bool encBytes = true, unsigned maxEncBytes = 5, bool dumpCodeOffs = true); #ifdef TARGET_X86 /*------------------------------------------------------------------------- * Dumps the InfoHdr to 'stdout' * table : Start of the GC info block * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES * Return value : Size in bytes of the header encoding */ size_t FASTCALL DumpInfoHdr (PTR_CBYTE gcInfoBlock, InfoHdr * header, /* OUT */ unsigned * methodSize, /* OUT */ bool verifyGCTables = false); #endif /*------------------------------------------------------------------------- * Dumps the GC tables to 'stdout' * gcInfoBlock : Start of the GC info block * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES * Return value : Size in bytes of the GC table encodings */ size_t FASTCALL DumpGCTable (PTR_CBYTE gcInfoBlock, #ifdef TARGET_X86 const InfoHdr& header, #endif unsigned methodSize, bool verifyGCTables = false); /*------------------------------------------------------------------------- * Dumps the location of ptrs for the given code offset * verifyGCTables : If the JIT has been compiled with VERIFY_GC_TABLES */ void FASTCALL DumpPtrsInFrame(PTR_CBYTE gcInfoBlock, PTR_CBYTE codeBlock, unsigned offs, bool verifyGCTables = false); public: typedef void (*printfFtn)(const char* fmt, ...); printfFtn gcPrintf; UINT32 gcInfoVersion; //------------------------------------------------------------------------- protected: bool fDumpEncBytes; unsigned cMaxEncBytes; bool fDumpCodeOffsets; /* Helper methods */ PTR_CBYTE DumpEncoding(PTR_CBYTE gcInfoBlock, size_t cDumpBytes); void DumpOffset (unsigned o); void DumpOffsetEx(unsigned o); }; /*****************************************************************************/ #endif // __GC_DUMP_H__ /*****************************************************************************/ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcinfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // ****************************************************************************** // WARNING!!!: These values are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfo.h // ****************************************************************************** /*****************************************************************************/ #ifndef _GCINFO_H_ #define _GCINFO_H_ /*****************************************************************************/ #include "daccess.h" #include "windef.h" // For BYTE // Some declarations in this file are used on non-x86 platforms, but most are x86-specific. // Use the lower 2 bits of the offsets stored in the tables // to encode properties const unsigned OFFSET_MASK = 0x3; // mask to access the low 2 bits // // Note for untracked locals the flags allowed are "pinned" and "byref" // and for tracked locals the flags allowed are "this" and "byref" // Note that these definitions should also match the definitions of // GC_CALL_INTERIOR and GC_CALL_PINNED in VM/gc.h // const unsigned byref_OFFSET_FLAG = 0x1; // the offset is an interior ptr const unsigned pinned_OFFSET_FLAG = 0x2; // the offset is a pinned ptr #if !defined(TARGET_X86) || !defined(FEATURE_EH_FUNCLETS) const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" #endif //----------------------------------------------------------------------------- // The current GCInfo Version //----------------------------------------------------------------------------- #define GCINFO_VERSION 2 //----------------------------------------------------------------------------- // GCInfoToken: A wrapper that contains the GcInfo data and version number. // // The version# is not stored in the GcInfo structure -- because it is // wasteful to store the version once for every method. // Instead, the version# istracked per range-section of generated/loaded methods. // // The GCInfo version is computed as : // 1) The current GCINFO_VERSION for JITted and Ngened images // 2) A function of the Ready - to - run major version stored in READYTORUN_HEADER // for ready - to - run images.ReadyToRunJitManager::JitTokenToGCInfoVersion() // provides the GcInfo version for any Method. //----------------------------------------------------------------------------- struct GCInfoToken { PTR_VOID Info; UINT32 Version; static UINT32 ReadyToRunVersionToGcInfoVersion(UINT32 readyToRunMajorVersion) { // GcInfo version is current from ReadyToRun version 2.0 return GCINFO_VERSION; } }; /*****************************************************************************/ #endif //_GCINFO_H_ /*****************************************************************************/ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcinfoarraylist.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _GCINFOARRAYLIST_H_ #define _GCINFOARRAYLIST_H_ // GCInfoArrayList is basically a more efficient linked list--it's useful for accumulating // lots of small fixed-size allocations into larger chunks which in a typical linked list // would incur an unnecessarily high amount of overhead. class GcInfoArrayListBase { private: static const size_t GrowthFactor = 2; protected: friend class IteratorBase; struct ChunkBase { ChunkBase* m_next; // actually GcInfoArrayListChunk* }; class IteratorBase { protected: IteratorBase(GcInfoArrayListBase* list, size_t firstChunkCapacity); ChunkBase* GetNextChunk(size_t& elementCount); private: GcInfoArrayListBase* m_list; ChunkBase* m_currentChunk; size_t m_currentChunkCount; }; GcInfoArrayListBase(IAllocator* allocator); virtual ~GcInfoArrayListBase(); void AppendNewChunk(size_t firstChunkCapacity, size_t elementSize, size_t chunkAlignment); public: size_t Count() { return m_itemCount; } protected: IAllocator* m_allocator; ChunkBase* m_firstChunk; // actually GcInfoArrayListChunk* ChunkBase* m_lastChunk; // actually GcInfoArrayListChunk* size_t m_lastChunkCount; size_t m_lastChunkCapacity; size_t m_itemCount; }; template class GcInfoArrayList : public GcInfoArrayListBase { private: struct Chunk : public ChunkBase { ElementType m_items[]; }; public: friend class Iterator; struct Iterator : IteratorBase { Iterator(GcInfoArrayList* list) : IteratorBase(list, FirstChunkCapacity) { } ElementType* GetNext(size_t* elementCount) { Chunk* chunk = reinterpret_cast(GetNextChunk(*elementCount)); return chunk == nullptr ? nullptr : &chunk->m_items[0]; } }; GcInfoArrayList(IAllocator* allocator) : GcInfoArrayListBase(allocator) { } ElementType* Append() { if (m_lastChunk == nullptr || m_lastChunkCount == m_lastChunkCapacity) { AppendNewChunk(FirstChunkCapacity, sizeof(ElementType), __alignof(ElementType)); } m_itemCount++; m_lastChunkCount++; return &reinterpret_cast(m_lastChunk)->m_items[m_lastChunkCount - 1]; } void CopyTo(ElementType* dest) { Iterator iter(this); ElementType* source; size_t elementCount; while (source = iter.GetNext(&elementCount), source != nullptr) { memcpy(dest, source, elementCount * sizeof(ElementType)); dest += elementCount; } } }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcinfodecoder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************** * * GC Information Decoding API * *****************************************************************/ // ****************************************************************************** // WARNING!!!: These values are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfodecoder.h // ****************************************************************************** #ifndef _GC_INFO_DECODER_ #define _GC_INFO_DECODER_ #define _max(a, b) (((a) > (b)) ? (a) : (b)) #define _min(a, b) (((a) < (b)) ? (a) : (b)) #if !defined(TARGET_X86) #define USE_GC_INFO_DECODER #endif #if !defined(GCINFODECODER_NO_EE) #include "eetwain.h" #else #ifdef FEATURE_NATIVEAOT typedef ArrayDPTR(const uint8_t) PTR_CBYTE; #define LIMITED_METHOD_CONTRACT #define SUPPORTS_DAC #define LOG(x) #define LOG_PIPTR(pObjRef, gcFlags, hCallBack) #define DAC_ARG(x) #define VALIDATE_ROOT(isInterior, hCallBack, pObjRef) #define UINT32 uint32_t #define INT32 int32_t #define UINT16 uint16_t #define UINT uint32_t #define SIZE_T uintptr_t #define SSIZE_T intptr_t #define LPVOID void* typedef void * OBJECTREF; #define GET_CALLER_SP(pREGDISPLAY) ((TADDR)0) struct GCInfoToken { PTR_VOID Info; UINT32 Version; GCInfoToken(PTR_VOID info) { Info = info; Version = 2; } }; #else // FEATURE_NATIVEAOT // Stuff from cgencpu.h: #ifndef __cgencpu_h__ inline void SetIP(T_CONTEXT* context, PCODE rip) { _ASSERTE(!"don't call this"); } inline TADDR GetSP(T_CONTEXT* context) { #ifdef TARGET_AMD64 return (TADDR)context->Rsp; #elif defined(TARGET_ARM) return (TADDR)context->Sp; #elif defined(TARGET_ARM64) return (TADDR)context->Sp; #elif defined(TARGET_LOONGARCH64) return (TADDR)context->Sp; #else _ASSERTE(!"nyi for platform"); #endif } inline PCODE GetIP(T_CONTEXT* context) { #ifdef TARGET_AMD64 return (PCODE) context->Rip; #elif defined(TARGET_ARM) return (PCODE)context->Pc; #elif defined(TARGET_ARM64) return (PCODE)context->Pc; #elif defined(TARGET_LOONGARCH64) return (PCODE)context->Pc; #else _ASSERTE(!"nyi for platform"); #endif } #endif // !__cgencpu_h__ // Misc. VM types: #ifndef DEFINE_OBJECTREF #define DEFINE_OBJECTREF class Object; typedef Object *OBJECTREF; #endif typedef SIZE_T TADDR; // Stuff from gc.h: #ifndef __GC_H #define GC_CALL_INTERIOR 0x1 #define GC_CALL_PINNED 0x2 #endif // !__GC_H // Stuff from stdmacros.h (can't include because it includes contract.h, which uses #pragma once) #ifndef _stdmacros_h_ inline BOOL IS_ALIGNED( size_t val, size_t alignment ) { // alignment must be a power of 2 for this implementation to work (need modulo otherwise) _ASSERTE( 0 == (alignment & (alignment - 1)) ); return 0 == (val & (alignment - 1)); } inline BOOL IS_ALIGNED( void* val, size_t alignment ) { return IS_ALIGNED( (size_t) val, alignment ); } #define FMT_REG "r%d " #define FMT_STK "sp%s0x%02x " #define DBG_STK(off) \ (off >= 0) ? "+" : "-", \ (off >= 0) ? off : -off #endif // Stuff from eetwain.h: #ifndef _EETWAIN_H typedef void (*GCEnumCallback)( void * hCallback, // callback data OBJECTREF* pObject, // address of object-reference we are reporting uint32_t flags // is this a pinned and/or interior pointer ); #endif // !_EETWAIN_H #include "regdisp.h" #endif // FEATURE_NATIVEAOT #ifndef _strike_h enum ICodeManagerFlags { ActiveStackFrame = 0x0001, // this is the currently active function ExecutionAborted = 0x0002, // execution of this function has been aborted // (i.e. it will not continue execution at the // current location) ParentOfFuncletStackFrame = 0x0040, // A funclet for this frame was previously reported NoReportUntracked = 0x0080, // EnumGCRefs/EnumerateLiveSlots should *not* include // any untracked slots }; #endif // !_strike_h #endif // GCINFODECODER_NO_EE #include "gcinfotypes.h" #ifdef _DEBUG #define MAX_PREDECODED_SLOTS 4 #else #define MAX_PREDECODED_SLOTS 64 #endif enum GcInfoDecoderFlags { DECODE_EVERYTHING = 0x0, DECODE_SECURITY_OBJECT = 0x01, // stack location of security object DECODE_CODE_LENGTH = 0x02, DECODE_VARARG = 0x04, DECODE_INTERRUPTIBILITY = 0x08, DECODE_GC_LIFETIMES = 0x10, DECODE_NO_VALIDATION = 0x20, DECODE_PSP_SYM = 0x40, DECODE_GENERICS_INST_CONTEXT = 0x80, // stack location of instantiation context for generics // (this may be either the 'this' ptr or the instantiation secret param) DECODE_GS_COOKIE = 0x100, // stack location of the GS cookie DECODE_FOR_RANGES_CALLBACK = 0x200, DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context) DECODE_EDIT_AND_CONTINUE = 0x800, DECODE_REVERSE_PINVOKE_VAR = 0x1000, DECODE_RETURN_KIND = 0x2000, #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) DECODE_HAS_TAILCALLS = 0x4000, #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 }; enum GcInfoHeaderFlags { GC_INFO_IS_VARARG = 0x1, // unused = 0x2, // was GC_INFO_HAS_SECURITY_OBJECT GC_INFO_HAS_GS_COOKIE = 0x4, GC_INFO_HAS_PSP_SYM = 0x8, GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK = 0x30, GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE = 0x00, GC_INFO_HAS_GENERICS_INST_CONTEXT_MT = 0x10, GC_INFO_HAS_GENERICS_INST_CONTEXT_MD = 0x20, GC_INFO_HAS_GENERICS_INST_CONTEXT_THIS = 0x30, GC_INFO_HAS_STACK_BASE_REGISTER = 0x40, #ifdef TARGET_AMD64 GC_INFO_WANTS_REPORT_ONLY_LEAF = 0x80, #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) GC_INFO_HAS_TAILCALLS = 0x80, #endif // TARGET_AMD64 GC_INFO_HAS_EDIT_AND_CONTINUE_INFO = 0x100, GC_INFO_REVERSE_PINVOKE_FRAME = 0x200, GC_INFO_FLAGS_BIT_SIZE_VERSION_1 = 9, GC_INFO_FLAGS_BIT_SIZE = 10, }; class BitStreamReader { public: BitStreamReader() { SUPPORTS_DAC; } BitStreamReader( PTR_CBYTE pBuffer ) { SUPPORTS_DAC; _ASSERTE( pBuffer != NULL ); m_pCurrent = m_pBuffer = dac_cast((size_t)dac_cast(pBuffer) & ~((size_t)sizeof(size_t)-1)); m_RelPos = m_InitialRelPos = (int)((size_t)dac_cast(pBuffer) % sizeof(size_t)) * 8/*BITS_PER_BYTE*/; } BitStreamReader(const BitStreamReader& other) { SUPPORTS_DAC; m_pBuffer = other.m_pBuffer; m_InitialRelPos = other.m_InitialRelPos; m_pCurrent = other.m_pCurrent; m_RelPos = other.m_RelPos; } const BitStreamReader& operator=(const BitStreamReader& other) { SUPPORTS_DAC; m_pBuffer = other.m_pBuffer; m_InitialRelPos = other.m_InitialRelPos; m_pCurrent = other.m_pCurrent; m_RelPos = other.m_RelPos; return *this; } // NOTE: This routine is perf-critical __forceinline size_t Read( int numBits ) { SUPPORTS_DAC; _ASSERTE(numBits > 0 && numBits <= BITS_PER_SIZE_T); size_t result = (*m_pCurrent) >> m_RelPos; int newRelPos = m_RelPos + numBits; if(newRelPos >= BITS_PER_SIZE_T) { m_pCurrent++; newRelPos -= BITS_PER_SIZE_T; if(newRelPos > 0) { size_t extraBits = (*m_pCurrent) << (numBits - newRelPos); result ^= extraBits; } } m_RelPos = newRelPos; result &= SAFE_SHIFT_LEFT(1, numBits) - 1; return result; } // This version reads one bit, returning zero/non-zero (not 0/1) // NOTE: This routine is perf-critical __forceinline size_t ReadOneFast() { SUPPORTS_DAC; size_t result = (*m_pCurrent) & (((size_t)1) << m_RelPos); if(++m_RelPos == BITS_PER_SIZE_T) { m_pCurrent++; m_RelPos = 0; } return result; } __forceinline size_t GetCurrentPos() { SUPPORTS_DAC; return (size_t) ((m_pCurrent - m_pBuffer) * BITS_PER_SIZE_T + m_RelPos - m_InitialRelPos); } __forceinline void SetCurrentPos( size_t pos ) { size_t adjPos = pos + m_InitialRelPos; m_pCurrent = m_pBuffer + adjPos / BITS_PER_SIZE_T; m_RelPos = (int)(adjPos % BITS_PER_SIZE_T); _ASSERTE(GetCurrentPos() == pos); } __forceinline void Skip( SSIZE_T numBitsToSkip ) { SUPPORTS_DAC; SetCurrentPos(GetCurrentPos() + numBitsToSkip); } __forceinline void AlignUpToByte() { if(m_RelPos <= BITS_PER_SIZE_T - 8) { m_RelPos = (m_RelPos + 7) & ~7; } else { m_RelPos = 0; m_pCurrent++; } } __forceinline size_t ReadBitAtPos( size_t pos ) { size_t adjPos = pos + m_InitialRelPos; size_t* ptr = m_pBuffer + adjPos / BITS_PER_SIZE_T; int relPos = (int)(adjPos % BITS_PER_SIZE_T); return (*ptr) & (((size_t)1) << relPos); } //-------------------------------------------------------------------------- // Decode variable length numbers // See the corresponding methods on BitStreamWriter for more information on the format //-------------------------------------------------------------------------- inline size_t DecodeVarLengthUnsigned( int base ) { _ASSERTE((base > 0) && (base < (int)BITS_PER_SIZE_T)); size_t numEncodings = size_t{ 1 } << base; size_t result = 0; for(int shift=0; ; shift+=base) { _ASSERTE(shift+base <= (int)BITS_PER_SIZE_T); size_t currentChunk = Read(base+1); result |= (currentChunk & (numEncodings-1)) << shift; if(!(currentChunk & numEncodings)) { // Extension bit is not set, we're done. return result; } } } inline SSIZE_T DecodeVarLengthSigned( int base ) { _ASSERTE((base > 0) && (base < (int)BITS_PER_SIZE_T)); size_t numEncodings = size_t{ 1 } << base; SSIZE_T result = 0; for(int shift=0; ; shift+=base) { _ASSERTE(shift+base <= (int)BITS_PER_SIZE_T); size_t currentChunk = Read(base+1); result |= (currentChunk & (numEncodings-1)) << shift; if(!(currentChunk & numEncodings)) { // Extension bit is not set, sign-extend and we're done. int sbits = BITS_PER_SIZE_T - (shift+base); result <<= sbits; result >>= sbits; // This provides the sign extension return result; } } } private: PTR_size_t m_pBuffer; int m_InitialRelPos; PTR_size_t m_pCurrent; int m_RelPos; }; struct GcSlotDesc { union { UINT32 RegisterNumber; GcStackSlot Stack; } Slot; GcSlotFlags Flags; }; class GcSlotDecoder { public: GcSlotDecoder() {} void DecodeSlotTable(BitStreamReader& reader); UINT32 GetNumSlots() { return m_NumSlots; } UINT32 GetNumUntracked() { return m_NumUntracked; } UINT32 GetNumTracked() { return m_NumSlots - m_NumUntracked; } UINT32 GetNumRegisters() { return m_NumRegisters; } const GcSlotDesc* GetSlotDesc(UINT32 slotIndex); private: GcSlotDesc m_SlotArray[MAX_PREDECODED_SLOTS]; BitStreamReader m_SlotReader; UINT32 m_NumSlots; UINT32 m_NumRegisters; UINT32 m_NumUntracked; UINT32 m_NumDecodedSlots; GcSlotDesc* m_pLastSlot; }; #ifdef USE_GC_INFO_DECODER class GcInfoDecoder { public: // If you are not interested in interruptibility or gc lifetime information, pass 0 as instructionOffset GcInfoDecoder( GCInfoToken gcInfoToken, GcInfoDecoderFlags flags = DECODE_EVERYTHING, UINT32 instructionOffset = 0 ); //------------------------------------------------------------------------ // Interruptibility //------------------------------------------------------------------------ bool IsInterruptible(); #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED // This is used for gccoverage bool IsSafePoint(UINT32 codeOffset); typedef void EnumerateSafePointsCallback (UINT32 offset, void * hCallback); void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback); #endif // Returns true to stop enumerating. typedef bool EnumerateInterruptibleRangesCallback (UINT32 startOffset, UINT32 stopOffset, void * hCallback); void EnumerateInterruptibleRanges ( EnumerateInterruptibleRangesCallback *pCallback, void * hCallback); //------------------------------------------------------------------------ // GC lifetime information //------------------------------------------------------------------------ bool EnumerateLiveSlots( PREGDISPLAY pRD, bool reportScratchSlots, unsigned flags, GCEnumCallback pCallBack, void * hCallBack ); // Public for the gc info dumper void EnumerateUntrackedSlots( PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, void * hCallBack ); //------------------------------------------------------------------------ // Miscellaneous method information //------------------------------------------------------------------------ INT32 GetGSCookieStackSlot(); UINT32 GetGSCookieValidRangeStart(); UINT32 GetGSCookieValidRangeEnd(); UINT32 GetPrologSize(); INT32 GetPSPSymStackSlot(); INT32 GetGenericsInstContextStackSlot(); INT32 GetReversePInvokeFrameStackSlot(); bool HasMethodDescGenericsInstContext(); bool HasMethodTableGenericsInstContext(); bool GetIsVarArg(); bool WantsReportOnlyLeaf(); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) bool HasTailCalls(); #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 ReturnKind GetReturnKind(); UINT32 GetCodeLength(); UINT32 GetStackBaseRegister(); UINT32 GetSizeOfEditAndContinuePreservedArea(); #ifdef TARGET_ARM64 UINT32 GetSizeOfEditAndContinueFixedStackFrame(); #endif size_t GetNumBytesRead(); #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA UINT32 GetSizeOfStackParameterArea(); #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA private: BitStreamReader m_Reader; UINT32 m_InstructionOffset; // Pre-decoded information bool m_IsInterruptible; bool m_IsVarArg; bool m_GenericSecretParamIsMD; bool m_GenericSecretParamIsMT; #ifdef TARGET_AMD64 bool m_WantsReportOnlyLeaf; #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) bool m_HasTailCalls; #endif // TARGET_AMD64 INT32 m_GSCookieStackSlot; INT32 m_ReversePInvokeFrameStackSlot; UINT32 m_ValidRangeStart; UINT32 m_ValidRangeEnd; INT32 m_PSPSymStackSlot; INT32 m_GenericsInstContextStackSlot; UINT32 m_CodeLength; UINT32 m_StackBaseRegister; UINT32 m_SizeOfEditAndContinuePreservedArea; #ifdef TARGET_ARM64 UINT32 m_SizeOfEditAndContinueFixedStackFrame; #endif ReturnKind m_ReturnKind; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32 m_NumSafePoints; UINT32 m_SafePointIndex; UINT32 FindSafePoint(UINT32 codeOffset); #endif UINT32 m_NumInterruptibleRanges; #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA UINT32 m_SizeOfStackOutgoingAndScratchArea; #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA #ifdef _DEBUG GcInfoDecoderFlags m_Flags; PTR_CBYTE m_GcInfoAddress; #endif UINT32 m_Version; static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback); OBJECTREF* GetRegisterSlot( int regNum, PREGDISPLAY pRD ); #ifdef TARGET_UNIX OBJECTREF* GetCapturedRegister( int regNum, PREGDISPLAY pRD ); #endif // TARGET_UNIX OBJECTREF* GetStackSlot( INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD ); #ifdef DACCESS_COMPILE int GetStackReg(int spBase); #endif // DACCESS_COMPILE bool IsScratchRegister(int regNum, PREGDISPLAY pRD); bool IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD); void ReportUntrackedSlots( GcSlotDecoder& slotDecoder, PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, void * hCallBack ); void ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, void * hCallBack ); void ReportStackSlotToGC( INT32 spOffset, GcStackSlotBase spBase, unsigned gcFlags, PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, void * hCallBack ); inline void ReportSlotToGC( GcSlotDecoder& slotDecoder, UINT32 slotIndex, PREGDISPLAY pRD, bool reportScratchSlots, unsigned inputFlags, GCEnumCallback pCallBack, void * hCallBack ) { _ASSERTE(slotIndex < slotDecoder.GetNumSlots()); const GcSlotDesc* pSlot = slotDecoder.GetSlotDesc(slotIndex); if(slotIndex < slotDecoder.GetNumRegisters()) { UINT32 regNum = pSlot->Slot.RegisterNumber; if( reportScratchSlots || !IsScratchRegister( regNum, pRD ) ) { ReportRegisterToGC( regNum, pSlot->Flags, pRD, inputFlags, pCallBack, hCallBack ); } else { LOG((LF_GCROOTS, LL_INFO1000, "\"Live\" scratch register " FMT_REG " not reported\n", regNum)); } } else { INT32 spOffset = pSlot->Slot.Stack.SpOffset; GcStackSlotBase spBase = pSlot->Slot.Stack.Base; if( reportScratchSlots || !IsScratchStackSlot(spOffset, spBase, pRD) ) { ReportStackSlotToGC( spOffset, spBase, pSlot->Flags, pRD, inputFlags, pCallBack, hCallBack ); } else { LOG((LF_GCROOTS, LL_INFO1000, "\"Live\" scratch stack slot " FMT_STK " not reported\n", DBG_STK(spOffset))); } } } }; #endif // USE_GC_INFO_DECODER #endif // _GC_INFO_DECODER_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcinfodumper.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __GCINFODUMPER_H__ #define __GCINFODUMPER_H__ #include "gcinfotypes.h" #include "gcinfodecoder.h" // ***************************************************************************** // WARNING!!!: These values and code are also used by SOS in the diagnostics // repo. Should updated in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfodumper.h // ***************************************************************************** // // This class dumps the contents of the gc encodings, providing outputs // similar to the inputs to GcInfoEncoder. This uses the same GcInfoDecoder // functions that the EE uses (vs. decoding the bits directly). // class GcInfoDumper { public: GcInfoDumper (GCInfoToken gcInfoToken); ~GcInfoDumper (); // Returns TRUE to stop decoding. typedef BOOL InterruptibleStateChangeProc ( UINT32 CodeOffset, BOOL fInterruptible, PVOID pvData); // Returns TRUE to stop decoding. typedef BOOL OnSafePointProc ( UINT32 CodeOffset, PVOID pvData); // Returns TRUE to stop decoding. typedef BOOL RegisterStateChangeProc ( UINT32 CodeOffset, UINT32 RegisterNumber, GcSlotFlags Flags, GcSlotState NewState, PVOID pvData); // Returns TRUE to stop decoding. typedef BOOL StackSlotStateChangeProc ( UINT32 CodeOffset, GcSlotFlags flags, GcStackSlotBase BaseRegister, SSIZE_T StackOffset, GcSlotState NewState, PVOID pvData); enum EnumerateStateChangesResults { SUCCESS = 0, OUT_OF_MEMORY, REPORTED_REGISTER_IN_CALLERS_FRAME, REPORTED_FRAME_POINTER, REPORTED_INVALID_BASE_REGISTER, REPORTED_INVALID_POINTER, DECODER_FAILED, }; // Returns TRUE if successful. FALSE if out of memory, invalid data, etc. EnumerateStateChangesResults EnumerateStateChanges ( InterruptibleStateChangeProc *pfnInterruptibleStateChange, RegisterStateChangeProc *pfnRegisterStateChange, StackSlotStateChangeProc *pfnStackSlotStateChange, OnSafePointProc *pfnSafePointFunc, PVOID pvData); size_t GetGCInfoSize(); private: struct LivePointerRecord { OBJECTREF *ppObject; DWORD flags; LivePointerRecord *pNext; UINT marked; }; GCInfoToken m_gcTable; UINT32 m_StackBaseRegister; UINT32 m_SizeOfEditAndContinuePreservedArea; LivePointerRecord *m_pRecords; RegisterStateChangeProc *m_pfnRegisterStateChange; StackSlotStateChangeProc *m_pfnStackSlotStateChange; PVOID m_pvCallbackData; EnumerateStateChangesResults m_Error; size_t m_gcInfoSize; static void LivePointerCallback ( LPVOID hCallback, // callback data OBJECTREF* pObject, // address of object-reference we are reporting uint32_t flags // is this a pinned and/or interior pointer DAC_ARG(DacSlotLocation loc)); // the location the pointer came from static void FreePointerRecords (LivePointerRecord *pRecords); // Return TRUE if callback requested to stop decoding. BOOL ReportPointerRecord ( UINT32 CodeOffset, BOOL fLive, REGDISPLAY *pRD, LivePointerRecord *pRecord); // Return TRUE if callback requested to stop decoding. BOOL ReportPointerDifferences ( UINT32 offset, REGDISPLAY *pRD, LivePointerRecord *pPrevState); }; #endif // !__GCINFODUMPER_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcinfoencoder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************** * * GC Information Encoding API * *****************************************************************/ /***************************************************************** ENCODING LAYOUT 1. Header Slim Header for simple and common cases: - EncodingType[Slim] - ReturnKind (Fat: 2 bits) - CodeLength - NumCallSites (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) Fat Header for other cases: - EncodingType[Fat] - Flag: isVarArg, unused (was hasSecurityObject), hasGSCookie, hasPSPSymStackSlot, hasGenericsInstContextStackSlot, hasStackBaseregister, wantsReportOnlyLeaf (AMD64 use only), hasTailCalls (ARM/ARM64 only) hasSizeOfEditAndContinuePreservedArea hasReversePInvokeFrame, - ReturnKind (Fat: 4 bits) - CodeLength - Prolog (if hasGenericsInstContextStackSlot || hasGSCookie) - Epilog (if hasGSCookie) - SecurityObjectStackSlot (if any) - GSCookieStackSlot (if any) - PSPSymStackSlot (if any) - GenericsInstContextStackSlot (if any) - StackBaseRegister (if any) - SizeOfEditAndContinuePreservedArea (if any) - ReversePInvokeFrameSlot (if any) - SizeOfStackOutgoingAndScratchArea (#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA) - NumCallSites (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) - NumInterruptibleRanges 2. Call sites offsets (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) 3. Fully-interruptible ranges 4. Slot table 5. GC state at call sites (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) 6. GC state at try clauses (#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED) 7. Chunk pointers 8. Chunk encodings STANDALONE_BUILD The STANDALONE_BUILD switch can be used to build the GcInfoEncoder library independently by clients outside the CoreClr tree. The GcInfo library uses some custom data-structures (ex: ArrayList, SimplerHashTable) and includes some utility libraries (ex: UtilCode) which pull in several other headers with considerable unrelated content. Rather than porting all the utility code to suite other clients, the STANDALONE_BUILD switch can be used to include only the minimal set of headers specific to GcInfo encodings. Clients of STANDALONE_BUILD will likely use standard library implementations of data-structures like ArrayList, HashMap etc., in place of the custom implementation currently used by GcInfoEncoder. Rather than spew the GcInfoEnoder code with #ifdef STANDALONE_BUILD ... #else .. #endif blocks, we include a special header GcInfoUtil.h in STANDALONE_BUILD mode. GcInfoUtil.h is expected to supply the interface/implementation for the data-structures and utilities used by GcInfoEncoder. This header should be provided by the clients doing the standalone build in their source tree. *****************************************************************/ #ifndef __GCINFOENCODER_H__ #define __GCINFOENCODER_H__ #ifdef STANDALONE_BUILD #include #include #include "GcInfoUtil.h" #include "corjit.h" #else #include #include #include #include "corjit.h" #include "iallocator.h" #include "gcinfoarraylist.h" #include "stdmacros.h" #include "eexcp.h" #endif #include "gcinfotypes.h" // As stated in issue #6008, GcInfoSize should be incorporated into debug builds. #ifdef _DEBUG #define MEASURE_GCINFO #endif #ifdef MEASURE_GCINFO struct GcInfoSize { size_t TotalSize; size_t NumMethods; size_t NumCallSites; size_t NumRanges; size_t NumRegs; size_t NumStack; size_t NumUntracked; size_t NumTransitions; size_t SizeOfCode; size_t EncInfoSize; size_t UntrackedSlotSize; size_t NumUntrackedSize; size_t FlagsSize; size_t RetKindSize; size_t CodeLengthSize; size_t ProEpilogSize; size_t SecObjSize; size_t GsCookieSize; size_t PspSymSize; size_t GenericsCtxSize; size_t StackBaseSize; size_t ReversePInvokeFrameSize; size_t FixedAreaSize; size_t NumCallSitesSize; size_t NumRangesSize; size_t CallSitePosSize; size_t RangeSize; size_t NumRegsSize; size_t NumStackSize; size_t RegSlotSize; size_t StackSlotSize; size_t CallSiteStateSize; size_t EhPosSize; size_t EhStateSize; size_t ChunkPtrSize; size_t ChunkMaskSize; size_t ChunkFinalStateSize; size_t ChunkTransitionSize; GcInfoSize(); GcInfoSize& operator+=(const GcInfoSize& other); void Log(DWORD level, const char * header); }; #endif struct GcSlotDesc { union { UINT32 RegisterNumber; GcStackSlot Stack; } Slot; GcSlotFlags Flags; BOOL IsRegister() const { return (Flags & GC_SLOT_IS_REGISTER); } BOOL IsInterior() const { return (Flags & GC_SLOT_INTERIOR); } BOOL IsPinned() const { return (Flags & GC_SLOT_PINNED); } BOOL IsUntracked() const { return (Flags & GC_SLOT_UNTRACKED); } BOOL IsDeleted() const { return (Flags & GC_SLOT_IS_DELETED); } void MarkDeleted() { Flags = (GcSlotFlags) (Flags | GC_SLOT_IS_DELETED); } }; class BitArray; class BitStreamWriter { public: BitStreamWriter( IAllocator* pAllocator ); // bit 0 is the least significative bit void Write( size_t data, UINT32 count ); inline size_t GetBitCount() { return m_BitCount; } inline size_t GetByteCount() { return ( m_BitCount + 7 ) / 8; } void CopyTo( BYTE* buffer ); void Dispose(); //-------------------------------------------------------- // Compute the number of bits used to encode variable length numbers // Uses base+1 bits at minimum // Bits 0..(base-1) represent the encoded quantity // If it doesn't fit, set bit #base to 1 and use base+1 more bits //-------------------------------------------------------- static int SizeofVarLengthUnsigned( size_t n, UINT32 base ); //-------------------------------------------------------- // Encode variable length numbers // Uses base+1 bits at minimum // Bits 0..(base-1) represent the encoded quantity // If it doesn't fit, set bit #base to 1 and use base+1 more bits //-------------------------------------------------------- int EncodeVarLengthUnsigned( size_t n, UINT32 base ); //-------------------------------------------------------- // Signed quantities are encoded the same as unsigned // The most relevant difference is that a number is considered // to fit in base bits if the topmost bit of a base-long chunk // matches the sign of the whole number //-------------------------------------------------------- int EncodeVarLengthSigned( SSIZE_T n, UINT32 base ); private: class MemoryBlockList; class MemoryBlock { friend class MemoryBlockList; MemoryBlock* m_next; public: size_t Contents[]; inline MemoryBlock* Next() { return m_next; } }; class MemoryBlockList { MemoryBlock* m_head; MemoryBlock* m_tail; public: MemoryBlockList(); inline MemoryBlock* Head() { return m_head; } MemoryBlock* AppendNew(IAllocator* allocator, size_t bytes); void Dispose(IAllocator* allocator); }; IAllocator* m_pAllocator; size_t m_BitCount; UINT32 m_FreeBitsInCurrentSlot; MemoryBlockList m_MemoryBlocks; const static int m_MemoryBlockSize = 128; // must be a multiple of the pointer size size_t* m_pCurrentSlot; // bits are written through this pointer size_t* m_OutOfBlockSlot; // sentinel value to determine when the block is full #ifdef _DEBUG int m_MemoryBlocksCount; #endif private: // Writes bits knowing that they will all fit in the current memory slot inline void WriteInCurrentSlot( size_t data, UINT32 count ) { data &= SAFE_SHIFT_LEFT(1, count) - 1; data <<= (BITS_PER_SIZE_T - m_FreeBitsInCurrentSlot); *m_pCurrentSlot |= data; } inline void AllocMemoryBlock() { _ASSERTE( IS_ALIGNED( m_MemoryBlockSize, sizeof( size_t ) ) ); MemoryBlock* pMemBlock = m_MemoryBlocks.AppendNew(m_pAllocator, m_MemoryBlockSize); m_pCurrentSlot = pMemBlock->Contents; m_OutOfBlockSlot = m_pCurrentSlot + m_MemoryBlockSize / sizeof( size_t ); #ifdef _DEBUG m_MemoryBlocksCount++; #endif } inline void InitCurrentSlot() { m_FreeBitsInCurrentSlot = BITS_PER_SIZE_T; *m_pCurrentSlot = 0; } }; typedef UINT32 GcSlotId; inline UINT32 GetNormCodeOffsetChunk(UINT32 normCodeOffset) { return normCodeOffset / NUM_NORM_CODE_OFFSETS_PER_CHUNK; } inline UINT32 GetCodeOffsetChunk(UINT32 codeOffset) { return (NORMALIZE_CODE_OFFSET(codeOffset)) / NUM_NORM_CODE_OFFSETS_PER_CHUNK; } enum GENERIC_CONTEXTPARAM_TYPE { GENERIC_CONTEXTPARAM_NONE = 0, GENERIC_CONTEXTPARAM_MT = 1, GENERIC_CONTEXTPARAM_MD = 2, GENERIC_CONTEXTPARAM_THIS = 3, }; extern void DECLSPEC_NORETURN ThrowOutOfMemory(); class GcInfoEncoder { public: typedef void (*NoMemoryFunction)(void); GcInfoEncoder( ICorJitInfo* pCorJitInfo, CORINFO_METHOD_INFO* pMethodInfo, IAllocator* pJitAllocator, NoMemoryFunction pNoMem = ::ThrowOutOfMemory ); struct LifetimeTransition { UINT32 CodeOffset; GcSlotId SlotId; BYTE BecomesLive; BYTE IsDeleted; }; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED void DefineCallSites(UINT32* pCallSites, BYTE* pCallSiteSizes, UINT32 numCallSites); #endif //------------------------------------------------------------------------ // Interruptibility //------------------------------------------------------------------------ // An instruction at offset x will be interruptible // if-and-only-if startInstructionOffset <= x < startInstructionOffset+length void DefineInterruptibleRange( UINT32 startInstructionOffset, UINT32 length ); //------------------------------------------------------------------------ // Slot information //------------------------------------------------------------------------ // // If spOffset is relative to the current SP, spOffset must be non-negative. // If spOffset is relative to the SP of the caller (same as SP at the method entry and exit) // Negative offsets describe GC refs in the local and outgoing areas. // Positive offsets describe GC refs in the scratch area // Note that if the dynamic allocation area is resized, the outgoing area will not be valid anymore // Old slots must be declared dead and new ones can be defined. // It's up to the JIT to do the right thing. We don't enforce this. GcSlotId GetRegisterSlotId( UINT32 regNum, GcSlotFlags flags ); GcSlotId GetStackSlotId( INT32 spOffset, GcSlotFlags flags, GcStackSlotBase spBase = GC_CALLER_SP_REL ); // // After a FinalizeSlotIds is called, no more slot definitions can be made. // FinalizeSlotIds must be called once and only once before calling Build() // void FinalizeSlotIds(); //------------------------------------------------------------------------ // Fully-interruptible information //------------------------------------------------------------------------ // // For inputs, pass zero as offset // // Indicates that the GC state of slot "slotId" becomes (and remains, until another transition) // "slotState" after the instruction preceding "instructionOffset" (so it is first in this state when // the IP of a suspended thread is at this instruction offset). void SetSlotState( UINT32 instructionOffset, GcSlotId slotId, GcSlotState slotState ); //------------------------------------------------------------------------ // ReturnKind //------------------------------------------------------------------------ void SetReturnKind(ReturnKind returnKind); //------------------------------------------------------------------------ // Miscellaneous method information //------------------------------------------------------------------------ void SetPrologSize( UINT32 prologSize ); void SetGSCookieStackSlot( INT32 spOffsetGSCookie, UINT32 validRangeStart, UINT32 validRangeEnd ); void SetPSPSymStackSlot( INT32 spOffsetPSPSym ); void SetGenericsInstContextStackSlot( INT32 spOffsetGenericsContext, GENERIC_CONTEXTPARAM_TYPE type); void SetReversePInvokeFrameSlot(INT32 spOffset); void SetIsVarArg(); void SetCodeLength( UINT32 length ); // Optional in the general case. Required if the method uses GC_FRAMEREG_REL stack slots void SetStackBaseRegister( UINT32 registerNumber ); // Number of slots preserved during EnC remap void SetSizeOfEditAndContinuePreservedArea( UINT32 size ); #ifdef TARGET_ARM64 void SetSizeOfEditAndContinueFixedStackFrame( UINT32 size ); #endif #ifdef TARGET_AMD64 // Used to only report a frame once for the leaf function/funclet // instead of once for each live function/funclet on the stack. // Called only by RyuJIT (not JIT64) void SetWantsReportOnlyLeaf(); #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) void SetHasTailCalls(); #endif // TARGET_AMD64 #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA void SetSizeOfStackOutgoingAndScratchArea( UINT32 size ); #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA //------------------------------------------------------------------------ // Encoding //------------------------------------------------------------------------ // // Build() encodes GC information into temporary buffers. // The method description cannot change after Build is called // void Build(); // // Write encoded information to its final destination and frees temporary buffers. // The encoder shouldn't be used anymore after calling this method. // It returns a pointer to the destination buffer, which address is byte-aligned // BYTE* Emit(); private: friend struct CompareLifetimeTransitionsByOffsetThenSlot; friend struct CompareLifetimeTransitionsByChunk; struct InterruptibleRange { UINT32 NormStartOffset; UINT32 NormStopOffset; }; ICorJitInfo* m_pCorJitInfo; CORINFO_METHOD_INFO* m_pMethodInfo; IAllocator* m_pAllocator; NoMemoryFunction m_pNoMem; BitStreamWriter m_Info1; // Used for everything except for chunk encodings BitStreamWriter m_Info2; // Used for chunk encodings GcInfoArrayList m_InterruptibleRanges; GcInfoArrayList m_LifetimeTransitions; bool m_IsVarArg; #if defined(TARGET_AMD64) bool m_WantsReportOnlyLeaf; #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) bool m_HasTailCalls; #endif // TARGET_AMD64 INT32 m_GSCookieStackSlot; UINT32 m_GSCookieValidRangeStart; UINT32 m_GSCookieValidRangeEnd; INT32 m_PSPSymStackSlot; INT32 m_GenericsInstContextStackSlot; GENERIC_CONTEXTPARAM_TYPE m_contextParamType; ReturnKind m_ReturnKind; UINT32 m_CodeLength; UINT32 m_StackBaseRegister; UINT32 m_SizeOfEditAndContinuePreservedArea; #ifdef TARGET_ARM64 UINT32 m_SizeOfEditAndContinueFixedStackFrame; #endif INT32 m_ReversePInvokeFrameSlot; InterruptibleRange* m_pLastInterruptibleRange; #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA UINT32 m_SizeOfStackOutgoingAndScratchArea; #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA void * eeAllocGCInfo (size_t blockSize); private: friend class EncoderCheckState; static const UINT32 m_SlotTableInitialSize = 32; UINT32 m_SlotTableSize; UINT32 m_NumSlots; GcSlotDesc *m_SlotTable; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32* m_pCallSites; BYTE* m_pCallSiteSizes; UINT32 m_NumCallSites; #endif // PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED void GrowSlotTable(); void WriteSlotStateVector(BitStreamWriter &writer, const BitArray& vector); UINT32 SizeofSlotStateVarLengthVector(const BitArray& vector, UINT32 baseSkip, UINT32 baseRun); void SizeofSlotStateVarLengthVector(const BitArray& vector, UINT32 baseSkip, UINT32 baseRun, UINT32 * pSizeofSimple, UINT32 * pSizeofRLE, UINT32 * pSizeofRLENeg); UINT32 WriteSlotStateVarLengthVector(BitStreamWriter &writer, const BitArray& vector, UINT32 baseSkip, UINT32 baseRun); bool IsAlwaysScratch(GcSlotDesc &slot); // Assumes that "*ppTransitions" is has size "numTransitions", is sorted by CodeOffset then by SlotId, // and that "*ppEndTransitions" points one beyond the end of the array. If "*ppTransitions" contains // any dead/live transitions pairs for the same CodeOffset and SlotID, removes those, by allocating a // new array, and copying the non-removed elements into it. If it does this, sets "*ppTransitions" to // point to the new array, "*pNumTransitions" to its shorted length, and "*ppEndTransitions" to // point one beyond the used portion of this array. void EliminateRedundantLiveDeadPairs(LifetimeTransition** ppTransitions, size_t* pNumTransitions, LifetimeTransition** ppEndTransitions); #ifdef _DEBUG bool m_IsSlotTableFrozen; #endif #ifdef MEASURE_GCINFO GcInfoSize m_CurrentMethodSize; #endif }; #endif // !__GCINFOENCODER_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcinfotypes.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __GCINFOTYPES_H__ #define __GCINFOTYPES_H__ #ifndef FEATURE_NATIVEAOT #include "gcinfo.h" #endif // ***************************************************************************** // WARNING!!!: These values and code are also used by SOS in the diagnostics // repo. Should updated in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfotypes.h // ***************************************************************************** #define PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED #define FIXED_STACK_PARAMETER_SCRATCH_AREA #define BITS_PER_SIZE_T ((int)sizeof(size_t)*8) //-------------------------------------------------------------------------------- // It turns out, that ((size_t)x) << y == x, when y is not a literal // and its value is BITS_PER_SIZE_T // I guess the processor only shifts of the right operand modulo BITS_PER_SIZE_T // In many cases, we want the above operation to yield 0, // hence the following macros //-------------------------------------------------------------------------------- __forceinline size_t SAFE_SHIFT_LEFT(size_t x, size_t count) { _ASSERTE(count <= BITS_PER_SIZE_T); return (x << 1) << (count - 1); } __forceinline size_t SAFE_SHIFT_RIGHT(size_t x, size_t count) { _ASSERTE(count <= BITS_PER_SIZE_T); return (x >> 1) >> (count - 1); } inline UINT32 CeilOfLog2(size_t x) { _ASSERTE(x > 0); UINT32 result = (x & (x - 1)) ? 1 : 0; while (x != 1) { result++; x >>= 1; } return result; } enum GcSlotFlags { GC_SLOT_BASE = 0x0, GC_SLOT_INTERIOR = 0x1, GC_SLOT_PINNED = 0x2, GC_SLOT_UNTRACKED = 0x4, // For internal use by the encoder/decoder GC_SLOT_IS_REGISTER = 0x8, GC_SLOT_IS_DELETED = 0x10, }; enum GcStackSlotBase { GC_CALLER_SP_REL = 0x0, GC_SP_REL = 0x1, GC_FRAMEREG_REL = 0x2, GC_SPBASE_FIRST = GC_CALLER_SP_REL, GC_SPBASE_LAST = GC_FRAMEREG_REL, }; #ifdef _DEBUG const char* const GcStackSlotBaseNames[] = { "caller.sp", "sp", "frame", }; #endif enum GcSlotState { GC_SLOT_DEAD = 0x0, GC_SLOT_LIVE = 0x1, }; struct GcStackSlot { INT32 SpOffset; GcStackSlotBase Base; bool operator==(const GcStackSlot& other) { return ((SpOffset == other.SpOffset) && (Base == other.Base)); } bool operator!=(const GcStackSlot& other) { return ((SpOffset != other.SpOffset) || (Base != other.Base)); } }; //-------------------------------------------------------------------------------- // ReturnKind -- encoding return type information in GcInfo // // When a method is stopped at a call - site for GC (ex: via return-address // hijacking) the runtime needs to know whether the value is a GC - value // (gc - pointer or gc - pointers stored in an aggregate). // It needs this information so that mark - phase can preserve the gc-pointers // being returned. // // The Runtime doesn't need the precise return-type of a method. // It only needs to find the GC-pointers in the return value. // The only scenarios currently supported by CoreCLR are: // 1. Object references // 2. ByRef pointers // 3. ARM64/X64 only : Structs returned in two registers // 4. X86 only : Floating point returns to perform the correct save/restore // of the return value around return-hijacking. // // Based on these cases, the legal set of ReturnKind enumerations are specified // for each architecture/encoding. // A value of this enumeration is stored in the GcInfo header. // //-------------------------------------------------------------------------------- // RT_Unset: An intermediate step for staged bringup. // When ReturnKind is RT_Unset, it means that the JIT did not set // the ReturnKind in the GCInfo, and therefore the VM cannot rely on it, // and must use other mechanisms (similar to GcInfo ver 1) to determine // the Return type's GC information. // // RT_Unset is only used in the following situations: // X64: Used by JIT64 until updated to use GcInfo v2 API // ARM: Used by JIT32 until updated to use GcInfo v2 API // // RT_Unset should have a valid encoding, whose bits are actually stored in the image. // For X86, there are no free bits, and there's no RT_Unused enumeration. #if defined(TARGET_X86) // 00 RT_Scalar // 01 RT_Object // 10 RT_ByRef // 11 RT_Float #elif defined(TARGET_ARM) // 00 RT_Scalar // 01 RT_Object // 10 RT_ByRef // 11 RT_Unset #elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Slim Header: // 00 RT_Scalar // 01 RT_Object // 10 RT_ByRef // 11 RT_Unset // Fat Header: // 0000 RT_Scalar // 0001 RT_Object // 0010 RT_ByRef // 0011 RT_Unset // 0100 RT_Scalar_Obj // 1000 RT_Scalar_ByRef // 0101 RT_Obj_Obj // 1001 RT_Obj_ByRef // 0110 RT_ByRef_Obj // 1010 RT_ByRef_ByRef #else #ifdef PORTABILITY_WARNING PORTABILITY_WARNING("Need ReturnKind for new Platform") #endif // PORTABILITY_WARNING #endif // Target checks enum ReturnKind { // Cases for Return in one register RT_Scalar = 0, RT_Object = 1, RT_ByRef = 2, #ifdef TARGET_X86 RT_Float = 3, // Encoding 3 means RT_Float on X86 #else RT_Unset = 3, // RT_Unset on other platforms #endif // TARGET_X86 // Cases for Struct Return in two registers // // We have the following equivalencies, because the VM's behavior is the same // for both cases: // RT_Scalar_Scalar == RT_Scalar // RT_Obj_Scalar == RT_Object // RT_ByRef_Scalar == RT_Byref // The encoding for these equivalencies will play out well because // RT_Scalar is zero. // // Naming: RT_firstReg_secondReg // Encoding: // // This encoding with exclusive bits for each register is chosen for ease of use, // and because it doesn't cost any more bits. // It can be changed (ex: to a linear sequence) if necessary. // For example, we can encode the GC-information for the two registers in 3 bits (instead of 4) // if we approximate RT_Obj_ByRef and RT_ByRef_Obj as RT_ByRef_ByRef. // RT_Scalar_Scalar = RT_Scalar RT_Scalar_Obj = RT_Object << 2 | RT_Scalar, RT_Scalar_ByRef = RT_ByRef << 2 | RT_Scalar, // RT_Obj_Scalar = RT_Object RT_Obj_Obj = RT_Object << 2 | RT_Object, RT_Obj_ByRef = RT_ByRef << 2 | RT_Object, // RT_ByRef_Scalar = RT_Byref RT_ByRef_Obj = RT_Object << 2 | RT_ByRef, RT_ByRef_ByRef = RT_ByRef << 2 | RT_ByRef, // Illegal or uninitialized value, // Not a valid encoding, never written to image. RT_Illegal = 0xFF }; // Identify ReturnKinds containing useful information inline bool IsValidReturnKind(ReturnKind returnKind) { return (returnKind != RT_Illegal) #ifndef TARGET_X86 && (returnKind != RT_Unset) #endif // TARGET_X86 ; } // Identify ReturnKinds that can be a part of a multi-reg struct return inline bool IsValidFieldReturnKind(ReturnKind returnKind) { return (returnKind == RT_Scalar || returnKind == RT_Object || returnKind == RT_ByRef); } inline bool IsPointerFieldReturnKind(ReturnKind returnKind) { _ASSERTE(IsValidFieldReturnKind(returnKind)); return (returnKind == RT_Object || returnKind == RT_ByRef); } inline bool IsValidReturnRegister(size_t regNo) { return (regNo == 0) #ifdef FEATURE_MULTIREG_RETURN || (regNo == 1) #endif // FEATURE_MULTIREG_RETURN ; } inline bool IsStructReturnKind(ReturnKind returnKind) { // Two bits encode integer/ref/float return-kinds. // Encodings needing more than two bits are (non-scalar) struct-returns. return returnKind > 3; } inline bool IsScalarReturnKind(ReturnKind returnKind) { return (returnKind == RT_Scalar) #ifdef TARGET_X86 || (returnKind == RT_Float) #endif // TARGET_X86 ; } inline bool IsPointerReturnKind(ReturnKind returnKind) { return IsValidReturnKind(returnKind) && !IsScalarReturnKind(returnKind); } // Helpers for combining/extracting individual ReturnKinds from/to Struct ReturnKinds. // Encoding is two bits per register inline ReturnKind GetStructReturnKind(ReturnKind reg0, ReturnKind reg1) { _ASSERTE(IsValidFieldReturnKind(reg0) && IsValidFieldReturnKind(reg1)); ReturnKind structReturnKind = (ReturnKind)(reg1 << 2 | reg0); _ASSERTE(IsValidReturnKind(structReturnKind)); return structReturnKind; } // Extract returnKind for the specified return register. // Also determines if higher ordinal return registers contain object references inline ReturnKind ExtractRegReturnKind(ReturnKind returnKind, size_t returnRegOrdinal, bool& moreRegs) { _ASSERTE(IsValidReturnKind(returnKind)); _ASSERTE(IsValidReturnRegister(returnRegOrdinal)); // Return kind of each return register is encoded in two bits at returnRegOrdinal*2 position from LSB ReturnKind regReturnKind = (ReturnKind)((returnKind >> (returnRegOrdinal * 2)) & 3); // Check if any other higher ordinal return registers have object references. // ReturnKind of higher ordinal return registers are encoded at (returnRegOrdinal+1)*2) position from LSB // If all of the remaining bits are 0 then there isn't any more RT_Object or RT_ByRef encoded in returnKind. moreRegs = (returnKind >> ((returnRegOrdinal+1) * 2)) != 0; _ASSERTE(IsValidReturnKind(regReturnKind)); _ASSERTE((returnRegOrdinal == 0) || IsValidFieldReturnKind(regReturnKind)); return regReturnKind; } inline const char *ReturnKindToString(ReturnKind returnKind) { switch (returnKind) { case RT_Scalar: return "Scalar"; case RT_Object: return "Object"; case RT_ByRef: return "ByRef"; #ifdef TARGET_X86 case RT_Float: return "Float"; #else case RT_Unset: return "UNSET"; #endif // TARGET_X86 case RT_Scalar_Obj: return "{Scalar, Object}"; case RT_Scalar_ByRef: return "{Scalar, ByRef}"; case RT_Obj_Obj: return "{Object, Object}"; case RT_Obj_ByRef: return "{Object, ByRef}"; case RT_ByRef_Obj: return "{ByRef, Object}"; case RT_ByRef_ByRef: return "{ByRef, ByRef}"; case RT_Illegal: return ""; default: return "!Impossible!"; } } #ifdef TARGET_X86 #include // For memcmp() #include "bitvector.h" // for ptrArgTP #ifndef FASTCALL #define FASTCALL __fastcall #endif // we use offsetof to get the offset of a field #include // offsetof enum infoHdrAdjustConstants { // Constants SET_FRAMESIZE_MAX = 7, SET_ARGCOUNT_MAX = 8, // Change to 6 SET_PROLOGSIZE_MAX = 16, SET_EPILOGSIZE_MAX = 10, // Change to 6 SET_EPILOGCNT_MAX = 4, SET_UNTRACKED_MAX = 3, SET_RET_KIND_MAX = 4, // 2 bits for ReturnKind ADJ_ENCODING_MAX = 0x7f, // Maximum valid encoding in a byte // Also used to mask off next bit from each encoding byte. MORE_BYTES_TO_FOLLOW = 0x80 // If the High-bit of a header or adjustment byte // is set, then there are more adjustments to follow. }; // // Enum to define codes that are used to incrementally adjust the InfoHdr structure. // First set of opcodes enum infoHdrAdjust { SET_FRAMESIZE = 0, // 0x00 SET_ARGCOUNT = SET_FRAMESIZE + SET_FRAMESIZE_MAX + 1, // 0x08 SET_PROLOGSIZE = SET_ARGCOUNT + SET_ARGCOUNT_MAX + 1, // 0x11 SET_EPILOGSIZE = SET_PROLOGSIZE + SET_PROLOGSIZE_MAX + 1, // 0x22 SET_EPILOGCNT = SET_EPILOGSIZE + SET_EPILOGSIZE_MAX + 1, // 0x2d SET_UNTRACKED = SET_EPILOGCNT + (SET_EPILOGCNT_MAX + 1) * 2, // 0x37 FIRST_FLIP = SET_UNTRACKED + SET_UNTRACKED_MAX + 1, FLIP_EDI_SAVED = FIRST_FLIP, // 0x3b FLIP_ESI_SAVED, // 0x3c FLIP_EBX_SAVED, // 0x3d FLIP_EBP_SAVED, // 0x3e FLIP_EBP_FRAME, // 0x3f FLIP_INTERRUPTIBLE, // 0x40 FLIP_DOUBLE_ALIGN, // 0x41 FLIP_SECURITY, // 0x42 FLIP_HANDLERS, // 0x43 FLIP_LOCALLOC, // 0x44 FLIP_EDITnCONTINUE, // 0x45 FLIP_VAR_PTR_TABLE_SZ, // 0x46 Flip whether a table-size exits after the header encoding FFFF_UNTRACKED_CNT, // 0x47 There is a count (>SET_UNTRACKED_MAX) after the header encoding FLIP_VARARGS, // 0x48 FLIP_PROF_CALLBACKS, // 0x49 FLIP_HAS_GS_COOKIE, // 0x4A - The offset of the GuardStack cookie follows after the header encoding FLIP_SYNC, // 0x4B FLIP_HAS_GENERICS_CONTEXT,// 0x4C FLIP_GENERICS_CONTEXT_IS_METHODDESC,// 0x4D FLIP_REV_PINVOKE_FRAME, // 0x4E NEXT_OPCODE, // 0x4F -- see next Adjustment enumeration NEXT_FOUR_START = 0x50, NEXT_FOUR_FRAMESIZE = 0x50, NEXT_FOUR_ARGCOUNT = 0x60, NEXT_THREE_PROLOGSIZE = 0x70, NEXT_THREE_EPILOGSIZE = 0x78 }; // Second set of opcodes, when first code is 0x4F enum infoHdrAdjust2 { SET_RETURNKIND = 0, // 0x00-SET_RET_KIND_MAX Set ReturnKind to value }; #define HAS_UNTRACKED ((unsigned int) -1) #define HAS_VARPTR ((unsigned int) -1) // 0 is a valid offset for the Reverse P/Invoke block // So use -1 as the sentinel for invalid and -2 as the sentinel for present. #define INVALID_REV_PINVOKE_OFFSET ((unsigned int) -1) #define HAS_REV_PINVOKE_FRAME_OFFSET ((unsigned int) -2) // 0 is not a valid offset for EBP-frames as all locals are at a negative offset // For ESP frames, the cookie is above (at a higher address than) the buffers, // and so cannot be at offset 0. #define INVALID_GS_COOKIE_OFFSET 0 // Temporary value to indicate that the offset needs to be read after the header #define HAS_GS_COOKIE_OFFSET ((unsigned int) -1) // 0 is not a valid sync offset #define INVALID_SYNC_OFFSET 0 // Temporary value to indicate that the offset needs to be read after the header #define HAS_SYNC_OFFSET ((unsigned int) -1) #define INVALID_ARGTAB_OFFSET 0 #include // Working set optimization: saving 12 * 128 = 1536 bytes in infoHdrShortcut struct InfoHdr; struct InfoHdrSmall { unsigned char prologSize; // 0 unsigned char epilogSize; // 1 unsigned char epilogCount : 3; // 2 [0:2] unsigned char epilogAtEnd : 1; // 2 [3] unsigned char ediSaved : 1; // 2 [4] which callee-saved regs are pushed onto stack unsigned char esiSaved : 1; // 2 [5] unsigned char ebxSaved : 1; // 2 [6] unsigned char ebpSaved : 1; // 2 [7] unsigned char ebpFrame : 1; // 3 [0] locals accessed relative to ebp unsigned char interruptible : 1; // 3 [1] is intr. at all points (except prolog/epilog), not just call-sites unsigned char doubleAlign : 1; // 3 [2] uses double-aligned stack (ebpFrame will be false) unsigned char security : 1; // 3 [3] has slot for security object unsigned char handlers : 1; // 3 [4] has callable handlers unsigned char localloc : 1; // 3 [5] uses localloc unsigned char editNcontinue : 1; // 3 [6] was JITed in EnC mode unsigned char varargs : 1; // 3 [7] function uses varargs calling convention unsigned char profCallbacks : 1; // 4 [0] unsigned char genericsContext : 1;//4 [1] function reports a generics context parameter is present unsigned char genericsContextIsMethodDesc : 1;//4[2] unsigned char returnKind : 2; // 4 [4] Available GcInfo v2 onwards, previously undefined unsigned short argCount; // 5,6 in bytes unsigned int frameSize; // 7,8,9,10 in bytes unsigned int untrackedCnt; // 11,12,13,14 unsigned int varPtrTableSize; // 15.16,17,18 // Checks whether "this" is compatible with "target". // It is not an exact bit match as "this" could have some // marker/place-holder values, which will have to be written out // after the header. bool isHeaderMatch(const InfoHdr& target) const; }; struct InfoHdr : public InfoHdrSmall { // 0 (zero) means that there is no GuardStack cookie // The cookie is either at ESP+gsCookieOffset or EBP-gsCookieOffset unsigned int gsCookieOffset; // 19,20,21,22 unsigned int syncStartOffset; // 23,24,25,26 unsigned int syncEndOffset; // 27,28,29,30 unsigned int revPInvokeOffset; // 31,32,33,34 Available GcInfo v2 onwards, previously undefined // 35 bytes total // Checks whether "this" is compatible with "target". // It is not an exact bit match as "this" could have some // marker/place-holder values, which will have to be written out // after the header. bool isHeaderMatch(const InfoHdr& target) const { #ifdef _ASSERTE // target cannot have place-holder values. _ASSERTE(target.untrackedCnt != HAS_UNTRACKED && target.varPtrTableSize != HAS_VARPTR && target.gsCookieOffset != HAS_GS_COOKIE_OFFSET && target.syncStartOffset != HAS_SYNC_OFFSET && target.revPInvokeOffset != HAS_REV_PINVOKE_FRAME_OFFSET); #endif // compare two InfoHdr's up to but not including the untrackCnt field if (memcmp(this, &target, offsetof(InfoHdr, untrackedCnt)) != 0) return false; if (untrackedCnt != target.untrackedCnt) { if (target.untrackedCnt <= SET_UNTRACKED_MAX) return false; else if (untrackedCnt != HAS_UNTRACKED) return false; } if (varPtrTableSize != target.varPtrTableSize) { if ((varPtrTableSize != 0) != (target.varPtrTableSize != 0)) return false; } if ((gsCookieOffset == INVALID_GS_COOKIE_OFFSET) != (target.gsCookieOffset == INVALID_GS_COOKIE_OFFSET)) return false; if ((syncStartOffset == INVALID_SYNC_OFFSET) != (target.syncStartOffset == INVALID_SYNC_OFFSET)) return false; if ((revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET) != (target.revPInvokeOffset == INVALID_REV_PINVOKE_OFFSET)) return false; return true; } }; union CallPattern { struct { unsigned char argCnt; unsigned char regMask; // EBP=0x8, EBX=0x4, ESI=0x2, EDI=0x1 unsigned char argMask; unsigned char codeDelta; } fld; unsigned val; }; #include #define IH_MAX_PROLOG_SIZE (51) extern const InfoHdrSmall infoHdrShortcut[]; extern int infoHdrLookup[]; inline void GetInfoHdr(int index, InfoHdr * header) { *((InfoHdrSmall *)header) = infoHdrShortcut[index]; header->gsCookieOffset = INVALID_GS_COOKIE_OFFSET; header->syncStartOffset = INVALID_SYNC_OFFSET; header->syncEndOffset = INVALID_SYNC_OFFSET; header->revPInvokeOffset = INVALID_REV_PINVOKE_OFFSET; } PTR_CBYTE FASTCALL decodeHeader(PTR_CBYTE table, UINT32 version, InfoHdr* header); BYTE FASTCALL encodeHeaderFirst(const InfoHdr& header, InfoHdr* state, int* more, int *pCached); BYTE FASTCALL encodeHeaderNext(const InfoHdr& header, InfoHdr* state, BYTE &codeSet); size_t FASTCALL decodeUnsigned(PTR_CBYTE src, unsigned* value); size_t FASTCALL decodeUDelta(PTR_CBYTE src, unsigned* value, unsigned lastValue); size_t FASTCALL decodeSigned(PTR_CBYTE src, int * value); #define CP_MAX_CODE_DELTA (0x23) #define CP_MAX_ARG_CNT (0x02) #define CP_MAX_ARG_MASK (0x00) extern const unsigned callPatternTable[]; extern const unsigned callCommonDelta[]; int FASTCALL lookupCallPattern(unsigned argCnt, unsigned regMask, unsigned argMask, unsigned codeDelta); void FASTCALL decodeCallPattern(int pattern, unsigned * argCnt, unsigned * regMask, unsigned * argMask, unsigned * codeDelta); #endif // _TARGET_86_ // Stack offsets must be 8-byte aligned, so we use this unaligned // offset to represent that the method doesn't have a security object #define NO_GS_COOKIE (-1) #define NO_STACK_BASE_REGISTER (0xffffffff) #define NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA (0xffffffff) #define NO_GENERICS_INST_CONTEXT (-1) #define NO_REVERSE_PINVOKE_FRAME (-1) #define NO_PSP_SYM (-1) #if defined(TARGET_AMD64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) #define NORMALIZE_STACK_SLOT(x) ((x)>>3) #define DENORMALIZE_STACK_SLOT(x) ((x)<<3) #define NORMALIZE_CODE_LENGTH(x) (x) #define DENORMALIZE_CODE_LENGTH(x) (x) // Encode RBP as 0 #define NORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) #define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) #define CODE_OFFSETS_NEED_NORMALIZATION 0 #define NORMALIZE_CODE_OFFSET(x) (x) #define DENORMALIZE_CODE_OFFSET(x) (x) #define NORMALIZE_REGISTER(x) (x) #define DENORMALIZE_REGISTER(x) (x) #define NORMALIZE_NUM_SAFE_POINTS(x) (x) #define DENORMALIZE_NUM_SAFE_POINTS(x) (x) #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 #define CODE_LENGTH_ENCBASE 8 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 #define STACK_BASE_REGISTER_ENCBASE 3 #define SIZE_OF_STACK_AREA_ENCBASE 3 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 #define REVERSE_PINVOKE_FRAME_ENCBASE 6 #define NUM_REGISTERS_ENCBASE 2 #define NUM_STACK_SLOTS_ENCBASE 2 #define NUM_UNTRACKED_SLOTS_ENCBASE 1 #define NORM_PROLOG_SIZE_ENCBASE 5 #define NORM_EPILOG_SIZE_ENCBASE 3 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 #define REGISTER_ENCBASE 3 #define REGISTER_DELTA_ENCBASE 2 #define STACK_SLOT_ENCBASE 6 #define STACK_SLOT_DELTA_ENCBASE 4 #define NUM_SAFE_POINTS_ENCBASE 2 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 #define NUM_EH_CLAUSES_ENCBASE 2 #define POINTER_SIZE_ENCBASE 3 #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 #elif defined(TARGET_ARM) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) #define NORMALIZE_STACK_SLOT(x) ((x)>>2) #define DENORMALIZE_STACK_SLOT(x) ((x)<<2) #define NORMALIZE_CODE_LENGTH(x) ((x)>>1) #define DENORMALIZE_CODE_LENGTH(x) ((x)<<1) // Encode R11 as zero #define NORMALIZE_STACK_BASE_REGISTER(x) ((((x) - 4) & 7) ^ 7) #define DENORMALIZE_STACK_BASE_REGISTER(x) (((x) ^ 7) + 4) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>2) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<2) #define CODE_OFFSETS_NEED_NORMALIZATION 1 #define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 2/4 bytes long in Thumb/ARM states, #define DENORMALIZE_CODE_OFFSET(x) (x) // but the safe-point offsets are encoded with a -1 adjustment. #define NORMALIZE_REGISTER(x) (x) #define DENORMALIZE_REGISTER(x) (x) #define NORMALIZE_NUM_SAFE_POINTS(x) (x) #define DENORMALIZE_NUM_SAFE_POINTS(x) (x) #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) // The choices of these encoding bases only affects space overhead // and performance, not semantics/correctness. #define PSP_SYM_STACK_SLOT_ENCBASE 5 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 5 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 5 #define GS_COOKIE_STACK_SLOT_ENCBASE 5 #define CODE_LENGTH_ENCBASE 7 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2 #define STACK_BASE_REGISTER_ENCBASE 1 #define SIZE_OF_STACK_AREA_ENCBASE 3 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 #define REVERSE_PINVOKE_FRAME_ENCBASE 5 #define NUM_REGISTERS_ENCBASE 2 #define NUM_STACK_SLOTS_ENCBASE 3 #define NUM_UNTRACKED_SLOTS_ENCBASE 3 #define NORM_PROLOG_SIZE_ENCBASE 5 #define NORM_EPILOG_SIZE_ENCBASE 3 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 4 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 #define REGISTER_ENCBASE 2 #define REGISTER_DELTA_ENCBASE 1 #define STACK_SLOT_ENCBASE 6 #define STACK_SLOT_DELTA_ENCBASE 4 #define NUM_SAFE_POINTS_ENCBASE 3 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 2 #define NUM_EH_CLAUSES_ENCBASE 3 #define POINTER_SIZE_ENCBASE 3 #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 #elif defined(TARGET_ARM64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) #define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned #define DENORMALIZE_STACK_SLOT(x) ((x)<<3) #define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long #define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) #define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) // Encode Frame pointer X29 as zero #define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) #define CODE_OFFSETS_NEED_NORMALIZATION 0 #define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point #define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment. #define NORMALIZE_REGISTER(x) (x) #define DENORMALIZE_REGISTER(x) (x) #define NORMALIZE_NUM_SAFE_POINTS(x) (x) #define DENORMALIZE_NUM_SAFE_POINTS(x) (x) #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 #define CODE_LENGTH_ENCBASE 8 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 #define STACK_BASE_REGISTER_ENCBASE 2 // FP encoded as 0, SP as 2. #define SIZE_OF_STACK_AREA_ENCBASE 3 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 #define SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE 4 #define REVERSE_PINVOKE_FRAME_ENCBASE 6 #define NUM_REGISTERS_ENCBASE 3 #define NUM_STACK_SLOTS_ENCBASE 2 #define NUM_UNTRACKED_SLOTS_ENCBASE 1 #define NORM_PROLOG_SIZE_ENCBASE 5 #define NORM_EPILOG_SIZE_ENCBASE 3 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 #define REGISTER_ENCBASE 3 #define REGISTER_DELTA_ENCBASE 2 #define STACK_SLOT_ENCBASE 6 #define STACK_SLOT_DELTA_ENCBASE 4 #define NUM_SAFE_POINTS_ENCBASE 3 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 #define NUM_EH_CLAUSES_ENCBASE 2 #define POINTER_SIZE_ENCBASE 3 #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 #elif defined(TARGET_LOONGARCH64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) #define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned #define DENORMALIZE_STACK_SLOT(x) ((x)<<3) #define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long #define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) #define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^22) // Encode Frame pointer fp=$22 as zero #define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^22) #define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) #define CODE_OFFSETS_NEED_NORMALIZATION 0 #define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point #define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment. #define NORMALIZE_REGISTER(x) (x) #define DENORMALIZE_REGISTER(x) (x) #define NORMALIZE_NUM_SAFE_POINTS(x) (x) #define DENORMALIZE_NUM_SAFE_POINTS(x) (x) #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 #define CODE_LENGTH_ENCBASE 8 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 ////TODO for LOONGARCH64. // FP/SP encoded as 0 or 2 ?? #define STACK_BASE_REGISTER_ENCBASE 2 #define SIZE_OF_STACK_AREA_ENCBASE 3 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 #define REVERSE_PINVOKE_FRAME_ENCBASE 6 #define NUM_REGISTERS_ENCBASE 3 #define NUM_STACK_SLOTS_ENCBASE 2 #define NUM_UNTRACKED_SLOTS_ENCBASE 1 #define NORM_PROLOG_SIZE_ENCBASE 5 #define NORM_EPILOG_SIZE_ENCBASE 3 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 #define REGISTER_ENCBASE 3 #define REGISTER_DELTA_ENCBASE 2 #define STACK_SLOT_ENCBASE 6 #define STACK_SLOT_DELTA_ENCBASE 4 #define NUM_SAFE_POINTS_ENCBASE 3 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 #define NUM_EH_CLAUSES_ENCBASE 2 #define POINTER_SIZE_ENCBASE 3 #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 #else #ifndef TARGET_X86 #ifdef PORTABILITY_WARNING PORTABILITY_WARNING("Please specialize these definitions for your platform!") #endif #endif #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif #define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) #define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) #define NORMALIZE_STACK_SLOT(x) (x) #define DENORMALIZE_STACK_SLOT(x) (x) #define NORMALIZE_CODE_LENGTH(x) (x) #define DENORMALIZE_CODE_LENGTH(x) (x) #define NORMALIZE_STACK_BASE_REGISTER(x) (x) #define DENORMALIZE_STACK_BASE_REGISTER(x) (x) #define NORMALIZE_SIZE_OF_STACK_AREA(x) (x) #define DENORMALIZE_SIZE_OF_STACK_AREA(x) (x) #define CODE_OFFSETS_NEED_NORMALIZATION 0 #define NORMALIZE_CODE_OFFSET(x) (x) #define DENORMALIZE_CODE_OFFSET(x) (x) #define NORMALIZE_REGISTER(x) (x) #define DENORMALIZE_REGISTER(x) (x) #define NORMALIZE_NUM_SAFE_POINTS(x) (x) #define DENORMALIZE_NUM_SAFE_POINTS(x) (x) #define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) #define PSP_SYM_STACK_SLOT_ENCBASE 6 #define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 #define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 #define GS_COOKIE_STACK_SLOT_ENCBASE 6 #define CODE_LENGTH_ENCBASE 6 #define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 #define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2 #define STACK_BASE_REGISTER_ENCBASE 3 #define SIZE_OF_STACK_AREA_ENCBASE 6 #define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 #define REVERSE_PINVOKE_FRAME_ENCBASE 6 #define NUM_REGISTERS_ENCBASE 3 #define NUM_STACK_SLOTS_ENCBASE 5 #define NUM_UNTRACKED_SLOTS_ENCBASE 5 #define NORM_PROLOG_SIZE_ENCBASE 4 #define NORM_EPILOG_SIZE_ENCBASE 3 #define NORM_CODE_OFFSET_DELTA_ENCBASE 3 #define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 5 #define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 5 #define REGISTER_ENCBASE 3 #define REGISTER_DELTA_ENCBASE REGISTER_ENCBASE #define STACK_SLOT_ENCBASE 6 #define STACK_SLOT_DELTA_ENCBASE 4 #define NUM_SAFE_POINTS_ENCBASE 4 #define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 #define NUM_EH_CLAUSES_ENCBASE 2 #define POINTER_SIZE_ENCBASE 3 #define LIVESTATE_RLE_RUN_ENCBASE 2 #define LIVESTATE_RLE_SKIP_ENCBASE 4 #endif #endif // !__GCINFOTYPES_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcmsg.inl ================================================ static const char* gcStartMsg() { STATIC_CONTRACT_LEAF; return "{ =========== BEGINGC %d, (requested generation = %lu, collect_classes = %lu) ==========\n"; } static const char* gcEndMsg() { STATIC_CONTRACT_LEAF; return "========== ENDGC %d (gen = %lu, collect_classes = %lu) ===========}\n"; } static const char* gcRootMsg() { STATIC_CONTRACT_LEAF; return " GC Root %p RELOCATED %p -> %p MT = %pT\n"; } static const char* gcRootPromoteMsg() { STATIC_CONTRACT_LEAF; return " IGCHeap::Promote: Promote GC Root *%p = %p MT = %pT\n"; } static const char* gcPlugMoveMsg() { STATIC_CONTRACT_LEAF; return "GC_HEAP RELOCATING Objects in heap within range [%p %p) by -0x%x bytes\n"; } static const char* gcServerThread0StartMsg() { STATIC_CONTRACT_LEAF; return "%d gc thread waiting..."; } static const char* gcServerThreadNStartMsg() { STATIC_CONTRACT_LEAF; return "%d gc thread waiting... Done"; } static const char* gcDetailedStartMsg() { STATIC_CONTRACT_LEAF; return "*GC* %d(gen0:%d)(%d)(alloc: %zd)(%s)(%d)"; } static const char* gcDetailedEndMsg() { STATIC_CONTRACT_LEAF; return "*EGC* %zd(gen0:%zd)(%zd)(%d)(%s)(%s)(%s)(ml: %d->%d)"; } static const char* gcStartMarkMsg() { STATIC_CONTRACT_LEAF; return "---- Mark Phase on heap %d condemning %d ----"; } static const char* gcStartPlanMsg() { STATIC_CONTRACT_LEAF; return "---- Plan Phase on heap %d ---- Condemned generation %d, promotion: %d"; } static const char* gcStartRelocateMsg() { STATIC_CONTRACT_LEAF; return "---- Relocate phase on heap %d -----"; } static const char* gcEndRelocateMsg() { STATIC_CONTRACT_LEAF; return "---- End of Relocate phase on heap %d ----"; } static const char* gcStartCompactMsg() { STATIC_CONTRACT_LEAF; return "---- Compact Phase on heap %d: %zx(%zx)----"; } static const char* gcEndCompactMsg() { STATIC_CONTRACT_LEAF; return "---- End of Compact phase on heap %d ----"; } static const char* gcMemCopyMsg() { STATIC_CONTRACT_LEAF; return " mc: [%zx->%zx, %zx->%zx["; } static const char* gcPlanPlugMsg() { STATIC_CONTRACT_LEAF; return "(%zx)[%zx->%zx, NA: [%zx(%zd), %zx[: %zx(%d), x: %zx (%s)"; } static const char* gcPlanPinnedPlugMsg() { STATIC_CONTRACT_LEAF; return "(%zx)PP: [%zx, %zx[%zx](m:%d)"; } static const char* gcDesiredNewAllocationMsg() { STATIC_CONTRACT_LEAF; return "h%d g%d surv: %zd current: %zd alloc: %zd (%d%%) f: %d%% new-size: %zd new-alloc: %zd"; } static const char* gcMakeUnusedArrayMsg() { STATIC_CONTRACT_LEAF; return "Making unused array [%zx, %zx["; } static const char* gcStartBgcThread() { STATIC_CONTRACT_LEAF; return "beginning of bgc on heap %d: gen2 FL: %d, FO: %d, frag: %d"; } static const char* gcRelocateReferenceMsg() { STATIC_CONTRACT_LEAF; return "Relocating reference *(%p) from %p to %p"; } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gcrefmap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _GCREFMAP_H_ #define _GCREFMAP_H_ #include "sigbuilder.h" // // The GCRef map is used to encode GC type of arguments for callsites. Logically, it is sequence where pos is // position of the reference in the stack frame and token is type of GC reference (one of GCREFMAP_XXX values). // // - The encoding always starts at the byte boundary. The high order bit of each byte is used to signal end of the encoding // stream. The last byte has the high order bit zero. It means that there are 7 useful bits in each byte. // - "pos" is always encoded as delta from previous pos. // - The basic encoding unit is two bits. Values 0, 1 and 2 are the common constructs (skip single slot, GC reference, interior // pointer). Value 3 means that extended encoding follows. // - The extended information is integer encoded in one or more four bit blocks. The high order bit of the four bit block is // used to signal the end. // - For x86, the encoding starts by size of the callee poped stack. The size is encoded using the same mechanism as above (two bit // basic encoding, with extended encoding for large values). ///////////////////////////////////////////////////////////////////////////////////// // A utility class to encode sequence of GC summaries for a callsite class GCRefMapBuilder { int m_PendingByte; // Pending value, not yet written out int m_Bits; // Number of bits in pending byte. Note that the trailing zero bits are not written out, // so this can be more than 7. int m_Pos; // Current position SigBuilder m_SigBuilder; // Append single bit to the stream void AppendBit(int bit) { if (bit != 0) { while (m_Bits >= 7) { m_SigBuilder.AppendByte((BYTE)(m_PendingByte | 0x80)); m_PendingByte = 0; m_Bits -= 7; } m_PendingByte |= (1 << m_Bits); } m_Bits++; } void AppendTwoBit(int bits) { AppendBit(bits & 1); AppendBit(bits >> 1); } void AppendInt(int val) { do { AppendBit(val & 1); AppendBit((val >> 1) & 1); AppendBit((val >> 2) & 1); val >>= 3; AppendBit((val != 0) ? 1 : 0); } while (val != 0); } public: GCRefMapBuilder() : m_PendingByte(0), m_Bits(0), m_Pos(0) { } #ifdef TARGET_X86 void WriteStackPop(int stackPop) { if (stackPop < 3) { AppendTwoBit(stackPop); } else { AppendTwoBit(3); AppendInt(stackPop - 3); } } #endif void WriteToken(int pos, int gcRefMapToken) { int posDelta = pos - m_Pos; m_Pos = pos + 1; _ASSERTE(posDelta >= 0); if (posDelta != 0) { if (posDelta < 4) { // Skipping by one slot at a time for small deltas produces smaller encoding. while (posDelta > 0) { AppendTwoBit(0); posDelta--; } } else { AppendTwoBit(3); AppendInt((posDelta - 4) << 1); } } if (gcRefMapToken < 3) { AppendTwoBit(gcRefMapToken); } else { AppendTwoBit(3); AppendInt(((gcRefMapToken - 3) << 1) | 1); } } void Flush() { if ((m_PendingByte & 0x7F) != 0 || m_Pos == 0) m_SigBuilder.AppendByte((BYTE)(m_PendingByte & 0x7F)); m_PendingByte = 0; m_Bits = 0; m_Pos = 0; } PVOID GetBlob(DWORD * pdwLength) { return m_SigBuilder.GetSignature(pdwLength); } DWORD GetBlobLength() { return m_SigBuilder.GetSignatureLength(); } }; ///////////////////////////////////////////////////////////////////////////////////// // A utility class to decode a GC summary for a callsite class GCRefMapDecoder { PTR_BYTE m_pCurrentByte; int m_PendingByte; int m_Pos; FORCEINLINE int GetBit() { int x = m_PendingByte; if (x & 0x80) { x = *m_pCurrentByte++; x |= ((x & 0x80) << 7); } m_PendingByte = x >> 1; return x & 1; } FORCEINLINE int GetTwoBit() { int result = GetBit(); result |= GetBit() << 1; return result; } int GetInt() { int result = 0; int bit = 0; do { result |= GetBit() << (bit++); result |= GetBit() << (bit++); result |= GetBit() << (bit++); } while (GetBit() != 0); return result; } public: GCRefMapDecoder(PTR_BYTE pBlob) : m_pCurrentByte(pBlob), m_PendingByte(0x80), m_Pos(0) { } BOOL AtEnd() { return m_PendingByte == 0; } #ifdef TARGET_X86 UINT ReadStackPop() { int x = GetTwoBit(); if (x == 3) x = GetInt() + 3; return x; } #endif int CurrentPos() { return m_Pos; } int ReadToken() { int val = GetTwoBit(); if (val == 3) { int ext = GetInt(); if ((ext & 1) == 0) { m_Pos += (ext >> 1) + 4; return GCREFMAP_SKIP; } else { m_Pos++; return (ext >> 1) + 3; } } m_Pos++; return val; } }; #endif // _GCREFMAP_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/genheaders.cs ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Xml; using System.Xml.Schema; using System.IO; public class GenerateHeaders { public static void Main(string[] args) { if (args.Length != 3) { Console.WriteLine("Usage:genheaders XML-file header-file resource-file"); return; } ValidateXML(args[0]); String Message=null; String SymbolicName=null; String NumericValue=null; String tempheaderfile = "temp.h"; String temprcfile = "temp.rc"; StreamWriter HSW=File.CreateText(tempheaderfile); StreamWriter RSW=File.CreateText(temprcfile); int FaciltyUrt=0x13; int SeveritySuccess=0; int SeverityError=1; int minSR = MakeHresult(SeveritySuccess,FaciltyUrt,0); int maxSR = MakeHresult(SeveritySuccess,FaciltyUrt,0xffff); int minHR = MakeHresult(SeverityError,FaciltyUrt,0); int maxHR = MakeHresult(SeverityError,FaciltyUrt,0xffff); PrintLicenseHeader(HSW); PrintHeader(HSW); PrintLicenseHeader(RSW); PrintResourceHeader(RSW); XmlTextReader rdr = new XmlTextReader(args[0]); rdr.WhitespaceHandling = WhitespaceHandling.None; while (rdr.Read()) { switch (rdr.NodeType) { case XmlNodeType.Element: if (rdr.Name.ToString() == "HRESULT") { NumericValue=rdr.GetAttribute("NumericValue"); } if (rdr.Name.ToString() == "Message") { Message = rdr.ReadString(); } if (rdr.Name.ToString() == "SymbolicName") { SymbolicName = rdr.ReadString(); } break; case XmlNodeType.EndElement: if(rdr.Name.ToString() == "HRESULT"){ // For CLR Hresult's we take the last 4 digits as the resource strings. if ( (NumericValue.StartsWith("0x")) || (NumericValue.StartsWith("0X")) ) { String HexResult = NumericValue.Substring(2); int num = int.Parse(HexResult, System.Globalization.NumberStyles.HexNumber); if ((num>minSR) && (num <= maxSR)) { num = num & 0xffff; HSW.WriteLine("#define " + SymbolicName + " SMAKEHR(0x" + num.ToString("x") + ")"); } else if ((num>minHR) && (num <= maxHR)) { num = num & 0xffff; HSW.WriteLine("#define " + SymbolicName + " EMAKEHR(0x" + num.ToString("x") + ")"); } else { HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); } } else { HSW.WriteLine("#define " + SymbolicName + " " + NumericValue ); } if (Message != null) { RSW.Write("\tMSG_FOR_URT_HR(" + SymbolicName + ") "); RSW.WriteLine(Message); } SymbolicName = null; NumericValue = null; Message = null; } break; } } PrintFooter(HSW); PrintResourceFooter(RSW); HSW.Close(); RSW.Close(); bool AreFilesEqual = false; if (File.Exists(args[1])) { StreamReader sr1 = new StreamReader(tempheaderfile); StreamReader sr2 = new StreamReader(args[1]); AreFilesEqual = CompareFiles(sr1, sr2); sr1.Close(); sr2.Close(); } if (!AreFilesEqual) { File.Copy(tempheaderfile, args[1], true); File.Copy(temprcfile, args[2], true); } if (!File.Exists(args[2])) { File.Copy(temprcfile, args[2], true); } File.Delete(tempheaderfile); File.Delete(temprcfile); } private static void ValidateXML (String XMLFile) { // Set the validation settings on the XmlReaderSettings object. XmlReaderSettings settings = new XmlReaderSettings(); settings.ValidationType = ValidationType.Schema; settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; settings.ValidationEventHandler += new ValidationEventHandler (ValidationCallBack); // Create the XmlReader object. XmlReader reader = XmlReader.Create(XMLFile, settings); // Parse the file. while (reader.Read()) { } } // Display any validation errors. private static void ValidationCallBack(object sender, ValidationEventArgs e) { Console.WriteLine("Validation Error: {0}", e.Message); Environment.Exit(-1); } private static void PrintLicenseHeader(StreamWriter SW) { SW.WriteLine("// Licensed to the .NET Foundation under one or more agreements."); SW.WriteLine("// The .NET Foundation licenses this file to you under the MIT license."); SW.WriteLine(); } private static void PrintHeader(StreamWriter SW) { SW.WriteLine("#ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); SW.WriteLine("#define __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); SW.WriteLine(); SW.WriteLine("#include "); SW.WriteLine(); SW.WriteLine(); SW.WriteLine("//"); SW.WriteLine("//This file is AutoGenerated -- Do Not Edit by hand!!!"); SW.WriteLine("//"); SW.WriteLine("//Add new HRESULTS along with their corresponding error messages to"); SW.WriteLine("//corerror.xml"); SW.WriteLine("//"); SW.WriteLine(); SW.WriteLine("#ifndef FACILITY_URT"); SW.WriteLine("#define FACILITY_URT 0x13"); SW.WriteLine("#endif"); SW.WriteLine("#ifndef EMAKEHR"); SW.WriteLine("#define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val)"); SW.WriteLine("#define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val)"); SW.WriteLine("#endif"); SW.WriteLine(); } private static void PrintFooter(StreamWriter SW) { SW.WriteLine(); SW.WriteLine(); SW.WriteLine("#endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__"); } private static void PrintResourceHeader(StreamWriter SW) { SW.WriteLine("STRINGTABLE DISCARDABLE"); SW.WriteLine("BEGIN"); } private static void PrintResourceFooter(StreamWriter SW) { SW.WriteLine("END"); } private static bool CompareFiles(StreamReader sr1, StreamReader sr2) { String line1,line2; while (true) { line1 = sr1.ReadLine(); line2 = sr2.ReadLine(); if ( (line1 == null) && (line2 == null) ) { return true; } if (line1 != line2) { return false; } } } private static int MakeHresult(int sev, int fac, int code) { return ((sev<<31) | (fac<<16) | (code)); } } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/genrops.pl ================================================ # Licensed to the .NET Foundation under one or more agreements. # The .NET Foundation licenses this file to you under the MIT license. # # GENREFOPS.PL # # PERL script used to generate the numbering of the reference opcodes # #use strict 'vars'; #use strict 'subs'; #use strict 'refs'; print "Reference opcodes\n"; print "This file is presently only for human consumption\n"; print "This file is generated from opcode.def using the genrops.pl script\n\n"; print "Name String Name refop encode\n"; print "-----------------------------------------------------------------\n"; my $ret = 0; my %oneByte; my %twoByte; $count = 0; while (<>) { # Process only OPDEF(....) lines if (/OPDEF\(\s*/) { chop; # Strip off trailing CR s/^OPDEF\(\s*//; # Strip off "OP(" s/\)$//; # Strip off ")" at end s/,\s*/,/g; # Remove whitespace # Split the line up into its basic parts ($enumname, $stringname, $pop, $push, $operand, $type, $size, $s1, $s2, $ctrl) = split(/,/); $s1 =~ s/0x//; $s1 = hex($s1); $s2 =~ s/0x//; $s2 = hex($s2); my $line = sprintf("%-24s %-24s 0x%03x", $enumname, $stringname, $count); if ($size == 1) { $line .= sprintf(" 0x%02x\n", $s2); if ($oneByte{$s2}) { printf("Error opcode 0x%x already defined!\n", $s2); print " Old = $oneByte{$s2}"; print " New = $line"; $ret = -1; } $oneByte{$s2} = $line; } elsif ($size == 2) { if ($twoByte{$s2}) { printf("Error opcode 0x%x 0x%x already defined!\n", $s1, $s2); print " Old = $twoByte{$s2}"; print " New = $line"; $ret = -1; } $line .= sprintf(" 0x%02x 0x%02x\n", $s1, $s2); $twoByte{$s2 + 256 * $s1} = $line; } else { $line .= "\n"; push(@deprecated, $line); } $count++; } } my $opcode; my $lastOp = -1; foreach $opcode (sort {$a <=> $b} keys(%oneByte)) { printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); print $oneByte{$opcode}; $lastOp = $opcode; } $lastOp = -1; foreach $opcode (sort {$a <=> $b} keys(%twoByte)) { printf("***** GAP %d instrs ****\n", $opcode - $lastOp) if ($lastOp + 1 != $opcode && $lastOp > 0); print $twoByte{$opcode}; $lastOp = $opcode; } print @deprecated; exit($ret); ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/gfunc_list.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // Any global function that should be tracked in the DAC should be provided here #ifndef DEFINE_DACGFN #define DEFINE_DACGFN(func) #endif #ifndef DEFINE_DACGFN_STATIC #define DEFINE_DACGFN_STATIC(class, func) #endif DEFINE_DACGFN(DACNotifyCompilationFinished) DEFINE_DACGFN(ThePreStub) #ifdef TARGET_ARM DEFINE_DACGFN(ThePreStubCompactARM) #endif DEFINE_DACGFN(ThePreStubPatchLabel) #ifdef FEATURE_COMINTEROP DEFINE_DACGFN(Unknown_AddRef) DEFINE_DACGFN(Unknown_AddRefSpecial) DEFINE_DACGFN(Unknown_AddRefInner) #endif #ifdef FEATURE_COMWRAPPERS DEFINE_DACGFN(ManagedObjectWrapper_QueryInterface) DEFINE_DACGFN(TrackerTarget_QueryInterface) #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/guidfromname.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef GUIDFROMNAME_H_ #define GUIDFROMNAME_H_ // GuidFromName.h - function prototype void CorGuidFromNameW ( GUID * pGuidResult, // resulting GUID LPCWSTR wzName, // the unicode name from which to generate a GUID SIZE_T cchName // name length in count of unicode character. // -1 if lstrlen(wzName)+1 should be used ); #endif // GUIDFROMNAME_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/holder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __HOLDER_H_ #define __HOLDER_H_ #include #include "cor.h" #include "staticcontract.h" #include "volatile.h" #include "palclr.h" #ifdef PAL_STDCPP_COMPAT #include #include #else #include "clr_std/utility" #include "clr_std/type_traits" #endif #if defined(FEATURE_COMINTEROP) && !defined(STRIKE) #include #include #endif // Note: you can't use CONTRACT's in this file. You can't use dynamic contracts because the impl of dynamic // contracts depends on holders. You can't use static contracts because they include the function name as a string, // and the template names in this file are just too long, so you get a compiler error. // // All the functions in this file are pretty basic, so the lack of CONTRACT's isn't a big loss. #ifdef _MSC_VER // Make sure we can recurse deep enough for FORCEINLINE #pragma inline_recursion(on) #pragma inline_depth(16) #pragma warning(disable:4714) #endif // _MSC_VER //------------------------------------------------------------------------------------------------ // Declare but do not define methods that would normally be automatically generated by the // compiler. This will produce a link-time error if they are used. This is involved in object // initialization and operator eliding; see // http://groups.google.com/group/comp.lang.c++/msg/3cd673ab749bed83?dmode=source // for the intricate details. #ifdef __GNUC__ // GCC checks accessibility of the copy ctor before performing elision optimization, so // it must be declared as public. VC does not, so we can declare it private to give an // earlier error message. #define HIDE_GENERATED_METHODS(_NAME) \ public: \ _NAME(_NAME const &); \ private: \ _NAME & operator=(_NAME const &); #else #define HIDE_GENERATED_METHODS(_NAME) \ private: \ _NAME(_NAME const &); \ _NAME & operator=(_NAME const &); #endif #ifdef _DEBUG //------------------------------------------------------------------------------------------------ // This is used to make Visual Studio autoexp.dat work sensibly with holders again. // The problem is that certain codebases (particulary Fusion) implement key data structures // using a class but refer to it using a holder to an interface type. This combination prevents // autoexp rules from working as desired. // // Example: Take this useful autoexp rule for CAssemblyName. // // CAssemblyName=<_rProp._rProp[3].asStr> // // To get the same rule to fire when your assemblyname is wrapped in a ReleaseHolder, // add these companion rules. // // HolderBase=_rProp._rProp[3].asStr> // HolderBase=_asCAssemblyName->_rProp._rProp[3].asStr> // //------------------------------------------------------------------------------------------------ struct AutoExpVisibleValue { private: union { const void *_pPreventEmptyUnion; }; }; #endif //_DEBUG //----------------------------------------------------------------------------- // Holder is the base class of all holder objects. Any backout object should derive from it. // (Eventually some additional bookkeeping and exception handling code will be placed in this // base class.) // // There are several ways to use this class: // 1. Derive from HolderBase, and instantiate a Holder or Wrapper around your base. This is necessary // if you need to add more state to your holder. // 2. Instantiate the Holder template with your type and functions. // 3. Instantiate the Wrapper template with your type and functions. The Wrapper adds some additional // operator overloads to provide "smart pointer" like behavior // 4. Use a prebaked Holder. This is ALWAYS the preferable strategy. It is expected that // the general design patter is that Holders will be provided as part of a typical data abstraction. // (See Crst for an example of this.) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // HolderBase defines the base holder functionality. You can subtype and plug in // a different base if you need to add more members for access during // acquire & release //----------------------------------------------------------------------------- template class HolderBase { friend class ClrDataAccess; protected: TYPE m_value; HolderBase(TYPE value) : m_value(value) { #ifdef _DEBUG m_pAutoExpVisibleValue = (const AutoExpVisibleValue *)(&m_value); #endif //_DEBUG } void DoAcquire() { // Insert any global or thread bookkeeping here } void DoRelease() { // Insert any global or thread bookkeeping here } #ifdef _DEBUG private: // NOT DEAD CODE: This field is not referenced in the source code but it is not a dead field. See comments above "class AutoExpVisibleValue" for why this field exists. // Note: What we really want is for m_value and m_pAutoExpVisibleValue to be members of a union. But the compiler won't let you build that // since it can't prove that "TYPE" doesn't have a non-trivial constructor. const AutoExpVisibleValue *m_pAutoExpVisibleValue; // This field is to be referenced from individual autoexp.dat files, NOT from the CLR source code. #endif //_DEBUG }; // class HolderBase<> #ifndef _PREFAST_ // Work around an ICE error in EspX.dll template BOOL CompareDefault(TYPE value, TYPE defaultValue) { STATIC_CONTRACT_SUPPORTS_DAC; return value == defaultValue; } #else template BOOL CompareDefault(TYPE value, TYPE defaultValue) { return FALSE; } #endif template BOOL NoNull(TYPE value, TYPE defaultValue) { return FALSE; } // Used e.g. for retail version of code:SyncAccessHolder template class NoOpBaseHolder { public: FORCEINLINE NoOpBaseHolder() { } FORCEINLINE NoOpBaseHolder(TYPE value, BOOL take = TRUE) { } FORCEINLINE ~NoOpBaseHolder() { } FORCEINLINE void Assign(TYPE value, BOOL fTake = TRUE) { } FORCEINLINE void Acquire() { } FORCEINLINE void Release() { } FORCEINLINE void Clear() { } FORCEINLINE void SuppressRelease() { } FORCEINLINE TYPE Extract() { } FORCEINLINE TYPE GetValue() { } FORCEINLINE BOOL IsNull() const { return FALSE; } private: NoOpBaseHolder& operator=(NoOpBaseHolder const &); NoOpBaseHolder(NoOpBaseHolder const &); }; // NoOpBaseHolder<> template < typename TYPE, typename BASE, UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault > class BaseHolder : protected BASE { friend class ClrDataAccess; protected: BOOL m_acquired; // Have we acquired the resource? static_assert(!std::is_pointer::value || DEFAULTVALUE == 0 || DEFAULTVALUE == UINT_PTR(-1 /*INVALID_HANDLE_VALUE*/), "DEFAULTVALUE must be NULL for pointer holders and wrappers."); public: FORCEINLINE BaseHolder() : BASE(TYPE(DEFAULTVALUE)), m_acquired(FALSE) { } FORCEINLINE BaseHolder(TYPE value) : BASE(value), m_acquired(FALSE) { if (!IsNull()) Acquire(); } FORCEINLINE BaseHolder(TYPE value, BOOL takeOwnership) : BASE(value), m_acquired(FALSE) { if (takeOwnership) Acquire(); } FORCEINLINE ~BaseHolder() { Release(); } // Sets the value to 'value'. Doesn't call Acquire if value is DEFAULTVALUE. FORCEINLINE void Assign(TYPE value) { Assign(value, !IS_NULL(value, TYPE(DEFAULTVALUE))); } // Sets the value to 'value'. Doesn't call Acquire if fTake is FALSE. FORCEINLINE void Assign(TYPE value, BOOL takeOwnership) { Release(); this->m_value = value; if (takeOwnership) Acquire(); } FORCEINLINE void Acquire() { STATIC_CONTRACT_WRAPPER; _ASSERTE(!m_acquired); if (!IsNull()) { this->DoAcquire(); m_acquired = TRUE; } } FORCEINLINE void Release() { STATIC_CONTRACT_WRAPPER; if (m_acquired) { _ASSERTE(!IsNull()); this->DoRelease(); m_acquired = FALSE; } } FORCEINLINE void Clear() { STATIC_CONTRACT_WRAPPER; Assign(TYPE(DEFAULTVALUE), FALSE); } FORCEINLINE void SuppressRelease() { STATIC_CONTRACT_LEAF; m_acquired = FALSE; } FORCEINLINE TYPE Extract() { STATIC_CONTRACT_WRAPPER; SuppressRelease(); return GetValue(); } FORCEINLINE TYPE GetValue() { STATIC_CONTRACT_LEAF; return this->m_value; } FORCEINLINE BOOL IsNull() const { STATIC_CONTRACT_WRAPPER; return IS_NULL(this->m_value, TYPE(DEFAULTVALUE)); } HIDE_GENERATED_METHODS(BaseHolder) }; // BaseHolder<> template class StateHolder { private: BOOL m_acquired; // Have we acquired the state? public: FORCEINLINE StateHolder(BOOL take = TRUE) : m_acquired(FALSE) { STATIC_CONTRACT_WRAPPER; if (take) Acquire(); } FORCEINLINE ~StateHolder() { STATIC_CONTRACT_WRAPPER; Release(); } FORCEINLINE void Acquire() { STATIC_CONTRACT_WRAPPER; // Insert any global or thread bookkeeping here _ASSERTE(!m_acquired); ACQUIRE(); m_acquired = TRUE; } FORCEINLINE void Release() { STATIC_CONTRACT_WRAPPER; // Insert any global or thread bookkeeping here if (m_acquired) { RELEASEF(); m_acquired = FALSE; } } FORCEINLINE void Clear() { STATIC_CONTRACT_WRAPPER; if (m_acquired) { RELEASEF(); } m_acquired = FALSE; } FORCEINLINE void SuppressRelease() { STATIC_CONTRACT_LEAF; m_acquired = FALSE; } HIDE_GENERATED_METHODS(StateHolder) }; // class StateHolder<> // Holder for the case where the acquire function can fail. template class ConditionalStateHolder { private: VALUE m_value; BOOL m_acquired; // Have we acquired the state? public: FORCEINLINE ConditionalStateHolder(VALUE value, BOOL take = TRUE) : m_value(value), m_acquired(FALSE) { STATIC_CONTRACT_WRAPPER; if (take) Acquire(); } FORCEINLINE ~ConditionalStateHolder() { STATIC_CONTRACT_WRAPPER; Release(); } FORCEINLINE BOOL Acquire() { STATIC_CONTRACT_WRAPPER; // Insert any global or thread bookkeeping here _ASSERTE(!m_acquired); m_acquired = ACQUIRE(m_value); return m_acquired; } FORCEINLINE void Release() { STATIC_CONTRACT_WRAPPER; // Insert any global or thread bookkeeping here if (m_acquired) { RELEASEF(m_value); m_acquired = FALSE; } } FORCEINLINE void Clear() { STATIC_CONTRACT_WRAPPER; if (m_acquired) { RELEASEF(m_value); } m_acquired = FALSE; } FORCEINLINE void SuppressRelease() { STATIC_CONTRACT_LEAF; m_acquired = FALSE; } FORCEINLINE BOOL Acquired() { STATIC_CONTRACT_LEAF; return m_acquired; } HIDE_GENERATED_METHODS(ConditionalStateHolder) }; // class ConditionalStateHolder<> // Making the copy constructor private produces a warning about "can't generate copy // constructor" on all holders (duh, that's the point.) #ifdef _MSC_VER #pragma warning(disable:4511) #endif // _MSC_VER //----------------------------------------------------------------------------- // BaseWrapper is just Base like a Holder, but it "transparently" proxies the type it contains, // using operator overloads. Use this when you want a holder to expose the functionality of // the value it contains. //----------------------------------------------------------------------------- template > class BaseWrapper : public BaseHolder { typedef BaseHolder BaseT; #ifdef __GNUC__ //#pragma GCC visibility push(hidden) #endif // __GNUC__ // This temporary object takes care of the case where we are initializing // a holder's contents by passing it as an out parameter. The object is // guaranteed to live longer than the call it is passed to, hence we should // properly acquire the object on return friend class AddressInitHolder; class AddressInitHolder { protected: BaseWrapper &m_holder; public: FORCEINLINE AddressInitHolder(BaseWrapper &holder) : m_holder(holder) { // // We must clear the value, to avoid the following scenario: // // ReleaseHolder pMyType; // hr = MyFunction(&pMyType, ...); // // hr = MyFunction(&pMyType, ...); <- calls Release before call and Acquire on return. // // If the second call to MyFunction were to fail and return without updating the // out parameter, then ~AddressInitHolder will all Acquire, which is a no-op on // the underlying pointer but sets m_acquired to TRUE. Thus, when pMyType goes // out of scope, ReleaseHolder will cause a double-release of pMyType. // // By calling Clear, then the call to Acquire in the dtor will not set m_acquired // to true since IsNull(m_holder.m_value) will return true. // m_holder.Clear(); } FORCEINLINE ~AddressInitHolder() { m_holder.Acquire(); } // It's not optimal to have to declare these casting operators. But if we don't, // people cannot cast the result of &holder to these values. (The C++ compiler won't // automatically use the TYPE * cast as an intermediate value.) So we put them here, // rather than forcing callers to double cast in these common cases. FORCEINLINE operator IUnknown **() { IUnknown *unknown; // Typesafe check. This will fail at compile time if // m_holder.m_value can't be converted to an IUnknown *. unknown = static_cast(m_holder.m_value); // do the cast with an unsafe cast return (IUnknown **)(&m_holder.m_value); } #if defined(FEATURE_COMINTEROP) && !defined(STRIKE) FORCEINLINE operator IInspectable **() { IInspectable *inspectable; // Typesafe check. This will fail at compile time if // m_holder.m_value can't be converted to an IInspectable *. inspectable = static_cast(m_holder.m_value); return (IInspectable **)(&m_holder.m_value); } #endif // FEATURE_COMINTEROP FORCEINLINE operator void **() { return (void **)(&m_holder.m_value); } FORCEINLINE operator void *() { return (void *)(&m_holder.m_value); } }; // Separate out method with TYPE * cast operator, since it may clash with IUnknown ** or // void ** cast operator. friend class TypedAddressInitHolder; class TypedAddressInitHolder : public AddressInitHolder { public: FORCEINLINE TypedAddressInitHolder(BaseWrapper & holder) : AddressInitHolder(holder) { } FORCEINLINE operator TYPE *() { return static_cast(&this->m_holder.m_value); } }; #ifdef __GNUC__ //#pragma GCC visibility pop #endif // __GNUC__ public: FORCEINLINE BaseWrapper() : BaseT(TYPE(DEFAULTVALUE), FALSE) { } FORCEINLINE BaseWrapper(TYPE value) : BaseT(value) { } FORCEINLINE BaseWrapper(TYPE value, BOOL take) : BaseT(value, take) { } FORCEINLINE BaseWrapper& operator=(TYPE value) { BaseT::Assign(value); return *this; } FORCEINLINE operator TYPE() const { return this->m_value; } FORCEINLINE TypedAddressInitHolder operator&() { return TypedAddressInitHolder(*this); } template FORCEINLINE bool operator==(T const & value) const { return !!(this->m_value == TYPE(value)); } template FORCEINLINE bool operator!=(T const & value) const { return !!(this->m_value != TYPE(value)); } // This handles the NULL value that is an int and the // compiler doesn't want to convert int to a pointer. FORCEINLINE bool operator==(int value) const { return !!(this->m_value == TYPE((void*)(SIZE_T)value)); } FORCEINLINE bool operator!=(int value) const { return !!(this->m_value != TYPE((void*)(SIZE_T)value)); } FORCEINLINE const TYPE &operator->() const { return this->m_value; } FORCEINLINE int operator!() const { return this->IsNull(); } private: HIDE_GENERATED_METHODS(BaseWrapper) }; // class BaseWrapper<> //----------------------------------------------------------------------------- // Generic templates to use to wrap up acquire/release functionality for Holder //----------------------------------------------------------------------------- template FORCEINLINE void DoNothing(TYPE value) { // @TODO: Due to prefast template problems, implementations of the DoNothing macro have been changed // Search by prefast, and remove them when prefast is ready } FORCEINLINE void DoNothing() { } // Prefast stuff.We should have DoNothing in the holder declaration, but currently // prefast doesnt support, it, so im stuffing all these here so if we need to change the template you can change // everything here. When prefast works, remove the following functions struct ConnectionCookie; FORCEINLINE void ConnectionCookieDoNothing(ConnectionCookie* p) { } class ComCallWrapper; FORCEINLINE void CCWHolderDoNothing(ComCallWrapper* p) { } FORCEINLINE void DispParamHolderDoNothing(VARIANT* p) { } FORCEINLINE void VariantPtrDoNothing(VARIANT* p) { } FORCEINLINE void VariantDoNothing(VARIANT) { } FORCEINLINE void ZeroDoNothing(VOID* p) { } class CtxEntry; FORCEINLINE void CtxEntryDoNothing(CtxEntry* p) { } struct RCW; FORCEINLINE void NewRCWHolderDoNothing(RCW*) { } // Prefast stuff.We should have DoNothing in the holder declaration FORCEINLINE void SafeArrayDoNothing(SAFEARRAY* p) { } //----------------------------------------------------------------------------- // Holder/Wrapper are the simplest way to define holders - they synthesizes a base class out of // function pointers //----------------------------------------------------------------------------- template class FunctionBase : protected HolderBase { friend class ClrDataAccess; protected: FORCEINLINE FunctionBase(TYPE value) : HolderBase(value) { } FORCEINLINE void DoAcquire() { ACQUIREF(this->m_value); } void DoRelease() { RELEASEF(this->m_value); } }; // class Function<> template < typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE), UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault, // For legacy compat (see EEJitManager::WriterLockHolder), where default ctor // causes ACQUIREF(DEFAULTVALUE), but ACQUIREF ignores the argument and // operates on static or global value instead. bool DEFAULT_CTOR_ACQUIRE = true > class Holder : public BaseHolder, DEFAULTVALUE, IS_NULL> { typedef BaseHolder, DEFAULTVALUE, IS_NULL> BaseT; public: FORCEINLINE Holder() : BaseT(TYPE(DEFAULTVALUE), DEFAULT_CTOR_ACQUIRE) { STATIC_CONTRACT_WRAPPER; } FORCEINLINE Holder(TYPE value) : BaseT(value) { STATIC_CONTRACT_WRAPPER; } FORCEINLINE Holder(TYPE value, BOOL takeOwnership) : BaseT(value, takeOwnership) { STATIC_CONTRACT_WRAPPER; } FORCEINLINE Holder& operator=(TYPE p) { STATIC_CONTRACT_WRAPPER; BaseT::operator=(p); return *this; } HIDE_GENERATED_METHODS(Holder) }; //--------------------------------------------------------------------------------------- // template < typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE), UINT_PTR DEFAULTVALUE = 0, BOOL IS_NULL(TYPE, TYPE) = CompareDefault, // For legacy compat (see EEJitManager::WriterLockHolder), where default ctor // causes ACQUIREF(DEFAULTVALUE), but ACQUIREF ignores the argument and // operates on static or global value instead. bool DEFAULT_CTOR_ACQUIRE = true > class Wrapper : public BaseWrapper, DEFAULTVALUE, IS_NULL> { typedef BaseWrapper, DEFAULTVALUE, IS_NULL> BaseT; public: FORCEINLINE Wrapper() : BaseT(TYPE(DEFAULTVALUE), DEFAULT_CTOR_ACQUIRE) { STATIC_CONTRACT_WRAPPER; } FORCEINLINE Wrapper(TYPE value) : BaseT(value) { STATIC_CONTRACT_WRAPPER; } FORCEINLINE Wrapper(TYPE value, BOOL takeOwnership) : BaseT(value, takeOwnership) { STATIC_CONTRACT_WRAPPER; } FORCEINLINE Wrapper& operator=(TYPE const & value) { STATIC_CONTRACT_WRAPPER; BaseT::operator=(value); return *this; } HIDE_GENERATED_METHODS(Wrapper) }; // Wrapper<> //--------------------------------------------------------------------------------------- // - Cannot use the standard INDEBUG macro: holder.h is used in places where INDEBUG is defined in the nonstandard way #if defined(_DEBUG) #define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) x #else #define INDEBUG_AND_WINDOWS_FOR_HOLDERS(x) #endif template class SpecializedWrapper : public Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL> { using BaseT = Wrapper<_TYPE*, DoNothing<_TYPE*>, _RELEASEF, NULL>; public: FORCEINLINE SpecializedWrapper() : BaseT(NULL, FALSE) { STATIC_CONTRACT_WRAPPER; INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) } FORCEINLINE SpecializedWrapper(_TYPE* value) : BaseT(value) { STATIC_CONTRACT_WRAPPER; INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) } FORCEINLINE SpecializedWrapper(_TYPE* value, BOOL takeOwnership) : BaseT(value, takeOwnership) { STATIC_CONTRACT_WRAPPER; INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) } FORCEINLINE ~SpecializedWrapper() { } SpecializedWrapper(SpecializedWrapper const &) = delete; SpecializedWrapper & operator=(SpecializedWrapper const &) = delete; FORCEINLINE SpecializedWrapper& operator=(_TYPE * value) { STATIC_CONTRACT_WRAPPER; BaseT::operator=(value); return *this; } FORCEINLINE SpecializedWrapper(SpecializedWrapper && other) : BaseT(NULL, FALSE) { STATIC_CONTRACT_WRAPPER; INDEBUG_AND_WINDOWS_FOR_HOLDERS(m_pvalue = &this->m_value;) *this = std::move(other); } FORCEINLINE SpecializedWrapper& operator=(SpecializedWrapper && other) { BaseT::m_value = std::move(other.BaseT::m_value); BaseT::m_acquired = std::move(other.BaseT::m_acquired); other.BaseT::m_value = nullptr; other.BaseT::m_acquired = FALSE; return *this; } /* Since operator& is overloaded we need a way to get a type safe this pointer. */ FORCEINLINE SpecializedWrapper* GetAddr() { STATIC_CONTRACT_LEAF; return this; } private: /* m_ppValue: Do not use from source code: Only for convenient use from debugger */ /* watch windows - saves five mouseclicks when inspecting holders. */ INDEBUG_AND_WINDOWS_FOR_HOLDERS(_TYPE ** m_pvalue;) }; //----------------------------------------------------------------------------- // NOTE: THIS IS UNSAFE TO USE IN THE VM for interop COM objects!! // WE DO NOT CORRECTLY CHANGE TO PREEMPTIVE MODE BEFORE CALLING RELEASE!! // USE SafeComHolder // // ReleaseHolder : COM Interface holder for use outside the VM (or on well known instances // which do not need preemptive Relesae) // // Usage example: // // { // ReleaseHolder foo; // hr = FunctionToGetRefOfFoo(&foo); // // Note ComHolder doesn't call AddRef - it assumes you already have a ref (if non-0). // } // foo->Release() on out of scope (WITHOUT RESPECT FOR GC MODE!!) // //----------------------------------------------------------------------------- template FORCEINLINE void DoTheRelease(TYPE *value) { if (value) { value->Release(); } } template using DoNothingHolder = SpecializedWrapper<_TYPE, DoNothing<_TYPE*>>; template using ReleaseHolder = SpecializedWrapper<_TYPE, DoTheRelease<_TYPE>>; template using NonVMComHolder = SpecializedWrapper<_TYPE, DoTheRelease<_TYPE>>; //----------------------------------------------------------------------------- // StubHolder : holder for stubs // // Usage example: // // { // StubHolder foo; // foo = new Stub(); // foo->AddRef(); // // Note StubHolder doesn't call AddRef for you. // } // foo->DecRef() on out of scope // //----------------------------------------------------------------------------- template class ExecutableWriterHolderNoLog; class ExecutableAllocator; template FORCEINLINE void StubRelease(TYPE* value) { if (value) { #ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS #ifdef TARGET_UNIX LOGGER::LogUsage(__FILE__, __LINE__, __PRETTY_FUNCTION__); #else LOGGER::LogUsage(__FILE__, __LINE__, __FUNCTION__); #endif #endif // LOG_EXECUTABLE_ALLOCATOR_STATISTICS ExecutableWriterHolderNoLog stubWriterHolder(value, sizeof(TYPE)); stubWriterHolder.GetRW()->DecRef(); } } template using StubHolder = SpecializedWrapper<_TYPE, StubRelease<_TYPE>>; //----------------------------------------------------------------------------- // CoTaskMemHolder : CoTaskMemAlloc allocated memory holder // // { // CoTaskMemHolder foo = (Foo*) CoTaskMemAlloc(sizeof(Foo)); // } // delete foo on out of scope //----------------------------------------------------------------------------- template FORCEINLINE void DeleteCoTaskMem(TYPE *value) { if (value) CoTaskMemFree(value); } template using CoTaskMemHolder = SpecializedWrapper<_TYPE, DeleteCoTaskMem<_TYPE>>; //----------------------------------------------------------------------------- // NewHolder : New'ed memory holder // // { // NewHolder foo = new Foo (); // } // delete foo on out of scope //----------------------------------------------------------------------------- template FORCEINLINE void Delete(TYPE *value) { STATIC_CONTRACT_LEAF; static_assert(!std::is_same::type, WCHAR>::value, "Must use NewArrayHolder (not NewHolder) for strings."); static_assert(!std::is_same::type, CHAR>::value, "Must use NewArrayHolder (not NewHolder) for strings."); delete value; } template using NewHolder = SpecializedWrapper<_TYPE, Delete<_TYPE>>; //----------------------------------------------------------------------------- // NewExecutableHolder : New'ed memory holder for executable memory. // // { // NewExecutableHolder foo = (Foo*) new (executable) Byte[num]; // } // delete foo on out of scope //----------------------------------------------------------------------------- // IJW template void DeleteExecutable(T *p); template using NewExecutableHolder = SpecializedWrapper<_TYPE, DeleteExecutable<_TYPE>>; //----------------------------------------------------------------------------- // NewArrayHolder : New []'ed pointer holder // { // NewArrayHolder foo = new Foo [30]; // } // delete [] foo on out of scope //----------------------------------------------------------------------------- template FORCEINLINE void DeleteArray(TYPE *value) { STATIC_CONTRACT_WRAPPER; delete [] value; value = NULL; } template using NewArrayHolder = SpecializedWrapper<_TYPE, DeleteArray<_TYPE>>; typedef NewArrayHolder AStringHolder; typedef NewArrayHolder WStringHolder; //----------------------------------------------------------------------------- // A special array holder that expects its contents are interface pointers, // and will call Release() on them. // // NOTE: You may ONLY use this if you've determined that it is SAFE to call // Release() on the contained interface pointers (e.g., as opposed to SafeRelease) // template class NewInterfaceArrayHolder : public NewArrayHolder { public: NewInterfaceArrayHolder() : NewArrayHolder(), m_cElements(0) { STATIC_CONTRACT_WRAPPER; } NewInterfaceArrayHolder& operator=(INTERFACE ** value) { STATIC_CONTRACT_WRAPPER; NewArrayHolder::operator=(value); return *this; } void SetElementCount(ULONG32 cElements) { STATIC_CONTRACT_LEAF; m_cElements = cElements; } ~NewInterfaceArrayHolder() { STATIC_CONTRACT_LEAF; for (ULONG32 i=0; i < m_cElements; i++) { if (this->m_value[i] != NULL) this->m_value[i]->Release(); } } protected: ULONG32 m_cElements; }; //----------------------------------------------------------------------------- // ResetPointerHolder : pointer which needs to be set to NULL // { // ResetPointerHolder holder = &pFoo; // } // "*pFoo=NULL" on out of scope //----------------------------------------------------------------------------- #ifdef __GNUC__ // With -fvisibility-inlines-hidden, the Invoke methods below // get hidden, which causes warnings when visible classes expose them. #define VISIBLE __attribute__ ((visibility("default"))) #else #define VISIBLE #endif // __GNUC__ namespace detail { template struct ZeroMem { static VISIBLE void Invoke(T * pVal) { ZeroMemory(pVal, sizeof(T)); } }; template struct ZeroMem { static VISIBLE void Invoke(T ** pVal) { *pVal = NULL; } }; } #undef VISIBLE template using ResetPointerHolder = SpecializedWrapper<_TYPE, detail::ZeroMem<_TYPE>::Invoke>; template using FieldNuller = SpecializedWrapper<_TYPE, detail::ZeroMem<_TYPE>::Invoke>; //----------------------------------------------------------------------------- // Wrap win32 functions using HANDLE //----------------------------------------------------------------------------- FORCEINLINE void VoidCloseHandle(HANDLE h) { if (h != NULL) CloseHandle(h); } // (UINT_PTR) -1 is INVALID_HANDLE_VALUE FORCEINLINE void VoidCloseFileHandle(HANDLE h) { if (h != ((HANDLE)((LONG_PTR) -1))) CloseHandle(h); } FORCEINLINE void VoidFindClose(HANDLE h) { FindClose(h); } FORCEINLINE void VoidUnmapViewOfFile(void *ptr) { UnmapViewOfFile(ptr); } template FORCEINLINE void TypeUnmapViewOfFile(TYPE *ptr) { UnmapViewOfFile(ptr); } // (UINT_PTR) -1 is INVALID_HANDLE_VALUE //@TODO: Dangerous default value. Some Win32 functions return INVALID_HANDLE_VALUE, some return NULL (such as CreatEvent). typedef Wrapper, VoidCloseHandle, (UINT_PTR) -1> HandleHolder; typedef Wrapper, VoidCloseFileHandle, (UINT_PTR) -1> FileHandleHolder; typedef Wrapper, VoidFindClose, (UINT_PTR) -1> FindHandleHolder; typedef Wrapper MapViewHolder; //----------------------------------------------------------------------------- // Misc holders //----------------------------------------------------------------------------- // A holder for HMODULE. FORCEINLINE void HolderFreeLibrary(HMODULE h) { FreeLibrary(h); } typedef Wrapper, HolderFreeLibrary, NULL> HModuleHolder; template FORCEINLINE void DoLocalFree(T* pMem) { #ifdef HOST_WINDOWS (LocalFree)((void*)pMem); #else (free)((void*)pMem); #endif } template using LocalAllocHolder = SpecializedWrapper<_TYPE, DoLocalFree<_TYPE>>; inline void BoolSet( _Out_ bool * val ) { *val = true; } inline void BoolUnset( _Out_ bool * val ) { *val = false; } typedef Wrapper< bool *, BoolSet, BoolUnset > BoolFlagStateHolder; // // We need the following methods to have volatile arguments, so that they can accept // raw pointers in addition to the results of the & operator on Volatile. // FORCEINLINE void CounterIncrease(RAW_KEYWORD(volatile) LONG* p) {InterlockedIncrement(p);}; FORCEINLINE void CounterDecrease(RAW_KEYWORD(volatile) LONG* p) {InterlockedDecrement(p);}; typedef Wrapper> CounterHolder; #ifdef HOST_WINDOWS FORCEINLINE void RegKeyRelease(HKEY k) {RegCloseKey(k);}; typedef Wrapper RegKeyHolder; #endif // HOST_WINDOWS class ErrorModeHolder { UINT m_oldMode; public: ErrorModeHolder(UINT newMode){m_oldMode=SetErrorMode(newMode);}; ~ErrorModeHolder(){SetErrorMode(m_oldMode);}; UINT OldMode() {return m_oldMode;}; }; #ifdef HOST_WINDOWS //----------------------------------------------------------------------------- // HKEYHolder : HKEY holder, Calls RegCloseKey on scope exit. // // { // HKEYHolder hFoo = NULL; // WszRegOpenKeyEx(HKEY_CLASSES_ROOT, L"Interface",0, KEY_READ, hFoo); // // } // close key on out of scope via RegCloseKey. //----------------------------------------------------------------------------- class HKEYHolder { public: HKEYHolder() { STATIC_CONTRACT_LEAF; m_value = 0; } ~HKEYHolder() { STATIC_CONTRACT_WRAPPER; if (m_value != NULL) ::RegCloseKey(m_value); } FORCEINLINE void operator=(HKEY p) { STATIC_CONTRACT_LEAF; if (p != 0) m_value = p; } FORCEINLINE operator HKEY() { STATIC_CONTRACT_LEAF; return m_value; } FORCEINLINE operator HKEY*() { STATIC_CONTRACT_LEAF; return &m_value; } FORCEINLINE HKEY* operator&() { STATIC_CONTRACT_LEAF; return &m_value; } private: HKEY m_value; }; #endif // HOST_WINDOWS //---------------------------------------------------------------------------- // // External data access does not want certain holder implementations // to be active as locks should not be taken and so on. Provide // a no-op in that case. // //---------------------------------------------------------------------------- #ifndef DACCESS_COMPILE #define DacHolder Holder #else template , BOOL VALIDATE_BACKOUT_STACK = TRUE> class DacHolder { protected: TYPE m_value; private: BOOL m_acquired; // Have we acquired the resource? public: FORCEINLINE DacHolder() : m_value(TYPE(DEFAULTVALUE)), m_acquired(FALSE) { STATIC_CONTRACT_SUPPORTS_DAC; } // construct a new instance of DacHolder // Arguments: // input: value - the resource held // take - indicates whether the lock should be taken--the default is true. See Notes: // Note: In DAC builds, the Acquire function does not actually take the lock, instead // it determines whether the lock is held (by the LS). If it is, the locked data // is assumed to be inconsistent and the Acquire function will throw. FORCEINLINE DacHolder(TYPE value, BOOL take = TRUE) : m_value(value), m_acquired(FALSE) { STATIC_CONTRACT_SUPPORTS_DAC; if (take) Acquire(); } FORCEINLINE ~DacHolder() { STATIC_CONTRACT_SUPPORTS_DAC; } // Sets the value to 'value'. Doesn't call Acquire/Release if fTake is FALSE. FORCEINLINE void Assign(TYPE value, BOOL fTake = TRUE) { m_value = value; } FORCEINLINE void Acquire() { STATIC_CONTRACT_SUPPORTS_DAC; if (!IsNull()) { m_acquired = TRUE; // because ACQUIRE is a template argument, if the line m_acquired = TRUE is placed after the call // where it logically belongs, the compiler flags it as "unreachable code." ACQUIRE(this->m_value); } } FORCEINLINE void Release() { // Insert any global or thread bookkeeping here if (m_acquired) { m_acquired = FALSE; } } FORCEINLINE void Clear() { m_value = TYPE(DEFAULTVALUE); m_acquired = FALSE; } FORCEINLINE void SuppressRelease() { m_acquired = FALSE; } FORCEINLINE TYPE GetValue() { return m_value; } FORCEINLINE BOOL IsNull() const { return IS_NULL(m_value, TYPE(DEFAULTVALUE)); } private: FORCEINLINE DacHolder& operator=(const Holder &holder) { } FORCEINLINE DacHolder(const Holder &holder) { } }; #endif // #ifndef DACCESS_COMPILE // Holder-specific clr::SafeAddRef and clr::SafeRelease helper functions. namespace clr { // Copied from utilcode.h. We can't include the header directly because there // is circular reference. // Forward declare the overload which is used by 'SafeAddRef' below. template static inline typename std::enable_if< std::is_pointer::value, ItfT >::type SafeAddRef(ItfT pItf); template < typename ItfT > __checkReturn ItfT * SafeAddRef(ReleaseHolder & pItf) { STATIC_CONTRACT_LIMITED_METHOD; //@TODO: Would be good to add runtime validation that the return value is used. return SafeAddRef(pItf.GetValue()); } namespace detail { template char IsHolderHelper(HolderBase*); int IsHolderHelper(...); template struct IsHolder : public std::conditional< sizeof(IsHolderHelper(reinterpret_cast(NULL))) == sizeof(char), std::true_type, std::false_type>::type {}; } template < typename T > typename std::enable_if::value, ULONG>::type SafeRelease(T& arg) { STATIC_CONTRACT_LIMITED_METHOD; return arg.Release(); } } #endif // __HOLDER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/iallocator.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // We would like to allow "util" collection classes to be usable both // from the VM and from the JIT. The latter case presents a // difficulty, because in the (x86, soon to be cross-platform) JIT // compiler, we require allocation to be done using a "no-release" // (aka, arena-style) allocator that is provided as methods of the // JIT's Compiler type. // To allow utilcode collection classes to deal with this, they may be // written to do allocation and freeing via an instance of the // "IAllocator" class defined in this file. // #ifndef _IALLOCATOR_DEFINED_ #define _IALLOCATOR_DEFINED_ #include "contract.h" #include "safemath.h" class IAllocator { public: virtual void* Alloc(size_t sz) = 0; // Allocate space for an array of "elems" elements, each of size "elemSize". virtual void* ArrayAlloc(size_t elems, size_t elemSize) = 0; virtual void Free(void* p) = 0; }; #endif // _IALLOCATOR_DEFINED_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/iceefilegen.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** ICeeFileGen.h - code generator interface. ** ** ** ** This interface provides functionality to create a CLR PE executable. ** ** This will typically be used by compilers to generate their compiled ** ** output executable. ** ** ** *****************************************************************************/ /* This is how this is typically used: // Step #1 ... Get CLR hosting API: #include #include ICLRMetaHost * pMetaHost; CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, &pMetaHost); // defined in mscoree.h ICLRRuntimeInfo * pCLRRuntimeInfo; pMetaHost->GetRuntime(wszClrVersion, IID_ICLRRuntimeInfo, &pCLRRuntimeInfo); // Step #2 ... use mscorpe APIs to create a file generator CreateICeeFileGen(...); // Get a ICeeFileGen CreateCeeFile(...); // Get a HCEEFILE (called for every output file needed) SetOutputFileName(...); // Set the name for the output file pEmit = IMetaDataEmit object; // Get a metadata emitter GetSectionBlock(...);, AddSectionReloc(...); ... // Get blocks, write non-metadata information, and add necessary relocation EmitMetaDataEx(pEmit); // Write out the metadata GenerateCeeFile(...); // Write out the file. DestroyICeeFileGen(...); // Release the ICeeFileGen object */ #ifndef _ICEEFILEGEN_H_ #define _ICEEFILEGEN_H_ #include #include "corpriv.h" class ICeeFileGen; typedef void *HCEEFILE; EXTERN_C HRESULT __stdcall CreateICeeFileGen(ICeeFileGen** pCeeFileGen); EXTERN_C HRESULT __stdcall DestroyICeeFileGen(ICeeFileGen ** ppCeeFileGen); typedef HRESULT (__stdcall * PFN_CreateICeeFileGen)(ICeeFileGen ** ceeFileGen); // call this to instantiate an ICeeFileGen interface typedef HRESULT (__stdcall * PFN_DestroyICeeFileGen)(ICeeFileGen ** ceeFileGen); // call this to delete an ICeeFileGen #define ICEE_CREATE_FILE_PE32 0x00000001 // Create a PE (32-bit) #define ICEE_CREATE_FILE_PE64 0x00000002 // Create a PE+ (64-bit) #define ICEE_CREATE_FILE_CORMAIN_STUB 0x00000004 // add a mscoree!_Cor___Main call stub #define ICEE_CREATE_FILE_STRIP_RELOCS 0x00000008 // strip the .reloc section #define ICEE_CREATE_MACHINE_MASK 0x0000FF00 // space for up to 256 machine targets (note: most users just do a bit check, not an equality compare after applying the mask) #define ICEE_CREATE_MACHINE_ILLEGAL 0x00000000 // An illegal machine name #define ICEE_CREATE_MACHINE_I386 0x00000100 // Create a IMAGE_FILE_MACHINE_I386 #define ICEE_CREATE_MACHINE_IA64 0x00000200 // Create a IMAGE_FILE_MACHINE_IA64 #define ICEE_CREATE_MACHINE_AMD64 0x00000400 // Create a IMAGE_FILE_MACHINE_AMD64 #define ICEE_CREATE_MACHINE_ARM 0x00000800 // Create a IMAGE_FILE_MACHINE_ARMNT #define ICEE_CREATE_MACHINE_ARM64 0x00001000 // Create a IMAGE_FILE_MACHINE_ARM64 // Pass this to CreateCeeFileEx to create a pure IL Exe or DLL #define ICEE_CREATE_FILE_PURE_IL ICEE_CREATE_FILE_PE32 | \ ICEE_CREATE_FILE_CORMAIN_STUB | \ ICEE_CREATE_MACHINE_I386 class ICeeFileGen { public: virtual ~ICeeFileGen() = default; virtual HRESULT CreateCeeFile(HCEEFILE *ceeFile); // call this to instantiate a file handle virtual HRESULT GetMethodRVA (HCEEFILE ceeFile, ULONG codeOffset, ULONG *codeRVA); virtual HRESULT EmitString (HCEEFILE ceeFile,_In_ LPWSTR strValue, ULONG *strRef); virtual HRESULT GenerateCeeFile (HCEEFILE ceeFile); virtual HRESULT SetOutputFileName (HCEEFILE ceeFile, _In_ LPWSTR outputFileName); _Return_type_success_(return == S_OK) virtual HRESULT GetOutputFileName (HCEEFILE ceeFile, _Out_ LPWSTR *outputFileName); virtual HRESULT SetResourceFileName (HCEEFILE ceeFile, _In_ LPWSTR resourceFileName); _Return_type_success_(return == S_OK) virtual HRESULT GetResourceFileName (HCEEFILE ceeFile, _Out_ LPWSTR *resourceFileName); virtual HRESULT SetImageBase(HCEEFILE ceeFile, size_t imageBase); virtual HRESULT SetSubsystem(HCEEFILE ceeFile, DWORD subsystem, DWORD major, DWORD minor); virtual HRESULT SetDllSwitch (HCEEFILE ceeFile, BOOL dllSwitch); virtual HRESULT GetDllSwitch (HCEEFILE ceeFile, BOOL *dllSwitch); virtual HRESULT DestroyCeeFile(HCEEFILE *ceeFile); // call this to delete a file handle virtual HRESULT GetSectionCreate (HCEEFILE ceeFile, const char *name, DWORD flags, HCEESECTION *section); virtual HRESULT GetIlSection (HCEEFILE ceeFile, HCEESECTION *section); virtual HRESULT GetRdataSection (HCEEFILE ceeFile, HCEESECTION *section); virtual HRESULT GetSectionDataLen (HCEESECTION section, ULONG *dataLen); virtual HRESULT GetSectionBlock (HCEESECTION section, ULONG len, ULONG align=1, void **ppBytes=0); virtual HRESULT AddSectionReloc (HCEESECTION section, ULONG offset, HCEESECTION relativeTo, CeeSectionRelocType relocType); virtual HRESULT SetEntryPoint (HCEEFILE ceeFile, mdMethodDef method); virtual HRESULT GetEntryPoint (HCEEFILE ceeFile, mdMethodDef *method); virtual HRESULT SetComImageFlags (HCEEFILE ceeFile, DWORD mask); virtual HRESULT GetComImageFlags (HCEEFILE ceeFile, DWORD *mask); // get IMapToken interface for tracking mapped tokens virtual HRESULT GetIMapTokenIface(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); virtual HRESULT SetDirectoryEntry (HCEEFILE ceeFile, HCEESECTION section, ULONG num, ULONG size, ULONG offset = 0); // Write out the metadata in "emitter" to the metadata section in "ceeFile" // Use EmitMetaDataAt() for more control virtual HRESULT EmitMetaDataEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); virtual HRESULT GetIMapTokenIfaceEx(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); virtual HRESULT CreateCeeFileFromICeeGen( ICeeGenInternal *pFromICeeGen, HCEEFILE *ceeFile, DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); // call this to instantiate a file handle virtual HRESULT SetManifestEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); virtual HRESULT ComputeSectionOffset(HCEESECTION section, _In_ char *ptr, unsigned *offset); virtual HRESULT ComputeOffset(HCEEFILE file, _In_ char *ptr, HCEESECTION *pSection, unsigned *offset); virtual HRESULT GetCorHeader(HCEEFILE ceeFile, IMAGE_COR20_HEADER **header); // Layout the sections and assign their starting addresses virtual HRESULT LinkCeeFile (HCEEFILE ceeFile); // Base RVA assinged to the section. To be called only after LinkCeeFile() virtual HRESULT GetSectionRVA (HCEESECTION section, ULONG *rva); _Return_type_success_(return == S_OK) virtual HRESULT ComputeSectionPointer(HCEESECTION section, ULONG offset, _Out_ char **ptr); virtual HRESULT SetVTableEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); // See the end of interface for another overload of AetVTableEntry virtual HRESULT SetStrongNameEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); // Emit the metadata from "emitter". // If 'section != 0, it will put the data in 'buffer'. This // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen' // (should use GetSaveSize to insure that buffer is big enough virtual HRESULT EmitMetaDataAt (HCEEFILE ceeFile, IMetaDataEmit *emitter, HCEESECTION section, DWORD offset, BYTE* buffer, unsigned buffLen); virtual HRESULT GetFileTimeStamp (HCEEFILE ceeFile, DWORD *pTimeStamp); // Add a notification handler. If it implements an interface that // the ICeeFileGen understands, S_OK is returned. Otherwise, // E_NOINTERFACE. virtual HRESULT AddNotificationHandler(HCEEFILE ceeFile, IUnknown *pHandler); virtual HRESULT SetFileAlignment(HCEEFILE ceeFile, ULONG fileAlignment); virtual HRESULT ClearComImageFlags (HCEEFILE ceeFile, DWORD mask); // call this to instantiate a PE+ (64-bit PE file) virtual HRESULT CreateCeeFileEx(HCEEFILE *ceeFile, ULONG createFlags); virtual HRESULT SetImageBase64(HCEEFILE ceeFile, ULONGLONG imageBase); virtual HRESULT GetHeaderInfo (HCEEFILE ceeFile, PIMAGE_NT_HEADERS *ppNtHeaders, PIMAGE_SECTION_HEADER *ppSections, ULONG *pNumSections); // Seed file is a base file which is copied over into the output file // Note that there are restrictions on the seed file (the sections // cannot be relocated), and that the copy is not complete as the new // headers overwrite the seed file headers. virtual HRESULT CreateCeeFileEx2(HCEEFILE *ceeFile, ULONG createFlags, LPCWSTR seedFileName = NULL); virtual HRESULT SetVTableEntry64(HCEEFILE ceeFile, ULONG size, void* ptr); }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/icorjitinfoimpl_generated.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // DO NOT EDIT THIS FILE! IT IS AUTOGENERATED // To regenerate run the gen script in src/coreclr/tools/Common/JitInterface/ThunkGenerator // and follow the instructions in docs/project/updating-jitinterface.md // ICorJitInfoImpl: declare for implementation all the members of the ICorJitInfo interface (which are // specified as pure virtual methods). This is done once, here, and all implementations share it, // to avoid duplicated declarations. This file is #include'd within all the ICorJitInfo implementation // classes. // // NOTE: this file is in exactly the same order, with exactly the same whitespace, as the ICorJitInfo // interface declaration (with the "virtual" and "= 0" syntax removed). This is to make it easy to compare // against the interface declaration. /**********************************************************************************/ // clang-format off /**********************************************************************************/ public: bool isIntrinsic( CORINFO_METHOD_HANDLE ftn) override; uint32_t getMethodAttribs( CORINFO_METHOD_HANDLE ftn) override; void setMethodAttribs( CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs) override; void getMethodSig( CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO* sig, CORINFO_CLASS_HANDLE memberParent) override; bool getMethodInfo( CORINFO_METHOD_HANDLE ftn, CORINFO_METHOD_INFO* info) override; CorInfoInline canInline( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd) override; void beginInlining( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd) override; void reportInliningDecision( CORINFO_METHOD_HANDLE inlinerHnd, CORINFO_METHOD_HANDLE inlineeHnd, CorInfoInline inlineResult, const char* reason) override; bool canTailCall( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE declaredCalleeHnd, CORINFO_METHOD_HANDLE exactCalleeHnd, bool fIsTailPrefix) override; void reportTailCallDecision( CORINFO_METHOD_HANDLE callerHnd, CORINFO_METHOD_HANDLE calleeHnd, bool fIsTailPrefix, CorInfoTailCall tailCallResult, const char* reason) override; void getEHinfo( CORINFO_METHOD_HANDLE ftn, unsigned EHnumber, CORINFO_EH_CLAUSE* clause) override; CORINFO_CLASS_HANDLE getMethodClass( CORINFO_METHOD_HANDLE method) override; CORINFO_MODULE_HANDLE getMethodModule( CORINFO_METHOD_HANDLE method) override; void getMethodVTableOffset( CORINFO_METHOD_HANDLE method, unsigned* offsetOfIndirection, unsigned* offsetAfterIndirection, bool* isRelative) override; bool resolveVirtualMethod( CORINFO_DEVIRTUALIZATION_INFO* info) override; CORINFO_METHOD_HANDLE getUnboxedEntry( CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg) override; CORINFO_CLASS_HANDLE getDefaultComparerClass( CORINFO_CLASS_HANDLE elemType) override; CORINFO_CLASS_HANDLE getDefaultEqualityComparerClass( CORINFO_CLASS_HANDLE elemType) override; void expandRawHandleIntrinsic( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_GENERICHANDLE_RESULT* pResult) override; bool isIntrinsicType( CORINFO_CLASS_HANDLE classHnd) override; CorInfoCallConvExtension getUnmanagedCallConv( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig, bool* pSuppressGCTransition) override; bool pInvokeMarshalingRequired( CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig) override; bool satisfiesMethodConstraints( CORINFO_CLASS_HANDLE parent, CORINFO_METHOD_HANDLE method) override; bool isCompatibleDelegate( CORINFO_CLASS_HANDLE objCls, CORINFO_CLASS_HANDLE methodParentCls, CORINFO_METHOD_HANDLE method, CORINFO_CLASS_HANDLE delegateCls, bool* pfIsOpenDelegate) override; void methodMustBeLoadedBeforeCodeIsRun( CORINFO_METHOD_HANDLE method) override; CORINFO_METHOD_HANDLE mapMethodDeclToMethodImpl( CORINFO_METHOD_HANDLE method) override; void getGSCookie( GSCookie* pCookieVal, GSCookie** ppCookieVal) override; void setPatchpointInfo( PatchpointInfo* patchpointInfo) override; PatchpointInfo* getOSRInfo( unsigned* ilOffset) override; void resolveToken( CORINFO_RESOLVED_TOKEN* pResolvedToken) override; bool tryResolveToken( CORINFO_RESOLVED_TOKEN* pResolvedToken) override; void findSig( CORINFO_MODULE_HANDLE module, unsigned sigTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* sig) override; void findCallSiteSig( CORINFO_MODULE_HANDLE module, unsigned methTOK, CORINFO_CONTEXT_HANDLE context, CORINFO_SIG_INFO* sig) override; CORINFO_CLASS_HANDLE getTokenTypeAsHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken) override; bool isValidToken( CORINFO_MODULE_HANDLE module, unsigned metaTOK) override; bool isValidStringRef( CORINFO_MODULE_HANDLE module, unsigned metaTOK) override; int getStringLiteral( CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize, int startIndex) override; size_t printObjectDescription( CORINFO_OBJECT_HANDLE handle, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) override; CorInfoType asCorInfoType( CORINFO_CLASS_HANDLE cls) override; const char* getClassNameFromMetadata( CORINFO_CLASS_HANDLE cls, const char** namespaceName) override; CORINFO_CLASS_HANDLE getTypeInstantiationArgument( CORINFO_CLASS_HANDLE cls, unsigned index) override; size_t printClassName( CORINFO_CLASS_HANDLE cls, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) override; bool isValueClass( CORINFO_CLASS_HANDLE cls) override; CorInfoInlineTypeCheck canInlineTypeCheck( CORINFO_CLASS_HANDLE cls, CorInfoInlineTypeCheckSource source) override; uint32_t getClassAttribs( CORINFO_CLASS_HANDLE cls) override; CORINFO_MODULE_HANDLE getClassModule( CORINFO_CLASS_HANDLE cls) override; CORINFO_ASSEMBLY_HANDLE getModuleAssembly( CORINFO_MODULE_HANDLE mod) override; const char* getAssemblyName( CORINFO_ASSEMBLY_HANDLE assem) override; void* LongLifetimeMalloc( size_t sz) override; void LongLifetimeFree( void* obj) override; size_t getClassModuleIdForStatics( CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE* pModule, void** ppIndirection) override; unsigned getClassSize( CORINFO_CLASS_HANDLE cls) override; unsigned getHeapClassSize( CORINFO_CLASS_HANDLE cls) override; bool canAllocateOnStack( CORINFO_CLASS_HANDLE cls) override; unsigned getClassAlignmentRequirement( CORINFO_CLASS_HANDLE cls, bool fDoubleAlignHint) override; unsigned getClassGClayout( CORINFO_CLASS_HANDLE cls, uint8_t* gcPtrs) override; unsigned getClassNumInstanceFields( CORINFO_CLASS_HANDLE cls) override; CORINFO_FIELD_HANDLE getFieldInClass( CORINFO_CLASS_HANDLE clsHnd, int32_t num) override; bool checkMethodModifier( CORINFO_METHOD_HANDLE hMethod, const char* modifier, bool fOptional) override; CorInfoHelpFunc getNewHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, bool* pHasSideEffects) override; CorInfoHelpFunc getNewArrHelper( CORINFO_CLASS_HANDLE arrayCls) override; CorInfoHelpFunc getCastingHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fThrowing) override; CorInfoHelpFunc getSharedCCtorHelper( CORINFO_CLASS_HANDLE clsHnd) override; CORINFO_CLASS_HANDLE getTypeForBox( CORINFO_CLASS_HANDLE cls) override; CorInfoHelpFunc getBoxHelper( CORINFO_CLASS_HANDLE cls) override; CorInfoHelpFunc getUnBoxHelper( CORINFO_CLASS_HANDLE cls) override; CORINFO_OBJECT_HANDLE getRuntimeTypePointer( CORINFO_CLASS_HANDLE cls) override; bool isObjectImmutable( CORINFO_OBJECT_HANDLE objPtr) override; bool getStringChar( CORINFO_OBJECT_HANDLE strObj, int index, uint16_t* value) override; CORINFO_CLASS_HANDLE getObjectType( CORINFO_OBJECT_HANDLE objPtr) override; bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup) override; void getReadyToRunDelegateCtorHelper( CORINFO_RESOLVED_TOKEN* pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP* pLookup) override; CorInfoInitClassResult initClass( CORINFO_FIELD_HANDLE field, CORINFO_METHOD_HANDLE method, CORINFO_CONTEXT_HANDLE context) override; void classMustBeLoadedBeforeCodeIsRun( CORINFO_CLASS_HANDLE cls) override; CORINFO_CLASS_HANDLE getBuiltinClass( CorInfoClassId classId) override; CorInfoType getTypeForPrimitiveValueClass( CORINFO_CLASS_HANDLE cls) override; CorInfoType getTypeForPrimitiveNumericClass( CORINFO_CLASS_HANDLE cls) override; bool canCast( CORINFO_CLASS_HANDLE child, CORINFO_CLASS_HANDLE parent) override; bool areTypesEquivalent( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) override; TypeCompareState compareTypesForCast( CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass) override; TypeCompareState compareTypesForEquality( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) override; CORINFO_CLASS_HANDLE mergeClasses( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) override; bool isMoreSpecificType( CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) override; TypeCompareState isEnum( CORINFO_CLASS_HANDLE cls, CORINFO_CLASS_HANDLE* underlyingType) override; CORINFO_CLASS_HANDLE getParentType( CORINFO_CLASS_HANDLE cls) override; CorInfoType getChildType( CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet) override; bool satisfiesClassConstraints( CORINFO_CLASS_HANDLE cls) override; bool isSDArray( CORINFO_CLASS_HANDLE cls) override; unsigned getArrayRank( CORINFO_CLASS_HANDLE cls) override; CorInfoArrayIntrinsic getArrayIntrinsicID( CORINFO_METHOD_HANDLE ftn) override; void* getArrayInitializationData( CORINFO_FIELD_HANDLE field, uint32_t size) override; CorInfoIsAccessAllowedResult canAccessClass( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_HELPER_DESC* pAccessHelper) override; size_t printFieldName( CORINFO_FIELD_HANDLE field, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) override; CORINFO_CLASS_HANDLE getFieldClass( CORINFO_FIELD_HANDLE field) override; CorInfoType getFieldType( CORINFO_FIELD_HANDLE field, CORINFO_CLASS_HANDLE* structType, CORINFO_CLASS_HANDLE memberParent) override; unsigned getFieldOffset( CORINFO_FIELD_HANDLE field) override; void getFieldInfo( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult) override; bool isFieldStatic( CORINFO_FIELD_HANDLE fldHnd) override; int getArrayOrStringLength( CORINFO_OBJECT_HANDLE objHnd) override; void getBoundaries( CORINFO_METHOD_HANDLE ftn, unsigned int* cILOffsets, uint32_t** pILOffsets, ICorDebugInfo::BoundaryTypes* implicitBoundaries) override; void setBoundaries( CORINFO_METHOD_HANDLE ftn, uint32_t cMap, ICorDebugInfo::OffsetMapping* pMap) override; void getVars( CORINFO_METHOD_HANDLE ftn, uint32_t* cVars, ICorDebugInfo::ILVarInfo** vars, bool* extendOthers) override; void setVars( CORINFO_METHOD_HANDLE ftn, uint32_t cVars, ICorDebugInfo::NativeVarInfo* vars) override; void reportRichMappings( ICorDebugInfo::InlineTreeNode* inlineTreeNodes, uint32_t numInlineTreeNodes, ICorDebugInfo::RichOffsetMapping* mappings, uint32_t numMappings) override; void* allocateArray( size_t cBytes) override; void freeArray( void* array) override; CORINFO_ARG_LIST_HANDLE getArgNext( CORINFO_ARG_LIST_HANDLE args) override; CorInfoTypeWithMod getArgType( CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args, CORINFO_CLASS_HANDLE* vcTypeRet) override; int getExactClasses( CORINFO_CLASS_HANDLE baseType, int maxExactClasses, CORINFO_CLASS_HANDLE* exactClsRet) override; CORINFO_CLASS_HANDLE getArgClass( CORINFO_SIG_INFO* sig, CORINFO_ARG_LIST_HANDLE args) override; CorInfoHFAElemType getHFAType( CORINFO_CLASS_HANDLE hClass) override; JITINTERFACE_HRESULT GetErrorHRESULT( struct _EXCEPTION_POINTERS* pExceptionPointers) override; uint32_t GetErrorMessage( char16_t* buffer, uint32_t bufferLength) override; int FilterException( struct _EXCEPTION_POINTERS* pExceptionPointers) override; void ThrowExceptionForJitResult( JITINTERFACE_HRESULT result) override; void ThrowExceptionForHelper( const CORINFO_HELPER_DESC* throwHelper) override; bool runWithErrorTrap( ICorJitInfo::errorTrapFunction function, void* parameter) override; bool runWithSPMIErrorTrap( ICorJitInfo::errorTrapFunction function, void* parameter) override; void getEEInfo( CORINFO_EE_INFO* pEEInfoOut) override; const char16_t* getJitTimeLogFilename() override; mdMethodDef getMethodDefFromMethod( CORINFO_METHOD_HANDLE hMethod) override; size_t printMethodName( CORINFO_METHOD_HANDLE ftn, char* buffer, size_t bufferSize, size_t* pRequiredBufferSize) override; const char* getMethodNameFromMetadata( CORINFO_METHOD_HANDLE ftn, const char** className, const char** namespaceName, const char** enclosingClassName) override; unsigned getMethodHash( CORINFO_METHOD_HANDLE ftn) override; size_t findNameOfToken( CORINFO_MODULE_HANDLE moduleHandle, mdToken token, char* szFQName, size_t FQNameCapacity) override; bool getSystemVAmd64PassStructInRegisterDescriptor( CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) override; uint32_t getLoongArch64PassStructInRegisterFlags( CORINFO_CLASS_HANDLE structHnd) override; uint32_t getThreadTLSIndex( void** ppIndirection) override; const void* getInlinedCallFrameVptr( void** ppIndirection) override; int32_t* getAddrOfCaptureThreadGlobal( void** ppIndirection) override; void* getHelperFtn( CorInfoHelpFunc ftnNum, void** ppIndirection) override; void getFunctionEntryPoint( CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP* pResult, CORINFO_ACCESS_FLAGS accessFlags) override; void getFunctionFixedEntryPoint( CORINFO_METHOD_HANDLE ftn, bool isUnsafeFunctionPointer, CORINFO_CONST_LOOKUP* pResult) override; void* getMethodSync( CORINFO_METHOD_HANDLE ftn, void** ppIndirection) override; CorInfoHelpFunc getLazyStringLiteralHelper( CORINFO_MODULE_HANDLE handle) override; CORINFO_MODULE_HANDLE embedModuleHandle( CORINFO_MODULE_HANDLE handle, void** ppIndirection) override; CORINFO_CLASS_HANDLE embedClassHandle( CORINFO_CLASS_HANDLE handle, void** ppIndirection) override; CORINFO_METHOD_HANDLE embedMethodHandle( CORINFO_METHOD_HANDLE handle, void** ppIndirection) override; CORINFO_FIELD_HANDLE embedFieldHandle( CORINFO_FIELD_HANDLE handle, void** ppIndirection) override; void embedGenericHandle( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fEmbedParent, CORINFO_GENERICHANDLE_RESULT* pResult) override; void getLocationOfThisType( CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND* pLookupKind) override; void getAddressOfPInvokeTarget( CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup) override; void* GetCookieForPInvokeCalliSig( CORINFO_SIG_INFO* szMetaSig, void** ppIndirection) override; bool canGetCookieForPInvokeCalliSig( CORINFO_SIG_INFO* szMetaSig) override; CORINFO_JUST_MY_CODE_HANDLE getJustMyCodeHandle( CORINFO_METHOD_HANDLE method, CORINFO_JUST_MY_CODE_HANDLE** ppIndirection) override; void GetProfilingHandle( bool* pbHookFunction, void** pProfilerHandle, bool* pbIndirectedHandles) override; void getCallInfo( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_CALLINFO_FLAGS flags, CORINFO_CALL_INFO* pResult) override; bool canAccessFamily( CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType) override; bool isRIDClassDomainID( CORINFO_CLASS_HANDLE cls) override; unsigned getClassDomainID( CORINFO_CLASS_HANDLE cls, void** ppIndirection) override; void* getFieldAddress( CORINFO_FIELD_HANDLE field, void** ppIndirection) override; bool getReadonlyStaticFieldValue( CORINFO_FIELD_HANDLE field, uint8_t* buffer, int bufferSize, int valueOffset, bool ignoreMovableObjects) override; CORINFO_CLASS_HANDLE getStaticFieldCurrentClass( CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) override; CORINFO_VARARGS_HANDLE getVarArgsHandle( CORINFO_SIG_INFO* pSig, void** ppIndirection) override; bool canGetVarArgsHandle( CORINFO_SIG_INFO* pSig) override; InfoAccessType constructStringLiteral( CORINFO_MODULE_HANDLE module, mdToken metaTok, void** ppValue) override; InfoAccessType emptyStringLiteral( void** ppValue) override; uint32_t getFieldThreadLocalStoreID( CORINFO_FIELD_HANDLE field, void** ppIndirection) override; void addActiveDependency( CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo) override; CORINFO_METHOD_HANDLE GetDelegateCtor( CORINFO_METHOD_HANDLE methHnd, CORINFO_CLASS_HANDLE clsHnd, CORINFO_METHOD_HANDLE targetMethodHnd, DelegateCtorArgs* pCtorData) override; void MethodCompileComplete( CORINFO_METHOD_HANDLE methHnd) override; bool getTailCallHelpers( CORINFO_RESOLVED_TOKEN* callToken, CORINFO_SIG_INFO* sig, CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, CORINFO_TAILCALL_HELPERS* pResult) override; bool convertPInvokeCalliToCall( CORINFO_RESOLVED_TOKEN* pResolvedToken, bool mustConvert) override; bool notifyInstructionSetUsage( CORINFO_InstructionSet instructionSet, bool supportEnabled) override; void updateEntryPointForTailCall( CORINFO_CONST_LOOKUP* entryPoint) override; void allocMem( AllocMemArgs* pArgs) override; void reserveUnwindInfo( bool isFunclet, bool isColdCode, uint32_t unwindSize) override; void allocUnwindInfo( uint8_t* pHotCode, uint8_t* pColdCode, uint32_t startOffset, uint32_t endOffset, uint32_t unwindSize, uint8_t* pUnwindBlock, CorJitFuncKind funcKind) override; void* allocGCInfo( size_t size) override; void setEHcount( unsigned cEH) override; void setEHinfo( unsigned EHnumber, const CORINFO_EH_CLAUSE* clause) override; bool logMsg( unsigned level, const char* fmt, va_list args) override; int doAssert( const char* szFile, int iLine, const char* szExpr) override; void reportFatalError( CorJitResult result) override; JITINTERFACE_HRESULT getPgoInstrumentationResults( CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema** pSchema, uint32_t* pCountSchemaItems, uint8_t** pInstrumentationData, ICorJitInfo::PgoSource* pgoSource) override; JITINTERFACE_HRESULT allocPgoInstrumentationBySchema( CORINFO_METHOD_HANDLE ftnHnd, ICorJitInfo::PgoInstrumentationSchema* pSchema, uint32_t countSchemaItems, uint8_t** pInstrumentationData) override; void recordCallSite( uint32_t instrOffset, CORINFO_SIG_INFO* callSig, CORINFO_METHOD_HANDLE methodHandle) override; void recordRelocation( void* location, void* locationRW, void* target, uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) override; uint16_t getRelocTypeHint( void* target) override; uint32_t getExpectedTargetArchitecture() override; uint32_t getJitFlags( CORJIT_FLAGS* flags, uint32_t sizeInBytes) override; /**********************************************************************************/ // clang-format on /**********************************************************************************/ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/il_kywd.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // COM+ IL keywords, symbols and values // // This is the master table used in ILASM (asmparse.y) // and ILDASM (dis.cpp) // symbols and values are defined in asmparse.y // and not used in dis.cpp // #ifndef __IL_KYWD_H_ #define __IL_KYWD_H_ KYWD( "void", VOID_, NO_VALUE ) KYWD( "bool", BOOL_, NO_VALUE ) KYWD( "char", CHAR_, NO_VALUE ) KYWD( "wchar", CHAR_, NO_VALUE ) KYWD( "int", INT_, NO_VALUE ) KYWD( "int8", INT8_, NO_VALUE ) KYWD( "int16", INT16_, NO_VALUE ) KYWD( "int32", INT32_, NO_VALUE ) KYWD( "int64", INT64_, NO_VALUE ) KYWD( "uint", UINT_, NO_VALUE ) KYWD( "uint8", UINT8_, NO_VALUE ) KYWD( "uint16", UINT16_, NO_VALUE ) KYWD( "uint32", UINT32_, NO_VALUE ) KYWD( "uint64", UINT64_, NO_VALUE ) KYWD( "float", FLOAT_, NO_VALUE ) KYWD( "float32", FLOAT32_, NO_VALUE ) KYWD( "float64", FLOAT64_, NO_VALUE ) KYWD( "refany", TYPEDREF_, NO_VALUE ) KYWD( "typedref", TYPEDREF_, NO_VALUE ) KYWD( "object", OBJECT_, NO_VALUE ) KYWD( "string", STRING_, NO_VALUE ) KYWD( "native", NATIVE_, NO_VALUE ) KYWD( "unsigned", UNSIGNED_, NO_VALUE ) KYWD( "value", VALUE_, NO_VALUE ) KYWD( "valuetype", VALUETYPE_, NO_VALUE ) KYWD( "class", CLASS_, NO_VALUE ) KYWD( "byreflike", BYREFLIKE_, NO_VALUE ) KYWD( "vararg", VARARG_, NO_VALUE ) KYWD( "default", DEFAULT_, NO_VALUE ) KYWD( "stdcall", STDCALL_, NO_VALUE ) KYWD( "thiscall", THISCALL_, NO_VALUE ) KYWD( "fastcall", FASTCALL_, NO_VALUE ) KYWD( "unmanaged", UNMANAGED_, NO_VALUE ) KYWD( "beforefieldinit",BEFOREFIELDINIT_, NO_VALUE ) KYWD( "instance", INSTANCE_, NO_VALUE ) KYWD( "filter", FILTER_, NO_VALUE ) KYWD( "catch", CATCH_, NO_VALUE ) KYWD( "static", STATIC_ , NO_VALUE ) KYWD( "public", PUBLIC_, NO_VALUE ) KYWD( "private", PRIVATE_, NO_VALUE ) KYWD( "forwarder", FORWARDER_, NO_VALUE ) KYWD( "synchronized", SYNCHRONIZED_, NO_VALUE ) KYWD( "interface", INTERFACE_, NO_VALUE ) KYWD( "extends", EXTENDS_, NO_VALUE ) KYWD( "implements", IMPLEMENTS_, NO_VALUE ) KYWD( "handler", HANDLER_, NO_VALUE ) KYWD( "finally", FINALLY_, NO_VALUE ) KYWD( "fault", FAULT_, NO_VALUE ) KYWD( "to", TO_, NO_VALUE ) KYWD( "abstract", ABSTRACT_, NO_VALUE ) KYWD( "auto", AUTO_, NO_VALUE ) KYWD( "sequential", SEQUENTIAL_, NO_VALUE ) KYWD( "explicit", EXPLICIT_, NO_VALUE ) KYWD( "ansi", ANSI_, NO_VALUE ) KYWD( "unicode", UNICODE_, NO_VALUE ) KYWD( "autochar", AUTOCHAR_, NO_VALUE ) KYWD( "import", IMPORT_, NO_VALUE ) KYWD( "enum", ENUM_, NO_VALUE ) KYWD( "virtual", VIRTUAL_, NO_VALUE ) KYWD( "strict", STRICT_, NO_VALUE ) KYWD( "il", CIL_, NO_VALUE ) KYWD( "cil", CIL_, NO_VALUE ) KYWD( "optil", OPTIL_, NO_VALUE ) KYWD( "managed", MANAGED_, NO_VALUE ) KYWD( "preservesig", PRESERVESIG_, NO_VALUE ) KYWD( "runtime", RUNTIME_, NO_VALUE ) KYWD( "method", METHOD_, NO_VALUE ) KYWD( "field", FIELD_, NO_VALUE ) KYWD( "property", PROPERTY_, NO_VALUE ) KYWD( "bytearray", BYTEARRAY_, NO_VALUE ) KYWD( "final", FINAL_, NO_VALUE ) KYWD( "sealed", SEALED_, NO_VALUE ) KYWD( "specialname", SPECIALNAME_, NO_VALUE ) KYWD( "family", FAMILY_, NO_VALUE ) KYWD( "assembly", ASSEMBLY_, NO_VALUE ) KYWD( "famandassem", FAMANDASSEM_, NO_VALUE ) KYWD( "famorassem", FAMORASSEM_, NO_VALUE ) KYWD( "privatescope", PRIVATESCOPE_, NO_VALUE ) KYWD( "nested", NESTED_, NO_VALUE ) KYWD( "hidebysig", HIDEBYSIG_, NO_VALUE ) KYWD( "newslot", NEWSLOT_, NO_VALUE ) KYWD( "aggressiveinlining",AGGRESSIVEINLINING_,NO_VALUE ) KYWD( "rtspecialname", RTSPECIALNAME_, NO_VALUE ) KYWD( "pinvokeimpl", PINVOKEIMPL_, NO_VALUE ) KYWD( "unmanagedexp", UNMANAGEDEXP_, NO_VALUE ) KYWD( "reqsecobj", REQSECOBJ_, NO_VALUE ) KYWD( ".ctor", _CTOR, NO_VALUE ) KYWD( ".cctor", _CCTOR, NO_VALUE ) KYWD( "initonly", INITONLY_, NO_VALUE ) KYWD( "literal", LITERAL_, NO_VALUE ) KYWD( "notserialized", NOTSERIALIZED_, NO_VALUE ) KYWD( "forwardref", FORWARDREF_, NO_VALUE ) KYWD( "internalcall", INTERNALCALL_, NO_VALUE ) KYWD( "noinlining", NOINLINING_, NO_VALUE ) KYWD( "nooptimization", NOOPTIMIZATION_, NO_VALUE ) KYWD( "aggressiveoptimization", AGGRESSIVEOPTIMIZATION_, NO_VALUE ) KYWD( "nomangle", NOMANGLE_, NO_VALUE ) KYWD( "lasterr", LASTERR_, NO_VALUE ) KYWD( "winapi", WINAPI_, NO_VALUE ) KYWD( "cdecl", CDECL_, NO_VALUE ) KYWD( "as", AS_, NO_VALUE ) KYWD( "pinned", PINNED_, NO_VALUE ) KYWD( "modreq", MODREQ_, NO_VALUE ) KYWD( "modopt", MODOPT_, NO_VALUE ) KYWD( "serializable", SERIALIZABLE_, NO_VALUE ) KYWD( "at", AT_, NO_VALUE ) KYWD( "tls", TLS_, NO_VALUE ) KYWD( "true", TRUE_, NO_VALUE ) KYWD( "false", FALSE_, NO_VALUE ) KYWD( "on", ON_, NO_VALUE ) KYWD( "off", OFF_, NO_VALUE ) KYWD( "bestfit", BESTFIT_, NO_VALUE ) KYWD( "charmaperror", CHARMAPERROR_, NO_VALUE ) /* assembler directives */ KYWD( ".class", _CLASS, NO_VALUE ) KYWD( ".this", _THIS, NO_VALUE ) KYWD( ".base", _BASE, NO_VALUE ) KYWD( ".nester", _NESTER, NO_VALUE ) KYWD( ".namespace", _NAMESPACE, NO_VALUE ) KYWD( ".method", _METHOD, NO_VALUE ) KYWD( ".field", _FIELD, NO_VALUE ) KYWD( ".emitbyte", _EMITBYTE, NO_VALUE ) KYWD( ".try", _TRY, NO_VALUE ) KYWD( ".maxstack", _MAXSTACK, NO_VALUE ) KYWD( ".locals", _LOCALS, NO_VALUE ) KYWD( ".entrypoint", _ENTRYPOINT, NO_VALUE ) KYWD( ".zeroinit", _ZEROINIT, NO_VALUE ) KYWD( ".data", _DATA, NO_VALUE ) KYWD( ".param", _PARAM, NO_VALUE ) KYWD( ".event", _EVENT, NO_VALUE ) KYWD( ".addon", _ADDON, NO_VALUE ) KYWD( ".removeon", _REMOVEON, NO_VALUE ) KYWD( ".fire", _FIRE, NO_VALUE ) KYWD( ".other", _OTHER, NO_VALUE ) KYWD( ".property", _PROPERTY, NO_VALUE ) KYWD( ".set", _SET, NO_VALUE ) KYWD( ".get", _GET, NO_VALUE ) KYWD( ".permission", _PERMISSION, NO_VALUE ) KYWD( ".permissionset", _PERMISSIONSET, NO_VALUE ) /* security actions */ KYWD( "request", REQUEST_, NO_VALUE ) KYWD( "demand", DEMAND_, NO_VALUE ) KYWD( "assert", ASSERT_, NO_VALUE ) KYWD( "deny", DENY_, NO_VALUE ) KYWD( "permitonly", PERMITONLY_, NO_VALUE ) KYWD( "linkcheck", LINKCHECK_, NO_VALUE ) KYWD( "inheritcheck", INHERITCHECK_, NO_VALUE ) KYWD( "reqmin", REQMIN_, NO_VALUE ) KYWD( "reqopt", REQOPT_, NO_VALUE ) KYWD( "reqrefuse", REQREFUSE_, NO_VALUE ) KYWD( "prejitgrant", PREJITGRANT_, NO_VALUE ) KYWD( "prejitdeny", PREJITDENY_, NO_VALUE ) KYWD( "noncasdemand", NONCASDEMAND_, NO_VALUE ) KYWD( "noncaslinkdemand",NONCASLINKDEMAND_, NO_VALUE ) KYWD( "noncasinheritance",NONCASINHERITANCE_,NO_VALUE ) /* extern debug data specifier */ KYWD( ".line", _LINE, NO_VALUE ) KYWD( ".language", _LANGUAGE, NO_VALUE ) KYWD( "#line", P_LINE, NO_VALUE ) /* custom value specifier */ KYWD( ".custom", _CUSTOM, NO_VALUE ) /* IL method attribute */ KYWD( "init", INIT_, NO_VALUE ) /* Class layout directives */ KYWD( ".size", _SIZE, NO_VALUE ) KYWD( ".pack", _PACK, NO_VALUE ) /* Manifest-related keywords */ KYWD( ".file", _FILE, NO_VALUE ) KYWD( "nometadata", NOMETADATA_, NO_VALUE ) KYWD( ".hash", _HASH, NO_VALUE ) KYWD( ".assembly", _ASSEMBLY, NO_VALUE ) KYWD( "retargetable", RETARGETABLE_, NO_VALUE ) KYWD( "windowsruntime", WINDOWSRUNTIME_, NO_VALUE ) KYWD( "noplatform", NOPLATFORM_, NO_VALUE ) KYWD( "legacy", LEGACY_, NO_VALUE ) KYWD( "library", LIBRARY_, NO_VALUE ) KYWD( "x86", X86_, NO_VALUE ) KYWD( "amd64", AMD64_, NO_VALUE ) KYWD( "arm", ARM_, NO_VALUE ) KYWD( "arm64", ARM64_, NO_VALUE ) KYWD( ".publickey", _PUBLICKEY, NO_VALUE ) KYWD( ".publickeytoken",_PUBLICKEYTOKEN, NO_VALUE ) KYWD( "algorithm", ALGORITHM_, NO_VALUE ) KYWD( ".ver", _VER, NO_VALUE ) KYWD( ".locale", _LOCALE, NO_VALUE ) KYWD( "extern", EXTERN_, NO_VALUE ) KYWD( ".export", _EXPORT, NO_VALUE ) KYWD( ".manifestres", _MRESOURCE, NO_VALUE ) KYWD( ".mresource", _MRESOURCE, NO_VALUE ) KYWD( ".module", _MODULE, NO_VALUE ) /* Field marshaling keywords */ KYWD( "marshal", MARSHAL_, NO_VALUE ) KYWD( "custom", CUSTOM_, NO_VALUE ) KYWD( "sysstring", SYSSTRING_, NO_VALUE ) KYWD( "fixed", FIXED_, NO_VALUE ) KYWD( "variant", VARIANT_, NO_VALUE ) KYWD( "currency", CURRENCY_, NO_VALUE ) KYWD( "syschar", SYSCHAR_, NO_VALUE ) KYWD( "decimal", DECIMAL_, NO_VALUE ) KYWD( "date", DATE_, NO_VALUE ) KYWD( "bstr", BSTR_, NO_VALUE ) KYWD( "tbstr", TBSTR_, NO_VALUE ) KYWD( "lpstr", LPSTR_, NO_VALUE ) KYWD( "lpwstr", LPWSTR_, NO_VALUE ) KYWD( "lptstr", LPTSTR_, NO_VALUE ) KYWD( "objectref", OBJECTREF_, NO_VALUE ) KYWD( "iunknown", IUNKNOWN_, NO_VALUE ) KYWD( "idispatch", IDISPATCH_, NO_VALUE ) KYWD( "iidparam", IIDPARAM_, NO_VALUE ) KYWD( "struct", STRUCT_, NO_VALUE ) KYWD( "safearray", SAFEARRAY_, NO_VALUE ) KYWD( "byvalstr", BYVALSTR_, NO_VALUE ) KYWD( "lpvoid", LPVOID_, NO_VALUE ) KYWD( "any", ANY_, NO_VALUE ) KYWD( "array", ARRAY_, NO_VALUE ) KYWD( "lpstruct", LPSTRUCT_, NO_VALUE ) /* VTable fixup keywords */ KYWD( ".vtfixup", _VTFIXUP, NO_VALUE ) KYWD( "fromunmanaged", FROMUNMANAGED_, NO_VALUE ) KYWD( "retainappdomain",RETAINAPPDOMAIN_, NO_VALUE ) KYWD( "callmostderived",CALLMOSTDERIVED_, NO_VALUE ) KYWD( ".vtentry", _VTENTRY, NO_VALUE ) /* Parameter attributes */ KYWD( "in", IN_, NO_VALUE ) KYWD( "out", OUT_, NO_VALUE ) KYWD( "opt", OPT_, NO_VALUE ) /* Method implementations */ KYWD( ".override", _OVERRIDE, NO_VALUE ) KYWD( "with", WITH_, NO_VALUE ) /* VariantType keywords */ KYWD( "null", NULL_, NO_VALUE ) KYWD( "error", ERROR_, NO_VALUE ) KYWD( "hresult", HRESULT_, NO_VALUE ) KYWD( "carray", CARRAY_, NO_VALUE ) KYWD( "userdefined", USERDEFINED_, NO_VALUE ) KYWD( "record", RECORD_, NO_VALUE ) KYWD( "filetime", FILETIME_, NO_VALUE ) KYWD( "blob", BLOB_, NO_VALUE ) KYWD( "stream", STREAM_, NO_VALUE ) KYWD( "storage", STORAGE_, NO_VALUE ) KYWD( "streamed_object",STREAMED_OBJECT_, NO_VALUE ) KYWD( "stored_object", STORED_OBJECT_, NO_VALUE ) KYWD( "blob_object", BLOB_OBJECT_, NO_VALUE ) KYWD( "cf", CF_, NO_VALUE ) KYWD( "clsid", CLSID_, NO_VALUE ) KYWD( "vector", VECTOR_, NO_VALUE ) /* Null reference keyword for InitOpt */ KYWD( "nullref", NULLREF_, NO_VALUE ) KYWD( "type", TYPE_, NO_VALUE ) KYWD( ".interfaceimpl", _INTERFACEIMPL, NO_VALUE ) /* Header flags keywords */ KYWD( ".subsystem", _SUBSYSTEM, NO_VALUE ) KYWD( ".corflags", _CORFLAGS, NO_VALUE ) KYWD( "alignment", ALIGNMENT_, NO_VALUE ) KYWD( ".imagebase", _IMAGEBASE, NO_VALUE ) KYWD( ".stackreserve", _STACKRESERVE, NO_VALUE ) /* Explicit binary flag specification keywords */ KYWD( "flags", FLAGS_, NO_VALUE ) KYWD( "callconv", CALLCONV_, NO_VALUE ) KYWD( "mdtoken", MDTOKEN_, NO_VALUE ) /* Some ILASM-specific syntactic sugar */ KYWD( ".typedef", _TYPEDEF, NO_VALUE ) KYWD( ".template", _TEMPLATE, NO_VALUE ) KYWD( ".typelist", _TYPELIST, NO_VALUE ) KYWD( ".mscorlib", _MSCORLIB, NO_VALUE ) /* Compilation control keywords */ KYWD( "#define", P_DEFINE, NO_VALUE ) KYWD( "#undef", P_UNDEF, NO_VALUE ) KYWD( "#ifdef", P_IFDEF, NO_VALUE ) KYWD( "#ifndef", P_IFNDEF, NO_VALUE ) KYWD( "#else", P_ELSE, NO_VALUE ) KYWD( "#endif", P_ENDIF, NO_VALUE ) KYWD( "#include", P_INCLUDE, NO_VALUE ) KYWD( "constraint", CONSTRAINT_, NO_VALUE ) /* Deprecated keywords */ KYWD( ".vtable", _VTABLE, NO_VALUE ) KYWD( "^THE_END^", 0, NO_VALUE ) #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ilformatter.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************/ /* ILFormatter.h */ /***************************************************************************/ #ifndef ILFormatter_h #define ILFormatter_h #include "opinfo.h" #include "outstring.h" struct IMetaDataImport; #define INVALID_IL_OFFSET 0x80000000 /***************************************************************************/ class ILFormatter { public: ILFormatter() : start(0), targetStart(0), stackStart(0) {} ILFormatter(IMetaDataImport* aMeta, const BYTE* aStart, const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh) : targetStart(0), stackStart(0) { init(aMeta, aStart, aLimit, maxStack, eh); } ~ILFormatter() { delete [] stackStart; delete [] targetStart; } void init(IMetaDataImport* aMeta, const BYTE* aStart, const BYTE* aLimit, unsigned maxStack, const COR_ILMETHOD_SECT_EH* eh); const BYTE* formatStatement(const BYTE* stmtIL, OutString* out); const BYTE* formatInstr(const BYTE* instrIL, OutString* out); private: void formatInstrArgs(OpInfo op, OpArgsVal arg, OutString* out, size_t curIP=INVALID_IL_OFFSET); void formatArgs(unsigned numArgs, OutString* out); void spillStack(OutString* out); void setStackAsTarget(size_t ilOffset); void setTarget(size_t ilOffset, size_t depth); private: const BYTE* start; // keeps us sane const BYTE* limit; IMetaDataImport* meta; // used to parse tokens etc struct StackEntry { OutString val; int prec; }; struct Target { size_t ilOffset; size_t stackDepth; }; Target* targetStart; Target* targetEnd; Target* targetCur; size_t stackDepth(); void pushAndClear(OutString* val, int prec); OutString* pop(int prec = 0); OutString* top(); void popN(size_t num); StackEntry* stackStart; StackEntry* stackEnd; StackEntry* stackCur; // points at the next slot to fill }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/internalunknownimpl.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // // InternalUnknownImpl.h // // Defines utility class IUnknownCommon, which provides default // implementations for IUnknown's AddRef, Release, and QueryInterface methods. // // Use: a class that implements one or more interfaces should derive from // IUnknownCommon with a template parameter list consisting of the // list of implemented interfaces and their IIDs. // // Example: // class MyInterfacesImpl : // public IUnknownCommon // { ... }; // // IUnknownCommon will provide base AddRef and Release semantics, and will // also provide an implementation of QueryInterface that will evaluate the // arguments against the set of supported interfaces and return the // appropriate result. // // //***************************************************************************** #ifndef __InternalUnknownImpl_h__ #define __InternalUnknownImpl_h__ #include #include "winwrap.h" #include "contract.h" #include "ex.h" #include "volatile.h" #include "debugmacros.h" template class IUnknownCommon : public T { protected: LONG m_cRef; public: IUnknownCommon() : m_cRef(0) { } // Add a virtual destructor to force derived types to also have virtual destructors. virtual ~IUnknownCommon() { } STDMETHOD_(ULONG, AddRef()) { return InterlockedIncrement(&m_cRef); } STDMETHOD_(ULONG, Release()) { _ASSERTE(m_cRef > 0); ULONG cRef = InterlockedDecrement(&m_cRef); if (cRef == 0) delete this; // Relies on virtual dtor to work properly. return cRef; } STDMETHOD(QueryInterface(REFIID riid, void** ppObj)) { if (ppObj == NULL) return E_INVALIDARG; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_T)) { AddRef(); *ppObj = static_cast(this); return S_OK; } *ppObj = NULL; return E_NOINTERFACE; } }; template class IUnknownCommon2 : public T, public T2 { protected: LONG m_cRef; public: IUnknownCommon2() : m_cRef(0) { } // Add a virtual destructor to force derived types to also have virtual destructors. virtual ~IUnknownCommon2() { } STDMETHOD_(ULONG, AddRef()) { return InterlockedIncrement(&m_cRef); } STDMETHOD_(ULONG, Release()) { _ASSERTE(m_cRef > 0); ULONG cRef = InterlockedDecrement(&m_cRef); if (cRef == 0) delete this; // Relies on virtual dtor to work properly. return cRef; } STDMETHOD(QueryInterface(REFIID riid, void** ppObj)) { if (ppObj == NULL) return E_INVALIDARG; if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_T)) { AddRef(); *ppObj = static_cast(this); return S_OK; } else if (IsEqualIID(riid, IID_T2)) { AddRef(); *ppObj = static_cast(this); return S_OK; } *ppObj = NULL; return E_NOINTERFACE; } }; #endif // __InternalUnknownImpl_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/intrinsic.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // Intrinsic.h // // Force several very useful functions to be intrinsic, which means that the // compiler will generate code inline for the functions instead of generating // a call to the function. // //***************************************************************************** #ifndef __intrinsic_h__ #define __intrinsic_h__ #ifdef _MSC_VER #pragma intrinsic(memcmp) #pragma intrinsic(memcpy) #pragma intrinsic(memset) #pragma intrinsic(strcmp) #pragma intrinsic(strcpy) #pragma intrinsic(strlen) #endif // defined(_MSC_VER) #endif // __intrinsic_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/iterator.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // Iterator.h // --------------------------------------------------------------------------- // ================================================================================ // Iterator pattern: // // This pattern is similar to the STL iterator pattern. It basically consists of // wrapping an "iteration variable" in an object, and providing pointer-like operators // on the iterator. Example usage: // // for (Iterator start = foo->Begin(), end = foo->End(); start != end; start++) // { // // use foo, start // } // // There are 3 levels of iterator functionality // 1. Enumerator (STL forward) - only go forward one at a time // Enumerators have the following operations: // operator * : access current element as ref // operator -> : access current element as ptr // operator++ : go to the next element // operator==, operator!= : compare to another enumerator // // // 2. Scanner (STL bidirectional) - backward or forward one at a time // Scanners have all the functionality of enumerators, plus: // operator-- : go backward one element // // 3. Indexer (STL random access) - skip around arbitrarily // Indexers have all the functionality of scanners, plus: // operator[] : access the element at index from iterator as ref // operator+= : advance iterator by index // operator+ : return new iterator at index from iterator // operator-= : rewind iterator by index // operator- : return new iterator at index back from iterator // operator <, operator <=, operator >, operator>= : // range comparison on two indexers // // The object being iterated should define the following methods: // Begin() return an iterator starting at the first element // End() return an iterator just past the last element // // Iterator types are normally defined as member types named "Iterator", no matter // what their functionality level is. // ================================================================================ #ifndef ITERATOR_H_ #define ITERATOR_H_ #include "contract.h" namespace HIDDEN { // These prototypes are not for direct use - they are only here to illustrate the // iterator pattern template class ScannerPrototype { public: typedef ScannerPrototype Iterator; ELEMENT &operator*(); ELEMENT *operator->(); Iterator &operator++(); Iterator operator++(int); Iterator &operator--(); Iterator operator--(int); bool operator==(const Iterator &i); bool operator!=(const Iterator &i); }; template class EnumeratorPrototype { public: typedef EnumeratorPrototype Iterator; ELEMENT &operator*(); ELEMENT *operator->(); Iterator &operator++(); Iterator operator++(int); bool operator==(const Iterator &i); bool operator!=(const Iterator &i); }; template class IndexerPrototype { public: typedef IndexerPrototype Iterator; ELEMENT &operator*(); ELEMENT *operator->(); ELEMENT &operator[](int index); Iterator &operator++(); Iterator operator++(int); Iterator &operator--(); Iterator operator--(int); Iterator &operator+=(SCOUNT_T index); Iterator &operator-=(SCOUNT_T index); Iterator operator+(SCOUNT_T index); Iterator operator-(SCOUNT_T index); SCOUNT_T operator-(Iterator &i); bool operator==(const Iterator &i); bool operator!=(const Iterator &i); bool operator<(const Iterator &i); bool operator<=(const Iterator &i); bool operator>(const Iterator &i); bool operator>=(const Iterator &i); }; template class EnumerablePrototype { typedef EnumeratorPrototype Iterator; Iterator Begin(); Iterator End(); }; template class ScannablePrototype { typedef ScannerPrototype Iterator; Iterator Begin(); Iterator End(); }; template class IndexablePrototype { typedef IndexerPrototype Iterator; Iterator Begin(); Iterator End(); }; }; // -------------------------------------------------------------------------------- // EnumeratorBase, ScannerBase, and IndexerBase are abstract classes // describing basic operations for iterator functionality at the different levels. // // You // 1. Use the classes as a pattern (don't derive from them), and plug in your own // class into the Enumerator/Scanner/Indexer templates below. // 2. Subclass the AbstractEnumerator/AbstractScanner/AbstractIndexer classes // -------------------------------------------------------------------------------- namespace HIDDEN { // These prototypes are not for direct use - they are only here to illustrate the // pattern of the BASE class for the Iterator templates template class EnumeratorBasePrototype { protected: EnumeratorBasePrototype(CONTAINER *container, BOOL begin); ELEMENT &Get() const; void Next(); BOOL Equal(const EnumeratorBasePrototype &i) const; CHECK DoCheck() const; }; template class ScannerBasePrototype { protected: ScannerBasePrototype(CONTAINER *container, BOOL begin); ELEMENT &Get() const; void Next(); void Previous(); BOOL Equal(const ScannerBasePrototype &i) const; CHECK DoCheck() const; }; template class IndexerBasePrototype { protected: IndexerBasePrototype(CONTAINER *container, SCOUNT_T delta); ELEMENT &GetAt(SCOUNT_T delta) const; void Skip(SCOUNT_T delta); SCOUNT_T Subtract(const IndexerBasePrototype &i) const; CHECK DoCheck(SCOUNT_T delta) const; }; }; template class CheckedIteratorBase { protected: #if defined(_DEBUG) const CONTAINER *m_container; int m_revision; #endif CHECK CheckRevision() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; #if defined(_DEBUG) && (defined(_MSC_VER) || defined(__llvm__)) __if_exists(CONTAINER::m_revision) { CHECK_MSG(m_revision == m_container->m_revision, "Use of Iterator after container has been modified"); } #endif CHECK_OK; } CheckedIteratorBase() { LIMITED_METHOD_DAC_CONTRACT; #if defined(_DEBUG) m_container = NULL; #endif } CheckedIteratorBase(const CONTAINER *container) { LIMITED_METHOD_CONTRACT; #if defined(_DEBUG) m_container = container; #if defined(_MSC_VER) || defined(__llvm__) __if_exists(CONTAINER::m_revision) { m_revision = m_container->m_revision; } #endif #endif } void Resync(const CONTAINER *container) { LIMITED_METHOD_DAC_CONTRACT; #if defined(_DEBUG) && (defined(_MSC_VER) || defined(__llvm__)) __if_exists(CONTAINER::m_revision) { m_revision = m_container->m_revision; } #endif } #if defined(_DEBUG) const CONTAINER *GetContainerDebug() const { LIMITED_METHOD_CONTRACT; return m_container; } #endif public: CHECK Check() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CHECK(CheckRevision()); CHECK_OK; } CHECK CheckContainer(const CONTAINER *container) const { WRAPPER_NO_CONTRACT; #if defined(_DEBUG) CHECK(container == m_container); #endif CHECK_OK; } }; // -------------------------------------------------------------------------------- // Enumerator, Scanner, and Indexer provide a template to produce an iterator // on an existing class with a single iteration variable. // // The template takes 3 type parameters: // CONTAINER - type of object being interated on // ELEMENT - type of iteration // BASE - base type of the iteration. This type must follow the pattern described // by the above Prototypes // -------------------------------------------------------------------------------- template class Enumerator { private: const SUBTYPE *This() const { return (const SUBTYPE *) this; } SUBTYPE *This() { return (SUBTYPE *)this; } public: Enumerator() { } CHECK CheckIndex() const { #if defined(_DEBUG) CHECK(This()->DoCheck()); #endif CHECK_OK; } ELEMENT &operator*() const { PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex()); return This()->Get(); } ELEMENT *operator->() const { PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex()); return &(This()->Get()); } SUBTYPE &operator++() { PRECONDITION(CheckPointer(This())); This()->Next(); return *This(); } SUBTYPE operator++(int) { PRECONDITION(CheckPointer(This())); SUBTYPE i = *This(); This()->Next(); return i; } bool operator==(const SUBTYPE &i) const { PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Equal(i); } bool operator!=(const SUBTYPE &i) const { PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return !This()->Equal(i); } }; template class Scanner { private: const SUBTYPE *This() const { return (const SUBTYPE *)this; } SUBTYPE *This() { return (SUBTYPE *)this; } public: Scanner() { } CHECK CheckIndex() const { #if defined(_DEBUG) CHECK(This()->DoCheck()); #endif CHECK_OK; } ELEMENT &operator*() const { PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex()); return This()->Get(); } ELEMENT *operator->() const { PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex()); return &This()->Get(); } SUBTYPE &operator++() { PRECONDITION(CheckPointer(This())); This()->Next(); return *This(); } SUBTYPE operator++(int) { PRECONDITION(CheckPointer(This())); SUBTYPE i = *This(); This()->Next(); return i; } SUBTYPE &operator--() { PRECONDITION(CheckPointer(This())); This()->Previous(); return *This(); } SUBTYPE operator--(int) { PRECONDITION(CheckPointer(this)); SUBTYPE i = *This(); This()->Previous(); return i; } bool operator==(const SUBTYPE &i) const { PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Equal(i); } bool operator!=(const SUBTYPE &i) const { PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return !This()->Equal(i); } }; template class Indexer { private: const SUBTYPE *This() const { return (const SUBTYPE *)this; } SUBTYPE *This() { return (SUBTYPE *)this; } public: Indexer() { LIMITED_METHOD_DAC_CONTRACT; } CHECK CheckIndex() const { #if defined(_DEBUG) CHECK(This()->DoCheck(0)); #endif CHECK_OK; } CHECK CheckIndex(int index) const { #if defined(_DEBUG) CHECK(This()->DoCheck(index)); #endif CHECK_OK; } ELEMENT &operator*() const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex(0)); return *(ELEMENT*)&This()->GetAt(0); } ELEMENT *operator->() const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex(0)); return &This()->GetAt(0); } ELEMENT &operator[](int index) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(This()->CheckIndex(index)); return *(ELEMENT*)&This()->GetAt(index); } SUBTYPE &operator++() { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); This()->Skip(1); return *This(); } SUBTYPE operator++(int) { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); SUBTYPE i = *This(); This()->Skip(1); return i; } SUBTYPE &operator--() { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); This()->Skip(-1); return *This(); } SUBTYPE operator--(int) { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); SUBTYPE i = *This(); This()->Skip(-1); return i; } SUBTYPE &operator+=(SCOUNT_T index) { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); This()->Skip(index); return *This(); } SUBTYPE operator+(SCOUNT_T index) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); SUBTYPE i = *This(); i.Skip(index); return i; } SUBTYPE &operator-=(SCOUNT_T index) { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); This()->Skip(-index); return *This(); } SUBTYPE operator-(SCOUNT_T index) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); SUBTYPE i = *This(); i.Skip(-index); return i; } SCOUNT_T operator-(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i); } bool operator==(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i) == 0; } bool operator!=(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i) != 0; } bool operator<(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i) < 0; } bool operator<=(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i) <= 0; } bool operator>(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i) > 0; } bool operator>=(const SUBTYPE &i) const { WRAPPER_NO_CONTRACT; PRECONDITION(CheckPointer(This())); PRECONDITION(i.Check()); return This()->Subtract(i) >= 0; } }; #endif // ITERATOR_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/jiteeversionguid.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // // #JITEEVersionIdentifier // // This GUID represents the version of the JIT/EE interface. Any time the interface between the JIT and // the EE changes (by adding or removing methods to any interface shared between them), this GUID should // be changed. This is the identifier verified by ICorJitCompiler::getVersionIdentifier(). // // You can use "uuidgen.exe -s" to generate this value. // // Note that this file is parsed by some tools, namely superpmi.py, so make sure the first line is exactly // of the form: // // constexpr GUID JITEEVersionIdentifier = { /* 1776ab48-edfa-49be-a11f-ec216b28174c */ // // (without the leading slashes or spaces). // // See docs/project/updating-jitinterface.md for details // // **** NOTE TO INTEGRATORS: // // If there is a merge conflict here, because the version changed in two different places, you must // create a **NEW** GUID, not simply choose one or the other! // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// // #ifndef GUID_DEFINED typedef struct _GUID { uint32_t Data1; // NOTE: diff from Win32, for LP64 uint16_t Data2; uint16_t Data3; uint8_t Data4[ 8 ]; } GUID; typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED constexpr GUID JITEEVersionIdentifier = { /* 0330a175-dd05-4760-840f-a1a4c47284d3 */ 0x330a175, 0xdd05, 0x4760, {0x84, 0xf, 0xa1, 0xa4, 0xc4, 0x72, 0x84, 0xd3} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // END JITEEVersionIdentifier // ////////////////////////////////////////////////////////////////////////////////////////////////////////// ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/jithelpers.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Allow multiple inclusion. ////////////////////////////////////////////////////////////////////////////////////////////////////////// // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // // The JIT/EE interface is versioned. By "interface", we mean mean any and all communication between the // JIT and the EE. Any time a change is made to the interface, the JIT/EE interface version identifier // must be updated. See code:JITEEVersionIdentifier for more information. // // THIS FILE IS PART OF THE JIT-EE INTERFACE. // // NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE // ////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef DYNAMICJITHELPER //I should never try to generate an alignment stub for a dynamic helper #define DYNAMICJITHELPER(code,fn,sig) JITHELPER(code,fn,sig) #endif // pfnHelper is set to NULL if it is a stubbed helper. // It will be set in InitJITHelpers2 JITHELPER(CORINFO_HELP_UNDEF, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) // Arithmetic JITHELPER(CORINFO_HELP_DIV, JIT_Div, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_MOD, JIT_Mod, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_UDIV, JIT_UDiv, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_UMOD, JIT_UMod, CORINFO_HELP_SIG_8_STACK) // CORINFO_HELP_DBL2INT, CORINFO_HELP_DBL2UINT, and CORINFO_HELP_DBL2LONG get // patched for CPUs that support SSE2 (P4 and above). #ifndef TARGET_64BIT JITHELPER(CORINFO_HELP_LLSH, JIT_LLsh, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_LRSH, JIT_LRsh, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_LRSZ, JIT_LRsz, CORINFO_HELP_SIG_REG_ONLY) #else // !TARGET_64BIT JITHELPER(CORINFO_HELP_LLSH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_LRSH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_LRSZ, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #endif // TARGET_64BIT JITHELPER(CORINFO_HELP_LMUL, JIT_LMul, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LMUL_OVF, JIT_LMulOvf, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_ULMUL_OVF, JIT_ULMulOvf, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LDIV, JIT_LDiv, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LMOD, JIT_LMod, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_ULDIV, JIT_ULDiv, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_ULMOD, JIT_ULMod, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_LNG2DBL, JIT_Lng2Dbl, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_ULNG2DBL, JIT_ULng2Dbl, CORINFO_HELP_SIG_8_STACK) DYNAMICJITHELPER(CORINFO_HELP_DBL2INT, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2INT_OVF, JIT_Dbl2IntOvf, CORINFO_HELP_SIG_8_STACK) DYNAMICJITHELPER(CORINFO_HELP_DBL2LNG, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2LNG_OVF, JIT_Dbl2LngOvf, CORINFO_HELP_SIG_8_STACK) DYNAMICJITHELPER(CORINFO_HELP_DBL2UINT, JIT_Dbl2Lng, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2UINT_OVF, JIT_Dbl2UIntOvf, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2ULNG, JIT_Dbl2ULng, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBL2ULNG_OVF, JIT_Dbl2ULngOvf, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_FLTREM, JIT_FltRem, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBLREM, JIT_DblRem, CORINFO_HELP_SIG_16_STACK) JITHELPER(CORINFO_HELP_FLTROUND, JIT_FloatRound, CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_DBLROUND, JIT_DoubleRound, CORINFO_HELP_SIG_16_STACK) // Allocating a new object JITHELPER(CORINFO_HELP_NEWFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_NEWSFAST_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8, JIT_New, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8_VC, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_NEWSFAST_ALIGN8_FINALIZE, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_NEW_MDARR, JIT_NewMDArr,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_NEWARR_1_DIRECT, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_VC, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_ALIGN8, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_STRCNS, JIT_StrCns, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_STRCNS_CURRENT_MODULE, NULL, CORINFO_HELP_SIG_REG_ONLY) // Object model JITHELPER(CORINFO_HELP_INITCLASS, JIT_InitClass, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_INITINSTCLASS, JIT_InitInstantiatedClass, CORINFO_HELP_SIG_REG_ONLY) // Casting helpers DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFINTERFACE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFARRAY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_ISINSTANCEOFANY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTINTERFACE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTARRAY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTANY, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_CHKCASTCLASS_SPECIAL, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_ISINSTANCEOF_EXCEPTION, JIT_IsInstanceOfException, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_BOX, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_BOX_NULLABLE, JIT_Box, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_UNBOX, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_UNBOX_NULLABLE, JIT_Unbox_Nullable, CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_GETREFANY, JIT_GetRefAny, CORINFO_HELP_SIG_8_STACK) DYNAMICJITHELPER(CORINFO_HELP_ARRADDR_ST, NULL, CORINFO_HELP_SIG_4_STACK) DYNAMICJITHELPER(CORINFO_HELP_LDELEMA_REF, NULL, CORINFO_HELP_SIG_4_STACK) // Exceptions JITHELPER(CORINFO_HELP_THROW, IL_Throw, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_RETHROW, IL_Rethrow, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_USER_BREAKPOINT, JIT_UserBreakpoint, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_RNGCHKFAIL, JIT_RngChkFail, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_OVERFLOW, JIT_Overflow, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROWDIVZERO, JIT_ThrowDivZero, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROWNULLREF, JIT_ThrowNullRef, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_VERIFICATION, IL_VerificationError,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_FAIL_FAST, JIT_FailFast, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_METHOD_ACCESS_EXCEPTION,JIT_ThrowMethodAccessException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_FIELD_ACCESS_EXCEPTION,JIT_ThrowFieldAccessException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CLASS_ACCESS_EXCEPTION,JIT_ThrowClassAccessException, CORINFO_HELP_SIG_REG_ONLY) #ifdef FEATURE_EH_FUNCLETS JITHELPER(CORINFO_HELP_ENDCATCH, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_ENDCATCH, JIT_EndCatch, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #endif JITHELPER(CORINFO_HELP_MON_ENTER, JIT_MonEnterWorker, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_MON_EXIT, JIT_MonExitWorker, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_MON_ENTER_STATIC, JIT_MonEnterStatic,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_MON_EXIT_STATIC, JIT_MonExitStatic,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETCLASSFROMMETHODPARAM, JIT_GetClassFromMethodParam, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSYNCFROMCLASSHANDLE, JIT_GetSyncFromClassHandle, CORINFO_HELP_SIG_REG_ONLY) // GC support DYNAMICJITHELPER(CORINFO_HELP_STOP_FOR_GC, JIT_RareDisableHelper, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_POLL_GC, JIT_PollGC, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_STRESS_GC, JIT_StressGC, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CHECK_OBJ, JIT_CheckObj, CORINFO_HELP_SIG_REG_ONLY) // GC Write barrier support DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF, JIT_WriteBarrier, CORINFO_HELP_SIG_NO_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF, JIT_CheckedWriteBarrier,CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_ASSIGN_REF_ENSURE_NONHEAP, JIT_WriteBarrierEnsureNonHeapTarget,CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_BYREF, JIT_ByRefWriteBarrier,CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_ASSIGN_STRUCT, JIT_StructWriteBarrier,CORINFO_HELP_SIG_4_STACK) // Accessing fields JITHELPER(CORINFO_HELP_GETFIELD8, JIT_GetField8,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELD8, JIT_SetField8,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_GETFIELD16, JIT_GetField16,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELD16, JIT_SetField16,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_GETFIELD32, JIT_GetField32,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELD32, JIT_SetField32,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_GETFIELD64, JIT_GetField64,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELD64, JIT_SetField64,CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_GETFIELDOBJ, JIT_GetFieldObj,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELDOBJ, JIT_SetFieldObj,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_GETFIELDSTRUCT, JIT_GetFieldStruct,CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_SETFIELDSTRUCT, JIT_SetFieldStruct,CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_GETFIELDFLOAT, JIT_GetFieldFloat,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELDFLOAT, JIT_SetFieldFloat,CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_GETFIELDDOUBLE, JIT_GetFieldDouble,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_SETFIELDDOUBLE, JIT_SetFieldDouble,CORINFO_HELP_SIG_8_STACK) JITHELPER(CORINFO_HELP_GETFIELDADDR, JIT_GetFieldAddr,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSTATICFIELDADDR_TLS, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_GETGENERICS_GCSTATIC_BASE, JIT_GetGenericsGCStaticBase,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE, JIT_GetGenericsNonGCStaticBase,CORINFO_HELP_SIG_REG_ONLY) #ifdef TARGET_X86 DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, NULL, CORINFO_HELP_SIG_REG_ONLY) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,NULL, CORINFO_HELP_SIG_REG_ONLY) #else DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, JIT_GetSharedGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, JIT_GetSharedNonGCStaticBase, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, JIT_GetSharedGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR,JIT_GetSharedNonGCStaticBaseNoCtor, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #endif JITHELPER(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCStaticBaseDynamicClass,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCStaticBaseDynamicClass,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS, JIT_ClassInitDynamicClass,CORINFO_HELP_SIG_REG_ONLY) // Thread statics JITHELPER(CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE, JIT_GetGenericsGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE, JIT_GetGenericsNonGCThreadStaticBase,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) // Debugger JITHELPER(CORINFO_HELP_DBG_IS_JUST_MY_CODE, JIT_DbgIsJustMyCode,CORINFO_HELP_SIG_REG_ONLY) /* Profiling enter/leave probe addresses */ DYNAMICJITHELPER(CORINFO_HELP_PROF_FCN_ENTER, JIT_ProfilerEnterLeaveTailcallStub, CORINFO_HELP_SIG_4_STACK) DYNAMICJITHELPER(CORINFO_HELP_PROF_FCN_LEAVE, JIT_ProfilerEnterLeaveTailcallStub, CORINFO_HELP_SIG_4_STACK) DYNAMICJITHELPER(CORINFO_HELP_PROF_FCN_TAILCALL, JIT_ProfilerEnterLeaveTailcallStub, CORINFO_HELP_SIG_4_STACK) // Miscellaneous JITHELPER(CORINFO_HELP_BBT_FCN_ENTER, JIT_LogMethodEnter,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_PINVOKE_CALLI, GenericPInvokeCalliHelper, CORINFO_HELP_SIG_NO_ALIGN_STUB) #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) JITHELPER(CORINFO_HELP_TAILCALL, JIT_TailCall, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_TAILCALL, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #endif JITHELPER(CORINFO_HELP_GETCURRENTMANAGEDTHREADID, JIT_GetCurrentManagedThreadId, CORINFO_HELP_SIG_REG_ONLY) #ifdef TARGET_64BIT JITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, JIT_InitPInvokeFrame, CORINFO_HELP_SIG_REG_ONLY) #else DYNAMICJITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, NULL, CORINFO_HELP_SIG_REG_ONLY) #endif #ifdef TARGET_X86 JITHELPER(CORINFO_HELP_MEMSET, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) JITHELPER(CORINFO_HELP_MEMCPY, NULL, CORINFO_HELP_SIG_CANNOT_USE_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_MEMSET, JIT_MemSet, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_MEMCPY, JIT_MemCpy, CORINFO_HELP_SIG_REG_ONLY) #endif // Generics JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_METHOD, JIT_GenericHandleMethod, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG,JIT_GenericHandleMethodLogging, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_CLASS, JIT_GenericHandleClass, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG, JIT_GenericHandleClassLogging, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE, JIT_GetRuntimeType, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_METHODDESC_TO_STUBRUNTIMEMETHOD, JIT_GetRuntimeMethodStub,CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_FIELDDESC_TO_STUBRUNTIMEFIELD, JIT_GetRuntimeFieldStub, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE, JIT_GetRuntimeType, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE_MAYBENULL, JIT_GetRuntimeType_MaybeNull, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_ARE_TYPES_EQUIVALENT, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_VIRTUAL_FUNC_PTR, JIT_VirtualFunctionPointer, CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_READYTORUN_NEW, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_NEWARR_1, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_ISINSTANCEOF, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_CHKCAST, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_VIRTUAL_FUNC_PTR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_HANDLE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_DELEGATE_CTOR, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_READYTORUN_GENERIC_STATIC_BASE, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) #ifdef FEATURE_EH_FUNCLETS JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE, ProcessCLRException, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, ProcessCLRException,CORINFO_HELP_SIG_UNDEF) #else // FEATURE_EH_FUNCLETS JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET, NULL, CORINFO_HELP_SIG_UNDEF) #endif // !FEATURE_EH_FUNCLETS #ifdef TARGET_X86 DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF_EAX, JIT_WriteBarrierEAX, CORINFO_HELP_SIG_NO_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF_EBX, JIT_WriteBarrierEBX, CORINFO_HELP_SIG_NO_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF_ECX, JIT_WriteBarrierECX, CORINFO_HELP_SIG_NO_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF_ESI, JIT_WriteBarrierESI, CORINFO_HELP_SIG_NO_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF_EDI, JIT_WriteBarrierEDI, CORINFO_HELP_SIG_NO_ALIGN_STUB) DYNAMICJITHELPER(CORINFO_HELP_ASSIGN_REF_EBP, JIT_WriteBarrierEBP, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, JIT_CheckedWriteBarrierEAX, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, JIT_CheckedWriteBarrierEBX, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, JIT_CheckedWriteBarrierECX, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, JIT_CheckedWriteBarrierESI, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, JIT_CheckedWriteBarrierEDI, CORINFO_HELP_SIG_NO_ALIGN_STUB) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, JIT_CheckedWriteBarrierEBP, CORINFO_HELP_SIG_NO_ALIGN_STUB) #else JITHELPER(CORINFO_HELP_ASSIGN_REF_EAX, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_ASSIGN_REF_EBX, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_ASSIGN_REF_ECX, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_ASSIGN_REF_ESI, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_ASSIGN_REF_EDI, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_ASSIGN_REF_EBP, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EAX, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBX, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ECX, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_ESI, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EDI, NULL, CORINFO_HELP_SIG_UNDEF) JITHELPER(CORINFO_HELP_CHECKED_ASSIGN_REF_EBP, NULL, CORINFO_HELP_SIG_UNDEF) #endif JITHELPER(CORINFO_HELP_LOOP_CLONE_CHOICE_ADDR, JIT_LoopCloneChoiceAddr, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_DEBUG_LOG_LOOP_CLONING, JIT_DebugLogLoopCloning, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROW_ARGUMENTEXCEPTION, JIT_ThrowArgumentException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROW_ARGUMENTOUTOFRANGEEXCEPTION, JIT_ThrowArgumentOutOfRangeException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROW_NOT_IMPLEMENTED, JIT_ThrowNotImplementedException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROW_PLATFORM_NOT_SUPPORTED, JIT_ThrowPlatformNotSupportedException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROW_TYPE_NOT_SUPPORTED, JIT_ThrowTypeNotSupportedException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_THROW_AMBIGUOUS_RESOLUTION_EXCEPTION, JIT_ThrowAmbiguousResolutionException, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_PINVOKE_BEGIN, JIT_PInvokeBegin, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_PINVOKE_END, JIT_PInvokeEnd, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER, JIT_ReversePInvokeEnter, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_ENTER_TRACK_TRANSITIONS, JIT_ReversePInvokeEnterTrackTransitions, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT, JIT_ReversePInvokeExit, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_JIT_REVERSE_PINVOKE_EXIT_TRACK_TRANSITIONS, JIT_ReversePInvokeExitTrackTransitions, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GVMLOOKUP_FOR_SLOT, NULL, CORINFO_HELP_SIG_NO_ALIGN_STUB) #if !defined(TARGET_ARM64) && !defined(TARGET_LOONGARCH64) JITHELPER(CORINFO_HELP_STACK_PROBE, JIT_StackProbe, CORINFO_HELP_SIG_REG_ONLY) #else JITHELPER(CORINFO_HELP_STACK_PROBE, NULL, CORINFO_HELP_SIG_UNDEF) #endif JITHELPER(CORINFO_HELP_PATCHPOINT, JIT_Patchpoint, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_PARTIAL_COMPILATION_PATCHPOINT, JIT_PartialCompilationPatchpoint, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CLASSPROFILE32, JIT_ClassProfile32, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_CLASSPROFILE64, JIT_ClassProfile64, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_DELEGATEPROFILE32, JIT_DelegateProfile32, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_DELEGATEPROFILE64, JIT_DelegateProfile64, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_VTABLEPROFILE32, JIT_VTableProfile32, CORINFO_HELP_SIG_4_STACK) JITHELPER(CORINFO_HELP_VTABLEPROFILE64, JIT_VTableProfile64, CORINFO_HELP_SIG_4_STACK) #if defined(TARGET_AMD64) || defined(TARGET_ARM64) JITHELPER(CORINFO_HELP_VALIDATE_INDIRECT_CALL, JIT_ValidateIndirectCall, CORINFO_HELP_SIG_REG_ONLY) #ifdef TARGET_AMD64 DYNAMICJITHELPER(CORINFO_HELP_DISPATCH_INDIRECT_CALL, JIT_DispatchIndirectCall, CORINFO_HELP_SIG_REG_ONLY) #else JITHELPER(CORINFO_HELP_DISPATCH_INDIRECT_CALL, JIT_DispatchIndirectCall, CORINFO_HELP_SIG_REG_ONLY) #endif #else JITHELPER(CORINFO_HELP_VALIDATE_INDIRECT_CALL, NULL, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_DISPATCH_INDIRECT_CALL, NULL, CORINFO_HELP_SIG_REG_ONLY) #endif #undef JITHELPER #undef DYNAMICJITHELPER #undef JITHELPER #undef DYNAMICJITHELPER ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/livedatatarget.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // // Define a Data-Target for a live process. // //***************************************************************************** #ifndef _LIVEPROC_DATATARGET_H_ #define _LIVEPROC_DATATARGET_H_ // Defines the Data-Target and other public interfaces. // Does not include IXClrData definitions. #include #ifndef TARGET_UNIX //--------------------------------------------------------------------------------------- // // Provides a simple legacy data-target implementation for a live, local, process. // Note that in arrowhead, most debuggers use ICorDebugDataTarget, and we have // implementations of this in MDbg. // class LiveProcDataTarget : public ICLRDataTarget { public: LiveProcDataTarget(HANDLE process, DWORD processId, CLRDATA_ADDRESS baseAddressOfEngine = NULL); // // IUnknown. // // This class is intended to be kept on the stack // or as a member and does not maintain a refcount. // STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ); STDMETHOD_(ULONG, AddRef)( THIS ); STDMETHOD_(ULONG, Release)( THIS ); // // ICLRDataTarget. // virtual HRESULT STDMETHODCALLTYPE GetMachineType( /* [out] */ ULONG32 *machine); virtual HRESULT STDMETHODCALLTYPE GetPointerSize( /* [out] */ ULONG32 *size); virtual HRESULT STDMETHODCALLTYPE GetImageBase( /* [string][in] */ LPCWSTR name, /* [out] */ CLRDATA_ADDRESS *base); virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ PBYTE buffer, /* [in] */ ULONG32 request, /* [optional][out] */ ULONG32 *done); virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ PBYTE buffer, /* [in] */ ULONG32 request, /* [optional][out] */ ULONG32 *done); virtual HRESULT STDMETHODCALLTYPE GetTLSValue( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS* value); virtual HRESULT STDMETHODCALLTYPE SetTLSValue( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value); virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( /* [out] */ ULONG32* threadID); virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [out, size_is(contextSize)] */ PBYTE context); virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [in, size_is(contextSize)] */ PBYTE context); virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); private: HANDLE m_process; DWORD m_processId; CLRDATA_ADDRESS m_baseAddressOfEngine; }; #endif // TARGET_UNIX #endif // _LIVEPROC_DATATARGET_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/llvm/Dwarf.def ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // ============================================================================== // LLVM Release License // ============================================================================== // University of Illinois/NCSA // Open Source License // // Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. // All rights reserved. // // Developed by: // // LLVM Team // // University of Illinois at Urbana-Champaign // // http://llvm.org // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal with // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimers. // // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimers in the // documentation and/or other materials provided with the distribution. // // * Neither the names of the LLVM Team, University of Illinois at // Urbana-Champaign, nor the names of its contributors may be used to // endorse or promote products derived from this Software without specific // prior written permission. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE // SOFTWARE. //===----------------------------------------------------------------------===// // // Macros for running through Dwarf enumerators. // //===----------------------------------------------------------------------===// // TODO: Add other DW-based macros. #if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \ defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ defined HANDLE_DW_VIRTUALITY) #error "Missing macro definition of HANDLE_DW*" #endif #ifndef HANDLE_DW_TAG #define HANDLE_DW_TAG(ID, NAME) #endif #ifndef HANDLE_DW_OP #define HANDLE_DW_OP(ID, NAME) #endif #ifndef HANDLE_DW_LANG #define HANDLE_DW_LANG(ID, NAME) #endif #ifndef HANDLE_DW_ATE #define HANDLE_DW_ATE(ID, NAME) #endif #ifndef HANDLE_DW_VIRTUALITY #define HANDLE_DW_VIRTUALITY(ID, NAME) #endif HANDLE_DW_TAG(0x0001, array_type) HANDLE_DW_TAG(0x0002, class_type) HANDLE_DW_TAG(0x0003, entry_point) HANDLE_DW_TAG(0x0004, enumeration_type) HANDLE_DW_TAG(0x0005, formal_parameter) HANDLE_DW_TAG(0x0008, imported_declaration) HANDLE_DW_TAG(0x000a, label) HANDLE_DW_TAG(0x000b, lexical_block) HANDLE_DW_TAG(0x000d, member) HANDLE_DW_TAG(0x000f, pointer_type) HANDLE_DW_TAG(0x0010, reference_type) HANDLE_DW_TAG(0x0011, compile_unit) HANDLE_DW_TAG(0x0012, string_type) HANDLE_DW_TAG(0x0013, structure_type) HANDLE_DW_TAG(0x0015, subroutine_type) HANDLE_DW_TAG(0x0016, typedef) HANDLE_DW_TAG(0x0017, union_type) HANDLE_DW_TAG(0x0018, unspecified_parameters) HANDLE_DW_TAG(0x0019, variant) HANDLE_DW_TAG(0x001a, common_block) HANDLE_DW_TAG(0x001b, common_inclusion) HANDLE_DW_TAG(0x001c, inheritance) HANDLE_DW_TAG(0x001d, inlined_subroutine) HANDLE_DW_TAG(0x001e, module) HANDLE_DW_TAG(0x001f, ptr_to_member_type) HANDLE_DW_TAG(0x0020, set_type) HANDLE_DW_TAG(0x0021, subrange_type) HANDLE_DW_TAG(0x0022, with_stmt) HANDLE_DW_TAG(0x0023, access_declaration) HANDLE_DW_TAG(0x0024, base_type) HANDLE_DW_TAG(0x0025, catch_block) HANDLE_DW_TAG(0x0026, const_type) HANDLE_DW_TAG(0x0027, constant) HANDLE_DW_TAG(0x0028, enumerator) HANDLE_DW_TAG(0x0029, file_type) HANDLE_DW_TAG(0x002a, friend) HANDLE_DW_TAG(0x002b, namelist) HANDLE_DW_TAG(0x002c, namelist_item) HANDLE_DW_TAG(0x002d, packed_type) HANDLE_DW_TAG(0x002e, subprogram) HANDLE_DW_TAG(0x002f, template_type_parameter) HANDLE_DW_TAG(0x0030, template_value_parameter) HANDLE_DW_TAG(0x0031, thrown_type) HANDLE_DW_TAG(0x0032, try_block) HANDLE_DW_TAG(0x0033, variant_part) HANDLE_DW_TAG(0x0034, variable) HANDLE_DW_TAG(0x0035, volatile_type) HANDLE_DW_TAG(0x0036, dwarf_procedure) HANDLE_DW_TAG(0x0037, restrict_type) HANDLE_DW_TAG(0x0038, interface_type) HANDLE_DW_TAG(0x0039, namespace) HANDLE_DW_TAG(0x003a, imported_module) HANDLE_DW_TAG(0x003b, unspecified_type) HANDLE_DW_TAG(0x003c, partial_unit) HANDLE_DW_TAG(0x003d, imported_unit) HANDLE_DW_TAG(0x003f, condition) HANDLE_DW_TAG(0x0040, shared_type) HANDLE_DW_TAG(0x0041, type_unit) HANDLE_DW_TAG(0x0042, rvalue_reference_type) HANDLE_DW_TAG(0x0043, template_alias) // New in DWARF v5. HANDLE_DW_TAG(0x0044, coarray_type) HANDLE_DW_TAG(0x0045, generic_subrange) HANDLE_DW_TAG(0x0046, dynamic_type) // User-defined tags. HANDLE_DW_TAG(0x4081, MIPS_loop) HANDLE_DW_TAG(0x4101, format_label) HANDLE_DW_TAG(0x4102, function_template) HANDLE_DW_TAG(0x4103, class_template) HANDLE_DW_TAG(0x4106, GNU_template_template_param) HANDLE_DW_TAG(0x4107, GNU_template_parameter_pack) HANDLE_DW_TAG(0x4108, GNU_formal_parameter_pack) HANDLE_DW_TAG(0x4200, APPLE_property) HANDLE_DW_TAG(0xb000, BORLAND_property) HANDLE_DW_TAG(0xb001, BORLAND_Delphi_string) HANDLE_DW_TAG(0xb002, BORLAND_Delphi_dynamic_array) HANDLE_DW_TAG(0xb003, BORLAND_Delphi_set) HANDLE_DW_TAG(0xb004, BORLAND_Delphi_variant) HANDLE_DW_OP(0x03, addr) HANDLE_DW_OP(0x06, deref) HANDLE_DW_OP(0x08, const1u) HANDLE_DW_OP(0x09, const1s) HANDLE_DW_OP(0x0a, const2u) HANDLE_DW_OP(0x0b, const2s) HANDLE_DW_OP(0x0c, const4u) HANDLE_DW_OP(0x0d, const4s) HANDLE_DW_OP(0x0e, const8u) HANDLE_DW_OP(0x0f, const8s) HANDLE_DW_OP(0x10, constu) HANDLE_DW_OP(0x11, consts) HANDLE_DW_OP(0x12, dup) HANDLE_DW_OP(0x13, drop) HANDLE_DW_OP(0x14, over) HANDLE_DW_OP(0x15, pick) HANDLE_DW_OP(0x16, swap) HANDLE_DW_OP(0x17, rot) HANDLE_DW_OP(0x18, xderef) HANDLE_DW_OP(0x19, abs) HANDLE_DW_OP(0x1a, and) HANDLE_DW_OP(0x1b, div) HANDLE_DW_OP(0x1c, minus) HANDLE_DW_OP(0x1d, mod) HANDLE_DW_OP(0x1e, mul) HANDLE_DW_OP(0x1f, neg) HANDLE_DW_OP(0x20, not) HANDLE_DW_OP(0x21, or ) HANDLE_DW_OP(0x22, plus) HANDLE_DW_OP(0x23, plus_uconst) HANDLE_DW_OP(0x24, shl) HANDLE_DW_OP(0x25, shr) HANDLE_DW_OP(0x26, shra) HANDLE_DW_OP(0x27, xor) HANDLE_DW_OP(0x2f, skip) HANDLE_DW_OP(0x28, bra) HANDLE_DW_OP(0x29, eq) HANDLE_DW_OP(0x2a, ge) HANDLE_DW_OP(0x2b, gt) HANDLE_DW_OP(0x2c, le) HANDLE_DW_OP(0x2d, lt) HANDLE_DW_OP(0x2e, ne) HANDLE_DW_OP(0x30, lit0) HANDLE_DW_OP(0x31, lit1) HANDLE_DW_OP(0x32, lit2) HANDLE_DW_OP(0x33, lit3) HANDLE_DW_OP(0x34, lit4) HANDLE_DW_OP(0x35, lit5) HANDLE_DW_OP(0x36, lit6) HANDLE_DW_OP(0x37, lit7) HANDLE_DW_OP(0x38, lit8) HANDLE_DW_OP(0x39, lit9) HANDLE_DW_OP(0x3a, lit10) HANDLE_DW_OP(0x3b, lit11) HANDLE_DW_OP(0x3c, lit12) HANDLE_DW_OP(0x3d, lit13) HANDLE_DW_OP(0x3e, lit14) HANDLE_DW_OP(0x3f, lit15) HANDLE_DW_OP(0x40, lit16) HANDLE_DW_OP(0x41, lit17) HANDLE_DW_OP(0x42, lit18) HANDLE_DW_OP(0x43, lit19) HANDLE_DW_OP(0x44, lit20) HANDLE_DW_OP(0x45, lit21) HANDLE_DW_OP(0x46, lit22) HANDLE_DW_OP(0x47, lit23) HANDLE_DW_OP(0x48, lit24) HANDLE_DW_OP(0x49, lit25) HANDLE_DW_OP(0x4a, lit26) HANDLE_DW_OP(0x4b, lit27) HANDLE_DW_OP(0x4c, lit28) HANDLE_DW_OP(0x4d, lit29) HANDLE_DW_OP(0x4e, lit30) HANDLE_DW_OP(0x4f, lit31) HANDLE_DW_OP(0x50, reg0) HANDLE_DW_OP(0x51, reg1) HANDLE_DW_OP(0x52, reg2) HANDLE_DW_OP(0x53, reg3) HANDLE_DW_OP(0x54, reg4) HANDLE_DW_OP(0x55, reg5) HANDLE_DW_OP(0x56, reg6) HANDLE_DW_OP(0x57, reg7) HANDLE_DW_OP(0x58, reg8) HANDLE_DW_OP(0x59, reg9) HANDLE_DW_OP(0x5a, reg10) HANDLE_DW_OP(0x5b, reg11) HANDLE_DW_OP(0x5c, reg12) HANDLE_DW_OP(0x5d, reg13) HANDLE_DW_OP(0x5e, reg14) HANDLE_DW_OP(0x5f, reg15) HANDLE_DW_OP(0x60, reg16) HANDLE_DW_OP(0x61, reg17) HANDLE_DW_OP(0x62, reg18) HANDLE_DW_OP(0x63, reg19) HANDLE_DW_OP(0x64, reg20) HANDLE_DW_OP(0x65, reg21) HANDLE_DW_OP(0x66, reg22) HANDLE_DW_OP(0x67, reg23) HANDLE_DW_OP(0x68, reg24) HANDLE_DW_OP(0x69, reg25) HANDLE_DW_OP(0x6a, reg26) HANDLE_DW_OP(0x6b, reg27) HANDLE_DW_OP(0x6c, reg28) HANDLE_DW_OP(0x6d, reg29) HANDLE_DW_OP(0x6e, reg30) HANDLE_DW_OP(0x6f, reg31) HANDLE_DW_OP(0x70, breg0) HANDLE_DW_OP(0x71, breg1) HANDLE_DW_OP(0x72, breg2) HANDLE_DW_OP(0x73, breg3) HANDLE_DW_OP(0x74, breg4) HANDLE_DW_OP(0x75, breg5) HANDLE_DW_OP(0x76, breg6) HANDLE_DW_OP(0x77, breg7) HANDLE_DW_OP(0x78, breg8) HANDLE_DW_OP(0x79, breg9) HANDLE_DW_OP(0x7a, breg10) HANDLE_DW_OP(0x7b, breg11) HANDLE_DW_OP(0x7c, breg12) HANDLE_DW_OP(0x7d, breg13) HANDLE_DW_OP(0x7e, breg14) HANDLE_DW_OP(0x7f, breg15) HANDLE_DW_OP(0x80, breg16) HANDLE_DW_OP(0x81, breg17) HANDLE_DW_OP(0x82, breg18) HANDLE_DW_OP(0x83, breg19) HANDLE_DW_OP(0x84, breg20) HANDLE_DW_OP(0x85, breg21) HANDLE_DW_OP(0x86, breg22) HANDLE_DW_OP(0x87, breg23) HANDLE_DW_OP(0x88, breg24) HANDLE_DW_OP(0x89, breg25) HANDLE_DW_OP(0x8a, breg26) HANDLE_DW_OP(0x8b, breg27) HANDLE_DW_OP(0x8c, breg28) HANDLE_DW_OP(0x8d, breg29) HANDLE_DW_OP(0x8e, breg30) HANDLE_DW_OP(0x8f, breg31) HANDLE_DW_OP(0x90, regx) HANDLE_DW_OP(0x91, fbreg) HANDLE_DW_OP(0x92, bregx) HANDLE_DW_OP(0x93, piece) HANDLE_DW_OP(0x94, deref_size) HANDLE_DW_OP(0x95, xderef_size) HANDLE_DW_OP(0x96, nop) HANDLE_DW_OP(0x97, push_object_address) HANDLE_DW_OP(0x98, call2) HANDLE_DW_OP(0x99, call4) HANDLE_DW_OP(0x9a, call_ref) HANDLE_DW_OP(0x9b, form_tls_address) HANDLE_DW_OP(0x9c, call_frame_cfa) HANDLE_DW_OP(0x9d, bit_piece) HANDLE_DW_OP(0x9e, implicit_value) HANDLE_DW_OP(0x9f, stack_value) // Extensions for GNU-style thread-local storage. HANDLE_DW_OP(0xe0, GNU_push_tls_address) // Extensions for Fission proposal. HANDLE_DW_OP(0xfb, GNU_addr_index) HANDLE_DW_OP(0xfc, GNU_const_index) // DWARF languages. HANDLE_DW_LANG(0x0001, C89) HANDLE_DW_LANG(0x0002, C) HANDLE_DW_LANG(0x0003, Ada83) HANDLE_DW_LANG(0x0004, C_plus_plus) HANDLE_DW_LANG(0x0005, Cobol74) HANDLE_DW_LANG(0x0006, Cobol85) HANDLE_DW_LANG(0x0007, Fortran77) HANDLE_DW_LANG(0x0008, Fortran90) HANDLE_DW_LANG(0x0009, Pascal83) HANDLE_DW_LANG(0x000a, Modula2) HANDLE_DW_LANG(0x000b, Java) HANDLE_DW_LANG(0x000c, C99) HANDLE_DW_LANG(0x000d, Ada95) HANDLE_DW_LANG(0x000e, Fortran95) HANDLE_DW_LANG(0x000f, PLI) HANDLE_DW_LANG(0x0010, ObjC) HANDLE_DW_LANG(0x0011, ObjC_plus_plus) HANDLE_DW_LANG(0x0012, UPC) HANDLE_DW_LANG(0x0013, D) // New in DWARF 5: HANDLE_DW_LANG(0x0014, Python) HANDLE_DW_LANG(0x0015, OpenCL) HANDLE_DW_LANG(0x0016, Go) HANDLE_DW_LANG(0x0017, Modula3) HANDLE_DW_LANG(0x0018, Haskell) HANDLE_DW_LANG(0x0019, C_plus_plus_03) HANDLE_DW_LANG(0x001a, C_plus_plus_11) HANDLE_DW_LANG(0x001b, OCaml) HANDLE_DW_LANG(0x001c, Rust) HANDLE_DW_LANG(0x001d, C11) HANDLE_DW_LANG(0x001e, Swift) HANDLE_DW_LANG(0x001f, Julia) HANDLE_DW_LANG(0x0020, Dylan) HANDLE_DW_LANG(0x0021, C_plus_plus_14) HANDLE_DW_LANG(0x0022, Fortran03) HANDLE_DW_LANG(0x0023, Fortran08) HANDLE_DW_LANG(0x8001, Mips_Assembler) HANDLE_DW_LANG(0xb000, BORLAND_Delphi) // DWARF attribute type encodings. HANDLE_DW_ATE(0x01, address) HANDLE_DW_ATE(0x02, boolean) HANDLE_DW_ATE(0x03, complex_float) HANDLE_DW_ATE(0x04, float) HANDLE_DW_ATE(0x05, signed) HANDLE_DW_ATE(0x06, signed_char) HANDLE_DW_ATE(0x07, unsigned) HANDLE_DW_ATE(0x08, unsigned_char) HANDLE_DW_ATE(0x09, imaginary_float) HANDLE_DW_ATE(0x0a, packed_decimal) HANDLE_DW_ATE(0x0b, numeric_string) HANDLE_DW_ATE(0x0c, edited) HANDLE_DW_ATE(0x0d, signed_fixed) HANDLE_DW_ATE(0x0e, unsigned_fixed) HANDLE_DW_ATE(0x0f, decimal_float) HANDLE_DW_ATE(0x10, UTF) // DWARF virtuality codes. HANDLE_DW_VIRTUALITY(0x00, none) HANDLE_DW_VIRTUALITY(0x01, virtual) HANDLE_DW_VIRTUALITY(0x02, pure_virtual) #undef HANDLE_DW_TAG #undef HANDLE_DW_OP #undef HANDLE_DW_LANG #undef HANDLE_DW_ATE #undef HANDLE_DW_VIRTUALITY ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/llvm/Dwarf.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // ============================================================================== // LLVM Release License // ============================================================================== // University of Illinois/NCSA // Open Source License // // Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. // All rights reserved. // // Developed by: // // LLVM Team // // University of Illinois at Urbana-Champaign // // http://llvm.org // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal with // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimers. // // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimers in the // documentation and/or other materials provided with the distribution. // // * Neither the names of the LLVM Team, University of Illinois at // Urbana-Champaign, nor the names of its contributors may be used to // endorse or promote products derived from this Software without specific // prior written permission. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE // SOFTWARE. //===----------------------------------------------------------------------===// // // \file // \brief This file contains constants used for implementing Dwarf // debug support. // // For details on the Dwarf specfication see the latest DWARF Debugging // Information Format standard document on http://www.dwarfstd.org. This // file often includes support for non-released standard features. // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H //===----------------------------------------------------------------------===// // Dwarf constants as gleaned from the DWARF Debugging Information Format V.4 // reference manual http://www.dwarfstd.org/. // // Do not mix the following two enumerations sets. DW_TAG_invalid changes the // enumeration base type. enum LLVMConstants : uint32_t { // LLVM mock tags (see also llvm/Support/Dwarf.def). DW_TAG_invalid = ~0U, // Tag for invalid results. DW_VIRTUALITY_invalid = ~0U, // Virtuality for invalid results. DW_MACINFO_invalid = ~0U, // Macinfo type for invalid results. // Other constants. DWARF_VERSION = 4, // Default dwarf version we output. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. DW_ARANGES_VERSION = 2 // Section version number for .debug_aranges. }; // Special ID values that distinguish a CIE from a FDE in DWARF CFI. // Not inside an enum because a 64-bit value is needed. const uint32_t DW_CIE_ID = UINT32_MAX; const uint64_t DW64_CIE_ID = UINT64_MAX; enum Tag : uint16_t { #define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID, #include "Dwarf.def" DW_TAG_lo_user = 0x4080, DW_TAG_hi_user = 0xffff, DW_TAG_user_base = 0x1000 // Recommended base for user tags. }; inline bool isType(Tag T) { switch (T) { case DW_TAG_array_type: case DW_TAG_class_type: case DW_TAG_interface_type: case DW_TAG_enumeration_type: case DW_TAG_pointer_type: case DW_TAG_reference_type: case DW_TAG_rvalue_reference_type: case DW_TAG_string_type: case DW_TAG_structure_type: case DW_TAG_subroutine_type: case DW_TAG_union_type: case DW_TAG_ptr_to_member_type: case DW_TAG_set_type: case DW_TAG_subrange_type: case DW_TAG_base_type: case DW_TAG_const_type: case DW_TAG_file_type: case DW_TAG_packed_type: case DW_TAG_volatile_type: case DW_TAG_typedef: return true; default: return false; } } enum Attribute : uint16_t { // Attributes DW_AT_sibling = 0x01, DW_AT_location = 0x02, DW_AT_name = 0x03, DW_AT_ordering = 0x09, DW_AT_byte_size = 0x0b, DW_AT_bit_offset = 0x0c, DW_AT_bit_size = 0x0d, DW_AT_stmt_list = 0x10, DW_AT_low_pc = 0x11, DW_AT_high_pc = 0x12, DW_AT_language = 0x13, DW_AT_discr = 0x15, DW_AT_discr_value = 0x16, DW_AT_visibility = 0x17, DW_AT_import = 0x18, DW_AT_string_length = 0x19, DW_AT_common_reference = 0x1a, DW_AT_comp_dir = 0x1b, DW_AT_const_value = 0x1c, DW_AT_containing_type = 0x1d, DW_AT_default_value = 0x1e, DW_AT_inline = 0x20, DW_AT_is_optional = 0x21, DW_AT_lower_bound = 0x22, DW_AT_producer = 0x25, DW_AT_prototyped = 0x27, DW_AT_return_addr = 0x2a, DW_AT_start_scope = 0x2c, DW_AT_bit_stride = 0x2e, DW_AT_upper_bound = 0x2f, DW_AT_abstract_origin = 0x31, DW_AT_accessibility = 0x32, DW_AT_address_class = 0x33, DW_AT_artificial = 0x34, DW_AT_base_types = 0x35, DW_AT_calling_convention = 0x36, DW_AT_count = 0x37, DW_AT_data_member_location = 0x38, DW_AT_decl_column = 0x39, DW_AT_decl_file = 0x3a, DW_AT_decl_line = 0x3b, DW_AT_declaration = 0x3c, DW_AT_discr_list = 0x3d, DW_AT_encoding = 0x3e, DW_AT_external = 0x3f, DW_AT_frame_base = 0x40, DW_AT_friend = 0x41, DW_AT_identifier_case = 0x42, DW_AT_macro_info = 0x43, DW_AT_namelist_item = 0x44, DW_AT_priority = 0x45, DW_AT_segment = 0x46, DW_AT_specification = 0x47, DW_AT_static_link = 0x48, DW_AT_type = 0x49, DW_AT_use_location = 0x4a, DW_AT_variable_parameter = 0x4b, DW_AT_virtuality = 0x4c, DW_AT_vtable_elem_location = 0x4d, DW_AT_allocated = 0x4e, DW_AT_associated = 0x4f, DW_AT_data_location = 0x50, DW_AT_byte_stride = 0x51, DW_AT_entry_pc = 0x52, DW_AT_use_UTF8 = 0x53, DW_AT_extension = 0x54, DW_AT_ranges = 0x55, DW_AT_trampoline = 0x56, DW_AT_call_column = 0x57, DW_AT_call_file = 0x58, DW_AT_call_line = 0x59, DW_AT_description = 0x5a, DW_AT_binary_scale = 0x5b, DW_AT_decimal_scale = 0x5c, DW_AT_small = 0x5d, DW_AT_decimal_sign = 0x5e, DW_AT_digit_count = 0x5f, DW_AT_picture_string = 0x60, DW_AT_mutable = 0x61, DW_AT_threads_scaled = 0x62, DW_AT_explicit = 0x63, DW_AT_object_pointer = 0x64, DW_AT_endianity = 0x65, DW_AT_elemental = 0x66, DW_AT_pure = 0x67, DW_AT_recursive = 0x68, DW_AT_signature = 0x69, DW_AT_main_subprogram = 0x6a, DW_AT_data_bit_offset = 0x6b, DW_AT_const_expr = 0x6c, DW_AT_enum_class = 0x6d, DW_AT_linkage_name = 0x6e, // New in DWARF 5: DW_AT_string_length_bit_size = 0x6f, DW_AT_string_length_byte_size = 0x70, DW_AT_rank = 0x71, DW_AT_str_offsets_base = 0x72, DW_AT_addr_base = 0x73, DW_AT_ranges_base = 0x74, DW_AT_dwo_id = 0x75, DW_AT_dwo_name = 0x76, DW_AT_reference = 0x77, DW_AT_rvalue_reference = 0x78, DW_AT_macros = 0x79, DW_AT_lo_user = 0x2000, DW_AT_hi_user = 0x3fff, DW_AT_MIPS_loop_begin = 0x2002, DW_AT_MIPS_tail_loop_begin = 0x2003, DW_AT_MIPS_epilog_begin = 0x2004, DW_AT_MIPS_loop_unroll_factor = 0x2005, DW_AT_MIPS_software_pipeline_depth = 0x2006, DW_AT_MIPS_linkage_name = 0x2007, DW_AT_MIPS_stride = 0x2008, DW_AT_MIPS_abstract_name = 0x2009, DW_AT_MIPS_clone_origin = 0x200a, DW_AT_MIPS_has_inlines = 0x200b, DW_AT_MIPS_stride_byte = 0x200c, DW_AT_MIPS_stride_elem = 0x200d, DW_AT_MIPS_ptr_dopetype = 0x200e, DW_AT_MIPS_allocatable_dopetype = 0x200f, DW_AT_MIPS_assumed_shape_dopetype = 0x2010, // This one appears to have only been implemented by Open64 for // fortran and may conflict with other extensions. DW_AT_MIPS_assumed_size = 0x2011, // GNU extensions DW_AT_sf_names = 0x2101, DW_AT_src_info = 0x2102, DW_AT_mac_info = 0x2103, DW_AT_src_coords = 0x2104, DW_AT_body_begin = 0x2105, DW_AT_body_end = 0x2106, DW_AT_GNU_vector = 0x2107, DW_AT_GNU_template_name = 0x2110, DW_AT_GNU_odr_signature = 0x210f, DW_AT_GNU_macros = 0x2119, // Extensions for Fission proposal. DW_AT_GNU_dwo_name = 0x2130, DW_AT_GNU_dwo_id = 0x2131, DW_AT_GNU_ranges_base = 0x2132, DW_AT_GNU_addr_base = 0x2133, DW_AT_GNU_pubnames = 0x2134, DW_AT_GNU_pubtypes = 0x2135, DW_AT_GNU_discriminator = 0x2136, // Borland extensions. DW_AT_BORLAND_property_read = 0x3b11, DW_AT_BORLAND_property_write = 0x3b12, DW_AT_BORLAND_property_implements = 0x3b13, DW_AT_BORLAND_property_index = 0x3b14, DW_AT_BORLAND_property_default = 0x3b15, DW_AT_BORLAND_Delphi_unit = 0x3b20, DW_AT_BORLAND_Delphi_class = 0x3b21, DW_AT_BORLAND_Delphi_record = 0x3b22, DW_AT_BORLAND_Delphi_metaclass = 0x3b23, DW_AT_BORLAND_Delphi_constructor = 0x3b24, DW_AT_BORLAND_Delphi_destructor = 0x3b25, DW_AT_BORLAND_Delphi_anonymous_method = 0x3b26, DW_AT_BORLAND_Delphi_interface = 0x3b27, DW_AT_BORLAND_Delphi_ABI = 0x3b28, DW_AT_BORLAND_Delphi_return = 0x3b29, DW_AT_BORLAND_Delphi_frameptr = 0x3b30, DW_AT_BORLAND_closure = 0x3b31, // LLVM project extensions. DW_AT_LLVM_include_path = 0x3e00, DW_AT_LLVM_config_macros = 0x3e01, DW_AT_LLVM_isysroot = 0x3e02, // Apple extensions. DW_AT_APPLE_optimized = 0x3fe1, DW_AT_APPLE_flags = 0x3fe2, DW_AT_APPLE_isa = 0x3fe3, DW_AT_APPLE_block = 0x3fe4, DW_AT_APPLE_major_runtime_vers = 0x3fe5, DW_AT_APPLE_runtime_class = 0x3fe6, DW_AT_APPLE_omit_frame_ptr = 0x3fe7, DW_AT_APPLE_property_name = 0x3fe8, DW_AT_APPLE_property_getter = 0x3fe9, DW_AT_APPLE_property_setter = 0x3fea, DW_AT_APPLE_property_attribute = 0x3feb, DW_AT_APPLE_objc_complete_type = 0x3fec, DW_AT_APPLE_property = 0x3fed }; enum Form : uint16_t { // Attribute form encodings DW_FORM_addr = 0x01, DW_FORM_block2 = 0x03, DW_FORM_block4 = 0x04, DW_FORM_data2 = 0x05, DW_FORM_data4 = 0x06, DW_FORM_data8 = 0x07, DW_FORM_string = 0x08, DW_FORM_block = 0x09, DW_FORM_block1 = 0x0a, DW_FORM_data1 = 0x0b, DW_FORM_flag = 0x0c, DW_FORM_sdata = 0x0d, DW_FORM_strp = 0x0e, DW_FORM_udata = 0x0f, DW_FORM_ref_addr = 0x10, DW_FORM_ref1 = 0x11, DW_FORM_ref2 = 0x12, DW_FORM_ref4 = 0x13, DW_FORM_ref8 = 0x14, DW_FORM_ref_udata = 0x15, DW_FORM_indirect = 0x16, DW_FORM_sec_offset = 0x17, DW_FORM_exprloc = 0x18, DW_FORM_flag_present = 0x19, DW_FORM_ref_sig8 = 0x20, // Extensions for Fission proposal DW_FORM_GNU_addr_index = 0x1f01, DW_FORM_GNU_str_index = 0x1f02, // Alternate debug sections proposal (output of "dwz" tool). DW_FORM_GNU_ref_alt = 0x1f20, DW_FORM_GNU_strp_alt = 0x1f21 }; enum LocationAtom { #define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID, #include "Dwarf.def" DW_OP_lo_user = 0xe0, DW_OP_hi_user = 0xff }; enum TypeKind { #define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID, #include "Dwarf.def" DW_ATE_lo_user = 0x80, DW_ATE_hi_user = 0xff }; enum DecimalSignEncoding { // Decimal sign attribute values DW_DS_unsigned = 0x01, DW_DS_leading_overpunch = 0x02, DW_DS_trailing_overpunch = 0x03, DW_DS_leading_separate = 0x04, DW_DS_trailing_separate = 0x05 }; enum EndianityEncoding { // Endianity attribute values DW_END_default = 0x00, DW_END_big = 0x01, DW_END_little = 0x02, DW_END_lo_user = 0x40, DW_END_hi_user = 0xff }; enum AccessAttribute { // Accessibility codes DW_ACCESS_public = 0x01, DW_ACCESS_protected = 0x02, DW_ACCESS_private = 0x03 }; enum VisibilityAttribute { // Visibility codes DW_VIS_local = 0x01, DW_VIS_exported = 0x02, DW_VIS_qualified = 0x03 }; enum VirtualityAttribute { #define HANDLE_DW_VIRTUALITY(ID, NAME) DW_VIRTUALITY_##NAME = ID, #include "Dwarf.def" DW_VIRTUALITY_max = 0x02 }; enum SourceLanguage { #define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID, #include "Dwarf.def" DW_LANG_lo_user = 0x8000, DW_LANG_hi_user = 0xffff }; enum CaseSensitivity { // Identifier case codes DW_ID_case_sensitive = 0x00, DW_ID_up_case = 0x01, DW_ID_down_case = 0x02, DW_ID_case_insensitive = 0x03 }; enum CallingConvention { // Calling convention codes DW_CC_normal = 0x01, DW_CC_program = 0x02, DW_CC_nocall = 0x03, DW_CC_lo_user = 0x40, DW_CC_GNU_borland_fastcall_i386 = 0x41, DW_CC_BORLAND_safecall = 0xb0, DW_CC_BORLAND_stdcall = 0xb1, DW_CC_BORLAND_pascal = 0xb2, DW_CC_BORLAND_msfastcall = 0xb3, DW_CC_BORLAND_msreturn = 0xb4, DW_CC_BORLAND_thiscall = 0xb5, DW_CC_BORLAND_fastcall = 0xb6, DW_CC_hi_user = 0xff }; enum InlineAttribute { // Inline codes DW_INL_not_inlined = 0x00, DW_INL_inlined = 0x01, DW_INL_declared_not_inlined = 0x02, DW_INL_declared_inlined = 0x03 }; enum ArrayDimensionOrdering { // Array ordering DW_ORD_row_major = 0x00, DW_ORD_col_major = 0x01 }; enum DiscriminantList { // Discriminant descriptor values DW_DSC_label = 0x00, DW_DSC_range = 0x01 }; enum LineNumberOps { // Line Number Standard Opcode Encodings DW_LNS_extended_op = 0x00, DW_LNS_copy = 0x01, DW_LNS_advance_pc = 0x02, DW_LNS_advance_line = 0x03, DW_LNS_set_file = 0x04, DW_LNS_set_column = 0x05, DW_LNS_negate_stmt = 0x06, DW_LNS_set_basic_block = 0x07, DW_LNS_const_add_pc = 0x08, DW_LNS_fixed_advance_pc = 0x09, DW_LNS_set_prologue_end = 0x0a, DW_LNS_set_epilogue_begin = 0x0b, DW_LNS_set_isa = 0x0c }; enum LineNumberExtendedOps { // Line Number Extended Opcode Encodings DW_LNE_end_sequence = 0x01, DW_LNE_set_address = 0x02, DW_LNE_define_file = 0x03, DW_LNE_set_discriminator = 0x04, DW_LNE_lo_user = 0x80, DW_LNE_hi_user = 0xff }; enum MacinfoRecordType { // Macinfo Type Encodings DW_MACINFO_define = 0x01, DW_MACINFO_undef = 0x02, DW_MACINFO_start_file = 0x03, DW_MACINFO_end_file = 0x04, DW_MACINFO_vendor_ext = 0xff }; enum MacroEntryType { // Macro Information Entry Type Encodings DW_MACRO_define = 0x01, DW_MACRO_undef = 0x02, DW_MACRO_start_file = 0x03, DW_MACRO_end_file = 0x04, DW_MACRO_define_indirect = 0x05, DW_MACRO_undef_indirect = 0x06, DW_MACRO_transparent_include = 0x07, DW_MACRO_define_indirect_sup = 0x08, DW_MACRO_undef_indirect_sup = 0x09, DW_MACRO_transparent_include_sup = 0x0a, DW_MACRO_define_indirectx = 0x0b, DW_MACRO_undef_indirectx = 0x0c, DW_MACRO_lo_user = 0xe0, DW_MACRO_hi_user = 0xff }; enum CallFrameInfo { // Call frame instruction encodings DW_CFA_extended = 0x00, DW_CFA_nop = 0x00, DW_CFA_advance_loc = 0x40, DW_CFA_offset = 0x80, DW_CFA_restore = 0xc0, DW_CFA_set_loc = 0x01, DW_CFA_advance_loc1 = 0x02, DW_CFA_advance_loc2 = 0x03, DW_CFA_advance_loc4 = 0x04, DW_CFA_offset_extended = 0x05, DW_CFA_restore_extended = 0x06, DW_CFA_undefined = 0x07, DW_CFA_same_value = 0x08, DW_CFA_register = 0x09, DW_CFA_remember_state = 0x0a, DW_CFA_restore_state = 0x0b, DW_CFA_def_cfa = 0x0c, DW_CFA_def_cfa_register = 0x0d, DW_CFA_def_cfa_offset = 0x0e, DW_CFA_def_cfa_expression = 0x0f, DW_CFA_expression = 0x10, DW_CFA_offset_extended_sf = 0x11, DW_CFA_def_cfa_sf = 0x12, DW_CFA_def_cfa_offset_sf = 0x13, DW_CFA_val_offset = 0x14, DW_CFA_val_offset_sf = 0x15, DW_CFA_val_expression = 0x16, DW_CFA_MIPS_advance_loc8 = 0x1d, DW_CFA_GNU_window_save = 0x2d, DW_CFA_GNU_args_size = 0x2e, DW_CFA_lo_user = 0x1c, DW_CFA_hi_user = 0x3f }; enum Constants { // Children flag DW_CHILDREN_no = 0x00, DW_CHILDREN_yes = 0x01, DW_EH_PE_absptr = 0x00, DW_EH_PE_omit = 0xff, DW_EH_PE_uleb128 = 0x01, DW_EH_PE_udata2 = 0x02, DW_EH_PE_udata4 = 0x03, DW_EH_PE_udata8 = 0x04, DW_EH_PE_sleb128 = 0x09, DW_EH_PE_sdata2 = 0x0A, DW_EH_PE_sdata4 = 0x0B, DW_EH_PE_sdata8 = 0x0C, DW_EH_PE_signed = 0x08, DW_EH_PE_pcrel = 0x10, DW_EH_PE_textrel = 0x20, DW_EH_PE_datarel = 0x30, DW_EH_PE_funcrel = 0x40, DW_EH_PE_aligned = 0x50, DW_EH_PE_indirect = 0x80 }; // Constants for debug_loc.dwo in the DWARF5 Split Debug Info Proposal enum LocationListEntry : unsigned char { DW_LLE_end_of_list_entry, DW_LLE_base_address_selection_entry, DW_LLE_start_end_entry, DW_LLE_start_length_entry, DW_LLE_offset_pair_entry }; /// Contstants for the DW_APPLE_PROPERTY_attributes attribute. /// Keep this list in sync with clang's DeclSpec.h ObjCPropertyAttributeKind. enum ApplePropertyAttributes { // Apple Objective-C Property Attributes DW_APPLE_PROPERTY_readonly = 0x01, DW_APPLE_PROPERTY_getter = 0x02, DW_APPLE_PROPERTY_assign = 0x04, DW_APPLE_PROPERTY_readwrite = 0x08, DW_APPLE_PROPERTY_retain = 0x10, DW_APPLE_PROPERTY_copy = 0x20, DW_APPLE_PROPERTY_nonatomic = 0x40, DW_APPLE_PROPERTY_setter = 0x80, DW_APPLE_PROPERTY_atomic = 0x100, DW_APPLE_PROPERTY_weak = 0x200, DW_APPLE_PROPERTY_strong = 0x400, DW_APPLE_PROPERTY_unsafe_unretained = 0x800 }; // Constants for the DWARF5 Accelerator Table Proposal enum AcceleratorTable { // Data layout descriptors. DW_ATOM_null = 0u, // Marker as the end of a list of atoms. DW_ATOM_die_offset = 1u, // DIE offset in the debug_info section. DW_ATOM_cu_offset = 2u, // Offset of the compile unit header that contains the // item in question. DW_ATOM_die_tag = 3u, // A tag entry. DW_ATOM_type_flags = 4u, // Set of flags for a type. // DW_ATOM_type_flags values. // Always set for C++, only set for ObjC if this is the @implementation for a // class. DW_FLAG_type_implementation = 2u, // Hash functions. // Daniel J. Bernstein hash. DW_hash_function_djb = 0u }; // Constants for the GNU pubnames/pubtypes extensions supporting gdb index. enum GDBIndexEntryKind { GIEK_NONE, GIEK_TYPE, GIEK_VARIABLE, GIEK_FUNCTION, GIEK_OTHER, GIEK_UNUSED5, GIEK_UNUSED6, GIEK_UNUSED7 }; enum GDBIndexEntryLinkage { GIEL_EXTERNAL, GIEL_STATIC }; /// \defgroup DwarfConstantsDumping Dwarf constants dumping functions /// /// All these functions map their argument's value back to the /// corresponding enumerator name or return nullptr if the value isn't /// known. /// /// @{ const char *TagString(unsigned Tag); const char *ChildrenString(unsigned Children); const char *AttributeString(unsigned Attribute); const char *FormEncodingString(unsigned Encoding); const char *OperationEncodingString(unsigned Encoding); const char *AttributeEncodingString(unsigned Encoding); const char *DecimalSignString(unsigned Sign); const char *EndianityString(unsigned Endian); const char *AccessibilityString(unsigned Access); const char *VisibilityString(unsigned Visibility); const char *VirtualityString(unsigned Virtuality); const char *LanguageString(unsigned Language); const char *CaseString(unsigned Case); const char *ConventionString(unsigned Convention); const char *InlineCodeString(unsigned Code); const char *ArrayOrderString(unsigned Order); const char *DiscriminantString(unsigned Discriminant); const char *LNStandardString(unsigned Standard); const char *LNExtendedString(unsigned Encoding); const char *MacinfoString(unsigned Encoding); const char *CallFrameString(unsigned Encoding); const char *ApplePropertyString(unsigned); const char *AtomTypeString(unsigned Atom); const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); /// @} /// \brief Returns the symbolic string representing Val when used as a value /// for attribute Attr. const char *AttributeValueString(uint16_t Attr, unsigned Val); /// \brief Decsribes an entry of the various gnu_pub* debug sections. /// /// The gnu_pub* kind looks like: /// /// 0-3 reserved /// 4-6 symbol kind /// 7 0 == global, 1 == static /// /// A gdb_index descriptor includes the above kind, shifted 24 bits up with the /// offset of the cu within the debug_info section stored in those 24 bits. struct PubIndexEntryDescriptor { GDBIndexEntryKind Kind; GDBIndexEntryLinkage Linkage; PubIndexEntryDescriptor(GDBIndexEntryKind Kind, GDBIndexEntryLinkage Linkage) : Kind(Kind), Linkage(Linkage) {} /* implicit */ PubIndexEntryDescriptor(GDBIndexEntryKind Kind) : Kind(Kind), Linkage(GIEL_EXTERNAL) {} explicit PubIndexEntryDescriptor(uint8_t Value) : Kind(static_cast((Value & KIND_MASK) >> KIND_OFFSET)), Linkage(static_cast((Value & LINKAGE_MASK) >> LINKAGE_OFFSET)) {} uint8_t toBits() { return Kind << KIND_OFFSET | Linkage << LINKAGE_OFFSET; } private: enum { KIND_OFFSET = 4, KIND_MASK = 7 << KIND_OFFSET, LINKAGE_OFFSET = 7, LINKAGE_MASK = 1 << LINKAGE_OFFSET }; }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/llvm/ELF.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // ============================================================================== // LLVM Release License // ============================================================================== // University of Illinois/NCSA // Open Source License // // Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. // All rights reserved. // // Developed by: // // LLVM Team // // University of Illinois at Urbana-Champaign // // http://llvm.org // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal with // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimers. // // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimers in the // documentation and/or other materials provided with the distribution. // // * Neither the names of the LLVM Team, University of Illinois at // Urbana-Champaign, nor the names of its contributors may be used to // endorse or promote products derived from this Software without specific // prior written permission. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE // SOFTWARE. //===----------------------------------------------------------------------===// // This header contains common, non-processor-specific data structures and // constants for the ELF file format. // // The details of the ELF32 bits in this file are largely based on the Tool // Interface Standard (TIS) Executable and Linking Format (ELF) Specification // Version 1.2, May 1995. The ELF64 stuff is based on ELF-64 Object File Format // Version 1.5, Draft 2, May 1998 as well as OpenBSD header files. // //===----------------------------------------------------------------------===// #ifndef LLVM_SUPPORT_ELF_H #define LLVM_SUPPORT_ELF_H typedef uint32_t Elf32_Addr; // Program address typedef uint32_t Elf32_Off; // File offset typedef uint16_t Elf32_Half; typedef uint32_t Elf32_Word; typedef int32_t Elf32_Sword; typedef uint64_t Elf64_Addr; typedef uint64_t Elf64_Off; typedef uint16_t Elf64_Half; typedef uint32_t Elf64_Word; typedef int32_t Elf64_Sword; typedef uint64_t Elf64_Xword; typedef int64_t Elf64_Sxword; // Object file magic string. static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; // e_ident size and indices. enum { EI_MAG0 = 0, // File identification index. EI_MAG1 = 1, // File identification index. EI_MAG2 = 2, // File identification index. EI_MAG3 = 3, // File identification index. EI_CLASS = 4, // File class. EI_DATA = 5, // Data encoding. EI_VERSION = 6, // File version. EI_OSABI = 7, // OS/ABI identification. EI_ABIVERSION = 8, // ABI version. EI_PAD = 9, // Start of padding bytes. EI_NIDENT = 16 // Number of bytes in e_ident. }; struct Elf32_Ehdr { unsigned char e_ident[EI_NIDENT]; // ELF Identification bytes Elf32_Half e_type; // Type of file (see ET_* below) Elf32_Half e_machine; // Required architecture for this file (see EM_*) Elf32_Word e_version; // Must be equal to 1 Elf32_Addr e_entry; // Address to jump to in order to start program Elf32_Off e_phoff; // Program header table's file offset, in bytes Elf32_Off e_shoff; // Section header table's file offset, in bytes Elf32_Word e_flags; // Processor-specific flags Elf32_Half e_ehsize; // Size of ELF header, in bytes Elf32_Half e_phentsize; // Size of an entry in the program header table Elf32_Half e_phnum; // Number of entries in the program header table Elf32_Half e_shentsize; // Size of an entry in the section header table Elf32_Half e_shnum; // Number of entries in the section header table Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table bool checkMagic() const { return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; } unsigned char getFileClass() const { return e_ident[EI_CLASS]; } unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } Elf32_Ehdr(); }; // 64-bit ELF header. Fields are the same as for ELF32, but with different // types (see above). struct Elf64_Ehdr { unsigned char e_ident[EI_NIDENT]; Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; Elf64_Off e_phoff; Elf64_Off e_shoff; Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; bool checkMagic() const { return (memcmp(e_ident, ElfMagic, strlen(ElfMagic))) == 0; } unsigned char getFileClass() const { return e_ident[EI_CLASS]; } unsigned char getDataEncoding() const { return e_ident[EI_DATA]; } Elf64_Ehdr(); }; // File types enum { ET_NONE = 0, // No file type ET_REL = 1, // Relocatable file ET_EXEC = 2, // Executable file ET_DYN = 3, // Shared object file ET_CORE = 4, // Core file ET_LOPROC = 0xff00, // Beginning of processor-specific codes ET_HIPROC = 0xffff // Processor-specific }; // Versioning enum { EV_NONE = 0, EV_CURRENT = 1 }; // Machine architectures // See current registered ELF machine architectures at: // http://www.uxsglobal.com/developers/gabi/latest/ch4.eheader.html enum { EM_NONE = 0, // No machine EM_M32 = 1, // AT&T WE 32100 EM_SPARC = 2, // SPARC EM_386 = 3, // Intel 386 EM_68K = 4, // Motorola 68000 EM_88K = 5, // Motorola 88000 EM_IAMCU = 6, // Intel MCU EM_860 = 7, // Intel 80860 EM_MIPS = 8, // MIPS R3000 EM_S370 = 9, // IBM System/370 EM_MIPS_RS3_LE = 10, // MIPS RS3000 Little-endian EM_PARISC = 15, // Hewlett-Packard PA-RISC EM_VPP500 = 17, // Fujitsu VPP500 EM_SPARC32PLUS = 18, // Enhanced instruction set SPARC EM_960 = 19, // Intel 80960 EM_PPC = 20, // PowerPC EM_PPC64 = 21, // PowerPC64 EM_S390 = 22, // IBM System/390 EM_SPU = 23, // IBM SPU/SPC EM_V800 = 36, // NEC V800 EM_FR20 = 37, // Fujitsu FR20 EM_RH32 = 38, // TRW RH-32 EM_RCE = 39, // Motorola RCE EM_ARM = 40, // ARM EM_ALPHA = 41, // DEC Alpha EM_SH = 42, // Hitachi SH EM_SPARCV9 = 43, // SPARC V9 EM_TRICORE = 44, // Siemens TriCore EM_ARC = 45, // Argonaut RISC Core EM_H8_300 = 46, // Hitachi H8/300 EM_H8_300H = 47, // Hitachi H8/300H EM_H8S = 48, // Hitachi H8S EM_H8_500 = 49, // Hitachi H8/500 EM_IA_64 = 50, // Intel IA-64 processor architecture EM_MIPS_X = 51, // Stanford MIPS-X EM_COLDFIRE = 52, // Motorola ColdFire EM_68HC12 = 53, // Motorola M68HC12 EM_MMA = 54, // Fujitsu MMA Multimedia Accelerator EM_PCP = 55, // Siemens PCP EM_NCPU = 56, // Sony nCPU embedded RISC processor EM_NDR1 = 57, // Denso NDR1 microprocessor EM_STARCORE = 58, // Motorola Star*Core processor EM_ME16 = 59, // Toyota ME16 processor EM_ST100 = 60, // STMicroelectronics ST100 processor EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor family EM_X86_64 = 62, // AMD x86-64 architecture EM_PDSP = 63, // Sony DSP Processor EM_PDP10 = 64, // Digital Equipment Corp. PDP-10 EM_PDP11 = 65, // Digital Equipment Corp. PDP-11 EM_FX66 = 66, // Siemens FX66 microcontroller EM_ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller EM_68HC16 = 69, // Motorola MC68HC16 Microcontroller EM_68HC11 = 70, // Motorola MC68HC11 Microcontroller EM_68HC08 = 71, // Motorola MC68HC08 Microcontroller EM_68HC05 = 72, // Motorola MC68HC05 Microcontroller EM_SVX = 73, // Silicon Graphics SVx EM_ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller EM_VAX = 75, // Digital VAX EM_CRIS = 76, // Axis Communications 32-bit embedded processor EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded processor EM_FIREPATH = 78, // Element 14 64-bit DSP Processor EM_ZSP = 79, // LSI Logic 16-bit DSP Processor EM_MMIX = 80, // Donald Knuth's educational 64-bit processor EM_HUANY = 81, // Harvard University machine-independent object files EM_PRISM = 82, // SiTera Prism EM_AVR = 83, // Atmel AVR 8-bit microcontroller EM_FR30 = 84, // Fujitsu FR30 EM_D10V = 85, // Mitsubishi D10V EM_D30V = 86, // Mitsubishi D30V EM_V850 = 87, // NEC v850 EM_M32R = 88, // Mitsubishi M32R EM_MN10300 = 89, // Matsushita MN10300 EM_MN10200 = 90, // Matsushita MN10200 EM_PJ = 91, // picoJava EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor EM_ARC_COMPACT = 93, // ARC International ARCompact processor (old // spelling/synonym: EM_ARC_A5) EM_XTENSA = 94, // Tensilica Xtensa Architecture EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor EM_NS32K = 97, // National Semiconductor 32000 series EM_TPC = 98, // Tenor Network TPC processor EM_SNP1K = 99, // Trebia SNP 1000 processor EM_ST200 = 100, // STMicroelectronics (www.st.com) ST200 EM_IP2K = 101, // Ubicom IP2xxx microcontroller family EM_MAX = 102, // MAX Processor EM_CR = 103, // National Semiconductor CompactRISC microprocessor EM_F2MC16 = 104, // Fujitsu F2MC16 EM_MSP430 = 105, // Texas Instruments embedded microcontroller msp430 EM_BLACKFIN = 106, // Analog Devices Blackfin (DSP) processor EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors EM_SEP = 108, // Sharp embedded microprocessor EM_ARCA = 109, // Arca RISC Microprocessor EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC // of Peking University EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor EM_CRX = 114, // National Semiconductor CompactRISC CRX EM_XGATE = 115, // Motorola XGATE embedded processor EM_C166 = 116, // Infineon C16x/XC16x processor EM_M16C = 117, // Renesas M16C series microprocessors EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal // Controller EM_CE = 119, // Freescale Communication Engine RISC core EM_M32C = 120, // Renesas M32C series microprocessors EM_TSK3000 = 131, // Altium TSK3000 core EM_RS08 = 132, // Freescale RS08 embedded processor EM_SHARC = 133, // Analog Devices SHARC family of 32-bit DSP // processors EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor EM_SCORE7 = 135, // Sunplus S+core7 RISC processor EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture EM_SE_C17 = 139, // Seiko Epson C17 family EM_TI_C6000 = 140, // The Texas Instruments TMS320C6000 DSP family EM_TI_C2000 = 141, // The Texas Instruments TMS320C2000 DSP family EM_TI_C5500 = 142, // The Texas Instruments TMS320C55x DSP family EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor EM_R32C = 162, // Renesas R32C series microprocessors EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family EM_HEXAGON = 164, // Qualcomm Hexagon processor EM_8051 = 165, // Intel 8051 and variants EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable // and extensible RISC processors EM_NDS32 = 167, // Andes Technology compact code size embedded RISC // processor family EM_ECOG1 = 168, // Cyan Technology eCOG1X family EM_ECOG1X = 168, // Cyan Technology eCOG1X family EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture EM_RX = 173, // Renesas RX family EM_METAG = 174, // Imagination Technologies META processor // architecture EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture EM_ECOG16 = 176, // Cyan Technology eCOG16 family EM_CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit // microprocessor EM_ETPU = 178, // Freescale Extended Time Processing Unit EM_SLE9X = 179, // Infineon Technologies SLE9X core EM_L10M = 180, // Intel L10M EM_K10M = 181, // Intel K10M EM_AARCH64 = 183, // ARM AArch64 EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller EM_TILE64 = 187, // Tilera TILE64 multicore architecture family EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family EM_CUDA = 190, // NVIDIA CUDA architecture EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family EM_CLOUDSHIELD = 192, // CloudShield architecture family EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family EM_ARC_COMPACT2 = 195, // Synopsys ARCompact V2 EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core EM_RL78 = 197, // Renesas RL78 family EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor EM_78KOR = 199, // Renesas 78KOR family EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) EM_BA1 = 201, // Beyond BA1 CPU architecture EM_BA2 = 202, // Beyond BA2 CPU architecture EM_XCORE = 203, // XMOS xCORE processor family EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) family EM_INTEL205 = 205, // Reserved by Intel EM_INTEL206 = 206, // Reserved by Intel EM_INTEL207 = 207, // Reserved by Intel EM_INTEL208 = 208, // Reserved by Intel EM_INTEL209 = 209, // Reserved by Intel EM_KM32 = 210, // KM211 KM32 32-bit processor EM_KMX32 = 211, // KM211 KMX32 32-bit processor EM_KMX16 = 212, // KM211 KMX16 16-bit processor EM_KMX8 = 213, // KM211 KMX8 8-bit processor EM_KVARC = 214, // KM211 KVARC processor EM_CDP = 215, // Paneve CDP architecture family EM_COGE = 216, // Cognitive Smart Memory Processor EM_COOL = 217, // iCelero CoolEngine EM_NORC = 218, // Nanoradio Optimized RISC EM_CSR_KALIMBA = 219, // CSR Kalimba architecture family EM_AMDGPU = 224, // AMD GPU architecture EM_RISCV = 243, EM_LOONGARCH = 258, // LoongArch processor // A request has been made to the maintainer of the official registry for // such numbers for an official value for WebAssembly. As soon as one is // allocated, this enum will be updated to use it. EM_WEBASSEMBLY = 0x4157, // WebAssembly architecture }; // Object file classes. enum { ELFCLASSNONE = 0, ELFCLASS32 = 1, // 32-bit object file ELFCLASS64 = 2 // 64-bit object file }; // Object file byte orderings. enum { ELFDATANONE = 0, // Invalid data encoding. ELFDATA2LSB = 1, // Little-endian object file ELFDATA2MSB = 2 // Big-endian object file }; // OS ABI identification. enum { ELFOSABI_NONE = 0, // UNIX System V ABI ELFOSABI_HPUX = 1, // HP-UX operating system ELFOSABI_NETBSD = 2, // NetBSD ELFOSABI_GNU = 3, // GNU/Linux ELFOSABI_LINUX = 3, // Historical alias for ELFOSABI_GNU. ELFOSABI_HURD = 4, // GNU/Hurd ELFOSABI_SOLARIS = 6, // Solaris ELFOSABI_AIX = 7, // AIX ELFOSABI_IRIX = 8, // IRIX ELFOSABI_FREEBSD = 9, // FreeBSD ELFOSABI_TRU64 = 10, // TRU64 UNIX ELFOSABI_MODESTO = 11, // Novell Modesto ELFOSABI_OPENBSD = 12, // OpenBSD ELFOSABI_OPENVMS = 13, // OpenVMS ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel ELFOSABI_AROS = 15, // AROS ELFOSABI_FENIXOS = 16, // FenixOS ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 ELFOSABI_AMDGPU_HSA = 64, // AMD HSA runtime ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 ELFOSABI_ARM = 97, // ARM ELFOSABI_STANDALONE = 255 // Standalone (embedded) application }; #define ELF_RELOC(name, value) name = value, // Specific e_flags for PPC64 enum { // e_flags bits specifying ABI: // 1 for original ABI using function descriptors, // 2 for revised ABI without function descriptors, // 0 for unspecified or not using any features affected by the differences. EF_PPC64_ABI = 3 }; // Special values for the st_other field in the symbol table entry for PPC64. enum { STO_PPC64_LOCAL_BIT = 5, STO_PPC64_LOCAL_MASK = (7 << STO_PPC64_LOCAL_BIT) }; static inline int64_t decodePPC64LocalEntryOffset(unsigned Other) { unsigned Val = (Other & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT; return ((1 << Val) >> 2) << 2; } static inline unsigned encodePPC64LocalEntryOffset(int64_t Offset) { unsigned Val = (Offset >= 4 * 4 ? (Offset >= 8 * 4 ? (Offset >= 16 * 4 ? 6 : 5) : 4) : (Offset >= 2 * 4 ? 3 : (Offset >= 1 * 4 ? 2 : 0))); return Val << STO_PPC64_LOCAL_BIT; } // ARM Specific e_flags enum : unsigned { EF_ARM_SOFT_FLOAT = 0x00000200U, EF_ARM_VFP_FLOAT = 0x00000400U, EF_ARM_EABI_UNKNOWN = 0x00000000U, EF_ARM_EABI_VER1 = 0x01000000U, EF_ARM_EABI_VER2 = 0x02000000U, EF_ARM_EABI_VER3 = 0x03000000U, EF_ARM_EABI_VER4 = 0x04000000U, EF_ARM_EABI_VER5 = 0x05000000U, EF_ARM_EABIMASK = 0xFF000000U }; // AVR specific e_flags enum : unsigned { EF_AVR_ARCH_AVR1 = 1, EF_AVR_ARCH_AVR2 = 2, EF_AVR_ARCH_AVR25 = 25, EF_AVR_ARCH_AVR3 = 3, EF_AVR_ARCH_AVR31 = 31, EF_AVR_ARCH_AVR35 = 35, EF_AVR_ARCH_AVR4 = 4, EF_AVR_ARCH_AVR5 = 5, EF_AVR_ARCH_AVR51 = 51, EF_AVR_ARCH_AVR6 = 6, EF_AVR_ARCH_AVRTINY = 100, EF_AVR_ARCH_XMEGA1 = 101, EF_AVR_ARCH_XMEGA2 = 102, EF_AVR_ARCH_XMEGA3 = 103, EF_AVR_ARCH_XMEGA4 = 104, EF_AVR_ARCH_XMEGA5 = 105, EF_AVR_ARCH_XMEGA6 = 106, EF_AVR_ARCH_XMEGA7 = 107 }; // Mips Specific e_flags enum : unsigned { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code EF_MIPS_ABI2 = 0x00000020, // File uses N32 ABI EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine // in 32-bit mode EF_MIPS_FP64 = 0x00000200, // Code compiled for a 32-bit machine // but uses 64-bit FP registers EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding // ABI flags EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture. EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode. EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode. EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. // MIPS machine variant EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900 EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010 EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100 EF_MIPS_MACH_4650 = 0x00850000, // MIPS R4650 EF_MIPS_MACH_4120 = 0x00870000, // NEC VR4120 EF_MIPS_MACH_4111 = 0x00880000, // NEC VR4111/VR4181 EF_MIPS_MACH_SB1 = 0x008a0000, // Broadcom SB-1 EF_MIPS_MACH_OCTEON = 0x008b0000, // Cavium Networks Octeon EF_MIPS_MACH_XLR = 0x008c0000, // RMI Xlr EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2 EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3 EF_MIPS_MACH_5400 = 0x00910000, // NEC VR5400 EF_MIPS_MACH_5900 = 0x00920000, // MIPS R5900 EF_MIPS_MACH_5500 = 0x00980000, // NEC VR5500 EF_MIPS_MACH_9000 = 0x00990000, // Unknown EF_MIPS_MACH_LS2E = 0x00a00000, // ST Microelectronics Loongson 2E EF_MIPS_MACH_LS2F = 0x00a10000, // ST Microelectronics Loongson 2F EF_MIPS_MACH_LS3A = 0x00a20000, // Loongson 3A EF_MIPS_MACH = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask // ARCH_ASE EF_MIPS_MICROMIPS = 0x02000000, // microMIPS EF_MIPS_ARCH_ASE_M16 = 0x04000000, // Has Mips-16 ISA extensions EF_MIPS_ARCH_ASE_MDMX = 0x08000000, // Has MDMX multimedia extensions EF_MIPS_ARCH_ASE = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags // ARCH EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set EF_MIPS_ARCH_4 = 0x30000000, // MIPS4 instruction set EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5 EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5 EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant }; // Special values for the st_other field in the symbol table entry for MIPS. enum { STO_MIPS_OPTIONAL = 0x04, // Symbol whose definition is optional STO_MIPS_PLT = 0x08, // PLT entry related dynamic table record STO_MIPS_PIC = 0x20, // PIC func in an object mixes PIC/non-PIC STO_MIPS_MICROMIPS = 0x80, // MIPS Specific ISA for MicroMips STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 }; // .MIPS.options section descriptor kinds enum { ODK_NULL = 0, // Undefined ODK_REGINFO = 1, // Register usage information ODK_EXCEPTIONS = 2, // Exception processing options ODK_PAD = 3, // Section padding options ODK_HWPATCH = 4, // Hardware patches applied ODK_FILL = 5, // Linker fill value ODK_TAGS = 6, // Space for tool identification ODK_HWAND = 7, // Hardware AND patches applied ODK_HWOR = 8, // Hardware OR patches applied ODK_GP_GROUP = 9, // GP group to use for text/data sections ODK_IDENT = 10, // ID information ODK_PAGESIZE = 11 // Page size information }; // LoongArch Specific e_flags enum : unsigned { EF_LARCH_ABI = 0x0003, EF_LARCH_ABI_LP32 = 0x0001, EF_LARCH_ABI_XLP32 = 0x0002, EF_LARCH_ABI_LP64 = 0x0003, }; // Hexagon-specific e_flags enum { // Object processor version flags, bits[11:0] EF_HEXAGON_MACH_V2 = 0x00000001, // Hexagon V2 EF_HEXAGON_MACH_V3 = 0x00000002, // Hexagon V3 EF_HEXAGON_MACH_V4 = 0x00000003, // Hexagon V4 EF_HEXAGON_MACH_V5 = 0x00000004, // Hexagon V5 EF_HEXAGON_MACH_V55 = 0x00000005, // Hexagon V55 EF_HEXAGON_MACH_V60 = 0x00000060, // Hexagon V60 // Highest ISA version flags EF_HEXAGON_ISA_MACH = 0x00000000, // Same as specified in bits[11:0] // of e_flags EF_HEXAGON_ISA_V2 = 0x00000010, // Hexagon V2 ISA EF_HEXAGON_ISA_V3 = 0x00000020, // Hexagon V3 ISA EF_HEXAGON_ISA_V4 = 0x00000030, // Hexagon V4 ISA EF_HEXAGON_ISA_V5 = 0x00000040, // Hexagon V5 ISA EF_HEXAGON_ISA_V55 = 0x00000050, // Hexagon V55 ISA EF_HEXAGON_ISA_V60 = 0x00000060, // Hexagon V60 ISA }; // Hexagon-specific section indexes for common small data enum { SHN_HEXAGON_SCOMMON = 0xff00, // Other access sizes SHN_HEXAGON_SCOMMON_1 = 0xff01, // Byte-sized access SHN_HEXAGON_SCOMMON_2 = 0xff02, // Half-word-sized access SHN_HEXAGON_SCOMMON_4 = 0xff03, // Word-sized access SHN_HEXAGON_SCOMMON_8 = 0xff04 // Double-word-size access }; #undef ELF_RELOC // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) Elf32_Word sh_type; // Section type (SHT_*) Elf32_Word sh_flags; // Section flags (SHF_*) Elf32_Addr sh_addr; // Address where section is to be loaded Elf32_Off sh_offset; // File offset of section data, in bytes Elf32_Word sh_size; // Size of section, in bytes Elf32_Word sh_link; // Section type-specific header table index link Elf32_Word sh_info; // Section type-specific extra information Elf32_Word sh_addralign; // Section address alignment Elf32_Word sh_entsize; // Size of records contained within the section }; // Section header for ELF64 - same fields as ELF32, different types. struct Elf64_Shdr { Elf64_Word sh_name; Elf64_Word sh_type; Elf64_Xword sh_flags; Elf64_Addr sh_addr; Elf64_Off sh_offset; Elf64_Xword sh_size; Elf64_Word sh_link; Elf64_Word sh_info; Elf64_Xword sh_addralign; Elf64_Xword sh_entsize; }; // Special section indices. enum { SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless SHN_LORESERVE = 0xff00, // Lowest reserved index SHN_LOPROC = 0xff00, // Lowest processor-specific index SHN_HIPROC = 0xff1f, // Highest processor-specific index SHN_LOOS = 0xff20, // Lowest operating system-specific index SHN_HIOS = 0xff3f, // Highest operating system-specific index SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables SHN_XINDEX = 0xffff, // Mark that the index is >= SHN_LORESERVE SHN_HIRESERVE = 0xffff // Highest reserved index }; // Section types. enum : unsigned { SHT_NULL = 0, // No associated section (inactive entry). SHT_PROGBITS = 1, // Program-defined contents. SHT_SYMTAB = 2, // Symbol table. SHT_STRTAB = 3, // String table. SHT_RELA = 4, // Relocation entries; explicit addends. SHT_HASH = 5, // Symbol hash table. SHT_DYNAMIC = 6, // Information for dynamic linking. SHT_NOTE = 7, // Information about the file. SHT_NOBITS = 8, // Data occupies no space in the file. SHT_REL = 9, // Relocation entries; no explicit addends. SHT_SHLIB = 10, // Reserved. SHT_DYNSYM = 11, // Symbol table. SHT_INIT_ARRAY = 14, // Pointers to initialization functions. SHT_FINI_ARRAY = 15, // Pointers to termination functions. SHT_PREINIT_ARRAY = 16, // Pointers to pre-init functions. SHT_GROUP = 17, // Section group. SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. SHT_LOOS = 0x60000000, // Lowest operating system-specific type. SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes. SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. SHT_GNU_verneed = 0x6ffffffe, // GNU version references. SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. SHT_HIOS = 0x6fffffff, // Highest operating system-specific type. SHT_LOPROC = 0x70000000, // Lowest processor arch-specific type. // Fixme: All this is duplicated in MCSectionELF. Why?? // Exception Index table SHT_ARM_EXIDX = 0x70000001U, // BPABI DLL dynamic linking pre-emption map SHT_ARM_PREEMPTMAP = 0x70000002U, // Object file compatibility attributes SHT_ARM_ATTRIBUTES = 0x70000003U, SHT_ARM_DEBUGOVERLAY = 0x70000004U, SHT_ARM_OVERLAYSECTION = 0x70000005U, SHT_HEX_ORDERED = 0x70000000, // Link editor is to sort the entries in // this section based on their sizes SHT_X86_64_UNWIND = 0x70000001, // Unwind information SHT_MIPS_REGINFO = 0x70000006, // Register usage information SHT_MIPS_OPTIONS = 0x7000000d, // General options SHT_MIPS_ABIFLAGS = 0x7000002a, // ABI information. SHT_LOONGARCH_REGINFO = 0x70000006, // Register usage information SHT_LOONGARCH_OPTIONS = 0x7000000d, // General options SHT_LOONGARCH_DWARF = 0x7000001e, // DWARF debugging section. SHT_LOONGARCH_ABIFLAGS = 0x7000002a, // ABI information. SHT_HIPROC = 0x7fffffff, // Highest processor arch-specific type. SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. SHT_HIUSER = 0xffffffff // Highest type reserved for applications. }; // Section flags. enum : unsigned { // Section data should be writable during execution. SHF_WRITE = 0x1, // Section occupies memory during program execution. SHF_ALLOC = 0x2, // Section contains executable machine instructions. SHF_EXECINSTR = 0x4, // The data in this section may be merged. SHF_MERGE = 0x10, // The data in this section is null-terminated strings. SHF_STRINGS = 0x20, // A field in this section holds a section header table index. SHF_INFO_LINK = 0x40U, // Adds special ordering requirements for link editors. SHF_LINK_ORDER = 0x80U, // This section requires special OS-specific processing to avoid incorrect // behavior. SHF_OS_NONCONFORMING = 0x100U, // This section is a member of a section group. SHF_GROUP = 0x200U, // This section holds Thread-Local Storage. SHF_TLS = 0x400U, // This section is excluded from the final executable or shared library. SHF_EXCLUDE = 0x80000000U, // Start of target-specific flags. /// XCORE_SHF_CP_SECTION - All sections with the "c" flag are grouped /// together by the linker to form the constant pool and the cp register is /// set to the start of the constant pool by the boot code. XCORE_SHF_CP_SECTION = 0x800U, /// XCORE_SHF_DP_SECTION - All sections with the "d" flag are grouped /// together by the linker to form the data section and the dp register is /// set to the start of the section by the boot code. XCORE_SHF_DP_SECTION = 0x1000U, SHF_MASKOS = 0x0ff00000, // Bits indicating processor-specific flags. SHF_MASKPROC = 0xf0000000, // If an object file section does not have this flag set, then it may not hold // more than 2GB and can be freely referred to in objects using smaller code // models. Otherwise, only objects using larger code models can refer to them. // For example, a medium code model object can refer to data in a section that // sets this flag besides being able to refer to data in a section that does // not set it; likewise, a small code model object can refer only to code in a // section that does not set this flag. SHF_X86_64_LARGE = 0x10000000, // All sections with the GPREL flag are grouped into a global data area // for faster accesses SHF_HEX_GPREL = 0x10000000, // Section contains text/data which may be replicated in other sections. // Linker must retain only one copy. SHF_MIPS_NODUPES = 0x01000000, // Linker must generate implicit hidden weak names. SHF_MIPS_NAMES = 0x02000000, // Section data local to process. SHF_MIPS_LOCAL = 0x04000000, // Do not strip this section. SHF_MIPS_NOSTRIP = 0x08000000, // Section must be part of global data area. SHF_MIPS_GPREL = 0x10000000, // This section should be merged. SHF_MIPS_MERGE = 0x20000000, // Address size to be inferred from section entry size. SHF_MIPS_ADDR = 0x40000000, // Section data is string data by default. SHF_MIPS_STRING = 0x80000000, // Linker must retain only one copy. SHF_LOONGARCH_NODUPES = 0x01000000, // Linker must generate implicit hidden weak names. SHF_LOONGARCH_NAMES = 0x02000000, // Section data local to process. SHF_LOONGARCH_LOCAL = 0x04000000, // Do not strip this section. SHF_LOONGARCH_NOSTRIP = 0x08000000, // Section must be part of global data area. SHF_LOONGARCH_GPREL = 0x10000000, // This section should be merged. SHF_LOONGARCH_MERGE = 0x20000000, // Address size to be inferred from section entry size. SHF_LOONGARCH_ADDR = 0x40000000, // Section data is string data by default. SHF_LOONGARCH_STRING = 0x80000000, SHF_AMDGPU_HSA_GLOBAL = 0x00100000, SHF_AMDGPU_HSA_READONLY = 0x00200000, SHF_AMDGPU_HSA_CODE = 0x00400000, SHF_AMDGPU_HSA_AGENT = 0x00800000 }; // Section Group Flags enum : unsigned { GRP_COMDAT = 0x1, GRP_MASKOS = 0x0ff00000, GRP_MASKPROC = 0xf0000000 }; // Symbol table entries for ELF32. struct Elf32_Sym { Elf32_Word st_name; // Symbol name (index into string table) Elf32_Addr st_value; // Value or address associated with the symbol Elf32_Word st_size; // Size of the symbol unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved Elf32_Half st_shndx; // Which section (header table index) it's defined in // These accessors and mutators correspond to the ELF32_ST_BIND, // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: unsigned char getBinding() const { return st_info >> 4; } unsigned char getType() const { return st_info & 0x0f; } void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { st_info = (unsigned char)((b << 4) + (t & 0x0f)); } }; // Symbol table entries for ELF64. struct Elf64_Sym { Elf64_Word st_name; // Symbol name (index into string table) unsigned char st_info; // Symbol's type and binding attributes unsigned char st_other; // Must be zero; reserved Elf64_Half st_shndx; // Which section (header tbl index) it's defined in Elf64_Addr st_value; // Value or address associated with the symbol Elf64_Xword st_size; // Size of the symbol // These accessors and mutators are identical to those defined for ELF32 // symbol table entries. unsigned char getBinding() const { return st_info >> 4; } unsigned char getType() const { return st_info & 0x0f; } void setBinding(unsigned char b) { setBindingAndType(b, getType()); } void setType(unsigned char t) { setBindingAndType(getBinding(), t); } void setBindingAndType(unsigned char b, unsigned char t) { st_info = (unsigned char)((b << 4) + (t & 0x0f)); } }; // The size (in bytes) of symbol table entries. enum { SYMENTRY_SIZE32 = 16, // 32-bit symbol entry size SYMENTRY_SIZE64 = 24 // 64-bit symbol entry size. }; // Symbol bindings. enum { STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def STB_GLOBAL = 1, // Global symbol, visible to all object files being combined STB_WEAK = 2, // Weak symbol, like global but lower-precedence STB_GNU_UNIQUE = 10, STB_LOOS = 10, // Lowest operating system-specific binding type STB_HIOS = 12, // Highest operating system-specific binding type STB_LOPROC = 13, // Lowest processor-specific binding type STB_HIPROC = 15 // Highest processor-specific binding type }; // Symbol types. enum { STT_NOTYPE = 0, // Symbol's type is not specified STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) STT_FUNC = 2, // Symbol is executable code (function, etc.) STT_SECTION = 3, // Symbol refers to a section STT_FILE = 4, // Local, absolute symbol that refers to a file STT_COMMON = 5, // An uninitialized common block STT_TLS = 6, // Thread local data object STT_GNU_IFUNC = 10, // GNU indirect function STT_LOOS = 10, // Lowest operating system-specific symbol type STT_HIOS = 12, // Highest operating system-specific symbol type STT_LOPROC = 13, // Lowest processor-specific symbol type STT_HIPROC = 15, // Highest processor-specific symbol type // AMDGPU symbol types STT_AMDGPU_HSA_KERNEL = 10, STT_AMDGPU_HSA_INDIRECT_FUNCTION = 11, STT_AMDGPU_HSA_METADATA = 12 }; enum { STV_DEFAULT = 0, // Visibility is specified by binding type STV_INTERNAL = 1, // Defined by processor supplements STV_HIDDEN = 2, // Not visible to other components STV_PROTECTED = 3 // Visible in other components but not preemptable }; // Symbol number. enum { STN_UNDEF = 0 }; // Special relocation symbols used in the MIPS64 ELF relocation entries enum { RSS_UNDEF = 0, // None RSS_GP = 1, // Value of gp RSS_GP0 = 2, // Value of gp used to create object being relocated RSS_LOC = 3 // Address of location being relocated }; // Relocation entry, without explicit addend. struct Elf32_Rel { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf32_Word r_info; // Symbol table index and type of relocation to apply // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: Elf32_Word getSymbol() const { return (r_info >> 8); } unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(Elf32_Word s, unsigned char t) { r_info = (s << 8) + t; } }; // Relocation entry with explicit addend. struct Elf32_Rela { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) Elf32_Word r_info; // Symbol table index and type of relocation to apply Elf32_Sword r_addend; // Compute value for relocatable field by adding this // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, // and ELF32_R_INFO macros defined in the ELF specification: Elf32_Word getSymbol() const { return (r_info >> 8); } unsigned char getType() const { return (unsigned char) (r_info & 0x0ff); } void setSymbol(Elf32_Word s) { setSymbolAndType(s, getType()); } void setType(unsigned char t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(Elf32_Word s, unsigned char t) { r_info = (s << 8) + t; } }; // Relocation entry, without explicit addend. struct Elf64_Rel { Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). Elf64_Xword r_info; // Symbol table index and type of relocation to apply. // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: Elf64_Word getSymbol() const { return (r_info >> 32); } Elf64_Word getType() const { return (Elf64_Word) (r_info & 0xffffffffL); } void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(Elf64_Word s, Elf64_Word t) { r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); } }; // Relocation entry with explicit addend. struct Elf64_Rela { Elf64_Addr r_offset; // Location (file byte offset, or program virtual addr). Elf64_Xword r_info; // Symbol table index and type of relocation to apply. Elf64_Sxword r_addend; // Compute value for relocatable field by adding this. // These accessors and mutators correspond to the ELF64_R_SYM, ELF64_R_TYPE, // and ELF64_R_INFO macros defined in the ELF specification: Elf64_Word getSymbol() const { return (r_info >> 32); } Elf64_Word getType() const { return (Elf64_Word) (r_info & 0xffffffffL); } void setSymbol(Elf64_Word s) { setSymbolAndType(s, getType()); } void setType(Elf64_Word t) { setSymbolAndType(getSymbol(), t); } void setSymbolAndType(Elf64_Word s, Elf64_Word t) { r_info = ((Elf64_Xword)s << 32) + (t&0xffffffffL); } }; // Program header for ELF32. struct Elf32_Phdr { Elf32_Word p_type; // Type of segment Elf32_Off p_offset; // File offset where segment is located, in bytes Elf32_Addr p_vaddr; // Virtual address of beginning of segment Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) Elf32_Word p_flags; // Segment flags Elf32_Word p_align; // Segment alignment constraint }; // Program header for ELF64. struct Elf64_Phdr { Elf64_Word p_type; // Type of segment Elf64_Word p_flags; // Segment flags Elf64_Off p_offset; // File offset where segment is located, in bytes Elf64_Addr p_vaddr; // Virtual address of beginning of segment Elf64_Addr p_paddr; // Physical addr of beginning of segment (OS-specific) Elf64_Xword p_filesz; // Num. of bytes in file image of segment (may be zero) Elf64_Xword p_memsz; // Num. of bytes in mem image of segment (may be zero) Elf64_Xword p_align; // Segment alignment constraint }; // Segment types. enum { PT_NULL = 0, // Unused segment. PT_LOAD = 1, // Loadable segment. PT_DYNAMIC = 2, // Dynamic linking information. PT_INTERP = 3, // Interpreter pathname. PT_NOTE = 4, // Auxiliary information. PT_SHLIB = 5, // Reserved. PT_PHDR = 6, // The program header table itself. PT_TLS = 7, // The thread-local storage template. PT_LOOS = 0x60000000, // Lowest operating system-specific pt entry type. PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. PT_HIPROC = 0x7fffffff, // Highest processor-specific program hdr entry type. // x86-64 program header types. // These all contain stack unwind tables. PT_GNU_EH_FRAME = 0x6474e550, PT_SUNW_EH_FRAME = 0x6474e550, PT_SUNW_UNWIND = 0x6464e550, PT_GNU_STACK = 0x6474e551, // Indicates stack executability. PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. // ARM program header types. PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility info // These all contain stack unwind tables. PT_ARM_EXIDX = 0x70000001, PT_ARM_UNWIND = 0x70000001, // MIPS program header types. PT_MIPS_REGINFO = 0x70000000, // Register usage information. PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. PT_MIPS_OPTIONS = 0x70000002, // Options segment. PT_MIPS_ABIFLAGS = 0x70000003, // Abiflags segment. // LOONGARCH program header types. PT_LOONGARCH_REGINFO = 0x70000000, // Register usage information. PT_LOONGARCH_RTPROC = 0x70000001, // Runtime procedure table. PT_LOONGARCH_OPTIONS = 0x70000002, // Options segment. PT_LOONGARCH_ABIFLAGS = 0x70000003, // Abiflags segment. // AMDGPU program header types. PT_AMDGPU_HSA_LOAD_GLOBAL_PROGRAM = 0x60000000, PT_AMDGPU_HSA_LOAD_GLOBAL_AGENT = 0x60000001, PT_AMDGPU_HSA_LOAD_READONLY_AGENT = 0x60000002, PT_AMDGPU_HSA_LOAD_CODE_AGENT = 0x60000003, // WebAssembly program header types. PT_WEBASSEMBLY_FUNCTIONS = PT_LOPROC + 0, // Function definitions. }; // Segment flag bits. enum : unsigned { PF_X = 1, // Execute PF_W = 2, // Write PF_R = 4, // Read PF_MASKOS = 0x0ff00000,// Bits for operating system-specific semantics. PF_MASKPROC = 0xf0000000 // Bits for processor-specific semantics. }; // Dynamic table entry for ELF32. struct Elf32_Dyn { Elf32_Sword d_tag; // Type of dynamic table entry. union { Elf32_Word d_val; // Integer value of entry. Elf32_Addr d_ptr; // Pointer value of entry. } d_un; }; // Dynamic table entry for ELF64. struct Elf64_Dyn { Elf64_Sxword d_tag; // Type of dynamic table entry. union { Elf64_Xword d_val; // Integer value of entry. Elf64_Addr d_ptr; // Pointer value of entry. } d_un; }; // Dynamic table entry tags. enum { DT_NULL = 0, // Marks end of dynamic array. DT_NEEDED = 1, // String table offset of needed library. DT_PLTRELSZ = 2, // Size of relocation entries in PLT. DT_PLTGOT = 3, // Address associated with linkage table. DT_HASH = 4, // Address of symbolic hash table. DT_STRTAB = 5, // Address of dynamic string table. DT_SYMTAB = 6, // Address of dynamic symbol table. DT_RELA = 7, // Address of relocation table (Rela entries). DT_RELASZ = 8, // Size of Rela relocation table. DT_RELAENT = 9, // Size of a Rela relocation entry. DT_STRSZ = 10, // Total size of the string table. DT_SYMENT = 11, // Size of a symbol table entry. DT_INIT = 12, // Address of initialization function. DT_FINI = 13, // Address of termination function. DT_SONAME = 14, // String table offset of a shared objects name. DT_RPATH = 15, // String table offset of library search path. DT_SYMBOLIC = 16, // Changes symbol resolution algorithm. DT_REL = 17, // Address of relocation table (Rel entries). DT_RELSZ = 18, // Size of Rel relocation table. DT_RELENT = 19, // Size of a Rel relocation entry. DT_PLTREL = 20, // Type of relocation entry used for linking. DT_DEBUG = 21, // Reserved for debugger. DT_TEXTREL = 22, // Relocations exist for non-writable segments. DT_JMPREL = 23, // Address of relocations associated with PLT. DT_BIND_NOW = 24, // Process all relocations before execution. DT_INIT_ARRAY = 25, // Pointer to array of initialization functions. DT_FINI_ARRAY = 26, // Pointer to array of termination functions. DT_INIT_ARRAYSZ = 27, // Size of DT_INIT_ARRAY. DT_FINI_ARRAYSZ = 28, // Size of DT_FINI_ARRAY. DT_RUNPATH = 29, // String table offset of lib search path. DT_FLAGS = 30, // Flags. DT_ENCODING = 32, // Values from here to DT_LOOS follow the rules // for the interpretation of the d_un union. DT_PREINIT_ARRAY = 32, // Pointer to array of preinit functions. DT_PREINIT_ARRAYSZ = 33, // Size of the DT_PREINIT_ARRAY array. DT_LOOS = 0x60000000, // Start of environment specific tags. DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. DT_LOPROC = 0x70000000, // Start of processor specific tags. DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. DT_GNU_HASH = 0x6FFFFEF5, // Reference to the GNU hash table. DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. DT_VERSYM = 0x6FFFFFF0, // The address of .gnu.version section. DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. DT_VERNEEDNUM = 0X6FFFFFFF, // The number of entries in DT_VERNEED. // Mips specific dynamic table entry tags. DT_MIPS_RLD_VERSION = 0x70000001, // 32 bit version number for runtime // linker interface. DT_MIPS_TIME_STAMP = 0x70000002, // Time stamp. DT_MIPS_ICHECKSUM = 0x70000003, // Checksum of external strings // and common sizes. DT_MIPS_IVERSION = 0x70000004, // Index of version string // in string table. DT_MIPS_FLAGS = 0x70000005, // 32 bits of flags. DT_MIPS_BASE_ADDRESS = 0x70000006, // Base address of the segment. DT_MIPS_MSYM = 0x70000007, // Address of .msym section. DT_MIPS_CONFLICT = 0x70000008, // Address of .conflict section. DT_MIPS_LIBLIST = 0x70000009, // Address of .liblist section. DT_MIPS_LOCAL_GOTNO = 0x7000000a, // Number of local global offset // table entries. DT_MIPS_CONFLICTNO = 0x7000000b, // Number of entries // in the .conflict section. DT_MIPS_LIBLISTNO = 0x70000010, // Number of entries // in the .liblist section. DT_MIPS_SYMTABNO = 0x70000011, // Number of entries // in the .dynsym section. DT_MIPS_UNREFEXTNO = 0x70000012, // Index of first external dynamic symbol // not referenced locally. DT_MIPS_GOTSYM = 0x70000013, // Index of first dynamic symbol // in global offset table. DT_MIPS_HIPAGENO = 0x70000014, // Number of page table entries // in global offset table. DT_MIPS_RLD_MAP = 0x70000016, // Address of run time loader map, // used for debugging. DT_MIPS_DELTA_CLASS = 0x70000017, // Delta C++ class definition. DT_MIPS_DELTA_CLASS_NO = 0x70000018, // Number of entries // in DT_MIPS_DELTA_CLASS. DT_MIPS_DELTA_INSTANCE = 0x70000019, // Delta C++ class instances. DT_MIPS_DELTA_INSTANCE_NO = 0x7000001A, // Number of entries // in DT_MIPS_DELTA_INSTANCE. DT_MIPS_DELTA_RELOC = 0x7000001B, // Delta relocations. DT_MIPS_DELTA_RELOC_NO = 0x7000001C, // Number of entries // in DT_MIPS_DELTA_RELOC. DT_MIPS_DELTA_SYM = 0x7000001D, // Delta symbols that Delta // relocations refer to. DT_MIPS_DELTA_SYM_NO = 0x7000001E, // Number of entries // in DT_MIPS_DELTA_SYM. DT_MIPS_DELTA_CLASSSYM = 0x70000020, // Delta symbols that hold // class declarations. DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, // Number of entries // in DT_MIPS_DELTA_CLASSSYM. DT_MIPS_CXX_FLAGS = 0x70000022, // Flags indicating information // about C++ flavor. DT_MIPS_PIXIE_INIT = 0x70000023, // Pixie information. DT_MIPS_SYMBOL_LIB = 0x70000024, // Address of .MIPS.symlib DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, // The GOT index of the first PTE // for a segment DT_MIPS_LOCAL_GOTIDX = 0x70000026, // The GOT index of the first PTE // for a local symbol DT_MIPS_HIDDEN_GOTIDX = 0x70000027, // The GOT index of the first PTE // for a hidden symbol DT_MIPS_PROTECTED_GOTIDX = 0x70000028, // The GOT index of the first PTE // for a protected symbol DT_MIPS_OPTIONS = 0x70000029, // Address of `.MIPS.options'. DT_MIPS_INTERFACE = 0x7000002A, // Address of `.interface'. DT_MIPS_DYNSTR_ALIGN = 0x7000002B, // Unknown. DT_MIPS_INTERFACE_SIZE = 0x7000002C, // Size of the .interface section. DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 0x7000002D, // Size of rld_text_resolve // function stored in the GOT. DT_MIPS_PERF_SUFFIX = 0x7000002E, // Default suffix of DSO to be added // by rld on dlopen() calls. DT_MIPS_COMPACT_SIZE = 0x7000002F, // Size of compact relocation // section (O32). DT_MIPS_GP_VALUE = 0x70000030, // GP value for auxiliary GOTs. DT_MIPS_AUX_DYNAMIC = 0x70000031, // Address of auxiliary .dynamic. DT_MIPS_PLTGOT = 0x70000032, // Address of the base of the PLTGOT. DT_MIPS_RWPLT = 0x70000034, // Points to the base // of a writable PLT. DT_MIPS_RLD_MAP_REL = 0x70000035 // Relative offset of run time loader // map, used for debugging. }; // DT_FLAGS values. enum { DF_ORIGIN = 0x01, // The object may reference $ORIGIN. DF_SYMBOLIC = 0x02, // Search the shared lib before searching the exe. DF_TEXTREL = 0x04, // Relocations may modify a non-writable segment. DF_BIND_NOW = 0x08, // Process all relocations on load. DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. }; // State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. enum { DF_1_NOW = 0x00000001, // Set RTLD_NOW for this object. DF_1_GLOBAL = 0x00000002, // Set RTLD_GLOBAL for this object. DF_1_GROUP = 0x00000004, // Set RTLD_GROUP for this object. DF_1_NODELETE = 0x00000008, // Set RTLD_NODELETE for this object. DF_1_LOADFLTR = 0x00000010, // Trigger filtee loading at runtime. DF_1_INITFIRST = 0x00000020, // Set RTLD_INITFIRST for this object. DF_1_NOOPEN = 0x00000040, // Set RTLD_NOOPEN for this object. DF_1_ORIGIN = 0x00000080, // $ORIGIN must be handled. DF_1_DIRECT = 0x00000100, // Direct binding enabled. DF_1_TRANS = 0x00000200, DF_1_INTERPOSE = 0x00000400, // Object is used to interpose. DF_1_NODEFLIB = 0x00000800, // Ignore default lib search path. DF_1_NODUMP = 0x00001000, // Object can't be dldump'ed. DF_1_CONFALT = 0x00002000, // Configuration alternative created. DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time. DF_1_NODIRECT = 0x00020000, // Object has no-direct binding. DF_1_IGNMULDEF = 0x00040000, DF_1_NOKSYMS = 0x00080000, DF_1_NOHDR = 0x00100000, DF_1_EDITED = 0x00200000, // Object is modified after built. DF_1_NORELOC = 0x00400000, DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers. DF_1_GLOBAUDIT = 0x01000000, // Global auditing required. DF_1_SINGLETON = 0x02000000 // Singleton symbols are used. }; // DT_MIPS_FLAGS values. enum { RHF_NONE = 0x00000000, // No flags. RHF_QUICKSTART = 0x00000001, // Uses shortcut pointers. RHF_NOTPOT = 0x00000002, // Hash size is not a power of two. RHS_NO_LIBRARY_REPLACEMENT = 0x00000004, // Ignore LD_LIBRARY_PATH. RHF_NO_MOVE = 0x00000008, // DSO address may not be relocated. RHF_SGI_ONLY = 0x00000010, // SGI specific features. RHF_GUARANTEE_INIT = 0x00000020, // Guarantee that .init will finish // executing before any non-init // code in DSO is called. RHF_DELTA_C_PLUS_PLUS = 0x00000040, // Contains Delta C++ code. RHF_GUARANTEE_START_INIT = 0x00000080, // Guarantee that .init will start // executing before any non-init // code in DSO is called. RHF_PIXIE = 0x00000100, // Generated by pixie. RHF_DEFAULT_DELAY_LOAD = 0x00000200, // Delay-load DSO by default. RHF_REQUICKSTART = 0x00000400, // Object may be requickstarted RHF_REQUICKSTARTED = 0x00000800, // Object has been requickstarted RHF_CORD = 0x00001000, // Generated by cord. RHF_NO_UNRES_UNDEF = 0x00002000, // Object contains no unresolved // undef symbols. RHF_RLD_ORDER_SAFE = 0x00004000 // Symbol table is in a safe order. }; // ElfXX_VerDef structure version (GNU versioning) enum { VER_DEF_NONE = 0, VER_DEF_CURRENT = 1 }; // VerDef Flags (ElfXX_VerDef::vd_flags) enum { VER_FLG_BASE = 0x1, VER_FLG_WEAK = 0x2, VER_FLG_INFO = 0x4 }; // Special constants for the version table. (SHT_GNU_versym/.gnu.version) enum { VER_NDX_LOCAL = 0, // Unversioned local symbol VER_NDX_GLOBAL = 1, // Unversioned global symbol VERSYM_VERSION = 0x7fff, // Version Index mask VERSYM_HIDDEN = 0x8000 // Hidden bit (non-default version) }; // ElfXX_VerNeed structure version (GNU versioning) enum { VER_NEED_NONE = 0, VER_NEED_CURRENT = 1 }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/loaderheap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // LoaderHeap.h // // // Utility functions for managing memory allocations that typically do not // need releasing. // //***************************************************************************** #ifndef __LoaderHeap_h__ #define __LoaderHeap_h__ #include "utilcode.h" #include "ex.h" #include "executableallocator.h" //============================================================================== // Interface used to back out loader heap allocations. //============================================================================== class ILoaderHeapBackout { #ifdef _DEBUG #define BackoutMem(pMem, dwSize) RealBackoutMem( (pMem), (dwSize), __FILE__, __LINE__, "UNKNOWN", -1 ) #else #define BackoutMem(pMem, dwSize) RealBackoutMem( (pMem), (dwSize) ) #endif public: virtual void RealBackoutMem(void *pMem , size_t dwSize #ifdef _DEBUG , _In_ _In_z_ const char *szFile , int lineNum , _In_ _In_z_ const char *szAllocFile , int allocLineNum #endif ) = 0; }; //============================================================================== // This structure packages up all the data needed to back out an AllocMem. // It's mainly a short term parking place to get the data from the AllocMem // to the AllocMemHolder while preserving the illusion that AllocMem() still // returns just a pointer as it did in V1. //============================================================================== struct TaggedMemAllocPtr { // Note: For AllocAlignedMem blocks, m_pMem and m_dwRequestedSize are the actual values to pass // to BackoutMem. Do not add "m_dwExtra" void *m_pMem; //Pointer to AllocMem'd block (needed to pass back to BackoutMem) size_t m_dwRequestedSize; //Requested allocation size (needed to pass back to BackoutMem) ILoaderHeapBackout *m_pHeap; //The heap that alloc'd the block (needed to know who to call BackoutMem on) //For AllocMem'd blocks, this is always 0. //For AllocAlignedMem blocks, you have to add m_dwExtra to m_pMem to arrive // at the actual aligned pointer. size_t m_dwExtra; #ifdef _DEBUG const char *m_szFile; //File that called AllocMem int m_lineNum; //Line # of AllocMem callsite #endif //! Note: this structure is copied around using bitwise copy ("="). //! Don't get too fancy putting stuff in here. It's really just a temporary //! holding place to get stuff from RealAllocMem() to the MemAllocHolder. public: // // This makes "void *ptr = pLoaderHeap->AllocMem()" work as in V1. // operator void*() const { LIMITED_METHOD_CONTRACT; return (void*)(m_dwExtra + (BYTE*)m_pMem); } template < typename T > T cast() const { LIMITED_METHOD_CONTRACT; return reinterpret_cast< T >( operator void *() ); } }; // # bytes to leave between allocations in debug mode // Set to a > 0 boundary to debug problems - I've made this zero, otherwise a 1 byte allocation becomes // a (1 + LOADER_HEAP_DEBUG_BOUNDARY) allocation #define LOADER_HEAP_DEBUG_BOUNDARY 0 #define VIRTUAL_ALLOC_RESERVE_GRANULARITY (64*1024) // 0x10000 (64 KB) typedef DPTR(struct LoaderHeapBlock) PTR_LoaderHeapBlock; struct LoaderHeapBlock { PTR_LoaderHeapBlock pNext; PTR_VOID pVirtualAddress; size_t dwVirtualSize; BOOL m_fReleaseMemory; #ifndef DACCESS_COMPILE // pVirtualMemory - the start address of the virtual memory // cbVirtualMemory - the length in bytes of the virtual memory // fReleaseMemory - should LoaderHeap be responsible for releasing this memory void Init(void *pVirtualMemory, size_t cbVirtualMemory, BOOL fReleaseMemory) { LIMITED_METHOD_CONTRACT; this->pNext = NULL; this->pVirtualAddress = pVirtualMemory; this->dwVirtualSize = cbVirtualMemory; this->m_fReleaseMemory = fReleaseMemory; } // Just calls LoaderHeapBlock::Init LoaderHeapBlock(void *pVirtualMemory, size_t cbVirtualMemory, BOOL fReleaseMemory) { WRAPPER_NO_CONTRACT; Init(pVirtualMemory, cbVirtualMemory, fReleaseMemory); } LoaderHeapBlock() { WRAPPER_NO_CONTRACT; Init(NULL, 0, FALSE); } #else // No ctors in DAC builds LoaderHeapBlock() {} #endif }; struct LoaderHeapFreeBlock; // Collection of methods for helping in debugging heap corruptions #ifdef _DEBUG class LoaderHeapSniffer; struct LoaderHeapEvent; #endif //=============================================================================== // This is the base class for LoaderHeap and ExplicitControlLoaderHeap. Unfortunately, // this class has become schizophrenic. Sometimes, it's used as a simple // allocator that's semantically (but not perfwise!) equivalent to a blackbox // alloc/free heap. Othertimes, it's used by callers who are actually aware // of how it reserves addresses and want direct control over the range over which // this thing allocates. These two types of allocations are handed out // from two independent pools inside the heap. // // The backout strategy we use for the simple heap probably isn't // directly applicable to the more advanced uses. // // We don't have time to refactor this so as a second-best measure, // we make most of UnlockedLoaderHeap's methods protected and force everyone // to use it them through two public derived classes that are mutual siblings. // // The LoaderHeap is the black-box heap and has a Backout() method but none // of the advanced features that let you control address ranges. // // The ExplicitControlLoaderHeap exposes all the advanced features but // has no Backout() feature. (If someone wants a backout feature, they need // to design an appropriate one into this class.) //=============================================================================== class UnlockedLoaderHeap { #ifdef _DEBUG friend class LoaderHeapSniffer; #endif #ifdef DACCESS_COMPILE friend class ClrDataAccess; #endif public: enum class HeapKind { Data, Executable, Interleaved }; private: // Linked list of ClrVirtualAlloc'd pages PTR_LoaderHeapBlock m_pFirstBlock; // Allocation pointer in current block PTR_BYTE m_pAllocPtr; // Points to the end of the committed region in the current block PTR_BYTE m_pPtrToEndOfCommittedRegion; PTR_BYTE m_pEndReservedRegion; // When we need to ClrVirtualAlloc() MEM_RESERVE a new set of pages, number of bytes to reserve DWORD m_dwReserveBlockSize; // When we need to commit pages from our reserved list, number of bytes to commit at a time DWORD m_dwCommitBlockSize; // For interleaved heap (RX pages interleaved with RW ones), this specifies the allocation granularity, // which is the individual code block size DWORD m_dwGranularity; // Range list to record memory ranges in RangeList * m_pRangeList; size_t m_dwTotalAlloc; HeapKind m_kind; LoaderHeapFreeBlock *m_pFirstFreeBlock; // This is used to hold on to a block of reserved memory provided to the // constructor. We do this instead of adding it as the first block because // that requires comitting the first page of the reserved block, and for // startup working set reasons we want to delay that as long as possible. LoaderHeapBlock m_reservedBlock; public: #ifdef _DEBUG enum { kCallTracing = 0x00000001, // Keep a permanent log of all callers kEncounteredOOM = 0x80000000, // One time flag to record that an OOM interrupted call tracing } LoaderHeapDebugFlags; DWORD m_dwDebugFlags; LoaderHeapEvent *m_pEventList; // Linked list of events (in reverse time order) #endif #ifdef _DEBUG size_t m_dwDebugWastedBytes; static DWORD s_dwNumInstancesOfLoaderHeaps; #endif #ifdef _DEBUG size_t DebugGetWastedBytes() { WRAPPER_NO_CONTRACT; return m_dwDebugWastedBytes + GetBytesAvailCommittedRegion(); } #endif #ifdef _DEBUG // Stubs allocated from a LoaderHeap will have unwind info registered with NT. // The info must be unregistered when the heap is destroyed. BOOL m_fPermitStubsWithUnwindInfo; BOOL m_fStubUnwindInfoUnregistered; #endif public: BOOL m_fExplicitControl; // Am I a LoaderHeap or an ExplicitControlLoaderHeap? void (*m_codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX); #ifdef DACCESS_COMPILE public: void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags); #endif public: typedef bool EnumPageRegionsCallback (PTR_VOID pvArgs, PTR_VOID pvAllocationBase, SIZE_T cbReserved); void EnumPageRegions (EnumPageRegionsCallback *pCallback, PTR_VOID pvArgs); #ifndef DACCESS_COMPILE protected: // Use this version if dwReservedRegionAddress already points to a // blob of reserved memory. This will set up internal data structures, // using the provided, reserved memory. UnlockedLoaderHeap(DWORD dwReserveBlockSize, DWORD dwCommitBlockSize, const BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, RangeList *pRangeList = NULL, HeapKind kind = HeapKind::Data, void (*codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX) = NULL, DWORD dwGranularity = 1); ~UnlockedLoaderHeap(); #endif private: size_t GetBytesAvailCommittedRegion(); size_t GetBytesAvailReservedRegion(); protected: // number of bytes available in region size_t UnlockedGetReservedBytesFree() { LIMITED_METHOD_CONTRACT; return m_pEndReservedRegion - m_pAllocPtr; } PTR_BYTE UnlockedGetAllocPtr() { LIMITED_METHOD_CONTRACT; return m_pAllocPtr; } private: // Get some more committed pages - either commit some more in the current reserved region, or, if it // has run out, reserve another set of pages BOOL GetMoreCommittedPages(size_t dwMinSize); // Commit memory pages starting at the specified adress BOOL CommitPages(void* pData, size_t dwSizeToCommitPart); protected: // Reserve some pages at any address BOOL UnlockedReservePages(size_t dwCommitBlockSize); protected: // In debug mode, allocate an extra LOADER_HEAP_DEBUG_BOUNDARY bytes and fill it with invalid data. The reason we // do this is that when we're allocating vtables out of the heap, it is very easy for code to // get careless, and end up reading from memory that it doesn't own - but since it will be // reading some other allocation's vtable, no crash will occur. By keeping a gap between // allocations, it is more likely that these errors will be encountered. void *UnlockedAllocMem(size_t dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ); void *UnlockedAllocMem_NoThrow(size_t dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ); protected: // Allocates memory aligned on power-of-2 boundary. // // The return value is a pointer that's guaranteed to be aligned. // // FREEING THIS BLOCK: Underneath, the actual block allocated may // be larger and start at an address prior to the one you got back. // It is this adjusted size and pointer that you pass to BackoutMem. // The required adjustment is passed back thru the pdwExtra pointer. // // Here is how to properly backout the memory: // // size_t dwExtra; // void *pMem = UnlockedAllocAlignedMem(dwRequestedSize, alignment, &dwExtra); // _ASSERTE( 0 == (pMem & (alignment - 1)) ); // UnlockedBackoutMem( ((BYTE*)pMem) - dExtra, dwRequestedSize + dwExtra ); // // If you use the AllocMemHolder or AllocMemTracker, all this is taken care of // behind the scenes. // // void *UnlockedAllocAlignedMem(size_t dwRequestedSize ,size_t dwAlignment ,size_t *pdwExtra #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ); void *UnlockedAllocAlignedMem_NoThrow(size_t dwRequestedSize ,size_t dwAlignment ,size_t *pdwExtra #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ); protected: // This frees memory allocated by UnlockAllocMem. It's given this horrible name to emphasize // that it's purpose is for error path leak prevention purposes. You shouldn't // use LoaderHeap's as general-purpose alloc-free heaps. void UnlockedBackoutMem(void *pMem , size_t dwSize #ifdef _DEBUG , _In_ _In_z_ const char *szFile , int lineNum , _In_ _In_z_ const char *szAllocFile , int AllocLineNum #endif ); public: // Perf Counter reports the size of the heap size_t GetSize () { LIMITED_METHOD_CONTRACT; return m_dwTotalAlloc; } BOOL IsExecutable(); BOOL IsInterleaved(); size_t AllocMem_TotalSize(size_t dwRequestedSize); public: #ifdef _DEBUG void DumpFreeList(); #endif public: // Extra CallTracing support #ifdef _DEBUG void UnlockedClearEvents(); //Discard saved events void UnlockedCompactEvents(); //Discard matching alloc/free events void UnlockedPrintEvents(); //Print event list #endif protected: void *UnlockedAllocMemForCode_NoThrow(size_t dwHeaderSize, size_t dwCodeSize, DWORD dwCodeAlignment, size_t dwReserveForJumpStubs); void UnlockedSetReservedRegion(BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, BOOL fReleaseMemory); }; //=============================================================================== // Create the LoaderHeap lock. It's the same lock for several different Heaps. //=============================================================================== inline CRITSEC_COOKIE CreateLoaderHeapLock() { return ClrCreateCriticalSection(CrstLoaderHeap,CrstFlags(CRST_UNSAFE_ANYMODE | CRST_DEBUGGER_THREAD)); } //=============================================================================== // The LoaderHeap is the black-box heap and has a Backout() method but none // of the advanced features that let you control address ranges. //=============================================================================== typedef DPTR(class LoaderHeap) PTR_LoaderHeap; class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout { private: CRITSEC_COOKIE m_CriticalSection; #ifndef DACCESS_COMPILE public: LoaderHeap(DWORD dwReserveBlockSize, DWORD dwCommitBlockSize, RangeList *pRangeList = NULL, UnlockedLoaderHeap::HeapKind kind = UnlockedLoaderHeap::HeapKind::Data, BOOL fUnlocked = FALSE, void (*codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX) = NULL, DWORD dwGranularity = 1 ) : UnlockedLoaderHeap(dwReserveBlockSize, dwCommitBlockSize, NULL, 0, pRangeList, kind, codePageGenerator, dwGranularity), m_CriticalSection(fUnlocked ? NULL : CreateLoaderHeapLock()) { WRAPPER_NO_CONTRACT; m_fExplicitControl = FALSE; } public: LoaderHeap(DWORD dwReserveBlockSize, DWORD dwCommitBlockSize, const BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, RangeList *pRangeList = NULL, UnlockedLoaderHeap::HeapKind kind = UnlockedLoaderHeap::HeapKind::Data, BOOL fUnlocked = FALSE, void (*codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX) = NULL, DWORD dwGranularity = 1 ) : UnlockedLoaderHeap(dwReserveBlockSize, dwCommitBlockSize, dwReservedRegionAddress, dwReservedRegionSize, pRangeList, kind, codePageGenerator, dwGranularity), m_CriticalSection(fUnlocked ? NULL : CreateLoaderHeapLock()) { WRAPPER_NO_CONTRACT; m_fExplicitControl = FALSE; } #endif // DACCESS_COMPILE virtual ~LoaderHeap() { WRAPPER_NO_CONTRACT; #ifndef DACCESS_COMPILE if (m_CriticalSection != NULL) { ClrDeleteCriticalSection(m_CriticalSection); } #endif // DACCESS_COMPILE } #ifdef _DEBUG #define AllocMem(dwSize) RealAllocMem( (dwSize), __FILE__, __LINE__ ) #define AllocMem_NoThrow(dwSize) RealAllocMem_NoThrow( (dwSize), __FILE__, __LINE__ ) #else #define AllocMem(dwSize) RealAllocMem( (dwSize) ) #define AllocMem_NoThrow(dwSize) RealAllocMem_NoThrow( (dwSize) ) #endif public: FORCEINLINE TaggedMemAllocPtr RealAllocMem(S_SIZE_T dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; if(dwSize.IsOverflow()) ThrowOutOfMemory(); return RealAllocMemUnsafe(dwSize.Value() COMMA_INDEBUG(szFile) COMMA_INDEBUG(lineNum)); } FORCEINLINE TaggedMemAllocPtr RealAllocMem_NoThrow(S_SIZE_T dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; if(dwSize.IsOverflow()) { TaggedMemAllocPtr tmap; tmap.m_pMem = NULL; tmap.m_dwRequestedSize = dwSize.Value(); tmap.m_pHeap = this; tmap.m_dwExtra = 0; #ifdef _DEBUG tmap.m_szFile = szFile; tmap.m_lineNum = lineNum; #endif return tmap; } return RealAllocMemUnsafe_NoThrow(dwSize.Value() COMMA_INDEBUG(szFile) COMMA_INDEBUG(lineNum)); } private: TaggedMemAllocPtr RealAllocMemUnsafe(size_t dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; void *pResult; TaggedMemAllocPtr tmap; CRITSEC_Holder csh(m_CriticalSection); pResult = UnlockedAllocMem(dwSize #ifdef _DEBUG , szFile , lineNum #endif ); tmap.m_pMem = pResult; tmap.m_dwRequestedSize = dwSize; tmap.m_pHeap = this; tmap.m_dwExtra = 0; #ifdef _DEBUG tmap.m_szFile = szFile; tmap.m_lineNum = lineNum; #endif return tmap; } TaggedMemAllocPtr RealAllocMemUnsafe_NoThrow(size_t dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; void *pResult; TaggedMemAllocPtr tmap; CRITSEC_Holder csh(m_CriticalSection); pResult = UnlockedAllocMem_NoThrow(dwSize #ifdef _DEBUG , szFile , lineNum #endif ); tmap.m_pMem = pResult; tmap.m_dwRequestedSize = dwSize; tmap.m_pHeap = this; tmap.m_dwExtra = 0; #ifdef _DEBUG tmap.m_szFile = szFile; tmap.m_lineNum = lineNum; #endif return tmap; } #ifdef _DEBUG #define AllocAlignedMem(dwSize, dwAlign) RealAllocAlignedMem( (dwSize), (dwAlign), __FILE__, __LINE__) #define AllocAlignedMem_NoThrow(dwSize, dwAlign) RealAllocAlignedMem_NoThrow( (dwSize), (dwAlign), __FILE__, __LINE__) #else #define AllocAlignedMem(dwSize, dwAlign) RealAllocAlignedMem( (dwSize), (dwAlign) ) #define AllocAlignedMem_NoThrow(dwSize, dwAlign) RealAllocAlignedMem_NoThrow( (dwSize), (dwAlign) ) #endif public: TaggedMemAllocPtr RealAllocAlignedMem(size_t dwRequestedSize ,size_t dwAlignment #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; CRITSEC_Holder csh(m_CriticalSection); TaggedMemAllocPtr tmap; void *pResult; size_t dwExtra; pResult = UnlockedAllocAlignedMem(dwRequestedSize ,dwAlignment ,&dwExtra #ifdef _DEBUG ,szFile ,lineNum #endif ); tmap.m_pMem = (void*)(((BYTE*)pResult) - dwExtra); tmap.m_dwRequestedSize = dwRequestedSize + dwExtra; tmap.m_pHeap = this; tmap.m_dwExtra = dwExtra; #ifdef _DEBUG tmap.m_szFile = szFile; tmap.m_lineNum = lineNum; #endif return tmap; } TaggedMemAllocPtr RealAllocAlignedMem_NoThrow(size_t dwRequestedSize ,size_t dwAlignment #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; CRITSEC_Holder csh(m_CriticalSection); TaggedMemAllocPtr tmap; void *pResult; size_t dwExtra; pResult = UnlockedAllocAlignedMem_NoThrow(dwRequestedSize ,dwAlignment ,&dwExtra #ifdef _DEBUG ,szFile ,lineNum #endif ); _ASSERTE(!(pResult == NULL && dwExtra != 0)); tmap.m_pMem = (void*)(((BYTE*)pResult) - dwExtra); tmap.m_dwRequestedSize = dwRequestedSize + dwExtra; tmap.m_pHeap = this; tmap.m_dwExtra = dwExtra; #ifdef _DEBUG tmap.m_szFile = szFile; tmap.m_lineNum = lineNum; #endif return tmap; } public: // This frees memory allocated by AllocMem. It's given this horrible name to emphasize // that it's purpose is for error path leak prevention purposes. You shouldn't // use LoaderHeap's as general-purpose alloc-free heaps. void RealBackoutMem(void *pMem , size_t dwSize #ifdef _DEBUG , _In_ _In_z_ const char *szFile , int lineNum , _In_ _In_z_ const char *szAllocFile , int allocLineNum #endif ) { WRAPPER_NO_CONTRACT; CRITSEC_Holder csh(m_CriticalSection); UnlockedBackoutMem(pMem , dwSize #ifdef _DEBUG , szFile , lineNum , szAllocFile , allocLineNum #endif ); } public: // Extra CallTracing support #ifdef _DEBUG void ClearEvents() { WRAPPER_NO_CONTRACT; CRITSEC_Holder csh(m_CriticalSection); UnlockedClearEvents(); } void CompactEvents() { WRAPPER_NO_CONTRACT; CRITSEC_Holder csh(m_CriticalSection); UnlockedCompactEvents(); } void PrintEvents() { WRAPPER_NO_CONTRACT; CRITSEC_Holder csh(m_CriticalSection); UnlockedPrintEvents(); } #endif }; //=============================================================================== // The ExplicitControlLoaderHeap exposes all the advanced features but // has no Backout() feature. (If someone wants a backout feature, they need // to design an appropriate one into this class.) // // Caller is responsible for synchronization. ExplicitControlLoaderHeap is // not multithread safe. //=============================================================================== typedef DPTR(class ExplicitControlLoaderHeap) PTR_ExplicitControlLoaderHeap; class ExplicitControlLoaderHeap : public UnlockedLoaderHeap { #ifndef DACCESS_COMPILE public: ExplicitControlLoaderHeap(RangeList *pRangeList = NULL, BOOL fMakeExecutable = FALSE ) : UnlockedLoaderHeap(0, 0, NULL, 0, pRangeList, fMakeExecutable ? UnlockedLoaderHeap::HeapKind::Executable : UnlockedLoaderHeap::HeapKind::Data) { WRAPPER_NO_CONTRACT; m_fExplicitControl = TRUE; } #endif // DACCESS_COMPILE public: void *RealAllocMem(size_t dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; void *pResult; pResult = UnlockedAllocMem(dwSize #ifdef _DEBUG , szFile , lineNum #endif ); return pResult; } void *RealAllocMem_NoThrow(size_t dwSize #ifdef _DEBUG ,_In_ _In_z_ const char *szFile ,int lineNum #endif ) { WRAPPER_NO_CONTRACT; void *pResult; pResult = UnlockedAllocMem_NoThrow(dwSize #ifdef _DEBUG , szFile , lineNum #endif ); return pResult; } public: void *AllocMemForCode_NoThrow(size_t dwHeaderSize, size_t dwCodeSize, DWORD dwCodeAlignment, size_t dwReserveForJumpStubs) { WRAPPER_NO_CONTRACT; return UnlockedAllocMemForCode_NoThrow(dwHeaderSize, dwCodeSize, dwCodeAlignment, dwReserveForJumpStubs); } void SetReservedRegion(BYTE* dwReservedRegionAddress, SIZE_T dwReservedRegionSize, BOOL fReleaseMemory) { WRAPPER_NO_CONTRACT; return UnlockedSetReservedRegion(dwReservedRegionAddress, dwReservedRegionSize, fReleaseMemory); } public: // number of bytes available in region size_t GetReservedBytesFree() { WRAPPER_NO_CONTRACT; return UnlockedGetReservedBytesFree(); } PTR_BYTE GetAllocPtr() { WRAPPER_NO_CONTRACT; return UnlockedGetAllocPtr(); } void ReservePages(size_t size) { WRAPPER_NO_CONTRACT; UnlockedReservePages(size); } }; //============================================================================== // AllocMemHolder : Allocated memory from LoaderHeap // // Old: // // Foo* pFoo = (Foo*)pLoaderHeap->AllocMem(size); // pFoo->BackoutMem(pFoo, size) // // // New: // // { // AllocMemHolder pfoo = pLoaderHeap->AllocMem(); // } // BackoutMem on out of scope // //============================================================================== template class AllocMemHolder { private: TaggedMemAllocPtr m_value; BOOL m_fAcquired; //-------------------------------------------------------------------- // All allowed (and disallowed) ctors here. //-------------------------------------------------------------------- public: // Allow the construction "Holder h;" AllocMemHolder() { LIMITED_METHOD_CONTRACT; m_value.m_pMem = NULL; m_value.m_dwRequestedSize = 0; m_value.m_pHeap = 0; m_value.m_dwExtra = 0; #ifdef _DEBUG m_value.m_szFile = NULL; m_value.m_lineNum = 0; #endif m_fAcquired = FALSE; } public: // Allow the construction "Holder h = pHeap->AllocMem()" AllocMemHolder(const TaggedMemAllocPtr value) { LIMITED_METHOD_CONTRACT; m_value = value; m_fAcquired = TRUE; } private: // Disallow "Holder holder1 = holder2" AllocMemHolder(const AllocMemHolder &); private: // Disallow "Holder holder1 = void*" AllocMemHolder(const LPVOID &); //-------------------------------------------------------------------- // Destructor (and the whole point of AllocMemHolder) //-------------------------------------------------------------------- public: ~AllocMemHolder() { WRAPPER_NO_CONTRACT; if (m_fAcquired && m_value.m_pMem) { m_value.m_pHeap->RealBackoutMem(m_value.m_pMem, m_value.m_dwRequestedSize #ifdef _DEBUG ,__FILE__ ,__LINE__ ,m_value.m_szFile ,m_value.m_lineNum #endif ); } } //-------------------------------------------------------------------- // All allowed (and disallowed) assignment operators here. //-------------------------------------------------------------------- public: // Reluctantly allow "AllocMemHolder h; ... h = pheap->AllocMem()" void operator=(const TaggedMemAllocPtr & value) { WRAPPER_NO_CONTRACT; // However, prevent repeated assignments as that would leak. _ASSERTE(m_value.m_pMem == NULL && !m_fAcquired); m_value = value; m_fAcquired = TRUE; } private: // Disallow "holder == holder2" const AllocMemHolder & operator=(const AllocMemHolder &); private: // Disallow "holder = void*" const AllocMemHolder & operator=(const LPVOID &); //-------------------------------------------------------------------- // Operations on the holder itself //-------------------------------------------------------------------- public: // Call this when you're ready to take ownership away from the holder. void SuppressRelease() { LIMITED_METHOD_CONTRACT; m_fAcquired = FALSE; } //-------------------------------------------------------------------- // ... And the smart-pointer stuff so we can drop holders on top // of former pointer variables (mostly) //-------------------------------------------------------------------- public: // Allow holder to be treated as the underlying pointer type operator TYPE* () { LIMITED_METHOD_CONTRACT; return (TYPE*)(void*)m_value; } public: // Allow holder to be treated as the underlying pointer type TYPE* operator->() { LIMITED_METHOD_CONTRACT; return (TYPE*)(void*)m_value; } public: int operator==(TYPE* value) { LIMITED_METHOD_CONTRACT; return ((void*)m_value) == ((void*)value); } public: int operator!=(TYPE* value) { LIMITED_METHOD_CONTRACT; return ((void*)m_value) != ((void*)value); } public: int operator!() const { LIMITED_METHOD_CONTRACT; return m_value.m_pMem == NULL; } }; // This utility helps track loaderheap allocations. Its main purpose // is to backout allocations in case of an exception. class AllocMemTracker { public: AllocMemTracker(); ~AllocMemTracker(); // Tells tracker to store an allocated loaderheap block. // // Returns the pointer address of block for convenience. // // Ok to call on failed loaderheap allocation (will just do nothing and propagate the OOM as apropos). // // If Track fails due to an OOM allocating node space, it will backout the loaderheap block before returning. void *Track(TaggedMemAllocPtr tmap); void *Track_NoThrow(TaggedMemAllocPtr tmap); void SuppressRelease(); private: struct AllocMemTrackerNode { ILoaderHeapBackout *m_pHeap; void *m_pMem; size_t m_dwRequestedSize; #ifdef _DEBUG const char *m_szAllocFile; int m_allocLineNum; #endif }; enum { kAllocMemTrackerBlockSize = #ifdef _DEBUG 3 #else 20 #endif }; struct AllocMemTrackerBlock { AllocMemTrackerBlock *m_pNext; int m_nextFree; AllocMemTrackerNode m_Node[kAllocMemTrackerBlockSize]; }; AllocMemTrackerBlock *m_pFirstBlock; AllocMemTrackerBlock m_FirstBlock; // Stack-allocate the first block - "new" the rest. protected: BOOL m_fReleased; }; #endif // __LoaderHeap_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/log.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Logging Facility // // Logging Subsystems #ifndef __LOG_H__ #define __LOG_H__ #define DEFINE_LOG_FACILITY(logname, value) logname = value, enum { #include "loglf.h" LF_ALWAYS = 0x80000000, // Log message irrepespective of LogFacility (if the level matches) LF_ALL = 0xFFFFFFFF, // Used only to mask bits. Never use as LOG((LF_ALL, ...)) // LogFacility2: all 32-bit of LogFacility are used, need a 2nd DWORD for more facilities LF2_MULTICOREJIT = 0x00000001 // Multicore JIT }; #define LL_EVERYTHING 10 #define LL_INFO1000000 9 // can be expected to generate 1,000,000 logs per small but not trivial run #define LL_INFO100000 8 // can be expected to generate 100,000 logs per small but not trivial run #define LL_INFO10000 7 // can be expected to generate 10,000 logs per small but not trivial run #define LL_INFO1000 6 // can be expected to generate 1,000 logs per small but not trivial run #define LL_INFO100 5 // can be expected to generate 100 logs per small but not trivial run #define LL_INFO10 4 // can be expected to generate 10 logs per small but not trivial run #define LL_WARNING 3 #define LL_ERROR 2 #define LL_FATALERROR 1 #define LL_ALWAYS 0 // impossible to turn off (log level never negative) #define INFO5 LL_INFO10 #define INFO4 LL_INFO100 #define INFO3 LL_INFO1000 #define INFO2 LL_INFO10000 #define INFO1 LL_INFO100000 #define WARNING 0 #define ERROR 0 #define FATALERROR 0 #ifndef LOGGING #define LOG(x) #define LOG2(x) #define LOGALWAYS(x) #define InitializeLogging() #define InitLogging() #define ShutdownLogging() #define FlushLogging() #define LoggingOn(facility, level) 0 #define Logging2On(facility, level) 0 #define EnterLogLock() #define LeaveLogLock() #else extern VOID InitializeLogging(); extern VOID InitLogging(); extern VOID ShutdownLogging(); extern VOID FlushLogging(); extern VOID LogSpew(DWORD facility, DWORD level, const char *fmt, ... ); extern VOID LogSpewValist(DWORD facility, DWORD level, const char *fmt, va_list args); extern VOID LogSpew2(DWORD facility2, DWORD level, const char *fmt, ... ); extern VOID LogSpew2Valist(DWORD facility2, DWORD level, const char *fmt, va_list args); extern VOID LogSpewAlwaysValist(const char *fmt, va_list args); extern VOID LogSpewAlways (const char *fmt, ... ); extern VOID EnterLogLock(); extern VOID LeaveLogLock(); VOID AddLoggingFacility( DWORD facility ); VOID SetLoggingLevel( DWORD level ); bool LoggingEnabled(); bool LoggingOn(DWORD facility, DWORD level); bool Logging2On(DWORD facility, DWORD level); #define LOG(x) do { if (LoggingEnabled()) { LogSpew x; } } while (0) #define LOG2(x) do { if (LoggingEnabled()) { LogSpew2 x; } } while (0) #define LOGALWAYS(x) LogSpewAlways x #endif #ifdef __cplusplus #include "stresslog.h" // special logging for retail code #endif #endif //__LOG_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/loglf.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // The code in sos.DumpLog depends on the first 32 facility codes // being bit flags sorted in incresing order. DEFINE_LOG_FACILITY(LF_GC ,0x00000001) DEFINE_LOG_FACILITY(LF_GCINFO ,0x00000002) DEFINE_LOG_FACILITY(LF_STUBS ,0x00000004) DEFINE_LOG_FACILITY(LF_JIT ,0x00000008) DEFINE_LOG_FACILITY(LF_LOADER ,0x00000010) DEFINE_LOG_FACILITY(LF_METADATA ,0x00000020) DEFINE_LOG_FACILITY(LF_SYNC ,0x00000040) DEFINE_LOG_FACILITY(LF_EEMEM ,0x00000080) DEFINE_LOG_FACILITY(LF_GCALLOC ,0x00000100) DEFINE_LOG_FACILITY(LF_CORDB ,0x00000200) DEFINE_LOG_FACILITY(LF_CLASSLOADER ,0x00000400) DEFINE_LOG_FACILITY(LF_CORPROF ,0x00000800) DEFINE_LOG_FACILITY(LF_DIAGNOSTICS_PORT ,0x00001000) DEFINE_LOG_FACILITY(LF_DBGALLOC ,0x00002000) DEFINE_LOG_FACILITY(LF_EH ,0x00004000) DEFINE_LOG_FACILITY(LF_ENC ,0x00008000) DEFINE_LOG_FACILITY(LF_ASSERT ,0x00010000) DEFINE_LOG_FACILITY(LF_VERIFIER ,0x00020000) DEFINE_LOG_FACILITY(LF_THREADPOOL ,0x00040000) DEFINE_LOG_FACILITY(LF_GCROOTS ,0x00080000) DEFINE_LOG_FACILITY(LF_INTEROP ,0x00100000) DEFINE_LOG_FACILITY(LF_MARSHALER ,0x00200000) DEFINE_LOG_FACILITY(LF_TIEREDCOMPILATION ,0x00400000) // This used to be IJW, but now repurposed for tiered compilation DEFINE_LOG_FACILITY(LF_ZAP ,0x00800000) DEFINE_LOG_FACILITY(LF_STARTUP ,0x01000000) // Log startupa and shutdown failures DEFINE_LOG_FACILITY(LF_APPDOMAIN ,0x02000000) DEFINE_LOG_FACILITY(LF_CODESHARING ,0x04000000) DEFINE_LOG_FACILITY(LF_STORE ,0x08000000) DEFINE_LOG_FACILITY(LF_SECURITY ,0x10000000) DEFINE_LOG_FACILITY(LF_LOCKS ,0x20000000) DEFINE_LOG_FACILITY(LF_BCL ,0x40000000) // LF_ALWAYS 0x80000000 // make certain you don't try to use this bit for a real facility // LF_ALL 0xFFFFFFFF // #undef DEFINE_LOG_FACILITY ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/longfilepathwrappers.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _WIN_PATH_APIS_WRAPPER_ #define _WIN_PATH_APIS_WRAPPER_ class SString; HMODULE LoadLibraryExWrapper( _In_ LPCWSTR lpLibFileName, _Reserved_ HANDLE hFile = NULL, _In_ DWORD dwFlags = 0 ); HANDLE CreateFileWrapper( _In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode, _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile ); DWORD GetFileAttributesWrapper( _In_ LPCWSTR lpFileName ); BOOL GetFileAttributesExWrapper( _In_ LPCWSTR lpFileName, _In_ GET_FILEEX_INFO_LEVELS fInfoLevelId, _Out_writes_bytes_(sizeof(WIN32_FILE_ATTRIBUTE_DATA)) LPVOID lpFileInformation ); #ifndef HOST_UNIX BOOL CopyFileExWrapper( _In_ LPCWSTR lpExistingFileName, _In_ LPCWSTR lpNewFileName, _In_opt_ LPPROGRESS_ROUTINE lpProgressRoutine, _In_opt_ LPVOID lpData, _When_(pbCancel != NULL, _Pre_satisfies_(*pbCancel == FALSE)) _Inout_opt_ LPBOOL pbCancel, _In_ DWORD dwCopyFlags ); #endif //HOST_UNIX DWORD SearchPathWrapper( _In_opt_ LPCWSTR lpPath, _In_ LPCWSTR lpFileName, _In_opt_ LPCWSTR lpExtension, _In_ BOOL getPath, SString& lpBuffer, _Out_opt_ LPWSTR * lpFilePart ); DWORD WINAPI GetTempPathWrapper( SString& lpBuffer ); DWORD GetModuleFileNameWrapper( _In_opt_ HMODULE hModule, SString& buffer ); DWORD WINAPI GetEnvironmentVariableWrapper( _In_opt_ LPCTSTR lpName, _Out_opt_ SString& lpBuffer ); #endif //_WIN_PATH_APIS_WRAPPER_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/md5.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // md5.h // // // A pretty fast implementation of MD5 // #ifndef __MD5_H__ #define __MD5_H__ ///////////////////////////////////////////////////////////////////////////////////// // // Declaration of the central transform function // void __stdcall MD5Transform(ULONG state[4], const ULONG* data); ///////////////////////////////////////////////////////////////////////////////////// #include // This structure is used to return the final resulting hash. // struct MD5HASHDATA { union { BYTE rgb[16]; struct { ULONGLONG ullLow; ULONGLONG ullHigh; } u; struct { ULONG u0; ULONG u1; ULONG u2; ULONG u3; } v; }; }; inline BOOL operator==(const MD5HASHDATA& me, const MD5HASHDATA& him) { return memcmp(&me, &him, sizeof(MD5HASHDATA)) == 0; } inline BOOL operator!=(const MD5HASHDATA& me, const MD5HASHDATA& him) { return memcmp(&me, &him, sizeof(MD5HASHDATA)) != 0; } // The engine that carries out the hash // class MD5 { // These four values must be contiguous, and in this order union { ULONG m_state[4]; struct { ULONG m_a; // state ULONG m_b; // ... variables ULONG m_c; // ... as found in ULONG m_d; // ... RFC1321 } u; }; BYTE m_data[64]; // where to accumulate the data as we are passed it ULONGLONG m_cbitHashed; // amount of data that we've hashed ULONG m_cbData; // number of bytes presently in data BYTE m_padding[64]; // padding data, used if length data not = 0 mod 64 public: ///////////////////////////////////////////////////////////////////////////////////// void Hash(const BYTE* pbData, ULONG cbData, MD5HASHDATA* phash, BOOL fConstructed = FALSE) { Init(fConstructed); HashMore(pbData, cbData); GetHashValue(phash); } ///////////////////////////////////////////////////////////////////////////////////// void Hash(const BYTE* pbData, ULONGLONG cbData, MD5HASHDATA* phash, BOOL fConstructed = FALSE) { Init(fConstructed); ULARGE_INTEGER ul; ul.QuadPart = cbData; while (ul.u.HighPart) { ULONG cbHash = 0xFFFFFFFF; // Hash as much as we can at once HashMore(pbData, cbHash); pbData += cbHash; ul.QuadPart -= cbHash; } HashMore(pbData, ul.u.LowPart); // Hash whatever is left GetHashValue(phash); } ///////////////////////////////////////////////////////////////////////////////////// void Init(BOOL fConstructed = FALSE); ///////////////////////////////////////////////////////////////////////////////////// void HashMore(const void* pvInput, ULONG cbInput); ///////////////////////////////////////////////////////////////////////////////////// void GetHashValue(MD5HASHDATA* phash); ///////////////////////////////////////////////////////////////////////////////////// }; #include #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/mdcommon.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // MDCommon.h // // Common header file for both MD and COMPLIB subdirectories // //***************************************************************************** #ifndef __MDCommon_h__ #define __MDCommon_h__ // File types for the database. enum FILETYPE { FILETYPE_UNKNOWN, // Unknown or undefined type. FILETYPE_CLB, // Native .clb file format. FILETYPE_NTPE, // Windows PE executable. }; enum MAPPINGTYPE { MTYPE_NOMAPPING, // No mapped file MTYPE_FLAT, // Mapped as a flat file MTYPE_IMAGE // Mapped with the SEC_IMAGE flag }; #define SCHEMA_STREAM_A "#Schema" #define STRING_POOL_STREAM_A "#Strings" #define BLOB_POOL_STREAM_A "#Blob" #define US_BLOB_POOL_STREAM_A "#US" #define GUID_POOL_STREAM_A "#GUID" #define COMPRESSED_MODEL_STREAM_A "#~" #define ENC_MODEL_STREAM_A "#-" #define MINIMAL_MD_STREAM_A "#JTD" #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB #define PDB_STREAM_A "#Pdb" #endif // FEATURE_METADATA_EMIT_PORTABLE_PDB #define SCHEMA_STREAM W("#Schema") #define STRING_POOL_STREAM W("#Strings") #define BLOB_POOL_STREAM W("#Blob") #define US_BLOB_POOL_STREAM W("#US") #define GUID_POOL_STREAM W("#GUID") #define COMPRESSED_MODEL_STREAM W("#~") #define ENC_MODEL_STREAM W("#-") #define MINIMAL_MD_STREAM W("#JTD") #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB #define PDB_STREAM W("#Pdb") #endif // FEATURE_METADATA_EMIT_PORTABLE_PDB #endif // __MDCommon_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/mdfileformat.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // MDFileFormat.h // // // This file contains a set of helpers to verify and read the file format. // This code does not handle the paging of the data, or different types of // I/O. See the StgTiggerStorage and StgIO code for this level of support. // //***************************************************************************** #ifndef __MDFileFormat_h__ #define __MDFileFormat_h__ #include #include "utilcode.h" //***************************************************************************** // The signature ULONG is the first 4 bytes of the file format. The second // signature string starts the header containing the stream list. It is used // for an integrity check when reading the header in lieu of a more complicated // system. //***************************************************************************** #define STORAGE_MAGIC_SIG 0x424A5342 // BSJB //***************************************************************************** // These values get written to the signature at the front of the file. Changing // these values should not be done lightly because all old files will no longer // be supported. In a future revision if a format change is required, a // backwards compatible migration path must be provided. //***************************************************************************** #define FILE_VER_MAJOR 1 #define FILE_VER_MINOR 1 // These are the last legitimate 0.x version macros. The file format has // sinced move up to 1.x (see macros above). After COM+ 1.0/NT 5 RTM's, these // macros should no longer be required or ever seen. #define FILE_VER_MAJOR_v0 0 #define FILE_VER_MINOR_v0 19 #define MAXSTREAMNAME 32 enum { STGHDR_NORMAL = 0x00, // Normal default flags. STGHDR_EXTRADATA = 0x01, // Additional data exists after header. }; //***************************************************************************** // This is the formal signature area at the front of the file. This structure // is not allowed to change, the shim depends on it staying the same size. // Use the reserved pointer if it must extended. //***************************************************************************** struct STORAGESIGNATURE; typedef STORAGESIGNATURE UNALIGNED * PSTORAGESIGNATURE; #include "pshpack1.h" struct STORAGESIGNATURE { METADATA_FIELDS_PROTECTION: ULONG lSignature; // "Magic" signature. USHORT iMajorVer; // Major file version. USHORT iMinorVer; // Minor file version. ULONG iExtraData; // Offset to next structure of information ULONG iVersionString; // Length of version string public: BYTE pVersion[0]; // Version string ULONG GetSignature() { return VAL32(lSignature); } void SetSignature(ULONG Signature) { lSignature = VAL32(Signature); } USHORT GetMajorVer() { return VAL16(iMajorVer); } void SetMajorVer(USHORT MajorVer) { iMajorVer = VAL16(MajorVer); } USHORT GetMinorVer() { return VAL16(iMinorVer); } void SetMinorVer(USHORT MinorVer) { iMinorVer = VAL16(MinorVer); } ULONG GetExtraDataOffset() { return VAL32(iExtraData); } void SetExtraDataOffset(ULONG ExtraDataOffset) { iExtraData = VAL32(ExtraDataOffset); } ULONG GetVersionStringLength() { return VAL32(iVersionString); } void SetVersionStringLength(ULONG VersionStringLength) { iVersionString = VAL32(VersionStringLength); } }; #include "poppack.h" //***************************************************************************** // The header of the storage format. //***************************************************************************** struct STORAGEHEADER; typedef STORAGEHEADER UNALIGNED * PSTORAGEHEADER; #include "pshpack1.h" struct STORAGEHEADER { METADATA_FIELDS_PROTECTION: BYTE fFlags; // STGHDR_xxx flags. BYTE pad; USHORT iStreams; // How many streams are there. public: BYTE GetFlags() { return fFlags; } void SetFlags(BYTE flags) { fFlags = flags; } void AddFlags(BYTE flags) { fFlags |= flags; } USHORT GetiStreams() { return VAL16(iStreams); } void SetiStreams(USHORT iStreamsCount) { iStreams = VAL16(iStreamsCount); } }; #include "poppack.h" //***************************************************************************** // Each stream is described by this struct, which includes the offset and size // of the data. The name is stored in ANSI null terminated. //***************************************************************************** struct STORAGESTREAM; typedef STORAGESTREAM UNALIGNED * PSTORAGESTREAM; #include "pshpack1.h" struct STORAGESTREAM { METADATA_FIELDS_PROTECTION: ULONG iOffset; // Offset in file for this stream. ULONG iSize; // Size of the file. char rcName[MAXSTREAMNAME]; // Start of name, null terminated. public: // Returns pointer to the next stream. Doesn't validate the structure. inline PSTORAGESTREAM NextStream() { int iLen = (int)(strlen(rcName) + 1); iLen = ALIGN4BYTE(iLen); return ((PSTORAGESTREAM) (((BYTE*)this) + (sizeof(ULONG) * 2) + iLen)); } // Returns pointer to the next stream. // Returns NULL if the structure has invalid format. inline PSTORAGESTREAM NextStream_Verify() { // Check existence of null-terminator in the name if (memchr(rcName, 0, MAXSTREAMNAME) == NULL) { return NULL; } return NextStream(); } inline ULONG GetStreamSize() { return (ULONG)(strlen(rcName) + 1 + (sizeof(STORAGESTREAM) - sizeof(rcName))); } inline char* GetName() { return rcName; } inline LPCWSTR GetName(__inout_ecount (iMaxSize) LPWSTR szName, int iMaxSize) { VERIFY(::WszMultiByteToWideChar(CP_ACP, 0, rcName, -1, szName, iMaxSize)); return (szName); } inline void SetName(LPCWSTR szName) { int size; size = WszWideCharToMultiByte(CP_ACP, 0, szName, -1, rcName, MAXSTREAMNAME, 0, 0); _ASSERTE(size > 0); } ULONG GetSize() { return VAL32(iSize); } void SetSize(ULONG Size) { iSize = VAL32(Size); } ULONG GetOffset() { return VAL32(iOffset); } void SetOffset(ULONG Offset) { iOffset = VAL32(Offset); } }; #include "poppack.h" class MDFormat { public: //***************************************************************************** // Verify the signature at the front of the file to see what type it is. //***************************************************************************** static HRESULT VerifySignature( PSTORAGESIGNATURE pSig, // The signature to check. ULONG cbData); // Size of metadata. //***************************************************************************** // Skip over the header and find the actual stream data. // It doesn't perform any checks for buffer overflow - use GetFirstStream_Verify // instead. //***************************************************************************** static PSTORAGESTREAM GetFirstStream(// Return pointer to the first stream. PSTORAGEHEADER pHeader, // Return copy of header struct. const void *pvMd); // Pointer to the full file. //***************************************************************************** // Skip over the header and find the actual stream data. Secure version of // GetFirstStream method. // The header is supposed to be verified by VerifySignature. // // Caller has to check available buffer size before using the first stream. //***************************************************************************** static PSTORAGESTREAM GetFirstStream_Verify(// Return pointer to the first stream. PSTORAGEHEADER pHeader, // Return copy of header struct. const void *pvMd, // Pointer to the full file. ULONG *pcbMd); // [in, out] Size of pvMd buffer (we don't want to read behind it) }; #endif // __MDFileFormat_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/memorypool.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _MEMORYPOOL_ #define _MEMORYPOOL_ #include "daccess.h" #include "contract.h" // // A MemoryPool is an allocator for a fixed size elements. // Allocating and freeing elements from the pool is very cheap compared // to a general allocator like new. However, a MemoryPool is slightly // more greedy - it preallocates a bunch of elements at a time, and NEVER // RELEASES MEMORY FROM THE POOL ONCE IT IS ALLOCATED, (unless you call // FreeAllElements.) // // It also has several additional features: // * you can free the entire pool of objects cheaply. // * you can test an object to see if it's an element of the pool. // class MemoryPool { public: #ifndef DACCESS_COMPILE MemoryPool(SIZE_T elementSize, SIZE_T initGrowth = 20, SIZE_T initCount = 0); #else MemoryPool() {} #endif ~MemoryPool() DAC_EMPTY(); BOOL IsElement(void *element); BOOL IsAllocatedElement(void *element); void *AllocateElement(); void *AllocateElementNoThrow(); void FreeElement(void *element); void FreeAllElements(); size_t GetSize(); private: struct Element { Element *next; #if _DEBUG int deadBeef; #endif }; struct Block { Block *next; Element *elementsEnd; #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4200) #endif Element elements[0]; #ifdef _MSC_VER #pragma warning(pop) #endif }; SIZE_T m_elementSize; SIZE_T m_growCount; Block *m_blocks; Element *m_freeList; BOOL AddBlock(SIZE_T elementCount); void DeadBeef(Element *element); public: // // NOTE: You can currently only iterate the elements // if none have been freed. // class Iterator { private: Block *m_next; BYTE *m_e, *m_eEnd; BYTE *m_end; SIZE_T m_size; public: Iterator(MemoryPool *pool); BOOL Next(); void *GetElement() {LIMITED_METHOD_CONTRACT; return (void *) (m_e-m_size); } }; friend class Iterator; }; class MemoryPoolElementHolder { protected: MemoryPool* m_pool; void* m_element; BOOL bRelease; public: void SuppressRelease() { LIMITED_METHOD_CONTRACT; _ASSERTE(bRelease); bRelease=false; } void Release() { LIMITED_METHOD_CONTRACT; _ASSERTE(bRelease); m_pool->FreeElement(m_element); bRelease=false; } MemoryPoolElementHolder(MemoryPool* pool, void* element) { LIMITED_METHOD_CONTRACT; m_pool=pool; m_element=element; bRelease=true; } ~MemoryPoolElementHolder() { LIMITED_METHOD_CONTRACT; if (bRelease) Release(); } operator void* () { LIMITED_METHOD_CONTRACT; return m_element; } }; #endif // _MEMORYPOOL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/memoryrange.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // MemoryRange.h // // defines the code:MemoryRange class. //***************************************************************************** #ifndef _memory_range_h #define _memory_range_h #include "daccess.h" // MemoryRange is a descriptor of a memory range. This groups (pointer + size). // // Some key qualities: // - simple! // - Not mutable // - blitabble descriptor which can be useful for out-of-process tools like the debugger. // - no ownership semantics. // - no manipulation, growing semantics. // - no memory marshalling, allocation, copying. etc. // - can be efficiently passed / copied / returned by value // // This class has general value as an abstraction to group pointer and size together. It also has significant // value to the debugger. An expected design pattern is that other mutable complex data structures (eg, // code:SBuffer, code:CGrowableStream) will provide an accessor to expose their underlying storage as a // MemoryRange to debugger. This mirrors the Debugger's code:TargetBuffer data structure, but as a // general-purpose VM utility versus a debugger right-side data structure. // class MemoryRange { public: // Constructor to create a memory range around a (start address, size) pair. MemoryRange() : m_pStartAddress(NULL), m_cbBytes(0) { SUPPORTS_DAC; } MemoryRange(PTR_VOID pStartAddress, SIZE_T cbBytes) : m_pStartAddress(pStartAddress), m_cbBytes(cbBytes) { SUPPORTS_DAC; } // Note: use compiler-default copy ctor and assignment operator // Check whether a pointer is in the memory range represented by this instance. BOOL IsInRange(PTR_VOID pAddress) const { LIMITED_METHOD_DAC_CONTRACT; return (dac_cast(pAddress) - dac_cast(m_pStartAddress)) < m_cbBytes; } // Check whether a pointer is in the memory range represented by this instance. BOOL IsInRange(TADDR pAddress) const { LIMITED_METHOD_DAC_CONTRACT; return (pAddress - dac_cast(m_pStartAddress)) < m_cbBytes; } // Get the starting address. PTR_VOID StartAddress() const { SUPPORTS_DAC; return m_pStartAddress; } // Get the size of the range in bytes SIZE_T Size() const { SUPPORTS_DAC; return m_cbBytes; } private: // The start of the memory range. PTR_VOID const m_pStartAddress; // The size of the memory range in bytes. // This is s SIZE_T so that it can describe any memory range in the process (for example, larger than 4gb on 64-bit machines) const SIZE_T m_cbBytes; }; typedef ArrayDPTR(MemoryRange) ARRAY_PTR_MemoryRange; #endif // _memory_range_h ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/metadata.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //**************************************************************************** // File: metadata.h // // // Notes: // Common includes for EE & metadata internal. This file contains // definition of CorMetaDataScope //**************************************************************************** #ifndef _METADATA_H_ #define _METADATA_H_ #include "ex.h" class IMetaModelCommon; class MDInternalRW; class UTSemReadWrite; inline int IsGlobalMethodParentTk(mdTypeDef td) { LIMITED_METHOD_CONTRACT; return (td == mdTypeDefNil || td == mdTokenNil); } typedef enum CorInternalStates { tdNoTypes = 0x00000000, tdAllAssemblies = 0x00000001, tdAllTypes = 0xffffffff, } CorInternalStates; // // MetaData custom value names. // enum CorIfaceAttr { ifDual = 0, // Interface derives from IDispatch. ifVtable = 1, // Interface derives from IUnknown. ifDispatch = 2, // Interface is a dispinterface. ifInspectable = 3, // Interface derives from IInspectable. ifLast = 4, // The last member of the enum. }; inline BOOL IsDispatchBasedItf(CorIfaceAttr ifaceAttr) { return (ifaceAttr == ifDual || ifaceAttr == ifDispatch); } enum CorClassIfaceAttr { clsIfNone = 0, // No class interface is generated. clsIfAutoDisp = 1, // A dispatch only class interface is generated. clsIfAutoDual = 2, // A dual class interface is generated. clsIfLast = 3, // The last member of the enum. }; // // The default values for the COM interface and class interface types. // #define DEFAULT_COM_INTERFACE_TYPE ifDual #define DEFAULT_CLASS_INTERFACE_TYPE clsIfAutoDisp #define HANDLE_UNCOMPRESSED(func) (E_FAIL) #define HANDLE_UNCOMPRESSED_BOOL(func) (false) class TOKENLIST : public CDynArray { }; typedef enum tagEnumType { MDSimpleEnum = 0x0, // simple enumerator that doesn't allocate memory // You could get this kind of enum if you perform a non-simple query (such as EnumMethodWithName). // MDDynamicArrayEnum = 0x2, // dynamic array that holds tokens } EnumType; //***************************************** // Enumerator used by MetaDataInternal //***************************************** struct HENUMInternal { DWORD m_tkKind; // kind of tables that the enum is holding the result uint32_t m_ulCount; // count of total entries holding by the enumerator EnumType m_EnumType; struct { uint32_t m_ulStart; uint32_t m_ulEnd; uint32_t m_ulCur; } u; // m_cursor will go away when we no longer support running EE with uncompressed // format. WHEN WE REMOVE THIS, REMOVE ITS VESTIAGES FROM ZeroEnum as well // union { void* m_alignpad; // The first item is m_cursor[] is a pointer char m_cursor[32]; // cursor holding query result for read/write mode }; // TOKENLIST daTKList; // dynamic arrays of token list HENUMInternal() : m_EnumType(MDSimpleEnum) { LIMITED_METHOD_DAC_CONTRACT; } // in-place initialization static void InitDynamicArrayEnum( HENUMInternal *pEnum); // HENUMInternal to be initialized static void InitSimpleEnum( DWORD tkKind, // kind of token that we are iterating ULONG ridStart, // starting rid ULONG ridEnd, // end rid HENUMInternal *pEnum); // HENUMInternal to be initialized // Specialized helper which should be better than always calling memset inline static void ZeroEnum( HENUMInternal *pEnum) { // we use this to avoid the memset that will happen otherwise. // this should be inlined in its caller. we are seeing a large // number of calls to memset from MDInternalRO::EnumPermissionSetsInit // on x64 which we can eliminate with this code. pEnum->m_tkKind = 0; pEnum->m_ulCount = 0; pEnum->m_EnumType = MDSimpleEnum; pEnum->u.m_ulStart = 0; pEnum->u.m_ulEnd = 0; pEnum->u.m_ulCur = 0; // TODO: remove this when we remove m_cursor from the HENUMInternal structure _ASSERTE(IS_ALIGNED(pEnum->m_cursor, sizeof(DWORD))); _ASSERTE((sizeof(HENUMInternal) - offsetof(HENUMInternal, m_cursor)) == (8 * sizeof(DWORD))); DWORD* pBuffer = (DWORD*)pEnum->m_cursor; pBuffer[0] = 0; pBuffer[1] = 0; pBuffer[2] = 0; pBuffer[3] = 0; pBuffer[4] = 0; pBuffer[5] = 0; pBuffer[6] = 0; pBuffer[7] = 0; } // This will only clear the content of enum and will not free the memory of enum static void ClearEnum( HENUMInternal *pmdEnum); // create a HENUMInternal. This will allocate the memory __checkReturn static HRESULT CreateSimpleEnum( DWORD tkKind, // kind of token that we are iterating ULONG ridStart, // starting rid ULONG ridEnd, // end rid HENUMInternal **ppEnum); // return the created HENUMInternal __checkReturn static HRESULT CreateDynamicArrayEnum( DWORD tkKind, // kind of token that we are iterating HENUMInternal **ppEnum); // return the created HENUMInternal // Destroy Enum. This will free the memory static void DestroyEnum( HENUMInternal *pmdEnum); static void DestroyEnumIfEmpty( HENUMInternal **ppEnum); // reset the enumerator pointer to NULL if empty __checkReturn static HRESULT EnumWithCount( HENUMInternal *pEnum, // enumerator ULONG cMax, // max tokens that caller wants mdToken rTokens[], // output buffer to fill the tokens ULONG *pcTokens); // number of tokens fill to the buffer upon return __checkReturn static HRESULT EnumWithCount( HENUMInternal *pEnum, // enumerator ULONG cMax, // max tokens that caller wants mdToken rTokens1[], // first output buffer to fill the tokens mdToken rTokens2[], // second output buffer to fill the tokens ULONG *pcTokens); // number of tokens fill to the buffer upon return __checkReturn static HRESULT AddElementToEnum( HENUMInternal *pEnum, // return the created HENUMInternal mdToken tk); // token to fill //***************************************** // Get next value contained in the enumerator //***************************************** static bool EnumNext( HENUMInternal *phEnum, // [IN] the enumerator to retrieve information mdToken *ptk); // [OUT] token to scope the search __checkReturn static HRESULT GetCount( HENUMInternal *phEnum, // [IN] the enumerator to retrieve information ULONG *pCount); // ]OUT] the index of the desired item __checkReturn static HRESULT GetElement( HENUMInternal *phEnum, // [IN] the enumerator to retrieve information ULONG ix, // ]IN] the index of the desired item mdToken *ptk); // [OUT] token to fill }; //***************************************** // Default Value for field, param or property. Returned by GetDefaultValue //***************************************** typedef struct _MDDefaultValue { #if BIGENDIAN _MDDefaultValue(void) { m_bType = ELEMENT_TYPE_END; } ~_MDDefaultValue(void) { if (m_bType == ELEMENT_TYPE_STRING) { delete[] m_wzValue; } } #endif // type of default value BYTE m_bType; // CorElementType for the default value // the default value union { BOOL m_bValue; // ELEMENT_TYPE_BOOLEAN CHAR m_cValue; // ELEMENT_TYPE_I1 BYTE m_byteValue; // ELEMENT_TYPE_UI1 SHORT m_sValue; // ELEMENT_TYPE_I2 USHORT m_usValue; // ELEMENT_TYPE_UI2 LONG m_lValue; // ELEMENT_TYPE_I4 ULONG m_ulValue; // ELEMENT_TYPE_UI4 LONGLONG m_llValue; // ELEMENT_TYPE_I8 ULONGLONG m_ullValue; // ELEMENT_TYPE_UI8 FLOAT m_fltValue; // ELEMENT_TYPE_R4 DOUBLE m_dblValue; // ELEMENT_TYPE_R8 LPCWSTR m_wzValue; // ELEMENT_TYPE_STRING IUnknown *m_unkValue; // ELEMENT_TYPE_CLASS }; ULONG m_cbSize; // default value size (for blob) } MDDefaultValue; //***************************************** // structure use to in GetAllEventAssociates and GetAllPropertyAssociates //***************************************** typedef struct { mdMethodDef m_memberdef; DWORD m_dwSemantics; } ASSOCIATE_RECORD; // // structure use to retrieve class layout information // typedef struct { RID m_ridFieldCur; // indexing to the field table RID m_ridFieldEnd; // end index to field table } MD_CLASS_LAYOUT; // Structure for describing the Assembly MetaData. typedef struct { USHORT usMajorVersion; // Major Version. USHORT usMinorVersion; // Minor Version. USHORT usBuildNumber; // Build Number. USHORT usRevisionNumber; // Revision Number. LPCSTR szLocale; // Locale. } AssemblyMetaDataInternal; // Callback definition for comparing signatures. // (*PSIGCOMPARE) (BYTE ScopeSignature[], DWORD ScopeSignatureLength, // BYTE ExternalSignature[], DWORD ExternalSignatureLength, // void* SignatureData); typedef BOOL (*PSIGCOMPARE)(PCCOR_SIGNATURE, DWORD, PCCOR_SIGNATURE, DWORD, void*); // {1B119F60-C507-4024-BB39-F8223FB3E1FD} EXTERN_GUID(IID_IMDInternalImport, 0x1b119f60, 0xc507, 0x4024, 0xbb, 0x39, 0xf8, 0x22, 0x3f, 0xb3, 0xe1, 0xfd); #undef INTERFACE #define INTERFACE IMDInternalImport DECLARE_INTERFACE_(IMDInternalImport, IUnknown) { //***************************************************************************** // return the count of entries of a given kind in a scope // For example, pass in mdtMethodDef will tell you how many MethodDef // contained in a scope //***************************************************************************** STDMETHOD_(ULONG, GetCountWithTokenKind)(// return hresult DWORD tkKind) PURE; // [IN] pass in the kind of token. //***************************************************************************** // enumerator for typedef //***************************************************************************** __checkReturn STDMETHOD(EnumTypeDefInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data //***************************************************************************** // enumerator for MethodImpl //***************************************************************************** __checkReturn STDMETHOD(EnumMethodImplInit)( // return hresult mdTypeDef td, // [IN] TypeDef over which to scope the enumeration. HENUMInternal *phEnumBody, // [OUT] buffer to fill for enumerator data for MethodBody tokens. HENUMInternal *phEnumDecl) PURE; // [OUT] buffer to fill for enumerator data for MethodDecl tokens. ULONG EnumMethodImplGetCount( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) // [IN] MethodDecl enumerator. { return phEnumBody->m_ulCount; } STDMETHOD_(void, EnumMethodImplReset)( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. __checkReturn STDMETHOD(EnumMethodImplNext)( // return hresult (S_OK = TRUE, S_FALSE = FALSE or error code) HENUMInternal *phEnumBody, // [IN] input enum for MethodBody HENUMInternal *phEnumDecl, // [IN] input enum for MethodDecl mdToken *ptkBody, // [OUT] return token for MethodBody mdToken *ptkDecl) PURE; // [OUT] return token for MethodDecl STDMETHOD_(void, EnumMethodImplClose)( HENUMInternal *phEnumBody, // [IN] MethodBody enumerator. HENUMInternal *phEnumDecl) PURE; // [IN] MethodDecl enumerator. //***************************************** // Enumerator helpers for memberdef, memberref, interfaceimp, // event, property, exception, param //***************************************** __checkReturn STDMETHOD(EnumGlobalFunctionsInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data __checkReturn STDMETHOD(EnumGlobalFieldsInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data __checkReturn STDMETHOD(EnumInit)( // return S_FALSE if record not found DWORD tkKind, // [IN] which table to work on mdToken tkParent, // [IN] token to scope the search HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill __checkReturn STDMETHOD(EnumAllInit)( // return S_FALSE if record not found DWORD tkKind, // [IN] which table to work on HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill bool EnumNext( HENUMInternal *phEnum, // [IN] the enumerator to retrieve information mdToken *ptk) // [OUT] token to scope the search { _ASSERTE(phEnum && ptk); if (phEnum->u.m_ulCur >= phEnum->u.m_ulEnd) return false; if ( phEnum->m_EnumType == MDSimpleEnum ) { *ptk = phEnum->u.m_ulCur | phEnum->m_tkKind; phEnum->u.m_ulCur++; } else { TOKENLIST *pdalist = (TOKENLIST *)&(phEnum->m_cursor); _ASSERTE( phEnum->m_EnumType == MDDynamicArrayEnum ); *ptk = *( pdalist->Get(phEnum->u.m_ulCur++) ); } return true; } ULONG EnumGetCount( HENUMInternal *phEnum) // [IN] the enumerator to retrieve information { _ASSERTE(phEnum); return phEnum->m_ulCount; } void EnumReset( HENUMInternal *phEnum) // [IN] the enumerator to be reset { _ASSERTE(phEnum); _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum); phEnum->u.m_ulCur = phEnum->u.m_ulStart; } // MDInternalRW::EnumReset void EnumClose( HENUMInternal *phEnum) // [IN] the enumerator to be closed { _ASSERTE( phEnum->m_EnumType == MDSimpleEnum || phEnum->m_EnumType == MDDynamicArrayEnum); if (phEnum->m_EnumType == MDDynamicArrayEnum) HENUMInternal::ClearEnum(phEnum); } //***************************************** // Enumerator helpers for CustomAttribute //***************************************** __checkReturn STDMETHOD(EnumCustomAttributeByNameInit)(// return S_FALSE if record not found mdToken tkParent, // [IN] token to scope the search LPCSTR szName, // [IN] CustomAttribute's name to scope the search HENUMInternal *phEnum) PURE; // [OUT] the enumerator to fill //***************************************** // Nagivator helper to navigate back to the parent token given a token. // For example, given a memberdef token, it will return the containing typedef. // // the mapping is as following: // ---given child type---------parent type // mdMethodDef mdTypeDef // mdFieldDef mdTypeDef // mdInterfaceImpl mdTypeDef // mdParam mdMethodDef // mdProperty mdTypeDef // mdEvent mdTypeDef // //***************************************** __checkReturn STDMETHOD(GetParentToken)( mdToken tkChild, // [IN] given child token mdToken *ptkParent) PURE; // [OUT] returning parent //***************************************** // Custom value helpers //***************************************** __checkReturn STDMETHOD(GetCustomAttributeProps)( // S_OK or error. mdCustomAttribute at, // [IN] The attribute. mdToken *ptkType) PURE; // [OUT] Put attribute type here. __checkReturn STDMETHOD(GetCustomAttributeAsBlob)( mdCustomAttribute cv, // [IN] given custom value token void const **ppBlob, // [OUT] return the pointer to internal blob ULONG *pcbSize) PURE; // [OUT] return the size of the blob // returned void in v1.0/v1.1 __checkReturn STDMETHOD (GetScopeProps)( LPCSTR *pszName, // [OUT] scope name GUID *pmvid) PURE; // [OUT] version id // finding a particular method __checkReturn STDMETHOD(FindMethodDef)( mdTypeDef classdef, // [IN] given typedef LPCSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob mdMethodDef *pmd) PURE; // [OUT] matching memberdef // return a iSeq's param given a MethodDef __checkReturn STDMETHOD(FindParamOfMethod)( // S_OK or error. mdMethodDef md, // [IN] The owning method of the param. ULONG iSeq, // [IN] The sequence # of the param. mdParamDef *pparamdef) PURE; // [OUT] Put ParamDef token here. //***************************************** // // GetName* functions // //***************************************** // return the name and namespace of typedef __checkReturn STDMETHOD(GetNameOfTypeDef)( mdTypeDef classdef, // given classdef LPCSTR *pszname, // return class name(unqualified) LPCSTR *psznamespace) PURE; // return the name space name __checkReturn STDMETHOD(GetIsDualOfTypeDef)( mdTypeDef classdef, // [IN] given classdef. ULONG *pDual) PURE; // [OUT] return dual flag here. __checkReturn STDMETHOD(GetIfaceTypeOfTypeDef)( mdTypeDef classdef, // [IN] given classdef. ULONG *pIface) PURE; // [OUT] 0=dual, 1=vtable, 2=dispinterface // get the name of either methoddef __checkReturn STDMETHOD(GetNameOfMethodDef)( // return the name of the memberdef in UTF8 mdMethodDef md, // given memberdef LPCSTR *pszName) PURE; __checkReturn STDMETHOD(GetNameAndSigOfMethodDef)( mdMethodDef methoddef, // [IN] given memberdef PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob LPCSTR *pszName) PURE; // return the name of a FieldDef __checkReturn STDMETHOD(GetNameOfFieldDef)( mdFieldDef fd, // given memberdef LPCSTR *pszName) PURE; // return the name of typeref __checkReturn STDMETHOD(GetNameOfTypeRef)( mdTypeRef classref, // [IN] given typeref LPCSTR *psznamespace, // [OUT] return typeref name LPCSTR *pszname) PURE; // [OUT] return typeref namespace // return the resolutionscope of typeref __checkReturn STDMETHOD(GetResolutionScopeOfTypeRef)( mdTypeRef classref, // given classref mdToken *ptkResolutionScope) PURE; // Find the type token given the name. __checkReturn STDMETHOD(FindTypeRefByName)( LPCSTR szNamespace, // [IN] Namespace for the TypeRef. LPCSTR szName, // [IN] Name of the TypeRef. mdToken tkResolutionScope, // [IN] Resolution Scope fo the TypeRef. mdTypeRef *ptk) PURE; // [OUT] TypeRef token returned. // return the TypeDef properties // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetTypeDefProps)( mdTypeDef classdef, // given classdef DWORD *pdwAttr, // return flags on class, tdPublic, tdAbstract mdToken *ptkExtends) PURE; // [OUT] Put base class TypeDef/TypeRef here // return the item's guid __checkReturn STDMETHOD(GetItemGuid)( mdToken tkObj, // [IN] given item. CLSID *pGuid) PURE; // [out[ put guid here. // Get enclosing class of the NestedClass. __checkReturn STDMETHOD(GetNestedClassProps)( // S_OK or error mdTypeDef tkNestedClass, // [IN] NestedClass token. mdTypeDef *ptkEnclosingClass) PURE; // [OUT] EnclosingClass token. // Get count of Nested classes given the enclosing class. __checkReturn STDMETHOD(GetCountNestedClasses)( // return count of Nested classes. mdTypeDef tkEnclosingClass, // Enclosing class. ULONG *pcNestedClassesCount) PURE; // Return array of Nested classes given the enclosing class. __checkReturn STDMETHOD(GetNestedClasses)( // Return actual count. mdTypeDef tkEnclosingClass, // [IN] Enclosing class. mdTypeDef *rNestedClasses, // [OUT] Array of nested class tokens. ULONG ulNestedClasses, // [IN] Size of array. ULONG *pcNestedClasses) PURE; // return the ModuleRef properties // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetModuleRefProps)( mdModuleRef mur, // [IN] moduleref token LPCSTR *pszName) PURE; // [OUT] buffer to fill with the moduleref name //***************************************** // // GetSig* functions // //***************************************** __checkReturn STDMETHOD(GetSigOfMethodDef)( mdMethodDef tkMethodDef, // [IN] given MethodDef ULONG * pcbSigBlob, // [OUT] count of bytes in the signature blob PCCOR_SIGNATURE * ppSig) PURE; __checkReturn STDMETHOD(GetSigOfFieldDef)( mdFieldDef tkFieldDef, // [IN] given FieldDef ULONG * pcbSigBlob, // [OUT] count of bytes in the signature blob PCCOR_SIGNATURE * ppSig) PURE; __checkReturn STDMETHOD(GetSigFromToken)( mdToken tk, // FieldDef, MethodDef, Signature or TypeSpec token ULONG * pcbSig, PCCOR_SIGNATURE * ppSig) PURE; //***************************************** // get method property //***************************************** __checkReturn STDMETHOD(GetMethodDefProps)( mdMethodDef md, // The method for which to get props. DWORD *pdwFlags) PURE; //***************************************** // return method implementation information, like RVA and implflags //***************************************** // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetMethodImplProps)( mdToken tk, // [IN] MethodDef ULONG *pulCodeRVA, // [OUT] CodeRVA DWORD *pdwImplFlags) PURE; // [OUT] Impl. Flags //***************************************** // return method implementation information, like RVA and implflags //***************************************** __checkReturn STDMETHOD(GetFieldRVA)( mdFieldDef fd, // [IN] fielddef ULONG *pulCodeRVA) PURE; // [OUT] CodeRVA //***************************************** // get field property //***************************************** __checkReturn STDMETHOD(GetFieldDefProps)( mdFieldDef fd, // [IN] given fielddef DWORD *pdwFlags) PURE; // [OUT] return fdPublic, fdPrive, etc flags //***************************************************************************** // return default value of a token(could be paramdef, fielddef, or property //***************************************************************************** __checkReturn STDMETHOD(GetDefaultValue)( mdToken tk, // [IN] given FieldDef, ParamDef, or Property MDDefaultValue *pDefaultValue) PURE;// [OUT] default value to fill //***************************************** // get dispid of a MethodDef or a FieldDef //***************************************** __checkReturn STDMETHOD(GetDispIdOfMemberDef)( // return hresult mdToken tk, // [IN] given methoddef or fielddef ULONG *pDispid) PURE; // [OUT] Put the dispid here. //***************************************** // return TypeRef/TypeDef given an InterfaceImpl token //***************************************** __checkReturn STDMETHOD(GetTypeOfInterfaceImpl)( // return the TypeRef/typedef token for the interfaceimpl mdInterfaceImpl iiImpl, // given a interfaceimpl mdToken *ptkType) PURE; //***************************************** // look up function for TypeDef //***************************************** __checkReturn STDMETHOD(FindTypeDef)( LPCSTR szNamespace, // [IN] Namespace for the TypeDef. LPCSTR szName, // [IN] Name of the TypeDef. mdToken tkEnclosingClass, // [IN] TypeRef/TypeDef Token for the enclosing class. mdTypeDef *ptypedef) PURE; // [IN] return typedef //***************************************** // return name and sig of a memberref //***************************************** __checkReturn STDMETHOD(GetNameAndSigOfMemberRef)( // return name here mdMemberRef memberref, // given memberref PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to a blob value of CLR signature ULONG *pcbSigBlob, // [OUT] count of bytes in the signature blob LPCSTR *pszName) PURE; //***************************************************************************** // Given memberref, return the parent. It can be TypeRef, ModuleRef, MethodDef //***************************************************************************** __checkReturn STDMETHOD(GetParentOfMemberRef)( mdMemberRef memberref, // given memberref mdToken *ptkParent) PURE; // return the parent token __checkReturn STDMETHOD(GetParamDefProps)( mdParamDef paramdef, // given a paramdef USHORT *pusSequence, // [OUT] slot number for this parameter DWORD *pdwAttr, // [OUT] flags LPCSTR *pszName) PURE; // [OUT] return the name of the parameter __checkReturn STDMETHOD(GetPropertyInfoForMethodDef)( // Result. mdMethodDef md, // [IN] memberdef mdProperty *ppd, // [OUT] put property token here LPCSTR *pName, // [OUT] put pointer to name here ULONG *pSemantic) PURE; // [OUT] put semantic here //***************************************** // class layout/sequence information //***************************************** __checkReturn STDMETHOD(GetClassPackSize)( // return error if class doesn't have packsize mdTypeDef td, // [IN] give typedef ULONG *pdwPackSize) PURE; // [OUT] 1, 2, 4, 8, or 16 __checkReturn STDMETHOD(GetClassTotalSize)( // return error if class doesn't have total size info mdTypeDef td, // [IN] give typedef ULONG *pdwClassSize) PURE; // [OUT] return the total size of the class __checkReturn STDMETHOD(GetClassLayoutInit)( mdTypeDef td, // [IN] give typedef MD_CLASS_LAYOUT *pLayout) PURE; // [OUT] set up the status of query here __checkReturn STDMETHOD(GetClassLayoutNext)( MD_CLASS_LAYOUT *pLayout, // [IN|OUT] set up the status of query here mdFieldDef *pfd, // [OUT] return the fielddef ULONG *pulOffset) PURE; // [OUT] return the offset/ulSequence associate with it //***************************************** // marshal information of a field //***************************************** __checkReturn STDMETHOD(GetFieldMarshal)( // return error if no native type associate with the token mdFieldDef fd, // [IN] given fielddef PCCOR_SIGNATURE *pSigNativeType, // [OUT] the native type signature ULONG *pcbNativeType) PURE; // [OUT] the count of bytes of *ppvNativeType //***************************************** // property APIs //***************************************** // find a property by name __checkReturn STDMETHOD(FindProperty)( mdTypeDef td, // [IN] given a typdef LPCSTR szPropName, // [IN] property name mdProperty *pProp) PURE; // [OUT] return property token // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetPropertyProps)( mdProperty prop, // [IN] property token LPCSTR *szProperty, // [OUT] property name DWORD *pdwPropFlags, // [OUT] property flags. PCCOR_SIGNATURE *ppvSig, // [OUT] property type. pointing to meta data internal blob ULONG *pcbSig) PURE; // [OUT] count of bytes in *ppvSig //********************************** // Event APIs //********************************** __checkReturn STDMETHOD(FindEvent)( mdTypeDef td, // [IN] given a typdef LPCSTR szEventName, // [IN] event name mdEvent *pEvent) PURE; // [OUT] return event token // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetEventProps)( mdEvent ev, // [IN] event token LPCSTR *pszEvent, // [OUT] Event name DWORD *pdwEventFlags, // [OUT] Event flags. mdToken *ptkEventType) PURE; // [OUT] EventType class //********************************** // find a particular associate of a property or an event //********************************** __checkReturn STDMETHOD(FindAssociate)( mdToken evprop, // [IN] given a property or event token DWORD associate, // [IN] given a associate semantics(setter, getter, testdefault, reset, AddOn, RemoveOn, Fire) mdMethodDef *pmd) PURE; // [OUT] return method def token // Note, void function in v1.0/v1.1 __checkReturn STDMETHOD(EnumAssociateInit)( mdToken evprop, // [IN] given a property or an event token HENUMInternal *phEnum) PURE; // [OUT] cursor to hold the query result // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetAllAssociates)( HENUMInternal *phEnum, // [IN] query result form GetPropertyAssociateCounts ASSOCIATE_RECORD *pAssociateRec, // [OUT] struct to fill for output ULONG cAssociateRec) PURE; // [IN] size of the buffer //********************************** // Get info about a PermissionSet. //********************************** // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetPermissionSetProps)( mdPermission pm, // [IN] the permission token. DWORD *pdwAction, // [OUT] CorDeclSecurity. void const **ppvPermission, // [OUT] permission blob. ULONG *pcbPermission) PURE; // [OUT] count of bytes of pvPermission. //**************************************** // Get the String given the String token. // Returns a pointer to the string, or NULL in case of error. //**************************************** __checkReturn STDMETHOD(GetUserString)( mdString stk, // [IN] the string token. ULONG *pchString, // [OUT] count of characters in the string. BOOL *pbIs80Plus, // [OUT] specifies where there are extended characters >= 0x80. LPCWSTR *pwszUserString) PURE; //***************************************************************************** // p-invoke APIs. //***************************************************************************** __checkReturn STDMETHOD(GetPinvokeMap)( mdToken tk, // [IN] FieldDef, MethodDef. DWORD *pdwMappingFlags, // [OUT] Flags used for mapping. LPCSTR *pszImportName, // [OUT] Import name. mdModuleRef *pmrImportDLL) PURE; // [OUT] ModuleRef token for the target DLL. //***************************************************************************** // helpers to convert a text signature to a com format //***************************************************************************** __checkReturn STDMETHOD(ConvertTextSigToComSig)( // Return hresult. BOOL fCreateTrIfNotFound, // [IN] create typeref if not found LPCSTR pSignature, // [IN] class file format signature CQuickBytes *pqbNewSig, // [OUT] place holder for CLR signature ULONG *pcbCount) PURE; // [OUT] the result size of signature //***************************************************************************** // Assembly MetaData APIs. //***************************************************************************** // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetAssemblyProps)( mdAssembly mda, // [IN] The Assembly for which to get the properties. const void **ppbPublicKey, // [OUT] Pointer to the public key. ULONG *pcbPublicKey, // [OUT] Count of bytes in the public key. ULONG *pulHashAlgId, // [OUT] Hash Algorithm. LPCSTR *pszName, // [OUT] Buffer to fill with name. AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. DWORD *pdwAssemblyFlags) PURE;// [OUT] Flags. // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetAssemblyRefProps)( mdAssemblyRef mdar, // [IN] The AssemblyRef for which to get the properties. const void **ppbPublicKeyOrToken, // [OUT] Pointer to the public key or token. ULONG *pcbPublicKeyOrToken, // [OUT] Count of bytes in the public key or token. LPCSTR *pszName, // [OUT] Buffer to fill with name. AssemblyMetaDataInternal *pMetaData,// [OUT] Assembly MetaData. const void **ppbHashValue, // [OUT] Hash blob. ULONG *pcbHashValue, // [OUT] Count of bytes in the hash blob. DWORD *pdwAssemblyRefFlags) PURE; // [OUT] Flags. // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetFileProps)( mdFile mdf, // [IN] The File for which to get the properties. LPCSTR *pszName, // [OUT] Buffer to fill with name. const void **ppbHashValue, // [OUT] Pointer to the Hash Value Blob. ULONG *pcbHashValue, // [OUT] Count of bytes in the Hash Value Blob. DWORD *pdwFileFlags) PURE; // [OUT] Flags. // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetExportedTypeProps)( mdExportedType mdct, // [IN] The ExportedType for which to get the properties. LPCSTR *pszNamespace, // [OUT] Namespace. LPCSTR *pszName, // [OUT] Name. mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. mdTypeDef *ptkTypeDef, // [OUT] TypeDef token within the file. DWORD *pdwExportedTypeFlags) PURE; // [OUT] Flags. // returned void in v1.0/v1.1 __checkReturn STDMETHOD(GetManifestResourceProps)( mdManifestResource mdmr, // [IN] The ManifestResource for which to get the properties. LPCSTR *pszName, // [OUT] Buffer to fill with name. mdToken *ptkImplementation, // [OUT] mdFile or mdAssemblyRef that provides the ExportedType. DWORD *pdwOffset, // [OUT] Offset to the beginning of the resource within the file. DWORD *pdwResourceFlags) PURE;// [OUT] Flags. __checkReturn STDMETHOD(FindExportedTypeByName)( // S_OK or error LPCSTR szNamespace, // [IN] Namespace of the ExportedType. LPCSTR szName, // [IN] Name of the ExportedType. mdExportedType tkEnclosingType, // [IN] ExportedType for the enclosing class. mdExportedType *pmct) PURE; // [OUT] Put ExportedType token here. __checkReturn STDMETHOD(FindManifestResourceByName)( // S_OK or error LPCSTR szName, // [IN] Name of the ManifestResource. mdManifestResource *pmmr) PURE; // [OUT] Put ManifestResource token here. __checkReturn STDMETHOD(GetAssemblyFromScope)( // S_OK or error mdAssembly *ptkAssembly) PURE; // [OUT] Put token here. __checkReturn STDMETHOD(GetCustomAttributeByName)( // S_OK or error mdToken tkObj, // [IN] Object with Custom Attribute. LPCUTF8 szName, // [IN] Name of desired Custom Attribute. const void **ppData, // [OUT] Put pointer to data here. ULONG *pcbData) PURE; // [OUT] Put size of data here. // Note: The return type of this method was void in v1 __checkReturn STDMETHOD(GetTypeSpecFromToken)( // S_OK or error. mdTypeSpec typespec, // [IN] Signature token. PCCOR_SIGNATURE *ppvSig, // [OUT] return pointer to token. ULONG *pcbSig) PURE; // [OUT] return size of signature. __checkReturn STDMETHOD(SetUserContextData)( // S_OK or E_NOTIMPL IUnknown *pIUnk) PURE; // The user context. __checkReturn STDMETHOD_(BOOL, IsValidToken)( // True or False. mdToken tk) PURE; // [IN] Given token. __checkReturn STDMETHOD(TranslateSigWithScope)( IMDInternalImport *pAssemImport, // [IN] import assembly scope. const void *pbHashValue, // [IN] hash value for the import assembly. ULONG cbHashValue, // [IN] count of bytes in the hash value. PCCOR_SIGNATURE pbSigBlob, // [IN] signature in the importing scope ULONG cbSigBlob, // [IN] count of bytes of signature IMetaDataAssemblyEmit *pAssemEmit, // [IN] assembly emit scope. IMetaDataEmit *emit, // [IN] emit interface CQuickBytes *pqkSigEmit, // [OUT] buffer to hold translated signature ULONG *pcbSig) PURE; // [OUT] count of bytes in the translated signature STDMETHOD_(IMetaModelCommon*, GetMetaModelCommon)( // Return MetaModelCommon interface. ) PURE; STDMETHOD_(IUnknown *, GetCachedPublicInterface)(BOOL fWithLock) PURE; // return the cached public interface __checkReturn STDMETHOD(SetCachedPublicInterface)(IUnknown *pUnk) PURE; // no return value STDMETHOD_(UTSemReadWrite*, GetReaderWriterLock)() PURE; // return the reader writer lock __checkReturn STDMETHOD(SetReaderWriterLock)(UTSemReadWrite * pSem) PURE; STDMETHOD_(mdModule, GetModuleFromScope)() PURE; // [OUT] Put mdModule token here. //----------------------------------------------------------------- // Additional custom methods // finding a particular method __checkReturn STDMETHOD(FindMethodDefUsingCompare)( mdTypeDef classdef, // [IN] given typedef LPCSTR szName, // [IN] member name PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob value of CLR signature ULONG cbSigBlob, // [IN] count of bytes in the signature blob PSIGCOMPARE pSignatureCompare, // [IN] Routine to compare signatures void* pSignatureArgs, // [IN] Additional info to supply the compare function mdMethodDef *pmd) PURE; // [OUT] matching memberdef // Additional v2 methods. //***************************************** // return a field offset for a given field //***************************************** __checkReturn STDMETHOD(GetFieldOffset)( mdFieldDef fd, // [IN] fielddef ULONG *pulOffset) PURE; // [OUT] FieldOffset __checkReturn STDMETHOD(GetMethodSpecProps)( mdMethodSpec ms, // [IN] The method instantiation mdToken *tkParent, // [OUT] MethodDef or MemberRef PCCOR_SIGNATURE *ppvSigBlob, // [OUT] point to the blob value of meta data ULONG *pcbSigBlob) PURE; // [OUT] actual size of signature blob __checkReturn STDMETHOD(GetTableInfoWithIndex)( ULONG index, // [IN] pass in the table index void **pTable, // [OUT] pointer to table at index void **pTableSize) PURE; // [OUT] size of table at index __checkReturn STDMETHOD(ApplyEditAndContinue)( void *pDeltaMD, // [IN] the delta metadata ULONG cbDeltaMD, // [IN] length of pData IMDInternalImport **ppv) PURE; // [OUT] the resulting metadata interface //********************************** // Generics APIs //********************************** __checkReturn STDMETHOD(GetGenericParamProps)( // S_OK or error. mdGenericParam rd, // [IN] The type parameter ULONG* pulSequence, // [OUT] Parameter sequence number DWORD* pdwAttr, // [OUT] Type parameter flags (for future use) mdToken *ptOwner, // [OUT] The owner (TypeDef or MethodDef) DWORD *reserved, // [OUT] The kind (TypeDef/Ref/Spec, for future use) LPCSTR *szName) PURE; // [OUT] The name __checkReturn STDMETHOD(GetGenericParamConstraintProps)( // S_OK or error. mdGenericParamConstraint rd, // [IN] The constraint token mdGenericParam *ptGenericParam, // [OUT] GenericParam that is constrained mdToken *ptkConstraintType) PURE; // [OUT] TypeDef/Ref/Spec constraint //***************************************************************************** // This function gets the "built for" version of a metadata scope. // NOTE: if the scope has never been saved, it will not have a built-for // version, and an empty string will be returned. //***************************************************************************** __checkReturn STDMETHOD(GetVersionString)( // S_OK or error. LPCSTR *pVer) PURE; // [OUT] Put version string here. __checkReturn STDMETHOD(GetTypeDefRefTokenInTypeSpec)(// return S_FALSE if enclosing type does not have a token mdTypeSpec tkTypeSpec, // [IN] TypeSpec token to look at mdToken *tkEnclosedToken) PURE; // [OUT] The enclosed type token #define MD_STREAM_VER_1X 0x10000 #define MD_STREAM_VER_2_B1 0x10001 #define MD_STREAM_VER_2 0x20000 STDMETHOD_(DWORD, GetMetadataStreamVersion)() PURE; //returns DWORD with major version of // MD stream in senior word and minor version--in junior word __checkReturn STDMETHOD(GetNameOfCustomAttribute)(// S_OK or error mdCustomAttribute mdAttribute, // [IN] The Custom Attribute LPCUTF8 *pszNamespace, // [OUT] Namespace of Custom Attribute. LPCUTF8 *pszName) PURE; // [OUT] Name of Custom Attribute. STDMETHOD(SetOptimizeAccessForSpeed)(// S_OK or error BOOL fOptSpeed) PURE; STDMETHOD(SetVerifiedByTrustedSource)(// S_OK or error BOOL fVerified) PURE; STDMETHOD(GetRvaOffsetData)( DWORD *pFirstMethodRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in MethodDef table. DWORD *pMethodDefRecordSize, // [OUT] Size of each record in MethodDef table. DWORD *pMethodDefCount, // [OUT] Number of records in MethodDef table. DWORD *pFirstFieldRvaOffset, // [OUT] Offset (from start of metadata) to the first RVA field in FieldRVA table. DWORD *pFieldRvaRecordSize, // [OUT] Size of each record in FieldRVA table. DWORD *pFieldRvaCount // [OUT] Number of records in FieldRVA table. ) PURE; //---------------------------------------------------------------------------------------- // !!! READ THIS !!! // // New methods have to be added at the end. The order and signatures of the existing methods // have to be preserved. We need to maintain a backward compatibility for this interface to // allow ildasm to work on SingleCLR. // //---------------------------------------------------------------------------------------- }; // IMDInternalImport // {E03D7730-D7E3-11d2-8C0D-00C04FF7431A} EXTERN_GUID(IID_IMDInternalImportENC, 0xe03d7730, 0xd7e3, 0x11d2, 0x8c, 0xd, 0x0, 0xc0, 0x4f, 0xf7, 0x43, 0x1a); #undef INTERFACE #define INTERFACE IMDInternalImportENC DECLARE_INTERFACE_(IMDInternalImportENC, IMDInternalImport) { private: using IMDInternalImport::ApplyEditAndContinue; public: // ENC only methods here. STDMETHOD(ApplyEditAndContinue)( // S_OK or error. MDInternalRW *pDelta) PURE; // Interface to MD with the ENC delta. STDMETHOD(EnumDeltaTokensInit)( // return hresult HENUMInternal *phEnum) PURE; // [OUT] buffer to fill for enumerator data }; // IMDInternalImportENC // {F102C526-38CB-49ed-9B5F-498816AE36E0} EXTERN_GUID(IID_IMDInternalEmit, 0xf102c526, 0x38cb, 0x49ed, 0x9b, 0x5f, 0x49, 0x88, 0x16, 0xae, 0x36, 0xe0); #undef INTERFACE #define INTERFACE IMDInternalEmit DECLARE_INTERFACE_(IMDInternalEmit, IUnknown) { STDMETHOD(ChangeMvid)( // S_OK or error. REFGUID newMvid) PURE; // GUID to use as the MVID STDMETHOD(SetMDUpdateMode)( ULONG updateMode, ULONG *pPreviousUpdateMode) PURE; }; // IMDInternalEmit #ifdef FEATURE_METADATA_CUSTOM_DATA_SOURCE struct IMDCustomDataSource; class CMiniMdSchema; struct CMiniTableDef; namespace MetaData { class DataBlob; } // {CC0C8F7A-A00B-493D-80B6-CE0C92491670} EXTERN_GUID(IID_IMDCustomDataSource, 0xcc0c8f7a, 0xa00b, 0x493d, 0x80, 0xb6, 0xce, 0xc, 0x92, 0x49, 0x16, 0x70); #undef INTERFACE #define INTERFACE IMDCustomDataSource DECLARE_INTERFACE_(IMDCustomDataSource, IUnknown) { STDMETHOD(GetSchema)(CMiniMdSchema* pSchema) PURE; STDMETHOD(GetTableDef)(ULONG32 tableIndex, CMiniTableDef* pTableDef) PURE; STDMETHOD(GetBlobHeap)(MetaData::DataBlob* pBlobHeapData) PURE; STDMETHOD(GetGuidHeap)(MetaData::DataBlob* pGuidHeapData) PURE; STDMETHOD(GetStringHeap)(MetaData::DataBlob* pStringHeapData) PURE; STDMETHOD(GetUserStringHeap)(MetaData::DataBlob* pUserStringHeapData) PURE; STDMETHOD(GetTableRecords)(ULONG32 tableIndex, MetaData::DataBlob* pTableRecordData) PURE; STDMETHOD(GetTableSortable)(ULONG32 tableIndex, BOOL* pSortable) PURE; STDMETHOD(GetStorageSignature)(MetaData::DataBlob* pStorageSignature) PURE; }; // IMDCustomDataSource // {503F79FB-7AAE-4364-BDA6-8E235D173AEC} EXTERN_GUID(IID_IMetaDataDispenserCustom, 0x503f79fb, 0x7aae, 0x4364, 0xbd, 0xa6, 0x8e, 0x23, 0x5d, 0x17, 0x3a, 0xec); #undef INTERFACE #define INTERFACE IMetaDataDispenserCustom DECLARE_INTERFACE_(IMetaDataDispenserCustom, IUnknown) { STDMETHOD(OpenScopeOnCustomDataSource)( // Return code. IMDCustomDataSource *pCustomSource, // [in] The scope to open. DWORD dwOpenFlags, // [in] Open mode flags. REFIID riid, // [in] The interface desired. IUnknown **ppIUnk) PURE; // [out] Return interface on success. }; // IMetaDataDispenserCustom #endif // FEATURE_METADATA_CUSTOM_DATA_SOURCE #ifdef FEATURE_METADATA_DEBUGGEE_DATA_SOURCE struct ICorDebugDataTarget; HRESULT CreateRemoteMDInternalRWSource(TADDR mdInternalRWRemoteAddress, ICorDebugDataTarget* pDataTarget, DWORD defines, DWORD dataStructureVersion, IMDCustomDataSource** ppDataSource); #endif enum MetaDataReorderingOptions { NoReordering=0x0, ReArrangeStringPool=0x1 }; #ifdef __HOLDER_H_ void DECLSPEC_NORETURN ThrowHR(HRESULT hr); // This wrapper class ensures that the HENUMInternal is EnumClose'd no matter how the scope is exited. class HENUMTypeDefInternalHolder { public: FORCEINLINE HENUMTypeDefInternalHolder(IMDInternalImport *pInternalImport) { WRAPPER_NO_CONTRACT; m_pInternalImport = pInternalImport; m_fAcquired = FALSE; } FORCEINLINE VOID EnumTypeDefInit() { CONTRACTL { THROWS; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumTypeDefInit(&m_hEnum); if (FAILED(hr)) { ThrowHR(hr); } m_fAcquired = TRUE; } FORCEINLINE HRESULT EnumTypeDefInitNoThrow() { WRAPPER_NO_CONTRACT; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumTypeDefInit(&m_hEnum); if (FAILED(hr)) { return hr; } m_fAcquired = TRUE; return hr; } FORCEINLINE ~HENUMTypeDefInternalHolder() { WRAPPER_NO_CONTRACT; if (m_fAcquired) { m_pInternalImport->EnumClose(&m_hEnum); } } FORCEINLINE HENUMInternal* operator& () { LIMITED_METHOD_CONTRACT; _ASSERTE(m_fAcquired); return &m_hEnum; } private: FORCEINLINE HENUMTypeDefInternalHolder(const HENUMTypeDefInternalHolder &) { LIMITED_METHOD_CONTRACT; _ASSERTE(!"Don't try to assign this class."); } private: IMDInternalImport *m_pInternalImport; HENUMInternal m_hEnum; BOOL m_fAcquired; }; // This wrapper class ensures that the HENUMInternal is EnumClose'd no matter how the scope is exited. class HENUMInternalHolder { public: FORCEINLINE HENUMInternalHolder(IMDInternalImport *pInternalImport) { WRAPPER_NO_CONTRACT; m_pInternalImport = pInternalImport; m_fAcquired = FALSE; } FORCEINLINE VOID EnumGlobalFunctionsInit() { CONTRACTL { THROWS; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumGlobalFunctionsInit(&m_hEnum); if (FAILED(hr)) { ThrowHR(hr); } m_fAcquired = TRUE; } FORCEINLINE VOID EnumGlobalFieldsInit() { CONTRACTL { THROWS; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumGlobalFieldsInit(&m_hEnum); if (FAILED(hr)) { ThrowHR(hr); } m_fAcquired = TRUE; } FORCEINLINE VOID EnumTypeDefInit() { CONTRACTL { THROWS; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumTypeDefInit(&m_hEnum); if (FAILED(hr)) { ThrowHR(hr); } m_fAcquired = TRUE; } FORCEINLINE VOID EnumAssociateInit(mdToken tkParent) // [IN] token to scope the search { CONTRACTL { THROWS; } CONTRACTL_END; _ASSERTE(!m_fAcquired); IfFailThrow(m_pInternalImport->EnumAssociateInit(tkParent, &m_hEnum)); m_fAcquired = TRUE; } FORCEINLINE VOID EnumInit(DWORD tkKind, // [IN] which table to work on mdToken tkParent // [IN] token to scope the search ) { CONTRACTL { THROWS; } CONTRACTL_END; HRESULT hr = EnumInitNoThrow(tkKind, tkParent); if (FAILED(hr)) { ThrowHR(hr); } } __checkReturn FORCEINLINE HRESULT EnumInitNoThrow(DWORD tkKind, // [IN] which table to work on mdToken tkParent // [IN] token to scope the search ) { CONTRACTL { NOTHROW; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumInit(tkKind, tkParent, &m_hEnum); if (SUCCEEDED(hr)) { m_fAcquired = TRUE; } return hr; } FORCEINLINE VOID EnumAllInit(DWORD tkKind // [IN] which table to work on ) { CONTRACTL { THROWS; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumAllInit(tkKind, &m_hEnum); if (FAILED(hr)) { ThrowHR(hr); } m_fAcquired = TRUE; } FORCEINLINE ULONG EnumGetCount() { CONTRACTL { NOTHROW; GC_NOTRIGGER; CONSISTENCY_CHECK(m_fAcquired); } CONTRACTL_END; return m_pInternalImport->EnumGetCount(&m_hEnum); } FORCEINLINE bool EnumNext(mdToken * pTok) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CONSISTENCY_CHECK(m_fAcquired); } CONTRACTL_END; return m_pInternalImport->EnumNext(&m_hEnum, pTok); } FORCEINLINE void EnumReset() { CONTRACTL { NOTHROW; GC_NOTRIGGER; CONSISTENCY_CHECK(m_fAcquired); } CONTRACTL_END; return m_pInternalImport->EnumReset(&m_hEnum); } FORCEINLINE ~HENUMInternalHolder() { WRAPPER_NO_CONTRACT; if (m_fAcquired) { // Ignore the error (void)m_pInternalImport->EnumClose(&m_hEnum); } } FORCEINLINE HENUMInternal* operator& () { LIMITED_METHOD_CONTRACT; _ASSERTE(m_fAcquired); return &m_hEnum; } private: FORCEINLINE HENUMInternalHolder(const HENUMInternalHolder &) { WRAPPER_NO_CONTRACT; _ASSERTE(!"Don't try to assign this class."); } protected: IMDInternalImport *m_pInternalImport; HENUMInternal m_hEnum; BOOL m_fAcquired; }; class HENUMInternalMethodImplHolder : protected HENUMInternalHolder { public: FORCEINLINE HENUMInternalMethodImplHolder(IMDInternalImport *pInternalImport) : HENUMInternalHolder(pInternalImport) { WRAPPER_NO_CONTRACT; } FORCEINLINE ~HENUMInternalMethodImplHolder() { WRAPPER_NO_CONTRACT; if (m_fAcquired) { // Ignore the error (void)m_pInternalImport->EnumClose(&m_hEnum2); } } FORCEINLINE void EnumMethodImplInit(mdToken tkParent // [IN] token to scope the search ) { CONTRACTL { THROWS; } CONTRACTL_END; HRESULT hr = EnumMethodImplInitNoThrow(tkParent); if (FAILED(hr)) { ThrowHR(hr); } } __checkReturn FORCEINLINE HRESULT EnumMethodImplInitNoThrow(mdToken tkParent // [IN] token to scope the search ) { CONTRACTL { NOTHROW; } CONTRACTL_END; _ASSERTE(!m_fAcquired); HRESULT hr = m_pInternalImport->EnumMethodImplInit(tkParent, &m_hEnum, &m_hEnum2); if (SUCCEEDED(hr)) { m_fAcquired = TRUE; } return hr; } __checkReturn FORCEINLINE HRESULT EnumMethodImplNext( mdToken *ptkImpl, mdToken *ptkDecl) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CONSISTENCY_CHECK(m_fAcquired); } CONTRACTL_END; return m_pInternalImport->EnumMethodImplNext(&m_hEnum, &m_hEnum2, ptkImpl, ptkDecl); } FORCEINLINE ULONG EnumMethodImplGetCount() { CONTRACTL { NOTHROW; GC_NOTRIGGER; CONSISTENCY_CHECK(m_fAcquired); } CONTRACTL_END; return m_pInternalImport->EnumMethodImplGetCount(&m_hEnum, &m_hEnum2); } protected: HENUMInternal m_hEnum2; }; #endif //__HOLDER_H_ #endif // _METADATA_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/metadataexports.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // MDCommon.h // // // Header for functions exported by metadata. These are consumed 2 ways: // 1. Mscoree provides public exports that plumb to some of these functions to invoke these dynamically. // 2. Standalone metadata (statically linked) // //***************************************************************************** #ifndef _METADATA_EXPORTS_ #define _METADATA_EXPORTS_ // General creation function for ClassFactory semantics. STDAPI MetaDataDllGetClassObject(REFCLSID rclsid, REFIID riid, void ** ppv); // Specific creation function to get IMetaDataDispenser(Ex) interface. HRESULT InternalCreateMetaDataDispenser(REFIID riid, void ** pMetaDataDispenserOut); STDAPI GetMDInternalInterface( LPVOID pData, ULONG cbData, DWORD flags, // [IN] MDInternal_OpenForRead or MDInternal_OpenForENC REFIID riid, // [in] The interface desired. void **ppIUnk); // [out] Return interface on success. STDAPI GetMDInternalInterfaceFromPublic( IUnknown *pIUnkPublic, // [IN] Given scope. REFIID riid, // [in] The interface desired. void **ppIUnkInternal); // [out] Return interface on success. STDAPI GetMDPublicInterfaceFromInternal( void *pIUnkPublic, // [IN] Given scope. REFIID riid, // [in] The interface desired. void **ppIUnkInternal); // [out] Return interface on success. STDAPI MDReOpenMetaDataWithMemory( void *pImport, // [IN] Given scope. public interfaces LPCVOID pData, // [in] Location of scope data. ULONG cbData); // [in] Size of the data pointed to by pData. STDAPI MDReOpenMetaDataWithMemoryEx( void *pImport, // [IN] Given scope. public interfaces LPCVOID pData, // [in] Location of scope data. ULONG cbData, // [in] Size of the data pointed to by pData. DWORD dwReOpenFlags); // [in] ReOpen flags #endif // _METADATA_EXPORTS_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/metahost.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /************************************************************************************** ** Motivation for redesigning the shim APIs: ** ** - old APIs assume that there is only one runtime in the process ** ** - old APIs are redundant (multiple ways for achieving the same effect) ** ** - old APIs are flat and difficult to version (*Ex variants etc.) ** ** - old APIs mix together totally different concepts - choosing a runtime vs. ** ** activating the runtime vs. performing an operation on the activated runtime ** ** - old APIs are poorly named (incosistent use of the Cor* prefix etc.) ** ** - all in all there's a lot of legacy behavior in the old APIs that it makes ** ** sense to start from scratch ** ** ** ** Design goals: ** ** - clear separation between the no-policy base part and the policy-decision- ** ** making part ** ** - easy to extend with additional functionality by introducing new versions of ** ** the interfaces (interface types are not hardcoded in method signatures) ** ** - functions performing clearly defined steps rather than poorly documented ** ** heavy-weight black boxes ** **************************************************************************************/ /************************************************************************************** ** Interfaces described in this IDL file follow the "Nano-COM" model. Basically ** ** lifetime management (AddRef/Release) and encapsulation (implicit context) are ** ** used from COM. There are no COM types (BSTR, SAFEARRAY, VARIANT), apartment ** ** models, aggregation, or registry activation (CoCreateInstance). ** **************************************************************************************/ import "unknwn.idl"; import "oaidl.idl"; import "ocidl.idl"; import "mscoree.idl"; cpp_quote("#include ") cpp_quote("STDAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, /*iid_is(riid)*/ LPVOID *ppInterface);") // IID ICLRMetaHost : uuid(D332DB9E-B9B3-4125-8207-A14884F53216) cpp_quote("EXTERN_GUID(IID_ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16);") // CLSID_CLRMetaHost : uuid(9280188D-0E8E-4867-B30C-7FA83884E8DE) cpp_quote("EXTERN_GUID(CLSID_CLRMetaHost, 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde);") // IID ICLRDebugging : uuid(D28F3C5A-9634-4206-A509-477552EEFB10) cpp_quote("EXTERN_GUID(IID_ICLRDebugging, 0xd28f3c5a, 0x9634, 0x4206, 0xa5, 0x9, 0x47, 0x75, 0x52, 0xee, 0xfb, 0x10);") // CLSID_CLRDebugging : uuid(BACC578D-FBDD-48a4-969F-02D932B74634) cpp_quote("EXTERN_GUID(CLSID_CLRDebugging, 0xbacc578d, 0xfbdd, 0x48a4, 0x96, 0x9f, 0x2, 0xd9, 0x32, 0xb7, 0x46, 0x34);") // IID ICLRRuntimeInfo : uuid(BD39D1D2-BA2F-486a-89B0-B4B0CB466891) cpp_quote("EXTERN_GUID(IID_ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91);") // IID ICLRDebuggingLibraryProvider interface : uuid{3151C08D-4D09-4f9b-8838-2880BF18FE51} cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51);") // IID ICLRDebuggingLibraryProvider2 interface : uuid{E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA} cpp_quote("EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA);") // For use in ICLRMetaHost::RequestRuntimeLoadedNotification interface ICLRRuntimeInfo; typedef HRESULT (__stdcall *CallbackThreadSetFnPtr)(); typedef HRESULT (__stdcall *CallbackThreadUnsetFnPtr)(); typedef void (__stdcall *RuntimeLoadedCallbackFnPtr)( ICLRRuntimeInfo *pRuntimeInfo, CallbackThreadSetFnPtr pfnCallbackThreadSet, CallbackThreadUnsetFnPtr pfnCallbackThreadUnset); /************************************************************************************** ** ICLRMetaHost ** ** Activated using mscoree!CLRCreateInstance. Does not do any policy decisions, get ** ** ICLRMetaHostPolicy if you need that. ** **************************************************************************************/ [ uuid(D332DB9E-B9B3-4125-8207-A14884F53216), version(1.0), helpstring("CLR meta hosting interface"), local ] interface ICLRMetaHost : IUnknown { /********************************************************************************** ** Returns installed runtime with the specific version. Fails if not found. ** ** NULL or any other wildcard is not accepted as pwzVersion ** ** Supersedes: CorBindToRuntimeEx with STARTUP_LOADER_SAFEMODE ** **********************************************************************************/ HRESULT GetRuntime( [in] LPCWSTR pwzVersion, [in] REFIID riid, // IID_ICLRRuntimeInfo [out, iid_is(riid), retval] LPVOID *ppRuntime); /********************************************************************************** ** Returns runtime version burned into a file's metadata. ** ** Supersedes: GetFileVersion ** **********************************************************************************/ HRESULT GetVersionFromFile( [in] LPCWSTR pwzFilePath, [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer); /********************************************************************************** ** Returns an enumerator of runtimes installed on the machine. ** ** Supersedes: (none) ** **********************************************************************************/ HRESULT EnumerateInstalledRuntimes( [out, retval] IEnumUnknown **ppEnumerator); /********************************************************************************** ** Provides an enumerator of runtimes loaded into the given process. ** ** Supersedes: GetVersionFromProcess ** **********************************************************************************/ HRESULT EnumerateLoadedRuntimes( [in] HANDLE hndProcess, [out, retval] IEnumUnknown **ppEnumerator); /********************************************************************************** ** Provides a callback when a new runtime version has just been loaded, but not ** ** started. ** ** ** ** The callback works in the following way: ** ** - the callback is invoked only when a runtime is loaded for the first time ** ** - the callback will not be invoked for reentrant loads of the same runtime ** ** - the callback will be for reentrant loads of other runtimes ** ** - it is guaranteed that no other thread may load the runtime until the ** ** callback returns; any thread that does so blocks until this time. ** ** - for non-reentrant multi-threaded runtime loads, callbacks are serialized ** ** - if the host intends to load (or cause to be loaded) another runtime in a ** ** reentrant fashion, or intends to perform any operations on the runtime ** ** corresponding to the callback instance, the pfnCallbackThreadSet and ** ** pfnCallbackThreadUnset arguments provided in the callback must be used ** ** in the following way: ** ** - pfnCallbackThreadSet must be called by the thread that might cause a ** ** runtime load before such a load is attempted ** ** - pfnCallbackThreadUnset must be called when the thread will no longer ** ** cause such a runtime load (and before returning from the initial ** ** callback) ** ** - pfnCallbackThreadSet and pfnCallbackThreadUnset are non-reentrant. ** ** ** ** pCallbackFunction: This function is invoked when a new runtime has just ** ** been loaded. A value of NULL results in a failure ** ** return value of E_POINTER. ** ** ** ** Supersedes: LockClrVersion ** **********************************************************************************/ HRESULT RequestRuntimeLoadedNotification( [in] RuntimeLoadedCallbackFnPtr pCallbackFunction); /********************************************************************************** ** Returns interface representing the runtime to which the legacy activation ** ** policy has been bound (for example, by a useLegacyV2RuntimeActivationPolicy ** ** config entry or by a call to ICLRRuntimeInfo::BindAsLegacyV2Runtime). ** **********************************************************************************/ HRESULT QueryLegacyV2RuntimeBinding( [in] REFIID riid, [out, iid_is(riid), retval] LPVOID *ppUnk); /********************************************************************************** ** Shuts down the current process. ** ** Supersedes: CorExitProcess ** **********************************************************************************/ HRESULT ExitProcess( [in] INT32 iExitCode); } // interface ICLRMetaHost /************************************************************************************* ** This structure defines the version of a CLR for debugging purposes. ** ** The wStructVersion field allows for future revisions to this structure to be ** ** made. Currently it must be set to 0. The remaining fields represent the ** ** typical major.minor.build.revision product version information. ** *************************************************************************************/ typedef struct _CLR_DEBUGGING_VERSION { WORD wStructVersion; WORD wMajor; WORD wMinor; WORD wBuild; WORD wRevision; } CLR_DEBUGGING_VERSION; typedef enum { /********************************************************************************** ** This runtime has a non-catchup managed debug event to send ** ** Catchup events include process, app domain, assembly, module, and thread ** ** creation notifications that bring the debugger up to the current state after ** ** attaching. Non-catchup events are everything else. ** **********************************************************************************/ CLR_DEBUGGING_MANAGED_EVENT_PENDING = 1, /********************************************************************************** ** The managed event that is pending is a Debugger.Launch request ** **********************************************************************************/ CLR_DEBUGGING_MANAGED_EVENT_DEBUGGER_LAUNCH = 2, } CLR_DEBUGGING_PROCESS_FLAGS; /************************************************************************************** ** ICLRDebuggingLibraryProvider ** ** Implemented by API user ** ** This interface allows the debugger to provide modules which are needed for ** ** debugging a particular CLR such as mscordbi and mscordacwks. The module handles ** ** need to remain valid until a call to ICLRDebugging::CanUnloadNow indicates they ** ** may be freed, at which point it is the caller's responsibility to free the ** ** handles. ** **************************************************************************************/ [ uuid(3151C08D-4D09-4f9b-8838-2880BF18FE51), version(1.0), helpstring("CLR debugging LibraryProvider callback interface"), local ] interface ICLRDebuggingLibraryProvider : IUnknown { /********************************************************************************** ** The goal of this method is to allow the debugger to provide a handle to a ** ** module which is needed for debugging. The debugger may use any available means** ** to locate and/or procure the module. See the security note below for important** ** information about implementing this method securely. ** ** Arguments: ** ** pwzFileName - The name of the module being requested ** ** dwTimeStamp - The date time stamp stored in the COFF file header of PE files ** ** dwSizeOfImage - The SizeOfImage field stored in the COFF optional file header ** ** of PE files ** ** phModule - Set this to the handle to the requested module on success. On ** ** failure leave it untouched. See security note below! ** ** ** ** Return value - S_OK if the module was provided, or any other convenient ** ** error HRESULT if the module could not be provided ** ** ** ** ** ** !!!!!!!!!!!!!! ** ** SECURITY NOTE: Anything the caller would not be willing to execute itself, it ** ** should not provide to the this API call ** ***********************************************************************************/ HRESULT ProvideLibrary( [in] const WCHAR* pwszFileName, [in] DWORD dwTimestamp, [in] DWORD dwSizeOfImage, [out] HMODULE* phModule); } /************************************************************************************** ** ICLRDebuggingLibraryProvider2 ** ** Implemented by API user ** ** This interface allows the debugger to provide module paths which are needed for ** ** debugging a particular CLR such as mscordbi and mscordacwks. ** **************************************************************************************/ [ uuid(E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA), version(1.0), helpstring("CLR debugging LibraryProvider callback interface"), local ] interface ICLRDebuggingLibraryProvider2 : IUnknown { /********************************************************************************** ** The goal of this method is to allow the debugger to provide a module path ** ** which is needed for debugging. The debugger may use any available means to ** ** locate and/or procure the module. See the security note below for important ** ** information about implementing this method securely. ** ** Arguments: ** ** pwzFileName - The name of the module being requested ** ** dwTimeStamp - The date time stamp stored in the COFF file header of PE files ** ** dwSizeOfImage - The SizeOfImage field stored in the COFF optional file header ** ** of PE files ** ** ppResolvedModulePath - Where *ppResolvedModulePath is a null terminated ** ** path to the module dll. On Windows it should be ** ** allocated with CoTaskMemAlloc. On Unix it should be ** ** allocated with malloc. Failure leave it untouched. See ** ** security note below! ** ** ** ** Return value - S_OK if the module was provided, or any other convenient ** ** error HRESULT if the module could not be provided ** ** ** ** !!!!!!!!!!!!!! ** ** SECURITY NOTE: Anything the caller would not be willing to execute itself, it ** ** should not provide to the this API call ** ***********************************************************************************/ HRESULT ProvideLibrary2( [in] const WCHAR* pwszFileName, [in] DWORD dwTimestamp, [in] DWORD dwSizeOfImage, [out] LPWSTR* ppResolvedModulePath); } /************************************************************************************** ** ICLRDebugging ** ** Activated using mscoree!CLRCreateInstance. ** **************************************************************************************/ [ uuid(D28F3C5A-9634-4206-A509-477552EEFB10), version(1.0), helpstring("CLR debugging interface for MetaHost interface"), local ] interface ICLRDebugging : IUnknown { /********************************************************************************** ** Get the ICorDebugProcess and other information corresponding to a clr module ** ** loaded in the process ** ** Arguments: ** ** moduleBaseAddress - The base address of a module in the target process. ** ** COR_E_NOT_CLR will be returned if the indicated module is ** ** not a clr. ** ** pDataTarget - A data target abstraction which allows the managed ** ** debugger to inspect process state. It must implement ** ** at least ICorDebugDataTarget. ** ** pLibraryProvider - A library provider callback interface that allows version ** ** specific debugging libraries to be located and loaded on ** ** demand. This parameter is only required if ppProcess or ** ** pFlags is non-NULL. ** ** pMaxDebuggerSupportedVersion - The version of the CLR this debugger is ** ** designed to support. The debugger should specify the ** ** major and minor versions from the newest CLR version this ** ** debugger supports. The function may still succeed with ** ** a newer version of the CLR than this if the CLR ** ** determines that it should be compatible. The build and ** ** revision values are currently ignored. ** ** riidProcess - The interface ID of the desired ICorDebugProcess ** ** interface. Currently the only legal values are ** ** IID_CORDEBUGPROCESS3, IID_CORDEBUGPROCESS2, and ** ** IID_CORDEBUGPROCESS. ** ** ppProcess - Returns a pointer to a COM interface identified by ** ** riidProcess. Future versions of the runtime may implement ** ** other interfaces. ** ** pwszVersion - On input this is either null, or points to a ** ** CLR_DEBUGGING_VERSION structure. The wStructVersion field ** ** must be initialized to 0. On output the structure will be ** ** filled in with the CLR version information. ** ** pFlags - Informational flags about the specified runtime, see ** ** CLR_DEBUGGING_PROCESS_FLAGS for a description of the ** ** flags. ** ** ** ** The return value is S_OK if succeeded or: ** ** E_POINTER if pDataTarget is NULL ** ** CORDBG_E_LIBRARY_PROVIDER_ERROR if the ICLRDebuggingLibraryProvider callback** ** returns an error or does not provide a valid** ** handle ** ** CORDBG_E_MISSING_DATA_TARGET_INTERFACE if the pDataTarget argument does not** ** implement the required data target ** ** interfaces for this version of the runtime. ** ** CORDBG_E_NOT_CLR if the indicated module is not a clr. It is ** ** possible that modules which do represent a ** ** CLR will not be detected if memory has been ** ** corrupted, is not available, or the CLR is ** ** of a newer version than the shim. ** ** CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL if this runtime version does not ** ** support this debugging model. Currently v4 ** ** supports this model and no previous version ** ** does. The pVersion output argument will ** ** still be set to the correct value after ** ** receiving this error. ** ** CORDBG_E_UNSUPPORTED_FORWARD_COMPAT if the version of the CLR is not ** ** compatible with the version this debugger ** ** claims to support. The pVersion output ** ** argument will still be set to the correct ** ** value after receiving this error. ** ** E_NO_INTERFACE if the riidProcess interface is not ** ** available. ** ** CORDBG_E_UNSUPPORTED_VERSION_STRUCT if the version struct does not have a ** ** recognized value for wStructVersion. The ** ** only accepted value at this time is 0. ** ** Any other convenient HRESULT error, depending on the execution. ** **********************************************************************************/ HRESULT OpenVirtualProcess( [in] ULONG64 moduleBaseAddress, [in] IUnknown * pDataTarget, [in] ICLRDebuggingLibraryProvider * pLibraryProvider, [in] CLR_DEBUGGING_VERSION * pMaxDebuggerSupportedVersion, [in] REFIID riidProcess, [out, iid_is(riidProcess)] IUnknown ** ppProcess, [in, out] CLR_DEBUGGING_VERSION * pVersion, [out] CLR_DEBUGGING_PROCESS_FLAGS * pdwFlags); /********************************************************************************** ** Determines if a library provided via an ICLRDebuggingLibraryProvider is still ** ** in use. Functionally this checks to see if all instances of ICorDebug* ** ** interfaces have been released and no thread is currently within a call to ** ** OpenVirtualProcess. ** ** Arguments: ** ** hModule - A module handle previously provided by the ** ** ICLRDebuggingLibraryProvider used in OpenVirtualProcess ** ** Returns: ** ** S_OK if the module can be unloaded now ** ** S_FALSE if the module is still in use ** ** Any other error HRESULT if a failure occurs ** ** ** ** Notes: As of the V4.0 implementation unloading is still not fully supported ** ** and all calls to this method will return S_FALSE. ** **********************************************************************************/ HRESULT CanUnloadNow(HMODULE hModule); } // interface ICLRDebugging /************************************************************************************** ** ICLRRuntimeInfo ** ** Represents a runtime - installed on the machine and/or loaded into a process. ** ** Includes functionality for obtaining various properties and for loading the ** ** runtime into the current process. The same installed runtime can be loaded ** ** multiple times in the same process (may not be supported in Dev10). ** **************************************************************************************/ [ uuid(BD39D1D2-BA2F-486a-89B0-B4B0CB466891), version(1.0), helpstring("CLR runtime instance"), local ] interface ICLRRuntimeInfo : IUnknown { // Methods that query information: /********************************************************************************** ** Returns the version of this runtime in the usual v-prefixed dotted form. ** ** Supersedes: GetRequestedRuntimeInfo, GetRequestedRuntimeVersion, ** ** GetCORVersion ** **********************************************************************************/ HRESULT GetVersionString( [out, size_is(*pcchBuffer), annotation("_Out_writes_all_opt_(*pcchBuffer)")] LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer); /********************************************************************************** ** Returns the directory where this runtime is installed. ** ** Supersedes: GetCORSystemDirectory ** **********************************************************************************/ HRESULT GetRuntimeDirectory( [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer); /********************************************************************************** ** Returns TRUE if this runtime is loaded into the specified process. ** ** Supersedes: GetCORSystemDirectory ** **********************************************************************************/ HRESULT IsLoaded( [in] HANDLE hndProcess, [out, retval] BOOL *pbLoaded); // Methods that may load the runtime: /********************************************************************************** ** Translates an HRESULT value into an error message. Use iLocaleID -1 for the ** ** default culture of the current thread. ** ** Supersedes: LoadStringRC, LoadStringRCEx ** **********************************************************************************/ HRESULT LoadErrorString( [in] UINT iResourceID, [out, size_is(*pcchBuffer), annotation("_Out_writes_all_(*pcchBuffer)")] LPWSTR pwzBuffer, [in, out] DWORD *pcchBuffer, [in, lcid] LONG iLocaleID); /********************************************************************************** ** Loads a library located alongside this runtime. ** ** Supersedes: LoadLibraryShim ** **********************************************************************************/ HRESULT LoadLibrary( [in] LPCWSTR pwzDllName, [out, retval] HMODULE *phndModule); /********************************************************************************** ** Gets the address of the specified function exported from this runtime. ** ** It should NOT be documented what module the function lives in. We may want ** ** to implement some forwarding policy here. The reason for exposing ** ** GetProcAddress are functions like mscorwks!GetCLRIdentityManager. ** ** Supersedes: GetRealProcAddress ** **********************************************************************************/ HRESULT GetProcAddress( [in] LPCSTR pszProcName, [out, retval] LPVOID *ppProc); /********************************************************************************** ** Loads the runtime into the current process and returns an interface through ** ** which runtime functionality is provided. ** ** ** ** Supported CLSIDs/IIDs: ** ** CLSID_CorMetaDataDispenser IID_IMetaDataDispenser,IID_IMetaDataDispenserEx ** ** CLSID_CorMetaDataDispenserRuntime dtto ** ** CLSID_CorRuntimeHost IID_ICorRuntimeHost ** ** CLSID_CLRRuntimeHost IID_ICLRRuntimeHost ** ** CLSID_TypeNameFactory IID_ITypeNameFactory ** ** CLSID_CLRStrongName IID_ICLRStrongName ** ** CLSID_CLRDebuggingLegacy IID_ICorDebug ** ** ** ** Supersedes: CorBindTo* and others ** **********************************************************************************/ HRESULT GetInterface( [in] REFCLSID rclsid, [in] REFIID riid, [out, iid_is(riid), retval] LPVOID *ppUnk); // Does not load runtime /********************************************************************************** ** Returns TRUE if this runtime could be loaded into the current process. Note ** ** that this method is side-effect free, and thus does not represent a ** ** commitment to be able to load this runtime if it sets *pbLoadable to be TRUE.** ** Supersedes: none ** **********************************************************************************/ HRESULT IsLoadable( [out, retval] BOOL *pbLoadable); /********************************************************************************** ** Sets startup flags and host config file that will be used at startup. ** ** Supersedes: The startupFlags parameter in CorBindToRuntimeEx/Host ** **********************************************************************************/ HRESULT SetDefaultStartupFlags( [in] DWORD dwStartupFlags, [in] LPCWSTR pwzHostConfigFile); /********************************************************************************** ** Gets startup flags and host config file that will be used at startup. ** ** Supersedes: GetStartupFlags, GetHostConfigurationFile ** **********************************************************************************/ HRESULT GetDefaultStartupFlags( [out] DWORD *pdwStartupFlags, [out, size_is(*pcchHostConfigFile), annotation("_Out_writes_all_opt_(*pcchHostConfigFile)")] LPWSTR pwzHostConfigFile, [in, out] DWORD *pcchHostConfigFile); /********************************************************************************** ** If not already bound (for example, with a useLegacyV2RuntimeActivationPolicy ** ** config setting), binds this runtime for all legacy V2 activation policy ** ** decisions. If a different runtime was already bound to the legacy V2 ** ** activation policy, returns CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND. If this ** ** runtime was already bound as the legacy V2 activation policy runtime, ** ** returns S_OK. ** **********************************************************************************/ HRESULT BindAsLegacyV2Runtime(); /********************************************************************************** ** Returns TRUE if the runtime has been started, i.e. Start() has been called. ** ** If it has been started, its STARTUP_FLAGS are returned. ** ** ** ** IMPORTANT: This method is valid only for v4+ runtimes. This method will ** ** return E_NOTIMPL for all pre-v4 runtimes. ** **********************************************************************************/ HRESULT IsStarted( [out] BOOL *pbStarted, [out] DWORD *pdwStartupFlags); }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/metamodelpub.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // MetaModelPub.h -- header file for Common Language Runtime metadata. // // //***************************************************************************** #ifndef _METAMODELPUB_H_ #define _METAMODELPUB_H_ #if _MSC_VER >= 1100 # pragma once #endif #include #include "contract.h" template inline T Align4(T p) { LIMITED_METHOD_CONTRACT; INT_PTR i = (INT_PTR)p; i = (i+(3)) & ~3; return (T)i; } typedef uint32_t RID; // check if a rid is valid or not #define InvalidRid(rid) ((rid) == 0) #ifndef METADATA_FIELDS_PROTECTION #define METADATA_FIELDS_PROTECTION public #endif //***************************************************************************** // Record definitions. Records have some combination of fixed size fields and // variable sized fields (actually, constant across a database, but variable // between databases). // // In this section we define record definitions which include the fixed size // fields and an enumeration of the variable sized fields. // // Naming is as follows: // Given some table "Xyz": // class XyzRec { public: // SOMETYPE m_SomeField; // // rest of the fixed fields. // enum { COL_Xyz_SomeOtherField, // // rest of the fields, enumerated. // COL_Xyz_COUNT }; // }; // // The important features are the class name (XyzRec), the enumerations // (COL_Xyz_FieldName), and the enumeration count (COL_Xyz_COUNT). // // THESE NAMING CONVENTIONS ARE CARVED IN STONE! DON'T TRY TO BE CREATIVE! // //***************************************************************************** // Have the compiler generate two byte alignment. Be careful to manually lay // out the fields for proper alignment. The alignment for variable-sized // fields will be computed at save time. #include // Non-sparse tables. class ModuleRec { METADATA_FIELDS_PROTECTION: USHORT m_Generation; // ENC generation. public: enum { COL_Generation, COL_Name, COL_Mvid, COL_EncId, COL_EncBaseId, COL_COUNT, COL_KEY }; USHORT GetGeneration() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Generation); } void SetGeneration(USHORT Generation) { LIMITED_METHOD_CONTRACT; m_Generation = VAL16(Generation); } }; class TypeRefRec { public: enum { COL_ResolutionScope, // mdModuleRef or mdAssemblyRef. COL_Name, COL_Namespace, COL_COUNT, COL_KEY }; }; class TypeDefRec { METADATA_FIELDS_PROTECTION: ULONG m_Flags; // Flags for this TypeDef public: enum { COL_Flags, COL_Name, // offset into string pool. COL_Namespace, COL_Extends, // coded token to typedef/typeref. COL_FieldList, // rid of first field. COL_MethodList, // rid of first method. COL_COUNT, COL_KEY }; ULONG GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL32(Flags); } void AddFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags |= VAL32(Flags); } void RemoveFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags &= ~VAL32(Flags); } }; class FieldPtrRec { public: enum { COL_Field, COL_COUNT, COL_KEY }; }; class FieldRec { METADATA_FIELDS_PROTECTION: USHORT m_Flags; // Flags for the field. public: enum { COL_Flags, COL_Name, COL_Signature, COL_COUNT, COL_KEY }; USHORT GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = (USHORT)VAL16(Flags); } void AddFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags |= (USHORT)VAL16(Flags); } void RemoveFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags &= (USHORT)~VAL16(Flags); } }; class MethodPtrRec { public: enum { COL_Method, COL_COUNT, COL_KEY }; }; class MethodRec { METADATA_FIELDS_PROTECTION: ULONG m_RVA; // RVA of the Method. USHORT m_ImplFlags; // Descr flags of the Method. USHORT m_Flags; // Flags for the Method. public: enum { COL_RVA, COL_ImplFlags, COL_Flags, COL_Name, COL_Signature, COL_ParamList, // Rid of first param. COL_COUNT, COL_KEY }; void Copy(MethodRec *pFrom) { LIMITED_METHOD_CONTRACT; m_RVA = pFrom->m_RVA; m_ImplFlags = pFrom->m_ImplFlags; m_Flags = pFrom->m_Flags; } ULONG GetRVA() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_RVA); } void SetRVA(ULONG RVA) { LIMITED_METHOD_CONTRACT; m_RVA = VAL32(RVA); } USHORT GetImplFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_ImplFlags); } void SetImplFlags(USHORT ImplFlags) { LIMITED_METHOD_CONTRACT; m_ImplFlags = VAL16(ImplFlags); } void AddImplFlags(USHORT ImplFlags) { LIMITED_METHOD_CONTRACT; m_ImplFlags |= VAL16(ImplFlags); } void RemoveImplFlags(USHORT ImplFlags) { LIMITED_METHOD_CONTRACT; m_ImplFlags &= ~VAL16(ImplFlags); } USHORT GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = (USHORT)VAL16(Flags); } void AddFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags |= (USHORT)VAL16(Flags); } void RemoveFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags &= (USHORT)~VAL16(Flags); } }; class ParamPtrRec { public: enum { COL_Param, COL_COUNT, COL_KEY }; }; class ParamRec { METADATA_FIELDS_PROTECTION: USHORT m_Flags; // Flags for this Param. USHORT m_Sequence; // Sequence # of param. 0 - return value. public: enum { COL_Flags, COL_Sequence, COL_Name, // Name of the param. COL_COUNT, COL_KEY }; void Copy(ParamRec *pFrom) { LIMITED_METHOD_CONTRACT; m_Flags = pFrom->m_Flags; m_Sequence = pFrom->m_Sequence; } USHORT GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = (USHORT)VAL16(Flags); } void AddFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags |= (USHORT)VAL16(Flags); } void RemoveFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags &= (USHORT)~VAL16(Flags); } USHORT GetSequence() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Sequence); } void SetSequence(USHORT Sequence) { LIMITED_METHOD_CONTRACT; m_Sequence = VAL16(Sequence); } }; class InterfaceImplRec { public: enum { COL_Class, // Rid of class' TypeDef. COL_Interface, // Coded rid of implemented interface. COL_COUNT, COL_KEY = COL_Class }; }; class MemberRefRec { public: enum { COL_Class, // Rid of TypeDef. COL_Name, COL_Signature, COL_COUNT, COL_KEY }; }; class StandAloneSigRec { public: enum { COL_Signature, COL_COUNT, COL_KEY }; }; // Sparse tables. These contain modifiers for tables above. class ConstantRec { METADATA_FIELDS_PROTECTION: BYTE m_Type; // Type of the constant. BYTE m_PAD1; public: enum { COL_Type, COL_Parent, // Coded rid of object (param, field). COL_Value, // Index into blob pool. COL_COUNT, COL_KEY = COL_Parent }; BYTE GetType() { LIMITED_METHOD_CONTRACT; return m_Type; } void SetType(BYTE Type) { LIMITED_METHOD_CONTRACT; m_Type = Type; } }; class CustomAttributeRec { public: enum { COL_Parent, // Coded rid of any object. COL_Type, // TypeDef or TypeRef. COL_Value, // Blob. COL_COUNT, COL_KEY = COL_Parent }; }; class FieldMarshalRec { public: enum { COL_Parent, // Coded rid of field or param. COL_NativeType, COL_COUNT, COL_KEY = COL_Parent }; }; class DeclSecurityRec { METADATA_FIELDS_PROTECTION: USHORT m_Action; public: enum { COL_Action, COL_Parent, COL_PermissionSet, COL_COUNT, COL_KEY = COL_Parent }; void Copy(DeclSecurityRec *pFrom) { LIMITED_METHOD_CONTRACT; m_Action = pFrom->m_Action; } USHORT GetAction() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Action); } void SetAction(USHORT Action) { LIMITED_METHOD_CONTRACT; m_Action = VAL16(Action); } }; class ClassLayoutRec { METADATA_FIELDS_PROTECTION: USHORT m_PackingSize; ULONG m_ClassSize; public: enum { COL_PackingSize, COL_ClassSize, COL_Parent, // Rid of TypeDef. COL_COUNT, COL_KEY = COL_Parent }; void Copy(ClassLayoutRec *pFrom) { LIMITED_METHOD_CONTRACT; m_PackingSize = pFrom->m_PackingSize; m_ClassSize = pFrom->m_ClassSize; } USHORT GetPackingSize() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_PackingSize); } void SetPackingSize(USHORT PackingSize) { LIMITED_METHOD_CONTRACT; m_PackingSize = VAL16(PackingSize); } ULONG GetClassSize() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_ClassSize); } void SetClassSize(ULONG ClassSize) { LIMITED_METHOD_CONTRACT; m_ClassSize = VAL32(ClassSize); } }; class FieldLayoutRec { METADATA_FIELDS_PROTECTION: ULONG m_OffSet; public: enum { COL_OffSet, COL_Field, COL_COUNT, COL_KEY = COL_Field }; void Copy(FieldLayoutRec *pFrom) { LIMITED_METHOD_CONTRACT; m_OffSet = pFrom->m_OffSet; } ULONG GetOffSet() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OffSet); } void SetOffSet(ULONG Offset) { LIMITED_METHOD_CONTRACT; m_OffSet = VAL32(Offset); } }; class EventMapRec { public: enum { COL_Parent, COL_EventList, // rid of first event. COL_COUNT, COL_KEY }; }; class EventPtrRec { public: enum { COL_Event, COL_COUNT, COL_KEY }; }; class EventRec { METADATA_FIELDS_PROTECTION: USHORT m_EventFlags; public: enum { COL_EventFlags, COL_Name, COL_EventType, COL_COUNT, COL_KEY }; USHORT GetEventFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_EventFlags); } void SetEventFlags(USHORT EventFlags) { LIMITED_METHOD_CONTRACT; m_EventFlags = VAL16(EventFlags); } void AddEventFlags(USHORT EventFlags) { LIMITED_METHOD_CONTRACT; m_EventFlags |= VAL16(EventFlags); } }; class PropertyMapRec { public: enum { COL_Parent, COL_PropertyList, // rid of first property. COL_COUNT, COL_KEY }; }; class PropertyPtrRec { public: enum { COL_Property, COL_COUNT, COL_KEY }; }; class PropertyRec { METADATA_FIELDS_PROTECTION: USHORT m_PropFlags; public: enum { COL_PropFlags, COL_Name, COL_Type, COL_COUNT, COL_KEY }; USHORT GetPropFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_PropFlags); } void SetPropFlags(USHORT PropFlags) { LIMITED_METHOD_CONTRACT; m_PropFlags = VAL16(PropFlags); } void AddPropFlags(USHORT PropFlags) { LIMITED_METHOD_CONTRACT; m_PropFlags |= VAL16(PropFlags); } }; class MethodSemanticsRec { METADATA_FIELDS_PROTECTION: USHORT m_Semantic; public: enum { COL_Semantic, COL_Method, COL_Association, COL_COUNT, COL_KEY = COL_Association }; USHORT GetSemantic() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Semantic); } void SetSemantic(USHORT Semantic) { LIMITED_METHOD_CONTRACT; m_Semantic = VAL16(Semantic); } }; class MethodImplRec { public: enum { COL_Class, // TypeDef where the MethodBody lives. COL_MethodBody, // MethodDef or MemberRef. COL_MethodDeclaration, // MethodDef or MemberRef. COL_COUNT, COL_KEY = COL_Class }; }; class ModuleRefRec { public: enum { COL_Name, COL_COUNT, COL_KEY }; }; class TypeSpecRec { public: enum { COL_Signature, COL_COUNT, COL_KEY }; }; class ImplMapRec { METADATA_FIELDS_PROTECTION: USHORT m_MappingFlags; public: enum { COL_MappingFlags, COL_MemberForwarded, // mdField or mdMethod. COL_ImportName, COL_ImportScope, // mdModuleRef. COL_COUNT, COL_KEY = COL_MemberForwarded }; USHORT GetMappingFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_MappingFlags); } void SetMappingFlags(USHORT MappingFlags) { LIMITED_METHOD_CONTRACT; m_MappingFlags = VAL16(MappingFlags); } }; class FieldRVARec { METADATA_FIELDS_PROTECTION: ULONG m_RVA; public: enum{ COL_RVA, COL_Field, COL_COUNT, COL_KEY = COL_Field }; void Copy(FieldRVARec *pFrom) { LIMITED_METHOD_CONTRACT; m_RVA = pFrom->m_RVA; } ULONG GetRVA() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_RVA); } void SetRVA(ULONG RVA) { LIMITED_METHOD_CONTRACT; m_RVA = VAL32(RVA); } }; class ENCLogRec { METADATA_FIELDS_PROTECTION: ULONG m_Token; // Token, or like a token, but with (ixTbl|0x80) instead of token type. ULONG m_FuncCode; // Function code describing the nature of ENC change. public: enum { COL_Token, COL_FuncCode, COL_COUNT, COL_KEY }; ULONG GetToken() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Token); } void SetToken(ULONG Token) { LIMITED_METHOD_CONTRACT; m_Token = VAL32(Token); } ULONG GetFuncCode() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_FuncCode); } void SetFuncCode(ULONG FuncCode) { LIMITED_METHOD_CONTRACT; m_FuncCode = VAL32(FuncCode); } }; class ENCMapRec { METADATA_FIELDS_PROTECTION: ULONG m_Token; // Token, or like a token, but with (ixTbl|0x80) instead of token type. public: enum { COL_Token, COL_COUNT, COL_KEY }; ULONG GetToken() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Token); } void SetToken(ULONG Token) { LIMITED_METHOD_CONTRACT; m_Token = VAL32(Token); } }; // Assembly tables. class AssemblyRec { METADATA_FIELDS_PROTECTION: ULONG m_HashAlgId; USHORT m_MajorVersion; USHORT m_MinorVersion; USHORT m_BuildNumber; USHORT m_RevisionNumber; ULONG m_Flags; public: enum { COL_HashAlgId, COL_MajorVersion, COL_MinorVersion, COL_BuildNumber, COL_RevisionNumber, COL_Flags, COL_PublicKey, // Public key identifying the publisher COL_Name, COL_Locale, COL_COUNT, COL_KEY }; void Copy(AssemblyRec *pFrom) { LIMITED_METHOD_CONTRACT; m_HashAlgId = pFrom->m_HashAlgId; m_MajorVersion = pFrom->m_MajorVersion; m_MinorVersion = pFrom->m_MinorVersion; m_BuildNumber = pFrom->m_BuildNumber; m_RevisionNumber = pFrom->m_RevisionNumber; m_Flags = pFrom->m_Flags; } ULONG GetHashAlgId() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_HashAlgId); } void SetHashAlgId (ULONG HashAlgId) { LIMITED_METHOD_CONTRACT; m_HashAlgId = VAL32(HashAlgId); } USHORT GetMajorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_MajorVersion); } void SetMajorVersion (USHORT MajorVersion) { LIMITED_METHOD_CONTRACT; m_MajorVersion = VAL16(MajorVersion); } USHORT GetMinorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_MinorVersion); } void SetMinorVersion (USHORT MinorVersion) { LIMITED_METHOD_CONTRACT; m_MinorVersion = VAL16(MinorVersion); } USHORT GetBuildNumber() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_BuildNumber); } void SetBuildNumber (USHORT BuildNumber) { LIMITED_METHOD_CONTRACT; m_BuildNumber = VAL16(BuildNumber); } USHORT GetRevisionNumber() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_RevisionNumber); } void SetRevisionNumber (USHORT RevisionNumber) { LIMITED_METHOD_CONTRACT; m_RevisionNumber = VAL16(RevisionNumber); } ULONG GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Flags); } void SetFlags (ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL32(Flags); } }; class AssemblyProcessorRec { METADATA_FIELDS_PROTECTION: ULONG m_Processor; public: enum { COL_Processor, COL_COUNT, COL_KEY }; ULONG GetProcessor() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Processor); } void SetProcessor(ULONG Processor) { LIMITED_METHOD_CONTRACT; m_Processor = VAL32(Processor); } }; class AssemblyOSRec { METADATA_FIELDS_PROTECTION: ULONG m_OSPlatformId; ULONG m_OSMajorVersion; ULONG m_OSMinorVersion; public: enum { COL_OSPlatformId, COL_OSMajorVersion, COL_OSMinorVersion, COL_COUNT, COL_KEY }; ULONG GetOSPlatformId() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OSPlatformId); } void SetOSPlatformId(ULONG OSPlatformId) { LIMITED_METHOD_CONTRACT; m_OSPlatformId = VAL32(OSPlatformId); } ULONG GetOSMajorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OSMajorVersion); } void SetOSMajorVersion(ULONG OSMajorVersion) { LIMITED_METHOD_CONTRACT; m_OSMajorVersion = VAL32(OSMajorVersion); } ULONG GetOSMinorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OSMinorVersion); } void SetOSMinorVersion(ULONG OSMinorVersion) { LIMITED_METHOD_CONTRACT; m_OSMinorVersion = VAL32(OSMinorVersion); } }; class AssemblyRefRec { METADATA_FIELDS_PROTECTION: USHORT m_MajorVersion; USHORT m_MinorVersion; USHORT m_BuildNumber; USHORT m_RevisionNumber; ULONG m_Flags; public: enum { COL_MajorVersion, COL_MinorVersion, COL_BuildNumber, COL_RevisionNumber, COL_Flags, COL_PublicKeyOrToken, // The public key or token identifying the publisher of the Assembly. COL_Name, COL_Locale, COL_HashValue, COL_COUNT, COL_KEY }; void Copy(AssemblyRefRec *pFrom) { LIMITED_METHOD_CONTRACT; m_MajorVersion = pFrom->m_MajorVersion; m_MinorVersion = pFrom->m_MinorVersion; m_BuildNumber = pFrom->m_BuildNumber; m_RevisionNumber = pFrom->m_RevisionNumber; m_Flags = pFrom->m_Flags; } USHORT GetMajorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_MajorVersion); } void SetMajorVersion(USHORT MajorVersion) { LIMITED_METHOD_CONTRACT; m_MajorVersion = VAL16(MajorVersion); } USHORT GetMinorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_MinorVersion); } void SetMinorVersion(USHORT MinorVersion) { LIMITED_METHOD_CONTRACT; m_MinorVersion = VAL16(MinorVersion); } USHORT GetBuildNumber() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_BuildNumber); } void SetBuildNumber(USHORT BuildNumber) { LIMITED_METHOD_CONTRACT; m_BuildNumber = VAL16(BuildNumber); } USHORT GetRevisionNumber() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_RevisionNumber); } void SetRevisionNumber(USHORT RevisionNumber) { LIMITED_METHOD_CONTRACT; m_RevisionNumber = RevisionNumber; } ULONG GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL32(Flags); } }; class AssemblyRefProcessorRec { METADATA_FIELDS_PROTECTION: ULONG m_Processor; public: enum { COL_Processor, COL_AssemblyRef, // mdtAssemblyRef COL_COUNT, COL_KEY }; ULONG GetProcessor() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Processor); } void SetProcessor(ULONG Processor) { LIMITED_METHOD_CONTRACT; m_Processor = VAL32(Processor); } }; class AssemblyRefOSRec { METADATA_FIELDS_PROTECTION: ULONG m_OSPlatformId; ULONG m_OSMajorVersion; ULONG m_OSMinorVersion; public: enum { COL_OSPlatformId, COL_OSMajorVersion, COL_OSMinorVersion, COL_AssemblyRef, // mdtAssemblyRef. COL_COUNT, COL_KEY }; ULONG GetOSPlatformId() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OSPlatformId); } void SetOSPlatformId(ULONG OSPlatformId) { LIMITED_METHOD_CONTRACT; m_OSPlatformId = VAL32(OSPlatformId); } ULONG GetOSMajorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OSMajorVersion); } void SetOSMajorVersion(ULONG OSMajorVersion) { LIMITED_METHOD_CONTRACT; m_OSMajorVersion = VAL32(OSMajorVersion); } ULONG GetOSMinorVersion() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_OSMinorVersion); } void SetOSMinorVersion(ULONG OSMinorVersion) { LIMITED_METHOD_CONTRACT; m_OSMinorVersion = VAL32(OSMinorVersion); } }; class FileRec { METADATA_FIELDS_PROTECTION: ULONG m_Flags; public: enum { COL_Flags, COL_Name, COL_HashValue, COL_COUNT, COL_KEY }; void Copy(FileRec *pFrom) { LIMITED_METHOD_CONTRACT; m_Flags = pFrom->m_Flags; } ULONG GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL32(Flags); } }; class ExportedTypeRec { METADATA_FIELDS_PROTECTION: ULONG m_Flags; ULONG m_TypeDefId; public: enum { COL_Flags, COL_TypeDefId, COL_TypeName, COL_TypeNamespace, COL_Implementation, // mdFile or mdAssemblyRef. COL_COUNT, COL_KEY }; void Copy(ExportedTypeRec *pFrom) { LIMITED_METHOD_CONTRACT; m_Flags = pFrom->m_Flags; m_TypeDefId = pFrom->m_TypeDefId; } ULONG GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL32(Flags); } ULONG GetTypeDefId() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_TypeDefId); } void SetTypeDefId(ULONG TypeDefId) { LIMITED_METHOD_CONTRACT; m_TypeDefId = VAL32(TypeDefId); } }; class ManifestResourceRec { METADATA_FIELDS_PROTECTION: ULONG m_Offset; ULONG m_Flags; public: enum { COL_Offset, COL_Flags, COL_Name, COL_Implementation, // mdFile or mdAssemblyRef. COL_COUNT, COL_KEY }; void Copy(ManifestResourceRec *pFrom) { LIMITED_METHOD_CONTRACT; m_Flags = pFrom->m_Flags; m_Offset = pFrom->m_Offset; } ULONG GetOffset() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Offset); } void SetOffset(ULONG Offset) { LIMITED_METHOD_CONTRACT; m_Offset = VAL32(Offset); } ULONG GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL32(&m_Flags); } void SetFlags(ULONG Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL32(Flags); } }; // End Assembly Tables. class NestedClassRec { public: enum { COL_NestedClass, COL_EnclosingClass, COL_COUNT, COL_KEY = COL_NestedClass }; }; // Generics class GenericParamRec { METADATA_FIELDS_PROTECTION: USHORT m_Number; // index; zero = first var USHORT m_Flags; // index; zero = first var public: enum { COL_Number, // index; zero = first var COL_Flags, // flags, for future use COL_Owner, // typeDef/methodDef COL_Name, // Purely descriptive, not used for binding purposes COL_COUNT, COL_KEY = COL_Owner }; USHORT GetNumber() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Number); } void SetNumber(USHORT Number) { LIMITED_METHOD_CONTRACT; m_Number = VAL16(Number); } USHORT GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Flags); } void SetFlags(USHORT Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL16(Flags); } }; // @todo: this definition is for reading the old (and wrong) GenericParamRec from a // Beta1 assembly. class GenericParamV1_1Rec { METADATA_FIELDS_PROTECTION: USHORT m_Number; // index; zero = first var USHORT m_Flags; // index; zero = first var public: enum { COL_Number, // index; zero = first var COL_Flags, // flags, for future use COL_Owner, // typeDef/methodDef COL_Name, // Purely descriptive, not used for binding purposes COL_Kind, // typeDef/Ref/Spec, reserved for future use COL_COUNT, COL_KEY = COL_Owner }; USHORT GetNumber() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Number); } void SetNumber(USHORT Number) { LIMITED_METHOD_CONTRACT; m_Number = VAL16(Number); } USHORT GetFlags() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Flags); } void SetFlags(USHORT Flags) { LIMITED_METHOD_CONTRACT; m_Flags = VAL16(Flags); } }; class MethodSpecRec { public: enum { COL_Method, // methodDef/memberRef COL_Instantiation, // signature COL_COUNT, COL_KEY }; }; class GenericParamConstraintRec { public: enum { COL_Owner, // GenericParam COL_Constraint, // typeDef/Ref/Spec COL_COUNT, COL_KEY = COL_Owner }; }; #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB /* Portable PDB tables */ // -- Dummy records to fill the gap to 0x30 class DummyRec { public: enum { COL_COUNT, COL_KEY }; }; class Dummy1Rec : public DummyRec {}; class Dummy2Rec : public DummyRec {}; class Dummy3Rec : public DummyRec {}; class DocumentRec { public: enum { COL_Name, COL_HashAlgorithm, COL_Hash, COL_Language, COL_COUNT, COL_KEY }; }; class MethodDebugInformationRec { public: enum { COL_Document, COL_SequencePoints, COL_COUNT, COL_KEY }; }; class LocalScopeRec { METADATA_FIELDS_PROTECTION: // [IMPORTANT]: Assigning values directly can override other columns, use PutCol instead ULONG m_StartOffset; // [IMPORTANT]: Assigning values directly can override other columns, use PutCol instead ULONG m_Length; public: enum { COL_Method, COL_ImportScope, COL_VariableList, COL_ConstantList, COL_StartOffset, COL_Length, COL_COUNT, COL_KEY }; }; class LocalVariableRec { METADATA_FIELDS_PROTECTION: USHORT m_Attributes; USHORT m_Index; public: enum { COL_Attributes, COL_Index, COL_Name, COL_COUNT, COL_KEY }; USHORT GetAttributes() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Attributes); } void SetAttributes(USHORT attributes) { LIMITED_METHOD_CONTRACT; m_Attributes = VAL16(attributes); } USHORT GetIndex() { LIMITED_METHOD_CONTRACT; return GET_UNALIGNED_VAL16(&m_Index); } void SetIndex(USHORT index) { LIMITED_METHOD_CONTRACT; m_Index = VAL16(index); } }; class LocalConstantRec { public: enum { COL_Name, COL_Signature, COL_COUNT, COL_KEY }; }; class ImportScopeRec { public: enum { COL_Parent, COL_Imports, COL_COUNT, COL_KEY }; }; // TODO: // class StateMachineMethodRec // class CustomDebugInformationRec #endif // FEATURE_METADATA_EMIT_PORTABLE_PDB #include // List of MiniMd tables. #define MiniMdTables() \ MiniMdTable(Module) \ MiniMdTable(TypeRef) \ MiniMdTable(TypeDef) \ MiniMdTable(FieldPtr) \ MiniMdTable(Field) \ MiniMdTable(MethodPtr) \ MiniMdTable(Method) \ MiniMdTable(ParamPtr) \ MiniMdTable(Param) \ MiniMdTable(InterfaceImpl) \ MiniMdTable(MemberRef) \ MiniMdTable(Constant) \ MiniMdTable(CustomAttribute)\ MiniMdTable(FieldMarshal) \ MiniMdTable(DeclSecurity) \ MiniMdTable(ClassLayout) \ MiniMdTable(FieldLayout) \ MiniMdTable(StandAloneSig) \ MiniMdTable(EventMap) \ MiniMdTable(EventPtr) \ MiniMdTable(Event) \ MiniMdTable(PropertyMap) \ MiniMdTable(PropertyPtr) \ MiniMdTable(Property) \ MiniMdTable(MethodSemantics)\ MiniMdTable(MethodImpl) \ MiniMdTable(ModuleRef) \ MiniMdTable(TypeSpec) \ MiniMdTable(ImplMap) \ MiniMdTable(FieldRVA) \ MiniMdTable(ENCLog) \ MiniMdTable(ENCMap) \ MiniMdTable(Assembly) \ MiniMdTable(AssemblyProcessor) \ MiniMdTable(AssemblyOS) \ MiniMdTable(AssemblyRef) \ MiniMdTable(AssemblyRefProcessor) \ MiniMdTable(AssemblyRefOS) \ MiniMdTable(File) \ MiniMdTable(ExportedType) \ MiniMdTable(ManifestResource) \ MiniMdTable(NestedClass) \ MiniMdTable(GenericParam) \ MiniMdTable(MethodSpec) \ MiniMdTable(GenericParamConstraint) #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB #define PortablePdbMiniMdTables() \ /* Dummy tables to fill the gap to 0x30 */ \ MiniMdTable(Dummy1) /* 0x2D */ \ MiniMdTable(Dummy2) /* 0x2E */ \ MiniMdTable(Dummy3) /* 0x2F */ \ /* Actual portable PDB tables */ \ MiniMdTable(Document) /* 0x30 */ \ MiniMdTable(MethodDebugInformation) /* 0x31 */ \ MiniMdTable(LocalScope) /* 0x32 */ \ MiniMdTable(LocalVariable) /* 0x33 */ \ MiniMdTable(LocalConstant) /* 0x34 */ \ MiniMdTable(ImportScope) /* 0x35 */ \ // TODO: // MiniMdTable(StateMachineMethod) /* 0x36 */ // MiniMdTable(CustomDebugInformation) /* 0x37 */ #endif // FEATURE_METADATA_EMIT_PORTABLE_PDB #undef MiniMdTable #define MiniMdTable(x) TBL_##x, enum { MiniMdTables() #ifdef FEATURE_METADATA_EMIT_PORTABLE_PDB PortablePdbMiniMdTables() #endif TBL_COUNT, // Highest table. TBL_COUNT_V1 = TBL_NestedClass + 1, // Highest table in v1.0 database #ifndef FEATURE_METADATA_EMIT_PORTABLE_PDB TBL_COUNT_V2 = TBL_GenericParamConstraint + 1 // Highest in v2.0 database #else TBL_COUNT_V2 = TBL_ImportScope + 1 // Highest in portable PDB database #endif }; #undef MiniMdTable // List of MiniMd coded token types. #define MiniMdCodedTokens() \ MiniMdCodedToken(TypeDefOrRef) \ MiniMdCodedToken(HasConstant) \ MiniMdCodedToken(HasCustomAttribute) \ MiniMdCodedToken(HasFieldMarshal) \ MiniMdCodedToken(HasDeclSecurity) \ MiniMdCodedToken(MemberRefParent) \ MiniMdCodedToken(HasSemantic) \ MiniMdCodedToken(MethodDefOrRef) \ MiniMdCodedToken(MemberForwarded) \ MiniMdCodedToken(Implementation) \ MiniMdCodedToken(CustomAttributeType) \ MiniMdCodedToken(ResolutionScope) \ MiniMdCodedToken(TypeOrMethodDef) \ #undef MiniMdCodedToken #define MiniMdCodedToken(x) CDTKN_##x, enum { MiniMdCodedTokens() CDTKN_COUNT }; #undef MiniMdCodedToken //***************************************************************************** // Meta-meta data. Constant across all MiniMds. //***************************************************************************** #ifndef _META_DATA_META_CONSTANTS_DEFINED #define _META_DATA_META_CONSTANTS_DEFINED const unsigned int iRidMax = 63; const unsigned int iCodedToken = 64; // base of coded tokens. const unsigned int iCodedTokenMax = 95; const unsigned int iSHORT = 96; // fixed types. const unsigned int iUSHORT = 97; const unsigned int iLONG = 98; const unsigned int iULONG = 99; const unsigned int iBYTE = 100; const unsigned int iSTRING = 101; // pool types. const unsigned int iGUID = 102; const unsigned int iBLOB = 103; inline int IsRidType(ULONG ix) {LIMITED_METHOD_CONTRACT; return ix <= iRidMax; } inline int IsCodedTokenType(ULONG ix) {LIMITED_METHOD_CONTRACT; return (ix >= iCodedToken) && (ix <= iCodedTokenMax); } inline int IsRidOrToken(ULONG ix) {LIMITED_METHOD_CONTRACT; return ix <= iCodedTokenMax; } inline int IsHeapType(ULONG ix) {LIMITED_METHOD_CONTRACT; return ix >= iSTRING; } inline int IsFixedType(ULONG ix) {LIMITED_METHOD_CONTRACT; return (ix < iSTRING) && (ix > iCodedTokenMax); } #endif enum MDPools { MDPoolStrings, // Id for the string pool. MDPoolGuids, // ...the GUID pool. MDPoolBlobs, // ...the blob pool. MDPoolUSBlobs, // ...the user string pool. MDPoolCount, // Count of pools, for array sizing. }; // enum MDPools struct CCodedTokenDef { ULONG m_cTokens; // Count of tokens. const mdToken *m_pTokens; // Array of tokens. const char *m_pName; // Name of the coded-token type. }; struct CMiniColDef { BYTE m_Type; // Type of the column. BYTE m_oColumn; // Offset of the column. BYTE m_cbColumn; // Size of the column. }; struct CMiniTableDef { CMiniColDef *m_pColDefs; // Array of field defs. BYTE m_cCols; // Count of columns in the table. BYTE m_iKey; // Column which is the key, if any. USHORT m_cbRec; // Size of the records. }; struct CMiniTableDefEx { CMiniTableDef m_Def; // Table definition. const char * const *m_pColNames; // Array of column names. const char *m_pName; // Name of the table. }; #endif // _METAMODELPUB_H_ // eof ------------------------------------------------------------------------ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/mpl/type_list ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Used in template metaprogramming, type lists consist of a series of // Scheme-like nodes that contain a Head type and a Tail type. The head // type is usually a non-list type, but compound lists are possible. // // Type lists are always terminated with a tail type of mpl::null_type. // #ifndef __type_list__ #define __type_list__ namespace mpl // 'mpl' => 'meta-programming library' { // Used as terminator in type_lists. class null_type {}; // The core type. See file comment for details. template struct type_list { typedef T head; typedef U tail; }; template struct type_at; template struct type_at, IDX> { typedef typename type_at::type type; }; template struct type_at, 0> { typedef head type; }; // Helper struct to create a type_list chain from a list of arguments. template < typename T1 = null_type, typename T2 = null_type, typename T3 = null_type, typename T4 = null_type, typename T5 = null_type, typename T6 = null_type, typename T7 = null_type, typename T8 = null_type, typename T9 = null_type, typename T10 = null_type, typename T11 = null_type, typename T12 = null_type, typename T13 = null_type, typename T14 = null_type, typename T15 = null_type, typename T16 = null_type, typename T17 = null_type, typename T18 = null_type > struct make_type_list { private: // recurse on the tail elements typedef typename make_type_list::type tail; public: // combine head with computed tail typedef type_list type; }; template<> struct make_type_list < null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type > { public: typedef null_type type; }; } #endif // __type_list__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/mscoree.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // /************************************************************************************** ** ** ** Mscoree.idl - interface definitions for mscoree.dll ** ** ** **************************************************************************************/ // // Interface descriptions // import "unknwn.idl"; cpp_quote("struct IActivationFactory;") interface IActivationFactory; cpp_quote("struct IHostControl;") interface IHostControl; cpp_quote("struct ICLRControl;") interface ICLRControl; // IID ICLRRuntimeHost: uuid(90F1A06C-7712-4762-86B5-7A5EBA6BDB02) cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02);") // IID ICLRRuntimeHost2: uuid(712AB73F-2C22-4807-AD7E-F501D7B72C2D) cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost2, 0x712AB73F, 0x2C22, 0x4807, 0xAD, 0x7E, 0xF5, 0x01, 0xD7, 0xb7, 0x2C, 0x2D);") // IID ICLRRuntimeHost4: uuid(64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF) cpp_quote("EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF);") #pragma midl_echo("typedef HRESULT (STDAPICALLTYPE *FnGetCLRRuntimeHost)(REFIID riid, IUnknown **pUnk);") typedef HRESULT (__stdcall *FExecuteInAppDomainCallback) (void* cookie); // By default GC is concurrent and only the base system library is loaded into the domain-neutral area. typedef enum { STARTUP_CONCURRENT_GC = 0x1, STARTUP_LOADER_OPTIMIZATION_MASK = 0x3<<1, // loader optimization mask STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN = 0x1<<1, // no domain neutral loading STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN = 0x2<<1, // all domain neutral loading STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST = 0x3<<1, // strong name domain neutral loading STARTUP_LOADER_SAFEMODE = 0x10, // Do not apply runtime version policy to the version passed in STARTUP_LOADER_SETPREFERENCE = 0x100, // Set preferred runtime. Do not actally start it STARTUP_SERVER_GC = 0x1000, // Use server GC STARTUP_HOARD_GC_VM = 0x2000, // GC keeps virtual address used STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = 0x4000, // Disallow mixing hosting interface STARTUP_LEGACY_IMPERSONATION = 0x10000, // Do not flow impersonation across async points by default STARTUP_DISABLE_COMMITTHREADSTACK = 0x20000, // Don't eagerly commit thread stack STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000, // Force flow impersonation across async points // (impersonations achieved thru p/invoke and managed will flow. // default is to flow only managed impersonation) STARTUP_TRIM_GC_COMMIT = 0x80000, // GC uses less committed space when system memory low STARTUP_ETW = 0x100000, STARTUP_ARM = 0x400000, // Enable the ARM feature. STARTUP_SINGLE_APPDOMAIN = 0x800000, // application runs in default domain, no more domains are created STARTUP_APPX_APP_MODEL = 0x1000000, // jupiter app STARTUP_DISABLE_RANDOMIZED_STRING_HASHING = 0x2000000 // Disable the randomized string hashing (not supported) } STARTUP_FLAGS; typedef enum { APPDOMAIN_SECURITY_DEFAULT =0x0, APPDOMAIN_SECURITY_SANDBOXED = 0x1, // appdomain is sandboxed APPDOMAIN_SECURITY_FORBID_CROSSAD_REVERSE_PINVOKE = 0x2, // no cross ad reverse pinvokes APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS = 0x4, // APPDOMAIN_FORCE_TRIVIAL_WAIT_OPERATIONS = 0x08, // do not pump messages during wait operations, do not call sync context // When passed by the host, this flag will allow any assembly to perform PInvoke or COMInterop operations. // Otherwise, by default, only platform assemblies can perform those operations. APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x10, APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS = 0x40, APPDOMAIN_ENABLE_ASSEMBLY_LOADFILE = 0x80, APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT = 0x100, } APPDOMAIN_SECURITY_FLAGS; typedef enum { WAIT_MSGPUMP = 0x1, WAIT_ALERTABLE = 0x2, WAIT_NOTINDEADLOCK = 0x4 }WAIT_OPTION; typedef enum { // Default to minidump DUMP_FLAVOR_Mini = 0, // Include critical CLR state DUMP_FLAVOR_CriticalCLRState = 1, // Include critical CLR state and ngen images without including hosted heap // It is host's responsibility to report hosted heap. DUMP_FLAVOR_NonHeapCLRState = 2, DUMP_FLAVOR_Default = DUMP_FLAVOR_Mini } ECustomDumpFlavor; const DWORD BucketParamsCount = 10; const DWORD BucketParamLength = 255; // used for indexing into BucketParameters::pszParams typedef enum { Parameter1 = 0, Parameter2, Parameter3, Parameter4, Parameter5, Parameter6, Parameter7, Parameter8, Parameter9, InvalidBucketParamIndex } BucketParameterIndex; typedef struct _BucketParameters { BOOL fInited; // Set to TRUE if the rest of this structure is valid. WCHAR pszEventTypeName[BucketParamLength]; // Name of the event type. WCHAR pszParams[BucketParamsCount][BucketParamLength]; // Parameter strings. } BucketParameters; //***************************************************************************** // New interface for hosting mscoree //***************************************************************************** [ uuid(90F1A06C-7712-4762-86B5-7A5EBA6BDB02), version(1.0), helpstring("Common Language Runtime Hosting Interface"), pointer_default(unique), local ] interface ICLRRuntimeHost : IUnknown { // Starts the runtime. This is equivalent to CoInitializeCor(). HRESULT Start(); // Terminates the runtime, This is equivalent CoUninitializeCor(); HRESULT Stop(); // Returns an object for configuring runtime, e.g. threading, lock // prior it starts. If the runtime has been initialized this // routine returns an error. See IHostControl. HRESULT SetHostControl([in] IHostControl* pHostControl); HRESULT GetCLRControl([out] ICLRControl** pCLRControl); HRESULT UnloadAppDomain([in] DWORD dwAppDomainId, [in] BOOL fWaitUntilDone); HRESULT ExecuteInAppDomain([in] DWORD dwAppDomainId, [in] FExecuteInAppDomainCallback pCallback, [in] void* cookie); HRESULT GetCurrentAppDomainId([out] DWORD *pdwAppDomainId); HRESULT ExecuteApplication([in] LPCWSTR pwzAppFullName, [in] DWORD dwManifestPaths, [in] LPCWSTR *ppwzManifestPaths, // optional [in] DWORD dwActivationData, [in] LPCWSTR *ppwzActivationData, // optional [out] int *pReturnValue); HRESULT ExecuteInDefaultAppDomain([in] LPCWSTR pwzAssemblyPath, [in] LPCWSTR pwzTypeName, [in] LPCWSTR pwzMethodName, [in] LPCWSTR pwzArgument, [out] DWORD *pReturnValue); }; //***************************************************************************** // New interface for hosting mscoree //***************************************************************************** [ object, uuid(712AB73F-2C22-4807-AD7E-F501D7B72C2D), version(2.0), helpstring("Common Language Runtime Hosting Interface"), pointer_default(unique), local ] interface ICLRRuntimeHost2 : ICLRRuntimeHost { // Creates an app domain (sandboxed or not) with the given manager class and the given // set of properties. HRESULT CreateAppDomainWithManager([in] LPCWSTR wszFriendlyName, [in] DWORD dwFlags, [in] LPCWSTR wszAppDomainManagerAssemblyName, [in] LPCWSTR wszAppDomainManagerTypeName, [in] int nProperties, [in] LPCWSTR* pPropertyNames, [in] LPCWSTR* pPropertyValues, [out] DWORD* pAppDomainID); HRESULT CreateDelegate([in] DWORD appDomainID, [in] LPCWSTR wszAssemblyName, [in] LPCWSTR wszClassName, [in] LPCWSTR wszMethodName, [out] INT_PTR* fnPtr); // Authenticates a host based upon a key value. No longer required. HRESULT Authenticate([in] ULONGLONG authKey); // Ensures CLR-set Mac (Mach) EH port is registered. HRESULT RegisterMacEHPort(); HRESULT SetStartupFlags([in] STARTUP_FLAGS dwFlags); HRESULT DllGetActivationFactory([in] DWORD appDomainID, [in] LPCWSTR wszTypeName, [out] IActivationFactory ** factory); HRESULT ExecuteAssembly([in] DWORD dwAppDomainId, [in] LPCWSTR pwzAssemblyPath, [in] int argc, [in] LPCWSTR* argv, [out] DWORD *pReturnValue); }; [ object, uuid(64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF), version(4.0), helpstring("Common Language Runtime Hosting Interface"), pointer_default(unique), local ] interface ICLRRuntimeHost4 : ICLRRuntimeHost2 { HRESULT UnloadAppDomain2([in] DWORD dwAppDomainId, [in] BOOL fWaitUntilDone, [out] int *pLatchedExitCode); }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/msodw.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma once /**************************************************************************** This files contains the handshake structure with which apps will launch Watson. ****************************************************************************/ #ifndef MSODW_H #define MSODW_H #pragma pack(push, msodw_h) #pragma pack(4) #define DW_MAX_BUCKETPARAM_CWC 255 typedef struct _GenericModeBlock { BOOL fInited; WCHAR wzEventTypeName[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP1[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP2[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP3[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP4[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP5[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP6[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP7[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP8[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP9[DW_MAX_BUCKETPARAM_CWC]; WCHAR wzP10[DW_MAX_BUCKETPARAM_CWC]; } GenericModeBlock; #pragma pack(pop, msodw_h) #endif // MSODW_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/msodwwrap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __msodwwrap_h__ #define __msodwwrap_h__ #ifndef MSODW_H #include "msodw.h" #endif // MSODW_H #endif // __msodwwrap_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/nativevaraccessors.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // The following are used to read and write data given NativeVarInfo // for primitive types. Don't use these for VALUECLASSes. //***************************************************************************** #ifndef _NATIVE_VAR_ACCESSORS_H_ #define _NATIVE_VAR_ACCESSORS_H_ #include "corjit.h" bool operator ==(const ICorDebugInfo::VarLoc &varLoc1, const ICorDebugInfo::VarLoc &varLoc2); #define MAX_NATIVE_VAR_LOCS 2 SIZE_T GetRegOffsInCONTEXT(ICorDebugInfo::RegNum regNum); struct NativeVarLocation { ULONG64 addr; TADDR size; bool contextReg; }; ULONG NativeVarLocations(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx, ULONG numLocs, NativeVarLocation* locs); SIZE_T *NativeVarStackAddr(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx); bool GetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx, SIZE_T * pVal1, SIZE_T * pVal2 BIT64_ARG(SIZE_T cbSize)); bool SetNativeVarVal(const ICorDebugInfo::VarLoc & varLoc, PT_CONTEXT pCtx, SIZE_T val1, SIZE_T val2 BIT64_ARG(SIZE_T cbSize)); #endif // #ifndef _NATIVE_VAR_ACCESSORS_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/new.hpp ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // #ifndef __new__hpp #define __new__hpp #if defined(_MSC_VER) && _MSC_VER < 1900 #define NOEXCEPT #else #define NOEXCEPT noexcept #endif struct NoThrow { int x; }; extern const NoThrow nothrow; void * __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; void * __cdecl operator new[](size_t n, const NoThrow&) NOEXCEPT; #ifdef _DEBUG void DisableThrowCheck(); #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/nibblemapmacros.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef NIBBLEMAPMACROS_H_ #define NIBBLEMAPMACROS_H_ /////////////////////////////////////////////////////////////////////// //// some mmgr stuff for JIT, especially for jit code blocks /////////////////////////////////////////////////////////////////////// // // In order to quickly find the start of a jit code block // we keep track of all those positions via a map. // Each entry in this map represents 32 byte (a bucket) of the code heap. // We make the assumption that no two code-blocks can start in // the same 32byte bucket; // Additionally we assume that every code header is DWORD aligned. // Because we cannot guarantee that jitblocks always start at // multiples of 32 bytes we cannot use a simple bitmap; instead we // use a nibble (4 bit) per bucket and encode the offset of the header // inside the bucket (in DWORDS). In order to make initialization // easier we add one to the real offset, a nibble-value of zero // means that there is no header start in the resp. bucket. // In order to speed up "backwards scanning" we start numbering // nibbles inside a DWORD from the highest bits (28..31). Because // of that we can scan backwards inside the DWORD with right shifts. #if defined(HOST_64BIT) // TODO: bump up the windows CODE_ALIGN to 16 and iron out any nibble map bugs that exist. // TODO: there is something wrong with USE_INDIRECT_CODEHEADER with CODE_ALIGN=16 # define CODE_ALIGN 4 # define LOG2_CODE_ALIGN 2 #else # define CODE_ALIGN sizeof(DWORD) // 4 byte boundry # define LOG2_CODE_ALIGN 2 #endif #define NIBBLE_MASK 0xf #define NIBBLE_SIZE 4 // 4 bits #define LOG2_NIBBLE_SIZE 2 #define NIBBLES_PER_DWORD ((8*sizeof(DWORD)) >> LOG2_NIBBLE_SIZE) // 8 (4-bit) nibbles per dword #define NIBBLES_PER_DWORD_MASK (NIBBLES_PER_DWORD - 1) // 7 #define LOG2_NIBBLES_PER_DWORD 3 #define BYTES_PER_BUCKET (NIBBLES_PER_DWORD * CODE_ALIGN) // 32 bytes per bucket #define LOG2_BYTES_PER_BUCKET (LOG2_CODE_ALIGN + LOG2_NIBBLES_PER_DWORD) // 5 bits per bucket #define MASK_BYTES_PER_BUCKET (BYTES_PER_BUCKET - 1) // 31 #define HIGHEST_NIBBLE_BIT (32 - NIBBLE_SIZE) // 28 (i.e 32 - 4) #define HIGHEST_NIBBLE_MASK (NIBBLE_MASK << HIGHEST_NIBBLE_BIT) // 0xf0000000 #define ADDR2POS(x) ((x) >> LOG2_BYTES_PER_BUCKET) #define ADDR2OFFS(x) (DWORD) ((((x) & MASK_BYTES_PER_BUCKET) >> LOG2_CODE_ALIGN) + 1) #define POSOFF2ADDR(pos, of) (size_t) (((pos) << LOG2_BYTES_PER_BUCKET) + (((of) - 1) << LOG2_CODE_ALIGN)) #define HEAP2MAPSIZE(x) (((x) / (BYTES_PER_BUCKET * NIBBLES_PER_DWORD)) * CODE_ALIGN) #define POS2SHIFTCOUNT(x) (DWORD) (HIGHEST_NIBBLE_BIT - (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE)) #define POS2MASK(x) (DWORD) ~(HIGHEST_NIBBLE_MASK >> (((x) & NIBBLES_PER_DWORD_MASK) << LOG2_NIBBLE_SIZE)) #endif // NIBBLEMAPMACROS_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/nibblestream.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // NibbleStream reader and writer. #ifndef _NIBBLESTREAM_H_ #define _NIBBLESTREAM_H_ #include "contract.h" #include "sigbuilder.h" typedef BYTE NIBBLE; //----------------------------------------------------------------------------- // Helpers for compression routines. //----------------------------------------------------------------------------- // This class allows variable-length compression of DWORDs. // // A value can be stored using one or more nibbles. 3 bits of a nibble are used // to store 3 bits of the value, and the top bit indicates if the following nibble // contains rest of the value. If the top bit is not set, then this // nibble is the last part of the value. // The higher bits of the value are written out first, and the lowest 3 bits // are written out last. // // In the encoded stream of bytes, the lower nibble of a byte is used before // the high nibble. // // A binary value ABCDEFGHI (where A is the highest bit) is encoded as // the follow two bytes : 1DEF1ABC XXXX0GHI // // Examples : // 0 => X0 // 1 => X1 // // 7 => X7 // 8 => 09 // 9 => 19 // // 0x3F (63) => 7F // 0x40 (64) => F9 X0 // 0x41 (65) => F9 X1 // // 0x1FF (511) => FF X7 // 0x200 (512) => 89 08 // 0x201 (513) => 89 18 class NibbleWriter { public: NibbleWriter() { LIMITED_METHOD_CONTRACT; m_fPending = false; } void Flush() { if (m_fPending) m_SigBuilder.AppendByte(m_PendingNibble); } PVOID GetBlob(DWORD * pdwLength) { return m_SigBuilder.GetSignature(pdwLength); } DWORD GetBlobLength() { return m_SigBuilder.GetSignatureLength(); } //............................................................................. // Writer methods //............................................................................. // Write a single nibble to the stream. void WriteNibble(NIBBLE i) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; _ASSERTE(i <= 0xF); if (m_fPending) { // Use the high nibble after the low nibble is used m_SigBuilder.AppendByte(m_PendingNibble | (i << 4)); m_fPending = false; } else { // Use the low nibble first m_PendingNibble = i; m_fPending = true; } } // Write an unsigned int via variable length nibble encoding. // We use the bit scheme: // 0ABC (if 0 <= dw <= 0x7) // 1ABC 0DEF (if 0 <= dw <= 0x7f) // 1ABC 1DEF 0GHI (if 0 <= dw <= 0x7FF) // etc.. void WriteEncodedU32(DWORD dw) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; // Fast path for common small inputs if (dw <= 63) { if (dw > 7) { WriteNibble((NIBBLE) ((dw >> 3) | 8)); } WriteNibble((NIBBLE) (dw & 7)); return; } // Note we must write this out with the low terminating nibble (0ABC) last b/c the // reader gets nibbles in the same order we write them. int i = 0; while ((dw >> i) > 7) { i+= 3; } while(i > 0) { WriteNibble((NIBBLE) ((dw >> i) & 0x7) | 0x8); i -= 3; } WriteNibble((NIBBLE) dw & 0x7); } // Write a signed 32 bit value. void WriteEncodedI32(int x) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; DWORD dw = (x < 0) ? (((-x) << 1) + 1) : (x << 1); WriteEncodedU32(dw); }; void WriteUnencodedU32(uint32_t x) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; for (int i = 0; i < 8; i++) { WriteNibble(static_cast(x & 0b1111)); x >>= 4; } } protected: NIBBLE m_PendingNibble; // Pending value, not yet written out. bool m_fPending; // SigBuilder is a convenient helper class for writing out small blobs SigBuilder m_SigBuilder; }; //----------------------------------------------------------------------------- class NibbleReader { public: NibbleReader(PTR_BYTE pBuffer, size_t size) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; _ASSERTE(pBuffer != NULL); m_pBuffer = pBuffer; m_cBytes = size; m_cNibble = 0; } // Get the index of the next Byte. // This tells us how many bytes (rounding up to whole bytes) have been read. // This is can be used to extract raw byte data that may be embedded on a byte boundary in the nibble stream. size_t GetNextByteIndex() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return (m_cNibble + 1) / 2; } NIBBLE ReadNibble() { CONTRACTL { THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; NIBBLE i = 0; // Bufer should have been allocated large enough to hold data. if (!(m_cNibble / 2 < m_cBytes)) { // We should never get here in a normal retail scenario. // We could wind up here if somebody provided us invalid data (maybe by corrupting an ngenned image). EX_THROW(HRException, (E_INVALIDARG)); } BYTE p = m_pBuffer[m_cNibble / 2]; if ((m_cNibble & 1) == 0) { // Read the low nibble first i = (NIBBLE) (p & 0xF); } else { // Read the high nibble after the low nibble has been read i = (NIBBLE) (p >> 4) & 0xF; } m_cNibble++; return i; } // Read an unsigned int that was encoded via variable length nibble encoding // from NibbleWriter::WriteEncodedU32. DWORD ReadEncodedU32() { CONTRACTL { THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; DWORD dw =0; #if defined(_DEBUG) || defined(DACCESS_COMPILE) int dwCount = 0; #endif // The encoding is variably lengthed, with the high-bit of every nibble indicating whether // there is another nibble in the value. Each nibble contributes 3 bits to the value. NIBBLE n; do { #if defined(_DEBUG) || defined(DACCESS_COMPILE) // If we've already read 11 nibbles (with 3 bits of usable data each), then we // should be done reading a 32-bit integer. // Avoid working with corrupted data and potentially long loops by failing if(dwCount > 11) { _ASSERTE_MSG(false, "Corrupt nibble stream - value exceeded 32-bits in size"); #ifdef DACCESS_COMPILE DacError(CORDBG_E_TARGET_INCONSISTENT); #endif } dwCount++; #endif n = ReadNibble(); dw = (dw << 3) + (n & 0x7); } while((n & 0x8) > 0); return dw; } int ReadEncodedI32() { CONTRACTL { THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; DWORD dw = ReadEncodedU32(); int x = dw >> 1; return (dw & 1) ? (-x) : (x); } DWORD ReadUnencodedU32() { CONTRACTL { THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; DWORD result = 0; for (int i = 0; i < 8; i++) { result |= static_cast(ReadNibble()) << (i * 4); } return result; } protected: PTR_BYTE m_pBuffer; size_t m_cBytes; // size of buffer. size_t m_cNibble; // Which nibble are we at? }; #endif // _NIBBLESTREAM_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/nsutilpriv.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // NSUtilPriv.h // // Helpers for converting namespace separators. // //***************************************************************************** #ifndef __NSUTILPRIV_H__ #define __NSUTILPRIV_H__ template class CQuickArray; class SString; struct ns { //***************************************************************************** // Determine how many chars large a fully qualified name would be given the // two parts of the name. The return value includes room for every character // in both names, as well as room for the separator and a final terminator. //***************************************************************************** static int GetFullLength( // Number of chars in full name. const WCHAR *szNameSpace, // Namspace for value. const WCHAR *szName); // Name of value. static int GetFullLength( // Number of chars in full name. LPCUTF8 szNameSpace, // Namspace for value. LPCUTF8 szName); // Name of value. //***************************************************************************** // Scan the given string to see if the name contains any invalid characters // that are not allowed. //***************************************************************************** static int IsValidName( // true if valid, false invalid. const WCHAR *szName); // Name to parse. static int IsValidName( // true if valid, false invalid. LPCUTF8 szName); // Name to parse. //***************************************************************************** // Scan the string from the rear looking for the first valid separator. If // found, return a pointer to it. Else return null. This code is smart enough // to skip over special sequences, such as: // a.b..ctor // ^ // | // The ".ctor" is considered one token. //***************************************************************************** static WCHAR *FindSep( // Pointer to separator or null. const WCHAR *szPath); // The path to look in. static LPUTF8 FindSep( // Pointer to separator or null. LPCUTF8 szPath); // The path to look in. //***************************************************************************** // Take a path and find the last separator (nsFindSep), and then replace the // separator with a '\0' and return a pointer to the name. So for example: // a.b.c // becomes two strings "a.b" and "c" and the return value points to "c". //***************************************************************************** static WCHAR *SplitInline( // Pointer to name portion. __inout __inout_z WCHAR *szPath); // The path to split. static LPUTF8 SplitInline( // Pointer to name portion. __inout __inout_z LPUTF8 szPath); // The path to split. static void SplitInline( __inout __inout_z LPWSTR szPath, // Path to split. LPCWSTR &szNameSpace, // Return pointer to namespace. LPCWSTR &szName); // Return pointer to name. static void SplitInline( __inout __inout_z LPUTF8 szPath, // Path to split. LPCUTF8 &szNameSpace, // Return pointer to namespace. LPCUTF8 &szName); // Return pointer to name. //***************************************************************************** // Split the last parsable element from the end of the string as the name, // the first part as the namespace. //***************************************************************************** static int SplitPath( // true ok, false trunction. const WCHAR *szPath, // Path to split. _Out_writes_opt_ (cchNameSpace) WCHAR *szNameSpace, // Output for namespace value. int cchNameSpace, // Max chars for output. _Out_writes_opt_ (cchName) WCHAR *szName, // Output for name. int cchName); // Max chars for output. static int SplitPath( // true ok, false trunction. LPCUTF8 szPath, // Path to split. _Out_writes_opt_ (cchNameSpace) LPUTF8 szNameSpace, // Output for namespace value. int cchNameSpace, // Max chars for output. _Out_writes_opt_ (cchName) LPUTF8 szName, // Output for name. int cchName); // Max chars for output. //***************************************************************************** // Take two values and put them together in a fully qualified path using the // correct separator. //***************************************************************************** static int MakePath( // true ok, false truncation. _Out_writes_(cchChars) WCHAR *szOut, // output path for name. int cchChars, // max chars for output path. const WCHAR *szNameSpace, // Namespace. const WCHAR *szName); // Name. static int MakePath( // true ok, false truncation. _Out_writes_(cchChars) LPUTF8 szOut, // output path for name. int cchChars, // max chars for output path. LPCUTF8 szNameSpace, // Namespace. LPCUTF8 szName); // Name. static int MakePath( // true ok, false truncation. _Out_writes_(cchChars) WCHAR *szOut, // output path for name. int cchChars, // max chars for output path. LPCUTF8 szNameSpace, // Namespace. LPCUTF8 szName); // Name. static int MakePath( // true ok, false out of memory CQuickBytes &qb, // Where to put results. LPCUTF8 szNameSpace, // Namespace for name. LPCUTF8 szName); // Final part of name. static int MakePath( // true ok, false out of memory CQuickArray &qa, // Where to put results. LPCUTF8 szNameSpace, // Namespace for name. LPCUTF8 szName); // Final part of name. static int MakePath( // true ok, false out of memory CQuickBytes &qb, // Where to put results. const WCHAR *szNameSpace, // Namespace for name. const WCHAR *szName); // Final part of name. static void MakePath( // throws on out of memory SString &ssBuf, // Where to put results. const SString &ssNameSpace, // Namespace for name. const SString &ssName); // Final part of name. //***************************************************************************** // Concatinate type names to assembly names //***************************************************************************** static bool MakeAssemblyQualifiedName( // true if ok, false if out of memory CQuickBytes &qb, // location to put result const WCHAR *szTypeName, // Type name const WCHAR *szAssemblyName); // Assembly Name static bool MakeAssemblyQualifiedName( // true ok, false truncation _Out_writes_ (dwBuffer) WCHAR* pBuffer, // Buffer to receive the results int dwBuffer, // Number of characters total in buffer const WCHAR *szTypeName, // Namespace for name. int dwTypeName, // Number of characters (not including null) const WCHAR *szAssemblyName, // Final part of name. int dwAssemblyName); // Number of characters (not including null) static int MakeNestedTypeName( // true ok, false out of memory CQuickBytes &qb, // Where to put results. LPCUTF8 szEnclosingName, // Full name for enclosing type LPCUTF8 szNestedName); // Full name for nested type static int MakeNestedTypeName( // true ok, false truncation. _Out_writes_ (cchChars) LPUTF8 szOut, // output path for name. int cchChars, // max chars for output path. LPCUTF8 szEnclosingName, // Full name for enclosing type LPCUTF8 szNestedName); // Full name for nested type static void MakeNestedTypeName( // throws on out of memory SString &ssBuf, // output path for name. const SString &ssEnclosingName, // Full name for enclosing type const SString &ssNestedName); // Full name for nested type }; // struct ns #ifndef NAMESPACE_SEPARATOR_CHAR #define NAMESPACE_SEPARATOR_CHAR '.' #define NAMESPACE_SEPARATOR_WCHAR W('.') #define NAMESPACE_SEPARATOR_STR "." #define NAMESPACE_SEPARATOR_WSTR W(".") #define NAMESPACE_SEPARATOR_LEN 1 #define ASSEMBLY_SEPARATOR_CHAR ',' #define ASSEMBLY_SEPARATOR_WCHAR W(',') #define ASSEMBLY_SEPARATOR_STR ", " #define ASSEMBLY_SEPARATOR_WSTR W(", ") #define ASSEMBLY_SEPARATOR_LEN 2 #define BACKSLASH_CHAR '\\' #define BACKSLASH_WCHAR W('\\') #define NESTED_SEPARATOR_CHAR '+' #define NESTED_SEPARATOR_WCHAR W('+') #define NESTED_SEPARATOR_STR "+" #define NESTED_SEPARATOR_WSTR W("+") #endif #define EMPTY_STR "" #define EMPTY_WSTR W("") #define MAKE_FULL_PATH_ON_STACK_UTF8(toptr, pnamespace, pname) \ { \ int __i##toptr = ns::GetFullLength(pnamespace, pname); \ toptr = (char *) alloca(__i##toptr); \ ns::MakePath(toptr, __i##toptr, pnamespace, pname); \ } #define MAKE_FULL_PATH_ON_STACK_UNICODE(toptr, pnamespace, pname) \ { \ int __i##toptr = ns::GetFullLength(pnamespace, pname); \ toptr = (WCHAR *) alloca(__i##toptr * sizeof(WCHAR)); \ ns::MakePath(toptr, __i##toptr, pnamespace, pname); \ } #define MAKE_FULLY_QUALIFIED_NAME(pszFullyQualifiedName, pszNameSpace, pszName) MAKE_FULL_PATH_ON_STACK_UTF8(pszFullyQualifiedName, pszNameSpace, pszName) #define MAKE_FULLY_QUALIFIED_MEMBER_NAME(ptr, pszNameSpace, pszClassName, pszMemberName, pszSig) \ { \ int __i##ptr = ns::GetFullLength(pszNameSpace, pszClassName); \ __i##ptr += (pszMemberName ? (int) strlen(pszMemberName) : 0); \ __i##ptr += (NAMESPACE_SEPARATOR_LEN * 2); \ __i##ptr += (pszSig ? (int) strlen(pszSig) : 0); \ ptr = (LPUTF8) alloca(__i##ptr); \ ns::MakePath(ptr, __i##ptr, pszNameSpace, pszClassName); \ if (pszMemberName) { \ strcat_s(ptr, __i##ptr, NAMESPACE_SEPARATOR_STR); \ strcat_s(ptr, __i##ptr, pszMemberName); \ } \ if (pszSig) { \ if (! pszMemberName) \ strcat_s(ptr, __i##ptr, NAMESPACE_SEPARATOR_STR); \ strcat_s(ptr, __i##ptr, pszSig); \ } \ } #ifdef _PREFAST_ // need to eliminate the expansion of MAKE_FULLY_QUALIFIED_MEMBER_NAME in prefast // builds to prevent it complaining about the potential for NULLs to strlen and strcat #undef MAKE_FULLY_QUALIFIED_MEMBER_NAME // need to set ptr=NULL so we don't get a build error because ptr isn't inited in a couple cases #define MAKE_FULLY_QUALIFIED_MEMBER_NAME(ptr, pszNameSpace, pszClassName, pszMemberName, pszSig) ptr=NULL; #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/opcode.def ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** Opcode.def - COM+ Intrinsic Opcodes and Macros. ** ** ** ** This is the master table from which all opcode lists ** ** are derived. New instructions must be added to this ** ** table and generators run to produce the lookup tables ** ** used by the interpreter loop. ** ** ** ** Stack Behaviour is describing the number of 4 byte ** ** slots pushed and Poped. ** ** ** *****************************************************************************/ #ifndef __OPCODE_DEF_ #define __OPCODE_DEF_ #define MOOT 0x00 // Marks unused second byte when encoding single #define STP1 0xFE // Prefix code 1 for Standard Map #define REFPRE 0xFF // Prefix for Reference Code Encoding #define RESERVED_PREFIX_START 0xF7 #endif // If the first byte of the standard encoding is 0xFF, then // the second byte can be used as 1 byte encoding. Otherwise l b b // the encoding is two bytes. e y y // n t t // g e e // (unused) t // Canonical Name String Name Stack Behaviour Operand Params Opcode Kind h 1 2 Control Flow // ------------------------------------------------------------------------------------------------------------------------------------------------------- OPDEF(CEE_NOP, "nop", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x00, NEXT) OPDEF(CEE_BREAK, "break", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x01, BREAK) OPDEF(CEE_LDARG_0, "ldarg.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x02, NEXT) OPDEF(CEE_LDARG_1, "ldarg.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x03, NEXT) OPDEF(CEE_LDARG_2, "ldarg.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x04, NEXT) OPDEF(CEE_LDARG_3, "ldarg.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x05, NEXT) OPDEF(CEE_LDLOC_0, "ldloc.0", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x06, NEXT) OPDEF(CEE_LDLOC_1, "ldloc.1", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x07, NEXT) OPDEF(CEE_LDLOC_2, "ldloc.2", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x08, NEXT) OPDEF(CEE_LDLOC_3, "ldloc.3", Pop0, Push1, InlineNone, IMacro, 1, 0xFF, 0x09, NEXT) OPDEF(CEE_STLOC_0, "stloc.0", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0A, NEXT) OPDEF(CEE_STLOC_1, "stloc.1", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0B, NEXT) OPDEF(CEE_STLOC_2, "stloc.2", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0C, NEXT) OPDEF(CEE_STLOC_3, "stloc.3", Pop1, Push0, InlineNone, IMacro, 1, 0xFF, 0x0D, NEXT) OPDEF(CEE_LDARG_S, "ldarg.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x0E, NEXT) OPDEF(CEE_LDARGA_S, "ldarga.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x0F, NEXT) OPDEF(CEE_STARG_S, "starg.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x10, NEXT) OPDEF(CEE_LDLOC_S, "ldloc.s", Pop0, Push1, ShortInlineVar, IMacro, 1, 0xFF, 0x11, NEXT) OPDEF(CEE_LDLOCA_S, "ldloca.s", Pop0, PushI, ShortInlineVar, IMacro, 1, 0xFF, 0x12, NEXT) OPDEF(CEE_STLOC_S, "stloc.s", Pop1, Push0, ShortInlineVar, IMacro, 1, 0xFF, 0x13, NEXT) OPDEF(CEE_LDNULL, "ldnull", Pop0, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x14, NEXT) OPDEF(CEE_LDC_I4_M1, "ldc.i4.m1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x15, NEXT) OPDEF(CEE_LDC_I4_0, "ldc.i4.0", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x16, NEXT) OPDEF(CEE_LDC_I4_1, "ldc.i4.1", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x17, NEXT) OPDEF(CEE_LDC_I4_2, "ldc.i4.2", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x18, NEXT) OPDEF(CEE_LDC_I4_3, "ldc.i4.3", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x19, NEXT) OPDEF(CEE_LDC_I4_4, "ldc.i4.4", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1A, NEXT) OPDEF(CEE_LDC_I4_5, "ldc.i4.5", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1B, NEXT) OPDEF(CEE_LDC_I4_6, "ldc.i4.6", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1C, NEXT) OPDEF(CEE_LDC_I4_7, "ldc.i4.7", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1D, NEXT) OPDEF(CEE_LDC_I4_8, "ldc.i4.8", Pop0, PushI, InlineNone, IMacro, 1, 0xFF, 0x1E, NEXT) OPDEF(CEE_LDC_I4_S, "ldc.i4.s", Pop0, PushI, ShortInlineI, IMacro, 1, 0xFF, 0x1F, NEXT) OPDEF(CEE_LDC_I4, "ldc.i4", Pop0, PushI, InlineI, IPrimitive, 1, 0xFF, 0x20, NEXT) OPDEF(CEE_LDC_I8, "ldc.i8", Pop0, PushI8, InlineI8, IPrimitive, 1, 0xFF, 0x21, NEXT) OPDEF(CEE_LDC_R4, "ldc.r4", Pop0, PushR4, ShortInlineR, IPrimitive, 1, 0xFF, 0x22, NEXT) OPDEF(CEE_LDC_R8, "ldc.r8", Pop0, PushR8, InlineR, IPrimitive, 1, 0xFF, 0x23, NEXT) OPDEF(CEE_UNUSED49, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x24, NEXT) OPDEF(CEE_DUP, "dup", Pop1, Push1+Push1, InlineNone, IPrimitive, 1, 0xFF, 0x25, NEXT) OPDEF(CEE_POP, "pop", Pop1, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x26, NEXT) OPDEF(CEE_JMP, "jmp", Pop0, Push0, InlineMethod, IPrimitive, 1, 0xFF, 0x27, CALL) OPDEF(CEE_CALL, "call", VarPop, VarPush, InlineMethod, IPrimitive, 1, 0xFF, 0x28, CALL) OPDEF(CEE_CALLI, "calli", VarPop, VarPush, InlineSig, IPrimitive, 1, 0xFF, 0x29, CALL) OPDEF(CEE_RET, "ret", VarPop, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x2A, RETURN) OPDEF(CEE_BR_S, "br.s", Pop0, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2B, BRANCH) OPDEF(CEE_BRFALSE_S, "brfalse.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2C, COND_BRANCH) OPDEF(CEE_BRTRUE_S, "brtrue.s", PopI, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2D, COND_BRANCH) OPDEF(CEE_BEQ_S, "beq.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2E, COND_BRANCH) OPDEF(CEE_BGE_S, "bge.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x2F, COND_BRANCH) OPDEF(CEE_BGT_S, "bgt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x30, COND_BRANCH) OPDEF(CEE_BLE_S, "ble.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x31, COND_BRANCH) OPDEF(CEE_BLT_S, "blt.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x32, COND_BRANCH) OPDEF(CEE_BNE_UN_S, "bne.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x33, COND_BRANCH) OPDEF(CEE_BGE_UN_S, "bge.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x34, COND_BRANCH) OPDEF(CEE_BGT_UN_S, "bgt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x35, COND_BRANCH) OPDEF(CEE_BLE_UN_S, "ble.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x36, COND_BRANCH) OPDEF(CEE_BLT_UN_S, "blt.un.s", Pop1+Pop1, Push0, ShortInlineBrTarget,IMacro, 1, 0xFF, 0x37, COND_BRANCH) OPDEF(CEE_BR, "br", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x38, BRANCH) OPDEF(CEE_BRFALSE, "brfalse", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x39, COND_BRANCH) OPDEF(CEE_BRTRUE, "brtrue", PopI, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0x3A, COND_BRANCH) OPDEF(CEE_BEQ, "beq", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3B, COND_BRANCH) OPDEF(CEE_BGE, "bge", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3C, COND_BRANCH) OPDEF(CEE_BGT, "bgt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3D, COND_BRANCH) OPDEF(CEE_BLE, "ble", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3E, COND_BRANCH) OPDEF(CEE_BLT, "blt", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x3F, COND_BRANCH) OPDEF(CEE_BNE_UN, "bne.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x40, COND_BRANCH) OPDEF(CEE_BGE_UN, "bge.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x41, COND_BRANCH) OPDEF(CEE_BGT_UN, "bgt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x42, COND_BRANCH) OPDEF(CEE_BLE_UN, "ble.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x43, COND_BRANCH) OPDEF(CEE_BLT_UN, "blt.un", Pop1+Pop1, Push0, InlineBrTarget, IMacro, 1, 0xFF, 0x44, COND_BRANCH) OPDEF(CEE_SWITCH, "switch", PopI, Push0, InlineSwitch, IPrimitive, 1, 0xFF, 0x45, COND_BRANCH) OPDEF(CEE_LDIND_I1, "ldind.i1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x46, NEXT) OPDEF(CEE_LDIND_U1, "ldind.u1", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x47, NEXT) OPDEF(CEE_LDIND_I2, "ldind.i2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x48, NEXT) OPDEF(CEE_LDIND_U2, "ldind.u2", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x49, NEXT) OPDEF(CEE_LDIND_I4, "ldind.i4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4A, NEXT) OPDEF(CEE_LDIND_U4, "ldind.u4", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4B, NEXT) OPDEF(CEE_LDIND_I8, "ldind.i8", PopI, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x4C, NEXT) OPDEF(CEE_LDIND_I, "ldind.i", PopI, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x4D, NEXT) OPDEF(CEE_LDIND_R4, "ldind.r4", PopI, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x4E, NEXT) OPDEF(CEE_LDIND_R8, "ldind.r8", PopI, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x4F, NEXT) OPDEF(CEE_LDIND_REF, "ldind.ref", PopI, PushRef, InlineNone, IPrimitive, 1, 0xFF, 0x50, NEXT) OPDEF(CEE_STIND_REF, "stind.ref", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x51, NEXT) OPDEF(CEE_STIND_I1, "stind.i1", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x52, NEXT) OPDEF(CEE_STIND_I2, "stind.i2", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x53, NEXT) OPDEF(CEE_STIND_I4, "stind.i4", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x54, NEXT) OPDEF(CEE_STIND_I8, "stind.i8", PopI+PopI8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x55, NEXT) OPDEF(CEE_STIND_R4, "stind.r4", PopI+PopR4, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x56, NEXT) OPDEF(CEE_STIND_R8, "stind.r8", PopI+PopR8, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x57, NEXT) OPDEF(CEE_ADD, "add", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x58, NEXT) OPDEF(CEE_SUB, "sub", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x59, NEXT) OPDEF(CEE_MUL, "mul", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5A, NEXT) OPDEF(CEE_DIV, "div", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5B, NEXT) OPDEF(CEE_DIV_UN, "div.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5C, NEXT) OPDEF(CEE_REM, "rem", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5D, NEXT) OPDEF(CEE_REM_UN, "rem.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5E, NEXT) OPDEF(CEE_AND, "and", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x5F, NEXT) OPDEF(CEE_OR, "or", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x60, NEXT) OPDEF(CEE_XOR, "xor", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x61, NEXT) OPDEF(CEE_SHL, "shl", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x62, NEXT) OPDEF(CEE_SHR, "shr", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x63, NEXT) OPDEF(CEE_SHR_UN, "shr.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x64, NEXT) OPDEF(CEE_NEG, "neg", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x65, NEXT) OPDEF(CEE_NOT, "not", Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0x66, NEXT) OPDEF(CEE_CONV_I1, "conv.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x67, NEXT) OPDEF(CEE_CONV_I2, "conv.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x68, NEXT) OPDEF(CEE_CONV_I4, "conv.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x69, NEXT) OPDEF(CEE_CONV_I8, "conv.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6A, NEXT) OPDEF(CEE_CONV_R4, "conv.r4", Pop1, PushR4, InlineNone, IPrimitive, 1, 0xFF, 0x6B, NEXT) OPDEF(CEE_CONV_R8, "conv.r8", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x6C, NEXT) OPDEF(CEE_CONV_U4, "conv.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x6D, NEXT) OPDEF(CEE_CONV_U8, "conv.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x6E, NEXT) OPDEF(CEE_CALLVIRT, "callvirt", VarPop, VarPush, InlineMethod, IObjModel, 1, 0xFF, 0x6F, CALL) OPDEF(CEE_CPOBJ, "cpobj", PopI+PopI, Push0, InlineType, IObjModel, 1, 0xFF, 0x70, NEXT) OPDEF(CEE_LDOBJ, "ldobj", PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0x71, NEXT) OPDEF(CEE_LDSTR, "ldstr", Pop0, PushRef, InlineString, IObjModel, 1, 0xFF, 0x72, NEXT) OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) OPDEF(CEE_CASTCLASS, "castclass", PopRef, PushRef, InlineType, IObjModel, 1, 0xFF, 0x74, NEXT) OPDEF(CEE_ISINST, "isinst", PopRef, PushI, InlineType, IObjModel, 1, 0xFF, 0x75, NEXT) OPDEF(CEE_CONV_R_UN, "conv.r.un", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0x76, NEXT) OPDEF(CEE_UNUSED58, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x77, NEXT) OPDEF(CEE_UNUSED1, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0x78, NEXT) OPDEF(CEE_UNBOX, "unbox", PopRef, PushI, InlineType, IPrimitive, 1, 0xFF, 0x79, NEXT) OPDEF(CEE_THROW, "throw", PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0x7A, THROW) OPDEF(CEE_LDFLD, "ldfld", PopRef, Push1, InlineField, IObjModel, 1, 0xFF, 0x7B, NEXT) OPDEF(CEE_LDFLDA, "ldflda", PopRef, PushI, InlineField, IObjModel, 1, 0xFF, 0x7C, NEXT) OPDEF(CEE_STFLD, "stfld", PopRef+Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x7D, NEXT) OPDEF(CEE_LDSFLD, "ldsfld", Pop0, Push1, InlineField, IObjModel, 1, 0xFF, 0x7E, NEXT) OPDEF(CEE_LDSFLDA, "ldsflda", Pop0, PushI, InlineField, IObjModel, 1, 0xFF, 0x7F, NEXT) OPDEF(CEE_STSFLD, "stsfld", Pop1, Push0, InlineField, IObjModel, 1, 0xFF, 0x80, NEXT) OPDEF(CEE_STOBJ, "stobj", PopI+Pop1, Push0, InlineType, IPrimitive, 1, 0xFF, 0x81, NEXT) OPDEF(CEE_CONV_OVF_I1_UN, "conv.ovf.i1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x82, NEXT) OPDEF(CEE_CONV_OVF_I2_UN, "conv.ovf.i2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x83, NEXT) OPDEF(CEE_CONV_OVF_I4_UN, "conv.ovf.i4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x84, NEXT) OPDEF(CEE_CONV_OVF_I8_UN, "conv.ovf.i8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x85, NEXT) OPDEF(CEE_CONV_OVF_U1_UN, "conv.ovf.u1.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x86, NEXT) OPDEF(CEE_CONV_OVF_U2_UN, "conv.ovf.u2.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x87, NEXT) OPDEF(CEE_CONV_OVF_U4_UN, "conv.ovf.u4.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x88, NEXT) OPDEF(CEE_CONV_OVF_U8_UN, "conv.ovf.u8.un", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0x89, NEXT) OPDEF(CEE_CONV_OVF_I_UN, "conv.ovf.i.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8A, NEXT) OPDEF(CEE_CONV_OVF_U_UN, "conv.ovf.u.un", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0x8B, NEXT) OPDEF(CEE_BOX, "box", Pop1, PushRef, InlineType, IPrimitive, 1, 0xFF, 0x8C, NEXT) OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT) OPDEF(CEE_LDLEN, "ldlen", PopRef, PushI, InlineNone, IObjModel, 1, 0xFF, 0x8E, NEXT) OPDEF(CEE_LDELEMA, "ldelema", PopRef+PopI, PushI, InlineType, IObjModel, 1, 0xFF, 0x8F, NEXT) OPDEF(CEE_LDELEM_I1, "ldelem.i1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x90, NEXT) OPDEF(CEE_LDELEM_U1, "ldelem.u1", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x91, NEXT) OPDEF(CEE_LDELEM_I2, "ldelem.i2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x92, NEXT) OPDEF(CEE_LDELEM_U2, "ldelem.u2", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x93, NEXT) OPDEF(CEE_LDELEM_I4, "ldelem.i4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x94, NEXT) OPDEF(CEE_LDELEM_U4, "ldelem.u4", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x95, NEXT) OPDEF(CEE_LDELEM_I8, "ldelem.i8", PopRef+PopI, PushI8, InlineNone, IObjModel, 1, 0xFF, 0x96, NEXT) OPDEF(CEE_LDELEM_I, "ldelem.i", PopRef+PopI, PushI, InlineNone, IObjModel, 1, 0xFF, 0x97, NEXT) OPDEF(CEE_LDELEM_R4, "ldelem.r4", PopRef+PopI, PushR4, InlineNone, IObjModel, 1, 0xFF, 0x98, NEXT) OPDEF(CEE_LDELEM_R8, "ldelem.r8", PopRef+PopI, PushR8, InlineNone, IObjModel, 1, 0xFF, 0x99, NEXT) OPDEF(CEE_LDELEM_REF, "ldelem.ref", PopRef+PopI, PushRef, InlineNone, IObjModel, 1, 0xFF, 0x9A, NEXT) OPDEF(CEE_STELEM_I, "stelem.i", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9B, NEXT) OPDEF(CEE_STELEM_I1, "stelem.i1", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9C, NEXT) OPDEF(CEE_STELEM_I2, "stelem.i2", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9D, NEXT) OPDEF(CEE_STELEM_I4, "stelem.i4", PopRef+PopI+PopI, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9E, NEXT) OPDEF(CEE_STELEM_I8, "stelem.i8", PopRef+PopI+PopI8, Push0, InlineNone, IObjModel, 1, 0xFF, 0x9F, NEXT) OPDEF(CEE_STELEM_R4, "stelem.r4", PopRef+PopI+PopR4, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA0, NEXT) OPDEF(CEE_STELEM_R8, "stelem.r8", PopRef+PopI+PopR8, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA1, NEXT) OPDEF(CEE_STELEM_REF, "stelem.ref", PopRef+PopI+PopRef, Push0, InlineNone, IObjModel, 1, 0xFF, 0xA2, NEXT) OPDEF(CEE_LDELEM, "ldelem", PopRef+PopI, Push1, InlineType, IObjModel, 1, 0xFF, 0xA3, NEXT) OPDEF(CEE_STELEM, "stelem", PopRef+PopI+Pop1, Push0, InlineType, IObjModel, 1, 0xFF, 0xA4, NEXT) OPDEF(CEE_UNBOX_ANY, "unbox.any", PopRef, Push1, InlineType, IObjModel, 1, 0xFF, 0xA5, NEXT) OPDEF(CEE_UNUSED5, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA6, NEXT) OPDEF(CEE_UNUSED6, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA7, NEXT) OPDEF(CEE_UNUSED7, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA8, NEXT) OPDEF(CEE_UNUSED8, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xA9, NEXT) OPDEF(CEE_UNUSED9, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAA, NEXT) OPDEF(CEE_UNUSED10, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAB, NEXT) OPDEF(CEE_UNUSED11, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAC, NEXT) OPDEF(CEE_UNUSED12, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAD, NEXT) OPDEF(CEE_UNUSED13, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAE, NEXT) OPDEF(CEE_UNUSED14, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xAF, NEXT) OPDEF(CEE_UNUSED15, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB0, NEXT) OPDEF(CEE_UNUSED16, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB1, NEXT) OPDEF(CEE_UNUSED17, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xB2, NEXT) OPDEF(CEE_CONV_OVF_I1, "conv.ovf.i1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB3, NEXT) OPDEF(CEE_CONV_OVF_U1, "conv.ovf.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB4, NEXT) OPDEF(CEE_CONV_OVF_I2, "conv.ovf.i2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB5, NEXT) OPDEF(CEE_CONV_OVF_U2, "conv.ovf.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB6, NEXT) OPDEF(CEE_CONV_OVF_I4, "conv.ovf.i4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB7, NEXT) OPDEF(CEE_CONV_OVF_U4, "conv.ovf.u4", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xB8, NEXT) OPDEF(CEE_CONV_OVF_I8, "conv.ovf.i8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xB9, NEXT) OPDEF(CEE_CONV_OVF_U8, "conv.ovf.u8", Pop1, PushI8, InlineNone, IPrimitive, 1, 0xFF, 0xBA, NEXT) OPDEF(CEE_UNUSED50, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBB, NEXT) OPDEF(CEE_UNUSED18, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBC, NEXT) OPDEF(CEE_UNUSED19, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBD, NEXT) OPDEF(CEE_UNUSED20, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBE, NEXT) OPDEF(CEE_UNUSED21, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xBF, NEXT) OPDEF(CEE_UNUSED22, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC0, NEXT) OPDEF(CEE_UNUSED23, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC1, NEXT) OPDEF(CEE_REFANYVAL, "refanyval", Pop1, PushI, InlineType, IPrimitive, 1, 0xFF, 0xC2, NEXT) OPDEF(CEE_CKFINITE, "ckfinite", Pop1, PushR8, InlineNone, IPrimitive, 1, 0xFF, 0xC3, NEXT) OPDEF(CEE_UNUSED24, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC4, NEXT) OPDEF(CEE_UNUSED25, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC5, NEXT) OPDEF(CEE_MKREFANY, "mkrefany", PopI, Push1, InlineType, IPrimitive, 1, 0xFF, 0xC6, NEXT) OPDEF(CEE_UNUSED59, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC7, NEXT) OPDEF(CEE_UNUSED60, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC8, NEXT) OPDEF(CEE_UNUSED61, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xC9, NEXT) OPDEF(CEE_UNUSED62, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCA, NEXT) OPDEF(CEE_UNUSED63, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCB, NEXT) OPDEF(CEE_UNUSED64, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCC, NEXT) OPDEF(CEE_UNUSED65, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCD, NEXT) OPDEF(CEE_UNUSED66, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCE, NEXT) OPDEF(CEE_UNUSED67, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xCF, NEXT) OPDEF(CEE_LDTOKEN, "ldtoken", Pop0, PushI, InlineTok, IPrimitive, 1, 0xFF, 0xD0, NEXT) OPDEF(CEE_CONV_U2, "conv.u2", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD1, NEXT) OPDEF(CEE_CONV_U1, "conv.u1", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD2, NEXT) OPDEF(CEE_CONV_I, "conv.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD3, NEXT) OPDEF(CEE_CONV_OVF_I, "conv.ovf.i", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD4, NEXT) OPDEF(CEE_CONV_OVF_U, "conv.ovf.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xD5, NEXT) OPDEF(CEE_ADD_OVF, "add.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD6, NEXT) OPDEF(CEE_ADD_OVF_UN, "add.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD7, NEXT) OPDEF(CEE_MUL_OVF, "mul.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD8, NEXT) OPDEF(CEE_MUL_OVF_UN, "mul.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xD9, NEXT) OPDEF(CEE_SUB_OVF, "sub.ovf", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDA, NEXT) OPDEF(CEE_SUB_OVF_UN, "sub.ovf.un", Pop1+Pop1, Push1, InlineNone, IPrimitive, 1, 0xFF, 0xDB, NEXT) OPDEF(CEE_ENDFINALLY, "endfinally", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDC, RETURN) OPDEF(CEE_LEAVE, "leave", Pop0, Push0, InlineBrTarget, IPrimitive, 1, 0xFF, 0xDD, BRANCH) OPDEF(CEE_LEAVE_S, "leave.s", Pop0, Push0, ShortInlineBrTarget,IPrimitive, 1, 0xFF, 0xDE, BRANCH) OPDEF(CEE_STIND_I, "stind.i", PopI+PopI, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xDF, NEXT) OPDEF(CEE_CONV_U, "conv.u", Pop1, PushI, InlineNone, IPrimitive, 1, 0xFF, 0xE0, NEXT) OPDEF(CEE_UNUSED26, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE1, NEXT) OPDEF(CEE_UNUSED27, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE2, NEXT) OPDEF(CEE_UNUSED28, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE3, NEXT) OPDEF(CEE_UNUSED29, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE4, NEXT) OPDEF(CEE_UNUSED30, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE5, NEXT) OPDEF(CEE_UNUSED31, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE6, NEXT) OPDEF(CEE_UNUSED32, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE7, NEXT) OPDEF(CEE_UNUSED33, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE8, NEXT) OPDEF(CEE_UNUSED34, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xE9, NEXT) OPDEF(CEE_UNUSED35, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEA, NEXT) OPDEF(CEE_UNUSED36, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEB, NEXT) OPDEF(CEE_UNUSED37, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEC, NEXT) OPDEF(CEE_UNUSED38, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xED, NEXT) OPDEF(CEE_UNUSED39, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEE, NEXT) OPDEF(CEE_UNUSED40, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xEF, NEXT) OPDEF(CEE_UNUSED41, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF0, NEXT) OPDEF(CEE_UNUSED42, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF1, NEXT) OPDEF(CEE_UNUSED43, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF2, NEXT) OPDEF(CEE_UNUSED44, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF3, NEXT) OPDEF(CEE_UNUSED45, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF4, NEXT) OPDEF(CEE_UNUSED46, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF5, NEXT) OPDEF(CEE_UNUSED47, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF6, NEXT) OPDEF(CEE_UNUSED48, "unused", Pop0, Push0, InlineNone, IPrimitive, 1, 0xFF, 0xF7, NEXT) OPDEF(CEE_PREFIX7, "prefix7", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF8, META) OPDEF(CEE_PREFIX6, "prefix6", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xF9, META) OPDEF(CEE_PREFIX5, "prefix5", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFA, META) OPDEF(CEE_PREFIX4, "prefix4", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFB, META) OPDEF(CEE_PREFIX3, "prefix3", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFC, META) OPDEF(CEE_PREFIX2, "prefix2", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFD, META) OPDEF(CEE_PREFIX1, "prefix1", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFE, META) OPDEF(CEE_PREFIXREF, "prefixref", Pop0, Push0, InlineNone, IInternal, 1, 0xFF, 0xFF, META) OPDEF(CEE_ARGLIST, "arglist", Pop0, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x00, NEXT) OPDEF(CEE_CEQ, "ceq", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x01, NEXT) OPDEF(CEE_CGT, "cgt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x02, NEXT) OPDEF(CEE_CGT_UN, "cgt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x03, NEXT) OPDEF(CEE_CLT, "clt", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x04, NEXT) OPDEF(CEE_CLT_UN, "clt.un", Pop1+Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x05, NEXT) OPDEF(CEE_LDFTN, "ldftn", Pop0, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x06, NEXT) OPDEF(CEE_LDVIRTFTN, "ldvirtftn", PopRef, PushI, InlineMethod, IPrimitive, 2, 0xFE, 0x07, NEXT) OPDEF(CEE_UNUSED56, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x08, NEXT) OPDEF(CEE_LDARG, "ldarg", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x09, NEXT) OPDEF(CEE_LDARGA, "ldarga", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0A, NEXT) OPDEF(CEE_STARG, "starg", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0B, NEXT) OPDEF(CEE_LDLOC, "ldloc", Pop0, Push1, InlineVar, IPrimitive, 2, 0xFE, 0x0C, NEXT) OPDEF(CEE_LDLOCA, "ldloca", Pop0, PushI, InlineVar, IPrimitive, 2, 0xFE, 0x0D, NEXT) OPDEF(CEE_STLOC, "stloc", Pop1, Push0, InlineVar, IPrimitive, 2, 0xFE, 0x0E, NEXT) OPDEF(CEE_LOCALLOC, "localloc", PopI, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x0F, NEXT) OPDEF(CEE_UNUSED57, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x10, NEXT) OPDEF(CEE_ENDFILTER, "endfilter", PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x11, RETURN) OPDEF(CEE_UNALIGNED, "unaligned.", Pop0, Push0, ShortInlineI, IPrefix, 2, 0xFE, 0x12, META) OPDEF(CEE_VOLATILE, "volatile.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x13, META) OPDEF(CEE_TAILCALL, "tail.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x14, META) OPDEF(CEE_INITOBJ, "initobj", PopI, Push0, InlineType, IObjModel, 2, 0xFE, 0x15, NEXT) OPDEF(CEE_CONSTRAINED, "constrained.", Pop0, Push0, InlineType, IPrefix, 2, 0xFE, 0x16, META) OPDEF(CEE_CPBLK, "cpblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x17, NEXT) OPDEF(CEE_INITBLK, "initblk", PopI+PopI+PopI, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x18, NEXT) OPDEF(CEE_UNUSED69, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x19, NEXT) OPDEF(CEE_RETHROW, "rethrow", Pop0, Push0, InlineNone, IObjModel, 2, 0xFE, 0x1A, THROW) OPDEF(CEE_UNUSED51, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1B, NEXT) OPDEF(CEE_SIZEOF, "sizeof", Pop0, PushI, InlineType, IPrimitive, 2, 0xFE, 0x1C, NEXT) OPDEF(CEE_REFANYTYPE, "refanytype", Pop1, PushI, InlineNone, IPrimitive, 2, 0xFE, 0x1D, NEXT) OPDEF(CEE_READONLY, "readonly.", Pop0, Push0, InlineNone, IPrefix, 2, 0xFE, 0x1E, META) OPDEF(CEE_UNUSED53, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x1F, NEXT) OPDEF(CEE_UNUSED54, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x20, NEXT) OPDEF(CEE_UNUSED55, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x21, NEXT) OPDEF(CEE_UNUSED70, "unused", Pop0, Push0, InlineNone, IPrimitive, 2, 0xFE, 0x22, NEXT) // These are not real opcodes, but they are handy internally in the EE #ifndef OPDEF_REAL_OPCODES_ONLY OPDEF(CEE_ILLEGAL, "illegal", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) OPDEF(CEE_MACRO_END, "endmac", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) OPDEF(CEE_CODE_LABEL, "codelabel", Pop0, Push0, InlineNone, IInternal, 0, MOOT, MOOT, META) #endif // OPDEF_REAL_OPCODES_ONLY #ifndef OPALIAS #define _OPALIAS_DEFINED_ #define OPALIAS(canonicalName, stringName, realOpcode) #endif OPALIAS(CEE_BRNULL, "brnull", CEE_BRFALSE) OPALIAS(CEE_BRNULL_S, "brnull.s", CEE_BRFALSE_S) OPALIAS(CEE_BRZERO, "brzero", CEE_BRFALSE) OPALIAS(CEE_BRZERO_S, "brzero.s", CEE_BRFALSE_S) OPALIAS(CEE_BRINST, "brinst", CEE_BRTRUE) OPALIAS(CEE_BRINST_S, "brinst.s", CEE_BRTRUE_S) OPALIAS(CEE_LDIND_U8, "ldind.u8", CEE_LDIND_I8) OPALIAS(CEE_LDELEM_U8, "ldelem.u8", CEE_LDELEM_I8) OPALIAS(CEE_LDELEM_ANY, "ldelem.any", CEE_LDELEM) OPALIAS(CEE_STELEM_ANY, "stelem.any", CEE_STELEM) OPALIAS(CEE_LDC_I4_M1x, "ldc.i4.M1", CEE_LDC_I4_M1) OPALIAS(CEE_ENDFAULT, "endfault", CEE_ENDFINALLY) #ifdef _OPALIAS_DEFINED_ #undef OPALIAS #undef _OPALIAS_DEFINED_ #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/openum.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __openum_h__ #define __openum_h__ typedef enum opcode_t { #define OPDEF(c,s,pop,push,args,type,l,s1,s2,ctrl) c, #include "opcode.def" #undef OPDEF CEE_COUNT, /* number of instructions and macros pre-defined */ } OPCODE; typedef enum opcode_format_t { InlineNone = 0, // no inline args InlineVar = 1, // local variable (U2 (U1 if Short on)) InlineI = 2, // an signed integer (I4 (I1 if Short on)) InlineR = 3, // a real number (R8 (R4 if Short on)) InlineBrTarget = 4, // branch target (I4 (I1 if Short on)) InlineI8 = 5, InlineMethod = 6, // method token (U4) InlineField = 7, // field token (U4) InlineType = 8, // type token (U4) InlineString = 9, // string TOKEN (U4) InlineSig = 10, // signature tok (U4) InlineRVA = 11, // ldptr token (U4) InlineTok = 12, // a meta-data token of unknown type (U4) InlineSwitch = 13, // count (U4), pcrel1 (U4) .... pcrelN (U4) InlinePhi = 14, // count (U1), var1 (U2) ... varN (U2) // WATCH OUT we are close to the limit here, if you add // more enumerations you need to change ShortIline definition below // The extended enumeration also encodes the size in the IL stream ShortInline = 16, // if this bit is set, the format is the 'short' format PrimaryMask = (ShortInline-1), // mask these off to get primary enumeration above ShortInlineVar = (ShortInline + InlineVar), ShortInlineI = (ShortInline + InlineI), ShortInlineR = (ShortInline + InlineR), ShortInlineBrTarget = (ShortInline + InlineBrTarget), InlineOpcode = (ShortInline + InlineNone), // This is only used internally. It means the 'opcode' is two byte instead of 1 } OPCODE_FORMAT; #endif /* __openum_h__ */ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/opinfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************/ /* OpInfo.h */ /***************************************************************************/ /* contains OpInfo, a wrapper that allows you to get useful information about IL opcodes, and how to decode them */ /***************************************************************************/ #ifndef OpInfo_h #define OpInfo_h #include "openum.h" // Decribes the flow of control properties of the instruction enum OpFlow { FLOW_META, // not a real instruction FLOW_CALL, // a call instruction FLOW_BRANCH, // unconditional branch, does not fall through FLOW_COND_BRANCH, // may fall through FLOW_PHI, FLOW_THROW, FLOW_BREAK, FLOW_RETURN, FLOW_NEXT, // flows into next instruction (none of the above) }; // These are all the possible arguments for the instruction /****************************************************************************/ union OpArgsVal { __int32 i; __int64 i8; double r; struct { unsigned count; int* targets; // targets are pcrelative displacements (little-endian) } switch_; struct { unsigned count; unsigned short* vars; } phi; }; /***************************************************************************/ // OpInfo parses a il instrution into an opcode, and a arg and updates the IP class OpInfo { public: OpInfo() { data = 0; } OpInfo(OPCODE opCode) { _ASSERTE(opCode < CEE_COUNT); data = &table[opCode]; } // fetch instruction at 'instrPtr, fills in 'args' returns pointer // to next instruction const unsigned char* fetch(const unsigned char* instrPtr, OpArgsVal* args); const char* getName() { return(data->name); } OPCODE_FORMAT getArgsInfo() { return(OPCODE_FORMAT(data->format & PrimaryMask)); } OpFlow getFlow() { return(data->flow); } OPCODE getOpcode() { return((OPCODE) (data-table)); } int getNumPop() { return(data->numPop); } int getNumPush() { return(data->numPush); } private: struct OpInfoData { const char* name; OPCODE_FORMAT format : 8; OpFlow flow : 8; int numPop : 3; // < 0 means depends on instr args int numPush : 3; // < 0 means depends on instr args OPCODE opcode : 10; // This is the same as the index into the table }; static OpInfoData table[]; private: OpInfoData* data; }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/optdefault.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Revert optimizations back to default // #undef FPO_ON #ifdef _MSC_VER #pragma optimize("",on) #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/optsmallperfcritical.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Set optimizations settings for small performance critical methods // #ifdef FPO_ON #error Recursive use of FPO_ON not supported #endif #define FPO_ON 1 #if defined(_MSC_VER) && !defined(_DEBUG) #pragma optimize("t", on) // optimize for speed #if !defined(HOST_AMD64) // 'y' isn't an option on amd64 #pragma optimize("y", on) // omit frame pointer #endif // !defined(TARGET_AMD64) #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/ostype.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include "staticcontract.h" #ifndef WRAPPER_NO_CONTRACT #define WRAPPER_NO_CONTRACT ANNOTATION_WRAPPER #endif #ifndef LIMITED_METHOD_CONTRACT #define LIMITED_METHOD_CONTRACT ANNOTATION_FN_LEAF #endif //***************************************************************************** // Enum to track which version of the OS we are running // Note that Win7 is the minimum supported platform. Any code using // utilcode (which includes the CLR's execution engine) will fail to start // on a pre-Win7 platform. This is enforced by InitRunningOnVersionStatus. //***************************************************************************** typedef enum { RUNNING_ON_STATUS_UNINITED = 0, RUNNING_ON_WIN7 = 1, RUNNING_ON_WIN8 = 2 } RunningOnStatusEnum; extern RunningOnStatusEnum gRunningOnStatus; void InitRunningOnVersionStatus(); //***************************************************************************** // Returns true if you are running on Windows 8 or newer. //***************************************************************************** inline BOOL RunningOnWin8() { WRAPPER_NO_CONTRACT; #if (!defined(HOST_X86) && !defined(HOST_AMD64)) return TRUE; #else if (gRunningOnStatus == RUNNING_ON_STATUS_UNINITED) { InitRunningOnVersionStatus(); } return (gRunningOnStatus >= RUNNING_ON_WIN8) ? TRUE : FALSE; #endif } #ifdef FEATURE_COMINTEROP inline BOOL WinRTSupported() { return RunningOnWin8(); } #endif // FEATURE_COMINTEROP #ifdef HOST_64BIT inline BOOL RunningInWow64() { return FALSE; } #else BOOL RunningInWow64(); #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/outstring.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*****************************************************************/ /* OutString.h */ /*****************************************************************/ /* A simple, lightweight, character output stream, with very few external dependancies (like sprintf ... ) */ /* Date : 2/1/99 */ /*****************************************************************/ #ifndef _OutString_h #define _OutString_h 1 #include "utilcode.h" // for overloaded new #include // for strlen, strcpy /*****************************************************************/ // a light weight character 'output' stream class OutString { public: enum FormatFlags { // used to control printing of numbers none = 0, put0x = 1, // put leading 0x on hexidecimal zeroFill = 2, // zero fill (instead of space fill) }; OutString() : start(0), end(0), cur(0) {} OutString(unsigned initialAlloc) { cur = start = new char[initialAlloc+1]; // for null termination end = &start[initialAlloc]; } ~OutString() { delete [] start; } // shortcut for printing decimal OutString& operator<<(int i) { return(dec(i)); } OutString& operator<<(double d); // FIX make this really unsigned OutString& operator<<(unsigned i) { return(dec(i)); } // prints out the hexidecimal representation OutString& dec(int i, size_t minWidth = 0); // prints out the hexidecimal representation OutString& hex(unsigned i, int minWidth = 0, unsigned flags = none); OutString& hex(unsigned __int64 i, int minWidth = 0, unsigned flags = none); OutString& hex(int i, int minWidth = 0, unsigned flags = none) { return hex(unsigned(i), minWidth, flags); } OutString& hex(__int64 i, int minWidth = 0, unsigned flags = none) { return hex((unsigned __int64) i, minWidth, flags); } // print out 'count' instances of the character 'c' OutString& pad(size_t count, char c); OutString& operator<<(char c) { if (cur >= end) Realloc(1); *cur++ = c; _ASSERTE(start <= cur && cur <= end); return(*this); } OutString& operator<<(const WCHAR* str) { size_t len = wcslen(str); if (cur+len > end) Realloc(len); while(str != 0) *cur++ = (char) *str++; _ASSERTE(start <= cur && cur <= end); return(*this); } OutString& prepend(const char c) { char buff[2]; buff[0] = c; buff[1] = 0; return(prepend(buff)); } OutString& prepend(const char* str) { size_t len = strlen(str); if (cur+len > end) Realloc(len); memmove(start+len, start, cur-start); memcpy(start, str, len); cur = cur + len; _ASSERTE(start <= cur && cur <= end); return(*this); } OutString& operator=(const OutString& str) { clear(); *this << str; return(*this); } OutString& operator<<(const OutString& str) { write(str.start, str.cur-str.start); return(*this); } OutString& operator<<(const char* str) { write(str, strlen(str)); return(*this); } void write(const char* str, size_t len) { if (cur+len > end) Realloc(len); memcpy(cur, str, len); cur = cur + len; _ASSERTE(start <= cur && cur <= end); } void swap(OutString& str) { char* tmp = start; start = str.start; str.start = tmp; tmp = end; end = str.end; str.end = tmp; tmp = cur; cur = str.cur; str.cur = tmp; _ASSERTE(start <= cur && cur <= end); } void clear() { cur = start; } size_t length() const { return(cur-start); } // return the null terminated string, OutString keeps ownership const char* val() const { *cur = 0; return(start); } // grab string (caller must now delete) OutString is cleared char* grab() { char* ret = start; *cur = 0; end = cur = start = 0; return(ret); } private: void Realloc(size_t neededSpace); char *start; // start of the buffer char *end; // points at the last place null terminator can go char *cur; // points at a null terminator }; #endif // _OutString_h ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/palclr.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== // File: palclr.h // // Various macros and constants that are necessary to make the CLR portable. // // =========================================================================== #if defined(HOST_WINDOWS) #ifndef __PALCLR_H__ #define __PALCLR_H__ // This macro is used to standardize the wide character string literals between UNIX and Windows. // Unix L"" is UTF32, and on windows it's UTF16. Because of built-in assumptions on the size // of string literals, it's important to match behaviour between Unix and Windows. Unix will be defined // as u"" (char16_t) #define W(str) L##str #include #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif #if __GNUC__ #ifndef __cdecl #define __cdecl __attribute__((__cdecl__)) #endif #endif #ifndef NOTHROW_DECL #ifdef _MSC_VER #define NOTHROW_DECL __declspec(nothrow) #else #define NOTHROW_DECL __attribute__((nothrow)) #endif // !_MSC_VER #endif // !NOTHROW_DECL #ifndef NOINLINE #ifdef _MSC_VER #define NOINLINE __declspec(noinline) #else #define NOINLINE __attribute__((noinline)) #endif // !_MSC_VER #endif // !NOINLINE #define ANALYZER_NORETURN #ifdef _MSC_VER #define EMPTY_BASES_DECL __declspec(empty_bases) #else #define EMPTY_BASES_DECL #endif // !_MSC_VER // // CPP_ASSERT() can be used within a class definition, to perform a // compile-time assertion involving private names within the class. // // MS compiler doesn't allow redefinition of the typedef within a template. // gcc doesn't allow redefinition of the typedef within a class, though // it does at file scope. #define CPP_ASSERT(n, e) typedef char __C_ASSERT__##n[(e) ? 1 : -1]; // PORTABILITY_ASSERT and PORTABILITY_WARNING macros are meant to be used to // mark places in the code that needs attention for portability. The usual // usage pattern is: // // int get_scratch_register() { // #if defined(TARGET_X86) // return eax; // #elif defined(TARGET_AMD64) // return rax; // #elif defined(TARGET_ARM) // return r0; // #else // PORTABILITY_ASSERT("scratch register"); // return 0; // #endif // } // // PORTABILITY_ASSERT is meant to be used inside functions/methods. It can // introduce compile-time and/or run-time errors. // PORTABILITY_WARNING is meant to be used outside functions/methods. It can // introduce compile-time errors or warnings only. // // People starting new ports will first define these to just cause run-time // errors. Once they fix all the places that need attention for portability, // they can define PORTABILITY_ASSERT and PORTABILITY_WARNING to cause // compile-time errors to make sure that they haven't missed anything. // // If it is reasonably possible all codepaths containing PORTABILITY_ASSERT // should be compilable (e.g. functions should return NULL or something if // they are expected to return a value). // // The message in these two macros should not contain any keywords like TODO // or NYI. It should be just the brief description of the problem. #if defined(TARGET_X86) // Finished ports - compile-time errors #define PORTABILITY_WARNING(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) #define PORTABILITY_ASSERT(message) NEED_TO_PORT_THIS_ONE(NEED_TO_PORT_THIS_ONE) #else // Ports in progress - run-time asserts only #define PORTABILITY_WARNING(message) #define PORTABILITY_ASSERT(message) _ASSERTE(false && (message)) #endif #define DIRECTORY_SEPARATOR_CHAR_A '\\' #define DIRECTORY_SEPARATOR_STR_A "\\" #define DIRECTORY_SEPARATOR_CHAR_W W('\\') #define DIRECTORY_SEPARATOR_STR_W W("\\") #define PATH_SEPARATOR_CHAR_W W(';') #define PATH_SEPARATOR_STR_W W(";") #define VOLUME_SEPARATOR_CHAR_W W(':') // PAL Macros // Not all compilers support fully anonymous aggregate types, so the // PAL provides names for those types. To allow existing definitions of // those types to continue to work, we provide macros that should be // used to reference fields within those types. #ifndef DECIMAL_SCALE #define DECIMAL_SCALE(dec) ((dec).scale) #endif #ifndef DECIMAL_SIGN #define DECIMAL_SIGN(dec) ((dec).sign) #endif #ifndef DECIMAL_SIGNSCALE #define DECIMAL_SIGNSCALE(dec) ((dec).signscale) #endif #ifndef DECIMAL_LO32 #define DECIMAL_LO32(dec) ((dec).Lo32) #endif #ifndef DECIMAL_MID32 #define DECIMAL_MID32(dec) ((dec).Mid32) #endif #ifndef DECIMAL_HI32 #define DECIMAL_HI32(dec) ((dec).Hi32) #endif #ifndef DECIMAL_LO64_GET #define DECIMAL_LO64_GET(dec) ((dec).Lo64) #endif #ifndef DECIMAL_LO64_SET #define DECIMAL_LO64_SET(dec,value) {(dec).Lo64 = value; } #endif #ifndef IMAGE_RELOC_FIELD #define IMAGE_RELOC_FIELD(img, f) ((img).f) #endif #ifndef IMAGE_IMPORT_DESC_FIELD #define IMAGE_IMPORT_DESC_FIELD(img, f) ((img).f) #endif #define IMAGE_RDE_ID(img) ((img)->Id) #define IMAGE_RDE_NAME(img) ((img)->Name) #define IMAGE_RDE_OFFSET(img) ((img)->OffsetToData) #ifndef IMAGE_RDE_NAME_FIELD #define IMAGE_RDE_NAME_FIELD(img, f) ((img)->f) #endif #define IMAGE_RDE_OFFSET_FIELD(img, f) ((img)->f) #ifndef IMAGE_FE64_FIELD #define IMAGE_FE64_FIELD(img, f) ((img).f) #endif #ifndef IMPORT_OBJ_HEADER_FIELD #define IMPORT_OBJ_HEADER_FIELD(obj, f) ((obj).f) #endif #ifndef IMAGE_COR20_HEADER_FIELD #define IMAGE_COR20_HEADER_FIELD(obj, f) ((obj).f) #endif // PAL Numbers // Used to ensure cross-compiler compatibility when declaring large // integer constants. 64-bit integer constants should be wrapped in the // declarations listed here. // // Each of the #defines here is wrapped to avoid conflicts with pal.h. #if defined(_MSC_VER) // MSVC's way of declaring large integer constants // If you define these in one step, without the _HELPER macros, you // get extra whitespace when composing these with other concatenating macros. #ifndef I64 #define I64_HELPER(x) x ## i64 #define I64(x) I64_HELPER(x) #endif #ifndef UI64 #define UI64_HELPER(x) x ## ui64 #define UI64(x) UI64_HELPER(x) #endif #else // GCC's way of declaring large integer constants // If you define these in one step, without the _HELPER macros, you // get extra whitespace when composing these with other concatenating macros. #ifndef I64 #define I64_HELPER(x) x ## LL #define I64(x) I64_HELPER(x) #endif #ifndef UI64 #define UI64_HELPER(x) x ## ULL #define UI64(x) UI64_HELPER(x) #endif #endif // PAL SEH // Macros for portable exception handling. The Win32 SEH is emulated using // these macros and setjmp/longjmp on Unix // // Usage notes: // // - The filter has to be a function taking two parameters: // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) // // - It is not possible to directly use the local variables in the filter. // All the local information that the filter has to need to know about should // be passed through pv parameter // // - Do not use goto to jump out of the PAL_TRY block // (jumping out of the try block is not a good idea even on Win32, because of // it causes stack unwind) // // - It is not possible to directly use the local variables in the try block. // All the local information that the filter has to need to know about should // be passed through pv parameter // // // Simple examples: // // struct Param { ... local variables used in try block and filter ... } param; // PAL_TRY(Param *, pParam, ¶m) { // read as: Param *pParam = ¶m; // .... // } PAL_FINALLY { // .... // } // PAL_ENDTRY // // // struct Param { ... local variables used in try block and filter ... } param; // PAL_TRY(Param *, pParam, ¶m) { // .... // } PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { // .... // } // PAL_ENDTRY // // // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) // { // ... // } // PAL_TRY(void *, unused, NULL) { // .... // } PAL_EXCEPT_FILTER(MyFilter) { // .... // } // PAL_ENDTRY // // // Complex example: // // struct MyParams // { // ... // } params; // // PAL_TRY(MyParams *, pMyParamsOuter, ¶ms) { // PAL_TRY(MyParams *, pMyParamsInnter, pMyParamsOuter) { // ... // if (error) goto Done; // ... // Done: ; // } PAL_EXCEPT_FILTER(OtherFilter) { // ... // } // PAL_ENDTRY // } // PAL_FINALLY { // } // PAL_ENDTRY // #include "staticcontract.h" #define HardwareExceptionHolder // Note: PAL_SEH_RESTORE_GUARD_PAGE is only ever defined in clrex.h, so we only restore guard pages automatically // when these macros are used from within the VM. #define PAL_SEH_RESTORE_GUARD_PAGE #define PAL_TRY_NAKED \ { \ bool __exHandled; __exHandled = false; \ DWORD __exCode; __exCode = 0; \ SCAN_EHMARKER(); \ __try \ { \ SCAN_EHMARKER_TRY(); #define PAL_EXCEPT_NAKED(Disposition) \ } \ __except(__exCode = GetExceptionCode(), Disposition) \ { \ __exHandled = true; \ SCAN_EHMARKER_CATCH(); \ PAL_SEH_RESTORE_GUARD_PAGE #define PAL_EXCEPT_FILTER_NAKED(pfnFilter, param) \ } \ __except(__exCode = GetExceptionCode(), \ pfnFilter(GetExceptionInformation(), param)) \ { \ __exHandled = true; \ SCAN_EHMARKER_CATCH(); \ PAL_SEH_RESTORE_GUARD_PAGE #define PAL_FINALLY_NAKED \ } \ __finally \ { \ #define PAL_ENDTRY_NAKED \ } \ PAL_ENDTRY_NAKED_DBG \ } \ #if defined(_DEBUG) && !defined(DACCESS_COMPILE) // // In debug mode, compile the try body as a method of a local class. // This way, the compiler will check that the body is not directly // accessing any local variables and arguments. // #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ { \ __ParamType __param = __paramRef; \ __ParamType __paramToPassToFilter = __paramRef; \ class __Body \ { \ public: \ static void Run(__ParamType __paramDef) \ { \ PAL_TRY_HANDLER_DBG_BEGIN // PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by // JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods // as on PAL. #define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) \ { \ struct __HandlerData { \ __ParamType __param; \ COMPILER_INSTANCE *__ciPtr; \ }; \ __HandlerData handlerData; \ handlerData.__param = __paramRef; \ handlerData.__ciPtr = ciPtr; \ __HandlerData* __param = &handlerData; \ __ParamType __paramToPassToFilter = __paramRef; \ class __Body \ { \ public: \ static void Run(__HandlerData* __pHandlerData) \ { \ PAL_TRY_HANDLER_DBG_BEGIN \ COMPILER_INSTANCE *ciPtr = __pHandlerData->__ciPtr; \ __ParamType __paramDef = __pHandlerData->__param; #define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ { \ __ParamType __param = __paramRef; \ __ParamType __paramToPassToFilter = __paramRef; \ class __Body \ { \ public: \ static void Run(__ParamType __paramDef) \ { \ PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) #define PAL_EXCEPT(Disposition) \ PAL_TRY_HANDLER_DBG_END \ } \ }; \ PAL_TRY_NAKED \ __Body::Run(__param); \ PAL_EXCEPT_NAKED(Disposition) #define PAL_EXCEPT_FILTER(pfnFilter) \ PAL_TRY_HANDLER_DBG_END \ } \ }; \ PAL_TRY_NAKED \ __Body::Run(__param); \ PAL_EXCEPT_FILTER_NAKED(pfnFilter, __paramToPassToFilter) #define PAL_FINALLY \ PAL_TRY_HANDLER_DBG_END \ } \ }; \ PAL_TRY_NAKED \ __Body::Run(__param); \ PAL_FINALLY_NAKED #define PAL_ENDTRY \ PAL_ENDTRY_NAKED \ } #else // _DEBUG #define PAL_TRY(__ParamType, __paramDef, __paramRef) \ { \ __ParamType __param = __paramRef; \ __ParamType __paramDef = __param; \ PAL_TRY_NAKED \ PAL_TRY_HANDLER_DBG_BEGIN // PAL_TRY implementation that abstracts usage of COMPILER_INSTANCE*, which is used by // JIT64. On Windows, we dont need to do anything special as we dont have nested classes/methods // as on PAL. #define PAL_TRY_CI(__ParamType, __paramDef, __paramRef) PAL_TRY(__ParamType, __paramDef, __paramRef) #define PAL_TRY_FOR_DLLMAIN(__ParamType, __paramDef, __paramRef, __reason) \ { \ __ParamType __param = __paramRef; \ __ParamType __paramDef; __paramDef = __param; \ PAL_TRY_NAKED \ PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(__reason) #define PAL_EXCEPT(Disposition) \ PAL_TRY_HANDLER_DBG_END \ PAL_EXCEPT_NAKED(Disposition) #define PAL_EXCEPT_FILTER(pfnFilter) \ PAL_TRY_HANDLER_DBG_END \ PAL_EXCEPT_FILTER_NAKED(pfnFilter, __param) #define PAL_FINALLY \ PAL_TRY_HANDLER_DBG_END \ PAL_FINALLY_NAKED #define PAL_ENDTRY \ PAL_ENDTRY_NAKED \ } #endif // _DEBUG // Executes the handler if the specified exception code matches // the one in the exception. Otherwise, returns EXCEPTION_CONTINUE_SEARCH. #define PAL_EXCEPT_IF_EXCEPTION_CODE(dwExceptionCode) PAL_EXCEPT((GetExceptionCode() == (dwExceptionCode))?EXCEPTION_EXECUTE_HANDLER:EXCEPTION_CONTINUE_SEARCH) #define PAL_CPP_TRY try #define PAL_CPP_ENDTRY #define PAL_CPP_THROW(type, obj) do { SCAN_THROW_MARKER; throw obj; } while (false) #define PAL_CPP_RETHROW do { SCAN_THROW_MARKER; throw; } while (false) #define PAL_CPP_CATCH_DERIVED(type, obj) catch (type * obj) #define PAL_CPP_CATCH_ALL catch (...) #define PAL_CPP_CATCH_EXCEPTION_NOARG catch (Exception *) #if defined(SOURCE_FORMATTING) #define __annotation(x) #endif #if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(CROSS_COMPILE) && !defined(DISABLE_CONTRACTS) #define PAL_TRY_HANDLER_DBG_BEGIN \ BOOL ___oldOkayToThrowValue = FALSE; \ ClrDebugState *___pState = ::GetClrDebugState(); \ __try \ { \ ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ ___pState->SetOkToThrow(); // Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ BOOL ___oldOkayToThrowValue = FALSE; \ ClrDebugState *___pState = NULL; \ if (_reason != DLL_PROCESS_ATTACH) \ ___pState = CheckClrDebugState(); \ __try \ { \ if (___pState) \ { \ ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ ___pState->SetOkToThrow(); \ } \ if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ { \ ___pState = NULL; \ } #define PAL_TRY_HANDLER_DBG_END \ } \ __finally \ { \ if (___pState != NULL) \ { \ _ASSERTE(___pState == CheckClrDebugState()); \ ___pState->SetOkToThrow( ___oldOkayToThrowValue ); \ } \ } #define PAL_ENDTRY_NAKED_DBG #else #define PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; #define PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; #define PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; #define PAL_ENDTRY_NAKED_DBG #endif // defined(ENABLE_CONTRACTS_IMPL) #if !BIGENDIAN // For little-endian machines, do nothing #define VAL16(x) x #define VAL32(x) x #define VAL64(x) x #define SwapString(x) #define SwapStringLength(x, y) #define SwapGuid(x) #endif // !BIGENDIAN #ifdef _MSC_VER // Get Unaligned values from a potentially unaligned object #define GET_UNALIGNED_16(_pObject) (*(UINT16 UNALIGNED *)(_pObject)) #define GET_UNALIGNED_32(_pObject) (*(UINT32 UNALIGNED *)(_pObject)) #define GET_UNALIGNED_64(_pObject) (*(UINT64 UNALIGNED *)(_pObject)) // Set Value on an potentially unaligned object #define SET_UNALIGNED_16(_pObject, _Value) (*(UNALIGNED UINT16 *)(_pObject)) = (UINT16)(_Value) #define SET_UNALIGNED_32(_pObject, _Value) (*(UNALIGNED UINT32 *)(_pObject)) = (UINT32)(_Value) #define SET_UNALIGNED_64(_pObject, _Value) (*(UNALIGNED UINT64 *)(_pObject)) = (UINT64)(_Value) // Get Unaligned values from a potentially unaligned object and swap the value #define GET_UNALIGNED_VAL16(_pObject) VAL16(GET_UNALIGNED_16(_pObject)) #define GET_UNALIGNED_VAL32(_pObject) VAL32(GET_UNALIGNED_32(_pObject)) #define GET_UNALIGNED_VAL64(_pObject) VAL64(GET_UNALIGNED_64(_pObject)) // Set a swap Value on an potentially unaligned object #define SET_UNALIGNED_VAL16(_pObject, _Value) SET_UNALIGNED_16(_pObject, VAL16((UINT16)_Value)) #define SET_UNALIGNED_VAL32(_pObject, _Value) SET_UNALIGNED_32(_pObject, VAL32((UINT32)_Value)) #define SET_UNALIGNED_VAL64(_pObject, _Value) SET_UNALIGNED_64(_pObject, VAL64((UINT64)_Value)) #endif #ifdef HOST_64BIT #define VALPTR(x) VAL64(x) #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_64(x) #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL64(x) #define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_64(p,x) #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL64(p,x) #else #define VALPTR(x) VAL32(x) #define GET_UNALIGNED_PTR(x) GET_UNALIGNED_32(x) #define GET_UNALIGNED_VALPTR(x) GET_UNALIGNED_VAL32(x) #define SET_UNALIGNED_PTR(p,x) SET_UNALIGNED_32(p,x) #define SET_UNALIGNED_VALPTR(p,x) SET_UNALIGNED_VAL32(p,x) #endif #define MAKEDLLNAME_W(name) name W(".dll") #define MAKEDLLNAME_A(name) name ".dll" #ifdef UNICODE #define MAKEDLLNAME(x) MAKEDLLNAME_W(x) #else #define MAKEDLLNAME(x) MAKEDLLNAME_A(x) #endif #if !defined(MAX_LONGPATH) #define MAX_LONGPATH 260 /* max. length of full pathname */ #endif #if !defined(MAX_PATH_FNAME) #define MAX_PATH_FNAME MAX_PATH /* max. length of full pathname */ #endif #define __clr_reserved __reserved #endif // __PALCLR_H__ #include "palclr_win.h" #ifndef IMAGE_FILE_MACHINE_LOONGARCH64 #define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 // LOONGARCH64. #endif #endif // defined(HOST_WINDOWS) ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/palclr_win.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== // File: palclr.h // // Various macros and constants that are necessary to make the CLR portable. // // =========================================================================== #ifndef __PALCLR_WIN_H__ #define __PALCLR_WIN_H__ // PAL SEH // Macros for portable exception handling. The Win32 SEH is emulated using // these macros and setjmp/longjmp on Unix // // Usage notes: // // - The filter has to be a function taking two parameters: // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) // // - It is not possible to directly use the local variables in the filter. // All the local information that the filter has to need to know about should // be passed through pv parameter // // - Do not use goto to jump out of the PAL_TRY block // (jumping out of the try block is not a good idea even on Win32, because of // it causes stack unwind) // // // Simple examples: // // PAL_TRY { // .... // } WIN_PAL_FINALLY { // .... // } // WIN_PAL_ENDTRY // // // PAL_TRY { // .... // } WIN_PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { // .... // } // WIN_PAL_ENDTRY // // // LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) // { // ... // } // PAL_TRY { // .... // } WIN_PAL_EXCEPT_FILTER(MyFilter, NULL) { // .... // } // WIN_PAL_ENDTRY // // // Complex example: // // struct MyParams // { // ... // } params; // // PAL_TRY { // PAL_TRY { // ... // if (error) goto Done; // ... // Done: ; // } WIN_PAL_EXCEPT_FILTER(OtherFilter, ¶ms) { // ... // } // WIN_PAL_ENDTRY // } // WIN_PAL_FINALLY { // } // WIN_PAL_ENDTRY // #if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(HOST_ARM) // @ARMTODO #define WIN_PAL_TRY_HANDLER_DBG_BEGIN \ BOOL ___oldOkayToThrowValue = FALSE; \ ClrDebugState *___pState = GetClrDebugState(); \ __try \ { \ ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ ___pState->SetOkToThrow(TRUE); \ ANNOTATION_TRY_BEGIN; // Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. #define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ BOOL ___oldOkayToThrowValue = FALSE; \ BOOL ___oldSOTolerantState = FALSE; \ ClrDebugState *___pState = CheckClrDebugState(); \ __try \ { \ if (___pState) \ { \ ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ ___pState->SetOkToThrow(TRUE); \ } \ if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ { \ ___pState = NULL; \ } \ ANNOTATION_TRY_BEGIN; #define WIN_PAL_TRY_HANDLER_DBG_END \ ANNOTATION_TRY_END; \ } \ __finally \ { \ if (___pState != NULL) \ { \ _ASSERTE(___pState == CheckClrDebugState()); \ ___pState->SetOkToThrow(___oldOkayToThrowValue); \ ___pState->SetSOTolerance(___oldSOTolerantState); \ } \ } #define WIN_PAL_ENDTRY_NAKED_DBG #else #define WIN_PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; #define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; #define WIN_PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; #define WIN_PAL_ENDTRY_NAKED_DBG #endif // defined(ENABLE_CONTRACTS_IMPL) #if defined(HOST_WINDOWS) // Native system libray handle. // In Windows, NATIVE_LIBRARY_HANDLE is the same as HMODULE. typedef HMODULE NATIVE_LIBRARY_HANDLE; #endif // HOST_WINDOWS #ifndef FALLTHROUGH #define FALLTHROUGH __fallthrough #endif // FALLTHROUGH #endif // __PALCLR_WIN_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/patchpointinfo.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- // patchpointinfo.h // -------------------------------------------------------------------------------- #include #ifndef _PATCHPOINTINFO_H_ #define _PATCHPOINTINFO_H_ // -------------------------------------------------------------------------------- // Describes information needed to make an OSR transition // - location of IL-visible locals and other important state on the // original (Tier0) method frame, with respect to top of frame // (hence these offsets will be negative as stack grows down) // - total size of the original frame // - callee save registers saved on the original (Tier0) frame // // Currently the patchpoint info is independent of the IL offset of the patchpoint. // // This data is produced when jitting a Tier0 method with OSR enabled, and consumed // by the Tier1/OSR jit request. // struct PatchpointInfo { // Determine how much storage is needed to hold this info static unsigned ComputeSize(unsigned localCount) { unsigned baseSize = sizeof(PatchpointInfo); unsigned variableSize = localCount * sizeof(int); unsigned totalSize = baseSize + variableSize; return totalSize; } // Initialize void Initialize(unsigned localCount, int totalFrameSize) { m_calleeSaveRegisters = 0; m_totalFrameSize = totalFrameSize; m_numberOfLocals = localCount; m_genericContextArgOffset = -1; m_keptAliveThisOffset = -1; m_securityCookieOffset = -1; m_monitorAcquiredOffset = -1; } // Copy void Copy(const PatchpointInfo* original) { m_calleeSaveRegisters = original->m_calleeSaveRegisters; m_genericContextArgOffset = original->m_genericContextArgOffset; m_keptAliveThisOffset = original->m_keptAliveThisOffset; m_securityCookieOffset = original->m_securityCookieOffset; m_monitorAcquiredOffset = original->m_monitorAcquiredOffset; for (unsigned i = 0; i < original->m_numberOfLocals; i++) { m_offsetAndExposureData[i] = original->m_offsetAndExposureData[i]; } } // Total size of this patchpoint info record, in bytes unsigned PatchpointInfoSize() const { return ComputeSize(m_numberOfLocals); } // Total frame size of the original method int TotalFrameSize() const { return m_totalFrameSize; } // Number of locals in the original method (including special locals) unsigned NumberOfLocals() const { return m_numberOfLocals; } // Original method caller SP offset for generic context arg int GenericContextArgOffset() const { return m_genericContextArgOffset; } bool HasGenericContextArgOffset() const { return m_genericContextArgOffset != -1; } void SetGenericContextArgOffset(int offset) { m_genericContextArgOffset = offset; } // Original method FP relative offset for kept-alive this int KeptAliveThisOffset() const { return m_keptAliveThisOffset; } bool HasKeptAliveThis() const { return m_keptAliveThisOffset != -1; } void SetKeptAliveThisOffset(int offset) { m_keptAliveThisOffset = offset; } // Original method FP relative offset for security cookie int SecurityCookieOffset() const { return m_securityCookieOffset; } bool HasSecurityCookie() const { return m_securityCookieOffset != -1; } void SetSecurityCookieOffset(int offset) { m_securityCookieOffset = offset; } // Original method FP relative offset for monitor acquired flag int MonitorAcquiredOffset() const { return m_monitorAcquiredOffset; } bool HasMonitorAcquired() const { return m_monitorAcquiredOffset != -1; } void SetMonitorAcquiredOffset(int offset) { m_monitorAcquiredOffset = offset; } // True if this local was address exposed in the original method bool IsExposed(unsigned localNum) const { return ((m_offsetAndExposureData[localNum] & EXPOSURE_MASK) != 0); } // FP relative offset of this local in the original method int Offset(unsigned localNum) const { return (m_offsetAndExposureData[localNum] >> OFFSET_SHIFT); } void SetOffsetAndExposure(unsigned localNum, int offset, bool isExposed) { m_offsetAndExposureData[localNum] = (offset << OFFSET_SHIFT) | (isExposed ? EXPOSURE_MASK : 0); } // Callee save registers saved by the original method. // Includes all saves that must be restored (eg includes pushed RBP on x64). // uint64_t CalleeSaveRegisters() const { return m_calleeSaveRegisters; } void SetCalleeSaveRegisters(uint64_t registerMask) { m_calleeSaveRegisters = registerMask; } private: enum { OFFSET_SHIFT = 0x1, EXPOSURE_MASK = 0x1 }; uint64_t m_calleeSaveRegisters; unsigned m_numberOfLocals; int m_totalFrameSize; int m_genericContextArgOffset; int m_keptAliveThisOffset; int m_securityCookieOffset; int m_monitorAcquiredOffset; int m_offsetAndExposureData[]; }; typedef DPTR(struct PatchpointInfo) PTR_PatchpointInfo; #endif // _PATCHPOINTINFO_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/pedecoder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- // PEDecoder.h // // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // PEDecoder - Utility class for reading and verifying PE files. // // Note that the Check step is optional if you are willing to trust the // integrity of the image. // (Or at any rate can be factored into an initial verification step.) // // Functions which access the memory of the PE file take a "flat" flag - this // indicates whether the PE images data has been loaded flat the way it resides in the file, // or if the sections have been mapped into memory at the proper base addresses. // // Finally, some functions take an optional "size" argument, which can be used for // range verification. This is an optional parameter, but if you omit it be sure // you verify the size in some other way. // -------------------------------------------------------------------------------- #ifndef PEDECODER_H_ #define PEDECODER_H_ // -------------------------------------------------------------------------------- // Required headers // -------------------------------------------------------------------------------- #include "windows.h" #include "clrtypes.h" #include "check.h" #include "contract.h" #include "cor.h" #include "corhdr.h" #include "corcompile.h" #include "readytorun.h" typedef DPTR(struct READYTORUN_CORE_HEADER) PTR_READYTORUN_CORE_HEADER; typedef DPTR(struct READYTORUN_HEADER) PTR_READYTORUN_HEADER; typedef DPTR(struct READYTORUN_SECTION) PTR_READYTORUN_SECTION; typedef DPTR(IMAGE_COR20_HEADER) PTR_IMAGE_COR20_HEADER; // -------------------------------------------------------------------------------- // Forward declared types // -------------------------------------------------------------------------------- class Module; // -------------------------------------------------------------------------------- // RVA definition // -------------------------------------------------------------------------------- // Needs to be DWORD to avoid conflict with typedef DWORD RVA; #ifdef _MSC_VER // Wrapper to suppress ambiguous overload problems with MSVC. inline CHECK CheckOverflow(RVA value1, COUNT_T value2) { WRAPPER_NO_CONTRACT; CHECK(CheckOverflow((UINT32) value1, (UINT32) value2)); CHECK_OK; } #endif // _MSC_VER // -------------------------------------------------------------------------------- // IMAGE_FILE_MACHINE_NATIVE // -------------------------------------------------------------------------------- #if defined(TARGET_X86) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_I386 #elif defined(TARGET_AMD64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_AMD64 #elif defined(TARGET_ARM) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARMNT #elif defined(TARGET_ARM64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_ARM64 #elif defined(TARGET_LOONGARCH64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_LOONGARCH64 #elif defined(TARGET_POWERPC64) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_POWERPC #elif defined(TARGET_S390X) #define IMAGE_FILE_MACHINE_NATIVE IMAGE_FILE_MACHINE_UNKNOWN #else #error "port me" #endif // Machine code for native images #if defined(__APPLE__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x4644 #elif defined(__FreeBSD__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0xADC4 #elif defined(__linux__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x7B79 #elif defined(__NetBSD__) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1993 #elif defined(__sun) #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0x1992 #else #define IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE 0 #endif #define IMAGE_FILE_MACHINE_NATIVE_NI (IMAGE_FILE_MACHINE_NATIVE ^ IMAGE_FILE_MACHINE_NATIVE_OS_OVERRIDE) // -------------------------------------------------------------------------------- // Types // -------------------------------------------------------------------------------- typedef DPTR(class PEDecoder) PTR_PEDecoder; typedef bool (*PEDecoder_ResourceTypesCallbackFunction)(LPCWSTR lpType, void* context); typedef bool (*PEDecoder_ResourceNamesCallbackFunction)(LPCWSTR lpName, LPCWSTR lpType, void* context); typedef bool (*PEDecoder_ResourceCallbackFunction)(LPCWSTR lpName, LPCWSTR lpType, DWORD langid, BYTE* data, COUNT_T cbData, void* context); class PEDecoder { public: // ------------------------------------------------------------ // Public API // ------------------------------------------------------------ // Access functions are divided into 3 categories: // Has - check if the element is present // Check - Do consistency checks on the element (requires Has). // This step is optional if you are willing to trust the integrity of the // image. (It is asserted in a checked build.) // Get - Access the element (requires Has and Check) PEDecoder(); PEDecoder(void *flatBase, COUNT_T size); // flatBase is the raw disk layout data (using MapViewOfFile) PEDecoder(PTR_VOID mappedBase, bool relocated = FALSE); // mappedBase is the mapped/expanded file (using LoadLibrary) void Init(void *flatBase, COUNT_T size); HRESULT Init(void *mappedBase, bool relocated = FALSE); void Reset(); //make sure you don't have a thread race PTR_VOID GetBase() const; // Currently loaded base, as opposed to GetPreferredBase() BOOL IsMapped() const; BOOL IsRelocated() const; BOOL IsFlat() const; BOOL HasContents() const; COUNT_T GetSize() const; // size of file on disk, as opposed to GetVirtualSize() // High level image checks: CHECK CheckFormat() const; // Check whatever is present CHECK CheckNTFormat() const; // Check a PE file image CHECK CheckCORFormat() const; // Check a COR image (IL or native) CHECK CheckILFormat() const; // Check a managed image CHECK CheckILOnlyFormat() const; // Check an IL only image // NT header access BOOL HasNTHeaders() const; CHECK CheckNTHeaders() const; IMAGE_NT_HEADERS32 *GetNTHeaders32() const; IMAGE_NT_HEADERS64 *GetNTHeaders64() const; BOOL Has32BitNTHeaders() const; const void *GetHeaders(COUNT_T *pSize = NULL) const; BOOL IsDll() const; BOOL HasBaseRelocations() const; const void *GetPreferredBase() const; // OptionalHeaders.ImageBase COUNT_T GetVirtualSize() const; // OptionalHeaders.SizeOfImage - size of mapped/expanded image in memory WORD GetSubsystem() const; WORD GetDllCharacteristics() const; DWORD GetTimeDateStamp() const; DWORD GetCheckSum() const; WORD GetMachine() const; WORD GetCharacteristics() const; DWORD GetFileAlignment() const; DWORD GetSectionAlignment() const; SIZE_T GetSizeOfStackReserve() const; SIZE_T GetSizeOfStackCommit() const; SIZE_T GetSizeOfHeapReserve() const; SIZE_T GetSizeOfHeapCommit() const; UINT32 GetLoaderFlags() const; UINT32 GetWin32VersionValue() const; COUNT_T GetNumberOfRvaAndSizes() const; COUNT_T GetNumberOfSections() const; PTR_IMAGE_SECTION_HEADER FindFirstSection() const; IMAGE_SECTION_HEADER *FindSection(LPCSTR sectionName) const; DWORD GetImageIdentity() const; BOOL HasWriteableSections() const; // Directory entry access BOOL HasDirectoryEntry(int entry) const; CHECK CheckDirectoryEntry(int entry, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const; IMAGE_DATA_DIRECTORY *GetDirectoryEntry(int entry) const; TADDR GetDirectoryEntryData(int entry, COUNT_T *pSize = NULL) const; // IMAGE_DATA_DIRECTORY access CHECK CheckDirectory(IMAGE_DATA_DIRECTORY *pDir, int forbiddenFlags = 0, IsNullOK ok = NULL_NOT_OK) const; TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const; TADDR GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const; // Basic RVA access CHECK CheckRva(RVA rva, IsNullOK ok = NULL_NOT_OK) const; CHECK CheckRva(RVA rva, COUNT_T size, int forbiddenFlags=0, IsNullOK ok = NULL_NOT_OK) const; TADDR GetRvaData(RVA rva, IsNullOK ok = NULL_NOT_OK) const; // Called with ok=NULL_OK only for mapped fields (RVA statics) CHECK CheckData(const void *data, IsNullOK ok = NULL_NOT_OK) const; CHECK CheckData(const void *data, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const; RVA GetDataRva(const TADDR data) const; BOOL PointerInPE(PTR_CVOID data) const; // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress CHECK CheckOffset(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const; CHECK CheckOffset(COUNT_T fileOffset, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const; TADDR GetOffsetData(COUNT_T fileOffset, IsNullOK ok = NULL_NOT_OK) const; // Called with ok=NULL_OK only for mapped fields (RVA statics) // Mapping between RVA and file offsets COUNT_T RvaToOffset(RVA rva) const; RVA OffsetToRva(COUNT_T fileOffset) const; // Base intra-image pointer access // (These are for pointers retrieved out of the PE image) CHECK CheckInternalAddress(SIZE_T address, IsNullOK ok = NULL_NOT_OK) const; CHECK CheckInternalAddress(SIZE_T address, COUNT_T size, IsNullOK ok = NULL_NOT_OK) const; TADDR GetInternalAddressData(SIZE_T address) const; // CLR loader IL Image verification - these checks apply to IL_ONLY images. BOOL IsILOnly() const; CHECK CheckILOnly() const; // Strong name & hashing support BOOL HasStrongNameSignature() const; CHECK CheckStrongNameSignature() const; PTR_CVOID GetStrongNameSignature(COUNT_T *pSize = NULL) const; // CorHeader flag support // IsStrongNameSigned indicates whether the signature has been filled in. // (otherwise if it has a signature it is delay signed.) BOOL IsStrongNameSigned() const; // TRUE if the COMIMAGE_FLAGS_STRONGNAMESIGNED flag is set // TLS BOOL HasTls() const; CHECK CheckTls() const; PTR_VOID GetTlsRange(COUNT_T *pSize = NULL) const; UINT32 GetTlsIndex() const; // Win32 resources void *GetWin32Resource(LPCWSTR lpName, LPCWSTR lpType, COUNT_T *pSize = NULL) const; bool EnumerateWin32ResourceTypes(PEDecoder_ResourceTypesCallbackFunction callback, void* context) const; bool EnumerateWin32ResourceNames(LPCWSTR lpType, PEDecoder_ResourceNamesCallbackFunction callback, void* context) const; bool EnumerateWin32Resources(LPCWSTR lpName, LPCWSTR lpType, PEDecoder_ResourceCallbackFunction callback, void* context) const; public: // COR header fields BOOL HasCorHeader() const; CHECK CheckCorHeader() const; IMAGE_COR20_HEADER *GetCorHeader() const; PTR_CVOID GetMetadata(COUNT_T *pSize = NULL) const; const void *GetResources(COUNT_T *pSize = NULL) const; CHECK CheckResource(COUNT_T offset) const; const void *GetResource(COUNT_T offset, COUNT_T *pSize = NULL) const; BOOL HasManagedEntryPoint() const; ULONG GetEntryPointToken() const; IMAGE_COR_VTABLEFIXUP *GetVTableFixups(COUNT_T *pCount = NULL) const; BOOL IsNativeMachineFormat() const; BOOL IsI386() const; void GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine); // Returns CorPEKind flags BOOL IsPlatformNeutral(); // Returns TRUE for IL-only platform neutral images // // Verifies that the IL is within the bounds of the image. // CHECK CheckILMethod(RVA rva); // // Compute size of IL blob. Assumes that the IL is within the bounds of the image - make sure // to call CheckILMethod before calling this method. // static SIZE_T ComputeILMethodSize(TADDR pIL); // Debug directory access, returns NULL if no such entry PTR_IMAGE_DEBUG_DIRECTORY GetDebugDirectoryEntry(UINT index) const; PTR_CVOID GetNativeManifestMetadata(COUNT_T* pSize = NULL) const; BOOL IsComponentAssembly() const; BOOL HasReadyToRunHeader() const; READYTORUN_HEADER *GetReadyToRunHeader() const; void GetEXEStackSizes(SIZE_T *PE_SizeOfStackReserve, SIZE_T *PE_SizeOfStackCommit) const; CHECK CheckWillCreateGuardPage() const; // Native DLLMain Entrypoint BOOL HasNativeEntryPoint() const; void *GetNativeEntryPoint() const; // Look up a named symbol in the export directory PTR_VOID GetExport(LPCSTR exportName) const; #ifdef _DEBUG // Stress mode for relocations static BOOL GetForceRelocs(); static BOOL ForceRelocForDLL(LPCWSTR lpFileName); #endif #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, bool enumThis); #endif protected: // ------------------------------------------------------------ // Protected API for subclass use // ------------------------------------------------------------ // Checking utilities static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva); static CHECK CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size); static CHECK CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer); static CHECK CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size); protected: // Flat mapping utilities - using PointerToRawData instead of (Relative)VirtualAddress IMAGE_SECTION_HEADER *RvaToSection(RVA rva) const; IMAGE_SECTION_HEADER *OffsetToSection(COUNT_T fileOffset) const; void SetRelocated(); IMAGE_NT_HEADERS* FindNTHeaders() const; private: // ------------------------------------------------------------ // Internal functions // ------------------------------------------------------------ enum METADATA_SECTION_TYPE { METADATA_SECTION_FULL, }; IMAGE_DATA_DIRECTORY *GetMetaDataHelper(METADATA_SECTION_TYPE type) const; static PTR_IMAGE_SECTION_HEADER FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders); IMAGE_COR20_HEADER *FindCorHeader() const; READYTORUN_HEADER *FindReadyToRunHeader() const; // Flat mapping utilities RVA InternalAddressToRva(SIZE_T address) const; // NT header subchecks CHECK CheckSection(COUNT_T previousAddressEnd, COUNT_T addressStart, COUNT_T addressSize, COUNT_T previousOffsetEnd, COUNT_T offsetStart, COUNT_T offsetSize) const; // Pure managed subchecks CHECK CheckILOnlyImportDlls() const; CHECK CheckILOnlyImportByNameTable(RVA rva) const; CHECK CheckILOnlyBaseRelocations() const; CHECK CheckILOnlyEntryPoint() const; // ------------------------------------------------------------ // Instance members // ------------------------------------------------------------ enum { FLAG_MAPPED = 0x01, // the file is mapped/hydrated (vs. the raw disk layout) FLAG_CONTENTS = 0x02, // the file has contents FLAG_RELOCATED = 0x04, // relocs have been applied FLAG_NT_CHECKED = 0x10, FLAG_COR_CHECKED = 0x20, FLAG_IL_ONLY_CHECKED = 0x40, FLAG_NATIVE_CHECKED = 0x80, FLAG_HAS_NO_READYTORUN_HEADER = 0x100, }; TADDR m_base; COUNT_T m_size; // size of file on disk, as opposed to OptionalHeaders.SizeOfImage ULONG m_flags; PTR_IMAGE_NT_HEADERS m_pNTHeaders; PTR_IMAGE_COR20_HEADER m_pCorHeader; PTR_READYTORUN_HEADER m_pReadyToRunHeader; }; // // MethodSectionIterator class is used to iterate hot (or) cold method section in an ngen image. // It can also iterate nibble maps generated by the JIT in a regular HeapList. // class MethodSectionIterator { private: PTR_DWORD m_codeTableStart; PTR_DWORD m_codeTable; PTR_DWORD m_codeTableEnd; BYTE *m_code; DWORD m_dword; DWORD m_index; BYTE *m_current; public: //If code is a target pointer, then GetMethodCode and FindMethodCode return //target pointers. codeTable may be a pointer of either type, since it is //converted internally into a host pointer. MethodSectionIterator(const void *code, SIZE_T codeSize, const void *codeTable, SIZE_T codeTableSize); BOOL Next(); BYTE *GetMethodCode() { return m_current; } // Get the start of method code of the current method in the iterator }; #include "pedecoder.inl" #endif // PEDECODER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/pedecoder.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- // PEDecoder.inl // // -------------------------------------------------------------------------------- #ifndef _PEDECODER_INL_ #define _PEDECODER_INL_ #include "pedecoder.h" #include "ex.h" #ifndef DACCESS_COMPILE inline PEDecoder::PEDecoder() : m_base(0), m_size(0), m_flags(0), m_pNTHeaders(nullptr), m_pCorHeader(nullptr), m_pReadyToRunHeader(nullptr) { CONTRACTL { CONSTRUCTOR_CHECK; NOTHROW; CANNOT_TAKE_LOCK; GC_NOTRIGGER; } CONTRACTL_END; } #else inline PEDecoder::PEDecoder() { LIMITED_METHOD_CONTRACT; } #endif // #ifndef DACCESS_COMPILE inline PTR_VOID PEDecoder::GetBase() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return PTR_VOID(m_base); } inline BOOL PEDecoder::IsMapped() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return (m_flags & FLAG_MAPPED) != 0; } inline BOOL PEDecoder::IsRelocated() const { LIMITED_METHOD_CONTRACT; return (m_flags & FLAG_RELOCATED) != 0; } inline void PEDecoder::SetRelocated() { m_flags |= FLAG_RELOCATED; } inline BOOL PEDecoder::IsFlat() const { LIMITED_METHOD_CONTRACT; return HasContents() && !IsMapped(); } inline BOOL PEDecoder::HasContents() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return (m_flags & FLAG_CONTENTS) != 0; } inline COUNT_T PEDecoder::GetSize() const { LIMITED_METHOD_DAC_CONTRACT; return m_size; } inline PEDecoder::PEDecoder(PTR_VOID mappedBase, bool fixedUp /*= FALSE*/) : m_base(dac_cast(mappedBase)), m_size(0), m_flags(FLAG_MAPPED | FLAG_CONTENTS | FLAG_NT_CHECKED | (fixedUp ? FLAG_RELOCATED : 0)), m_pNTHeaders(nullptr), m_pCorHeader(nullptr), m_pReadyToRunHeader(nullptr) { CONTRACTL { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(mappedBase)); PRECONDITION(PEDecoder(mappedBase,fixedUp).CheckNTHeaders()); THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; // Temporarily set the size to 2 pages, so we can get the headers. m_size = GetOsPageSize()*2; m_pNTHeaders = PTR_IMAGE_NT_HEADERS(FindNTHeaders()); if (!m_pNTHeaders) ThrowHR(COR_E_BADIMAGEFORMAT); m_size = VAL32(m_pNTHeaders->OptionalHeader.SizeOfImage); } #ifndef DACCESS_COMPILE //REM //what's the right way to do this? //we want to use some against TADDR, but also want to do //some against what's just in the current process. //m_base is a TADDR in DAC all the time, though. //Have to implement separate fn to do the lookup?? inline PEDecoder::PEDecoder(void *flatBase, COUNT_T size) : m_base((TADDR)flatBase), m_size(size), m_flags(FLAG_CONTENTS), m_pNTHeaders(NULL), m_pCorHeader(NULL), m_pReadyToRunHeader(NULL) { CONTRACTL { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(flatBase)); NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; } inline void PEDecoder::Init(void *flatBase, COUNT_T size) { CONTRACTL { INSTANCE_CHECK; PRECONDITION((size == 0) || CheckPointer(flatBase)); PRECONDITION(!HasContents()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; m_base = (TADDR)flatBase; m_size = size; m_flags = FLAG_CONTENTS; } inline HRESULT PEDecoder::Init(void *mappedBase, bool fixedUp /*= FALSE*/) { CONTRACTL { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; PRECONDITION(CheckPointer(mappedBase)); PRECONDITION(!HasContents()); } CONTRACTL_END; m_base = (TADDR)mappedBase; m_flags = FLAG_MAPPED | FLAG_CONTENTS; if (fixedUp) m_flags |= FLAG_RELOCATED; // Temporarily set the size to 2 pages, so we can get the headers. m_size = GetOsPageSize()*2; m_pNTHeaders = FindNTHeaders(); if (!m_pNTHeaders) return COR_E_BADIMAGEFORMAT; m_size = VAL32(m_pNTHeaders->OptionalHeader.SizeOfImage); return S_OK; } inline void PEDecoder::Reset() { CONTRACTL { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; m_base=NULL; m_flags=NULL; m_size=NULL; m_pNTHeaders=NULL; m_pCorHeader=NULL; m_pReadyToRunHeader=NULL; } #endif // #ifndef DACCESS_COMPILE inline IMAGE_NT_HEADERS32 *PEDecoder::GetNTHeaders32() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return dac_cast(FindNTHeaders()); } inline IMAGE_NT_HEADERS64 *PEDecoder::GetNTHeaders64() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return dac_cast(FindNTHeaders()); } inline BOOL PEDecoder::Has32BitNTHeaders() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(HasNTHeaders()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACTL_END; return (FindNTHeaders()->OptionalHeader.Magic == VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC)); } inline const void *PEDecoder::GetHeaders(COUNT_T *pSize) const { CONTRACT(const void *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same if (pSize != NULL) *pSize = VAL32(FindNTHeaders()->OptionalHeader.SizeOfHeaders); RETURN (const void *) m_base; } inline BOOL PEDecoder::IsDll() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; return ((FindNTHeaders()->FileHeader.Characteristics & VAL16(IMAGE_FILE_DLL)) != 0); } inline BOOL PEDecoder::HasBaseRelocations() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; return ((FindNTHeaders()->FileHeader.Characteristics & VAL16(IMAGE_FILE_RELOCS_STRIPPED)) == 0); } inline const void *PEDecoder::GetPreferredBase() const { CONTRACT(const void *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL, NULL_OK)); } CONTRACT_END; if (Has32BitNTHeaders()) RETURN (const void *) (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.ImageBase); else RETURN (const void *) (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.ImageBase); } inline COUNT_T PEDecoder::GetVirtualSize() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same return VAL32(FindNTHeaders()->OptionalHeader.SizeOfImage); } inline WORD PEDecoder::GetSubsystem() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same return VAL16(FindNTHeaders()->OptionalHeader.Subsystem); } inline WORD PEDecoder::GetDllCharacteristics() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same return VAL16(FindNTHeaders()->OptionalHeader.DllCharacteristics); } inline DWORD PEDecoder::GetTimeDateStamp() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; return VAL32(FindNTHeaders()->FileHeader.TimeDateStamp); } inline DWORD PEDecoder::GetCheckSum() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same return VAL32(FindNTHeaders()->OptionalHeader.CheckSum); } inline DWORD PEDecoder::GetFileAlignment() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same return VAL32(FindNTHeaders()->OptionalHeader.FileAlignment); } inline DWORD PEDecoder::GetSectionAlignment() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; //even though some data in OptionalHeader is different for 32 and 64, this field is the same return VAL32(FindNTHeaders()->OptionalHeader.SectionAlignment); } inline WORD PEDecoder::GetMachine() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; return VAL16(FindNTHeaders()->FileHeader.Machine); } inline WORD PEDecoder::GetCharacteristics() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; return VAL16(FindNTHeaders()->FileHeader.Characteristics); } inline SIZE_T PEDecoder::GetSizeOfStackReserve() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackReserve); else return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackReserve); } inline SIZE_T PEDecoder::GetSizeOfStackCommit() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfStackCommit); else return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfStackCommit); } inline SIZE_T PEDecoder::GetSizeOfHeapReserve() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfHeapReserve); else return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfHeapReserve); } inline SIZE_T PEDecoder::GetSizeOfHeapCommit() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return (SIZE_T) VAL32(GetNTHeaders32()->OptionalHeader.SizeOfHeapCommit); else return (SIZE_T) VAL64(GetNTHeaders64()->OptionalHeader.SizeOfHeapCommit); } inline UINT32 PEDecoder::GetLoaderFlags() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return VAL32(GetNTHeaders32()->OptionalHeader.LoaderFlags); else return VAL32(GetNTHeaders64()->OptionalHeader.LoaderFlags); } inline UINT32 PEDecoder::GetWin32VersionValue() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return VAL32(GetNTHeaders32()->OptionalHeader.Win32VersionValue); else return VAL32(GetNTHeaders64()->OptionalHeader.Win32VersionValue); } inline COUNT_T PEDecoder::GetNumberOfRvaAndSizes() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; if (Has32BitNTHeaders()) return VAL32(GetNTHeaders32()->OptionalHeader.NumberOfRvaAndSizes); else return VAL32(GetNTHeaders64()->OptionalHeader.NumberOfRvaAndSizes); } inline BOOL PEDecoder::HasDirectoryEntry(int entry) const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; if (Has32BitNTHeaders()) return (GetNTHeaders32()->OptionalHeader.DataDirectory[entry].VirtualAddress != 0); else return (GetNTHeaders64()->OptionalHeader.DataDirectory[entry].VirtualAddress != 0); } inline IMAGE_DATA_DIRECTORY *PEDecoder::GetDirectoryEntry(int entry) const { CONTRACT(IMAGE_DATA_DIRECTORY *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACT_END; if (Has32BitNTHeaders()) RETURN dac_cast( dac_cast(GetNTHeaders32()) + offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory) + entry * sizeof(IMAGE_DATA_DIRECTORY)); else RETURN dac_cast( dac_cast(GetNTHeaders64()) + offsetof(IMAGE_NT_HEADERS64, OptionalHeader.DataDirectory) + entry * sizeof(IMAGE_DATA_DIRECTORY)); } inline TADDR PEDecoder::GetDirectoryEntryData(int entry, COUNT_T *pSize) const { CONTRACT(TADDR) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(CheckDirectoryEntry(entry, 0, NULL_OK)); PRECONDITION(CheckPointer(pSize, NULL_OK)); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACT_END; IMAGE_DATA_DIRECTORY *pDir = GetDirectoryEntry(entry); if (pSize != NULL) *pSize = VAL32(pDir->Size); RETURN GetDirectoryData(pDir); } inline TADDR PEDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir) const { CONTRACT(TADDR) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(CheckDirectory(pDir, 0, NULL_OK)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); CANNOT_TAKE_LOCK; } CONTRACT_END; RETURN GetRvaData(VAL32(pDir->VirtualAddress)); } inline TADDR PEDecoder::GetDirectoryData(IMAGE_DATA_DIRECTORY *pDir, COUNT_T *pSize) const { CONTRACT(TADDR) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(CheckDirectory(pDir, 0, NULL_OK)); PRECONDITION(CheckPointer(pSize)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; POSTCONDITION(CheckPointer((void *)RETVAL, NULL_OK)); CANNOT_TAKE_LOCK; } CONTRACT_END; *pSize = VAL32(pDir->Size); RETURN GetRvaData(VAL32(pDir->VirtualAddress)); } inline TADDR PEDecoder::GetInternalAddressData(SIZE_T address) const { CONTRACT(TADDR) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(CheckInternalAddress(address, NULL_OK)); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer((void *)RETVAL)); } CONTRACT_END; RETURN GetRvaData(InternalAddressToRva(address)); } inline BOOL PEDecoder::HasCorHeader() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; SUPPORTS_DAC; GC_NOTRIGGER; } CONTRACTL_END; return HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER); } inline BOOL PEDecoder::IsILOnly() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(HasCorHeader()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; // Pretend that ready-to-run images are IL-only return((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_ILONLY)) != 0) || HasReadyToRunHeader(); } inline COUNT_T PEDecoder::RvaToOffset(RVA rva) const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(CheckRva(rva,NULL_OK)); NOTHROW; CANNOT_TAKE_LOCK; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; if(rva > 0) { IMAGE_SECTION_HEADER *section = RvaToSection(rva); if (section == NULL) return rva; return rva - VAL32(section->VirtualAddress) + VAL32(section->PointerToRawData); } else return 0; } inline RVA PEDecoder::OffsetToRva(COUNT_T fileOffset) const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(CheckOffset(fileOffset,NULL_OK)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; if(fileOffset > 0) { IMAGE_SECTION_HEADER *section = OffsetToSection(fileOffset); PREFIX_ASSUME (section!=NULL); //TODO: actually it is possible that it si null we need to rethink how we handle this cases and do better there return fileOffset - VAL32(section->PointerToRawData) + VAL32(section->VirtualAddress); } else return 0; } inline BOOL PEDecoder::IsStrongNameSigned() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(HasCorHeader()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; return ((GetCorHeader()->Flags & VAL32(COMIMAGE_FLAGS_STRONGNAMESIGNED)) != 0); } inline BOOL PEDecoder::HasStrongNameSignature() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(HasCorHeader()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; return (GetCorHeader()->StrongNameSignature.VirtualAddress != 0); } inline CHECK PEDecoder::CheckStrongNameSignature() const { CONTRACT_CHECK { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(HasCorHeader()); PRECONDITION(HasStrongNameSignature()); NOTHROW; GC_NOTRIGGER; } CONTRACT_CHECK_END; return CheckDirectory(&GetCorHeader()->StrongNameSignature, IMAGE_SCN_MEM_WRITE, NULL_OK); } inline PTR_CVOID PEDecoder::GetStrongNameSignature(COUNT_T *pSize) const { CONTRACT(PTR_CVOID) { INSTANCE_CHECK; PRECONDITION(HasCorHeader()); PRECONDITION(HasStrongNameSignature()); PRECONDITION(CheckStrongNameSignature()); PRECONDITION(CheckPointer(pSize, NULL_OK)); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; IMAGE_DATA_DIRECTORY *pDir = &GetCorHeader()->StrongNameSignature; if (pSize != NULL) *pSize = VAL32(pDir->Size); RETURN dac_cast(GetDirectoryData(pDir)); } inline BOOL PEDecoder::HasTls() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; return HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_TLS); } inline CHECK PEDecoder::CheckTls() const { CONTRACT_CHECK { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; } CONTRACT_CHECK_END; CHECK(CheckDirectoryEntry(IMAGE_DIRECTORY_ENTRY_TLS, 0, NULL_OK)); IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); CHECK(CheckUnderflow(VALPTR(pTlsHeader->EndAddressOfRawData), VALPTR(pTlsHeader->StartAddressOfRawData))); CHECK(VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData) <= COUNT_T_MAX); CHECK(CheckInternalAddress(VALPTR(pTlsHeader->StartAddressOfRawData), (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)))); CHECK_OK; } inline PTR_VOID PEDecoder::GetTlsRange(COUNT_T * pSize) const { CONTRACT(void *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(HasTls()); PRECONDITION(CheckTls()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); } CONTRACT_END; IMAGE_TLS_DIRECTORY *pTlsHeader = PTR_IMAGE_TLS_DIRECTORY(GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS)); if (pSize != 0) *pSize = (COUNT_T) (VALPTR(pTlsHeader->EndAddressOfRawData) - VALPTR(pTlsHeader->StartAddressOfRawData)); PREFIX_ASSUME (pTlsHeader!=NULL); RETURN PTR_VOID(GetInternalAddressData(pTlsHeader->StartAddressOfRawData)); } inline UINT32 PEDecoder::GetTlsIndex() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(HasTls()); PRECONDITION(CheckTls()); NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; IMAGE_TLS_DIRECTORY *pTlsHeader = (IMAGE_TLS_DIRECTORY *) GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_TLS); return (UINT32)*PTR_UINT32(GetInternalAddressData((SIZE_T)VALPTR(pTlsHeader->AddressOfIndex))); } inline IMAGE_COR20_HEADER *PEDecoder::GetCorHeader() const { CONTRACT(IMAGE_COR20_HEADER *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(HasCorHeader()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACT_END; if (m_pCorHeader == NULL) const_cast(this)->m_pCorHeader = dac_cast(FindCorHeader()); RETURN m_pCorHeader; } inline BOOL PEDecoder::IsNativeMachineFormat() const { if (!HasContents() || !HasNTHeaders() ) return FALSE; _ASSERTE(m_pNTHeaders); WORD expectedFormat = HasCorHeader() && HasReadyToRunHeader() ? IMAGE_FILE_MACHINE_NATIVE_NI : IMAGE_FILE_MACHINE_NATIVE; //do not call GetNTHeaders as we do not want to bother with PE32->PE32+ conversion return m_pNTHeaders->FileHeader.Machine==expectedFormat; } inline BOOL PEDecoder::IsI386() const { if (!HasContents() || !HasNTHeaders() ) return FALSE; _ASSERTE(m_pNTHeaders); //do not call GetNTHeaders as we do not want to bother with PE32->PE32+ conversion return m_pNTHeaders->FileHeader.Machine==IMAGE_FILE_MACHINE_I386; } // static inline PTR_IMAGE_SECTION_HEADER PEDecoder::FindFirstSection(IMAGE_NT_HEADERS * pNTHeaders) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return dac_cast( dac_cast(pNTHeaders) + offsetof(IMAGE_NT_HEADERS, OptionalHeader) + VAL16(pNTHeaders->FileHeader.SizeOfOptionalHeader)); } inline COUNT_T PEDecoder::GetNumberOfSections() const { CONTRACTL { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACTL_END; return VAL16(FindNTHeaders()->FileHeader.NumberOfSections); } inline DWORD PEDecoder::GetImageIdentity() const { WRAPPER_NO_CONTRACT; return GetTimeDateStamp() ^ GetCheckSum() ^ DWORD( GetVirtualSize() ); } inline PTR_IMAGE_SECTION_HEADER PEDecoder::FindFirstSection() const { CONTRACT(IMAGE_SECTION_HEADER *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); SUPPORTS_DAC; } CONTRACT_END; RETURN FindFirstSection(FindNTHeaders()); } inline IMAGE_NT_HEADERS *PEDecoder::FindNTHeaders() const { CONTRACT(IMAGE_NT_HEADERS *) { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACT_END; RETURN PTR_IMAGE_NT_HEADERS(m_base + VAL32(PTR_IMAGE_DOS_HEADER(m_base)->e_lfanew)); } inline IMAGE_COR20_HEADER *PEDecoder::FindCorHeader() const { CONTRACT(IMAGE_COR20_HEADER *) { INSTANCE_CHECK; PRECONDITION(HasCorHeader()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACT_END; const IMAGE_COR20_HEADER * pCor=PTR_IMAGE_COR20_HEADER(GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_COMHEADER)); RETURN ((IMAGE_COR20_HEADER*)pCor); } inline CHECK PEDecoder::CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CHECK(CheckOverflow(rangeBase, rangeSize)); CHECK(rva >= rangeBase); CHECK(rva <= rangeBase + rangeSize); CHECK_OK; } inline CHECK PEDecoder::CheckBounds(RVA rangeBase, COUNT_T rangeSize, RVA rva, COUNT_T size) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CHECK(CheckOverflow(rangeBase, rangeSize)); CHECK(CheckOverflow(rva, size)); CHECK(rva >= rangeBase); CHECK(rva + size <= rangeBase + rangeSize); CHECK_OK; } inline CHECK PEDecoder::CheckBounds(const void *rangeBase, COUNT_T rangeSize, const void *pointer) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CHECK(CheckOverflow(dac_cast(rangeBase), rangeSize)); CHECK(dac_cast(pointer) >= dac_cast(rangeBase)); CHECK(dac_cast(pointer) <= dac_cast(rangeBase) + rangeSize); CHECK_OK; } inline CHECK PEDecoder::CheckBounds(PTR_CVOID rangeBase, COUNT_T rangeSize, PTR_CVOID pointer, COUNT_T size) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CHECK(CheckOverflow(rangeBase, rangeSize)); CHECK(CheckOverflow(pointer, size)); CHECK(dac_cast(pointer) >= dac_cast(rangeBase)); CHECK(dac_cast(pointer) + size <= dac_cast(rangeBase) + rangeSize); CHECK_OK; } inline void PEDecoder::GetPEKindAndMachine(DWORD * pdwPEKind, DWORD *pdwMachine) { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; DWORD dwKind=0,dwMachine=0; if(HasContents() && HasNTHeaders()) { dwMachine = GetMachine(); BOOL fIsPE32Plus = !Has32BitNTHeaders(); if (fIsPE32Plus) dwKind |= (DWORD)pe32Plus; if (HasCorHeader()) { IMAGE_COR20_HEADER * pCorHdr = GetCorHeader(); if(pCorHdr != NULL) { DWORD dwCorFlags = pCorHdr->Flags; if (dwCorFlags & VAL32(COMIMAGE_FLAGS_ILONLY)) { dwKind |= (DWORD)peILonly; #ifdef HOST_64BIT // compensate for shim promotion of PE32/ILONLY headers to PE32+ on WIN64 if (fIsPE32Plus && (GetMachine() == IMAGE_FILE_MACHINE_I386)) dwKind &= ~((DWORD)pe32Plus); #endif } if (COR_IS_32BIT_REQUIRED(dwCorFlags)) dwKind |= (DWORD)pe32BitRequired; else if (COR_IS_32BIT_PREFERRED(dwCorFlags)) dwKind |= (DWORD)pe32BitPreferred; // compensate for MC++ peculiarity if(dwKind == 0) dwKind = (DWORD)pe32BitRequired; } else { dwKind |= (DWORD)pe32Unmanaged; } if (HasReadyToRunHeader()) { if (dwMachine == IMAGE_FILE_MACHINE_NATIVE_NI) { // Supply the original machine type to the assembly binder dwMachine = IMAGE_FILE_MACHINE_NATIVE; } if ((GetReadyToRunHeader()->CoreHeader.Flags & READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE) != 0) { // Supply the original PEKind/Machine to the assembly binder to make the full assembly name look like the original dwKind = peILonly; dwMachine = IMAGE_FILE_MACHINE_I386; } } } else { dwKind |= (DWORD)pe32Unmanaged; } } *pdwPEKind = dwKind; *pdwMachine = dwMachine; } inline BOOL PEDecoder::IsPlatformNeutral() { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; DWORD dwKind, dwMachine; GetPEKindAndMachine(&dwKind, &dwMachine); return ((dwKind & (peILonly | pe32Plus | pe32BitRequired)) == peILonly) && (dwMachine == IMAGE_FILE_MACHINE_I386); } inline BOOL PEDecoder::IsComponentAssembly() const { CONTRACTL { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACTL_END; return HasReadyToRunHeader() && (m_pReadyToRunHeader->CoreHeader.Flags & READYTORUN_FLAG_COMPONENT) != 0; } inline BOOL PEDecoder::HasReadyToRunHeader() const { CONTRACTL { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACTL_END; if (m_flags & FLAG_HAS_NO_READYTORUN_HEADER) return FALSE; if (m_pReadyToRunHeader != NULL) return TRUE; return FindReadyToRunHeader() != NULL; } inline READYTORUN_HEADER * PEDecoder::GetReadyToRunHeader() const { CONTRACT(READYTORUN_HEADER *) { INSTANCE_CHECK; PRECONDITION(CheckNTHeaders()); PRECONDITION(HasCorHeader()); PRECONDITION(HasReadyToRunHeader()); NOTHROW; GC_NOTRIGGER; POSTCONDITION(CheckPointer(RETVAL)); SUPPORTS_DAC; CANNOT_TAKE_LOCK; } CONTRACT_END; if (m_pReadyToRunHeader != NULL) RETURN m_pReadyToRunHeader; RETURN FindReadyToRunHeader(); } #endif // _PEDECODER_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/pesectionman.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // Section Manager for portable executables // Common to both Memory Only and Static (EXE making) code #ifndef PESectionMan_H #define PESectionMan_H #include "windef.h" #include "ceegen.h" #include "blobfetcher.h" class PESection; struct PESectionReloc; struct _IMAGE_SECTION_HEADER; class PESectionMan { public: virtual ~PESectionMan() {} HRESULT Init(); HRESULT Cleanup(); // Finds section with given name, or creates a new one HRESULT getSectionCreate( const char *name, unsigned flags, // IMAGE_SCN_* flags. eg. IMAGE_SCN_CNT_INITIALIZED_DATA PESection **section); // Since we allocate, we must delete (Bug in VC, see knowledge base Q122675) void sectionDestroy(PESection **section); // Apply all the relocs for in memory conversion HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); HRESULT cloneInstance(PESectionMan *destination); protected: // Finds section with given name. returns 0 if not found virtual PESection *getSection(const char *name); // Create a new section virtual HRESULT newSection( const char *name, PESection **section, unsigned flags = sdNone, unsigned estSize = 0x10000, unsigned estRelocs = 1); // Keep proctected & no accessors, so that derived class PEWriter // is the ONLY one with access PESection **sectStart; PESection **sectCur; PESection **sectEnd; }; // class PESectionMan /*************************************************************** * This represents a section of a ICeeFileGen. Multiple sections * can be created with pointers to one another. These will * automatically get fixed up when the ICeeFileGen is "baked". * * It is implemented using CBlobFetcher as a list of blobs. * Thus it can grow arbitrarily. At the same time, it can appear * as a flat consecutive piece of memory which can be indexed into * using offsets. */ class PESection : public CeeSectionImpl { public: // bytes in this section at present unsigned dataLen(); // Apply all the relocs for in memory conversion HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); // get a block to write on (use instead of write to avoid copy) char* getBlock(unsigned len, unsigned align=1); // writes 'val' (which is offset into section 'relativeTo') // and adds a relocation fixup for that section void writeSectReloc(unsigned val, CeeSection& relativeTo, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra=0); // Indicates that the DWORD at 'offset' in the current section should // have the base of section 'relativeTo' added to it HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra=0); // If relativeTo is NULL, it is treated as a base reloc. // ie. the value only needs to be fixed at load time if the module gets rebased. HRESULT addSectReloc(unsigned offset, PESection *relativeTo, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra=0); // Add a base reloc for the given offset in the current section HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc = srRelocHighLow, CeeSectionRelocExtra *extra = 0); // section name unsigned char *name() { LIMITED_METHOD_CONTRACT; return (unsigned char *) m_name; } // section flags unsigned flags() { LIMITED_METHOD_CONTRACT; return m_flags; } // virtual base unsigned getBaseRVA() { LIMITED_METHOD_CONTRACT; return m_baseRVA; } // return the dir entry for this section int getDirEntry() { LIMITED_METHOD_CONTRACT; return dirEntry; } // this section will be directory entry 'num' HRESULT directoryEntry(unsigned num); // Indexes offset as if this were an array // Returns a pointer into the correct blob virtual char * computePointer(unsigned offset) const; // Checks to see if pointer is in section virtual BOOL containsPointer(_In_ char *ptr) const; // Given a pointer pointing into this section, // computes an offset as if this were an array virtual unsigned computeOffset(_In_ char *ptr) const; // Make 'destination' a copy of the current PESection HRESULT cloneInstance(PESection *destination); // Cause the section to allocate memory in smaller chunks void SetInitialGrowth(unsigned growth); virtual ~PESection(); private: // purposely not defined, PESection(); // purposely not defined, PESection(const PESection&); // purposely not defined, PESection& operator=(const PESection& x); // this dir entry points to this section int dirEntry; protected: friend class PEWriter; friend class PEWriterSection; friend class PESectionMan; PESection(const char* name, unsigned flags, unsigned estSize, unsigned estRelocs); // Blob fetcher handles getBlock() and fetching binary chunks. CBlobFetcher m_blobFetcher; PESectionReloc* m_relocStart; PESectionReloc* m_relocCur; PESectionReloc* m_relocEnd; // These will be set while baking (finalizing) the file unsigned m_baseRVA; // RVA into the file of this section. unsigned m_filePos; // Start offset into the file (treated as a data image) unsigned m_filePad; // Padding added to the end of the section for alignment char m_name[8+6]; // extra room for digits unsigned m_flags; struct _IMAGE_SECTION_HEADER* m_header; // Corresponding header. Assigned after link() }; /***************************************************************/ /* implementation section */ inline HRESULT PESection::directoryEntry(unsigned num) { WRAPPER_NO_CONTRACT; TESTANDRETURN(num < 16, E_INVALIDARG); dirEntry = num; return S_OK; } // This remembers the location where a reloc needs to be applied. // It is relative to the contents of a PESection struct PESectionReloc { CeeSectionRelocType type; // type of reloc unsigned offset; // offset within the current PESection where the reloc is to be applied CeeSectionRelocExtra extra; PESection* section; // target PESection. NULL implies that the target is a fixed address outside the module }; #endif // #define PESectionMan_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/pgo_formatprocessing.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // This header defines the algorithms for generating and parsing pgo compressed schema formats #ifndef PGO_FORMATPROCESSING_H #define PGO_FORMATPROCESSING_H #ifdef FEATURE_PGO inline INT_PTR HashToPgoUnknownHandle(uint32_t hash) { // Map from a 32bit hash to the 32 different unknown type handle values return (hash & 0x1F) + 1; } inline ICorJitInfo::PgoInstrumentationKind operator|(ICorJitInfo::PgoInstrumentationKind a, ICorJitInfo::PgoInstrumentationKind b) { return static_cast(static_cast(a) | static_cast(b)); } inline ICorJitInfo::PgoInstrumentationKind operator&(ICorJitInfo::PgoInstrumentationKind a, ICorJitInfo::PgoInstrumentationKind b) { return static_cast(static_cast(a) & static_cast(b)); } inline ICorJitInfo::PgoInstrumentationKind operator-(ICorJitInfo::PgoInstrumentationKind a, ICorJitInfo::PgoInstrumentationKind b) { return static_cast(static_cast(a) - static_cast(b)); } inline ICorJitInfo::PgoInstrumentationKind operator~(ICorJitInfo::PgoInstrumentationKind a) { return static_cast(~static_cast(a)); } inline uint32_t InstrumentationKindToSize(ICorJitInfo::PgoInstrumentationKind kind) { switch(kind & ICorJitInfo::PgoInstrumentationKind::MarshalMask) { case ICorJitInfo::PgoInstrumentationKind::None: return 0; case ICorJitInfo::PgoInstrumentationKind::FourByte: return 4; case ICorJitInfo::PgoInstrumentationKind::EightByte: return 8; case ICorJitInfo::PgoInstrumentationKind::TypeHandle: case ICorJitInfo::PgoInstrumentationKind::MethodHandle: return TARGET_POINTER_SIZE; default: _ASSERTE(FALSE); return 0; } } inline UINT InstrumentationKindToAlignment(ICorJitInfo::PgoInstrumentationKind kind) { switch(kind & ICorJitInfo::PgoInstrumentationKind::AlignMask) { case ICorJitInfo::PgoInstrumentationKind::Align4Byte: return 4; case ICorJitInfo::PgoInstrumentationKind::Align8Byte: return 8; case ICorJitInfo::PgoInstrumentationKind::AlignPointer: return TARGET_POINTER_SIZE; default: return (UINT)InstrumentationKindToSize(kind); } } #define SIGN_MASK_ONEBYTE_64BIT 0xffffffffffffffc0LL #define SIGN_MASK_TWOBYTE_64BIT 0xffffffffffffe000LL #define SIGN_MASK_FOURBYTE_64BIT 0xffffffff80000000LL template bool ReadCompressedInts(const uint8_t *pByte, size_t cbDataMax, IntHandler intProcessor) { while (cbDataMax > 0) { // This logic is a variant on CorSigUncompressSignedInt which allows for the full range of an int64_t int64_t signedInt; if ((*pByte & 0x80) == 0x0) // 0??? ???? { signedInt = *pByte >> 1; if (*pByte & 1) signedInt |= SIGN_MASK_ONEBYTE_64BIT; pByte += 1; cbDataMax -=1; } else if ((*pByte & 0xC0) == 0x80) // 10?? ???? { if (cbDataMax < 2) return false; int shiftedInt = ((*pByte & 0x3f) << 8) | *(pByte + 1); signedInt = shiftedInt >> 1; if (shiftedInt & 1) signedInt |= SIGN_MASK_TWOBYTE_64BIT; pByte += 2; cbDataMax -= 2; } else if ((*pByte) == 0xC1) { if (cbDataMax < 9) return false; signedInt = (int64_t)((((int64_t)*(pByte + 1)) << 56 | ((int64_t)*(pByte+2)) << 48 | ((int64_t)*(pByte+3)) << 40 | ((int64_t)*(pByte+4)) << 32) | ((int64_t)*(pByte + 5)) << 24 | ((int64_t)*(pByte+6)) << 16 | ((int64_t)*(pByte+7)) << 8 | ((int64_t)*(pByte+8))); pByte += 9; cbDataMax -= 9; } else { if (cbDataMax < 5) return false; signedInt = (int32_t)((*(pByte + 1) << 24 | *(pByte+2) << 16 | *(pByte+3) << 8 | *(pByte+4))); pByte += 5; cbDataMax -= 5; } if (!intProcessor(signedInt)) { return false; } } return true; } enum class InstrumentationDataProcessingState { Done = 0, ILOffset = 0x1, Type = 0x2, Count = 0x4, Other = 0x8, UpdateProcessMask = 0xF, UpdateProcessMaskFlag = 0x100, }; inline InstrumentationDataProcessingState operator|(InstrumentationDataProcessingState a, InstrumentationDataProcessingState b) { return static_cast(static_cast(a) | static_cast(b)); } inline InstrumentationDataProcessingState operator&(InstrumentationDataProcessingState a, InstrumentationDataProcessingState b) { return static_cast(static_cast(a) & static_cast(b)); } inline InstrumentationDataProcessingState operator~(InstrumentationDataProcessingState a) { return static_cast(~static_cast(a)); } class ProcessSchemaUpdateFunctor { ICorJitInfo::PgoInstrumentationSchema curSchema = {}; InstrumentationDataProcessingState processingState = InstrumentationDataProcessingState::UpdateProcessMaskFlag; public: const ICorJitInfo::PgoInstrumentationSchema& GetSchema() const { return curSchema; } bool ProcessInteger(int32_t curValue) { if (processingState == InstrumentationDataProcessingState::UpdateProcessMaskFlag) { processingState = (InstrumentationDataProcessingState)curValue; assert((processingState & ~InstrumentationDataProcessingState::UpdateProcessMask) == InstrumentationDataProcessingState::Done); return false; } if ((processingState & InstrumentationDataProcessingState::ILOffset) == InstrumentationDataProcessingState::ILOffset) { curSchema.ILOffset = (int32_t)((int64_t)curSchema.ILOffset + curValue); processingState = processingState & ~InstrumentationDataProcessingState::ILOffset; } else if ((processingState & InstrumentationDataProcessingState::Type) == InstrumentationDataProcessingState::Type) { curSchema.InstrumentationKind = static_cast(static_cast(curSchema.InstrumentationKind) + curValue); processingState = processingState & ~InstrumentationDataProcessingState::Type; } else if ((processingState & InstrumentationDataProcessingState::Count) == InstrumentationDataProcessingState::Count) { curSchema.Count = (int32_t)((int64_t)curSchema.Count + curValue); processingState = processingState & ~InstrumentationDataProcessingState::Count; } else if ((processingState & InstrumentationDataProcessingState::Other) == InstrumentationDataProcessingState::Other) { curSchema.Other = (int32_t)((int64_t)curSchema.Other + curValue); processingState = processingState & ~InstrumentationDataProcessingState::Other; } if (processingState == InstrumentationDataProcessingState::Done) { processingState = InstrumentationDataProcessingState::UpdateProcessMaskFlag; return true; } return false; } }; template bool ReadInstrumentationSchema(const uint8_t *pByte, size_t cbDataMax, SchemaHandler handler) { ProcessSchemaUpdateFunctor schemaHandlerUpdate; bool done = false; ReadCompressedInts(pByte, cbDataMax, [&handler, &schemaHandlerUpdate, &done](int64_t curValue) { if (schemaHandlerUpdate.ProcessInteger((int32_t)curValue)) { if (schemaHandlerUpdate.GetSchema().InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::Done) { done = true; return false; } if (!handler(schemaHandlerUpdate.GetSchema())) { return false; } } return true; }); return done; } template bool ReadInstrumentationData(const uint8_t *pByte, size_t cbDataMax, SchemaAndDataHandler& handler) { ProcessSchemaUpdateFunctor schemaHandler; bool done = false; int64_t lastDataValue = 0; int64_t lastTypeDataValue = 0; int64_t lastMethodDataValue = 0; int32_t dataCountToRead = 0; ReadCompressedInts(pByte, cbDataMax, [&](int64_t curValue) { if (dataCountToRead > 0) { switch(schemaHandler.GetSchema().InstrumentationKind & ICorJitInfo::PgoInstrumentationKind::MarshalMask) { case ICorJitInfo::PgoInstrumentationKind::FourByte: case ICorJitInfo::PgoInstrumentationKind::EightByte: lastDataValue += curValue; if (!handler(schemaHandler.GetSchema(), lastDataValue, schemaHandler.GetSchema().Count - dataCountToRead)) { return false; } break; case ICorJitInfo::PgoInstrumentationKind::TypeHandle: lastTypeDataValue += curValue; if (!handler(schemaHandler.GetSchema(), lastTypeDataValue, schemaHandler.GetSchema().Count - dataCountToRead)) { return false; } break; case ICorJitInfo::PgoInstrumentationKind::MethodHandle: lastMethodDataValue += curValue; if (!handler(schemaHandler.GetSchema(), lastMethodDataValue, schemaHandler.GetSchema().Count - dataCountToRead)) { return false; } break; default: assert(!"Unexpected PGO instrumentation data type"); break; } dataCountToRead--; return true; } if (schemaHandler.ProcessInteger((int32_t)curValue)) { if (schemaHandler.GetSchema().InstrumentationKind == ICorJitInfo::PgoInstrumentationKind::Done) { done = true; return false; } if (InstrumentationKindToSize(schemaHandler.GetSchema().InstrumentationKind) == 0) { if (!handler(schemaHandler.GetSchema(), 0, 0)) { return false; } } else { dataCountToRead = schemaHandler.GetSchema().Count; } } return true; }); return done; } inline bool CountInstrumentationDataSize(const uint8_t *pByte, size_t cbDataMax, int32_t *pInstrumentationSchemaCount) { *pInstrumentationSchemaCount = 0; return ReadInstrumentationSchema(pByte, cbDataMax, [pInstrumentationSchemaCount](const ICorJitInfo::PgoInstrumentationSchema& schema) { (*pInstrumentationSchemaCount)++; return true; }); } inline bool ComparePgoSchemaEquals(const uint8_t *pByte, size_t cbDataMax, const ICorJitInfo::PgoInstrumentationSchema* schemaTable, size_t cSchemas) { size_t iSchema = 0; return ReadInstrumentationSchema(pByte, cbDataMax, [schemaTable, cSchemas, &iSchema](const ICorJitInfo::PgoInstrumentationSchema& schema) { if (iSchema >= cSchemas) return false; if (schema.InstrumentationKind != schemaTable[iSchema].InstrumentationKind) return false; if (schema.ILOffset != schemaTable[iSchema].ILOffset) return false; if (schema.Count != schemaTable[iSchema].Count) return false; if (schema.Other != schemaTable[iSchema].Other) return false; return true; }); } inline void LayoutPgoInstrumentationSchema(const ICorJitInfo::PgoInstrumentationSchema& prevSchema, ICorJitInfo::PgoInstrumentationSchema* currentSchema) { size_t instrumentationSize = InstrumentationKindToSize(currentSchema->InstrumentationKind); if (instrumentationSize != 0) { currentSchema->Offset = (UINT)AlignUp((size_t)prevSchema.Offset + (size_t)InstrumentationKindToSize(prevSchema.InstrumentationKind) * prevSchema.Count, InstrumentationKindToAlignment(currentSchema->InstrumentationKind)); } else { currentSchema->Offset = prevSchema.Offset; } } template bool ReadInstrumentationSchemaWithLayout(const uint8_t *pByte, size_t cbDataMax, size_t initialOffset, SchemaHandler& handler) { ICorJitInfo::PgoInstrumentationSchema prevSchema; memset(&prevSchema, 0, sizeof(ICorJitInfo::PgoInstrumentationSchema)); prevSchema.Offset = initialOffset; return ReadInstrumentationSchema(pByte, cbDataMax, [&prevSchema, &handler](ICorJitInfo::PgoInstrumentationSchema curSchema) { LayoutPgoInstrumentationSchema(prevSchema, &curSchema); if (!handler(curSchema)) return false; prevSchema = curSchema; return true; }); } // Return true if schemaTable entries are a subset of the schema described by pByte, with matching entries in the same order. // Also updates offset of the matching entries in schemaTable to those of the pByte schema. // inline bool CheckIfPgoSchemaIsCompatibleAndSetOffsets(const uint8_t *pByte, size_t cbDataMax, ICorJitInfo::PgoInstrumentationSchema* schemaTable, size_t cSchemas) { size_t nMatched = 0; size_t initialOffset = cbDataMax; auto handler = [schemaTable, cSchemas, &nMatched](const ICorJitInfo::PgoInstrumentationSchema& schema) { if ((nMatched < cSchemas) && (schema.InstrumentationKind == schemaTable[nMatched].InstrumentationKind) && (schema.ILOffset == schemaTable[nMatched].ILOffset) && (schema.Count == schemaTable[nMatched].Count) && (schema.Other == schemaTable[nMatched].Other)) { schemaTable[nMatched].Offset = schema.Offset; nMatched++; } return true; }; ReadInstrumentationSchemaWithLayout(pByte, cbDataMax, initialOffset, handler); return (nMatched == cSchemas); } inline bool ReadInstrumentationSchemaWithLayoutIntoSArray(const uint8_t *pByte, size_t cbDataMax, size_t initialOffset, SArray* pSchemas) { auto lambda = [pSchemas](const ICorJitInfo::PgoInstrumentationSchema &schema) { pSchemas->Append(schema); return true; }; return ReadInstrumentationSchemaWithLayout(pByte, cbDataMax, initialOffset, lambda); } #define SIGN_MASK_ONEBYTE_64BIT 0xffffffffffffffc0LL #define SIGN_MASK_TWOBYTE_64BIT 0xffffffffffffe000LL #define SIGN_MASK_FOURBYTE_64BIT 0xffffffff80000000LL template bool WriteCompressedIntToBytes(int64_t value, ByteWriter& byteWriter) { uint8_t isSigned = 0; // This function is modeled on CorSigCompressSignedInt, but differs in that // it handles arbitrary int64 values, not just a subset if (value < 0) isSigned = 1; if ((value & SIGN_MASK_ONEBYTE_64BIT) == 0 || (value & SIGN_MASK_ONEBYTE_64BIT) == SIGN_MASK_ONEBYTE_64BIT) { return byteWriter((uint8_t)((value & ~SIGN_MASK_ONEBYTE) << 1 | isSigned)); } else if ((value & SIGN_MASK_TWOBYTE_64BIT) == 0 || (value & SIGN_MASK_TWOBYTE_64BIT) == SIGN_MASK_TWOBYTE_64BIT) { int32_t iData = (int32_t)((value & ~SIGN_MASK_TWOBYTE_64BIT) << 1 | isSigned); _ASSERTE(iData <= 0x3fff); byteWriter(uint8_t((iData >> 8) | 0x80)); return byteWriter(uint8_t(iData & 0xff)); } else if ((value & SIGN_MASK_FOURBYTE_64BIT) == 0 || (value & SIGN_MASK_FOURBYTE_64BIT) == SIGN_MASK_FOURBYTE_64BIT) { // Unlike CorSigCompressSignedInt, this just writes a header byte // then 4 bytes, ignoring the whole signed bit detail byteWriter(0xC0); byteWriter(uint8_t((value >> 24) & 0xff)); byteWriter(uint8_t((value >> 16) & 0xff)); byteWriter(uint8_t((value >> 8) & 0xff)); return byteWriter(uint8_t((value >> 0) & 0xff)); } else { // Unlike CorSigCompressSignedInt, this just writes a header byte // then 8 bytes, ignoring the whole signed bit detail byteWriter(0xC1); byteWriter(uint8_t((value >> 56) & 0xff)); byteWriter(uint8_t((value >> 48) & 0xff)); byteWriter(uint8_t((value >> 40) & 0xff)); byteWriter(uint8_t((value >> 32) & 0xff)); byteWriter(uint8_t((value >> 24) & 0xff)); byteWriter(uint8_t((value >> 16) & 0xff)); byteWriter(uint8_t((value >> 8) & 0xff)); return byteWriter(uint8_t((value >> 0) & 0xff)); } } template bool WriteIndividualSchemaToBytes(ICorJitInfo::PgoInstrumentationSchema prevSchema, ICorJitInfo::PgoInstrumentationSchema curSchema, ByteWriter& byteWriter) { int64_t ilOffsetDiff = (int64_t)curSchema.ILOffset - (int64_t)prevSchema.ILOffset; int64_t OtherDiff = (int64_t)curSchema.Other - (int64_t)prevSchema.Other; int64_t CountDiff = (int64_t)curSchema.Count - (int64_t)prevSchema.Count; int64_t TypeDiff = (int64_t)curSchema.InstrumentationKind - (int64_t)prevSchema.InstrumentationKind; InstrumentationDataProcessingState modifyMask = (InstrumentationDataProcessingState)0; if (ilOffsetDiff != 0) modifyMask = modifyMask | InstrumentationDataProcessingState::ILOffset; if (TypeDiff != 0) modifyMask = modifyMask | InstrumentationDataProcessingState::Type; if (CountDiff != 0) modifyMask = modifyMask | InstrumentationDataProcessingState::Count; if (OtherDiff != 0) modifyMask = modifyMask | InstrumentationDataProcessingState::Other; _ASSERTE(modifyMask != InstrumentationDataProcessingState::Done); WriteCompressedIntToBytes((int32_t)modifyMask, byteWriter); if ((ilOffsetDiff != 0) && !WriteCompressedIntToBytes(ilOffsetDiff, byteWriter)) return false; if ((TypeDiff != 0) && !WriteCompressedIntToBytes(TypeDiff, byteWriter)) return false; if ((CountDiff != 0) && !WriteCompressedIntToBytes(CountDiff, byteWriter)) return false; if ((OtherDiff != 0) && !WriteCompressedIntToBytes(OtherDiff, byteWriter)) return false; return true; } template bool WriteInstrumentationSchemaToBytes(const ICorJitInfo::PgoInstrumentationSchema* schemaTable, size_t cSchemas, const ByteWriter& byteWriter) { ICorJitInfo::PgoInstrumentationSchema prevSchema; memset(&prevSchema, 0, sizeof(ICorJitInfo::PgoInstrumentationSchema)); for (size_t iSchema = 0; iSchema < cSchemas; iSchema++) { if (!WriteIndividualSchemaToBytes(prevSchema, schemaTable[iSchema], byteWriter)) return false; prevSchema = schemaTable[iSchema]; } // Terminate the schema list with an entry which is Done ICorJitInfo::PgoInstrumentationSchema terminationSchema = prevSchema; terminationSchema.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::Done; if (!WriteIndividualSchemaToBytes(prevSchema, terminationSchema, byteWriter)) return false; return true; } template class SchemaAndDataWriter { const ByteWriter& byteWriter; uint8_t* pInstrumentationData; ICorJitInfo::PgoInstrumentationSchema prevSchema = {}; int64_t lastIntDataWritten = 0; int64_t lastTypeDataWritten = 0; int64_t lastMethodDataWritten = 0; public: SchemaAndDataWriter(const ByteWriter& byteWriter, uint8_t* pInstrumentationData) : byteWriter(byteWriter), pInstrumentationData(pInstrumentationData) {} bool AppendSchema(ICorJitInfo::PgoInstrumentationSchema schema) { if (!WriteIndividualSchemaToBytes(prevSchema, schema, byteWriter)) return false; prevSchema = schema; return true; } template bool AppendDataFromLastSchema(TypeHandleProcessor& thProcessor, MethodHandleProcessor& mhProcessor) { uint8_t *pData = (pInstrumentationData + prevSchema.Offset); for (int32_t iDataElem = 0; iDataElem < prevSchema.Count; iDataElem++) { int64_t logicalDataToWrite; switch(prevSchema.InstrumentationKind & ICorJitInfo::PgoInstrumentationKind::MarshalMask) { case ICorJitInfo::PgoInstrumentationKind::None: return true; case ICorJitInfo::PgoInstrumentationKind::FourByte: { logicalDataToWrite = *(volatile int32_t*)pData; bool returnValue = WriteCompressedIntToBytes(logicalDataToWrite - lastIntDataWritten, byteWriter); lastIntDataWritten = logicalDataToWrite; if (!returnValue) return false; pData += 4; break; } case ICorJitInfo::PgoInstrumentationKind::EightByte: { logicalDataToWrite = *(volatile int64_t*)pData; bool returnValue = WriteCompressedIntToBytes(logicalDataToWrite - lastIntDataWritten, byteWriter); lastIntDataWritten = logicalDataToWrite; if (!returnValue) return false; pData += 8; break; } case ICorJitInfo::PgoInstrumentationKind::TypeHandle: { logicalDataToWrite = *(volatile intptr_t*)pData; // As there could be tearing otherwise, inform the caller of exactly what value was written. thProcessor((intptr_t)logicalDataToWrite); bool returnValue = WriteCompressedIntToBytes(logicalDataToWrite - lastTypeDataWritten, byteWriter); lastTypeDataWritten = logicalDataToWrite; if (!returnValue) return false; pData += sizeof(intptr_t); break; } case ICorJitInfo::PgoInstrumentationKind::MethodHandle: { logicalDataToWrite = *(volatile intptr_t*)pData; // As there could be tearing otherwise, inform the caller of exactly what value was written. mhProcessor((intptr_t)logicalDataToWrite); bool returnValue = WriteCompressedIntToBytes(logicalDataToWrite - lastMethodDataWritten, byteWriter); lastMethodDataWritten = logicalDataToWrite; if (!returnValue) return false; pData += sizeof(intptr_t); break; } default: _ASSERTE(!"Unexpected type"); return false; } } return true; } bool Finish() { // Terminate the schema list with an entry which is Done ICorJitInfo::PgoInstrumentationSchema terminationSchema = prevSchema; terminationSchema.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::Done; if (!WriteIndividualSchemaToBytes(prevSchema, terminationSchema, byteWriter)) return false; return true; } }; inline bool WriteInstrumentationSchema(const ICorJitInfo::PgoInstrumentationSchema* schemaTable, size_t cSchemas, uint8_t* array, size_t byteCount) { return WriteInstrumentationSchemaToBytes(schemaTable, cSchemas, [&array, &byteCount](uint8_t data) { if (byteCount == 0) return false; *array = data; array += 1; byteCount--; return true; }); } #endif // FEATURE_PGO #endif // PGO_FORMATPROCESSING_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/pinvokeoverride.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** pinvokeoverride.h - PInvoke binding override ** ** ** *****************************************************************************/ #ifndef _PINVOKEOVERRIDE_H_ #define _PINVOKEOVERRIDE_H_ #include "coreclrhost.h" class PInvokeOverride { public: // Override source. This represents the priority order in which overrides will be called. enum class Source { RuntimeConfiguration, ObjectiveCInterop, Last = ObjectiveCInterop, }; static void SetPInvokeOverride(_In_ PInvokeOverrideFn* overrideImpl, _In_ Source source); static const void* GetMethodImpl(_In_z_ const char* libraryName, _In_z_ const char* entrypointName); }; #endif // _PINVOKEOVERRIDE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/posterror.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // UtilCode.h // // Utility functions implemented in UtilCode.lib. // //***************************************************************************** #ifndef __PostError_h__ #define __PostError_h__ #include "switches.h" //***************************************************************************** // This function will post an error for the client. If the LOWORD(hrRpt) can // be found as a valid error message, then it is loaded and formatted with // the arguments passed in. If it cannot be found, then the error is checked // against FormatMessage to see if it is a system error. System errors are // not formatted so no add'l parameters are required. If any errors in this // process occur, hrRpt is returned for the client with no error posted. //***************************************************************************** HRESULT PostError( // Returned error. HRESULT hrRpt, // Reported error. ...); // Error arguments. #endif // __PostError_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/predeftlsslot.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __PREDEFTLSSLOT_H__ #define __PREDEFTLSSLOT_H__ // ****************************************************************************** // WARNING!!!: These enums are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/predeftlsslot.h // ****************************************************************************** // The historic location of ThreadType slot kept for compatibility with SOS // TODO: Introduce DAC API to make this hack unnecessary enum PredefinedTlsSlots { TlsIdx_ThreadType = 11 // bit flags to indicate special thread's type }; enum TlsThreadTypeFlag // flag used for thread type in Tls data { ThreadType_GC = 0x00000001, ThreadType_Timer = 0x00000002, ThreadType_Gate = 0x00000004, ThreadType_DbgHelper = 0x00000008, ThreadType_Shutdown = 0x00000010, ThreadType_DynamicSuspendEE = 0x00000020, ThreadType_Finalizer = 0x00000040, ThreadType_ADUnloadHelper = 0x00000200, ThreadType_ShutdownHelper = 0x00000400, ThreadType_Threadpool_IOCompletion = 0x00000800, ThreadType_Threadpool_Worker = 0x00001000, ThreadType_Wait = 0x00002000, ThreadType_ProfAPI_Attach = 0x00004000, ThreadType_ProfAPI_Detach = 0x00008000, ThreadType_ETWRundownThread = 0x00010000, ThreadType_GenericInstantiationCompare= 0x00020000, // Used to indicate that the thread is determining if a generic instantiation in an ngen image matches a lookup. }; #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/prettyprintsig.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // This code supports formatting a method and it's signature in a friendly // and consistent format. // //***************************************************************************** #ifndef __PrettyPrintSig_h__ #define __PrettyPrintSig_h__ #include class CQuickBytes; // // The return value is either NULL or a null-terminated ASCII string // //--------------------------------------------------------------------------------------- // // Prints a signature in a human readable format. // No one should use this function. This exists strictly for backwards compatibility with external formats. // // Arguments: // sigPtr - Method/field sig to convert // sigLen - length of sig // name - the name of the method for this sig. Can be L"" // scratch - scratch buffer to use // pIMDI - Import api to use. // // Return Value: // The formatted string. // // Assumptions: // None // // Notes: // Dev's SHOULD NOT create new callers to this function. Use // code:PrettyPrintSig in formatype.h instead. This function exists for // legacy support in the CLR. There are places that depend on the format // of this string. // LPCWSTR PrettyPrintSigLegacy( PCCOR_SIGNATURE sigPtr, // Method/field sig to convert unsigned sigLen, // length of sig LPCWSTR name, // the name of the method for this sig. Can be L"" CQuickBytes *scratch, // scratch buffer to use IMetaDataImport *pIMDI); // Import api to use. struct IMDInternalImport; //--------------------------------------------------------------------------------------- // // Prints a signature in a human readable format. // No one should use this function. This exists strictly for backwards compatibility with external formats. // // Arguments: // sigPtr - Method/field sig to convert // sigLen - length of sig // name - the name of the method for this sig. Can be L"" // out - The buffer in which to write the pretty printed string. // pIMDI - Import api to use. // // Return Value: // An HRESULT and the formatted string is in out as a unicode string. // // Assumptions: // None // // Notes: // Dev's SHOULD NOT create new callers to this function. Use // code:PrettyPrintSig in formattype.h instead. This function exists for // legacy support in the CLR. There are places that depend on the format // of this string. // HRESULT PrettyPrintSigInternalLegacy( // S_OK or error. PCCOR_SIGNATURE sigPtr, // sig to convert, unsigned sigLen, // length of sig LPCSTR name, // can be "", the name of the method for this sig CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI); // Import api to use. // // On success, the null-terminated ASCII string is in "out.Ptr()" // #endif // __PrettyPrintSig_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/profilepriv.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // ProfilePriv.h // // // Structures, etc. used by the Profiling API and throughout the EE // // ====================================================================================== #ifndef _ProfilePriv_h_ #define _ProfilePriv_h_ // Forward declarations class EEToProfInterfaceImpl; class ProfToEEInterfaceImpl; class Object; struct ScanContext; enum EtwGCRootFlags: int32_t; enum EtwGCRootKind: int32_t; struct IAssemblyBindingClosure; struct AssemblyReferenceClosureWalkContextForProfAPI; #include "eventpipeadaptertypes.h" #if defined (PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED) #ifndef PROFILING_SUPPORTED_DATA #define PROFILING_SUPPORTED_DATA 1 #endif // PROFILING_SUPPORTED_DATA #include "corprof.h" #include "slist.h" #define MAX_NOTIFICATION_PROFILERS 32 //--------------------------------------------------------------------------------------- // Enumerates the various init states of profiling. // // *** NOTE: The order is important here, as some of the status checks (e.g., // CORProfilerPresentOrInitializing) use ">" with these enum values. *** enum ProfilerStatus { kProfStatusNone = 0, // No profiler running. kProfStatusDetaching = 1, // Prof was running, is now detaching, but still loaded kProfStatusInitializingForStartupLoad = 2, // Prof ready for (or in) its Initialize callback kProfStatusInitializingForAttachLoad = 3, // Prof ready for (or in) its InitializeForAttach callback kProfStatusActive = 4, // Prof completed initialization and is actively running kProfStatusPreInitialize = 5, // Prof is in LoadProfiler, but initialization has yet to occur }; class CurrentProfilerStatus { private: // Why volatile? // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization Volatile m_profStatus; public: void Init(); ProfilerStatus Get(); void Set(ProfilerStatus profStatus); }; class EventMask { friend class ProfControlBlock; private: const UINT64 EventMaskLowMask = 0x00000000FFFFFFFF; const UINT64 EventMaskHighShiftAmount = 32; const UINT64 EventMaskHighMask = 0xFFFFFFFF00000000; Volatile m_eventMask; public: EventMask() : m_eventMask(0) { } EventMask& operator=(const EventMask& other); BOOL IsEventMaskSet(DWORD eventMask); DWORD GetEventMask(); void SetEventMask(DWORD eventMask); BOOL IsEventMaskHighSet(DWORD eventMaskHigh); DWORD GetEventMaskHigh(); void SetEventMaskHigh(DWORD eventMaskHigh); }; class ProfilerInfo { public: // **** IMPORTANT!! **** // All uses of pProfInterface must be properly synchronized to avoid the profiler // from detaching while the EE attempts to call into it. The recommended way to do // this is to use the (lockless) BEGIN_PROFILER_CALLBACK / END_PROFILER_CALLBACK macros. See // code:BEGIN_PROFILER_CALLBACK for instructions. For full details on how the // synchronization works, see // code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization VolatilePtr pProfInterface; // **** IMPORTANT!! **** CurrentProfilerStatus curProfStatus; EventMask eventMask; Volatile inUse; DWORD slot; // Reset those variables that is only for the current attach session void ResetPerSessionStatus(); void Init(); }; enum class ProfilerCallbackType { Active, ActiveOrInitializing }; // We need a way to track which profilers are in active calls, to synchronize with detach. // If we detached a profiler while it was actively in a callback there would be issues. // However, we don't want to pin all profilers, because then a chatty profiler could // cause another profiler to not be able to detach. We can't just check the event masks // before and after the call because it is legal for a profiler to change its event mask, // and then it would be possible for a profiler to permanently prevent itself from detaching. // // WHEN IS EvacuationCounterHolder REQUIRED? // Answer: any time you access a ProfilerInfo *. There is a specific sequence that must be followed: // - Do a dirty read of the Profiler interface // - Increment an evacuation counter by using EvacuationCounterHolder as a RAII guard class // - Now do a clean read of the ProfilerInfo's status - this will be changed during detach and // is always read with a memory barrier // // The DoProfilerCallback/IterateProfilers functions automate this process for you, you should use // them unless you are absolutely sure you know what you're doing class EvacuationCounterHolder { private: ProfilerInfo *m_pProfilerInfo; Thread *m_pThread; public: EvacuationCounterHolder(ProfilerInfo *pProfilerInfo); ~EvacuationCounterHolder(); }; struct StoredProfilerNode { CLSID guid; SString path; SLink m_Link; }; typedef SList STOREDPROFILERLIST; // --------------------------------------------------------------------------------------- // Global struct that lets the EE see the load status of the profiler, and provides a // pointer (pProfInterface) through which profiler calls can be made // // When you are adding new session, please refer to // code:ProfControlBlock::ResetPerSessionStatus#ProfileResetSessionStatus for more details. class ProfControlBlock { private: // IsProfilerPresent(pProfilerInfo) returns whether or not a CLR Profiler is actively loaded // (meaning it's initialized and ready to receive callbacks). FORCEINLINE BOOL IsProfilerPresent(ProfilerInfo *pProfilerInfo) { LIMITED_METHOD_DAC_CONTRACT; return pProfilerInfo->curProfStatus.Get() >= kProfStatusActive; } FORCEINLINE BOOL IsProfilerPresentOrInitializing(ProfilerInfo *pProfilerInfo) { return pProfilerInfo->curProfStatus.Get() > kProfStatusDetaching; } template FORCEINLINE VOID DoOneProfilerIteration(ProfilerInfo *pProfilerInfo, ProfilerCallbackType callbackType, Func callback, Args... args) { // This is the dirty read if (pProfilerInfo->pProfInterface.Load() != NULL) { #ifdef FEATURE_PROFAPI_ATTACH_DETACH // Now indicate we are accessing the profiler EvacuationCounterHolder evacuationCounter(pProfilerInfo); #endif // FEATURE_PROFAPI_ATTACH_DETACH if ((callbackType == ProfilerCallbackType::Active && IsProfilerPresent(pProfilerInfo)) || (callbackType == ProfilerCallbackType::ActiveOrInitializing && IsProfilerPresentOrInitializing(pProfilerInfo))) { callback(pProfilerInfo, args...); } } } template FORCEINLINE VOID IterateProfilers(ProfilerCallbackType callbackType, Func callback, Args... args) { DoOneProfilerIteration(&mainProfilerInfo, callbackType, callback, args...); if (notificationProfilerCount > 0) { for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) { ProfilerInfo *current = &(notificationOnlyProfilers[i]); DoOneProfilerIteration(current, callbackType, callback, args...); } } } public: BOOL fGCInProgress; BOOL fBaseSystemClassesLoaded; STOREDPROFILERLIST storedProfilers; ProfilerInfo mainProfilerInfo; ProfilerInfo notificationOnlyProfilers[MAX_NOTIFICATION_PROFILERS]; Volatile notificationProfilerCount; EventMask globalEventMask; #ifdef PROF_TEST_ONLY_FORCE_ELT_DATA // #TestOnlyELT This implements a test-only (and debug-only) hook that allows a test // profiler to ensure enter/leave/tailcall is enabled on startup even though no // profiler is loaded on startup. This allows an attach profiler to use ELT to build // shadow stacks for the sole purpose of verifying OTHER areas of the profiling API // (e.g., stack walking). When this BOOL is TRUE, the JIT will insert calls to the // slow-path profiling API enter/leave/tailcall hooks, which will forward the call to // a profiler if one is loaded (and do nothing otherwise). // // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information // on how the test hooks lift restrictions normally in place for the Info functions. BOOL fTestOnlyForceEnterLeave; #endif #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED_DATA // #TestOnlyObjectAllocated This implements a test-only (and debug-only) hook that allows // a test profiler to ensure ObjectAllocated callback is enabled on startup even though no // profiler is loaded on startup. This allows an attach profiler to use ObjectAllocated // callback for the sole purpose of verifying OTHER GC areas of the profiling API // (e.g., constructing a object graph). When this BOOL is TRUE, the JIT will use special // version of new allocators that issue object allocation notifications, which will forward // the notifications to a profiler if one is loaded (and do nothing otherwise). // // See code:AreCallbackStateFlagsSet#P2CLRRestrictionsOverview for general information // on how the test hooks lift restrictions normally in place for the Info functions. BOOL fTestOnlyForceObjectAllocated; #endif #ifdef _DEBUG // Test-only, debug-only code to allow attaching profilers to call ICorProfilerInfo interface, // which would otherwise be disallowed for attaching profilers BOOL fTestOnlyEnableICorProfilerInfo; #endif // _DEBUG // Whether we've turned off concurrent GC during attach Volatile fConcurrentGCDisabledForAttach; Volatile fProfControlBlockInitialized; Volatile fProfilerRequestedRuntimeSuspend; void Init(); BOOL IsMainProfiler(EEToProfInterfaceImpl *pEEToProf); BOOL IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE); ProfilerInfo *GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE); template static void DoProfilerCallbackHelper(ProfilerInfo *pProfilerInfo, ConditionFunc condition, CallbackFunc callback, HRESULT *pHR, Args... args) { if (condition(pProfilerInfo)) { HRESULT innerHR = callback(pProfilerInfo->pProfInterface, args...); if (FAILED(innerHR)) { *pHR = innerHR; } } } template FORCEINLINE HRESULT DoProfilerCallback(ProfilerCallbackType callbackType, ConditionFunc condition, CallbackFunc callback, Args... args) { HRESULT hr = S_OK; IterateProfilers(callbackType, &DoProfilerCallbackHelper, condition, callback, &hr, args...); return hr; } #ifndef DACCESS_COMPILE ProfilerInfo *FindNextFreeProfilerInfoSlot(); void DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo); void UpdateGlobalEventMask(); #endif // DACCESS_COMPILE BOOL IsCallback3Supported(); BOOL IsCallback5Supported(); BOOL RequiresGenericsContextForEnterLeave(); UINT_PTR EEFunctionIDMapper(FunctionID funcId, BOOL * pbHookFunction); void ThreadCreated(ThreadID threadID); void ThreadDestroyed(ThreadID threadID); void ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId); void ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[]); void Shutdown(); void FunctionUnloadStarted(FunctionID functionId); void JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock); void JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock); void DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader); void DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock); void DynamicMethodUnloaded(FunctionID functionId); void JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction); void JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result); HRESULT JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline); void ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock); HRESULT GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl); void ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock); void ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus); void ModuleLoadStarted(ModuleID moduleId); void ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus); void ModuleUnloadStarted(ModuleID moduleId); void ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus); void ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId); void ModuleInMemorySymbolsUpdated(ModuleID moduleId); void ClassLoadStarted(ClassID classId); void ClassLoadFinished(ClassID classId, HRESULT hrStatus); void ClassUnloadStarted(ClassID classId); void ClassUnloadFinished(ClassID classId, HRESULT hrStatus); void AppDomainCreationStarted(AppDomainID appDomainId); void AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus); void AppDomainShutdownStarted(AppDomainID appDomainId); void AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus); void AssemblyLoadStarted(AssemblyID assemblyId); void AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus); void AssemblyUnloadStarted(AssemblyID assemblyId); void AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus); void UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason); void ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason); void ExceptionThrown(ObjectID thrownObjectId); void ExceptionSearchFunctionEnter(FunctionID functionId); void ExceptionSearchFunctionLeave(); void ExceptionSearchFilterEnter(FunctionID funcId); void ExceptionSearchFilterLeave(); void ExceptionSearchCatcherFound(FunctionID functionId); void ExceptionOSHandlerEnter(FunctionID funcId); void ExceptionOSHandlerLeave(FunctionID funcId); void ExceptionUnwindFunctionEnter(FunctionID functionId); void ExceptionUnwindFunctionLeave(); void ExceptionUnwindFinallyEnter(FunctionID functionId); void ExceptionUnwindFinallyLeave(); void ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId); void ExceptionCatcherLeave(); void COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots); void RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason); void RuntimeSuspendFinished(); void RuntimeSuspendAborted(); void RuntimeResumeStarted(); void RuntimeResumeFinished(); void RuntimeThreadSuspended(ThreadID suspendedThreadId); void RuntimeThreadResumed(ThreadID resumedThreadId); void ObjectAllocated(ObjectID objectId, ClassID classId); void FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID); void MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting); void EndMovedReferences(void *pHeapId); void RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId); void EndRootReferences2(void *pHeapId); void ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId); void EndConditionalWeakTableElementReferences(void *pHeapId); void AllocByClass(ObjectID objId, ClassID classId, void *pHeapId); void EndAllocByClass(void *pHeapId); HRESULT ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef); void HandleCreated(UINT_PTR handleId, ObjectID initialObjectId); void HandleDestroyed(UINT_PTR handleId); void GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason); void GarbageCollectionFinished(); void GetAssemblyReferences(LPCWSTR wszAssemblyPath, IAssemblyBindingClosure *pClosure, AssemblyReferenceClosureWalkContextForProfAPI *pContext); void EventPipeEventDelivered(EventPipeProvider *provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread, ULONG numStackFrames, UINT_PTR stackFrames[]); void EventPipeProviderCreated(EventPipeProvider *provider); }; GVAL_DECL(ProfControlBlock, g_profControlBlock); // Provides definitions of the CORProfilerTrack* functions that test whether a profiler // is active and responding to various callbacks #include "profilepriv.inl" //--------------------------------------------------------------- // Bit flags used to track profiler callback execution state, such as which // ICorProfilerCallback method we're currently executing. These help us enforce the // invariants of which calls a profiler is allowed to make at given times. These flags // are stored in Thread::m_profilerCallbackState. // // For now, we ensure: // * Only asynchronous-safe calls are made asynchronously (i.e., are made from // outside of profiler callbacks). // * GC_TRIGGERS info methods are not called from GC_NOTRIGGER callbacks // // Later, we may choose to enforce even more refined call trees and add more flags. #define COR_PRF_CALLBACKSTATE_INCALLBACK 0x1 #define COR_PRF_CALLBACKSTATE_IN_TRIGGERS_SCOPE 0x2 #define COR_PRF_CALLBACKSTATE_FORCEGC_WAS_CALLED 0x4 #define COR_PRF_CALLBACKSTATE_REJIT_WAS_CALLED 0x8 // //--------------------------------------------------------------- #endif // defined(PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED) // This is the helper callback that the gc uses when walking the heap. bool HeapWalkHelper(Object* pBO, void* pv); void ScanRootsHelper(Object* pObj, Object** ppRoot, ScanContext *pSC, uint32_t dwUnused); bool AllocByClassHelper(Object* pBO, void* pv); #endif // _ProfilePriv_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/profilepriv.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // ProfilePriv.inl // // // Inlined functions used by the Profiling API and throughout the EE. Most notably are // the CORProfilerTrack* functions that test whether a profiler is active and responding // to various callbacks // // ====================================================================================== #ifndef _ProfilePriv_inl_ #define _ProfilePriv_inl_ #include "eetoprofinterfaceimpl.h" #ifdef PROFILING_SUPPORTED #include "profilinghelper.h" #endif // PROFILING_SUPPORTED //--------------------------------------------------------------------------------------- // CurrentProfilerStatus //--------------------------------------------------------------------------------------- inline void CurrentProfilerStatus::Init() { LIMITED_METHOD_CONTRACT; m_profStatus = kProfStatusNone; } inline ProfilerStatus CurrentProfilerStatus::Get() { LIMITED_METHOD_DAC_CONTRACT; return m_profStatus; } inline EventMask& EventMask::operator=(const EventMask& other) { m_eventMask = other.m_eventMask; return *this; } inline BOOL EventMask::IsEventMaskSet(DWORD eventMask) { return (GetEventMask() & eventMask) != 0; } inline DWORD EventMask::GetEventMask() { return (DWORD)(m_eventMask & EventMaskLowMask); } inline void EventMask::SetEventMask(DWORD eventMask) { m_eventMask = (m_eventMask & EventMaskHighMask) | (UINT64)eventMask; } inline BOOL EventMask::IsEventMaskHighSet(DWORD eventMaskHigh) { return (GetEventMaskHigh() & eventMaskHigh) != 0; } inline DWORD EventMask::GetEventMaskHigh() { return (DWORD)((m_eventMask & EventMaskHighMask) >> EventMaskHighShiftAmount); } inline void EventMask::SetEventMaskHigh(DWORD eventMaskHigh) { m_eventMask = (m_eventMask & EventMaskLowMask) | ((UINT64)eventMaskHigh << EventMaskHighShiftAmount); } // Reset those variables that is only for the current attach session inline void ProfilerInfo::ResetPerSessionStatus() { LIMITED_METHOD_CONTRACT; pProfInterface = NULL; eventMask.SetEventMask(COR_PRF_MONITOR_NONE); eventMask.SetEventMaskHigh(COR_PRF_HIGH_MONITOR_NONE); } inline void ProfilerInfo::Init() { curProfStatus.Init(); ResetPerSessionStatus(); inUse = FALSE; } inline HRESULT AnyProfilerPassesConditionHelper(EEToProfInterfaceImpl *profInterface, BOOL *pAnyPassed) { *pAnyPassed = TRUE; return S_OK; } template FORCEINLINE BOOL AnyProfilerPassesCondition(ConditionFunc condition) { BOOL anyPassed = FALSE; (&g_profControlBlock)->DoProfilerCallback(ProfilerCallbackType::ActiveOrInitializing, condition, &AnyProfilerPassesConditionHelper, &anyPassed); return anyPassed; } //--------------------------------------------------------------------------------------- // ProfControlBlock //--------------------------------------------------------------------------------------- inline void ProfControlBlock::Init() { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; mainProfilerInfo.Init(); // Special magic value for the main one mainProfilerInfo.slot = MAX_NOTIFICATION_PROFILERS; for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) { notificationOnlyProfilers[i].Init(); notificationOnlyProfilers[i].slot = (DWORD)i; } globalEventMask.SetEventMask(COR_PRF_MONITOR_NONE); globalEventMask.SetEventMaskHigh(COR_PRF_HIGH_MONITOR_NONE); fGCInProgress = FALSE; fBaseSystemClassesLoaded = FALSE; #ifdef PROF_TEST_ONLY_FORCE_ELT fTestOnlyForceEnterLeave = FALSE; #endif #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED fTestOnlyForceObjectAllocated = FALSE; #endif #ifdef _DEBUG fTestOnlyEnableICorProfilerInfo = FALSE; #endif // _DEBUG fConcurrentGCDisabledForAttach = FALSE; mainProfilerInfo.ResetPerSessionStatus(); fProfControlBlockInitialized = TRUE; fProfilerRequestedRuntimeSuspend = FALSE; } inline BOOL ProfControlBlock::IsMainProfiler(EEToProfInterfaceImpl *pEEToProf) { EEToProfInterfaceImpl *pProfInterface = mainProfilerInfo.pProfInterface.Load(); return pProfInterface == pEEToProf; } inline BOOL ProfControlBlock::IsMainProfiler(ProfToEEInterfaceImpl *pProfToEE) { EEToProfInterfaceImpl *pProfInterface = mainProfilerInfo.pProfInterface.Load(); return pProfInterface != NULL && pProfInterface->m_pProfToEE == pProfToEE; } inline void GetProfilerInfoHelper(ProfilerInfo *pProfilerInfo, ProfToEEInterfaceImpl *pProfToEE, ProfilerInfo **ppFoundProfilerInfo) { if (pProfilerInfo->pProfInterface->GetProfToEE() == pProfToEE) { *ppFoundProfilerInfo = pProfilerInfo; } } inline ProfilerInfo *ProfControlBlock::GetProfilerInfo(ProfToEEInterfaceImpl *pProfToEE) { ProfilerInfo *pProfilerInfo = NULL; IterateProfilers(ProfilerCallbackType::ActiveOrInitializing, &GetProfilerInfoHelper, pProfToEE, &pProfilerInfo); return pProfilerInfo; } #ifndef DACCESS_COMPILE inline ProfilerInfo *ProfControlBlock::FindNextFreeProfilerInfoSlot() { for (SIZE_T i = 0; i < MAX_NOTIFICATION_PROFILERS; ++i) { if (InterlockedCompareExchange((LONG *)notificationOnlyProfilers[i].inUse.GetPointer(), TRUE, FALSE) == FALSE) { InterlockedIncrement(notificationProfilerCount.GetPointer()); return &(notificationOnlyProfilers[i]); } } return NULL; } inline void ProfControlBlock::DeRegisterProfilerInfo(ProfilerInfo *pProfilerInfo) { pProfilerInfo->inUse = FALSE; InterlockedDecrement(notificationProfilerCount.GetPointer()); } inline void UpdateGlobalEventMaskHelper(ProfilerInfo *pProfilerInfo, DWORD *pEventMask) { *pEventMask |= pProfilerInfo->eventMask.GetEventMask(); } inline void UpdateGlobalEventMaskHighHelper(ProfilerInfo *pProfilerInfo, DWORD *pEventMaskHigh) { *pEventMaskHigh |= pProfilerInfo->eventMask.GetEventMaskHigh(); } inline void ProfControlBlock::UpdateGlobalEventMask() { while (true) { UINT64 originalEventMask = globalEventMask.m_eventMask; UINT64 qwEventMask = 0; IterateProfilers(ProfilerCallbackType::ActiveOrInitializing, [](ProfilerInfo *pProfilerInfo, UINT64 *pEventMask) { *pEventMask |= pProfilerInfo->eventMask.m_eventMask; }, &qwEventMask); // We are relying on the memory barrier introduced by InterlockedCompareExchange64 to observer any // change to the global event mask. if ((UINT64)InterlockedCompareExchange64((LONG64 *)&(globalEventMask.m_eventMask), (LONG64)qwEventMask, (LONG64)originalEventMask) == originalEventMask) { break; } } } #endif // DACCESS_COMPILE inline BOOL IsCallback3SupportedHelper(ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback3Supported(); } FORCEINLINE BOOL ProfControlBlock::IsCallback3Supported() { return AnyProfilerPassesCondition(&IsCallback3SupportedHelper); } inline BOOL IsCallback5SupportedHelper(ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->IsCallback5Supported(); } FORCEINLINE BOOL ProfControlBlock::IsCallback5Supported() { return AnyProfilerPassesCondition(&IsCallback5SupportedHelper); } inline BOOL RequiresGenericsContextForEnterLeaveHelper(ProfilerInfo *pProfilerInfo) { return pProfilerInfo->pProfInterface->RequiresGenericsContextForEnterLeave(); } FORCEINLINE BOOL ProfControlBlock::RequiresGenericsContextForEnterLeave() { return AnyProfilerPassesCondition(&RequiresGenericsContextForEnterLeaveHelper); } inline bool DoesProfilerWantEEFunctionIDMapper(ProfilerInfo *pProfilerInfo) { return ((pProfilerInfo->pProfInterface->GetFunctionIDMapper() != NULL) || (pProfilerInfo->pProfInterface->GetFunctionIDMapper2() != NULL)); } inline void EEFunctionIDMapperHelper(ProfilerInfo *pProfilerInfo, FunctionID funcId, BOOL *pbHookFunction, UINT_PTR *pPtr) { if (DoesProfilerWantEEFunctionIDMapper(pProfilerInfo)) { *pPtr = pProfilerInfo->pProfInterface->EEFunctionIDMapper(funcId, pbHookFunction); } } inline UINT_PTR ProfControlBlock::EEFunctionIDMapper(FunctionID funcId, BOOL *pbHookFunction) { LIMITED_METHOD_CONTRACT; UINT_PTR ptr = NULL; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, &EEFunctionIDMapperHelper, funcId, pbHookFunction, &ptr); return ptr; } inline BOOL IsProfilerTrackingThreads(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS); } inline HRESULT ThreadCreatedHelper(EEToProfInterfaceImpl *profInterface, ThreadID threadID) { return profInterface->ThreadCreated(threadID); } inline void ProfControlBlock::ThreadCreated(ThreadID threadID) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, &ThreadCreatedHelper, threadID); } inline HRESULT ThreadDestroyedHelper(EEToProfInterfaceImpl *profInterface, ThreadID threadID) { return profInterface->ThreadDestroyed(threadID); } inline void ProfControlBlock::ThreadDestroyed(ThreadID threadID) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, &ThreadDestroyedHelper, threadID); } inline HRESULT ThreadAssignedToOSThreadHelper(EEToProfInterfaceImpl *profInterface, ThreadID managedThreadId, DWORD osThreadId) { return profInterface->ThreadAssignedToOSThread(managedThreadId, osThreadId); } inline void ProfControlBlock::ThreadAssignedToOSThread(ThreadID managedThreadId, DWORD osThreadId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, &ThreadAssignedToOSThreadHelper, managedThreadId, osThreadId); } inline HRESULT ThreadNameChangedHelper(EEToProfInterfaceImpl *profInterface, ThreadID managedThreadId, ULONG cchName, WCHAR name[]) { return profInterface->ThreadNameChanged(managedThreadId, cchName, name); } inline void ProfControlBlock::ThreadNameChanged(ThreadID managedThreadId, ULONG cchName, WCHAR name[]) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingThreads, &ThreadNameChangedHelper, managedThreadId, cchName, name); } inline HRESULT ShutdownHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->Shutdown(); } inline void ProfControlBlock::Shutdown() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, [](ProfilerInfo *pProfilerInfo) { return true; }, &ShutdownHelper); } inline BOOL IsProfilerTrackingJITInfo(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION); } inline HRESULT JITCompilationFinishedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { return profInterface->JITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); } inline void ProfControlBlock::JITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, &JITCompilationFinishedHelper, functionId, hrStatus, fIsSafeToBlock); } inline HRESULT JITCompilationStartedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, BOOL fIsSafeToBlock) { return profInterface->JITCompilationStarted(functionId, fIsSafeToBlock); } inline void ProfControlBlock::JITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, &JITCompilationStartedHelper, functionId, fIsSafeToBlock); } inline HRESULT DynamicMethodJITCompilationStartedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) { return profInterface->DynamicMethodJITCompilationStarted(functionId, fIsSafeToBlock, pILHeader, cbILHeader); } inline void ProfControlBlock::DynamicMethodJITCompilationStarted(FunctionID functionId, BOOL fIsSafeToBlock, LPCBYTE pILHeader, ULONG cbILHeader) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, &DynamicMethodJITCompilationStartedHelper, functionId, fIsSafeToBlock, pILHeader, cbILHeader); } inline HRESULT DynamicMethodJITCompilationFinishedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { return profInterface->DynamicMethodJITCompilationFinished(functionId, hrStatus, fIsSafeToBlock); } inline void ProfControlBlock::DynamicMethodJITCompilationFinished(FunctionID functionId, HRESULT hrStatus, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, &DynamicMethodJITCompilationFinishedHelper, functionId, hrStatus, fIsSafeToBlock); } inline BOOL IsProfilerMonitoringDynamicFunctionUnloads(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS); } inline HRESULT DynamicMethodUnloadedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) { return profInterface->DynamicMethodUnloaded(functionId); } inline void ProfControlBlock::DynamicMethodUnloaded(FunctionID functionId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerMonitoringDynamicFunctionUnloads, &DynamicMethodUnloadedHelper, functionId); } inline BOOL IsProfilerTrackingCacheSearches(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES); } inline HRESULT JITCachedFunctionSearchStartedHelper(EEToProfInterfaceImpl *profInterface, BOOL *pAllTrue, FunctionID functionId) { BOOL fUseCachedFunction = TRUE; HRESULT hr = profInterface->JITCachedFunctionSearchStarted(functionId, &fUseCachedFunction); *pAllTrue = *pAllTrue && fUseCachedFunction; return hr; } inline void ProfControlBlock::JITCachedFunctionSearchStarted(FunctionID functionId, BOOL *pbUseCachedFunction) { LIMITED_METHOD_CONTRACT; BOOL allTrue = TRUE; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingCacheSearches, &JITCachedFunctionSearchStartedHelper, &allTrue, functionId); // If any reject it, consider it rejected. *pbUseCachedFunction = allTrue; } inline HRESULT JITCachedFunctionSearchFinishedHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, COR_PRF_JIT_CACHE result) { return profInterface->JITCachedFunctionSearchFinished(functionId, result); } inline void ProfControlBlock::JITCachedFunctionSearchFinished(FunctionID functionId, COR_PRF_JIT_CACHE result) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingCacheSearches, &JITCachedFunctionSearchFinishedHelper, functionId, result); } inline HRESULT JITInliningHelper(EEToProfInterfaceImpl *profInterface, BOOL *pAllTrue, FunctionID callerId, FunctionID calleeId) { BOOL fShouldInline = TRUE; HRESULT hr = profInterface->JITInlining(callerId, calleeId, &fShouldInline); *pAllTrue = *pAllTrue && fShouldInline; return hr; } inline HRESULT ProfControlBlock::JITInlining(FunctionID callerId, FunctionID calleeId, BOOL *pfShouldInline) { LIMITED_METHOD_CONTRACT; *pfShouldInline = TRUE; BOOL allTrue = TRUE; HRESULT hr = DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingJITInfo, &JITInliningHelper, &allTrue, callerId, calleeId); // If any reject it, consider it rejected. *pfShouldInline = allTrue; return hr; } inline BOOL IsRejitEnabled(ProfilerInfo *pProfilerInfo) { return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT); } inline void ReJITCompilationStartedHelper(ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) { if (IsRejitEnabled(pProfilerInfo)) { pProfilerInfo->pProfInterface->ReJITCompilationStarted(functionId, reJitId, fIsSafeToBlock); } } inline void ProfControlBlock::ReJITCompilationStarted(FunctionID functionId, ReJITID reJitId, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, &ReJITCompilationStartedHelper, functionId, reJitId, fIsSafeToBlock); } inline void GetReJITParametersHelper(ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl, HRESULT *pHr) { if (IsRejitEnabled(pProfilerInfo)) { *pHr = pProfilerInfo->pProfInterface->GetReJITParameters(moduleId, methodId, pFunctionControl); } } inline HRESULT ProfControlBlock::GetReJITParameters(ModuleID moduleId, mdMethodDef methodId, ICorProfilerFunctionControl *pFunctionControl) { LIMITED_METHOD_CONTRACT; HRESULT hr = S_OK; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, &GetReJITParametersHelper, moduleId, methodId, pFunctionControl, &hr); return hr; } inline void ReJITCompilationFinishedHelper(ProfilerInfo *pProfilerInfo, FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) { if (IsRejitEnabled(pProfilerInfo)) { pProfilerInfo->pProfInterface->ReJITCompilationFinished(functionId, reJitId, hrStatus, fIsSafeToBlock); } } inline void ProfControlBlock::ReJITCompilationFinished(FunctionID functionId, ReJITID reJitId, HRESULT hrStatus, BOOL fIsSafeToBlock) { LIMITED_METHOD_CONTRACT; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, &ReJITCompilationFinishedHelper, functionId, reJitId, hrStatus, fIsSafeToBlock); } inline void ReJITErrorHelper(ProfilerInfo *pProfilerInfo, ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) { if (IsRejitEnabled(pProfilerInfo)) { pProfilerInfo->pProfInterface->ReJITError(moduleId, methodId, functionId, hrStatus); } } inline void ProfControlBlock::ReJITError(ModuleID moduleId, mdMethodDef methodId, FunctionID functionId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoOneProfilerIteration(&mainProfilerInfo, ProfilerCallbackType::Active, &ReJITErrorHelper, moduleId, methodId, functionId, hrStatus); } inline BOOL IsProfilerTrackingModuleLoads(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS); } inline HRESULT ModuleLoadStartedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId) { return profInterface->ModuleLoadStarted(moduleId); } inline void ProfControlBlock::ModuleLoadStarted(ModuleID moduleId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, &ModuleLoadStartedHelper, moduleId); } inline HRESULT ModuleLoadFinishedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId, HRESULT hrStatus) { return profInterface->ModuleLoadFinished(moduleId, hrStatus); } inline void ProfControlBlock::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, &ModuleLoadFinishedHelper, moduleId, hrStatus); } inline HRESULT ModuleUnloadStartedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId) { return profInterface->ModuleUnloadStarted(moduleId); } inline void ProfControlBlock::ModuleUnloadStarted(ModuleID moduleId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, &ModuleUnloadStartedHelper, moduleId); } inline HRESULT ModuleUnloadFinishedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId, HRESULT hrStatus) { return profInterface->ModuleUnloadFinished(moduleId, hrStatus); } inline void ProfControlBlock::ModuleUnloadFinished(ModuleID moduleId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, &ModuleUnloadFinishedHelper, moduleId, hrStatus); } inline HRESULT ModuleAttachedToAssemblyHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId, AssemblyID AssemblyId) { return profInterface->ModuleAttachedToAssembly(moduleId, AssemblyId); } inline void ProfControlBlock::ModuleAttachedToAssembly(ModuleID moduleId, AssemblyID AssemblyId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingModuleLoads, &ModuleAttachedToAssemblyHelper, moduleId, AssemblyId); } inline BOOL IsProfilerTrackingInMemorySymbolsUpdatesEnabled(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED); } inline HRESULT ModuleInMemorySymbolsUpdatedHelper(EEToProfInterfaceImpl *profInterface, ModuleID moduleId) { return profInterface->ModuleInMemorySymbolsUpdated(moduleId); } inline void ProfControlBlock::ModuleInMemorySymbolsUpdated(ModuleID moduleId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingInMemorySymbolsUpdatesEnabled, &ModuleInMemorySymbolsUpdatedHelper, moduleId); } inline BOOL IsProfilerTrackingClasses(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS); } inline HRESULT ClassLoadStartedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId) { return profInterface->ClassLoadStarted(classId); } inline void ProfControlBlock::ClassLoadStarted(ClassID classId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, &ClassLoadStartedHelper, classId); } inline HRESULT ClassLoadFinishedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId, HRESULT hrStatus) { return profInterface->ClassLoadFinished(classId, hrStatus); } inline void ProfControlBlock::ClassLoadFinished(ClassID classId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, &ClassLoadFinishedHelper, classId, hrStatus); } inline HRESULT ClassUnloadStartedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId) { return profInterface->ClassUnloadStarted(classId); } inline void ProfControlBlock::ClassUnloadStarted(ClassID classId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, &ClassUnloadStartedHelper, classId); } inline HRESULT ClassUnloadFinishedHelper(EEToProfInterfaceImpl *profInterface, ClassID classId, HRESULT hrStatus) { return profInterface->ClassUnloadFinished(classId, hrStatus); } inline void ProfControlBlock::ClassUnloadFinished(ClassID classId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingClasses, &ClassUnloadFinishedHelper, classId, hrStatus); } inline BOOL IsProfilerTrackingAppDomainLoads(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS); } inline HRESULT AppDomainCreationStartedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId) { return profInterface->AppDomainCreationStarted(appDomainId); } inline void ProfControlBlock::AppDomainCreationStarted(AppDomainID appDomainId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, &AppDomainCreationStartedHelper, appDomainId); } inline HRESULT AppDomainCreationFinishedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId, HRESULT hrStatus) { return profInterface->AppDomainCreationFinished(appDomainId, hrStatus); } inline void ProfControlBlock::AppDomainCreationFinished(AppDomainID appDomainId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, &AppDomainCreationFinishedHelper, appDomainId, hrStatus); } inline HRESULT AppDomainShutdownStartedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId) { return profInterface->AppDomainShutdownStarted(appDomainId); } inline void ProfControlBlock::AppDomainShutdownStarted(AppDomainID appDomainId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, &AppDomainShutdownStartedHelper, appDomainId); } inline HRESULT AppDomainShutdownFinishedHelper(EEToProfInterfaceImpl *profInterface, AppDomainID appDomainId, HRESULT hrStatus) { return profInterface->AppDomainShutdownFinished(appDomainId, hrStatus); } inline void ProfControlBlock::AppDomainShutdownFinished(AppDomainID appDomainId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAppDomainLoads, &AppDomainShutdownFinishedHelper, appDomainId, hrStatus); } inline BOOL IsProfilerTrackingAssemblyLoads(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS); } inline HRESULT AssemblyLoadStartedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId) { return profInterface->AssemblyLoadStarted(assemblyId); } inline void ProfControlBlock::AssemblyLoadStarted(AssemblyID assemblyId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, &AssemblyLoadStartedHelper, assemblyId); } inline HRESULT AssemblyLoadFinishedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId, HRESULT hrStatus) { return profInterface->AssemblyLoadFinished(assemblyId, hrStatus); } inline void ProfControlBlock::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, &AssemblyLoadFinishedHelper, assemblyId, hrStatus); } inline HRESULT AssemblyUnloadStartedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId) { return profInterface->AssemblyUnloadStarted(assemblyId); } inline void ProfControlBlock::AssemblyUnloadStarted(AssemblyID assemblyId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, &AssemblyUnloadStartedHelper, assemblyId); } inline HRESULT AssemblyUnloadFinishedHelper(EEToProfInterfaceImpl *profInterface, AssemblyID assemblyId, HRESULT hrStatus) { return profInterface->AssemblyUnloadFinished(assemblyId, hrStatus); } inline void ProfControlBlock::AssemblyUnloadFinished(AssemblyID assemblyId, HRESULT hrStatus) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAssemblyLoads, &AssemblyUnloadFinishedHelper, assemblyId, hrStatus); } inline BOOL IsProfilerTrackingTransitions(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS); } inline HRESULT UnmanagedToManagedTransitionHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { return profInterface->UnmanagedToManagedTransition(functionId, reason); } inline void ProfControlBlock::UnmanagedToManagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingTransitions, &UnmanagedToManagedTransitionHelper, functionId, reason); } inline HRESULT ManagedToUnmanagedTransitionHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { return profInterface->ManagedToUnmanagedTransition(functionId, reason); } inline void ProfControlBlock::ManagedToUnmanagedTransition(FunctionID functionId, COR_PRF_TRANSITION_REASON reason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingTransitions, &ManagedToUnmanagedTransitionHelper, functionId, reason); } inline BOOL IsProfilerTrackingExceptions(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS); } inline HRESULT ExceptionThrownHelper(EEToProfInterfaceImpl *profInterface, ObjectID thrownObjectId) { return profInterface->ExceptionThrown(thrownObjectId); } inline void ProfControlBlock::ExceptionThrown(ObjectID thrownObjectId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionThrownHelper, thrownObjectId); } inline HRESULT ExceptionSearchFunctionEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) { return profInterface->ExceptionSearchFunctionEnter(functionId); } inline void ProfControlBlock::ExceptionSearchFunctionEnter(FunctionID functionId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionSearchFunctionEnterHelper, functionId); } inline HRESULT ExceptionSearchFunctionLeaveHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->ExceptionSearchFunctionLeave(); } inline void ProfControlBlock::ExceptionSearchFunctionLeave() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionSearchFunctionLeaveHelper); } inline HRESULT ExceptionSearchFilterEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID funcId) { return profInterface->ExceptionSearchFilterEnter(funcId); } inline void ProfControlBlock::ExceptionSearchFilterEnter(FunctionID funcId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionSearchFilterEnterHelper, funcId); } inline HRESULT ExceptionSearchFilterLeaveHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->ExceptionSearchFilterLeave(); } inline void ProfControlBlock::ExceptionSearchFilterLeave() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionSearchFilterLeaveHelper); } inline HRESULT ExceptionSearchCatcherFoundHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) { return profInterface->ExceptionSearchCatcherFound(functionId); } inline void ProfControlBlock::ExceptionSearchCatcherFound(FunctionID functionId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionSearchCatcherFoundHelper, functionId); } inline HRESULT ExceptionOSHandlerEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID funcId) { return profInterface->ExceptionOSHandlerEnter(funcId); } inline void ProfControlBlock::ExceptionOSHandlerEnter(FunctionID funcId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionOSHandlerEnterHelper, funcId); } inline HRESULT ExceptionOSHandlerLeaveHelper(EEToProfInterfaceImpl *profInterface, FunctionID funcId) { return profInterface->ExceptionOSHandlerLeave(funcId); } inline void ProfControlBlock::ExceptionOSHandlerLeave(FunctionID funcId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionOSHandlerLeaveHelper, funcId); } inline HRESULT ExceptionUnwindFunctionEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) { return profInterface->ExceptionUnwindFunctionEnter(functionId); } inline void ProfControlBlock::ExceptionUnwindFunctionEnter(FunctionID functionId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionUnwindFunctionEnterHelper, functionId); } inline HRESULT ExceptionUnwindFunctionLeaveHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->ExceptionUnwindFunctionLeave(); } inline void ProfControlBlock::ExceptionUnwindFunctionLeave() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionUnwindFunctionLeaveHelper); } inline HRESULT ExceptionUnwindFinallyEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId) { return profInterface->ExceptionUnwindFinallyEnter(functionId); } inline void ProfControlBlock::ExceptionUnwindFinallyEnter(FunctionID functionId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionUnwindFinallyEnterHelper, functionId); } inline HRESULT ExceptionUnwindFinallyLeaveHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->ExceptionUnwindFinallyLeave(); } inline void ProfControlBlock::ExceptionUnwindFinallyLeave() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionUnwindFinallyLeaveHelper); } inline HRESULT ExceptionCatcherEnterHelper(EEToProfInterfaceImpl *profInterface, FunctionID functionId, ObjectID objectId) { return profInterface->ExceptionCatcherEnter(functionId, objectId); } inline void ProfControlBlock::ExceptionCatcherEnter(FunctionID functionId, ObjectID objectId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionCatcherEnterHelper, functionId, objectId); } inline HRESULT ExceptionCatcherLeaveHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->ExceptionCatcherLeave(); } inline void ProfControlBlock::ExceptionCatcherLeave() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingExceptions, &ExceptionCatcherLeaveHelper); } inline BOOL IsProfilerTrackingCCW(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW); } inline HRESULT COMClassicVTableCreatedHelper(EEToProfInterfaceImpl *profInterface, ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) { return profInterface->COMClassicVTableCreated(wrappedClassId, implementedIID, pVTable, cSlots); } inline void ProfControlBlock::COMClassicVTableCreated(ClassID wrappedClassId, REFGUID implementedIID, void *pVTable, ULONG cSlots) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingCCW, &COMClassicVTableCreatedHelper, wrappedClassId, implementedIID, pVTable, cSlots); } inline BOOL IsProfilerTrackingSuspends(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS); } inline HRESULT RuntimeSuspendStartedHelper(EEToProfInterfaceImpl *profInterface, COR_PRF_SUSPEND_REASON suspendReason) { return profInterface->RuntimeSuspendStarted(suspendReason); } inline void ProfControlBlock::RuntimeSuspendStarted(COR_PRF_SUSPEND_REASON suspendReason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeSuspendStartedHelper, suspendReason); } inline HRESULT RuntimeSuspendFinishedHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->RuntimeSuspendFinished(); } inline void ProfControlBlock::RuntimeSuspendFinished() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeSuspendFinishedHelper); } inline HRESULT RuntimeSuspendAbortedHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->RuntimeSuspendAborted(); } inline void ProfControlBlock::RuntimeSuspendAborted() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeSuspendAbortedHelper); } inline HRESULT RuntimeResumeStartedHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->RuntimeResumeStarted(); } inline void ProfControlBlock::RuntimeResumeStarted() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeResumeStartedHelper); } inline HRESULT RuntimeResumeFinishedHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->RuntimeResumeFinished(); } inline void ProfControlBlock::RuntimeResumeFinished() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeResumeFinishedHelper); } inline HRESULT RuntimeThreadSuspendedHelper(EEToProfInterfaceImpl *profInterface, ThreadID suspendedThreadId) { return profInterface->RuntimeThreadSuspended(suspendedThreadId); } inline void ProfControlBlock::RuntimeThreadSuspended(ThreadID suspendedThreadId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeThreadSuspendedHelper, suspendedThreadId); } inline HRESULT RuntimeThreadResumedHelper(EEToProfInterfaceImpl *profInterface, ThreadID resumedThreadId) { return profInterface->RuntimeThreadResumed(resumedThreadId); } inline void ProfControlBlock::RuntimeThreadResumed(ThreadID resumedThreadId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingSuspends, &RuntimeThreadResumedHelper, resumedThreadId); } inline BOOL IsProfilerTrackingAllocations(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return (pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED) || pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED)); } inline HRESULT ObjectAllocatedHelper(EEToProfInterfaceImpl *profInterface, ObjectID objectId, ClassID classId) { return profInterface->ObjectAllocated(objectId, classId); } inline void ProfControlBlock::ObjectAllocated(ObjectID objectId, ClassID classId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingAllocations, &ObjectAllocatedHelper, objectId, classId); } inline BOOL IsProfilerTrackingGC(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskSet(COR_PRF_MONITOR_GC); } inline HRESULT FinalizeableObjectQueuedHelper(EEToProfInterfaceImpl *profInterface, BOOL isCritical, ObjectID objectID) { return profInterface->FinalizeableObjectQueued(isCritical, objectID); } inline void ProfControlBlock::FinalizeableObjectQueued(BOOL isCritical, ObjectID objectID) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &FinalizeableObjectQueuedHelper, isCritical, objectID); } inline HRESULT MovedReferenceHelper(EEToProfInterfaceImpl *profInterface, BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) { return profInterface->MovedReference(pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); } inline void ProfControlBlock::MovedReference(BYTE *pbMemBlockStart, BYTE *pbMemBlockEnd, ptrdiff_t cbRelocDistance, void *pHeapId, BOOL fCompacting) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &MovedReferenceHelper, pbMemBlockStart, pbMemBlockEnd, cbRelocDistance, pHeapId, fCompacting); } inline HRESULT EndMovedReferencesHelper(EEToProfInterfaceImpl *profInterface, void *pHeapId) { return profInterface->EndMovedReferences(pHeapId); } inline void ProfControlBlock::EndMovedReferences(void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &EndMovedReferencesHelper, pHeapId); } inline HRESULT RootReference2Helper(EEToProfInterfaceImpl *profInterface, BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) { return profInterface->RootReference2(objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); } inline void ProfControlBlock::RootReference2(BYTE *objectId, EtwGCRootKind dwEtwRootKind, EtwGCRootFlags dwEtwRootFlags, void *rootID, void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &RootReference2Helper, objectId, dwEtwRootKind, dwEtwRootFlags, rootID, pHeapId); } inline HRESULT EndRootReferences2Helper(EEToProfInterfaceImpl *profInterface, void *pHeapId) { return profInterface->EndRootReferences2(pHeapId); } inline void ProfControlBlock::EndRootReferences2(void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &EndRootReferences2Helper, pHeapId); } inline HRESULT ConditionalWeakTableElementReferenceHelper(EEToProfInterfaceImpl *profInterface, BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) { if (!profInterface->IsCallback5Supported()) { return S_OK; } return profInterface->ConditionalWeakTableElementReference(primaryObjectId, secondaryObjectId, rootID, pHeapId); } inline void ProfControlBlock::ConditionalWeakTableElementReference(BYTE *primaryObjectId, BYTE *secondaryObjectId, void *rootID, void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &ConditionalWeakTableElementReferenceHelper, primaryObjectId, secondaryObjectId, rootID, pHeapId); } inline HRESULT EndConditionalWeakTableElementReferencesHelper(EEToProfInterfaceImpl *profInterface, void *pHeapId) { if (!profInterface->IsCallback5Supported()) { return S_OK; } return profInterface->EndConditionalWeakTableElementReferences(pHeapId); } inline void ProfControlBlock::EndConditionalWeakTableElementReferences(void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &EndConditionalWeakTableElementReferencesHelper, pHeapId); } inline HRESULT AllocByClassHelper(EEToProfInterfaceImpl *profInterface, ObjectID objId, ClassID classId, void *pHeapId) { return profInterface->AllocByClass(objId, classId, pHeapId); } inline void ProfControlBlock::AllocByClass(ObjectID objId, ClassID classId, void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &AllocByClassHelper, objId, classId, pHeapId); } inline HRESULT EndAllocByClassHelper(EEToProfInterfaceImpl *profInterface, void *pHeapId) { return profInterface->EndAllocByClass(pHeapId); } inline void ProfControlBlock::EndAllocByClass(void *pHeapId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &EndAllocByClassHelper, pHeapId); } inline HRESULT ObjectReferenceHelper(EEToProfInterfaceImpl *profInterface, ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) { return profInterface->ObjectReference(objId, classId, cNumRefs, arrObjRef); } inline HRESULT ProfControlBlock::ObjectReference(ObjectID objId, ClassID classId, ULONG cNumRefs, ObjectID *arrObjRef) { LIMITED_METHOD_CONTRACT; return DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &ObjectReferenceHelper, objId, classId, cNumRefs, arrObjRef); } inline HRESULT HandleCreatedHelper(EEToProfInterfaceImpl *profInterface, UINT_PTR handleId, ObjectID initialObjectId) { return profInterface->HandleCreated(handleId, initialObjectId); } inline void ProfControlBlock::HandleCreated(UINT_PTR handleId, ObjectID initialObjectId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &HandleCreatedHelper, handleId, initialObjectId); } inline HRESULT HandleDestroyedHelper(EEToProfInterfaceImpl *profInterface, UINT_PTR handleId) { return profInterface->HandleDestroyed(handleId); } inline void ProfControlBlock::HandleDestroyed(UINT_PTR handleId) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGC, &HandleDestroyedHelper, handleId); } inline BOOL IsProfilerTrackingBasicGC(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC); } inline BOOL IsProfilerTrackingMovedObjects(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS); } inline BOOL IsProfilerTrackingGCOrBasicGC(ProfilerInfo *pProfilerInfo) { return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingBasicGC(pProfilerInfo); } inline BOOL IsProfilerTrackingGCOrMovedObjects(ProfilerInfo *pProfilerInfo) { return IsProfilerTrackingGC(pProfilerInfo) || IsProfilerTrackingMovedObjects(pProfilerInfo); } inline HRESULT GarbageCollectionStartedHelper(EEToProfInterfaceImpl *profInterface, int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) { return profInterface->GarbageCollectionStarted(cGenerations, generationCollected, reason); } inline void ProfControlBlock::GarbageCollectionStarted(int cGenerations, BOOL generationCollected[], COR_PRF_GC_REASON reason) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGCOrBasicGC, &GarbageCollectionStartedHelper, cGenerations, generationCollected, reason); } inline HRESULT GarbageCollectionFinishedHelper(EEToProfInterfaceImpl *profInterface) { return profInterface->GarbageCollectionFinished(); } inline void ProfControlBlock::GarbageCollectionFinished() { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerTrackingGCOrBasicGC, &GarbageCollectionFinishedHelper); } inline BOOL IsProfilerMonitoringEventPipe(ProfilerInfo *pProfilerInfo) { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; } CONTRACTL_END; return pProfilerInfo->eventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE); } inline HRESULT EventPipeEventDeliveredHelper(EEToProfInterfaceImpl *profInterface, EventPipeProvider *provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread, ULONG numStackFrames, UINT_PTR stackFrames[]) { return profInterface->EventPipeEventDelivered(provider, eventId, eventVersion, cbMetadataBlob, metadataBlob, cbEventData, eventData, pActivityId, pRelatedActivityId, pEventThread, numStackFrames, stackFrames); } inline void ProfControlBlock::EventPipeEventDelivered(EventPipeProvider *provider, DWORD eventId, DWORD eventVersion, ULONG cbMetadataBlob, LPCBYTE metadataBlob, ULONG cbEventData, LPCBYTE eventData, LPCGUID pActivityId, LPCGUID pRelatedActivityId, Thread *pEventThread, ULONG numStackFrames, UINT_PTR stackFrames[]) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerMonitoringEventPipe, &EventPipeEventDeliveredHelper, provider, eventId, eventVersion, cbMetadataBlob, metadataBlob, cbEventData, eventData, pActivityId, pRelatedActivityId, pEventThread, numStackFrames, stackFrames); } inline HRESULT EventPipeProviderCreatedHelper(EEToProfInterfaceImpl *profInterface, EventPipeProvider *provider) { return profInterface->EventPipeProviderCreated(provider); } inline void ProfControlBlock::EventPipeProviderCreated(EventPipeProvider *provider) { LIMITED_METHOD_CONTRACT; DoProfilerCallback(ProfilerCallbackType::Active, IsProfilerMonitoringEventPipe, &EventPipeProviderCreatedHelper, provider); } //--------------------------------------------------------------------------------------- // Inlined helpers used throughout the runtime to check for the profiler's load status // and what features it enabled callbacks for. //--------------------------------------------------------------------------------------- FORCEINLINE BOOL CORProfilerPresent() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->mainProfilerInfo.pProfInterface.Load() != NULL || (&g_profControlBlock)->notificationProfilerCount.Load() > 0; } FORCEINLINE BOOL CORMainProfilerPresent() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->mainProfilerInfo.curProfStatus.Get() >= kProfStatusActive; } // These return whether a CLR Profiler is actively loaded AND has requested the // specified callback or functionality FORCEINLINE BOOL CORProfilerFunctionIDMapperEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (CORMainProfilerPresent() && ( ((&g_profControlBlock)->mainProfilerInfo.pProfInterface->GetFunctionIDMapper() != NULL) || ((&g_profControlBlock)->mainProfilerInfo.pProfInterface->GetFunctionIDMapper2() != NULL) )); } FORCEINLINE BOOL CORProfilerTrackJITInfo() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_JIT_COMPILATION); } FORCEINLINE BOOL CORProfilerTrackCacheSearches() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CACHE_SEARCHES); } FORCEINLINE BOOL CORProfilerTrackModuleLoads() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_MODULE_LOADS); } FORCEINLINE BOOL CORProfilerTrackAssemblyLoads() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ASSEMBLY_LOADS); } FORCEINLINE BOOL CORProfilerTrackAppDomainLoads() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_APPDOMAIN_LOADS); } FORCEINLINE BOOL CORProfilerTrackThreads() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_THREADS); } FORCEINLINE BOOL CORProfilerTrackClasses() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CLASS_LOADS); } FORCEINLINE BOOL CORProfilerTrackGC() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_GC); } FORCEINLINE BOOL CORProfilerTrackAllocationsEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return ( #ifdef PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED (&g_profControlBlock)->fTestOnlyForceObjectAllocated || #endif (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_OBJECT_ALLOCATED) ); } FORCEINLINE BOOL CORProfilerTrackAllocations() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_OBJECT_ALLOCATED); } FORCEINLINE BOOL CORProfilerTrackLargeAllocations() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED); } FORCEINLINE BOOL CORProfilerTrackPinnedAllocations() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_PINNEDOBJECT_ALLOCATED); } FORCEINLINE BOOL CORProfilerEnableRejit() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_REJIT); } FORCEINLINE BOOL CORProfilerTrackExceptions() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_EXCEPTIONS); } FORCEINLINE BOOL CORProfilerTrackTransitions() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CODE_TRANSITIONS); } FORCEINLINE BOOL CORProfilerTrackEnterLeave() { STATIC_CONTRACT_LIMITED_METHOD; #ifdef PROF_TEST_ONLY_FORCE_ELT if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) return TRUE; #endif // PROF_TEST_ONLY_FORCE_ELT return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_ENTERLEAVE); } FORCEINLINE BOOL CORProfilerTrackCCW() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_CCW); } FORCEINLINE BOOL CORProfilerTrackSuspends() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_MONITOR_SUSPENDS); } FORCEINLINE BOOL CORProfilerDisableInlining() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_INLINING); } FORCEINLINE BOOL CORProfilerDisableOptimizations() { CONTRACTL { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACTL_END; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_OPTIMIZATIONS); } FORCEINLINE BOOL CORProfilerUseProfileImages() { STATIC_CONTRACT_LIMITED_METHOD; #ifdef PROF_TEST_ONLY_FORCE_ELT if ((&g_profControlBlock)->fTestOnlyForceEnterLeave) return TRUE; #endif // PROF_TEST_ONLY_FORCE_ELT return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_REQUIRE_PROFILE_IMAGE); } FORCEINLINE BOOL CORProfilerDisableAllNGenImages() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_DISABLE_ALL_NGEN_IMAGES); } FORCEINLINE BOOL CORProfilerTrackConditionalWeakTableElements() { STATIC_CONTRACT_LIMITED_METHOD; return CORProfilerTrackGC() && (&g_profControlBlock)->IsCallback5Supported(); } // These return whether a CLR Profiler has requested the specified functionality. // // Note that, unlike the above functions, a profiler that's not done loading (and is // still somewhere in the initialization phase) still counts. This is only safe because // these functions are not used to determine whether to issue a callback. These functions // are used primarily during the initialization path to choose between slow / fast-path // ELT hooks (and later on as part of asserts). FORCEINLINE BOOL CORProfilerELT3SlowPathEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)); } FORCEINLINE BOOL CORProfilerELT3SlowPathEnterEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO)); } FORCEINLINE BOOL CORProfilerELT3SlowPathLeaveEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO)); } FORCEINLINE BOOL CORProfilerELT3SlowPathTailcallEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_FRAME_INFO)); } FORCEINLINE BOOL CORProfilerELT2FastPathEnterEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_ARGS | COR_PRF_ENABLE_FRAME_INFO))); } FORCEINLINE BOOL CORProfilerELT2FastPathLeaveEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FUNCTION_RETVAL | COR_PRF_ENABLE_FRAME_INFO))); } FORCEINLINE BOOL CORProfilerELT2FastPathTailcallEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return !((&g_profControlBlock)->globalEventMask.IsEventMaskSet((COR_PRF_ENABLE_STACK_SNAPSHOT | COR_PRF_ENABLE_FRAME_INFO))); } FORCEINLINE BOOL CORProfilerFunctionArgsEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_ARGS); } FORCEINLINE BOOL CORProfilerFunctionReturnValueEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FUNCTION_RETVAL); } FORCEINLINE BOOL CORProfilerFrameInfoEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_FRAME_INFO); } FORCEINLINE BOOL CORProfilerStackSnapshotEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskSet(COR_PRF_ENABLE_STACK_SNAPSHOT); } FORCEINLINE BOOL CORProfilerInMemorySymbolsUpdatesEnabled() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED); } FORCEINLINE BOOL CORProfilerTrackDynamicFunctionUnloads() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS); } FORCEINLINE BOOL CORProfilerDisableTieredCompilation() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_DISABLE_TIERED_COMPILATION); } FORCEINLINE BOOL CORProfilerTrackBasicGC() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_BASIC_GC); } FORCEINLINE BOOL CORProfilerTrackGCMovedObjects() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS); } FORCEINLINE BOOL CORProfilerTrackEventPipe() { STATIC_CONTRACT_LIMITED_METHOD; return (&g_profControlBlock)->globalEventMask.IsEventMaskHighSet(COR_PRF_HIGH_MONITOR_EVENT_PIPE); } #if defined(PROFILING_SUPPORTED) //--------------------------------------------------------------------------------------- // These macros must be placed around any callbacks to g_profControlBlock by // the EE. Example: // { // BEGIN_PROFILER_CALLBACK(CORProfilerTrackAppDomainLoads; // g_profControlBlock.AppDomainCreationStarted(MyAppDomainID); // END_PROFILER_CALLBACK(); // } // The parameter to the BEGIN_PROFILER_CALLBACK is the condition you want to check for, to // determine whether the profiler is loaded and requesting the callback you're about to // issue. Typically, this will be a call to one of the inline functions in // profilepriv.inl. If the condition is true, the macro will increment an evacuation // counter that effectively pins the profiler, recheck the condition, and (if still // true), execute whatever code you place inside the BEGIN/END_PROFILER_CALLBACK block. If // your condition is more complex than a simple profiler status check, then place the // profiler status check as parameter to the macro, and add a separate if inside the // block. Example: // // { // BEGIN_PROFILER_CALLBACK(CorProfilerTrackTransitions); // if (!pNSL->pMD->IsQCall()) // { // g_profControlBlock. // ManagedToUnmanagedTransition((FunctionID) pNSL->pMD, // COR_PRF_TRANSITION_CALL); // } // END_PROFILER_CALLBACK(); // } // // This ensures that the extra condition check (in this case "if // (!pNSL->pMD->IsQCall())") is only evaluated if the profiler is loaded. That way, we're // not executing extra, unnecessary instructions when no profiler is present. // // See code:ProfilingAPIUtility::InitializeProfiling#LoadUnloadCallbackSynchronization // for more details about how the synchronization works. #define BEGIN_PROFILER_CALLBACK(condition) \ /* Do a cheap check of the condition (dirty-read) */ \ if (condition) \ { \ #define END_PROFILER_CALLBACK() } #else // PROFILING_SUPPORTED // Profiling feature not supported #define BEGIN_PROFILER_CALLBACK(condition) if (false) { #define END_PROFILER_CALLBACK() } #endif // PROFILING_SUPPORTED #endif // _ProfilePriv_inl_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/random.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // random.h // // // Defines a random number generator, initially from the System.Random code in the BCL. // // Main advantages over rand() are: // // 1) It generates better random numbers // 2) It can have multiple instantiations with different seeds // 3) It behaves the same regardless of whether we build with VC++ or GCC // // If you are working in the VM, we have a convenience method: code:GetRandomInt. This usess a thread-local // Random instance if a Thread object is available, and otherwise falls back to a global instance // with a spin-lock. // #ifndef _CLRRANDOM_H_ #define _CLRRANDOM_H_ #include // // Forbid the use of srand()/rand(), as these are globally shared facilities and our use of them would // interfere with native user code in the same process. This override is not compatible with stl headers. // #if !defined(DO_NOT_DISABLE_RAND) && !defined(USE_STL) #ifdef srand #undef srand #endif #define srand Do_not_use_srand #ifdef rand #undef rand #endif #define rand Do_not_use_rand #endif //!DO_NOT_DISABLE_RAND && !USE_STL class CLRRandom { private: // // Private Constants // static const int MBIG = INT_MAX; static const int MSEED = 161803398; static const int MZ = 0; // // Member Variables // int inext; int inextp; int SeedArray[56]; bool initialized; public: // // Constructors // CLRRandom() { LIMITED_METHOD_CONTRACT; initialized = false; } void Init() { LIMITED_METHOD_CONTRACT; LARGE_INTEGER time; if (!QueryPerformanceCounter(&time)) time.QuadPart = GetTickCount(); Init((int)time.u.LowPart ^ GetCurrentThreadId() ^ GetCurrentProcessId()); } void Init(int Seed) { LIMITED_METHOD_CONTRACT; int ii; int mj, mk; //Initialize our Seed array. mj = MSEED - abs(Seed); SeedArray[55]=mj; mk=1; for (int i=1; i<55; i++) { //Apparently the range [1..55] is special (Knuth) and so we're wasting the 0'th position. ii = (21*i)%55; SeedArray[ii]=mk; mk = mj - mk; if (mk<0) mk+=MBIG; mj=SeedArray[ii]; } for (int k=1; k<5; k++) { for (int i=1; i<56; i++) { SeedArray[i] -= SeedArray[1+(i+30)%55]; if (SeedArray[i]<0) SeedArray[i]+=MBIG; } } inext=0; inextp = 21; Seed = 1; initialized = true; } bool IsInitialized() { LIMITED_METHOD_CONTRACT; return initialized; } private: // // Package Private Methods // /*====================================Sample==================================== **Action: Return a new random number [0..1) and reSeed the Seed array. **Returns: A double [0..1) **Arguments: None **Exceptions: None ==============================================================================*/ double Sample() { LIMITED_METHOD_CONTRACT; //Including this division at the end gives us significantly improved //random number distribution. return (InternalSample()*(1.0/MBIG)); } int InternalSample() { LIMITED_METHOD_CONTRACT; int retVal; int locINext = inext; int locINextp = inextp; if (++locINext >=56) locINext=1; if (++locINextp>= 56) locINextp = 1; retVal = SeedArray[locINext]-SeedArray[locINextp]; if (retVal == MBIG) retVal--; if (retVal<0) retVal+=MBIG; SeedArray[locINext]=retVal; inext = locINext; inextp = locINextp; return retVal; } double GetSampleForLargeRange() { LIMITED_METHOD_CONTRACT; // The distribution of double value returned by Sample // is not distributed well enough for a large range. // If we use Sample for a range [Int32.MinValue..Int32.MaxValue) // We will end up getting even numbers only. int result = InternalSample(); // Note we can't use addition here. The distribution will be bad if we do that. bool negative = (InternalSample()%2 == 0) ? true : false; // decide the sign based on second sample if( negative) { result = -result; } double d = result; d += (INT_MAX - 1); // get a number in range [0 .. 2 * Int32MaxValue - 1) d /= 2*(unsigned int)INT_MAX - 1 ; return d; } public: // // Public Instance Methods // /*=====================================Next===================================== **Returns: An int [0..Int32.MaxValue) **Arguments: None **Exceptions: None. ==============================================================================*/ int Next() { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); return InternalSample(); } /*=====================================Next===================================== **Returns: An int [minvalue..maxvalue) **Arguments: minValue -- the least legal value for the Random number. ** maxValue -- One greater than the greatest legal return value. **Exceptions: None. ==============================================================================*/ int Next(int minValue, int maxValue) { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); _ASSERTE(minValue < maxValue); LONGLONG range = (LONGLONG)maxValue-minValue; double result; if( range <= (LONGLONG)INT_MAX) result = (Sample() * range) + minValue; else result = (GetSampleForLargeRange() * range) + minValue; _ASSERTE(result >= minValue && result < maxValue); return (int)result; } /*=====================================Next===================================== **Returns: An int [0..maxValue) **Arguments: maxValue -- One more than the greatest legal return value. **Exceptions: None. ==============================================================================*/ int Next(int maxValue) { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); double result = Sample()*maxValue; _ASSERTE(result >= 0 && result < maxValue); return (int)result; } /*=====================================Next===================================== **Returns: A double [0..1) **Arguments: None **Exceptions: None ==============================================================================*/ double NextDouble() { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); double result = Sample(); _ASSERTE(result >= 0 && result < 1); return result; } /*==================================NextBytes=================================== **Action: Fills the byte array with random bytes [0..0x7f]. The entire array is filled. **Returns:Void **Arguments: buffer -- the array to be filled. **Exceptions: None ==============================================================================*/ void NextBytes(_Out_writes_(length) BYTE buffer[], int length) { LIMITED_METHOD_CONTRACT; _ASSERTE(initialized); for (int i=0; iControlPC); } inline TADDR GetRegdisplaySP(REGDISPLAY_BASE *pRD) { LIMITED_METHOD_DAC_CONTRACT; return pRD->SP; } inline void SetRegdisplaySP(REGDISPLAY_BASE *pRD, LPVOID sp) { LIMITED_METHOD_DAC_CONTRACT; pRD->SP = (TADDR)sp; } #if defined(TARGET_X86) struct REGDISPLAY : public REGDISPLAY_BASE { #ifndef FEATURE_EH_FUNCLETS // TODO: Unify with pCurrentContext / pCallerContext used on 64-bit PCONTEXT pContextForUnwind; // scratch context for unwinding // used to preserve context saved in the frame that // could be otherwise wiped by the unwinding DWORD * pEdi; DWORD * pEsi; DWORD * pEbx; DWORD * pEdx; DWORD * pEcx; DWORD * pEax; DWORD * pEbp; #endif // !FEATURE_EH_FUNCLETS #ifndef FEATURE_EH_FUNCLETS #define REG_METHODS(reg) \ inline PDWORD Get##reg##Location(void) { return p##reg; } \ inline void Set##reg##Location(PDWORD p##reg) { this->p##reg = p##reg; } #else // !FEATURE_EH_FUNCLETS #define REG_METHODS(reg) \ inline PDWORD Get##reg##Location(void) { return pCurrentContextPointers->reg; } \ inline void Set##reg##Location(PDWORD p##reg) \ { \ pCurrentContextPointers->reg = p##reg; \ pCurrentContext->reg = *p##reg; \ } #endif // FEATURE_EH_FUNCLETS REG_METHODS(Eax) REG_METHODS(Ecx) REG_METHODS(Edx) REG_METHODS(Ebx) REG_METHODS(Esi) REG_METHODS(Edi) REG_METHODS(Ebp) #undef REG_METHODS TADDR PCTAddr; }; inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_DAC_CONTRACT; #ifdef FEATURE_EH_FUNCLETS return (TADDR)display->pCurrentContext->Ebp; #else return (TADDR)*display->GetEbpLocation(); #endif } inline LPVOID GetRegdisplayFPAddress(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; return (LPVOID)display->GetEbpLocation(); } // This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { LIMITED_METHOD_CONTRACT; #ifdef FEATURE_EH_FUNCLETS return stackPointer < ((LPVOID)(display->SP)); #else return (TADDR)stackPointer < display->PCTAddr; #endif } inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { LIMITED_METHOD_DAC_CONTRACT; #ifdef FEATURE_EH_FUNCLETS _ASSERTE(GetRegdisplaySP(display) == GetSP(display->pCurrentContext)); return GetRegdisplaySP(display); #else return display->PCTAddr; #endif } #elif defined(TARGET_64BIT) #if defined(TARGET_ARM64) typedef struct _Arm64VolatileContextPointer { union { struct { PDWORD64 X0; PDWORD64 X1; PDWORD64 X2; PDWORD64 X3; PDWORD64 X4; PDWORD64 X5; PDWORD64 X6; PDWORD64 X7; PDWORD64 X8; PDWORD64 X9; PDWORD64 X10; PDWORD64 X11; PDWORD64 X12; PDWORD64 X13; PDWORD64 X14; PDWORD64 X15; PDWORD64 X16; PDWORD64 X17; //X18 is reserved by OS, in userspace it represents TEB }; PDWORD64 X[18]; }; } Arm64VolatileContextPointer; #endif //TARGET_ARM64 #if defined(TARGET_LOONGARCH64) typedef struct _Loongarch64VolatileContextPointer { PDWORD64 R0; PDWORD64 A0; PDWORD64 A1; PDWORD64 A2; PDWORD64 A3; PDWORD64 A4; PDWORD64 A5; PDWORD64 A6; PDWORD64 A7; PDWORD64 T0; PDWORD64 T1; PDWORD64 T2; PDWORD64 T3; PDWORD64 T4; PDWORD64 T5; PDWORD64 T6; PDWORD64 T7; PDWORD64 T8; PDWORD64 X0; } Loongarch64VolatileContextPointer; #endif struct REGDISPLAY : public REGDISPLAY_BASE { #ifdef TARGET_ARM64 Arm64VolatileContextPointer volatileCurrContextPointers; #endif #ifdef TARGET_LOONGARCH64 Loongarch64VolatileContextPointer volatileCurrContextPointers; #endif REGDISPLAY() { // Initialize memset(this, 0, sizeof(REGDISPLAY)); } }; inline TADDR GetRegdisplayFP(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; return NULL; } inline TADDR GetRegdisplayFPAddress(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; return NULL; } // This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { LIMITED_METHOD_CONTRACT; return stackPointer < ((LPVOID)(display->SP)); } inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { #if defined(TARGET_AMD64) // On AMD64, the MemoryStackFp value is the current sp (i.e. the sp value when calling another method). _ASSERTE(GetRegdisplaySP(display) == GetSP(display->pCurrentContext)); return GetRegdisplaySP(display); #elif defined(TARGET_ARM64) _ASSERTE(display->IsCallerContextValid); return GetSP(display->pCallerContext); #else // TARGET_AMD64 PORTABILITY_ASSERT("GetRegdisplayStackMark NYI for this platform (Regdisp.h)"); return NULL; #endif // TARGET_AMD64 } #elif defined(TARGET_ARM) // ResumableFrame is pushed on the stack before // starting the GC. registers r0-r3 in ResumableFrame can // contain roots which might need to be updated if they are // relocated. On Stack walking the addresses of the registers in the // resumable Frame are passed to GC using pCurrentContextPointers // member in _REGDISPLAY. However On ARM KNONVOLATILE_CONTEXT_POINTERS // does not contain pointers for volatile registers. Therefore creating // this structure to store pointers to volatile registers and adding an object // as member in _REGDISPLAY typedef struct _ArmVolatileContextPointer { PDWORD R0; PDWORD R1; PDWORD R2; PDWORD R3; PDWORD R12; } ArmVolatileContextPointer; struct REGDISPLAY : public REGDISPLAY_BASE { ArmVolatileContextPointer volatileCurrContextPointers; DWORD * pPC; // processor neutral name REGDISPLAY() { // Initialize regdisplay memset(this, 0, sizeof(REGDISPLAY)); // Setup the pointer to ControlPC field pPC = &ControlPC; } }; // This function tells us if the given stack pointer is in one of the frames of the functions called by the given frame inline BOOL IsInCalleesFrames(REGDISPLAY *display, LPVOID stackPointer) { LIMITED_METHOD_CONTRACT; return stackPointer < ((LPVOID)(TADDR)(display->SP)); } inline TADDR GetRegdisplayStackMark(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; // ARM uses the establisher frame as the marker _ASSERTE(display->IsCallerContextValid); return GetSP(display->pCallerContext); } #else // none of the above processors #error "RegDisplay functions are not implemented on this platform." #endif #if defined(TARGET_64BIT) || defined(TARGET_ARM) || (defined(TARGET_X86) && defined(FEATURE_EH_FUNCLETS)) // This needs to be implemented for platforms that have funclets. inline LPVOID GetRegdisplayReturnValue(REGDISPLAY *display) { LIMITED_METHOD_CONTRACT; #if defined(TARGET_AMD64) return (LPVOID)display->pCurrentContext->Rax; #elif defined(TARGET_ARM64) return (LPVOID)display->pCurrentContext->X0; #elif defined(TARGET_ARM) return (LPVOID)((TADDR)display->pCurrentContext->R0); #elif defined(TARGET_X86) return (LPVOID)display->pCurrentContext->Eax; #elif defined(TARGET_LOONGARCH64) return (LPVOID)display->pCurrentContext->A0; #else PORTABILITY_ASSERT("GetRegdisplayReturnValue NYI for this platform (Regdisp.h)"); return NULL; #endif } inline void SyncRegDisplayToCurrentContext(REGDISPLAY* pRD) { LIMITED_METHOD_CONTRACT; #if defined(TARGET_64BIT) pRD->SP = (INT_PTR)GetSP(pRD->pCurrentContext); pRD->ControlPC = INT_PTR(GetIP(pRD->pCurrentContext)); #elif defined(TARGET_ARM) pRD->SP = (DWORD)GetSP(pRD->pCurrentContext); pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext); #elif defined(TARGET_X86) pRD->SP = (DWORD)GetSP(pRD->pCurrentContext); pRD->ControlPC = (DWORD)GetIP(pRD->pCurrentContext); #else // TARGET_X86 PORTABILITY_ASSERT("SyncRegDisplayToCurrentContext"); #endif #ifdef DEBUG_REGDISPLAY CheckRegDisplaySP(pRD); #endif // DEBUG_REGDISPLAY } #endif // TARGET_64BIT || TARGET_ARM || (TARGET_X86 && FEATURE_EH_FUNCLETS) typedef REGDISPLAY *PREGDISPLAY; #ifdef FEATURE_EH_FUNCLETS inline void FillContextPointers(PT_KNONVOLATILE_CONTEXT_POINTERS pCtxPtrs, PT_CONTEXT pCtx) { #ifdef TARGET_AMD64 for (int i = 0; i < 16; i++) { *(&pCtxPtrs->Rax + i) = (&pCtx->Rax + i); } #elif defined(TARGET_ARM64) // TARGET_AMD64 for (int i = 0; i < 12; i++) { *(&pCtxPtrs->X19 + i) = (&pCtx->X19 + i); } #elif defined(TARGET_LOONGARCH64) // TARGET_ARM64 *(&pCtxPtrs->S0) = &pCtx->S0; *(&pCtxPtrs->S1) = &pCtx->S1; *(&pCtxPtrs->S2) = &pCtx->S2; *(&pCtxPtrs->S3) = &pCtx->S3; *(&pCtxPtrs->S4) = &pCtx->S4; *(&pCtxPtrs->S5) = &pCtx->S5; *(&pCtxPtrs->S6) = &pCtx->S6; *(&pCtxPtrs->S7) = &pCtx->S7; *(&pCtxPtrs->S8) = &pCtx->S8; *(&pCtxPtrs->Tp) = &pCtx->Tp; *(&pCtxPtrs->Fp) = &pCtx->Fp; *(&pCtxPtrs->Ra) = &pCtx->Ra; #elif defined(TARGET_ARM) // TARGET_LOONGARCH64 // Copy over the nonvolatile integer registers (R4-R11) for (int i = 0; i < 8; i++) { *(&pCtxPtrs->R4 + i) = (&pCtx->R4 + i); } #elif defined(TARGET_X86) // TARGET_ARM for (int i = 0; i < 7; i++) { *(&pCtxPtrs->Edi + i) = (&pCtx->Edi + i); } #else // TARGET_X86 PORTABILITY_ASSERT("FillContextPointers"); #endif // _TARGET_???_ (ELSE) } #endif // FEATURE_EH_FUNCLETS inline void FillRegDisplay(const PREGDISPLAY pRD, PT_CONTEXT pctx, PT_CONTEXT pCallerCtx = NULL) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; #ifndef FEATURE_EH_FUNCLETS #ifdef TARGET_X86 pRD->pContext = pctx; pRD->pContextForUnwind = NULL; pRD->pEdi = &(pctx->Edi); pRD->pEsi = &(pctx->Esi); pRD->pEbx = &(pctx->Ebx); pRD->pEbp = &(pctx->Ebp); pRD->pEax = &(pctx->Eax); pRD->pEcx = &(pctx->Ecx); pRD->pEdx = &(pctx->Edx); pRD->SP = pctx->Esp; pRD->ControlPC = (PCODE)(pctx->Eip); pRD->PCTAddr = (UINT_PTR)&(pctx->Eip); #else // TARGET_X86 PORTABILITY_ASSERT("FillRegDisplay"); #endif // _TARGET_???_ (ELSE) #else // !FEATURE_EH_FUNCLETS pRD->pContext = pctx; // Setup the references pRD->pCurrentContextPointers = &pRD->ctxPtrsOne; pRD->pCallerContextPointers = &pRD->ctxPtrsTwo; pRD->pCurrentContext = &(pRD->ctxOne); pRD->pCallerContext = &(pRD->ctxTwo); // copy the active context to initialize our stackwalk *(pRD->pCurrentContext) = *(pctx); // copy the caller context as well if it's specified if (pCallerCtx == NULL) { pRD->IsCallerContextValid = FALSE; pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. } else { *(pRD->pCallerContext) = *(pCallerCtx); pRD->IsCallerContextValid = TRUE; pRD->IsCallerSPValid = TRUE; // Don't add usage of this field. This is only temporary. } FillContextPointers(&pRD->ctxPtrsOne, pctx); #if defined(TARGET_ARM) // Fill volatile context pointers. They can be used by GC in the case of the leaf frame pRD->volatileCurrContextPointers.R0 = &pctx->R0; pRD->volatileCurrContextPointers.R1 = &pctx->R1; pRD->volatileCurrContextPointers.R2 = &pctx->R2; pRD->volatileCurrContextPointers.R3 = &pctx->R3; pRD->volatileCurrContextPointers.R12 = &pctx->R12; pRD->ctxPtrsOne.Lr = &pctx->Lr; pRD->pPC = &pRD->pCurrentContext->Pc; #elif defined(TARGET_ARM64) // TARGET_ARM // Fill volatile context pointers. They can be used by GC in the case of the leaf frame for (int i=0; i < 18; i++) pRD->volatileCurrContextPointers.X[i] = &pctx->X[i]; #elif defined(TARGET_LOONGARCH64) // TARGET_ARM64 pRD->volatileCurrContextPointers.A0 = &pctx->A0; pRD->volatileCurrContextPointers.A1 = &pctx->A1; pRD->volatileCurrContextPointers.A2 = &pctx->A2; pRD->volatileCurrContextPointers.A3 = &pctx->A3; pRD->volatileCurrContextPointers.A4 = &pctx->A4; pRD->volatileCurrContextPointers.A5 = &pctx->A5; pRD->volatileCurrContextPointers.A6 = &pctx->A6; pRD->volatileCurrContextPointers.A7 = &pctx->A7; pRD->volatileCurrContextPointers.T0 = &pctx->T0; pRD->volatileCurrContextPointers.T1 = &pctx->T1; pRD->volatileCurrContextPointers.T2 = &pctx->T2; pRD->volatileCurrContextPointers.T3 = &pctx->T3; pRD->volatileCurrContextPointers.T4 = &pctx->T4; pRD->volatileCurrContextPointers.T5 = &pctx->T5; pRD->volatileCurrContextPointers.T6 = &pctx->T6; pRD->volatileCurrContextPointers.T7 = &pctx->T7; pRD->volatileCurrContextPointers.T8 = &pctx->T8; pRD->volatileCurrContextPointers.X0 = &pctx->X0; #endif // TARGET_LOONGARCH64 #ifdef DEBUG_REGDISPLAY pRD->_pThread = NULL; #endif // DEBUG_REGDISPLAY // This will setup the PC and SP SyncRegDisplayToCurrentContext(pRD); #endif // !FEATURE_EH_FUNCLETS } // Initialize a new REGDISPLAY/CONTEXT pair from an existing valid REGDISPLAY. inline void CopyRegDisplay(const PREGDISPLAY pInRD, PREGDISPLAY pOutRD, T_CONTEXT *pOutCtx) { WRAPPER_NO_CONTRACT; // The general strategy is to extract the register state from the input REGDISPLAY // into the new CONTEXT then simply call FillRegDisplay. T_CONTEXT* pOutCallerCtx = NULL; #ifndef FEATURE_EH_FUNCLETS #if defined(TARGET_X86) if (pInRD->pEdi != NULL) {pOutCtx->Edi = *pInRD->pEdi;} else {pInRD->pEdi = NULL;} if (pInRD->pEsi != NULL) {pOutCtx->Esi = *pInRD->pEsi;} else {pInRD->pEsi = NULL;} if (pInRD->pEbx != NULL) {pOutCtx->Ebx = *pInRD->pEbx;} else {pInRD->pEbx = NULL;} if (pInRD->pEbp != NULL) {pOutCtx->Ebp = *pInRD->pEbp;} else {pInRD->pEbp = NULL;} if (pInRD->pEax != NULL) {pOutCtx->Eax = *pInRD->pEax;} else {pInRD->pEax = NULL;} if (pInRD->pEcx != NULL) {pOutCtx->Ecx = *pInRD->pEcx;} else {pInRD->pEcx = NULL;} if (pInRD->pEdx != NULL) {pOutCtx->Edx = *pInRD->pEdx;} else {pInRD->pEdx = NULL;} pOutCtx->Esp = pInRD->SP; pOutCtx->Eip = pInRD->ControlPC; #else // TARGET_X86 PORTABILITY_ASSERT("CopyRegDisplay"); #endif // _TARGET_???_ #else // FEATURE_EH_FUNCLETS *pOutCtx = *(pInRD->pCurrentContext); if (pInRD->IsCallerContextValid) { pOutCallerCtx = pInRD->pCallerContext; } #endif // FEATURE_EH_FUNCLETS if (pOutRD) FillRegDisplay(pOutRD, pOutCtx, pOutCallerCtx); } // Get address of a register in a CONTEXT given the reg number. For X86, // the reg number is the R/M number from ModR/M byte or base in SIB byte inline size_t * getRegAddr (unsigned regNum, PTR_CONTEXT regs) { #ifdef TARGET_X86 _ASSERTE(regNum < 8); static const SIZE_T OFFSET_OF_REGISTERS[] = { offsetof(CONTEXT, Eax), offsetof(CONTEXT, Ecx), offsetof(CONTEXT, Edx), offsetof(CONTEXT, Ebx), offsetof(CONTEXT, Esp), offsetof(CONTEXT, Ebp), offsetof(CONTEXT, Esi), offsetof(CONTEXT, Edi), }; return (PTR_size_t)(PTR_BYTE(regs) + OFFSET_OF_REGISTERS[regNum]); #elif defined(TARGET_AMD64) _ASSERTE(regNum < 16); return (size_t *)®s->Rax + regNum; #elif defined(TARGET_ARM) _ASSERTE(regNum < 16); return (size_t *)®s->R0 + regNum; #elif defined(TARGET_ARM64) _ASSERTE(regNum < 31); return (size_t *)®s->X0 + regNum; #elif defined(TARGET_LOONGARCH64) _ASSERTE(regNum < 32); return (size_t *)®s->R0 + regNum; #else _ASSERTE(!"@TODO Port - getRegAddr (Regdisp.h)"); #endif return(0); } //--------------------------------------------------------------------------------------- // // This is just a simpler helper function to convert a REGDISPLAY to a CONTEXT. // // Arguments: // pRegDisp - the REGDISPLAY to be converted // pContext - the buffer for storing the converted CONTEXT // inline void UpdateContextFromRegDisp(PREGDISPLAY pRegDisp, PT_CONTEXT pContext) { _ASSERTE((pRegDisp != NULL) && (pContext != NULL)); #ifndef FEATURE_EH_FUNCLETS #if defined(TARGET_X86) pContext->ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL); pContext->Edi = *pRegDisp->pEdi; pContext->Esi = *pRegDisp->pEsi; pContext->Ebx = *pRegDisp->pEbx; pContext->Ebp = *pRegDisp->pEbp; pContext->Eax = *pRegDisp->pEax; pContext->Ecx = *pRegDisp->pEcx; pContext->Edx = *pRegDisp->pEdx; pContext->Esp = pRegDisp->SP; pContext->Eip = pRegDisp->ControlPC; #else // TARGET_X86 PORTABILITY_ASSERT("UpdateContextFromRegDisp"); #endif // _TARGET_???_ #else // FEATURE_EH_FUNCLETS *pContext = *pRegDisp->pCurrentContext; #endif // FEATURE_EH_FUNCLETS } #endif // __REGDISP_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/releaseholder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // This class acts a smart pointer which calls the Release method on any object // you place in it when the ReleaseHolder class falls out of scope. You may use it // just like you would a standard pointer to a COM object (including if (foo), // if (!foo), if (foo == 0), etc) except for two caveats: // 1. This class never calls AddRef and it always calls Release when it // goes out of scope. // 2. You should never use & to try to get a pointer to a pointer unless // you call Release first, or you will leak whatever this object contains // prior to updating its internal pointer. template class ReleaseHolder { public: ReleaseHolder() : m_ptr(NULL) {} ReleaseHolder(T* ptr) : m_ptr(ptr) {} ~ReleaseHolder() { Release(); } void operator=(T *ptr) { Release(); m_ptr = ptr; } T* operator->() { return m_ptr; } operator T*() { return m_ptr; } T** operator&() { return &m_ptr; } T* GetPtr() const { return m_ptr; } T* Detach() { T* pT = m_ptr; m_ptr = NULL; return pT; } void Release() { if (m_ptr != NULL) { m_ptr->Release(); m_ptr = NULL; } } private: T* m_ptr; }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/safemath.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // safemath.h // // overflow checking infrastructure // --------------------------------------------------------------------------- #ifndef SAFEMATH_H_ #define SAFEMATH_H_ // This file is included from several places outside the CLR, so we can't // pull in files like DebugMacros.h. However, we assume that the standard // clrtypes (UINT32 etc.) are defined. #include "debugmacrosext.h" #ifndef _ASSERTE_SAFEMATH #ifdef _ASSERTE // Use _ASSERTE if we have it (should always be the case in the CLR) #define _ASSERTE_SAFEMATH _ASSERTE #else // Otherwise (eg. we're being used from a tool like SOS) there isn't much // we can rely on that is available everywhere. In // several other tools we just take the recourse of disabling asserts, // we'll do the same here. // Ideally we'd have a collection of common utilities available everywhere. #define _ASSERTE_SAFEMATH(a) #endif #endif #include "static_assert.h" #ifdef PAL_STDCPP_COMPAT #include #else #include "clr_std/type_traits" #endif //================================================================== // Semantics: if val can be represented as the exact same value // when cast to Dst type, then FitsIn(val) will return true; // otherwise FitsIn returns false. // // Dst and Src must both be integral types. // // It's important to note that most of the conditionals in this // function are based on static type information and as such will // be optimized away. In particular, the case where the signs are // identical will result in no code branches. #ifdef _PREFAST_ #pragma warning(push) #pragma warning(disable:6326) // PREfast warning: Potential comparison of a constant with another constant #endif // _PREFAST_ template inline bool FitsIn(Src val) { #ifdef _MSC_VER static_assert_no_msg(!__is_class(Dst)); static_assert_no_msg(!__is_class(Src)); #endif if (std::is_signed::value == std::is_signed::value) { // Src and Dst are equally signed if (sizeof(Src) <= sizeof(Dst)) { // No truncation is possible return true; } else { // Truncation is possible, requiring runtime check return val == (Src)((Dst)val); } } else if (std::is_signed::value) { // Src is signed, Dst is unsigned #ifdef __GNUC__ // Workaround for GCC warning: "comparison is always // false due to limited range of data type." if (!(val == 0 || val > 0)) #else if (val < 0) #endif { // A negative number cannot be represented by an unsigned type return false; } else { if (sizeof(Src) <= sizeof(Dst)) { // No truncation is possible return true; } else { // Truncation is possible, requiring runtime check return val == (Src)((Dst)val); } } } else { // Src is unsigned, Dst is signed if (sizeof(Src) < sizeof(Dst)) { // No truncation is possible. Note that Src is strictly // smaller than Dst. return true; } else { // Truncation is possible, requiring runtime check #ifdef __GNUC__ // Workaround for GCC warning: "comparison is always // true due to limited range of data type." If in fact // Dst were unsigned we'd never execute this code // anyway. return ((Dst)val > 0 || (Dst)val == 0) && #else return ((Dst)val >= 0) && #endif (val == (Src)((Dst)val)); } } } // Requires that Dst is an integral type, and that DstMin and DstMax are the // minimum and maximum values of that type, respectively. Returns "true" iff // "val" can be represented in the range [DstMin..DstMax] (allowing loss of precision, but // not truncation). template inline bool FloatFitsInIntType(float val) { float DstMinF = static_cast(DstMin); float DstMaxF = static_cast(DstMax); return DstMinF <= val && val <= DstMaxF; } template inline bool DoubleFitsInIntType(double val) { double DstMinD = static_cast(DstMin); double DstMaxD = static_cast(DstMax); return DstMinD <= val && val <= DstMaxD; } #ifdef _PREFAST_ #pragma warning(pop) #endif //_PREFAST_ #define ovadd_lt(a, b, rhs) (((a) + (b) < (rhs) ) && ((a) + (b) >= (a))) #define ovadd_le(a, b, rhs) (((a) + (b) <= (rhs) ) && ((a) + (b) >= (a))) #define ovadd_gt(a, b, rhs) (((a) + (b) > (rhs) ) || ((a) + (b) < (a))) #define ovadd_ge(a, b, rhs) (((a) + (b) >= (rhs) ) || ((a) + (b) < (a))) #define ovadd3_gt(a, b, c, rhs) (((a) + (b) + (c) > (rhs)) || ((a) + (b) < (a)) || ((a) + (b) + (c) < (c))) //----------------------------------------------------------------------------- // // Liberally lifted from https://github.com/dcleblanc/SafeInt and modified. // // Modified to track an overflow bit instead of throwing exceptions. In most // cases the Visual C++ optimizer (Whidbey beta1 - v14.00.40607) is able to // optimize the bool away completely. // Note that using a sentinel value (IntMax for example) to represent overflow // actually results in poorer code-gen. // // This has also been simplified significantly to remove functionality we // don't currently want (division, implicit conversions, many additional operators etc.) // // Example: // unsafe: UINT32 bufSize = headerSize + elementCount * sizeof(void*); // becomes: // S_UINT32 bufSize = S_UINT32(headerSize) + S_UINT32(elementCount) * // S_UINT32( sizeof(void*) ); // if( bufSize.IsOverflow() ) { } // else { use bufSize.Value() } // or: // UINT32 tmp, bufSize; // if( !ClrSafeInt::multiply( elementCount, sizeof(void*), tmp ) || // !ClrSafeInt::addition( tmp, headerSize, bufSize ) ) // { } // else { use bufSize } // //----------------------------------------------------------------------------- // TODO: Any way to prevent unintended instantiations? This is only designed to // work with unsigned integral types (signed types will work but we probably // don't need signed support). template class ClrSafeInt { public: // Default constructor - 0 value by default ClrSafeInt() : m_value(0), m_overflow(false) COMMA_INDEBUG( m_checkedOverflow( false ) ) { } // Value constructor // This is explicit because otherwise it would be harder to // differentiate between checked and unchecked usage of an operator. // I.e. si + x + y vs. si + ( x + y ) // // Set the m_checkedOverflow bit to true since this is being initialized // with a constant value and we know that it is valid. A scenario in // which this is useful is when an overflow causes a fallback value to // be used: // if (val.IsOverflow()) // val = ClrSafeInt(some_value); explicit ClrSafeInt( T v ) : m_value(v), m_overflow(false) COMMA_INDEBUG( m_checkedOverflow( true ) ) { } template explicit ClrSafeInt(U u) : m_value(0), m_overflow(false) COMMA_INDEBUG( m_checkedOverflow( false ) ) { if (!FitsIn(u)) { m_overflow = true; } else { m_value = (T)u; } } template ClrSafeInt(ClrSafeInt u) : m_value(0), m_overflow(false) COMMA_INDEBUG( m_checkedOverflow( false ) ) { if (u.IsOverflow() || !FitsIn(u.Value())) { m_overflow = true; } else { m_value = (T)u.Value(); } } // Note: compiler-generated copy constructor and assignment operator // are correct for our purposes. // Note: The MS compiler will sometimes silently perform value-destroying // conversions when calling the operators below. // Eg. "ClrSafeInt s(0); s += int(-1);" will result in s // having the value 0xffffffff without generating a compile-time warning. // Narrowing conversions are generally level 4 warnings so may or may not // be visible. // // In the original SafeInt class, all operators have an // additional overload that takes an arbitrary type U and then safe // conversions are performed (resulting in overflow whenever the value // cannot be preserved). // We could do the same thing, but currently don't because: // - we don't believe there are common cases where this would result in a // security hole. // - the extra complexity isn't worth the benefits // - it would prevent compiler warnings in the cases we do get warnings for. // true if there has been an overflow leading up to the creation of this // value, false otherwise. // Note that in debug builds we track whether our client called this, // so we should not be calling this method ourselves from within this class. inline bool IsOverflow() const { INDEBUG( m_checkedOverflow = true; ) return m_overflow; } // Get the value of this integer. // Must only be called when IsOverflow()==false. If this is called // on overflow we'll assert in Debug and return 0 in release. inline T Value() const { _ASSERTE_SAFEMATH( m_checkedOverflow ); // Ensure our caller first checked the overflow bit _ASSERTE_SAFEMATH( !m_overflow ); return m_value; } // force the value into the overflow state. inline void SetOverflow() { INDEBUG( this->m_checkedOverflow = false; ) this->m_overflow = true; // incase someone manages to call Value in release mode - should be optimized out this->m_value = 0; } // // OPERATORS // // Addition and multiplication. Only permitted when both sides are explicitly // wrapped inside of a ClrSafeInt and when the types match exactly. // If we permitted a RHS of type 'T', then there would be differences // in correctness between mathematically equivalent expressions such as // "si + x + y" and "si + ( x + y )". Unfortunately, not permitting this // makes expressions involving constants tedius and ugly since the constants // must be wrapped in ClrSafeInt instances. If we become confident that // our tools (PreFast) will catch all integer overflows, then we can probably // safely add this. inline ClrSafeInt operator +(ClrSafeInt rhs) const { ClrSafeInt result; // value is initialized to 0 if( this->m_overflow || rhs.m_overflow || !addition( this->m_value, rhs.m_value, result.m_value ) ) { result.m_overflow = true; } return result; } inline ClrSafeInt operator -(ClrSafeInt rhs) const { ClrSafeInt result; // value is initialized to 0 if( this->m_overflow || rhs.m_overflow || !subtraction( this->m_value, rhs.m_value, result.m_value ) ) { result.m_overflow = true; } return result; } inline ClrSafeInt operator *(ClrSafeInt rhs) const { ClrSafeInt result; // value is initialized to 0 if( this->m_overflow || rhs.m_overflow || !multiply( this->m_value, rhs.m_value, result.m_value ) ) { result.m_overflow = true; } return result; } // Accumulation operators // Here it's ok to have versions that take a value of type 'T', however we still // don't allow any mixed-type operations. inline ClrSafeInt& operator +=(ClrSafeInt rhs) { INDEBUG( this->m_checkedOverflow = false; ) if( this->m_overflow || rhs.m_overflow || !ClrSafeInt::addition( this->m_value, rhs.m_value, this->m_value ) ) { this->SetOverflow(); } return *this; } inline ClrSafeInt& operator +=(T rhs) { INDEBUG( this->m_checkedOverflow = false; ) if( this->m_overflow || !ClrSafeInt::addition( this->m_value, rhs, this->m_value ) ) { this->SetOverflow(); } return *this; } inline ClrSafeInt& operator *=(ClrSafeInt rhs) { INDEBUG( this->m_checkedOverflow = false; ) if( this->m_overflow || rhs.m_overflow || !ClrSafeInt::multiply( this->m_value, rhs.m_value, this->m_value ) ) { this->SetOverflow(); } return *this; } inline ClrSafeInt& operator *=(T rhs) { INDEBUG( this->m_checkedOverflow = false; ) if( this->m_overflow || !ClrSafeInt::multiply( this->m_value, rhs, this->m_value ) ) { this->SetOverflow(); } return *this; } // // STATIC HELPER METHODS //these compile down to something as efficient as macros and allow run-time testing //of type by the developer // template static bool IsSigned(U) { return std::is_signed::value; } static bool IsSigned() { return std::is_signed::value; } static bool IsMixedSign(T lhs, T rhs) { return ((lhs ^ rhs) < 0); } static unsigned char BitCount(){return (sizeof(T)*8);} static bool Is64Bit(){return sizeof(T) == 8;} static bool Is32Bit(){return sizeof(T) == 4;} static bool Is16Bit(){return sizeof(T) == 2;} static bool Is8Bit(){return sizeof(T) == 1;} //both of the following should optimize away static T MaxInt() { if(IsSigned()) { return (T)~((T)1 << (BitCount()-1)); } //else return (T)(~(T)0); } static T MinInt() { if(IsSigned()) { return (T)((T)1 << (BitCount()-1)); } else { return ((T)0); } } // Align a value up to the nearest boundary, which must be a power of 2 inline void AlignUp( T alignment ) { _ASSERTE_SAFEMATH( IsPowerOf2( alignment ) ); *this += (alignment - 1); if( !this->m_overflow ) { m_value &= ~(alignment - 1); } } // // Arithmetic implementation functions // //note - this looks complex, but most of the conditionals //are constant and optimize away //for example, a signed 64-bit check collapses to: /* if(lhs == 0 || rhs == 0) return 0; if(MaxInt()/+lhs < +rhs) { //overflow throw SafeIntException(ERROR_ARITHMETIC_OVERFLOW); } //ok return lhs * rhs; Which ought to inline nicely */ // Returns true if safe, false for overflow. static bool multiply(T lhs, T rhs, T &result) { if(Is64Bit()) { //we're 64 bit - slow, but the only way to do it if(IsSigned()) { return ClrSafeInt::multiply((int64_t)lhs, (int64_t)rhs, (int64_t&)result); } else { return ClrSafeInt::multiply((uint64_t)lhs, (uint64_t)rhs, (uint64_t&)result); } } else if(Is32Bit()) { //we're 32-bit if(IsSigned()) { return ClrSafeInt::multiply((int32_t)lhs, (int32_t)rhs, (int32_t&)result); } else { return ClrSafeInt::multiply((uint32_t)lhs, (uint32_t)rhs, (uint32_t&)result); } } else if(Is16Bit()) { //16-bit if(IsSigned()) { return ClrSafeInt::multiply((int16_t)lhs, (int16_t)rhs, (int16_t&)result); } else { return ClrSafeInt::multiply((uint16_t)lhs, (uint16_t)rhs, (uint16_t&)result); } } else //8-bit { _ASSERTE_SAFEMATH(Is8Bit()); if(IsSigned()) { return ClrSafeInt::multiply((int8_t)lhs, (int8_t)rhs, (int8_t&)result); } else { return ClrSafeInt::multiply((uint8_t)lhs, (uint8_t)rhs, (uint8_t&)result); } } } // Returns true if safe, false on overflow static inline bool addition(T lhs, T rhs, T &result) { if(IsSigned()) { //test for +/- combo if(!IsMixedSign(lhs, rhs)) { //either two negatives, or 2 positives #ifdef __GNUC__ // Workaround for GCC warning: "comparison is always // false due to limited range of data type." if (!(rhs == 0 || rhs > 0)) #else if(rhs < 0) #endif // __GNUC__ else { //two negatives if(lhs < (T)(MinInt() - rhs)) //remember rhs < 0 { return false; } //ok } else { //two positives if((T)(MaxInt() - lhs) < rhs) { return false; } //OK } } //else overflow not possible result = lhs + rhs; return true; } else //unsigned { if((T)(MaxInt() - lhs) < rhs) { return false; } result = lhs + rhs; return true; } } // Returns true if safe, false on overflow static inline bool subtraction(T lhs, T rhs, T& result) { T tmp = lhs - rhs; if(IsSigned()) { if(IsMixedSign(lhs, rhs)) //test for +/- combo { //mixed positive and negative //two cases - +X - -Y => X + Y - check for overflow against MaxInt() // -X - +Y - check for overflow against MinInt() if(lhs >= 0) //first case { //test is X - -Y > MaxInt() //equivalent to X > MaxInt() - |Y| //Y == MinInt() creates special case //Even 0 - MinInt() can't be done //note that the special case collapses into the general case, due to the fact //MaxInt() - MinInt() == -1, and lhs is non-negative //OR tmp should be GTE lhs // old test - leave in for clarity //if(lhs > (T)(MaxInt() + rhs)) //remember that rhs is negative if(tmp < lhs) { return false; } //fall through to return value } else { //second case //test is -X - Y < MinInt() //or -X < MinInt() + Y //we do not have the same issues because abs(MinInt()) > MaxInt() //tmp should be LTE lhs //if(lhs < (T)(MinInt() + rhs)) // old test - leave in for clarity if(tmp > lhs) { return false; } //fall through to return value } } // else //both negative, or both positive //no possible overflow result = tmp; return true; } else { //easy unsigned case if(lhs < rhs) { return false; } result = tmp; return true; } } private: // Private helper functions // Note that's it occasionally handy to call the arithmetic implementation // functions above so we leave them public, even though we almost always use // the operators instead. // True if the specified value is a power of two. static inline bool IsPowerOf2( T x ) { // find the smallest power of 2 >= x T testPow = 1; while( testPow < x ) { testPow = testPow << 1; // advance to next power of 2 if( testPow <= 0 ) { return false; // overflow } } return( testPow == x ); } // // Instance data // // The integer value this instance represents, or 0 if overflow. T m_value; // True if overflow has been reached. Once this is set, it cannot be cleared. bool m_overflow; // In debug builds we verify that our caller checked the overflow bit before // accessing the value. This flag is cleared on initialization, and whenever // m_value or m_overflow changes, and set only when IsOverflow // is called. INDEBUG( mutable bool m_checkedOverflow; ) }; template <> inline bool ClrSafeInt::multiply(int64_t lhs, int64_t rhs, int64_t &result) { //fast track this one - and avoid DIV_0 below if(lhs == 0 || rhs == 0) { result = 0; return true; } if(!IsMixedSign(lhs, rhs)) { //both positive or both negative //result will be positive, check for lhs * rhs > MaxInt if(lhs > 0) { //both positive if(MaxInt()/lhs < rhs) { //overflow return false; } } else { //both negative //comparison gets tricky unless we force it to positive //EXCEPT that -MinInt is undefined - can't be done //And MinInt always has a greater magnitude than MaxInt if(lhs == MinInt() || rhs == MinInt()) { //overflow return false; } if(MaxInt()/(-lhs) < (-rhs) ) { //overflow return false; } } } else { //mixed sign - this case is difficult //test case is lhs * rhs < MinInt => overflow //if lhs < 0 (implies rhs > 0), //lhs < MinInt/rhs is the correct test //else if lhs > 0 //rhs < MinInt/lhs is the correct test //avoid dividing MinInt by a negative number, //because MinInt/-1 is a corner case if(lhs < 0) { if(lhs < MinInt()/rhs) { //overflow return false; } } else { if(rhs < MinInt()/lhs) { //overflow return false; } } } //ok result = lhs * rhs; return true; } template <> inline bool ClrSafeInt::multiply(uint64_t lhs, uint64_t rhs, uint64_t &result) { //fast track this one - and avoid DIV_0 below if(lhs == 0 || rhs == 0) { result = 0; return true; } //unsigned, easy case if(MaxInt()/lhs < rhs) { //overflow return false; } //ok result = lhs * rhs; return true; } template <> inline bool ClrSafeInt::multiply(int32_t lhs, int32_t rhs, int32_t &result) { INT64 tmp = (INT64)lhs * (INT64)rhs; //upper 33 bits must be the same //most common case is likely that both are positive - test first if( (tmp & 0xffffffff80000000LL) == 0 || (tmp & 0xffffffff80000000LL) == 0xffffffff80000000LL) { //this is OK result = (int32_t)tmp; return true; } //overflow return false; } template <> inline bool ClrSafeInt::multiply(uint32_t lhs, uint32_t rhs, uint32_t &result) { UINT64 tmp = (UINT64)lhs * (UINT64)rhs; if (tmp & 0xffffffff00000000ULL) //overflow { //overflow return false; } result = (uint32_t)tmp; return true; } template <> inline bool ClrSafeInt::multiply(int16_t lhs, int16_t rhs, int16_t &result) { INT32 tmp = (INT32)lhs * (INT32)rhs; //upper 17 bits must be the same //most common case is likely that both are positive - test first if( (tmp & 0xffff8000) == 0 || (tmp & 0xffff8000) == 0xffff8000) { //this is OK result = (int16_t)tmp; return true; } //overflow return false; } template <> inline bool ClrSafeInt::multiply(uint16_t lhs, uint16_t rhs, uint16_t &result) { UINT32 tmp = (UINT32)lhs * (UINT32)rhs; if (tmp & 0xffff0000) //overflow { return false; } result = (uint16_t)tmp; return true; } template <> inline bool ClrSafeInt::multiply(int8_t lhs, int8_t rhs, int8_t &result) { INT16 tmp = (INT16)lhs * (INT16)rhs; //upper 9 bits must be the same //most common case is likely that both are positive - test first if( (tmp & 0xff80) == 0 || (tmp & 0xff80) == 0xff80) { //this is OK result = (int8_t)tmp; return true; } //overflow return false; } template <> inline bool ClrSafeInt::multiply(uint8_t lhs, uint8_t rhs, uint8_t &result) { UINT16 tmp = ((UINT16)lhs) * ((UINT16)rhs); if (tmp & 0xff00) //overflow { return false; } result = (uint8_t)tmp; return true; } // Allows creation of a ClrSafeInt corresponding to the type of the argument. template ClrSafeInt AsClrSafeInt(T t) { return ClrSafeInt(t); } template ClrSafeInt AsClrSafeInt(ClrSafeInt t) { return t; } // Convenience safe-integer types. Currently these are the only types // we are using ClrSafeInt with. We may want to add others. // These type names are based on our standardized names in clrtypes.h typedef ClrSafeInt S_UINT8; typedef ClrSafeInt S_UINT16; //typedef ClrSafeInt S_UINT32; #define S_UINT32 ClrSafeInt typedef ClrSafeInt S_UINT64; typedef ClrSafeInt S_SIZE_T; #endif // SAFEMATH_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/safewrap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // SafeWrap.h // // // This file contains wrapper functions for Win32 API's that take SStrings // and use CLR-safe holders. //***************************************************************************** /* Guidelines for SafeWrapper APIs: Most of these are 'common-sense', plus a few arbitrary decisions thrown in for consistency's sake. - THROWING: Throw on oom, but return all other failure codes. The rationale here is that SString operations already throw, so to make these APIs non-throwing would require an extra EX_TRY/EX_CATCH. Most callees will want to throw on OOM anyways. So making these APIs non-throwing would mean an extra try/catch in the caller + an extra check at the callee. We can eliminate that overhead and just make it throwing. Return non-oom failure codes because callees actually freqeuntly expect an API to fail. For example, the callee will have special handling for file-not-found. For convenience, you could add a no-throwing wrapper version of the API. - NAMING: Prefix the name with 'Clr', just like we do for win32 APIs going through hosting. - DON'T FORGET CONTRACTS: Most of these APIs will likely be Throws/GC_Notrigger. Also use PRECONDITIONs + POSTCONDITIONS when possible. - SIGNATURES: Keep the method signture as close the original win32 API as possible. - Preserve the return type + value. (except allow it to throw on oom). If the return value should be a holder, then use that as an out-parameter at the end of the argument list. We don't want to return holders because that will cause the dtors to be called. - For input strings use 'const SString &' instead of 'LPCWSTR'. - Change ('out' string, length) pairs to 'SString &' (this is the convention the rest of the CLR uses for SStrings) - Use Holders where appropriate. - Preserve other parameters. - USE SSTRINGS TO AVOID BUFFER OVERRUN ISSUES: Repeated here for emphasis. Use SStrings when applicable to make it very easy to verify the code does not have buffer overruns. This will also simplify callsites from having to figure out the length of the output string. - USE YOUR BEST JUDGEMENT: The primary goal of these API wrappers is to embrace 'security-safe' practices. Certainly take any additional steps to that goal. For example, it may make sense to eliminate corner case inputs for a given API or to break a single confusing API up into several discrete and move obvious APIs. */ #ifndef _safewrap_h_ #define _safewrap_h_ #include "holder.h" /* --------------------------------------------------------------------------- * * Simple wrapper around RegisterEventSource/ReportEvent/DeregisterEventSource * --------------------------------------------------------------------------- */ // Returns ERROR_SUCCESS if succeessful in reporting to event log, or // Windows error code to indicate the specific error. DWORD ClrReportEvent( LPCWSTR pEventSource, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, LPCWSTR *lpStrings, DWORD dwDataSize = 0, LPVOID lpRawData = NULL); DWORD ClrReportEvent( LPCWSTR pEventSource, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, LPCWSTR pMessage); //***************************************************************************** // This provides a wrapper around GetFileSize() that forces it to fail // if the file is >4g and pdwHigh is NULL. Other than that, it acts like // the genuine GetFileSize(). // // //***************************************************************************** DWORD inline SafeGetFileSize(HANDLE hFile, DWORD *pdwHigh) { if (pdwHigh != NULL) { return ::GetFileSize(hFile, pdwHigh); } else { DWORD hi; DWORD lo = ::GetFileSize(hFile, &hi); if (lo == 0xffffffff && GetLastError() != NO_ERROR) { return lo; } // api succeeded. is the file too large? if (hi != 0) { // there isn't really a good error to set here... SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0xffffffff; } if (lo == 0xffffffff) { // note that a success return of (hi=0,lo=0xffffffff) will be // treated as an error by the caller. Again, that's part of the // price of being a slacker and not handling the high dword. // We'll set a lasterror for them to pick up. SetLastError(ERROR_NOT_ENOUGH_MEMORY); } return lo; } } #endif // _safewrap_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sarray.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- // SArray.h // -------------------------------------------------------------------------------- #ifndef _SARRAY_H_ #define _SARRAY_H_ #include "sbuffer.h" // -------------------------------------------------------------------------------- // SArray is a typed array wrapper around an SBuffer. It manages individual // constructors and destructors of array elements if avaiable, as well as providing // typed access. // -------------------------------------------------------------------------------- template class SArray { private: SBuffer m_buffer; static COUNT_T VerifySizeRange(ELEMENT * begin, ELEMENT * end); public: class Iterator; friend class Iterator; SArray(); SArray(COUNT_T count); SArray(ELEMENT * begin, ELEMENT * end); ~SArray(); void Clear(); void Set(const SArray &array); COUNT_T GetCount() const; BOOL IsEmpty() const; void SetCount(COUNT_T count); COUNT_T GetAllocation() const; void Preallocate(int count) const; void Trim() const; void Copy(const Iterator &to, const Iterator &from, COUNT_T size); void Move(const Iterator &to, const Iterator &from, COUNT_T size); void Copy(const Iterator &i, const ELEMENT *source, COUNT_T size); void Copy(void *dest, const Iterator &i, COUNT_T size); Iterator Append() { WRAPPER_NO_CONTRACT; COUNT_T count = GetCount(); if ( GetAllocation() == count ) Preallocate( 2 * count ); Iterator i = End(); Insert(i); return i; } void Append(ELEMENT elem) { WRAPPER_NO_CONTRACT; *Append() = elem; } ELEMENT AppendEx(ELEMENT elem) { WRAPPER_NO_CONTRACT; *Append() = elem; return elem; } void Insert(const Iterator &i); void Delete(const Iterator &i); void Insert(const Iterator &i, COUNT_T count); void Delete(const Iterator &i, COUNT_T count); void Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount); ELEMENT *OpenRawBuffer(COUNT_T maxElementCount); ELEMENT *OpenRawBuffer(); void CloseRawBuffer(COUNT_T actualElementCount); void CloseRawBuffer(); Iterator Begin() { WRAPPER_NO_CONTRACT; return Iterator(this, 0); } Iterator End() { WRAPPER_NO_CONTRACT; return Iterator(this, GetCount()); } Iterator operator+(COUNT_T index) { return Iterator(this, index); } ELEMENT & operator[] (int index); const ELEMENT & operator[] (int index) const; ELEMENT & operator[] (COUNT_T index); const ELEMENT & operator[] (COUNT_T index) const; protected: SArray(void *prealloc, COUNT_T size); public: class EMPTY_BASES_DECL Iterator : public CheckedIteratorBase >, public Indexer { friend class SArray; friend class Indexer; SBuffer::Iterator m_i; public: Iterator(SArray *array, SCOUNT_T index) : CheckedIteratorBase >(array) { WRAPPER_NO_CONTRACT; m_i = array->m_buffer.Begin() + index*sizeof(ELEMENT); } protected: ELEMENT &GetAt(SCOUNT_T delta) const { LIMITED_METHOD_CONTRACT; return * (ELEMENT *) &m_i[delta*sizeof(ELEMENT)]; } void Skip(SCOUNT_T delta) { LIMITED_METHOD_CONTRACT; m_i += delta*sizeof(ELEMENT); } COUNT_T Subtract(const Iterator &i) const { LIMITED_METHOD_CONTRACT; return (m_i - i.m_i)/sizeof(ELEMENT); } CHECK DoCheck(SCOUNT_T delta) const { WRAPPER_NO_CONTRACT; return m_i.CheckIndex(delta*sizeof(ELEMENT)); } public: CHECK Check() const { WRAPPER_NO_CONTRACT; return m_i.Check(); } }; ELEMENT *GetElements() const; private: //-------------------------------------------------------------------- // Routines for managing the buffer content. //-------------------------------------------------------------------- void ConstructBuffer(const Iterator &i, COUNT_T size); void CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from); void DestructBuffer(const Iterator &i, COUNT_T size); }; // ================================================================================ // InlineSArray : Tempate for an SArray with preallocated element space // ================================================================================ template class EMPTY_BASES_DECL InlineSArray : public SArray { private: #ifdef TARGET_WINDOWS #pragma warning(push) #pragma warning(disable:4200) // zero sized array #pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads DECLSPEC_ALIGN(BUFFER_ALIGNMENT) BYTE m_prealloc[SIZE*sizeof(ELEMENT)]; #pragma warning(pop) #else // use UINT64 to get maximum alignment of the memory UINT64 m_prealloc[ALIGN(SIZE*sizeof(ELEMENT),sizeof(UINT64))/sizeof(UINT64)]; #endif // _MSC_VER public: InlineSArray(); }; // ================================================================================ // StackSArray : SArray with relatively large preallocated buffer for stack use // ================================================================================ template class EMPTY_BASES_DECL StackSArray : public InlineSArray { }; // ================================================================================ // Inline definitions // ================================================================================ #include "sarray.inl" #endif // _SARRAY_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sarray.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- // SArray.inl // -------------------------------------------------------------------------------- #ifndef _SARRAY_INL_ #define _SARRAY_INL_ #include "sarray.h" template inline SArray::SArray() : m_buffer() { LIMITED_METHOD_CONTRACT; } template inline SArray::SArray(COUNT_T count) : m_buffer(count * sizeof(ELEMENT)) { WRAPPER_NO_CONTRACT; ConstructBuffer(Begin(), count); } template inline COUNT_T SArray::VerifySizeRange(ELEMENT * begin, ELEMENT *end) { WRAPPER_NO_CONTRACT; if (end < begin) ThrowHR(COR_E_OVERFLOW); SIZE_T bufferSize = (end - begin) * sizeof(ELEMENT); if (!FitsIn(bufferSize)) ThrowHR(COR_E_OVERFLOW); return static_cast(bufferSize); } template inline SArray::SArray(ELEMENT * begin, ELEMENT * end) : m_buffer(VerifySizeRange(begin, end)) { WRAPPER_NO_CONTRACT; CopyConstructBuffer(Begin(), static_cast(end - begin), begin); } template inline SArray::SArray(void *prealloc, COUNT_T count) : m_buffer(SBuffer::Prealloc, prealloc, count*sizeof(ELEMENT)) { LIMITED_METHOD_CONTRACT; } template SArray::~SArray() { CONTRACTL { NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; // Cannot call Clear because DestructBuffer has THROWS in its contract if (!BITWISE_COPY) { COUNT_T elementCount = GetCount(); for (COUNT_T i = 0; i < elementCount; i++) { (&((*this)[i]))->~ELEMENT(); } } } template inline void SArray::Clear() { WRAPPER_NO_CONTRACT; DestructBuffer(Begin(), GetCount()); m_buffer.Clear(); } template inline ELEMENT* SArray::OpenRawBuffer(COUNT_T elementCount) { WRAPPER_NO_CONTRACT; return (ELEMENT*)m_buffer.OpenRawBuffer(elementCount * sizeof(ELEMENT)); } template inline ELEMENT* SArray::OpenRawBuffer() { WRAPPER_NO_CONTRACT; return (ELEMENT*)m_buffer.OpenRawBuffer(GetCount() * sizeof(ELEMENT)); } template inline void SArray::CloseRawBuffer(COUNT_T finalElementCount) { WRAPPER_NO_CONTRACT; m_buffer.CloseRawBuffer(finalElementCount * sizeof(ELEMENT)); } template inline void SArray::CloseRawBuffer() { WRAPPER_NO_CONTRACT; m_buffer.CloseRawBuffer(); } template inline void SArray::Set(const SArray &array) { WRAPPER_NO_CONTRACT; if (BITWISE_COPY) { m_buffer.Set(array.m_buffer); } else { DestructBuffer(Begin(), GetCount()); m_buffer.SetSize(0); m_buffer.SetSize(array.m_buffer.GetSize()); CopyConstructBuffer(Begin(), GetCount(), array.GetElements()); } } template inline COUNT_T SArray::GetCount() const { WRAPPER_NO_CONTRACT; return m_buffer.GetSize()/sizeof(ELEMENT); } template inline BOOL SArray::IsEmpty() const { WRAPPER_NO_CONTRACT; return GetCount() == 0; } template inline void SArray::SetCount(COUNT_T count) { WRAPPER_NO_CONTRACT; COUNT_T oldCount = GetCount(); if (count > oldCount) ConstructBuffer(Begin() + oldCount, count - oldCount); m_buffer.SetSize(count*sizeof(ELEMENT)); if (oldCount > count) DestructBuffer(Begin() + count, oldCount - count); } template inline COUNT_T SArray::GetAllocation() const { WRAPPER_NO_CONTRACT; return m_buffer.GetAllocation() / sizeof(ELEMENT); } template inline void SArray::Preallocate(int count) const { WRAPPER_NO_CONTRACT; m_buffer.Preallocate(count * sizeof(ELEMENT)); } template inline void SArray::Trim() const { WRAPPER_NO_CONTRACT; m_buffer.Trim(); } template inline void SArray::Copy(const Iterator &to, const Iterator &from, COUNT_T size) { WRAPPER_NO_CONTRACT; // @todo: destruction/construction semantics are broken on overlapping copies DestructBuffer(to, size); CopyConstructBuffer(to, size, from); } template inline void SArray::Move(const Iterator &to, const Iterator &from, COUNT_T size) { // @todo: destruction/construction semantics are broken on overlapping moves DestructBuffer(to, size); m_buffer.Move(to, from, size*sizeof(ELEMENT)); ConstructBuffer(from, size); } template inline void SArray::Copy(const Iterator &i, const ELEMENT *source, COUNT_T size) { WRAPPER_NO_CONTRACT; DestructBuffer(i, size); CopyConstructBuffer(i, size, source); } template inline void SArray::Copy(void *dest, const Iterator &i, COUNT_T size) { WRAPPER_NO_CONTRACT; // @todo: destruction/construction semantics are unclear m_buffer.Copy(dest, i.m_i, size*sizeof(ELEMENT)); } template inline void SArray::Insert(const Iterator &i) { WRAPPER_NO_CONTRACT; Replace(i, 0, 1); } template inline void SArray::Delete(const Iterator &i) { WRAPPER_NO_CONTRACT; Replace(i, 1, 0); } template inline void SArray::Insert(const Iterator &i, COUNT_T count) { WRAPPER_NO_CONTRACT; Replace(i, 0, count); } template inline void SArray::Delete(const Iterator &i, COUNT_T count) { Delete(i, 0, count); } template inline void SArray::Replace(const Iterator &i, COUNT_T deleteCount, COUNT_T insertCount) { WRAPPER_NO_CONTRACT; DestructBuffer(i, deleteCount); m_buffer.Replace(i.m_i, deleteCount*sizeof(ELEMENT), insertCount*sizeof(ELEMENT)); ConstructBuffer(i, insertCount); } template inline ELEMENT &SArray::operator[](int index) { WRAPPER_NO_CONTRACT; return *(GetElements() + index); } template inline const ELEMENT &SArray::operator[](int index) const { WRAPPER_NO_CONTRACT; return *(GetElements() + index); } template inline ELEMENT &SArray::operator[](COUNT_T index) { WRAPPER_NO_CONTRACT; return *(GetElements() + index); } template inline const ELEMENT &SArray::operator[](COUNT_T index) const { return *(GetElements() + index); } template inline ELEMENT *SArray::GetElements() const { LIMITED_METHOD_CONTRACT; return (ELEMENT *) (const BYTE *) m_buffer; } template inline void SArray::ConstructBuffer(const Iterator &i, COUNT_T size) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; if (!BITWISE_COPY) { ELEMENT *start = GetElements() + (i - Begin()); ELEMENT *end = start + size; while (start < end) { new (start) ELEMENT(); start++; } } } template inline void SArray::CopyConstructBuffer(const Iterator &i, COUNT_T size, const ELEMENT *from) { ptrdiff_t start_offset = i - Begin(); ELEMENT *p = (ELEMENT *) m_buffer.OpenRawBuffer(m_buffer.GetSize()) + start_offset; if (BITWISE_COPY) { memmove(p, from, size * sizeof(ELEMENT)); } else { ELEMENT *start = (ELEMENT *) p; ELEMENT *end = (ELEMENT *) (p + size); while (start < end) { new (start) ELEMENT(*from); start++; from++; } } m_buffer.CloseRawBuffer(); } template inline void SArray::DestructBuffer(const Iterator &i, COUNT_T size) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; if (!BITWISE_COPY) { ELEMENT *start = GetElements() + (i - Begin()); ELEMENT *end = start + size; while (start < end) { start->ELEMENT::~ELEMENT(); start++; } } } template inline InlineSArray::InlineSArray() : SArray((void*)m_prealloc, SIZE) { LIMITED_METHOD_CONTRACT; } #endif // _SARRAY_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sbuffer.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -------------------------------------------------------------------------------- // SBuffer.h (Safe Buffer) // // -------------------------------------------------------------------------------- // -------------------------------------------------------------------------------- // SBuffer is a relatively safe way to manipulate a dynamically // allocated data buffer. An SBuffer is conceptually a simple array // of bytes. It maintains both a conceptual size and an actual allocated size. // // SBuffer provides safe access to the data buffer by providing rich high // level functionality (like insertion, deleteion, copying, comparison, and // iteration) without exposing direct pointers to its buffers. // // For interoperability, SBuffers can expose their buffers - either as readonly // by BYTE * or void * cases, or as writable by the OpenRawBuffer/CloseRawBuffer // entry points. Use of these should be limited wherever possible though; as there // is always a possibilility of buffer overrun. // // To mimimize heap allocations, the InlineSBuffer template will preallocate a fixed // size buffer inline with the SBuffer object itself. It will use this buffer unless // it needs a bigger one, in which case it transparently moves on to using the heap. // The StackSBuffer class instatiates the InlineSBuffer with a standard heuristic // stack preallocation size. // // SBuffer is "subclassable" to add content typeing to the buffer. See SArray and // SString for examples. // -------------------------------------------------------------------------------- #ifndef _SBUFFER_H_ #define _SBUFFER_H_ #include "clrtypes.h" #include "iterator.h" #include "check.h" #include "daccess.h" #include "memoryrange.h" // ================================================================================ // Macros for computing padding // ================================================================================ #define ALIGNMENT(size) \ (( ((size)^((size)-1)) >> 1) +1) #define ALIGN(size, align) \ (((size)+((align)-1)) & ~((align)-1)) #define PAD(size, align) \ (ALIGN((size), (align)) - (size)) // ================================================================================ // SBuffer : base class for safe buffers // ================================================================================ typedef DPTR(class SBuffer) PTR_SBuffer; class SBuffer { public: //-------------------------------------------------------------------- // Flags and constants //-------------------------------------------------------------------- enum ImmutableFlag { Immutable }; enum PreallocFlag { Prealloc }; //-------------------------------------------------------------------- // Types //-------------------------------------------------------------------- public: class CIterator; friend class CIterator; class Iterator; friend class Iterator; //-------------------------------------------------------------------- // Initializers and constructors //-------------------------------------------------------------------- public: // Constructors SBuffer(); SBuffer(COUNT_T size); SBuffer(const BYTE *buffer, COUNT_T size); explicit SBuffer(const SBuffer &buffer); // Immutable constructor should ONLY be used if buffer will // NEVER BE FREED OR MODIFIED. PERIOD. . SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T size); // Prealloc should be allocated inline with SBuffer - it must have the same // lifetime as SBuffer's memory. SBuffer(PreallocFlag prealloc, void *buffer, COUNT_T size); ~SBuffer(); void Clear(); void Set(const SBuffer &buffer); void Set(const BYTE *buffer, COUNT_T size); void SetImmutable(const BYTE *buffer, COUNT_T size); //-------------------------------------------------------------------- // Buffer size routines. A buffer has an externally visible size, but // it also has an internal allocation size which may be larger. //-------------------------------------------------------------------- // Get and set size of buffer. Note that the actual size of the // internally allocated memory block may be bigger. COUNT_T GetSize() const; void SetSize(COUNT_T count); // Grow size of buffer to maximum amount without reallocating. void MaximizeSize(); //-------------------------------------------------------------------- // Buffer allocation routines //-------------------------------------------------------------------- // Return the current available allocation space of the buffer. COUNT_T GetAllocation() const; // Preallocate some memory you expect to use. This can prevent // multiple reallocations. Note this does not change the visible // size of the buffer. void Preallocate(COUNT_T allocation) const; // Shrink memory usage of buffer to minimal amount. Note that // this does not change the visible size of the buffer. void Trim() const; //-------------------------------------------------------------------- // Content manipulation routines //-------------------------------------------------------------------- void Zero(); void Fill(BYTE value); void Fill(const Iterator &to, BYTE value, COUNT_T size); // Internal copy. "Copy" leaves from range as is; "Move" // leaves from range in uninitialized state. // (This distinction is more important when using from a // typed wrapper than in the base SBuffer class.) // // NOTE: Copy vs Move is NOT based on whether ranges overlap // or not. Ranges may overlap in either case. // // Note that both Iterators must be on THIS buffer. void Copy(const Iterator &to, const CIterator &from, COUNT_T size); void Move(const Iterator &to, const CIterator &from, COUNT_T size); // External copy. void Copy(const Iterator &i, const SBuffer &source); void Copy(const Iterator &i, const void *source, COUNT_T size); void Copy(void *dest, const CIterator &i, COUNT_T size); // Insert bytes at the given iterator location. void Insert(const Iterator &i, const SBuffer &source); void Insert(const Iterator &i, COUNT_T size); // Delete bytes at the given iterator location void Delete(const Iterator &i, COUNT_T size); // Replace bytes at the given iterator location void Replace(const Iterator &i, COUNT_T deleteSize, const SBuffer &insert); void Replace(const Iterator &i, COUNT_T deleteSize, COUNT_T insertSize); // Compare entire buffer; return -1, 0, 1 int Compare(const SBuffer &compare) const; int Compare(const BYTE *match, COUNT_T size) const; // Compare entire buffer; return TRUE or FALSE BOOL Equals(const SBuffer &compare) const; BOOL Equals(const BYTE *match, COUNT_T size) const; // Match portion of this buffer to given bytes; return TRUE or FALSE BOOL Match(const CIterator &i, const SBuffer &match) const; BOOL Match(const CIterator &i, const BYTE *match, COUNT_T size) const; //-------------------------------------------------------------------- // Iterators // // Note that any iterator returned is not // valid after any operation which may resize the buffer, unless // the operation was performed on that particular iterator. //-------------------------------------------------------------------- CIterator Begin() const; CIterator End() const; Iterator Begin(); Iterator End(); BYTE & operator[] (int index); const BYTE & operator[] (int index) const; //-------------------------------------------------------------------- // Raw buffer access // // Accessing a raw buffer via pointer is inherently more dangerous than // other uses of this API, and should be avoided if at all possible. // It is primarily provided for compatibility with existing APIs. // // Note that any buffer pointer returned is not // valid after any operation which may resize the buffer. //-------------------------------------------------------------------- // Casting operators return the existing buffer as // a raw const pointer. Note that the pointer is valid only // until the buffer is modified via an API. operator const void *() const; operator const BYTE *() const; // To write directly to the SString's underlying buffer: // 1) Call OpenRawBuffer() and pass it the count of bytes // you need. // 2) That returns a pointer to the raw buffer which you can write to. // 3) When you are done writing to the pointer, call CloseBuffer() // and pass it the count of bytes you actually wrote. // The pointer from step 1 is now invalid. // example usage: // void GetInfo(SBuffer &buf) // { // BYTE *p = buf.OpenRawBuffer(3); // OSGetSomeInfo(p, 3); // buf.CloseRawBuffer(); // } // You should open the buffer, write the data, and immediately close it. // No sbuffer operations are valid while the buffer is opened. // // In a debug build, Open/Close will do lots of little checks to make sure // you don't buffer overflow while it's opened. In a retail build, this // is a very streamlined action. // Open the raw buffer for writing count bytes BYTE *OpenRawBuffer(COUNT_T maxCount); // Call after OpenRawBuffer(). // Provide the count of bytes actually used. This will make sure the // SBuffer's size is correct. void CloseRawBuffer(COUNT_T actualCount); // Close the buffer. Assumes that we completely filled the buffer // that OpenRawBuffer() gave back. void CloseRawBuffer(); //-------------------------------------------------------------------- // Check routines. These are typically used internally, but may be // called externally if desired. //-------------------------------------------------------------------- CHECK CheckBufferClosed() const; static CHECK CheckSize(COUNT_T size); static CHECK CheckAllocation(COUNT_T allocation); CHECK CheckIteratorRange(const CIterator &i) const; CHECK CheckIteratorRange(const CIterator &i, COUNT_T size) const; CHECK Check() const; CHECK Invariant() const; CHECK InternalInvariant() const; protected: //-------------------------------------------------------------------- // Internal helper routines //-------------------------------------------------------------------- // Preserve = preserve contents while reallocating typedef enum { DONT_PRESERVE = 0, PRESERVE = 1, } Preserve; void Resize(COUNT_T size, Preserve preserve = PRESERVE); void ResizePadded(COUNT_T size, Preserve preserve = PRESERVE); void TweakSize(COUNT_T size); void ReallocateBuffer(COUNT_T allocation, Preserve preserve); void EnsureMutable() const; //-------------------------------------------------------------------- // We define some extra flags and fields for subclasses (these are specifically // designed for SString, but use otherwise if desired.) //-------------------------------------------------------------------- BOOL IsFlag1() const; void SetFlag1(); void ClearFlag1(); BOOL IsFlag2() const; void SetFlag2(); void ClearFlag2(); BOOL IsFlag3() const; void SetFlag3(); void ClearFlag3(); INT GetRepresentationField() const; void SetRepresentationField(int value); protected: //-------------------------------------------------------------------- // Flag access //-------------------------------------------------------------------- BOOL IsAllocated() const; void SetAllocated(); void ClearAllocated(); BOOL IsImmutable() const; void SetImmutable(); void ClearImmutable(); #if _DEBUG BOOL IsOpened() const; void SetOpened(); void ClearOpened(); #endif //-------------------------------------------------------------------- // Buffer management routines //-------------------------------------------------------------------- // Allocate and free a memory buffer BYTE *NewBuffer(COUNT_T allocation); void DeleteBuffer(BYTE *buffer, COUNT_T allocation); // Use existing buffer BYTE *UseBuffer(BYTE *buffer, COUNT_T *allocation); CHECK CheckBuffer(const BYTE* buffer, COUNT_T allocation) const; // Manipulates contents of the buffer via the plugins below, but // adds some debugging checks. Should always call through here rather // than directly calling the extensibility points. void DebugMoveBuffer(_Out_writes_bytes_(size) BYTE *to, BYTE *from, COUNT_T size); void DebugCopyConstructBuffer(_Out_writes_bytes_(size) BYTE *to, const BYTE *from, COUNT_T size); void DebugConstructBuffer(BYTE *buffer, COUNT_T size); void DebugDestructBuffer(BYTE *buffer, COUNT_T size); void DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size); #ifdef _DEBUG static BOOL EnsureGarbageCharOnly(const BYTE *buffer, COUNT_T size); #endif CHECK CheckUnusedBuffer(const BYTE *buffer, COUNT_T size) const; #ifdef DACCESS_COMPILE public: // Expose the raw Target address of the buffer to DAC. // This does not do any marshalling. This can be useful if the caller wants to allocate the buffer on // its own heap so that it can survive Flush calls. MemoryRange DacGetRawBuffer() const { SUPPORTS_DAC; PTR_VOID p = dac_cast((TADDR) m_buffer); return MemoryRange(p, GetSize()); } protected: // Return a host copy of the buffer, allocated on the DAC heap (and thus invalidated at the next call to Flush). void* DacGetRawContent(void) const { SUPPORTS_DAC; // SBuffers are used in DAC in two ways - buffers in the host, and marshalled buffers from the target. // This is a problem - we can't reason about the address space of the buffer statically, and instead rely on // the dynamic usage (i.e. the methods are basically bifurcated into those you can use on host instances, // and those you can use on marshalled copies). // Ideally we'll have two versions of the SBuffer code - one that's marshalled (normal DACization) and one // that isn't (host-only utility). This is the "dual-mode DAC problem". // But this only affects a couple classes, and so for now we'll ignore the problem - causing a bunch of DacCop // violations. DACCOP_IGNORE(CastBetweenAddressSpaces, "SBuffer has the dual-mode DAC problem"); DACCOP_IGNORE(FieldAccess, "SBuffer has the dual-mode DAC problem"); TADDR bufAddr = (TADDR)m_buffer; return DacInstantiateTypeByAddress(bufAddr, m_size, true); } void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) const { SUPPORTS_DAC; if (flags != CLRDATA_ENUM_MEM_TRIAGE) { DacEnumMemoryRegion((TADDR)m_buffer, m_size); } } #endif //---------------------------------------------------------------------------- // Iterator base class //---------------------------------------------------------------------------- friend class CheckedIteratorBase; class EMPTY_BASES_DECL Index : public CheckedIteratorBase { friend class SBuffer; friend class CIterator; friend class Indexer; friend class Iterator; friend class Indexer; protected: BYTE* m_ptr; Index(); Index(SBuffer *container, SCOUNT_T index); BYTE &GetAt(SCOUNT_T delta) const; void Skip(SCOUNT_T delta); SCOUNT_T Subtract(const Index &i) const; CHECK DoCheck(SCOUNT_T delta) const; void Resync(const SBuffer *container, BYTE *value) const; }; public: class EMPTY_BASES_DECL CIterator : public Index, public Indexer { friend class SBuffer; public: CIterator() { } CIterator(const SBuffer *buffer, int index) : Index(const_cast(buffer), index) { } }; class EMPTY_BASES_DECL Iterator : public Index, public Indexer { friend class SBuffer; public: operator const CIterator &() const { return *(const CIterator *)this; } operator CIterator &() { return *(CIterator *)this; } Iterator() { } Iterator(SBuffer *buffer, int index) : Index(buffer, index) { } }; //---------------------------------------------------------------------------- // Member and data declarations //---------------------------------------------------------------------------- private: enum { REPRESENTATION_MASK = 0x07, ALLOCATED = 0x08, IMMUTABLE = 0x10, OPENED = 0x20, FLAG1 = 0x40, FLAG2 = 0x80, FLAG3 = 0x100, }; COUNT_T m_size; // externally visible size COUNT_T m_allocation; // actual allocated size UINT32 m_flags; // @todo: steal flags from sizes protected: union { BYTE *m_buffer; WCHAR *m_asStr; // For debugging, view as a unicode string }; #if _DEBUG protected: // We will update the "revision" of the buffer every time it is potentially reallocation, // so we can tell when iterators are no longer valid. int m_revision; #endif }; // ================================================================================ // InlineSBuffer : Tlempate for an SBuffer with preallocated buffer space // ================================================================================ #define BUFFER_ALIGNMENT 4 template class EMPTY_BASES_DECL InlineSBuffer : public SBuffer { private: #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4200) // zero sized array #pragma warning(disable:4324) // don't complain if DECLSPEC_ALIGN actually pads DECLSPEC_ALIGN(BUFFER_ALIGNMENT) BYTE m_prealloc[size]; #pragma warning(pop) #else // use UINT64 to get maximum alignment of the memory UINT64 m_prealloc[ALIGN(size,sizeof(UINT64))/sizeof(UINT64)]; #endif // _MSC_VER public: InlineSBuffer() : SBuffer(Prealloc, (BYTE*)m_prealloc, size) { WRAPPER_NO_CONTRACT; } }; // a 1K sized buffer filled with $ that we'll use in debug builds for verification #define GARBAGE_FILL_DWORD 0x24242424 // $$$$ #define GARBAGE_FILL_BUFFER_ITEMS 16 #define GARBAGE_FILL_BUFFER_SIZE GARBAGE_FILL_BUFFER_ITEMS*sizeof(DWORD) // ================================================================================ // StackSBuffer : SBuffer with relatively large preallocated buffer for stack use // ================================================================================ #define STACK_ALLOC 256 typedef InlineSBuffer StackSBuffer; // ================================================================================ // Inline definitions // ================================================================================ /// a wrapper for templates and such, that use "==". /// more expensive than a typical "==", though inline BOOL operator == (const SBuffer& b1,const SBuffer& b2) { return b1.Equals(b2); }; #include #endif // _SBUFFER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sbuffer.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // #ifndef _SBUFFER_INL_ #define _SBUFFER_INL_ #include "sbuffer.h" #if defined(_MSC_VER) #pragma inline_depth (20) #endif #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4702) // Disable bogus unreachable code warning #endif // _MSC_VER inline SBuffer::SBuffer(PreallocFlag flag, void *buffer, COUNT_T size) : m_size(0), m_allocation(NULL), m_flags(0), m_buffer(NULL) { CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; m_buffer = UseBuffer((BYTE *) buffer, &size); m_allocation = size; #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline SBuffer::SBuffer() : m_size(0), m_allocation(0), m_flags(0), m_buffer(NULL) { CONTRACT_VOID { CONSTRUCTOR_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACT_END; #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline SBuffer::SBuffer(COUNT_T size) : m_size(0), m_allocation(0), m_flags(0), m_buffer(NULL) { CONTRACT_VOID {; CONSTRUCTOR_CHECK; PRECONDITION(CheckSize(size)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Resize(size); #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline SBuffer::SBuffer(const SBuffer &buffer) : m_size(0), m_allocation(0), m_flags(0), m_buffer(NULL) { CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(buffer.Check()); POSTCONDITION(Equals(buffer)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Set(buffer); #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline SBuffer::SBuffer(const BYTE *buffer, COUNT_T size) : m_size(0), m_allocation(0), m_flags(0), m_buffer(NULL) { CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); PRECONDITION(CheckSize(size)); POSTCONDITION(Equals(buffer, size)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Set(buffer, size); #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline SBuffer::SBuffer(ImmutableFlag immutable, const BYTE *buffer, COUNT_T size) : m_size(size), m_allocation(size), m_flags(IMMUTABLE), m_buffer(const_cast(buffer)) { CONTRACT_VOID { CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); PRECONDITION(CheckSize(size)); POSTCONDITION(Equals(buffer, size)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline SBuffer::~SBuffer() { CONTRACT_VOID { NOTHROW; DESTRUCTOR_CHECK; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (IsAllocated()) { DeleteBuffer(m_buffer, m_allocation); } #ifdef _DEBUG m_revision = 0; #endif RETURN; } inline void SBuffer::Set(const SBuffer &buffer) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(buffer.Check()); POSTCONDITION(Equals(buffer)); THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (buffer.IsImmutable() && (IsImmutable() || m_allocation < buffer.GetSize())) { // Share immutable block rather than reallocate and copy // (Note that we prefer to copy to our buffer if we // don't have to reallocate it.) if (IsAllocated()) DeleteBuffer(m_buffer, m_allocation); m_size = buffer.m_size; m_allocation = buffer.m_allocation; m_buffer = buffer.m_buffer; m_flags = buffer.m_flags; #if _DEBUG // Increment our revision to invalidate iterators m_revision++; #endif } else { Resize(buffer.m_size, DONT_PRESERVE); EnsureMutable(); // PreFix seems to think it can choose m_allocation==0 and buffer.m_size > 0 here. // From the code for Resize and EnsureMutable, this is clearly impossible. PREFIX_ASSUME( (this->m_buffer != NULL) || (buffer.m_size == 0) ); MoveMemory(m_buffer, buffer.m_buffer, buffer.m_size); } RETURN; } inline void SBuffer::Set(const BYTE *buffer, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); POSTCONDITION(Equals(buffer, size)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Resize(size); EnsureMutable(); // PreFix seems to think it can choose m_allocation==0 and size > 0 here. // From the code for Resize, this is clearly impossible. PREFIX_ASSUME( (this->m_buffer != NULL) || (size == 0) ); if (size != 0) MoveMemory(m_buffer, buffer, size); RETURN; } inline void SBuffer::SetImmutable(const BYTE *buffer, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); POSTCONDITION(Equals(buffer, size)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; SBuffer temp(Immutable, buffer, size); { // This can't really throw CONTRACT_VIOLATION(ThrowsViolation); Set(temp); } RETURN; } inline COUNT_T SBuffer::GetSize() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return m_size; } inline void SBuffer::SetSize(COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckSize(size)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Resize(size); RETURN; } inline void SBuffer::MaximizeSize() { CONTRACT_VOID { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; } CONTRACT_END; if (!IsImmutable()) Resize(m_allocation); RETURN; } inline COUNT_T SBuffer::GetAllocation() const { CONTRACT(COUNT_T) { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACT_END; RETURN m_allocation; } inline void SBuffer::Preallocate(COUNT_T allocation) const { CONTRACT_VOID { if (allocation) THROWS; else NOTHROW; INSTANCE_CHECK; PRECONDITION(CheckAllocation(allocation)); THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (allocation > m_allocation) const_cast(this)->ReallocateBuffer(allocation, PRESERVE); RETURN; } inline void SBuffer::Trim() const { CONTRACT_VOID { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; } CONTRACT_END; if (!IsImmutable()) const_cast(this)->ReallocateBuffer(m_size, PRESERVE); RETURN; } inline void SBuffer::Zero() { CONTRACT_VOID { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACT_END; ZeroMemory(m_buffer, m_size); RETURN; } inline void SBuffer::Fill(BYTE value) { CONTRACT_VOID { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACT_END; memset(m_buffer, value, m_size); RETURN; } inline void SBuffer::Fill(const Iterator &i, BYTE value, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, size)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; memset(i.m_ptr, value, size); RETURN; } inline void SBuffer::Copy(const Iterator &to, const CIterator &from, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(to, size)); PRECONDITION(CheckIteratorRange(from, size)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; DebugDestructBuffer(to.m_ptr, size); DebugCopyConstructBuffer(to.m_ptr, from.m_ptr, size); RETURN; } inline void SBuffer::Move(const Iterator &to, const CIterator &from, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(to, size)); PRECONDITION(CheckIteratorRange(from, size)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; DebugDestructBuffer(to.m_ptr, size); DebugMoveBuffer(to.m_ptr, from.m_ptr, size); DebugConstructBuffer(from.m_ptr, size); RETURN; } inline void SBuffer::Copy(const Iterator &i, const SBuffer &source) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, source.GetSize())); PRECONDITION(source.Check()); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; DebugDestructBuffer(i.m_ptr, source.m_size); DebugCopyConstructBuffer(i.m_ptr, source.m_buffer, source.m_size); RETURN; } inline void SBuffer::Copy(const Iterator &i, const void *source, COUNT_T size) { CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); PRECONDITION(CheckIteratorRange(i, size)); PRECONDITION(CheckPointer(source, size == 0 ? NULL_OK : NULL_NOT_OK)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; } CONTRACT_END; DebugDestructBuffer(i.m_ptr, size); DebugCopyConstructBuffer(i.m_ptr, (const BYTE *) source, size); RETURN; } inline void SBuffer::Copy(void *dest, const CIterator &i, COUNT_T size) { CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); PRECONDITION(CheckIteratorRange(i, size)); PRECONDITION(CheckPointer(dest, size == 0 ? NULL_OK : NULL_NOT_OK)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; memcpy(dest, i.m_ptr, size); RETURN; } inline void SBuffer::Insert(const Iterator &i, const SBuffer &source) { CONTRACT_VOID { INSTANCE_CHECK; THROWS; PRECONDITION(CheckIteratorRange(i,0)); GC_NOTRIGGER; } CONTRACT_END; Replace(i, 0, source.GetSize()); Copy(i, source, source.GetSize()); RETURN; } inline void SBuffer::Insert(const Iterator &i, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; THROWS; PRECONDITION(CheckIteratorRange(i,0)); GC_NOTRIGGER; } CONTRACT_END; Replace(i, 0, size); RETURN; } inline void SBuffer::Clear() { CONTRACT_VOID { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; } CONTRACT_END; Delete(Begin(), GetSize()); RETURN; } inline void SBuffer::Delete(const Iterator &i, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, size)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Replace(i, size, 0); RETURN; } inline void SBuffer::Replace(const Iterator &i, COUNT_T deleteSize, const SBuffer &insert) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i, deleteSize)); THROWS; GC_NOTRIGGER; } CONTRACT_END; Replace(i, deleteSize, insert.GetSize()); Copy(i, insert, insert.GetSize()); RETURN; } inline int SBuffer::Compare(const SBuffer &compare) const { CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(compare.Check()); POSTCONDITION(RETVAL == -1 || RETVAL == 0 || RETVAL == 1); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; RETURN Compare(compare.m_buffer, compare.m_size); } inline int SBuffer::Compare(const BYTE *compare, COUNT_T size) const { CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckPointer(compare)); PRECONDITION(CheckSize(size)); POSTCONDITION(RETVAL == -1 || RETVAL == 0 || RETVAL == 1); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; COUNT_T smaller; int equals; int result; if (m_size < size) { smaller = m_size; equals = -1; } else if (m_size > size) { smaller = size; equals = 1; } else { smaller = size; equals = 0; } result = memcmp(m_buffer, compare, size); if (result == 0) RETURN equals; else RETURN result; } inline BOOL SBuffer::Equals(const SBuffer &compare) const { CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(compare.Check()); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; RETURN Equals(compare.m_buffer, compare.m_size); } inline BOOL SBuffer::Equals(const BYTE *compare, COUNT_T size) const { CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckPointer(compare)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; if (m_size != size) RETURN FALSE; else RETURN (memcmp(m_buffer, compare, size) == 0); } inline BOOL SBuffer::Match(const CIterator &i, const SBuffer &match) const { CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); PRECONDITION(match.Check()); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; RETURN Match(i, match.m_buffer, match.m_size); } inline BOOL SBuffer::Match(const CIterator &i, const BYTE *match, COUNT_T size) const { CONTRACT(int) { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(match)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; COUNT_T remaining = (COUNT_T) (m_buffer + m_size - i.m_ptr); if (remaining < size) RETURN FALSE; RETURN (memcmp(i.m_ptr, match, size) == 0); } //---------------------------------------------------------------------------- // EnsureMutable // Ensures that the buffer is mutable //---------------------------------------------------------------------------- inline void SBuffer::EnsureMutable() const { CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckBufferClosed()); THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (IsImmutable()) const_cast(this)->ReallocateBuffer(m_allocation, PRESERVE); RETURN; } //---------------------------------------------------------------------------- // Resize // Change the visible size of the buffer; realloc if necessary //---------------------------------------------------------------------------- FORCEINLINE void SBuffer::Resize(COUNT_T size, Preserve preserve) { CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); POSTCONDITION(GetSize() == size); POSTCONDITION(m_allocation >= GetSize()); POSTCONDITION(CheckInvariant(*this)); if (size > 0) THROWS; else NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; #ifdef _DEBUG // Change our revision m_revision++; #endif SCOUNT_T delta = size - m_size; if (delta < 0) DebugDestructBuffer(m_buffer + size, -delta); // Only actually allocate if we are growing if (size > m_allocation) ReallocateBuffer(size, preserve); if (delta > 0) DebugConstructBuffer(m_buffer + m_size, delta); m_size = size; RETURN; } //---------------------------------------------------------------------------- // ResizePadded // Change the visible size of the buffer; realloc if necessary // add extra space to minimize further growth //---------------------------------------------------------------------------- inline void SBuffer::ResizePadded(COUNT_T size, Preserve preserve) { CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); POSTCONDITION(GetSize() == size); POSTCONDITION(m_allocation >= GetSize()); POSTCONDITION(CheckInvariant(*this)); if (size > 0) THROWS; else NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; #ifdef _DEBUG // Change our revision m_revision++; #endif SCOUNT_T delta = size - m_size; if (delta < 0) DebugDestructBuffer(m_buffer + size, -delta); // Only actually allocate if we are growing if (size > m_allocation) { COUNT_T padded = (size*3)/2; ReallocateBuffer(padded, preserve); } if (delta > 0) DebugConstructBuffer(m_buffer + m_size, delta); m_size = size; RETURN; } //---------------------------------------------------------------------------- // TweakSize // An optimized form of Resize, which can only adjust the size within the // currently allocated range, and never reallocates //---------------------------------------------------------------------------- inline void SBuffer::TweakSize(COUNT_T size) { CONTRACT_VOID { PRECONDITION(CheckPointer(this)); PRECONDITION(CheckSize(size)); PRECONDITION(size <= GetAllocation()); POSTCONDITION(GetSize() == size); POSTCONDITION(CheckInvariant(*this)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; #ifdef _DEBUG // Change our revision m_revision++; #endif SCOUNT_T delta = size - m_size; if (delta < 0) DebugDestructBuffer(m_buffer + size, -delta); else DebugConstructBuffer(m_buffer + m_size, delta); m_size = size; RETURN; } //----------------------------------------------------------------------------- // SBuffer allocates all memory via NewBuffer & DeleteBuffer members. // If SBUFFER_CANARY_CHECKS is defined, NewBuffer will place Canaries at the start // and end of the buffer to detect overflows. //----------------------------------------------------------------------------- #ifdef _DEBUG #define SBUFFER_CANARY_CHECKS 1 #endif #ifdef SBUFFER_CANARY_CHECKS // The value we place at the start/end of the buffer, static const UINT64 SBUFFER_CANARY_VALUE = UI64(0xD00BED00BED00BAA); // Expose the quantity of padding needed when providing a prealloced // buffer. This is an unrolled version of the actualAllocation calculated // below for use as a constant value for InlineSString to use. It is // padded with one additional sizeof(SBUFFER_CANARY_VALUE) to account for // possible alignment problems issues (pre- and post-padding). #define SBUFFER_PADDED_SIZE(desiredUsefulSize) \ ((((SIZE_T)(desiredUsefulSize) + sizeof(SBUFFER_CANARY_VALUE) - 1) & \ ~(sizeof(SBUFFER_CANARY_VALUE)-1)) + 3 * sizeof(SBUFFER_CANARY_VALUE)) #else // SBUFFER_CANARY_CHECKS #define SBUFFER_PADDED_SIZE(desiredUsefulSize) (desiredUsefulSize) #endif // SBUFFER_CANARY_CHECKS else // Must match expected guaranteed alignment of new [] #ifdef ALIGN_ACCESS static const int SBUFFER_ALIGNMENT = ALIGN_ACCESS; #else static const int SBUFFER_ALIGNMENT = 4; #endif //---------------------------------------------------------------------------- // Allocate memory, use canaries. //---------------------------------------------------------------------------- inline BYTE *SBuffer::NewBuffer(COUNT_T allocation) { CONTRACT(BYTE*) { PRECONDITION(CheckSize(allocation)); PRECONDITION(allocation > 0); POSTCONDITION(CheckPointer(RETVAL)); THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; #ifdef SBUFFER_CANARY_CHECKS COUNT_T alignPadding = AlignmentPad(allocation, sizeof(SBUFFER_CANARY_VALUE)); COUNT_T actualAllocation= sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding + sizeof(SBUFFER_CANARY_VALUE); BYTE *raw = new BYTE [actualAllocation]; *(UINT64*) raw = SBUFFER_CANARY_VALUE; *(UINT64*) (raw + sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding) = SBUFFER_CANARY_VALUE; BYTE *buffer = raw + sizeof(SBUFFER_CANARY_VALUE); #else BYTE *buffer = new BYTE [allocation]; #endif DebugStompUnusedBuffer(buffer, allocation); CONSISTENCY_CHECK(CheckBuffer(buffer, allocation)); RETURN buffer; } //---------------------------------------------------------------------------- // Use existing memory, use canaries. //---------------------------------------------------------------------------- inline BYTE *SBuffer::UseBuffer(BYTE *buffer, COUNT_T *allocation) { CONTRACT(BYTE*) { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; SUPPORTS_DAC_HOST_ONLY; PRECONDITION(CheckPointer(buffer)); PRECONDITION(CheckSize(*allocation)); // POSTCONDITION(CheckPointer(RETVAL)); POSTCONDITION(CheckSize(*allocation)); } CONTRACT_END; #ifdef SBUFFER_CANARY_CHECKS COUNT_T prepad = AlignmentPad((SIZE_T) buffer, sizeof(SBUFFER_CANARY_VALUE)); COUNT_T postpad = AlignmentTrim((SIZE_T) buffer+*allocation, sizeof(SBUFFER_CANARY_VALUE)); SCOUNT_T usableAllocation = *allocation - prepad - sizeof(SBUFFER_CANARY_VALUE) - sizeof(SBUFFER_CANARY_VALUE) - postpad; if (usableAllocation <= 0) { buffer = NULL; *allocation = 0; } else { BYTE *result = buffer + prepad + sizeof(SBUFFER_CANARY_VALUE); *(UINT64*) (buffer + prepad) = SBUFFER_CANARY_VALUE; *(UINT64*) (buffer + prepad + sizeof(SBUFFER_CANARY_VALUE) + usableAllocation) = SBUFFER_CANARY_VALUE; buffer = result; *allocation = usableAllocation; } #endif DebugStompUnusedBuffer(buffer, *allocation); CONSISTENCY_CHECK(CheckBuffer(buffer, *allocation)); RETURN buffer; } //---------------------------------------------------------------------------- // Free memory allocated by NewHelper //---------------------------------------------------------------------------- inline void SBuffer::DeleteBuffer(BYTE *buffer, COUNT_T allocation) { CONTRACT_VOID { PRECONDITION(CheckSize(allocation)); POSTCONDITION(CheckPointer(buffer)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; CONSISTENCY_CHECK(CheckBuffer(buffer, allocation)); #ifdef SBUFFER_CANARY_CHECKS delete [] (buffer - sizeof(SBUFFER_CANARY_VALUE)); #else delete [] buffer; #endif RETURN; } //---------------------------------------------------------------------------- // Check the buffer at the given address. The memory must have been a pointer // returned by NewHelper. //---------------------------------------------------------------------------- inline CHECK SBuffer::CheckBuffer(const BYTE *buffer, COUNT_T allocation) const { CONTRACT_CHECK { NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; PRECONDITION(CheckPointer(buffer)); } CONTRACT_CHECK_END; if (allocation > 0) { #ifdef SBUFFER_CANARY_CHECKS const BYTE *raw = buffer - sizeof(SBUFFER_CANARY_VALUE); COUNT_T alignPadding = ((allocation + (sizeof(SBUFFER_CANARY_VALUE) - 1)) & ~((sizeof(SBUFFER_CANARY_VALUE) - 1))) - allocation; CHECK_MSG(*(UINT64*) raw == SBUFFER_CANARY_VALUE, "SBuffer underflow"); CHECK_MSG(*(UINT64*) (raw + sizeof(SBUFFER_CANARY_VALUE) + allocation + alignPadding) == SBUFFER_CANARY_VALUE, "SBuffer overflow"); #endif CHECK_MSG((((SIZE_T)buffer) & (SBUFFER_ALIGNMENT-1)) == 0, "SBuffer not properly aligned"); } CHECK_OK; } inline BYTE *SBuffer::OpenRawBuffer(COUNT_T size) { CONTRACT(BYTE*) { #if _DEBUG PRECONDITION_MSG(!IsOpened(), "Can't nest calls to OpenBuffer()"); #endif PRECONDITION(CheckSize(size)); POSTCONDITION(GetSize() == size); THROWS; GC_NOTRIGGER; } CONTRACT_END; Resize(size); EnsureMutable(); #if _DEBUG SetOpened(); #endif RETURN m_buffer; } //---------------------------------------------------------------------------- // Close an open buffer. Assumes that we wrote exactly number of characters // we requested in OpenBuffer. //---------------------------------------------------------------------------- inline void SBuffer::CloseRawBuffer() { CONTRACT_VOID { #if _DEBUG PRECONDITION(IsOpened()); #endif THROWS; GC_NOTRIGGER; } CONTRACT_END; CloseRawBuffer(m_size); RETURN; } //---------------------------------------------------------------------------- // CloseBuffer() tells the SBuffer that we're done using the unsafe buffer. // finalSize is the count of bytes actually used (so we can set m_count). // This is important if we request a buffer larger than what we actually // used. //---------------------------------------------------------------------------- inline void SBuffer::CloseRawBuffer(COUNT_T finalSize) { CONTRACT_VOID { #if _DEBUG PRECONDITION_MSG(IsOpened(), "Can only CloseRawBuffer() after a call to OpenRawBuffer()"); #endif PRECONDITION(CheckSize(finalSize)); PRECONDITION_MSG(finalSize <= GetSize(), "Can't use more characters than requested via OpenRawBuffer()"); THROWS; GC_NOTRIGGER; } CONTRACT_END; #if _DEBUG ClearOpened(); #endif TweakSize(finalSize); CONSISTENCY_CHECK(CheckBuffer(m_buffer, m_allocation)); RETURN; } inline SBuffer::operator const void *() const { LIMITED_METHOD_CONTRACT; return (void *) m_buffer; } inline SBuffer::operator const BYTE *() const { LIMITED_METHOD_DAC_CONTRACT; return m_buffer; } inline BYTE &SBuffer::operator[](int index) { LIMITED_METHOD_CONTRACT; return m_buffer[index]; } inline const BYTE &SBuffer::operator[](int index) const { LIMITED_METHOD_CONTRACT; return m_buffer[index]; } inline SBuffer::Iterator SBuffer::Begin() { CONTRACT(SBuffer::Iterator) { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; // This is a bit unfortunate to have to do here, but it's our // last opportunity before possibly doing a *i= with the iterator EnsureMutable(); RETURN Iterator(this, 0); } inline SBuffer::Iterator SBuffer::End() { CONTRACT(SBuffer::Iterator) { INSTANCE_CHECK; THROWS; GC_NOTRIGGER; } CONTRACT_END; // This is a bit unfortunate to have to do here, but it's our // last opportunity before possibly doing a *i= with the iterator EnsureMutable(); RETURN Iterator(this, m_size); } inline SBuffer::CIterator SBuffer::Begin() const { CONTRACT(SBuffer::CIterator) { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACT_END; RETURN SBuffer::CIterator(this, 0); } inline SBuffer::CIterator SBuffer::End() const { CONTRACT(SBuffer::CIterator) { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACT_END; RETURN CIterator(const_cast(this), m_size); } inline BOOL SBuffer::IsAllocated() const { LIMITED_METHOD_DAC_CONTRACT; return (m_flags & ALLOCATED) != 0; } inline void SBuffer::SetAllocated() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; m_flags |= ALLOCATED; } inline void SBuffer::ClearAllocated() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; m_flags &= ~ALLOCATED; } inline BOOL SBuffer::IsImmutable() const { LIMITED_METHOD_DAC_CONTRACT; return (m_flags & IMMUTABLE) != 0; } inline void SBuffer::SetImmutable() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; m_flags |= IMMUTABLE; } inline void SBuffer::ClearImmutable() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; m_flags &= ~IMMUTABLE; } inline BOOL SBuffer::IsFlag1() const { LIMITED_METHOD_DAC_CONTRACT; return (m_flags & FLAG1) != 0; } inline void SBuffer::SetFlag1() { LIMITED_METHOD_DAC_CONTRACT; m_flags |= FLAG1; } inline void SBuffer::ClearFlag1() { LIMITED_METHOD_CONTRACT; m_flags &= ~FLAG1; } inline BOOL SBuffer::IsFlag2() const { LIMITED_METHOD_CONTRACT; return (m_flags & FLAG2) != 0; } inline void SBuffer::SetFlag2() { LIMITED_METHOD_CONTRACT; m_flags |= FLAG2; } inline void SBuffer::ClearFlag2() { LIMITED_METHOD_CONTRACT; m_flags &= ~FLAG2; } inline BOOL SBuffer::IsFlag3() const { LIMITED_METHOD_DAC_CONTRACT; return (m_flags & FLAG3) != 0; } inline void SBuffer::SetFlag3() { LIMITED_METHOD_CONTRACT; m_flags |= FLAG3; } inline void SBuffer::ClearFlag3() { LIMITED_METHOD_DAC_CONTRACT; m_flags &= ~FLAG3; } inline int SBuffer::GetRepresentationField() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return (m_flags & REPRESENTATION_MASK); } inline void SBuffer::SetRepresentationField(int value) { CONTRACT_VOID { PRECONDITION((value & ~REPRESENTATION_MASK) == 0); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; m_flags &= ~REPRESENTATION_MASK; m_flags |= value; RETURN; } #if _DEBUG inline BOOL SBuffer::IsOpened() const { LIMITED_METHOD_CONTRACT; return (m_flags & OPENED) != 0; } inline void SBuffer::SetOpened() { LIMITED_METHOD_CONTRACT; m_flags |= OPENED; } inline void SBuffer::ClearOpened() { LIMITED_METHOD_CONTRACT; m_flags &= ~OPENED; } #endif inline void SBuffer::DebugMoveBuffer(_Out_writes_bytes_(size) BYTE *to, BYTE *from, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(to, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckPointer(from, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (size == 0) // special case RETURN; // Handle overlapping ranges if (to > from && to < from + size) CONSISTENCY_CHECK(CheckUnusedBuffer(from + size, (COUNT_T) (to - from))); else if (to < from && to + size > from) CONSISTENCY_CHECK(CheckUnusedBuffer(to, (COUNT_T) (from - to))); else CONSISTENCY_CHECK(CheckUnusedBuffer(to, size)); memmove(to, from, size); // Handle overlapping ranges if (to > from && to < from + size) DebugStompUnusedBuffer(from, (COUNT_T) (to - from)); else if (to < from && to + size > from) DebugStompUnusedBuffer(to + size, (COUNT_T) (from - to)); else DebugStompUnusedBuffer(from, size); RETURN; } inline void SBuffer::DebugCopyConstructBuffer(_Out_writes_bytes_(size) BYTE *to, const BYTE *from, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(to, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckPointer(from, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (size != 0) { CONSISTENCY_CHECK(CheckUnusedBuffer(to, size)); memmove(to, from, size); } RETURN; } inline void SBuffer::DebugConstructBuffer(BYTE *buffer, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC; DEBUG_ONLY; } CONTRACT_END; if (size != 0) { CONSISTENCY_CHECK(CheckUnusedBuffer(buffer, size)); } RETURN; } inline void SBuffer::DebugDestructBuffer(BYTE *buffer, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; DEBUG_ONLY; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; if (size != 0) { DebugStompUnusedBuffer(buffer, size); } RETURN; } static const BYTE GARBAGE_FILL_CHARACTER = '$'; extern const DWORD g_garbageFillBuffer[]; inline void SBuffer::DebugStompUnusedBuffer(BYTE *buffer, COUNT_T size) { CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(CheckPointer(buffer, size == 0 ? NULL_OK : NULL_NOT_OK)); PRECONDITION(CheckSize(size)); NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; DEBUG_ONLY; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; #if _DEBUG if (!IsImmutable() || buffer < m_buffer || buffer > m_buffer + m_allocation) // Allocating a new buffer { // Whack the memory if (size > GARBAGE_FILL_BUFFER_SIZE) size = GARBAGE_FILL_BUFFER_SIZE; memset(buffer, GARBAGE_FILL_CHARACTER, size); } #endif RETURN; } #if _DEBUG inline BOOL SBuffer::EnsureGarbageCharOnly(const BYTE *buffer, COUNT_T size) { LIMITED_METHOD_CONTRACT; BOOL bRet = TRUE; if (size > GARBAGE_FILL_BUFFER_SIZE) { size = GARBAGE_FILL_BUFFER_SIZE; } if (bRet && size > 0) { bRet &= (memcmp(buffer, g_garbageFillBuffer, size) == 0); } return bRet; } #endif inline CHECK SBuffer::CheckUnusedBuffer(const BYTE *buffer, COUNT_T size) const { WRAPPER_NO_CONTRACT; // This check is too expensive. #if 0 // _DEBUG if (!IsImmutable() || buffer < m_buffer || buffer > m_buffer + m_allocation) // Allocating a new buffer { if (!SBuffer::EnsureGarbageCharOnly(buffer, size)) { CHECK_FAIL("Overwrite of unused buffer region found"); } } #endif CHECK_OK; } inline CHECK SBuffer::Check() const { WRAPPER_NO_CONTRACT; CHECK(CheckBufferClosed()); CHECK_OK; } inline CHECK SBuffer::Invariant() const { LIMITED_METHOD_CONTRACT; CHECK_OK; } inline CHECK SBuffer::InternalInvariant() const { WRAPPER_NO_CONTRACT; CHECK(m_size <= m_allocation); CHECK(CheckUnusedBuffer(m_buffer + m_size, m_allocation - m_size)); if (IsAllocated()) CHECK(CheckBuffer(m_buffer, m_allocation)); CHECK_OK; } inline CHECK SBuffer::CheckBufferClosed() const { WRAPPER_NO_CONTRACT; #if _DEBUG CHECK_MSG(!IsOpened(), "Cannot use buffer API while raw open is in progress"); #endif CHECK_OK; } inline CHECK SBuffer::CheckSize(COUNT_T size) { LIMITED_METHOD_CONTRACT; // !todo: add any range checking here CHECK_OK; } inline CHECK SBuffer::CheckAllocation(COUNT_T size) { LIMITED_METHOD_CONTRACT; // !todo: add any range checking here CHECK_OK; } inline CHECK SBuffer::CheckIteratorRange(const CIterator &i) const { WRAPPER_NO_CONTRACT; CHECK(i.Check()); CHECK(i.CheckContainer(this)); CHECK(i >= Begin()); CHECK(i < End()); CHECK_OK; } inline CHECK SBuffer::CheckIteratorRange(const CIterator &i, COUNT_T size) const { WRAPPER_NO_CONTRACT; CHECK(i.Check()); CHECK(i.CheckContainer(this)); CHECK(i >= Begin()); CHECK(i + size <= End()); CHECK_OK; } inline SBuffer::Index::Index() { LIMITED_METHOD_DAC_CONTRACT; m_ptr = NULL; } inline SBuffer::Index::Index(SBuffer *container, SCOUNT_T index) : CheckedIteratorBase(container) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; m_ptr = container->m_buffer + index; } inline BYTE &SBuffer::Index::GetAt(SCOUNT_T delta) const { LIMITED_METHOD_DAC_CONTRACT; return m_ptr[delta]; } inline void SBuffer::Index::Skip(SCOUNT_T delta) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; m_ptr += delta; } inline SCOUNT_T SBuffer::Index::Subtract(const Index &i) const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; return (SCOUNT_T) (m_ptr - i.m_ptr); } inline CHECK SBuffer::Index::DoCheck(SCOUNT_T delta) const { WRAPPER_NO_CONTRACT; #if _DEBUG CHECK(m_ptr + delta >= GetContainerDebug()->m_buffer); CHECK(m_ptr + delta < GetContainerDebug()->m_buffer + GetContainerDebug()->m_size); #endif CHECK_OK; } inline void SBuffer::Index::Resync(const SBuffer *buffer, BYTE *value) const { CONTRACT_VOID { // INSTANCE_CHECK - Iterator is out of sync with its object now by definition POSTCONDITION(CheckPointer(this)); PRECONDITION(CheckPointer(buffer)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } CONTRACT_END; const_cast(this)->CheckedIteratorBase::Resync(const_cast(buffer)); const_cast(this)->m_ptr = value; RETURN; } #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER #endif // _SBUFFER_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sha1.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // #ifndef SHA1_H_ #define SHA1_H_ // Hasher class, performs no allocation and therefore does not throw or return // errors. Usage is as follows: // Create an instance (this initializes the hash). // Add one or more blocks of input data using AddData(). // Retrieve the hash using GetHash(). This can be done as many times as desired // until the object is destructed. Once a hash is asked for, further AddData // calls will be ignored. There is no way to reset object state (simply // destroy the object and create another instead). #define SHA1_HASH_SIZE 20 // Number of bytes output by SHA-1 typedef struct { DWORD magic_sha1; // Magic value for A_SHA_CTX DWORD awaiting_data[16]; // Data awaiting full 512-bit block. // Length (nbit_total[0] % 512) bits. // Unused part of buffer (at end) is zero DWORD partial_hash[5]; // Hash through last full block DWORD nbit_total[2]; // Total length of message so far // (bits, mod 2^64) } SHA1_CTX; class SHA1Hash { private: SHA1_CTX m_Context; BYTE m_Value[SHA1_HASH_SIZE]; BOOL m_fFinalized; void SHA1Init(SHA1_CTX*); void SHA1Update(SHA1_CTX*, const BYTE*, const DWORD); void SHA1Final(SHA1_CTX*, BYTE* digest); public: SHA1Hash(); void AddData(BYTE *pbData, DWORD cbData); BYTE *GetHash(); }; #endif // SHA1_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/shash.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _SHASH_H_ #define _SHASH_H_ #include "utilcode.h" // for string hash functions #include "clrtypes.h" #include "check.h" #include "iterator.h" // SHash is a templated closed chaining hash table of pointers. It provides // for multiple entries under the same key, and also for deleting elements. // Synchronization: // Synchronization requirements depend on use. There are several properties to take into account: // // - Lookups may be asynchronous with each other // - Lookups must be exclusive with Add operations // (@todo: this can be remedied by delaying destruction of old tables during reallocation, e.g. during GC) // - Remove operations may be asynchronous with Lookup/Add, unless elements are also deallocated. (In which // case full synchronization is required) // Common "gotchas": // - The Add method never replaces an element. The new element will be added even if an element with the same // key is already present. If you don't want this, use AddOrReplace. // - You need special sentinel values for the element to represent Null and Deleted. 0 and -1 are the default // choices but you will need something else if elements can legally have any of these two values. // - Deriving directly from the general purpose classes (such as SHash itself) requires implementing a // TRAITS class which can be daunting. Consider using one of the specialized classes (e.g. WStringSHash) first. // A SHash is templated by a class of TRAITS. These traits define the various specifics of the // particular hash table. // The required traits are: // // element_t Type of elements in the hash table. These elements are stored // by value in the hash table. Elements must look more or less // like primitives - they must support assignment relatively // efficiently. There are 2 required sentinel values: // Null and Deleted (described below). (Note that element_t is // very commonly a pointer type.) // // The key must be derivable from the element; if your // table's keys are independent of the stored values, element_t // should be a key/value pair. // // key_t Type of the lookup key. The key is used for identity // comparison between elements, and also as a key for lookup. // This is also used by value and should support // efficient assignment. // // count_t integral type for counts. Typically inherited by default // Traits (COUNT_T). // // static key_t GetKey(const element_t &e) Get key from element. Should be stable for a given e. // static BOOL Equals(key_t k1, key_t k2) Compare 2 keys for equality. Again, should be stable. // static count_t Hash(key_t k) Compute hash from a key. For efficient operation, the hashes // for a set of elements should have random uniform distribution. // // static const bool s_NoThrow TRUE if GetKey, Equals, and hash are NOTHROW functions. // Affects the THROWS clauses of several SHash functions. // (Note that the Null- and Deleted-related functions below // are not affected by this and must always be NOTHROW.) // // static element_t Null() Return the Null sentinel value. May be inherited from // default traits if it can be assigned from 0. // static element_t Deleted() Return the Deleted sentinel value. May be inherited from the // default traits if it can be assigned from -1. // static const bool IsNull(const ELEMENT &e) Compare element with Null sentinel value. May be inherited from // default traits if it can be assigned from 0. // static const bool IsDeleted(const ELEMENT &e) Compare element with Deleted sentinel value. May be inherited from the // default traits if it can be assigned from -1. // static bool ShouldDelete(const ELEMENT &e) Called in addition to IsDeleted() when s_supports_autoremove is true, see more // information there. // // static void OnDestructPerEntryCleanupAction(ELEMENT& e) Called on every element when in hashtable destructor. // s_DestructPerEntryCleanupAction must be set to true if implemented. // static void OnRemovePerEntryCleanupAction(ELEMENT& e) Called when an element is removed from the hashtable, including when // the hashtable is destructed. s_RemovePerEntryCleanupAction must be set to true // if implemented. // // s_growth_factor_numerator // s_growth_factor_denominator Factor to grow allocation (numerator/denominator). // Typically inherited from default traits (3/2) // // s_density_factor_numerator // s_density_factor_denominator Maximum occupied density of table before growth // occurs (num/denom). Typically inherited (3/4). // // s_minimum_allocation Minimum table allocation count (size on first growth.) It is // probably preferable to call Reallocate on initialization rather // than override his from the default traits. (7) // // s_supports_remove Set to false for a slightly faster implementation that does not // support deletes. There is a downside to the s_supports_remove flag, // in that there may be more copies of the template instantiated through // the system as different variants are used. // // s_supports_autoremove When autoremove is supported, ShouldDelete() is called in addition to // IsDeleted() in any situation that involves walking the table's elements, to // determine if an element should be deleted. It enables the hash table to // self-clean elements whose underlying lifetime may be controlled externally. Note // that since some lookup/iteration operations are const (can operate on a // "const SHash"), when autoremove is supported, any such const operation may still // modify the hash table. If this is set to true, s_supports_remove must also be // true. // // s_DestructPerEntryCleanupAction Set to true if OnDestructPerEntryCleanupAction has non-empty implementation. // s_RemovePerEntryCleanupAction Set to true if OnRemovePerEntryCleanupAction has non-empty implementation. // Only one of s_DestructPerEntryCleanupAction and s_RemovePerEntryCleanupAction // may be set to true. // // DefaultHashTraits provides defaults for seldomly customized values in traits classes. template < typename ELEMENT > class DefaultSHashTraits { public: typedef COUNT_T count_t; typedef ELEMENT element_t; typedef DPTR(element_t) PTR_element_t; // by default SHash is DAC-aware. For RS // only SHash use NonDacAwareSHashTraits // (which typedefs element_t* PTR_element_t) static const COUNT_T s_growth_factor_numerator = 3; static const COUNT_T s_growth_factor_denominator = 2; static const COUNT_T s_density_factor_numerator = 3; static const COUNT_T s_density_factor_denominator = 4; static const COUNT_T s_minimum_allocation = 7; static const bool s_supports_remove = true; static const bool s_supports_autoremove = false; static ELEMENT Null() { return (ELEMENT)(TADDR)0; } static ELEMENT Deleted() { return (ELEMENT)(TADDR)-1; } static bool IsNull(const ELEMENT &e) { return e == (ELEMENT)(TADDR)0; } static bool IsDeleted(const ELEMENT &e) { return e == (ELEMENT)(TADDR)-1; } static bool ShouldDelete(const ELEMENT &e) { return false; } static inline void OnDestructPerEntryCleanupAction(const ELEMENT& e) { /* Do nothing */ } static const bool s_DestructPerEntryCleanupAction = false; static void OnRemovePerEntryCleanupAction(const ELEMENT &e) {} static const bool s_RemovePerEntryCleanupAction = false; static const bool s_NoThrow = true; // No defaults - must specify: // // typedef key_t; // static key_t GetKey(const element_t &i); // static BOOL Equals(key_t k1, key_t k2); // static count_t Hash(key_t k); }; // Hash table class definition template class EMPTY_BASES_DECL SHash : public TRAITS , private noncopyable { friend class VerifyLayoutsMD; // verifies class layout doesn't accidentally change public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename TRAITS::element_t element_t; typedef typename TRAITS::PTR_element_t PTR_element_t; typedef typename TRAITS::key_t key_t; typedef typename TRAITS::count_t count_t; class Index; friend class Index; class Iterator; class KeyIndex; friend class KeyIndex; class KeyIterator; // Constructor/destructor. SHash tables always start out empty, with no // allocation overhead. Call Reallocate to prime with an initial size if // desired. SHash(); ~SHash(); // Lookup an element in the table by key. Returns NULL if no element in the table // has the given key. Note that multiple entries for the same key may be stored - // this will return the first element added. Use KeyIterator to find all elements // with a given key. element_t Lookup(key_t key) const; // Pointer-based flavor of Lookup (allows efficient access to tables of structures) const element_t* LookupPtr(key_t key) const; // Pointer-based flavor to replace an existing element (allows efficient access to tables of structures) void ReplacePtr(const element_t *elementPtr, const element_t &newElement, bool invokeCleanupAction = true); // Add an element to the hash table. This will never replace an element; multiple // elements may be stored with the same key. void Add(const element_t &element); // NoThrow version of Add. Returns TRUE if element was added, FALSE otherwise. BOOL AddNoThrow(const element_t &element); // Add a new element to the hash table, if no element with the same key is already // there. Otherwise, it will replace the existing element. This has the effect of // updating an element rather than adding a duplicate. void AddOrReplace(const element_t & element); // NoThrow version of AddOrReplace. Returns TRUE if element was added/replaced, FALSE otherwise. BOOL AddOrReplaceNoThrow(const element_t &element); // Remove the first element matching the key from the hash table. void Remove(key_t key); // Remove the specific element. void Remove(Iterator& i); void Remove(KeyIterator& i); // Pointer-based flavor of Remove (allows efficient access to tables of structures) void RemovePtr(element_t * element); // Remove all elements in the hashtable void RemoveAll(); // Begin and End pointers for iteration over entire table. Iterator Begin() const; Iterator End() const; // Begin and End pointers for iteration over all elements with a given key. KeyIterator Begin(key_t key) const; KeyIterator End(key_t key) const; // Return the number of elements currently stored in the table count_t GetCount() const; // Return the number of elements allocated in the table count_t GetCapacity() const; // Resizes a hash table for growth. The new size is computed based // on the current population, growth factor, and maximum density factor. void Grow(); // Reallocates a hash table to a specific size. The size must be big enough // to hold all elements in the table appropriately. // // Note that the actual table size must always be a prime number; the number // passed in will be upward adjusted if necessary. void Reallocate(count_t newTableSize); // Makes a call on the Functor for each element in the hash table, passing // the element as an argument. Functor is expected to look like this: // // class Functor // { // public: // void operator() (element_t &element) { ... } // } template void ForEach(Functor &functor); private: // NoThrow version of Grow function. Returns FALSE on failure. BOOL GrowNoThrow(); // See if it is OK to grow the hash table by one element. If not, reallocate // the hash table. BOOL CheckGrowth(); // NoThrow version of CheckGrowth function. Returns FALSE on failure. BOOL CheckGrowthNoThrow(); // Allocates new resized hash table for growth. Does not update the hash table on the object. // The new size is computed based on the current population, growth factor, and maximum density factor. element_t * Grow_OnlyAllocateNewTable(count_t * pcNewSize); // NoThrow version of Grow_OnlyAllocateNewTable. Returns NULL on failure. element_t * Grow_OnlyAllocateNewTableNoThrow(count_t * pcNewSize); // Utility function to allocate new table (does not copy the values into it yet). Returns the size of new table in // *pcNewTableSize (finds next prime). // Phase 1 of code:Reallocate element_t * AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize); // NoThrow version of AllocateNewTable utility function. Returns NULL on failure. element_t * AllocateNewTableNoThrow(count_t requestedSize, count_t * pcNewTableSize); // Utility function to replace old table with newly allocated table (as allocated by // code:AllocateNewTable). Copies all 'old' values into the new table first. // Returns the old table. Caller is expected to delete it (via code:DeleteOldTable). // Phase 2 of code:Reallocate element_t * ReplaceTable(element_t * newTable, count_t newTableSize); // Utility function to delete old table (as returned by code:ReplaceTable). // Phase 3 of code:Reallocate void DeleteOldTable(element_t * oldTable); // Utility function that does not call code:CheckGrowth. // Add an element to the hash table. This will never replace an element; multiple // elements may be stored with the same key. void Add_GrowthChecked(const element_t & element); // Utility function to add a new element to the hash table. Note that // it is perfectly fine for the element to be a duplicate - if so it // is added an additional time. Returns TRUE if a new empty spot was used; // FALSE if an existing deleted slot. BOOL Add(element_t *table, count_t tableSize, const element_t &element); // Utility function to add a new element to the hash table, if no element with the same key // is already there. Otherwise, it will replace the existing element. This has the effect of // updating an element rather than adding a duplicate. void AddOrReplace(element_t *table, count_t tableSize, const element_t &element); // Utility function to find the first element with the given key in // the hash table. const element_t* Lookup(PTR_element_t table, count_t tableSize, key_t key) const; // Utility function to remove the first element with the given key // in the hash table. void Remove(element_t *table, count_t tableSize, key_t key); // Utility function to remove the specific element. void RemoveElement(element_t *table, count_t tableSize, element_t *element); // Index for whole table iterator. This is also the base for the keyed iterator. public: class EMPTY_BASES_DECL Index : public CheckedIteratorBase< SHash > { friend class SHash; friend class Iterator; friend class Enumerator; // The methods implementation has to be here for portability // Some compilers won't compile the separate implementation in shash.inl protected: SHash *m_hash; PTR_element_t m_table; count_t m_tableSize; count_t m_index; // Iteration may modify the hash table if s_supports_autoremove is true. Since it typically does not modify the hash // table, it should be possible to iterate over a "const SHash". So this takes a "const SHash *" and casts away the // const to support autoremove. Index(const SHash *hash, BOOL begin) : m_hash(const_cast(hash)), m_table(hash->m_table), m_tableSize(hash->m_tableSize), m_index(begin ? 0 : m_tableSize) { LIMITED_METHOD_CONTRACT; } const element_t &Get() const { LIMITED_METHOD_CONTRACT; return m_table[m_index]; } void First() { LIMITED_METHOD_CONTRACT; if (m_index >= m_tableSize) { return; } if (!TRAITS::IsNull(m_table[m_index]) && !TRAITS::IsDeleted(m_table[m_index])) { if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(m_table[m_index])) { m_hash->RemoveElement(m_table, m_tableSize, &m_table[m_index]); } else { return; } } Next(); } void Next() { LIMITED_METHOD_CONTRACT; if (m_index >= m_tableSize) return; for (;;) { m_index++; if (m_index >= m_tableSize) break; if (!TRAITS::IsNull(m_table[m_index]) && !TRAITS::IsDeleted(m_table[m_index])) { if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(m_table[m_index])) { m_hash->RemoveElement(m_table, m_tableSize, &m_table[m_index]); } else { break; } } } } bool Equal(const Index &i) const { LIMITED_METHOD_CONTRACT; return i.m_index == m_index; } CHECK DoCheck() const { CHECK_OK; } }; class EMPTY_BASES_DECL Iterator : public Index, public Enumerator { friend class SHash; public: Iterator(const SHash *hash, BOOL begin) : Index(hash, begin) { } }; // Index for iterating elements with a given key. // // Note that the m_index field // is artificially bumped to m_tableSize when the end of iteration is reached. // This allows a canonical End iterator to be used. class EMPTY_BASES_DECL KeyIndex : public Index { friend class SHash; friend class KeyIterator; friend class Enumerator; // The methods implementation has to be here for portability // Some compilers won't compile the separate implementation in shash.inl protected: key_t m_key; count_t m_increment; KeyIndex(const SHash *hash, BOOL begin) : Index(hash, begin), m_increment(0) { LIMITED_METHOD_CONTRACT; } void SetKey(key_t key) { LIMITED_METHOD_CONTRACT; if (Index::m_tableSize > 0) { m_key = key; count_t hash = TRAITS::Hash(key); this->m_index = hash % this->m_tableSize; m_increment = (hash % (this->m_tableSize-1)) + 1; // Find first valid element if (TRAITS::IsNull(this->m_table[this->m_index])) { this->m_index = this->m_tableSize; return; } if (!TRAITS::IsDeleted(this->m_table[this->m_index])) { if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(this->m_table[this->m_index])) { this->m_hash->RemoveElement(this->m_table, this->m_tableSize, &this->m_table[this->m_index]); } else if (TRAITS::Equals(m_key, TRAITS::GetKey(this->m_table[this->m_index]))) { return; } } Next(); } } void Next() { LIMITED_METHOD_CONTRACT; while (TRUE) { this->m_index += m_increment; if (this->m_index >= this->m_tableSize) this->m_index -= this->m_tableSize; if (TRAITS::IsNull(this->m_table[this->m_index])) { this->m_index = this->m_tableSize; break; } if (TRAITS::IsDeleted(this->m_table[this->m_index])) { continue; } if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(this->m_table[this->m_index])) { this->m_hash->RemoveElement(this->m_table, this->m_tableSize, &this->m_table[this->m_index]); continue; } if (TRAITS::Equals(m_key, TRAITS::GetKey(this->m_table[this->m_index]))) { break; } } } }; class EMPTY_BASES_DECL KeyIterator : public KeyIndex, public Enumerator { friend class SHash; public: operator Iterator &() { return *(Iterator*)this; } operator const Iterator &() { return *(const Iterator*)this; } KeyIterator(const SHash *hash, BOOL begin) : KeyIndex(hash, begin) { } }; private: // Test for prime number. static BOOL IsPrime(COUNT_T number); // Find the next prime number >= the given value. static COUNT_T NextPrime(COUNT_T number); // Instance members PTR_element_t m_table; // pointer to table count_t m_tableSize; // allocated size of table count_t m_tableCount; // number of elements in table count_t m_tableOccupied; // number, includes deleted slots count_t m_tableMax; // maximum occupied count before reallocating }; // class SHash // disables support for DAC marshaling. Useful for defining right-side only SHashes template class EMPTY_BASES_DECL NonDacAwareSHashTraits : public PARENT { public: typedef typename PARENT::element_t element_t; typedef element_t * PTR_element_t; }; // disables support for removing elements - produces slightly faster implementation template class EMPTY_BASES_DECL NoRemoveSHashTraits : public PARENT { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename PARENT::element_t element_t; typedef typename PARENT::count_t count_t; static const bool s_supports_remove = false; static element_t Deleted() { UNREACHABLE(); } static bool IsDeleted(const element_t &e) { LIMITED_METHOD_DAC_CONTRACT; return false; } }; // PtrHashTraits is a template to provides useful defaults for pointer hash tables // It relies on methods GetKey and Hash defined on ELEMENT template class EMPTY_BASES_DECL PtrSHashTraits : public DefaultSHashTraits { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef DefaultSHashTraits PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::count_t count_t; typedef KEY key_t; static key_t GetKey(const element_t &e) { WRAPPER_NO_CONTRACT; return e->GetKey(); } static BOOL Equals(key_t k1, key_t k2) { LIMITED_METHOD_CONTRACT; return k1 == k2; } static count_t Hash(key_t k) { WRAPPER_NO_CONTRACT; return ELEMENT::Hash(k); } }; template class EMPTY_BASES_DECL PtrSHash : public SHash< PtrSHashTraits > { }; template class PtrSHashWithCleanupTraits : public PtrSHashTraits { public: void OnDestructPerEntryCleanupAction(ELEMENT * elem) { delete elem; } static const bool s_DestructPerEntryCleanupAction = true; }; // a class that automatically deletes data referenced by the pointers (so effectively it takes ownership of the data) // since I was too lazy to implement Remove() APIs properly, removing entries is disallowed template class EMPTY_BASES_DECL PtrSHashWithCleanup : public SHash< NoRemoveSHashTraits< PtrSHashWithCleanupTraits > > { }; // Provides case-sensitive comparison and hashing functionality through static // and functor object methods. Can be instantiated with CHAR or WCHAR. template struct CaseSensitiveStringCompareHash { private: typedef CharT const * str_t; static size_t _strcmp(CHAR const *left, CHAR const *right) { return ::strcmp(left, right); } static size_t _strcmp(WCHAR const *left, WCHAR const *right) { return ::wcscmp(left, right); } static size_t _hash(CHAR const *str) { return HashStringA(str); } static size_t _hash(WCHAR const *str) { return HashString(str); } public: static size_t compare(str_t left, str_t right) { return _strcmp(left, right); } size_t operator()(str_t left, str_t right) { return compare(left, right); } static size_t hash(str_t str) { return _hash(str); } size_t operator()(str_t str) { return hash(str); } }; // Provides case-insensitive comparison and hashing functionality through static // and functor object methods. Can be instantiated with CHAR or WCHAR. template struct CaseInsensitiveStringCompareHash { private: typedef CharT const * str_t; static size_t _strcmp(str_t left, str_t right) { return ::SString::_tstricmp(left, right); } static size_t _hash(CHAR const *str) { return HashiStringA(str); } static size_t _hash(WCHAR const *str) { return HashiString(str); } public: static size_t compare(str_t left, str_t right) { return _strcmp(left, right); } size_t operator()(str_t left, str_t right) { return compare(left, right); } static size_t hash(str_t str) { return _hash(str); } size_t operator()(str_t str) { return hash(str); } }; // StringSHashTraits is a traits class useful for string-keyed // pointer hash tables. template > class EMPTY_BASES_DECL StringSHashTraits : public PtrSHashTraits { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef PtrSHashTraits PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::key_t key_t; typedef typename PARENT::count_t count_t; static BOOL Equals(key_t k1, key_t k2) { LIMITED_METHOD_CONTRACT; if (k1 == NULL && k2 == NULL) return TRUE; if (k1 == NULL || k2 == NULL) return FALSE; return ComparerT::compare(k1, k2) == 0; } static count_t Hash(key_t k) { LIMITED_METHOD_CONTRACT; if (k == NULL) return 0; else return (count_t)ComparerT::hash(k); } }; template // Could use IUnknown but would rather take advantage of C++ type checking struct StringHashElement { const CharT *GetKey() { return String; } COMINTERFACE *Object; CharT *String; }; template > class EMPTY_BASES_DECL StringHashWithCleanupTraits : public StringSHashTraits, CharT, ComparerT> { public: void OnDestructPerEntryCleanupAction(StringHashElement * e) { if (e->String != NULL) { delete[] e->String; } if (e->Object != NULL) { e->Object->Release(); } } static const bool s_DestructPerEntryCleanupAction = true; }; template > class EMPTY_BASES_DECL StringSHashWithCleanup : public SHash< StringHashWithCleanupTraits > { }; template class EMPTY_BASES_DECL StringSHash : public SHash< StringSHashTraits > { }; template class EMPTY_BASES_DECL WStringSHash : public SHash< StringSHashTraits > { }; template class EMPTY_BASES_DECL SStringSHashTraits : public PtrSHashTraits { public: typedef PtrSHashTraits PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::key_t key_t; typedef typename PARENT::count_t count_t; static const bool s_NoThrow = false; static BOOL Equals(const key_t &k1, const key_t &k2) { WRAPPER_NO_CONTRACT; return k1.Equals(k2); } static count_t Hash(const key_t &k) { WRAPPER_NO_CONTRACT; return k.Hash(); } }; template class EMPTY_BASES_DECL SStringSHash : public SHash< SStringSHashTraits > { }; template class EMPTY_BASES_DECL SetSHashTraits : public DefaultSHashTraits { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename DefaultSHashTraits::element_t element_t; typedef typename DefaultSHashTraits::count_t count_t; typedef ELEMENT key_t; static key_t GetKey(element_t e) { LIMITED_METHOD_CONTRACT; return e; } static BOOL Equals(key_t k1, key_t k2) { LIMITED_METHOD_CONTRACT; return k1 == k2; } static count_t Hash(key_t k) { LIMITED_METHOD_CONTRACT; return (count_t)(size_t)k; } }; template > > class EMPTY_BASES_DECL SetSHash : public SHash< TRAITS > { typedef SHash PARENT; public: BOOL Contains(ELEMENT key) const { return PARENT::LookupPtr(key) != NULL; } }; template class EMPTY_BASES_DECL PtrSetSHashTraits : public SetSHashTraits { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef SetSHashTraits PARENT; typedef typename PARENT::element_t element_t; typedef typename PARENT::key_t key_t; typedef typename PARENT::count_t count_t; static count_t Hash(key_t k) { WRAPPER_NO_CONTRACT; return (count_t)(size_t)k >> 2; } }; template class EMPTY_BASES_DECL DeleteElementsOnDestructSHashTraits : public PARENT_TRAITS { public: static inline void OnDestructPerEntryCleanupAction(typename PARENT_TRAITS::element_t e) { delete e; } static const bool s_DestructPerEntryCleanupAction = true; }; #if !defined(CC_JIT) // workaround: Key is redefined in JIT64 template class KeyValuePair { KEY key; VALUE value; public: KeyValuePair() { } KeyValuePair(const KEY& k, const VALUE& v) : key(k), value(v) { } KEY const & Key() const { LIMITED_METHOD_CONTRACT; return key; } VALUE const & Value() const { LIMITED_METHOD_CONTRACT; return value; } }; template class EMPTY_BASES_DECL MapSHashTraits : public DefaultSHashTraits< KeyValuePair > { public: // explicitly declare local typedefs for these traits types, otherwise // the compiler may get confused typedef typename DefaultSHashTraits< KeyValuePair >::element_t element_t; typedef typename DefaultSHashTraits< KeyValuePair >::count_t count_t; typedef KEY key_t; static key_t GetKey(element_t e) { LIMITED_METHOD_CONTRACT; return e.Key(); } static BOOL Equals(key_t k1, key_t k2) { LIMITED_METHOD_CONTRACT; return k1 == k2; } static count_t Hash(key_t k) { LIMITED_METHOD_CONTRACT; return (count_t)(size_t)k; } static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(KEY(),VALUE()); } static const element_t Deleted() { LIMITED_METHOD_CONTRACT; return element_t(KEY(-1), VALUE()); } static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.Key() == KEY(); } static bool IsDeleted(const element_t &e) { return e.Key() == KEY(-1); } }; template > > class EMPTY_BASES_DECL MapSHash : public SHash< TRAITS > { typedef SHash< TRAITS > PARENT; public: void Add(KEY key, VALUE value) { CONTRACTL { THROWS; GC_NOTRIGGER; PRECONDITION(key != (KEY)0); } CONTRACTL_END; PARENT::Add(KeyValuePair(key, value)); } BOOL Lookup(KEY key, VALUE* pValue) const; }; template class EMPTY_BASES_DECL MapSHashWithRemove : public SHash< MapSHashTraits > { typedef SHash< MapSHashTraits > PARENT; public: void Add(KEY key, VALUE value) { CONTRACTL { THROWS; GC_NOTRIGGER; PRECONDITION(key != (KEY)0 && key != (KEY)-1); } CONTRACTL_END; PARENT::Add(KeyValuePair(key, value)); } BOOL Lookup(KEY key, VALUE* pValue) const { CONTRACTL { NOTHROW; GC_NOTRIGGER; PRECONDITION(key != (KEY)0 && key != (KEY)-1); } CONTRACTL_END; const KeyValuePair *pRet = PARENT::LookupPtr(key); if (pRet == NULL) return FALSE; *pValue = pRet->Value(); return TRUE; } void Remove(KEY key) { CONTRACTL { NOTHROW; GC_NOTRIGGER; PRECONDITION(key != (KEY)0 && key != (KEY)-1); } CONTRACTL_END; PARENT::Remove(key); } }; #endif // CC_JIT #include "shash.inl" #endif // _SHASH_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/shash.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _SHASH_INL_ #define _SHASH_INL_ // Many SHash functions do not throw on their own, but may propagate an exception // from Hash, Equals, or GetKey. #define NOTHROW_UNLESS_TRAITS_THROWS if (TRAITS::s_NoThrow) NOTHROW; else THROWS void DECLSPEC_NORETURN ThrowOutOfMemory(); template SHash::SHash() : m_table(nullptr), m_tableSize(0), m_tableCount(0), m_tableOccupied(0), m_tableMax(0) { LIMITED_METHOD_CONTRACT; #ifndef __GNUC__ // these crash GCC static_assert_no_msg(SHash::s_growth_factor_numerator > SHash::s_growth_factor_denominator); static_assert_no_msg(SHash::s_density_factor_numerator < SHash::s_density_factor_denominator); #endif static_assert_no_msg(TRAITS::s_supports_remove || !TRAITS::s_supports_autoremove); static_assert_no_msg(!TRAITS::s_DestructPerEntryCleanupAction || !TRAITS::s_RemovePerEntryCleanupAction); } template SHash::~SHash() { LIMITED_METHOD_CONTRACT; if (TRAITS::s_DestructPerEntryCleanupAction) { for (Iterator i = Begin(); i != End(); i++) { TRAITS::OnDestructPerEntryCleanupAction(*i); } } else if (TRAITS::s_RemovePerEntryCleanupAction) { for (Iterator i = Begin(); i != End(); i++) { TRAITS::OnRemovePerEntryCleanupAction(*i); } } delete [] m_table; } template typename SHash::count_t SHash::GetCount() const { LIMITED_METHOD_CONTRACT; return m_tableCount; } template typename SHash::count_t SHash::GetCapacity() const { LIMITED_METHOD_CONTRACT; return m_tableMax; } template typename SHash::element_t SHash::Lookup(key_t key) const { CONTRACT(element_t) { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; INSTANCE_CHECK; POSTCONDITION(TRAITS::IsNull(RETVAL) || TRAITS::Equals(key, TRAITS::GetKey(RETVAL))); SUPPORTS_DAC_WRAPPER; } CONTRACT_END; const element_t *pRet = Lookup(m_table, m_tableSize, key); RETURN ((pRet != NULL) ? (*pRet) : TRAITS::Null()); } template const typename SHash::element_t * SHash::LookupPtr(key_t key) const { CONTRACT(const element_t *) { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; INSTANCE_CHECK; POSTCONDITION(RETVAL == NULL || TRAITS::Equals(key, TRAITS::GetKey(*RETVAL))); } CONTRACT_END; RETURN Lookup(m_table, m_tableSize, key); } template void SHash::ReplacePtr(const element_t *elementPtr, const element_t &newElement, bool invokeCleanupAction) { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(m_table <= elementPtr); PRECONDITION(elementPtr < m_table + m_tableSize); PRECONDITION(!TRAITS::IsNull(*elementPtr)); PRECONDITION(!TRAITS::IsDeleted(*elementPtr)); PRECONDITION(!TRAITS::IsNull(newElement)); PRECONDITION(!TRAITS::IsDeleted(newElement)); PRECONDITION(TRAITS::Equals(TRAITS::GetKey(newElement), TRAITS::GetKey(*elementPtr))); } CONTRACT_END; if (TRAITS::s_RemovePerEntryCleanupAction && invokeCleanupAction) { TRAITS::OnRemovePerEntryCleanupAction(*elementPtr); } *const_cast(elementPtr) = newElement; RETURN; } template void SHash::Add(const element_t & element) { CONTRACT_VOID { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; CheckGrowth(); Add_GrowthChecked(element); RETURN; } template BOOL SHash::AddNoThrow(const element_t & element) { CONTRACT(BOOL) { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; static_assert(TRAITS::s_NoThrow, "This SHash does not support NOTHROW."); BOOL haveSpace = CheckGrowthNoThrow(); if (haveSpace) Add_GrowthChecked(element); RETURN haveSpace; } template void SHash::Add_GrowthChecked(const element_t & element) { CONTRACT_VOID { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; INSTANCE_CHECK; POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; if (Add(m_table, m_tableSize, element)) m_tableOccupied++; m_tableCount++; RETURN; } template void SHash::AddOrReplace(const element_t &element) { CONTRACT_VOID { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; static_assert(!TRAITS::s_supports_remove, "SHash::AddOrReplace is not implemented for SHash with support for remove operations."); POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; CheckGrowth(); AddOrReplace(m_table, m_tableSize, element); RETURN; } template BOOL SHash::AddOrReplaceNoThrow(const element_t &element) { CONTRACT(BOOL) { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; static_assert(!TRAITS::s_supports_remove, "SHash::AddOrReplaceNoThrow is not implemented for SHash with support for remove operations."); POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*LookupPtr(TRAITS::GetKey(element))))); } CONTRACT_END; static_assert(TRAITS::s_NoThrow, "This SHash does not support NOTHROW."); BOOL haveSpace = CheckGrowthNoThrow(); if (haveSpace) AddOrReplace(m_table, m_tableSize, element); RETURN haveSpace; } template void SHash::Remove(key_t key) { CONTRACT_VOID { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; INSTANCE_CHECK; static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); PRECONDITION(!(TRAITS::IsNull(Lookup(key)))); } CONTRACT_END; Remove(m_table, m_tableSize, key); RETURN; } template void SHash::Remove(Iterator& i) { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); PRECONDITION(!(TRAITS::IsNull(*i))); PRECONDITION(!(TRAITS::IsDeleted(*i))); } CONTRACT_END; RemoveElement(m_table, m_tableSize, (element_t*)&(*i)); RETURN; } template void SHash::Remove(KeyIterator& i) { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); PRECONDITION(!(TRAITS::IsNull(*i))); PRECONDITION(!(TRAITS::IsDeleted(*i))); } CONTRACT_END; RemoveElement(m_table, m_tableSize, (element_t*)&(*i)); RETURN; } template void SHash::RemovePtr(element_t * p) { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); PRECONDITION(!(TRAITS::IsNull(*p))); PRECONDITION(!(TRAITS::IsDeleted(*p))); } CONTRACT_END; RemoveElement(m_table, m_tableSize, p); RETURN; } template void SHash::RemoveAll() { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; } CONTRACT_END; if (TRAITS::s_RemovePerEntryCleanupAction) { for (Iterator i = Begin(); i != End(); i++) { TRAITS::OnRemovePerEntryCleanupAction(*i); } } delete [] m_table; m_table = NULL; m_tableSize = 0; m_tableCount = 0; m_tableOccupied = 0; m_tableMax = 0; RETURN; } template typename SHash::Iterator SHash::Begin() const { LIMITED_METHOD_CONTRACT; Iterator i(this, TRUE); i.First(); return i; } template typename SHash::Iterator SHash::End() const { LIMITED_METHOD_CONTRACT; return Iterator(this, FALSE); } template typename SHash::KeyIterator SHash::Begin(key_t key) const { LIMITED_METHOD_CONTRACT; KeyIterator k(this, TRUE); k.SetKey(key); return k; } template typename SHash::KeyIterator SHash::End(key_t key) const { LIMITED_METHOD_CONTRACT; return KeyIterator(this, FALSE); } template BOOL SHash::CheckGrowth() { CONTRACT(BOOL) { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; } CONTRACT_END; if (m_tableOccupied == m_tableMax) { Grow(); RETURN TRUE; } RETURN FALSE; } template BOOL SHash::CheckGrowthNoThrow() { CONTRACT(BOOL) { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; } CONTRACT_END; static_assert(TRAITS::s_NoThrow, "This SHash does not support NOTHROW."); BOOL result = TRUE; if (m_tableOccupied == m_tableMax) { result = GrowNoThrow(); } RETURN result; } template void SHash::Grow() { CONTRACT_VOID { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; } CONTRACT_END; count_t newSize; element_t * newTable = Grow_OnlyAllocateNewTable(&newSize); element_t * oldTable = ReplaceTable(newTable, newSize); DeleteOldTable(oldTable); RETURN; } template BOOL SHash::GrowNoThrow() { CONTRACT(BOOL) { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(TRAITS::s_NoThrow); } CONTRACT_END; count_t newSize; element_t * newTable = Grow_OnlyAllocateNewTableNoThrow(&newSize); if (newTable) { element_t * oldTable = ReplaceTable(newTable, newSize); DeleteOldTable(oldTable); } RETURN (newTable != NULL); } template typename SHash::element_t * SHash::Grow_OnlyAllocateNewTable(count_t * pcNewSize) { CONTRACT(element_t *) { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; } CONTRACT_END; count_t newSize = (count_t) (m_tableCount * TRAITS::s_growth_factor_numerator / TRAITS::s_growth_factor_denominator * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator); if (newSize < TRAITS::s_minimum_allocation) newSize = TRAITS::s_minimum_allocation; // handle potential overflow if (newSize < m_tableCount) ThrowOutOfMemory(); RETURN AllocateNewTable(newSize, pcNewSize); } template typename SHash::element_t * SHash::Grow_OnlyAllocateNewTableNoThrow(count_t * pcNewSize) { CONTRACT(element_t *) { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(TRAITS::s_NoThrow); } CONTRACT_END; count_t newSize = (count_t) (m_tableCount * TRAITS::s_growth_factor_numerator / TRAITS::s_growth_factor_denominator * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator); if (newSize < TRAITS::s_minimum_allocation) newSize = TRAITS::s_minimum_allocation; // handle potential overflow if (newSize < m_tableCount) return NULL; RETURN AllocateNewTableNoThrow(newSize, pcNewSize); } template void SHash::Reallocate(count_t requestedSize) { CONTRACT_VOID { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; } CONTRACT_END; count_t newTableSize; element_t * newTable = AllocateNewTable(requestedSize, &newTableSize); element_t * oldTable = ReplaceTable(newTable, newTableSize); DeleteOldTable(oldTable); RETURN; } template template void SHash::ForEach(Functor &functor) { WRAPPER_NO_CONTRACT; // LIMITED_METHOD_CONTRACT + Functor for (count_t i = 0; i < m_tableSize; i++) { element_t element = m_table[i]; if (TRAITS::IsNull(element) || TRAITS::IsDeleted(element)) { continue; } if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(element)) { RemoveElement(m_table, m_tableSize, &m_table[i]); continue; } functor(element); } } template typename SHash::element_t * SHash::AllocateNewTable(count_t requestedSize, count_t * pcNewTableSize) { CONTRACT(element_t *) { THROWS; GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(requestedSize >= (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); } CONTRACT_END; // Allocation size must be a prime number. This is necessary so that hashes uniformly // distribute to all indices, and so that chaining will visit all indices in the hash table. *pcNewTableSize = NextPrime(requestedSize); element_t * newTable = new element_t [*pcNewTableSize]; element_t * p = newTable; element_t * pEnd = newTable + *pcNewTableSize; while (p < pEnd) { *p = TRAITS::Null(); p++; } RETURN newTable; } template typename SHash::element_t * SHash::AllocateNewTableNoThrow(count_t requestedSize, count_t * pcNewTableSize) { CONTRACT(element_t *) { NOTHROW; GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(requestedSize >= (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); PRECONDITION(TRAITS::s_NoThrow); } CONTRACT_END; // Allocation size must be a prime number. This is necessary so that hashes uniformly // distribute to all indices, and so that chaining will visit all indices in the hash table. *pcNewTableSize = NextPrime(requestedSize); element_t * newTable = new (nothrow) element_t [*pcNewTableSize]; if (newTable) { element_t * p = newTable; element_t * pEnd = newTable + *pcNewTableSize; while (p < pEnd) { *p = TRAITS::Null(); p++; } } RETURN newTable; } template typename SHash::element_t * SHash::ReplaceTable(element_t * newTable, count_t newTableSize) { CONTRACT(element_t *) { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(newTableSize >= (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator)); } CONTRACT_END; element_t * oldTable = m_table; // Move all entries over to new table. for (Iterator i = Begin(), end = End(); i != end; i++) { const element_t & cur = (*i); _ASSERTE(!TRAITS::IsNull(cur)); _ASSERTE(!TRAITS::IsDeleted(cur)); Add(newTable, newTableSize, cur); } m_table = PTR_element_t(newTable); m_tableSize = newTableSize; m_tableMax = (count_t) (newTableSize * TRAITS::s_density_factor_numerator / TRAITS::s_density_factor_denominator); m_tableOccupied = m_tableCount; RETURN oldTable; } template void SHash::DeleteOldTable(element_t * oldTable) { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; } CONTRACT_END; // @todo: // We might want to try to delay this cleanup to allow asynchronous readers if (oldTable != NULL) delete [] oldTable; RETURN; } template const typename SHash::element_t * SHash::Lookup(PTR_element_t table, count_t tableSize, key_t key) const { CONTRACT(const element_t *) { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; POSTCONDITION(RETVAL == NULL || TRAITS::Equals(key, TRAITS::GetKey(*RETVAL))); SUPPORTS_DAC_WRAPPER; // supports DAC only if the traits class does } CONTRACT_END; if (tableSize == 0) RETURN NULL; count_t hash = TRAITS::Hash(key); count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t& current = table[index]; if (TRAITS::IsNull(current)) RETURN NULL; if (!TRAITS::IsDeleted(current)) { if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(current)) { const_cast *>(this)->RemoveElement(table, tableSize, ¤t); } else if (TRAITS::Equals(key, TRAITS::GetKey(current))) { RETURN ¤t; } } if (increment == 0) increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) index -= tableSize; } } template BOOL SHash::Add(element_t * table, count_t tableSize, const element_t & element) { CONTRACT(BOOL) { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*Lookup(table, tableSize, TRAITS::GetKey(element))))); } CONTRACT_END; key_t key = TRAITS::GetKey(element); count_t hash = TRAITS::Hash(key); count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t & current = table[index]; if (TRAITS::IsNull(current)) { table[index] = element; RETURN TRUE; } if (TRAITS::IsDeleted(current)) { table[index] = element; RETURN FALSE; } if (TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(current)) { RemoveElement(table, tableSize, ¤t); table[index] = element; RETURN FALSE; } if (increment == 0) increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) index -= tableSize; } } template void SHash::AddOrReplace(element_t *table, count_t tableSize, const element_t &element) { CONTRACT_VOID { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; static_assert(!TRAITS::s_supports_remove, "SHash::AddOrReplace is not implemented for SHash with support for remove operations."); POSTCONDITION(TRAITS::Equals(TRAITS::GetKey(element), TRAITS::GetKey(*Lookup(table, tableSize, TRAITS::GetKey(element))))); } CONTRACT_END; key_t key = TRAITS::GetKey(element); count_t hash = TRAITS::Hash(key); count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t& current = table[index]; _ASSERTE(!TRAITS::IsDeleted(current)); if (TRAITS::IsNull(current)) { table[index] = element; m_tableCount++; m_tableOccupied++; RETURN; } else if (TRAITS::Equals(key, TRAITS::GetKey(current))) { if (TRAITS::s_RemovePerEntryCleanupAction) { TRAITS::OnRemovePerEntryCleanupAction(current); } table[index] = element; RETURN; } if (increment == 0) increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) index -= tableSize; } } template void SHash::Remove(element_t *table, count_t tableSize, key_t key) { CONTRACT_VOID { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; static_assert(TRAITS::s_supports_remove, "This SHash does not support remove operations."); PRECONDITION(Lookup(table, tableSize, key) != NULL); } CONTRACT_END; count_t hash = TRAITS::Hash(key); count_t index = hash % tableSize; count_t increment = 0; // delay computation while (TRUE) { element_t& current = table[index]; if (TRAITS::IsNull(current)) RETURN; if (!TRAITS::IsDeleted(current)) { if ((TRAITS::s_supports_autoremove && TRAITS::ShouldDelete(current)) || TRAITS::Equals(key, TRAITS::GetKey(current))) { RemoveElement(table, tableSize, ¤t); } } if (increment == 0) increment = (hash % (tableSize-1)) + 1; index += increment; if (index >= tableSize) index -= tableSize; } } template void SHash::RemoveElement(element_t *table, count_t tableSize, element_t *element) { CONTRACT_VOID { NOTHROW; GC_NOTRIGGER; PRECONDITION(TRAITS::s_supports_remove); PRECONDITION(table <= element && element < table + tableSize); PRECONDITION(!TRAITS::IsNull(*element) && !TRAITS::IsDeleted(*element)); } CONTRACT_END; if (TRAITS::s_RemovePerEntryCleanupAction) { TRAITS::OnRemovePerEntryCleanupAction(*element); } *element = TRAITS::Deleted(); m_tableCount--; RETURN; } template BOOL SHash::IsPrime(COUNT_T number) { CONTRACT(BOOL) { NOTHROW; GC_NOTRIGGER; } CONTRACT_END; // This is a very low-tech check for primality, which doesn't scale very well. // There are more efficient tests if this proves to be burdensome for larger // tables. if ((number & 1) == 0) RETURN FALSE; COUNT_T factor = 3; while (factor * factor <= number) { if ((number % factor) == 0) RETURN FALSE; factor += 2; } RETURN TRUE; } // allow coexistence with simplerhash.inl #ifndef _HASH_PRIMES_DEFINED #define _HASH_PRIMES_DEFINED namespace { const COUNT_T g_shash_primes[] = { 11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919, 1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591, 17519,21023,25229,30293,36353,43627,52361,62851,75431,90523, 108631, 130363, 156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 }; } #endif //_HASH_PRIMES_DEFINED template COUNT_T SHash::NextPrime(COUNT_T number) { CONTRACT(COUNT_T) { NOTHROW; GC_NOTRIGGER; POSTCONDITION(IsPrime(RETVAL)); } CONTRACT_END; for (int i = 0; i < (int) (sizeof(g_shash_primes) / sizeof(g_shash_primes[0])); i++) { if (g_shash_primes[i] >= number) RETURN g_shash_primes[i]; } if ((number&1) == 0) number++; while (number != 1) { if (IsPrime(number)) RETURN number; number +=2; } // overflow ThrowOutOfMemory(); } template BOOL MapSHash::Lookup(KEY key, VALUE* pValue) const { CONTRACTL { NOTHROW_UNLESS_TRAITS_THROWS; GC_NOTRIGGER; PRECONDITION(key != (KEY)0); } CONTRACTL_END; const KeyValuePair *pRet = PARENT::LookupPtr(key); if (pRet == NULL) return FALSE; *pValue = pRet->Value(); return TRUE; } #endif // _SHASH_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/shimload.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*============================================================ ** ** Header: ShimLoad.hpp ** ** Purpose: Delay load hook used to images to bind to ** dll's shim shipped with the EE ** ** ===========================================================*/ #ifndef _SHIMLOAD_H #define _SHIMLOAD_H //***************************************************************************** // Sets/Gets the directory based on the location of the module. This routine // is called at COR setup time. Set is called during EEStartup and by the // MetaData dispenser. //***************************************************************************** HRESULT SetInternalSystemDirectory(); HRESULT GetInternalSystemDirectory(_Out_writes_opt_(*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength); #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sigbuilder.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _SIGBUILDER_H_ #define _SIGBUILDER_H_ #include "contract.h" // // Simple signature builder // class SigBuilder { PBYTE m_pBuffer; DWORD m_dwLength; DWORD m_dwAllocation; // Preallocate space for small signatures BYTE m_prealloc[64]; // Grow the buffer to get at least cbMin of free space void Grow(SIZE_T cbMin); // Ensure that the buffer has at least cbMin of free space FORCEINLINE void Ensure(SIZE_T cb) { if (m_dwAllocation - m_dwLength < cb) Grow(cb); } public: SigBuilder() : m_pBuffer(m_prealloc), m_dwLength(0), m_dwAllocation(sizeof(m_prealloc)) { LIMITED_METHOD_CONTRACT; } ~SigBuilder(); SigBuilder(DWORD cbPreallocationSize); PVOID GetSignature(DWORD * pdwLength) { LIMITED_METHOD_CONTRACT; *pdwLength = m_dwLength; return m_pBuffer; } DWORD GetSignatureLength() { LIMITED_METHOD_CONTRACT; return m_dwLength; } void AppendByte(BYTE b); void AppendData(ULONG data); void AppendElementType(CorElementType etype) { WRAPPER_NO_CONTRACT; AppendByte(static_cast(etype)); } void AppendToken(mdToken tk); void AppendPointer(void * ptr) { WRAPPER_NO_CONTRACT; AppendBlob(&ptr, sizeof(ptr)); } void AppendBlob(const PVOID pBlob, SIZE_T cbBlob); }; #endif // _SIGBUILDER_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sigparser.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // sigparser.h // // #ifndef _H_SIGPARSER #define _H_SIGPARSER #include "utilcode.h" #include "corhdr.h" #include "corinfo.h" #include "corpriv.h" #include //--------------------------------------------------------------------------------------- // These macros define how arguments are mapped to the stack in the managed calling convention. // We assume to be walking a method's signature left-to-right, in the virtual calling convention. // See MethodDesc::Call for details on this virtual calling convention. // These macros tell us whether the arguments we see as we proceed with the signature walk are mapped // to increasing or decreasing stack addresses. This is valid only for arguments that go on the stack. //--------------------------------------------------------------------------------------- #if defined(TARGET_X86) #define STACK_GROWS_DOWN_ON_ARGS_WALK #else #define STACK_GROWS_UP_ON_ARGS_WALK #endif //------------------------------------------------------------------------ // Encapsulates how compressed integers and typeref tokens are encoded into // a bytestream. // // As you use this class please understand the implicit normalizations // on the CorElementType's returned by the various methods, especially // for variable types (e.g. !0 in generic signatures), string types // (i.e. E_T_STRING), object types (E_T_OBJECT), constructed types // (e.g. List) and enums. //------------------------------------------------------------------------ class SigParser { protected: // This type is performance critical - do not add fields to it. // (If you must, check for managed types that may use a SigParser or SigPointer inline, like ArgIterator.) PCCOR_SIGNATURE m_ptr; uint32_t m_dwLen; //------------------------------------------------------------------------ // Skips specified number of bytes WITHOUT VALIDATION. Only to be used // when it is known that it won't overflow the signature buffer. //------------------------------------------------------------------------ FORCEINLINE void SkipBytes(uint32_t cb) { SUPPORTS_DAC; _ASSERT(cb <= m_dwLen); m_ptr += cb; m_dwLen -= cb; } public: //------------------------------------------------------------------------ // Constructor. //------------------------------------------------------------------------ SigParser() { LIMITED_METHOD_DAC_CONTRACT; m_ptr = NULL; m_dwLen = 0; } SigParser(const SigParser &sig); //------------------------------------------------------------------------ // Initialize //------------------------------------------------------------------------ FORCEINLINE SigParser(PCCOR_SIGNATURE ptr) { LIMITED_METHOD_CONTRACT; m_ptr = ptr; // We don't know the size of the signature, so we'll say it's "big enough" m_dwLen = 0xffffffff; } FORCEINLINE SigParser(PCCOR_SIGNATURE ptr, uint32_t len) { LIMITED_METHOD_CONTRACT; m_ptr = ptr; m_dwLen = len; } inline void SetSig(PCCOR_SIGNATURE ptr) { LIMITED_METHOD_CONTRACT; m_ptr = ptr; // We don't know the size of the signature, so we'll say it's "big enough" m_dwLen = 0xffffffff; } inline void SetSig(PCCOR_SIGNATURE ptr, uint32_t len) { LIMITED_METHOD_CONTRACT; m_ptr = ptr; m_dwLen = len; } inline BOOL IsNull() const { LIMITED_METHOD_CONTRACT; return (m_ptr == NULL); } // Returns represented signature as pointer and size. void GetSignature( PCCOR_SIGNATURE * pSig, uint32_t * pcbSigSize) { *pSig = m_ptr; *pcbSigSize = m_dwLen; } //========================================================================= // The RAW interface for reading signatures. You see exactly the signature, // apart from custom modifiers which for historical reasons tend to get eaten. // // DO NOT USE THESE METHODS UNLESS YOU'RE TOTALLY SURE YOU WANT // THE RAW signature. You nearly always want GetElemTypeClosed() or // PeekElemTypeClosed() or one of the MetaSig functions. See the notes above. // These functions will return E_T_INTERNAL, E_T_VAR, E_T_MVAR and such // so the caller must be able to deal with those //========================================================================= //------------------------------------------------------------------------ // Remove one compressed integer (using CorSigUncompressData) from // the head of the stream and return it. //------------------------------------------------------------------------ __checkReturn FORCEINLINE HRESULT GetData(uint32_t* data) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; uint32_t sizeOfData = 0; uint32_t tempData; if (data == NULL) data = &tempData; HRESULT hr = CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); if (SUCCEEDED(hr)) { SkipBytes(sizeOfData); } return hr; } //------------------------------------------------------------------------- // Remove one byte and return it. //------------------------------------------------------------------------- __checkReturn FORCEINLINE HRESULT GetByte(BYTE *data) { LIMITED_METHOD_CONTRACT; if (m_dwLen > 0) { if (data != NULL) *data = *m_ptr; SkipBytes(1); return S_OK; } if (data != NULL) *data = 0; return META_E_BAD_SIGNATURE; } //------------------------------------------------------------------------- // Peek at value of one byte and return it. //------------------------------------------------------------------------- __checkReturn FORCEINLINE HRESULT PeekByte(BYTE *data) { LIMITED_METHOD_CONTRACT; if (m_dwLen > 0) { if (data != NULL) *data = *m_ptr; return S_OK; } if (data != NULL) *data = 0; return META_E_BAD_SIGNATURE; } //------------------------------------------------------------------------- // The element type as defined in CorElementType. No normalization for // generics (E_T_VAR, E_T_MVAR,..) or dynamic methods (E_T_INTERNAL occurs) //------------------------------------------------------------------------- __checkReturn HRESULT GetElemTypeSlow(CorElementType * etype) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; CorElementType tmpEType; if (etype == NULL) etype = &tmpEType; SigParser sigTemp(*this); HRESULT hr = sigTemp.SkipCustomModifiers(); if (SUCCEEDED(hr)) { BYTE bElemType = 0; hr = sigTemp.GetByte(&bElemType); *etype = (CorElementType)bElemType; if (SUCCEEDED(hr)) { *this = sigTemp; return S_OK; } } *etype = ELEMENT_TYPE_END; return META_E_BAD_SIGNATURE; } // Inlined version __checkReturn FORCEINLINE HRESULT GetElemType(CorElementType * etype) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (m_dwLen > 0) { CorElementType typ = (CorElementType) * m_ptr; if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte { if (etype != NULL) { * etype = typ; } SkipBytes(1); return S_OK; } } // Slower/normal path return GetElemTypeSlow(etype); } // Note: Calling convention is always one byte, not four bytes __checkReturn HRESULT GetCallingConvInfo(uint32_t * data) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; uint32_t tmpData; if (data == NULL) data = &tmpData; HRESULT hr = CorSigUncompressCallingConv(m_ptr, m_dwLen, data); if (SUCCEEDED(hr)) { SkipBytes(1); } return hr; } __checkReturn HRESULT GetCallingConv(uint32_t* data) // @REVISIT_TODO: Calling convention is one byte, not four. { WRAPPER_NO_CONTRACT; uint32_t info; HRESULT hr = GetCallingConvInfo(&info); if (SUCCEEDED(hr) && data != NULL) { *data = IMAGE_CEE_CS_CALLCONV_MASK & info; } return hr; } //------------------------------------------------------------------------ // Non-destructive read of compressed integer. //------------------------------------------------------------------------ __checkReturn HRESULT PeekData(uint32_t *data) const { WRAPPER_NO_CONTRACT; _ASSERTE(data != NULL); uint32_t sizeOfData = 0; return CorSigUncompressData(m_ptr, m_dwLen, data, &sizeOfData); } //------------------------------------------------------------------------ // Non-destructive read of element type. // // This routine makes it look as if the String type is encoded // via ELEMENT_TYPE_CLASS followed by a token for the String class, // rather than the ELEMENT_TYPE_STRING. This is partially to avoid // rewriting client code which depended on this behavior previously. // But it also seems like the right thing to do generally. // No normalization for generics (E_T_VAR, E_T_MVAR,..) or // dynamic methods (E_T_INTERNAL occurs) //------------------------------------------------------------------------ __checkReturn HRESULT PeekElemTypeSlow(CorElementType *etype) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; _ASSERTE(etype != NULL); SigParser sigTemp(*this); HRESULT hr = sigTemp.GetElemType(etype); if (SUCCEEDED(hr) && (*etype == ELEMENT_TYPE_STRING || *etype == ELEMENT_TYPE_OBJECT)) *etype = ELEMENT_TYPE_CLASS; return hr; } // inline version __checkReturn FORCEINLINE HRESULT PeekElemType(CorElementType *etype) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; _ASSERTE(etype != NULL); if (m_dwLen > 0) { CorElementType typ = (CorElementType) * m_ptr; if (typ < ELEMENT_TYPE_CMOD_REQD) // fast path with no modifiers: single byte { if ((typ == ELEMENT_TYPE_STRING) || (typ == ELEMENT_TYPE_OBJECT)) { *etype = ELEMENT_TYPE_CLASS; } else { *etype = typ; } return S_OK; } } return PeekElemTypeSlow(etype); } //------------------------------------------------------------------------- // Returns the raw size of the type next in the signature, or returns // E_INVALIDARG for base types that have variables sizes. //------------------------------------------------------------------------- __checkReturn HRESULT PeekElemTypeSize(uint32_t *pSize) { WRAPPER_NO_CONTRACT; HRESULT hr = S_OK; uint32_t dwSize = 0; if (pSize == NULL) { pSize = &dwSize; } SigParser sigTemp(*this); hr = sigTemp.SkipAnyVASentinel(); if (FAILED(hr)) { return hr; } *pSize = 0; BYTE bElementType = 0; hr = sigTemp.GetByte(&bElementType); if (FAILED(hr)) { return hr; } switch (bElementType) { case ELEMENT_TYPE_I8: case ELEMENT_TYPE_U8: case ELEMENT_TYPE_R8: #ifdef HOST_64BIT case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: #endif // WIN64 *pSize = 8; break; case ELEMENT_TYPE_I4: case ELEMENT_TYPE_U4: case ELEMENT_TYPE_R4: #ifndef HOST_64BIT case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: #endif // HOST_64BIT *pSize = 4; break; case ELEMENT_TYPE_I2: case ELEMENT_TYPE_U2: case ELEMENT_TYPE_CHAR: *pSize = 2; break; case ELEMENT_TYPE_I1: case ELEMENT_TYPE_U1: case ELEMENT_TYPE_BOOLEAN: *pSize = 1; break; case ELEMENT_TYPE_STRING: case ELEMENT_TYPE_PTR: case ELEMENT_TYPE_BYREF: case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_OBJECT: case ELEMENT_TYPE_FNPTR: case ELEMENT_TYPE_TYPEDBYREF: case ELEMENT_TYPE_ARRAY: case ELEMENT_TYPE_SZARRAY: *pSize = sizeof(void *); break; case ELEMENT_TYPE_VOID: break; case ELEMENT_TYPE_END: case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); return E_INVALIDARG; case ELEMENT_TYPE_VALUETYPE: _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); return E_INVALIDARG; default: _ASSERTE( !"CorSigGetElementTypeSize given invalid signature to size!" ); return META_E_BAD_SIGNATURE; } return hr; } //------------------------------------------------------------------------ // Is this at the Sentinel (the ... in a varargs signature) that marks // the beginning of varguments that are not decared at the target bool AtSentinel() const { if (m_dwLen > 0) return *m_ptr == ELEMENT_TYPE_SENTINEL; else return false; } //------------------------------------------------------------------------ // Removes a compressed metadata token and returns it. // WARNING: dynamic methods do not have tokens so this api is completely // broken in that case. Make sure you call this function if // you are absolutely sure E_T_INTERNAL was not in the sig //------------------------------------------------------------------------ __checkReturn FORCEINLINE HRESULT GetToken(mdToken * token) { WRAPPER_NO_CONTRACT; uint32_t dwLen; mdToken tempToken; if (token == NULL) token = &tempToken; HRESULT hr = CorSigUncompressToken(m_ptr, m_dwLen, token, &dwLen); if (SUCCEEDED(hr)) { SkipBytes(dwLen); } return hr; } //------------------------------------------------------------------------ // Removes a pointer value and returns it. Used for ELEMENT_TYPE_INTERNAL. __checkReturn FORCEINLINE HRESULT GetPointer(void ** pPtr) { WRAPPER_NO_CONTRACT; if (m_dwLen < sizeof(void *)) { // Not enough data to read a pointer if (pPtr != NULL) { *pPtr = NULL; } return META_E_BAD_SIGNATURE; } if (pPtr != NULL) { *pPtr = *(void * UNALIGNED *)m_ptr; } SkipBytes(sizeof(void *)); return S_OK; } //------------------------------------------------------------------------ // Tests if two SigParsers point to the same location in the stream. //------------------------------------------------------------------------ FORCEINLINE BOOL Equals(SigParser sp) const { LIMITED_METHOD_CONTRACT; return m_ptr == sp.m_ptr; } __checkReturn HRESULT SkipCustomModifiers() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; HRESULT hr = S_OK; SigParser sigTemp(*this); hr = sigTemp.SkipAnyVASentinel(); if (FAILED(hr)) { return hr; } BYTE bElementType = 0; hr = sigTemp.PeekByte(&bElementType); if (FAILED(hr)) return hr; while ((ELEMENT_TYPE_CMOD_REQD == bElementType) || (ELEMENT_TYPE_CMOD_OPT == bElementType)) { sigTemp.SkipBytes(1); mdToken token; hr = sigTemp.GetToken(&token); if (FAILED(hr)) return hr; hr = sigTemp.PeekByte(&bElementType); if (FAILED(hr)) return hr; } // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types // that we support while parsing various signatures if (bElementType >= ELEMENT_TYPE_MAX) { switch (bElementType) { case ELEMENT_TYPE_VAR_ZAPSIG: case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: case ELEMENT_TYPE_CANON_ZAPSIG: case ELEMENT_TYPE_MODULE_ZAPSIG: case ELEMENT_TYPE_PINNED: break; default: return META_E_BAD_SIGNATURE; } } *this = sigTemp; return hr; }// SkipCustomModifiers __checkReturn HRESULT SkipFunkyAndCustomModifiers() { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; SigParser sigTemp(*this); HRESULT hr = S_OK; hr = sigTemp.SkipAnyVASentinel(); if (FAILED(hr)) { return hr; } BYTE bElementType = 0; hr = sigTemp.PeekByte(&bElementType); if (FAILED(hr)) return hr; while (ELEMENT_TYPE_CMOD_REQD == bElementType || ELEMENT_TYPE_CMOD_OPT == bElementType || ELEMENT_TYPE_MODIFIER == bElementType || ELEMENT_TYPE_PINNED == bElementType) { sigTemp.SkipBytes(1); mdToken token; hr = sigTemp.GetToken(&token); if (FAILED(hr)) return hr; hr = sigTemp.PeekByte(&bElementType); if (FAILED(hr)) return hr; } // Following custom modifiers must be an element type value which is less than ELEMENT_TYPE_MAX, or one of the other element types // that we support while parsing various signatures if (bElementType >= ELEMENT_TYPE_MAX) { switch (bElementType) { case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: case ELEMENT_TYPE_CANON_ZAPSIG: case ELEMENT_TYPE_MODULE_ZAPSIG: case ELEMENT_TYPE_PINNED: break; default: return META_E_BAD_SIGNATURE; } } *this = sigTemp; return hr; }// SkipFunkyAndCustomModifiers __checkReturn HRESULT SkipAnyVASentinel() { WRAPPER_NO_CONTRACT; HRESULT hr = S_OK; BYTE bElementType = 0; hr = PeekByte(&bElementType); if (FAILED(hr)) return hr; if (bElementType == ELEMENT_TYPE_SENTINEL) { SkipBytes(1); } return hr; }// SkipAnyVASentinel //------------------------------------------------------------------------ // Assumes that the SigParser points to the start of an element type // (i.e. function parameter, function return type or field type.) // Advances the pointer to the first data after the element type. //------------------------------------------------------------------------ __checkReturn HRESULT SkipExactlyOne(); //------------------------------------------------------------------------ // Skip only the method header of the signature, not the signature of // the arguments. //------------------------------------------------------------------------ __checkReturn HRESULT SkipMethodHeaderSignature(uint32_t *pcArgs); //------------------------------------------------------------------------ // Skip a sub signature (as immediately follows an ELEMENT_TYPE_FNPTR). //------------------------------------------------------------------------ __checkReturn HRESULT SkipSignature(); public: //------------------------------------------------------------------------ // Return pointer // PLEASE DON'T USE THIS. // // Return the internal pointer. It's hard to resist, but please try // not to use this. Certainly don't use it if there's any chance of the // signature containing generic type variables. // // It's currently only used for working on the // signatures stored in TypeSpec tokens (we should add a new abstraction, // i.e. on MetaSig for this) and a couple of places to do with COM // and native interop signature parsing. // We should try to get rid of these uses as well. //------------------------------------------------------------------------ PCCOR_SIGNATURE GetPtr() const { LIMITED_METHOD_DAC_CONTRACT; return m_ptr; } }; // class SigParser //------------------------------------------------------------------------ FORCEINLINE SigParser::SigParser( const SigParser &sig) : m_ptr(sig.m_ptr), m_dwLen(sig.m_dwLen) { LIMITED_METHOD_DAC_CONTRACT; } /*****************************************************************/ /* CorTypeInfo is a single global table that you can hang information about ELEMENT_TYPE_* */ class CorTypeInfo { protected: struct CorTypeInfoEntry { LPCUTF8 nameSpace; LPCUTF8 className; CorElementType type : 8; unsigned size : 8; CorInfoGCType gcType : 3; unsigned isArray : 1; unsigned isPrim : 1; unsigned isFloat : 1; unsigned isModifier : 1; unsigned isGenVar : 1; // 1 more byte here to use for 32-bit }; protected: FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo(CorElementType type) { CONTRACTL { THROWS; GC_NOTRIGGER; SUPPORTS_DAC; #ifdef MODE_ANY MODE_ANY; #endif } CONTRACTL_END; if (type >= (CorElementType)ARRAY_SIZE(info)) { ThrowHR(COR_E_BADIMAGEFORMAT); } return info[type]; } FORCEINLINE static const CorTypeInfoEntry &GetTypeInfo_NoThrow(CorElementType type) { LIMITED_METHOD_DAC_CONTRACT; if (type >= (CorElementType)ARRAY_SIZE(info)) { return info[ELEMENT_TYPE_END]; } return info[type]; } public: FORCEINLINE static LPCUTF8 GetName(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).className; } FORCEINLINE static LPCUTF8 GetNamespace(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).nameSpace; } static void CheckConsistency() { LIMITED_METHOD_CONTRACT; for (int i = 0; i < (int)ARRAY_SIZE(info); i++) { _ASSERTE(info[i].type == i); } } FORCEINLINE static CorInfoGCType GetGCType(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).gcType; } FORCEINLINE static CorInfoGCType GetGCType_NoThrow(CorElementType type) { LIMITED_METHOD_DAC_CONTRACT; return GetTypeInfo_NoThrow(type).gcType; } static BOOL IsObjRef(CorElementType type) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return (GetGCType(type) == TYPE_GC_REF); } static BOOL IsObjRef_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return (GetGCType_NoThrow(type) == TYPE_GC_REF); } static BOOL IsByRef(CorElementType type) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return (GetGCType(type) == TYPE_GC_BYREF); } static BOOL IsByRef_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return (GetGCType_NoThrow(type) == TYPE_GC_BYREF); } FORCEINLINE static BOOL IsGenericVariable(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).isGenVar; } FORCEINLINE static BOOL IsGenericVariable_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo_NoThrow(type).isGenVar; } FORCEINLINE static BOOL IsArray(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).isArray; } FORCEINLINE static BOOL IsArray_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo_NoThrow(type).isArray; } FORCEINLINE static BOOL IsFloat(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).isFloat; } FORCEINLINE static BOOL IsFloat_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo_NoThrow(type).isFloat; } FORCEINLINE static BOOL IsModifier(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).isModifier; } FORCEINLINE static BOOL IsModifier_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo_NoThrow(type).isModifier; } FORCEINLINE static BOOL IsPrimitiveType(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).isPrim; } FORCEINLINE static BOOL IsPrimitiveType_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo_NoThrow(type).isPrim; } FORCEINLINE static unsigned Size(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo(type).size; } FORCEINLINE static unsigned Size_NoThrow(CorElementType type) { WRAPPER_NO_CONTRACT; return GetTypeInfo_NoThrow(type).size; } static CorElementType FindPrimitiveType(LPCUTF8 name); protected: static const CorTypeInfoEntry info[ELEMENT_TYPE_MAX]; }; // class CorTypeInfo // Returns the address of the payload inside the stackelem inline void* StackElemEndiannessFixup(void* pStackElem, UINT cbSize) { LIMITED_METHOD_CONTRACT; BYTE *pRetVal = (BYTE*)pStackElem; #if BIGENDIAN switch (cbSize) { case 1: pRetVal += sizeof(void*)-1; break; case 2: pRetVal += sizeof(void*)-2; break; #ifdef HOST_64BIT case 4: pRetVal += sizeof(void*)-4; break; #endif default: // nothing to do break; } #endif return pRetVal; } #endif /* _H_SIGINFOBASE */ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/simplerhash.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _SIMPLERHASHTABLE_H_ #define _SIMPLERHASHTABLE_H_ #include "iallocator.h" // SimplerHashTable implements a mapping from a Key type to a Value type, // via a hash table. // Synchronization is the responsibility of the caller: if a // SimplerHash is used in a multithreaded context, the table should be // associated with a lock. // SimplerHashTable actually takes four template arguments: Key, // KeyFuncs, Value, and Behavior. We don't assume that Key has hash or equality // functions specific names; rather, we assume that KeyFuncs has // statics methods // int GetHashCode(Key) // and // bool Equals(Key, Key) // and use those. An // instantiator can thus make a small "adaptor class" to invoke // existing instance method hash and/or equality functions. If the // implementor of a candidate Key class K understands this convention, // these static methods can be implemented by K, so that K can be used // as the actual arguments for the both Key and KeyTrait classes. // // The "Behavior" argument provides the following static members: // // s_growth_factor_numerator // s_growth_factor_denominator Factor to grow allocation (numerator/denominator). // Typically inherited from default traits (3/2) // // s_density_factor_numerator // s_density_factor_denominator Maximum occupied density of table before growth // occurs (num/denom). Typically inherited (3/4). // // s_minimum_allocation Minimum table allocation count (size on first growth.) It is // probably preferable to call Reallocate on initialization rather // than override his from the default traits. (7) // // NoMemory() Called when the hash table is unable to grow due to potential // overflow or the lack of a sufficiently large prime. void DECLSPEC_NORETURN ThrowOutOfMemory(); class DefaultSimplerHashBehavior { public: static const unsigned s_growth_factor_numerator = 3; static const unsigned s_growth_factor_denominator = 2; static const unsigned s_density_factor_numerator = 3; static const unsigned s_density_factor_denominator = 4; static const unsigned s_minimum_allocation = 7; inline static void DECLSPEC_NORETURN NoMemory() { ::ThrowOutOfMemory(); } }; // Stores info about primes, including the magic number and shift amount needed // to implement a divide without using the divide instruction class PrimeInfo { public: constexpr PrimeInfo() : prime(0), magic(0), shift(0) {} constexpr PrimeInfo(unsigned p, unsigned m, unsigned s) : prime(p), magic(m), shift(s) {} unsigned prime; unsigned magic; unsigned shift; }; // Hash table class definition template class SimplerHashTable { public: // Forward declaration. class KeyIterator; // Constructor/destructor. SHash tables always start out empty, with no // allocation overhead. Call Reallocate to prime with an initial size if // desired. Pass NULL as the IAllocator* if you want to use DefaultAllocator // (basically, operator new/delete). SimplerHashTable(IAllocator* alloc); ~SimplerHashTable(); // operators new/delete when an IAllocator is to be used. void * operator new(size_t sz, IAllocator * alloc); void * operator new[](size_t sz, IAllocator * alloc); void operator delete(void * p, IAllocator * alloc); void operator delete[](void * p, IAllocator * alloc); // If the table contains a mapping for "key", returns "true" and // sets "*pVal" to the value to which "key" maps. Otherwise, // returns false, and does not modify "*pVal". bool Lookup(Key k, Value* pVal = NULL) const; Value *LookupPointer(Key k) const; // Causes the table to map "key" to "val". Returns "true" if // "key" had already been mapped by the table, "false" otherwise. bool Set(Key k, Value val); // Ensures that "key" is not mapped to a value by the "table." // Returns "true" iff it had been mapped. bool Remove(Key k); // Remove all mappings in the table. void RemoveAll(); // Begin and End pointers for iteration over entire table. KeyIterator Begin() const; KeyIterator End() const; // Return the number of elements currently stored in the table unsigned GetCount() const; private: // Forward declaration of the linked-list node class. struct Node; unsigned GetIndexForKey(Key k) const; // If the table has a mapping for "k", return the node containing // that mapping, else "NULL". Node* FindNode(Key k) const; // Resizes a hash table for growth. The new size is computed based // on the current population, growth factor, and maximum density factor. void Grow(); // See if it is OK to grow the hash table by one element. If not, reallocate // the hash table. void CheckGrowth(); public: // Reallocates a hash table to a specific size. The size must be big enough // to hold all elements in the table appropriately. // // Note that the actual table size must always be a prime number; the number // passed in will be upward adjusted if necessary. void Reallocate(unsigned newTableSize); // For iteration, we use a pattern similar to the STL "forward // iterator" pattern. It basically consists of wrapping an // "iteration variable" in an object, and providing pointer-like // operators on the iterator. Example usage: // // for (SimplerHashTable::KeyIterator iter = foo->Begin(), end = foo->End(); !iter.Equal(end); iter++) // { // // use foo, iter. // } // iter.Get() will yield (a reference to) the // current key. It will assert the equivalent of "iter != end." class KeyIterator { private: friend class SimplerHashTable; // The method implementations have to be here for portability. // Some compilers won't compile the separate implementation in shash.inl Node** m_table; Node* m_node; unsigned m_tableSize; unsigned m_index; public: KeyIterator(const SimplerHashTable *hash, BOOL begin) : m_table(hash->m_table), m_node(NULL), m_tableSize(hash->m_tableSizeInfo.prime), m_index(begin ? 0 : m_tableSize) { if (begin && hash->m_tableCount > 0) { assert(m_table != NULL); while (m_index < m_tableSize && m_table[m_index] == NULL) m_index++; if (m_index >= m_tableSize) { return; } else { m_node = m_table[m_index]; } assert(m_node != NULL); } } const Key& Get() const { assert(m_node != NULL); return m_node->m_key; } const Value& GetValue() const { assert(m_node != NULL); return m_node->m_val; } void SetValue(const Value & value) const { assert(m_node != NULL); m_node->m_val = value; } void Next() { if (m_node != NULL) { m_node = m_node->m_next; if (m_node != NULL) { return; } // Otherwise... m_index++; } while (m_index < m_tableSize && m_table[m_index] == NULL) m_index++; if (m_index >= m_tableSize) { m_node = NULL; return; } else { m_node = m_table[m_index]; } assert(m_node != NULL); } bool Equal(const KeyIterator &i) const { return i.m_node == m_node; } void operator++() { Next(); } void operator++(int) { Next(); } }; // HashTableRef only exists to support operator[] // operator[] returns a HashTableRef which enables operator[] to support reading and writing // in a normal array, it just returns a ref an actual element, which is not possible here. class HashTableRef { public: // this is really the getter for the array. operator Value() { Value result; table->Lookup(key, &result); return result; } void operator =(const Value v) { table->Set(key, v); } friend class SimplerHashTable; protected: HashTableRef(SimplerHashTable *t, Key k) { table = t; key = k; } SimplerHashTable *table; Key key; }; Value &operator[](Key k) const { Value* p = LookupPointer(k); assert(p); return *p; } private: // Find the next prime number >= the given value. static PrimeInfo NextPrime(unsigned number); // Instance members IAllocator* m_alloc; // IAllocator to use in this // table. // The node type. struct Node { Node* m_next; // Assume that the alignment requirement of Key and Value are no greater than Node*, so put m_next to avoid unnecessary padding. Key m_key; Value m_val; Node(Key k, Value v, Node* next) : m_next(next), m_key(k), m_val(v) {} void* operator new(size_t sz, IAllocator* alloc) { return alloc->Alloc(sz); } void operator delete(void* p, IAllocator* alloc) { alloc->Free(p); } }; Node** m_table; // pointer to table PrimeInfo m_tableSizeInfo; // size of table (a prime) and information about it unsigned m_tableCount; // number of elements in table unsigned m_tableMax; // maximum occupied count }; #include "simplerhash.inl" // A few simple KeyFuncs types... // Base class for types whose equality function is the same as their "==". template struct KeyFuncsDefEquals { static bool Equals(const T& x, const T& y) { return x == y; } }; template struct PtrKeyFuncs: public KeyFuncsDefEquals { public: static unsigned GetHashCode(const T* ptr) { // Hmm. Maybe (unsigned) ought to be "ssize_t" -- or this ought to be ifdef'd by size. return static_cast(reinterpret_cast(ptr)); } }; template // Must be coercable to "unsigned" with no loss of information. struct SmallPrimitiveKeyFuncs: public KeyFuncsDefEquals { static unsigned GetHashCode(const T& val) { return static_cast(val); } }; template // Assumed to be of size sizeof(UINT64). struct LargePrimitiveKeyFuncs: public KeyFuncsDefEquals { static unsigned GetHashCode(const T val) { // A static cast when T is a float or a double converts the value (i.e. 0.25 converts to 0) // // Instead we want to use all of the bits of a float to create the hash value // So we cast the address of val to a pointer to an equivalent sized unsigned int // This allows us to read the actual bit representation of a float type // // We can't read beyond the end of val, so we use sizeof(T) to determine // exactly how many bytes to read // if (sizeof(T) == 8) { // cast &val to (UINT64 *) then deref to get the bits UINT64 asUINT64 = *(reinterpret_cast(&val)); // Get the upper and lower 32-bit values from the 64-bit value UINT32 upper32 = static_cast (asUINT64 >> 32); UINT32 lower32 = static_cast (asUINT64 & 0xFFFFFFFF); // Exclusive-Or the upper32 and the lower32 values return static_cast(upper32 ^ lower32); } else if (sizeof(T) == 4) { // cast &val to (UINT32 *) then deref to get the bits UINT32 asUINT32 = *(reinterpret_cast(&val)); // Just return the 32-bit value return static_cast(asUINT32); } else if ((sizeof(T) == 2) || (sizeof(T) == 1)) { // For small sizes we must have an integer type // so we can just use the static_cast. // return static_cast(val); } else { // Only support Hashing for types that are 8,4,2 or 1 bytes in size assert(!"Unsupported size"); return static_cast(val); // compile-time error here when we have a illegal size } } }; #endif // _SIMPLERHASHTABLE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/simplerhash.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _SIMPLERHASHTABLE_INL_ #define _SIMPLERHASHTABLE_INL_ // To implement magic-number divide with a 32-bit magic number, // multiply by the magic number, take the top 64 bits, and shift that // by the amount given in the table. inline unsigned magicNumberDivide(unsigned numerator, const PrimeInfo &p) { unsigned __int64 num = numerator; unsigned __int64 mag = p.magic; unsigned __int64 product = (num * mag) >> (32 + p.shift); return (unsigned) product; } inline unsigned magicNumberRem(unsigned numerator, const PrimeInfo &p) { unsigned div = magicNumberDivide(numerator, p); unsigned result = numerator - (div * p.prime); assert(result == numerator % p.prime); return result; } template SimplerHashTable::SimplerHashTable(IAllocator* alloc) : m_alloc(alloc), m_table(NULL), m_tableSizeInfo(), m_tableCount(0), m_tableMax(0) { assert(m_alloc != nullptr); #ifndef __GNUC__ // these crash GCC static_assert_no_msg(Behavior::s_growth_factor_numerator > Behavior::s_growth_factor_denominator); static_assert_no_msg(Behavior::s_density_factor_numerator < Behavior::s_density_factor_denominator); #endif } template SimplerHashTable::~SimplerHashTable() { RemoveAll(); } template void * SimplerHashTable::operator new(size_t sz, IAllocator * alloc) { return alloc->Alloc(sz); } template void * SimplerHashTable::operator new[](size_t sz, IAllocator * alloc) { return alloc->Alloc(sz); } template void SimplerHashTable::operator delete(void * p, IAllocator * alloc) { alloc->Free(p); } template void SimplerHashTable::operator delete[](void * p, IAllocator * alloc) { alloc->Free(p); } template unsigned SimplerHashTable::GetCount() const { return m_tableCount; } template bool SimplerHashTable::Lookup(Key key, Value* pVal) const { Node* pN = FindNode(key); if (pN != NULL) { if (pVal != NULL) { *pVal = pN->m_val; } return true; } else { return false; } } template Value *SimplerHashTable::LookupPointer(Key key) const { Node* pN = FindNode(key); if (pN != NULL) return &(pN->m_val); else return NULL; } template typename SimplerHashTable::Node* SimplerHashTable::FindNode(Key k) const { if (m_tableSizeInfo.prime == 0) return NULL; unsigned index = GetIndexForKey(k); Node* pN = m_table[index]; if (pN == NULL) return NULL; // Otherwise... while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key)) pN = pN->m_next; assert(pN == NULL || KeyFuncs::Equals(k, pN->m_key)); // If pN != NULL, it's the node for the key, else the key isn't mapped. return pN; } template unsigned SimplerHashTable::GetIndexForKey(Key k) const { unsigned hash = KeyFuncs::GetHashCode(k); unsigned index = magicNumberRem(hash, m_tableSizeInfo); return index; } template bool SimplerHashTable::Set(Key k, Value v) { CheckGrowth(); assert(m_tableSizeInfo.prime != 0); unsigned index = GetIndexForKey(k); Node* pN = m_table[index]; while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key)) { pN = pN->m_next; } if (pN != NULL) { pN->m_val = v; return true; } else { Node* pNewNode = new (m_alloc) Node(k, v, m_table[index]); m_table[index] = pNewNode; m_tableCount++; return false; } } template bool SimplerHashTable::Remove(Key k) { unsigned index = GetIndexForKey(k); Node* pN = m_table[index]; Node** ppN = &m_table[index]; while (pN != NULL && !KeyFuncs::Equals(k, pN->m_key)) { ppN = &pN->m_next; pN = pN->m_next; } if (pN != NULL) { *ppN = pN->m_next; m_tableCount--; Node::operator delete(pN, m_alloc); return true; } else { return false; } } template void SimplerHashTable::RemoveAll() { for (unsigned i = 0; i < m_tableSizeInfo.prime; i++) { for (Node* pN = m_table[i]; pN != NULL; ) { Node* pNext = pN->m_next; Node::operator delete(pN, m_alloc); pN = pNext; } } m_alloc->Free(m_table); m_table = NULL; m_tableSizeInfo = PrimeInfo(); m_tableCount = 0; m_tableMax = 0; return; } template typename SimplerHashTable::KeyIterator SimplerHashTable::Begin() const { KeyIterator i(this, TRUE); return i; } template typename SimplerHashTable::KeyIterator SimplerHashTable::End() const { return KeyIterator(this, FALSE); } template void SimplerHashTable::CheckGrowth() { if (m_tableCount == m_tableMax) { Grow(); } } template void SimplerHashTable::Grow() { unsigned newSize = (unsigned) (m_tableCount * Behavior::s_growth_factor_numerator / Behavior::s_growth_factor_denominator * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator); if (newSize < Behavior::s_minimum_allocation) newSize = Behavior::s_minimum_allocation; // handle potential overflow if (newSize < m_tableCount) Behavior::NoMemory(); Reallocate(newSize); } template void SimplerHashTable::Reallocate(unsigned newTableSize) { assert(newTableSize >= (GetCount() * Behavior::s_density_factor_denominator / Behavior::s_density_factor_numerator)); // Allocation size must be a prime number. This is necessary so that hashes uniformly // distribute to all indices, and so that chaining will visit all indices in the hash table. PrimeInfo newPrime = NextPrime(newTableSize); newTableSize = newPrime.prime; Node** newTable = (Node**)m_alloc->ArrayAlloc(newTableSize, sizeof(Node*)); for (unsigned i = 0; i < newTableSize; i++) { newTable[i] = NULL; } // Move all entries over to new table (re-using the Node structures.) for (unsigned i = 0; i < m_tableSizeInfo.prime; i++) { Node* pN = m_table[i]; while (pN != NULL) { Node* pNext = pN->m_next; unsigned newIndex = magicNumberRem(KeyFuncs::GetHashCode(pN->m_key), newPrime); pN->m_next = newTable[newIndex]; newTable[newIndex] = pN; pN = pNext; } } // @todo: // We might want to try to delay this cleanup to allow asynchronous readers if (m_table != NULL) m_alloc->Free(m_table); m_table = newTable; m_tableSizeInfo = newPrime; m_tableMax = (unsigned) (newTableSize * Behavior::s_density_factor_numerator / Behavior::s_density_factor_denominator); } // Table of primes and their magic-number-divide constant. // For more info see the book "Hacker's Delight" chapter 10.9 "Unsigned Division by Divisors >= 1" // These were selected by looking for primes, each roughly twice as big as the next, having // 32-bit magic numbers, (because the algorithm for using 33-bit magic numbers is slightly slower). // extern const PrimeInfo primeInfo[27]; template PrimeInfo SimplerHashTable::NextPrime(unsigned number) { for (int i = 0; i < (int) (sizeof(primeInfo) / sizeof(primeInfo[0])); i++) { if (primeInfo[i].prime >= number) return primeInfo[i]; } // overflow Behavior::NoMemory(); } #endif // _SIMPLERHASHTABLE_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/slist.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //----------------------------------------------------------------------------- // @File: slist.h // // // @commn: Bunch of utility classes // // HISTORY: // 02/03/98: created helper classes // SLink, link node for singly linked list, every class that is intrusively // linked should have a data member of this type // SList, template linked list class, contains only inline // methods for fast list operations, with proper type checking // // see below for futher info. on how to use these template classes // //----------------------------------------------------------------------------- //#ifndef _H_UTIL //#error "I am a part of util.hpp Please don't include me alone !" //#endif #ifndef _H_SLIST_ #define _H_SLIST_ //------------------------------------------------------------------ // struct SLink, to use a singly linked list // have a data member m_Link of type SLink in your class // and instantiate the template SList class //-------------------------------------------------------------------- struct SLink; typedef DPTR(struct SLink) PTR_SLink; struct SLink { PTR_SLink m_pNext; SLink() { LIMITED_METHOD_CONTRACT; m_pNext = NULL; } void InsertAfter(SLink* pLinkToInsert) { LIMITED_METHOD_CONTRACT; PRECONDITION_MSG(NULL == pLinkToInsert->m_pNext, "This method does not support inserting lists"); PTR_SLink pTemp = m_pNext; m_pNext = PTR_SLink(pLinkToInsert); pLinkToInsert->m_pNext = pTemp; } // find pLink within the list starting at pHead // if found remove the link from the list and return the link // otherwise return NULL static SLink* FindAndRemove(SLink *pHead, SLink* pLink, SLink ** ppPrior) { LIMITED_METHOD_CONTRACT; _ASSERTE(pHead != NULL); _ASSERTE(pLink != NULL); SLink* pFreeLink = NULL; *ppPrior = NULL; while (pHead->m_pNext != NULL) { if (pHead->m_pNext == pLink) { pFreeLink = pLink; pHead->m_pNext = pLink->m_pNext; *ppPrior = pHead; break; } pHead = pHead->m_pNext; } return pFreeLink; } }; //------------------------------------------------------------------ // class SList. Intrusive singly linked list. // // To use SList with the default instantiation, your class should // define a data member of type SLink and named 'm_Link'. To use a // different field name, you need to provide an explicit LinkPtr // template argument. For example: // 'SList' // // SList has two different behaviours depending on boolean // fHead variable, // // if fHead is true, then the list allows only InsertHead operations // if fHead is false, then the list allows only InsertTail operations // the code is optimized to perform these operations // all methods are inline, and conditional compiled based on template // argument 'fHead' // so there is no actual code size increase //-------------------------------------------------------------- template class SList { public: // typedef used by the Queue class below typedef T ENTRY_TYPE; protected: // used as sentinel SLink m_link; // slink.m_pNext == Null PTR_SLink m_pHead; PTR_SLink m_pTail; // get the list node within the object static SLink* GetLink (T* pLink) { LIMITED_METHOD_DAC_CONTRACT; return &(pLink->*LinkPtr); } // move to the beginning of the object given the pointer within the object static T* GetObject (SLink* pLink) { LIMITED_METHOD_DAC_CONTRACT; if (pLink == NULL) { return NULL; } else { #if 1 // Newer compilers define offsetof to be __builtin_offsetof, which doesn't use the // old-school memory model trick to determine offset. const UINT_PTR offset = (((UINT_PTR)&(((T *)0x1000)->*LinkPtr))-0x1000); return (T*)__PTR(dac_cast(pLink) - offset); #else return (T*)__PTR(dac_cast(pLink) - offsetof(T, *LinkPtr)); #endif } } public: SList() { WRAPPER_NO_CONTRACT; #ifndef DACCESS_COMPILE Init(); #endif // !defined(DACCESS_COMPILE) } void Init() { LIMITED_METHOD_CONTRACT; m_pHead = PTR_SLink(&m_link); // NOTE :: fHead variable is template argument // the following code is a compiled in, only if the fHead flag // is set to false, if (!fHead) { m_pTail = PTR_SLink(&m_link); } } bool IsEmpty() { LIMITED_METHOD_CONTRACT; return m_pHead->m_pNext == NULL; } #ifndef DACCESS_COMPILE void InsertTail(T *pObj) { LIMITED_METHOD_CONTRACT; // NOTE : conditional compilation on fHead template variable if (!fHead) { _ASSERTE(pObj != NULL); SLink *pLink = GetLink(pObj); m_pTail->m_pNext = pLink; m_pTail = pLink; } else {// you instantiated this class asking only for InsertHead operations _ASSERTE(0); } } void InsertHead(T *pObj) { LIMITED_METHOD_CONTRACT; // NOTE : conditional compilation on fHead template variable if (fHead) { _ASSERTE(pObj != NULL); SLink *pLink = GetLink(pObj); pLink->m_pNext = m_pHead->m_pNext; m_pHead->m_pNext = pLink; } else {// you instantiated this class asking only for InsertTail operations _ASSERTE(0); } } T* RemoveHead() { LIMITED_METHOD_CONTRACT; SLink* pLink = m_pHead->m_pNext; if (pLink != NULL) { m_pHead->m_pNext = pLink->m_pNext; } // conditionally compiled, if the instantiated class // uses Insert Tail operations if (!fHead) { if(m_pTail == pLink) { m_pTail = m_pHead; } } return GetObject(pLink); } #endif // !DACCESS_COMPILE T* GetHead() { WRAPPER_NO_CONTRACT; return GetObject(m_pHead->m_pNext); } T* GetTail() { WRAPPER_NO_CONTRACT; // conditional compile if (fHead) { // you instantiated this class asking only for InsertHead operations // you need to walk the list yourself to find the tail _ASSERTE(0); } return (m_pHead != m_pTail) ? GetObject(m_pTail) : NULL; } static T *GetNext(T *pObj) { WRAPPER_NO_CONTRACT; _ASSERTE(pObj != NULL); return GetObject(GetLink(pObj)->m_pNext); } T* FindAndRemove(T *pObj) { WRAPPER_NO_CONTRACT; _ASSERTE(pObj != NULL); SLink *prior; SLink *ret = SLink::FindAndRemove(m_pHead, GetLink(pObj), &prior); if (ret == m_pTail) m_pTail = PTR_SLink(prior); return GetObject(ret); } class Iterator { friend class SList; public: Iterator & operator++() { _ASSERTE(m_cur != NULL); m_cur = SList::GetNext(m_cur); return *this; } Iterator operator++(int) { Iterator it(m_cur); ++(*this); return it; } bool operator==(Iterator const & other) const { return m_cur == other.m_cur || (m_cur != NULL && other.m_cur != NULL && *m_cur == *other.m_cur); } bool operator!=(Iterator const & other) const { return !(*this == other); } T & operator*() { _ASSERTE(m_cur != NULL); return *m_cur; } T * operator->() const { return m_cur; } private: Iterator(SList * pList) : m_cur(pList->GetHead()) { } Iterator(T* pObj) : m_cur(pObj) { } Iterator() : m_cur(NULL) { } T* m_cur; }; Iterator begin() { return Iterator(GetHead()); } Iterator end() { return Iterator(); } }; template struct SListElem { SLink m_Link; ElemT m_Value; operator ElemT const &() const { return m_Value; } operator ElemT &() { return m_Value; } ElemT const & operator*() const { return m_Value; } ElemT & operator*() { return m_Value; } ElemT const & GetValue() const { return m_Value; } ElemT & GetValue() { return m_Value; } SListElem() : m_Link() , m_Value() { } template SListElem(T1&& val) : m_Link() , m_Value(std::forward(val)) { } template SListElem(T1&& val1, T2&& val2) : m_Link() , m_Value(std::forward(val1), std::forward(val2)) { } template SListElem(T1&& val1, T2&& val2, T3&& val3) : m_Link() , m_Value(std::forward(val1), std::forward(val2), std::forward(val3)) { } template SListElem(T1&& val1, T2&& val2, T3&& val3, T4&& val4) : m_Link() , m_Value(std::forward(val1), std::forward(val2), std::forward(val3), std::forward(val4)) { } }; #endif // _H_SLIST_ // End of file: list.h ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sospriv.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** sospriv.idl - The private interface that SOS uses to query the runtime ** ** for internal data. ** ** ** *****************************************************************************/ import "unknwn.idl"; import "xclrdata.idl"; struct DacpSyncBlockCleanupData; struct DacpThreadStoreData; struct DacpAppDomainStoreData; struct DacpAppDomainData; struct DacpAssemblyData; struct DacpThreadData; struct DacpMethodDescData; struct DacpCodeHeaderData; struct DacpThreadpoolData; struct DacpObjectData; struct DacpWorkRequestData; struct DacpMethodTableData; struct DacpWorkRequestData; struct DacpModuleData; struct DacpGcHeapData; struct DacpJitManagerInfo; struct DacpHeapSegmentData; struct DacpDomainLocalModuleData; struct DacpDomainLocalModuleData; struct DACEHInfo; struct DacpRCWData; struct DacpAllocData; struct DacpGenerationAllocData; struct DacpExceptionObjectData; cpp_quote("#if 0") typedef ULONG64 CLRDATA_ADDRESS; typedef int CONTEXT; typedef int T_CONTEXT; typedef int mdToken; typedef unsigned int size_t; typedef int ModuleMapType; typedef int VCSHeapType; cpp_quote("#endif") cpp_quote("typedef enum { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE } ModuleMapType;") cpp_quote("typedef enum {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap} VCSHeapType;") typedef void (*MODULEMAPTRAVERSE)(UINT index, CLRDATA_ADDRESS methodTable,LPVOID token); typedef void (*VISITHEAP)(CLRDATA_ADDRESS blockData,size_t blockSize,BOOL blockIsCurrentBlock); typedef BOOL (*VISITRCWFORCLEANUP)(CLRDATA_ADDRESS RCW,CLRDATA_ADDRESS Context,CLRDATA_ADDRESS Thread, BOOL bIsFreeThreaded, LPVOID token); typedef BOOL (*DUMPEHINFO)(UINT clauseIndex,UINT totalClauses, struct DACEHInfo *pEHInfo,LPVOID token); cpp_quote("#ifndef _SOS_HandleData") cpp_quote("#define _SOS_HandleData") typedef struct _SOSHandleData { CLRDATA_ADDRESS AppDomain; CLRDATA_ADDRESS Handle; CLRDATA_ADDRESS Secondary; unsigned int Type; BOOL StrongReference; // For RefCounted Handles unsigned int RefCount; unsigned int JupiterRefCount; BOOL IsPegged; } SOSHandleData; cpp_quote("#endif //HandleData") [ object, local, uuid(286CA186-E763-4F61-9760-487D43AE4341) ] interface ISOSEnum : IUnknown { HRESULT Skip([in] unsigned int count); HRESULT Reset(); HRESULT GetCount([out] unsigned int *pCount); } [ object, local, uuid(3E269830-4A2B-4301-8EE2-D6805B29B2FA) ] interface ISOSHandleEnum : ISOSEnum { HRESULT Next([in] unsigned int count, [out, size_is(count), length_is(*pNeeded)] SOSHandleData handles[], [out] unsigned int *pNeeded); } cpp_quote("#ifndef _SOS_StackReference_") cpp_quote("#define _SOS_StackReference_") typedef enum SOSStackSourceType { SOS_StackSourceIP, // Instruction pointer in managed code SOS_StackSourceFrame, // clr!Frame } SOSStackSourceType; typedef enum SOSRefFlags { SOSRefInterior = 1, SOSRefPinned = 2 } SOSRefFlags; typedef struct _SOS_StackRefData { BOOL HasRegisterInformation; int Register; int Offset; CLRDATA_ADDRESS Address; CLRDATA_ADDRESS Object; unsigned int Flags; SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; } SOSStackRefData; /* Informs the user that we were unable to process the given clr!Frame or * managed frame. */ typedef struct _SOS_StackRefError { SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; } SOSStackRefError; cpp_quote("#endif // _SOS_StackReference_") [ object, local, uuid(774F4E1B-FB7B-491B-976D-A8130FE355E9) ] interface ISOSStackRefErrorEnum : ISOSEnum { HRESULT Next([in] unsigned int count, [out, size_is(count), length_is(*pFetched)] SOSStackRefError ref[], [out] unsigned int *pFetched); } [ object, local, uuid(8FA642BD-9F10-4799-9AA3-512AE78C77EE) ] interface ISOSStackRefEnum : ISOSEnum { HRESULT Next([in] unsigned int count, [out, size_is(count), length_is(*pFetched)] SOSStackRefData ref[], [out] unsigned int *pFetched); /* Reports all frames which we could not enumerate gc references for. */ HRESULT EnumerateErrors([out] ISOSStackRefErrorEnum **ppEnum); } [ object, local, uuid(436f00f2-b42a-4b9f-870c-e73db66ae930) ] interface ISOSDacInterface : IUnknown { // ThreadStore HRESULT GetThreadStoreData(struct DacpThreadStoreData *data); // AppDomains HRESULT GetAppDomainStoreData(struct DacpAppDomainStoreData *data); HRESULT GetAppDomainList(unsigned int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded); HRESULT GetAppDomainData(CLRDATA_ADDRESS addr, struct DacpAppDomainData *data); HRESULT GetAppDomainName(CLRDATA_ADDRESS addr, unsigned int count, WCHAR *name, unsigned int *pNeeded); HRESULT GetDomainFromContext(CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain); // Assemblies HRESULT GetAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], int *pNeeded); HRESULT GetAssemblyData(CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data); HRESULT GetAssemblyName(CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); // Modules HRESULT GetModule(CLRDATA_ADDRESS addr, IXCLRDataModule **mod); HRESULT GetModuleData(CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data); HRESULT TraverseModuleMap(ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token); HRESULT GetAssemblyModuleList(CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[], unsigned int *pNeeded); HRESULT GetILForModule(CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il); // Threads HRESULT GetThreadData(CLRDATA_ADDRESS thread, struct DacpThreadData *data); HRESULT GetThreadFromThinlockID(UINT thinLockId, CLRDATA_ADDRESS *pThread); HRESULT GetStackLimits(CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp); // MethodDescs HRESULT GetMethodDescData(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, struct DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData); HRESULT GetMethodDescPtrFromIP(CLRDATA_ADDRESS ip, CLRDATA_ADDRESS * ppMD); HRESULT GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, WCHAR *name, unsigned int *pNeeded); HRESULT GetMethodDescPtrFromFrame(CLRDATA_ADDRESS frameAddr, CLRDATA_ADDRESS * ppMD); HRESULT GetMethodDescFromToken(CLRDATA_ADDRESS moduleAddr, mdToken token, CLRDATA_ADDRESS *methodDesc); HRESULT GetMethodDescTransparencyData(CLRDATA_ADDRESS methodDesc, struct DacpMethodDescTransparencyData *data); // JIT Data HRESULT GetCodeHeaderData(CLRDATA_ADDRESS ip, struct DacpCodeHeaderData *data); HRESULT GetJitManagerList(unsigned int count, struct DacpJitManagerInfo *managers, unsigned int *pNeeded); HRESULT GetJitHelperFunctionName(CLRDATA_ADDRESS ip, unsigned int count, char *name, unsigned int *pNeeded); HRESULT GetJumpThunkTarget(T_CONTEXT *ctx, CLRDATA_ADDRESS *targetIP, CLRDATA_ADDRESS *targetMD); // ThreadPool HRESULT GetThreadpoolData(struct DacpThreadpoolData *data); HRESULT GetWorkRequestData(CLRDATA_ADDRESS addrWorkRequest, struct DacpWorkRequestData *data); HRESULT GetHillClimbingLogEntry(CLRDATA_ADDRESS addr, struct DacpHillClimbingLogEntry *data); // Objects HRESULT GetObjectData(CLRDATA_ADDRESS objAddr, struct DacpObjectData *data); HRESULT GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, WCHAR *stringData, unsigned int *pNeeded); HRESULT GetObjectClassName(CLRDATA_ADDRESS obj, unsigned int count, WCHAR *className, unsigned int *pNeeded); // MethodTable HRESULT GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, WCHAR *mtName, unsigned int *pNeeded); HRESULT GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data); HRESULT GetMethodTableSlot(CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA_ADDRESS *value); HRESULT GetMethodTableFieldData(CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data); HRESULT GetMethodTableTransparencyData(CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *data); // EEClass HRESULT GetMethodTableForEEClass(CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value); // FieldDesc HRESULT GetFieldDescData(CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data); // Frames HRESULT GetFrameName(CLRDATA_ADDRESS vtable, unsigned int count, WCHAR *frameName, unsigned int *pNeeded); // PEFiles HRESULT GetPEFileBase(CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base); HRESULT GetPEFileName(CLRDATA_ADDRESS addr, unsigned int count, WCHAR *fileName, unsigned int *pNeeded); // GC HRESULT GetGCHeapData(struct DacpGcHeapData *data); HRESULT GetGCHeapList(unsigned int count, CLRDATA_ADDRESS heaps[], unsigned int *pNeeded); // svr only HRESULT GetGCHeapDetails(CLRDATA_ADDRESS heap, struct DacpGcHeapDetails *details); // wks only HRESULT GetGCHeapStaticData(struct DacpGcHeapDetails *data); HRESULT GetHeapSegmentData(CLRDATA_ADDRESS seg, struct DacpHeapSegmentData *data); HRESULT GetOOMData(CLRDATA_ADDRESS oomAddr, struct DacpOomData *data); HRESULT GetOOMStaticData(struct DacpOomData *data); HRESULT GetHeapAnalyzeData(CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyzeData *data); HRESULT GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *data); // DomainLocal HRESULT GetDomainLocalModuleData(CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data); HRESULT GetDomainLocalModuleDataFromAppDomain(CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data); HRESULT GetDomainLocalModuleDataFromModule(CLRDATA_ADDRESS moduleAddr, struct DacpDomainLocalModuleData *data); // ThreadLocal HRESULT GetThreadLocalModuleData(CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *data); // SyncBlock HRESULT GetSyncBlockData(unsigned int number, struct DacpSyncBlockData *data); HRESULT GetSyncBlockCleanupData(CLRDATA_ADDRESS addr, struct DacpSyncBlockCleanupData *data); // Handles HRESULT GetHandleEnum(ISOSHandleEnum **ppHandleEnum); HRESULT GetHandleEnumForTypes(unsigned int types[], unsigned int count, ISOSHandleEnum **ppHandleEnum); HRESULT GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppHandleEnum); // EH HRESULT TraverseEHInfo(CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token); HRESULT GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException); // StressLog HRESULT GetStressLogAddress(CLRDATA_ADDRESS *stressLog); // Heaps HRESULT TraverseLoaderHeap(CLRDATA_ADDRESS loaderHeapAddr, VISITHEAP pCallback); HRESULT GetCodeHeapList(CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo *codeHeaps, unsigned int *pNeeded); HRESULT TraverseVirtCallStubHeap(CLRDATA_ADDRESS pAppDomain, VCSHeapType heaptype, VISITHEAP pCallback); // Other HRESULT GetUsefulGlobals(struct DacpUsefulGlobalsData *data); HRESULT GetClrWatsonBuckets(CLRDATA_ADDRESS thread, void *pGenericModeBlock); HRESULT GetTLSIndex(ULONG *pIndex); HRESULT GetDacModuleHandle(HMODULE *phModule); // COM HRESULT GetRCWData(CLRDATA_ADDRESS addr, struct DacpRCWData *data); HRESULT GetRCWInterfaces(CLRDATA_ADDRESS rcw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); HRESULT GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *data); HRESULT GetCCWInterfaces(CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); HRESULT TraverseRCWCleanupList(CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token); // GC Reference Functions /* GetStackReferences * Enumerates all references on a given callstack. */ HRESULT GetStackReferences([in] DWORD osThreadID, [out] ISOSStackRefEnum **ppEnum); HRESULT GetRegisterName([in] int regName, [in] unsigned int count, [out] WCHAR *buffer, [out] unsigned int *pNeeded); HRESULT GetThreadAllocData(CLRDATA_ADDRESS thread, struct DacpAllocData *data); HRESULT GetHeapAllocData(unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded); // For BindingDisplay plugin HRESULT GetFailedAssemblyList(CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[], unsigned int *pNeeded); HRESULT GetPrivateBinPaths(CLRDATA_ADDRESS appDomain, int count, WCHAR *paths, unsigned int *pNeeded); HRESULT GetAssemblyLocation(CLRDATA_ADDRESS assembly, int count, WCHAR *location, unsigned int *pNeeded); HRESULT GetAppDomainConfigFile(CLRDATA_ADDRESS appDomain, int count, WCHAR *configFile, unsigned int *pNeeded); HRESULT GetApplicationBase(CLRDATA_ADDRESS appDomain, int count, WCHAR *base, unsigned int *pNeeded); HRESULT GetFailedAssemblyData(CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult); HRESULT GetFailedAssemblyLocation(CLRDATA_ADDRESS assesmbly, unsigned int count, WCHAR *location, unsigned int *pNeeded); HRESULT GetFailedAssemblyDisplayName(CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); }; [ object, local, uuid(A16026EC-96F4-40BA-87FB-5575986FB7AF) ] interface ISOSDacInterface2 : IUnknown { HRESULT GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data); HRESULT IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy); }; [ object, local, uuid(B08C5CDC-FD8A-49C5-AB38-5FEEF35235B4) ] interface ISOSDacInterface3 : IUnknown { HRESULT GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data); HRESULT GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData *data); HRESULT GetGCGlobalMechanisms(size_t* globalMechanisms); }; [ object, local, uuid(74B9D34C-A612-4B07-93DD-5462178FCE11) ] interface ISOSDacInterface4 : IUnknown { HRESULT GetClrNotification(CLRDATA_ADDRESS arguments[], int count, int *pNeeded); }; [ object, local, uuid(127d6abe-6c86-4e48-8e7b-220781c58101) ] interface ISOSDacInterface5 : IUnknown { HRESULT GetTieredVersions(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs); }; [ object, local, uuid(11206399-4B66-4EDB-98EA-85654E59AD45) ] interface ISOSDacInterface6 : IUnknown { HRESULT GetMethodTableCollectibleData(CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data); }; [ object, local, uuid(c1020dde-fe98-4536-a53b-f35a74c327eb) ] interface ISOSDacInterface7 : IUnknown { HRESULT GetPendingReJITID(CLRDATA_ADDRESS methodDesc, int *pRejitId); HRESULT GetReJITInformation(CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpReJitData2 *pRejitData); HRESULT GetProfilerModifiedILInformation(CLRDATA_ADDRESS methodDesc, struct DacpProfilerILData *pILData); HRESULT GetMethodsWithProfilerModifiedIL(CLRDATA_ADDRESS mod, CLRDATA_ADDRESS *methodDescs, int cMethodDescs, int *pcMethodDescs); }; [ object, local, uuid(c12f35a9-e55c-4520-a894-b3dc5165dfce) ] interface ISOSDacInterface8 : IUnknown { HRESULT GetNumberGenerations(unsigned int *pGenerations); // WKS HRESULT GetGenerationTable(unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded); HRESULT GetFinalizationFillPointers(unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded); // SVR HRESULT GetGenerationTableSvr(CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded); HRESULT GetFinalizationFillPointersSvr(CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded); HRESULT GetAssemblyLoadContext(CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS* assemblyLoadContext); } // Increment anytime there is a change in the data structures that SOS depends on like // stress log structs (StressMsg, StressLogChunck, ThreadStressLog, etc), exception // stack traces (StackTraceElement), the PredefinedTlsSlots enums, etc. cpp_quote("#define SOS_BREAKING_CHANGE_VERSION 3") [ object, local, uuid(4eca42d8-7e7b-4c8a-a116-7bfbf6929267) ] interface ISOSDacInterface9 : IUnknown { HRESULT GetBreakingChangeVersion(int* pVersion); } [ object, local, uuid(90B8FCC3-7251-4B0A-AE3D-5C13A67EC9AA) ] interface ISOSDacInterface10 : IUnknown { HRESULT GetObjectComWrappersData(CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS *rcw, unsigned int count, CLRDATA_ADDRESS *mowList, unsigned int *pNeeded); HRESULT IsComWrappersCCW(CLRDATA_ADDRESS ccw, BOOL *isComWrappersCCW); HRESULT GetComWrappersCCWData(CLRDATA_ADDRESS ccw, CLRDATA_ADDRESS *managedObject, int *refCount); HRESULT IsComWrappersRCW(CLRDATA_ADDRESS rcw, BOOL *isComWrappersRCW); HRESULT GetComWrappersRCWData(CLRDATA_ADDRESS rcw, CLRDATA_ADDRESS *identity); } [ object, local, uuid(96BA1DB9-14CD-4492-8065-1CAAECF6E5CF) ] interface ISOSDacInterface11 : IUnknown { HRESULT IsTrackedType(CLRDATA_ADDRESS objAddr, BOOL* isTrackedType, BOOL* hasTaggedMemory); HRESULT GetTaggedMemory(CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS* taggedMemory, size_t* taggedMemorySizeInBytes); } [ object, local, uuid(1b93bacc-8ca4-432d-943a-3e6e7ec0b0a3) ] interface ISOSDacInterface12 : IUnknown { HRESULT GetGlobalAllocationContext(CLRDATA_ADDRESS* allocPtr, CLRDATA_ADDRESS* allocLimit); } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sstring.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // SString.h (Safe String) // // --------------------------------------------------------------------------- // ------------------------------------------------------------------------------------------ // SString is the "standard" string representation for the EE. Its has two purposes. // (1) it provides an easy-to-use, relatively efficient, string class for APIs to standardize // on. // (2) it completely encapsulates all "unsafe" string operations - that is, string operations // which yield possible buffer overrun bugs. Typesafe use of this API should help guarantee // safety. // // A SString is conceptually unicode, although the internal conversion might be delayed as long as possible // Basically it's up to the implementation whether conversion takes place immediately or is delayed, and if // delayed, what operations trigger the conversion. // // Note that anywhere you express a "position" in a string, it is in terms of the Unicode representation of the // string. // // If you need a direct non-unicode representation, you will have to provide a fresh SString which can // receive a conversion operation if necessary. // // The alternate encodings available are: // 1. ASCII - string consisting entirely of ASCII (7 bit) characters. This is the only 1 byte encoding // guaranteed to be fixed width. Such a string is also a valid instance of all the other 1 byte string // representations, and we take advantage of this fact. // 2. UTF-8 - standard multibyte unicode encoding. // 3. ANSI - Potentially multibyte encoding using the ANSI page determined by GetACP(). // // @todo: Note that we could also provide support for several other cases (but currently do not.) // - Page specified by GetOEMCP() (OEM page) // - Arbitrary page support // // @todo: argument & overflow/underflow checking needs to be added // ------------------------------------------------------------------------------------------ #ifndef _SSTRING_H_ #define _SSTRING_H_ #include "utilcode.h" #include "sbuffer.h" #include "debugmacros.h" // ========================================================================================== // Documentational typedefs: use these to indicate specific representations of 8 bit strings: // ========================================================================================== // Note that LPCSTR means ASCII (7-bit) only! typedef CHAR ASCII; typedef ASCII *LPASCII; typedef const ASCII *LPCASCII; typedef CHAR ANSI; typedef ANSI *LPANSI; typedef const ANSI *LPCANSI; typedef CHAR UTF8; typedef UTF8 *LPUTF8; typedef const UTF8 *LPCUTF8; // ========================================================================================== // SString is the base class for safe strings. // ========================================================================================== typedef DPTR(class SString) PTR_SString; class EMPTY_BASES_DECL SString : private SBuffer { friend struct _DacGlobals; private: enum Representation { // Note: bits are meaningful: xVS V == Variable? S == Single byte width? REPRESENTATION_EMPTY = 0x00, // 000 REPRESENTATION_UNICODE = 0x04, // 100 REPRESENTATION_ASCII = 0x01, // 001 REPRESENTATION_UTF8 = 0x03, // 011 REPRESENTATION_VARIABLE_MASK = 0x02, REPRESENTATION_SINGLE_MASK = 0x01, REPRESENTATION_MASK = 0x07, }; // Minimum guess for Printf buffer size const static COUNT_T MINIMUM_GUESS = 20; #ifdef _DEBUG // Used to have a public ctor of this form - made it too easy to lose // utf8 info by accident. Now you have to specify the representation type // explicitly - this privator ctor prevents reinsertion of this ctor. explicit SString(const ASCII *) { _ASSERTE(!"Don't call this."); } #endif protected: class Index; friend class Index; public: // CIterators/Iterator'string must be modified by SString APIs. class CIterator; class Iterator; // Tokens for constructor overloads enum tagUTF8Literal { Utf8Literal }; enum tagLiteral { Literal }; enum tagUTF8 { Utf8 }; enum tagASCII { Ascii }; static void Startup(); static CHECK CheckStartup(); static const SString &Empty(); SString(); explicit SString(const SString &s); SString(const SString &s1, const SString &s2); SString(const SString &s1, const SString &s2, const SString &s3); SString(const SString &s1, const SString &s2, const SString &s3, const SString &s4); SString(const SString &s, const CIterator &i, COUNT_T length); SString(const SString &s, const CIterator &start, const CIterator &end); SString(const WCHAR *string); SString(const WCHAR *string, COUNT_T count); SString(enum tagASCII dummyTag, const ASCII *string); SString(enum tagASCII dummyTag, const ASCII *string, COUNT_T count); SString(enum tagUTF8 dummytag, const UTF8 *string); SString(enum tagUTF8 dummytag, const UTF8 *string, COUNT_T count); SString(WCHAR character); // NOTE: Literals MUST be read-only never-freed strings. SString(enum tagLiteral dummytag, const CHAR *literal); SString(enum tagUTF8Literal dummytag, const UTF8 *literal); SString(enum tagLiteral dummytag, const WCHAR *literal); SString(enum tagLiteral dummytag, const WCHAR *literal, COUNT_T count); // Set this string to the concatenation of s1,s2,s3,s4 void Set(const SString &s); void Set(const SString &s1, const SString &s2); void Set(const SString &s1, const SString &s2, const SString &s3); void Set(const SString &s1, const SString &s2, const SString &s3, const SString &s4); // Set this string to the substring of s, starting at i, of length characters. void Set(const SString &s, const CIterator &i, COUNT_T length); // Set this string to the substring of s, starting at start and ending at end (exclusive) void Set(const SString &s, const CIterator &start, const CIterator &end); // Set this string to a copy of the given string void Set(const WCHAR *string); void SetASCII(const ASCII *string); void SetUTF8(const UTF8 *string); void SetAndConvertToUTF8(const WCHAR* string); // Set this string to a copy of the first count chars of the given string void Set(const WCHAR *string, COUNT_T count); // Set this string to a prellocated copy of a given string. // The caller is the owner of the buffer and has to coordinate its lifetime. void SetPreallocated(const WCHAR *string, COUNT_T count); void SetASCII(const ASCII *string, COUNT_T count); void SetUTF8(const UTF8 *string, COUNT_T count); // Set this string to the unicode character void Set(WCHAR character); // Set this string to the UTF8 character void SetUTF8(CHAR character); // Set this string to the given literal. We share the mem and don't make a copy. void SetLiteral(const CHAR *literal); void SetLiteral(const WCHAR *literal); // ------------------------------------------------------------------ // Public operations // ------------------------------------------------------------------ // Normalizes the string representation to unicode. This can be used to // make basic read-only operations non-failing. void Normalize() const; // Return the number of characters in the string (excluding the terminating NULL). COUNT_T GetCount() const; BOOL IsEmpty() const; // Return whether a single byte string has all characters which fit in the ASCII set. // (Note that this will return FALSE if the string has been converted to unicode for any // reason.) BOOL IsASCII() const; // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! // // THIS IS NOT SUPPORTED FULLY ON WIN9x // SString case-insensitive comparison is based off LCMapString, // which does not work on characters outside the current OS code page. // // Case insensitive code in SString is primarily targeted at // supporting path comparisons, which is supported correctly on 9x, // since file system names are limited to the OS code page. // // !!!!!!!!!!!!!! WARNING about case insensitive operations !!!!!!!!!!!!!!! // Compute a content-based hash value ULONG Hash() const; ULONG HashCaseInsensitive() const; // Do a string comparison. Return 0 if the strings // have the same value, -1 if this is "less than" s, or 1 if // this is "greater than" s. int Compare(const SString &s) const; int CompareCaseInsensitive(const SString &s) const; // invariant locale // Do a case sensitive string comparison. Return TRUE if the strings // have the same value FALSE if not. BOOL Equals(const SString &s) const; BOOL EqualsCaseInsensitive(const SString &s) const; // invariant locale // Match s to a portion of the string starting at the position. // Return TRUE if the strings have the same value // (regardless of representation), FALSE if not. BOOL Match(const CIterator &i, const SString &s) const; BOOL MatchCaseInsensitive(const CIterator &i, const SString &s) const; // invariant locale BOOL Match(const CIterator &i, WCHAR c) const; BOOL MatchCaseInsensitive(const CIterator &i, WCHAR c) const; // invariant locale // Like match, but advances the iterator past the match // if successful BOOL Skip(CIterator &i, const SString &s) const; BOOL Skip(CIterator &i, WCHAR c) const; // Start searching for a match of the given string, starting at // the given iterator point. // If a match exists, move the iterator to point to the nearest // occurrence of s in the string and return TRUE. // If no match exists, return FALSE and leave the iterator unchanged. BOOL Find(CIterator &i, const SString &s) const; BOOL Find(CIterator &i, const WCHAR *s) const; BOOL FindASCII(CIterator &i, const ASCII *s) const; BOOL FindUTF8(CIterator &i, const UTF8 *s) const; BOOL Find(CIterator &i, WCHAR c) const; BOOL FindBack(CIterator &i, const SString &s) const; BOOL FindBack(CIterator &i, const WCHAR *s) const; BOOL FindBackASCII(CIterator &i, const ASCII *s) const; BOOL FindBackUTF8(CIterator &i, const UTF8 *s) const; BOOL FindBack(CIterator &i, WCHAR c) const; // Returns TRUE if this string begins with the contents of s BOOL BeginsWith(const SString &s) const; BOOL BeginsWithCaseInsensitive(const SString &s) const; // invariant locale // Returns TRUE if this string ends with the contents of s BOOL EndsWith(const SString &s) const; BOOL EndsWithCaseInsensitive(const SString &s) const; // invariant locale // Sets this string to an empty string "". void Clear(); // Truncate the string to the iterator position void Truncate(const Iterator &i); // Append s to the end of this string. void Append(const SString &s); void Append(const WCHAR *s); void AppendASCII(const CHAR *s); void AppendUTF8(const CHAR *s); // Append char c to the end of this string. void Append(const WCHAR c); void AppendUTF8(const CHAR c); // Insert s into this string at the 'position'th character. void Insert(const Iterator &i, const SString &s); void Insert(const Iterator &i, const WCHAR *s); void InsertASCII(const Iterator &i, const CHAR *s); void InsertUTF8(const Iterator &i, const CHAR *s); // Delete substring position + length void Delete(const Iterator &i, COUNT_T length); // Replace character at i with c void Replace(const Iterator &i, WCHAR c); // Replace substring at (i,i+length) with s void Replace(const Iterator &i, COUNT_T length, const SString &s); // Make sure that string buffer has room to grow void Preallocate(COUNT_T characters) const; // Shrink buffer size as much as possible (reallocate if necessary.) void Trim() const; // ------------------------------------------------------------------ // Iterators: // ------------------------------------------------------------------ // SString splits iterators into two categories. // // CIterator and Iterator are cheap to create, but allow only read-only // access to the string. // // For CIterator & Iterator, we try our best to iterate the string without // modifying it. (Currently, we do require an ASCII or Unicode string // for simple WCHAR retrieval, but you could imagine being more flexible // going forward - perhaps even supporting iterating multibyte encodings // directly.) // // Because of the runtime-changable nature of the string, CIterators // require an extra member to record the character size. They also // are unable to properly implement GetAt as required by the template // (since there may not be a direct WCHAR pointer), so they provide // further customization in a subclass. // // Normally the user expects to cast Iterators to CIterators transparently, so // we provide a constructor on CIterator to support this. protected: class EMPTY_BASES_DECL Index : public SBuffer::Index { friend class SString; friend class Indexer; friend class Indexer; protected: int m_characterSizeShift; Index(); Index(SString *string, SCOUNT_T index); BYTE &GetAt(SCOUNT_T delta) const; void Skip(SCOUNT_T delta); SCOUNT_T Subtract(const Index &i) const; CHECK DoCheck(SCOUNT_T delta) const; void Resync(const SString *string, BYTE *ptr) const; const WCHAR *GetUnicode() const; const CHAR *GetASCII() const; public: // Note these should supersede the Indexer versions // since this class comes first in the inheritance list WCHAR operator*() const; void operator->() const; WCHAR operator[](int index) const; }; public: class EMPTY_BASES_DECL CIterator : public Index, public Indexer { friend class SString; public: const Iterator &ConstCast() const { return *(const Iterator *)this; } Iterator &ConstCast() { return *(Iterator *)this; } operator const SBuffer::CIterator &() const { return *(const SBuffer::CIterator *)this; } operator SBuffer::CIterator &() { return *(SBuffer::CIterator *)this; } CIterator() { } CIterator(const SString *string, int index) : Index(const_cast(string), index) { } // explicitly resolve these for gcc WCHAR operator*() const { return Index::operator*(); } void operator->() const { Index::operator->(); } WCHAR operator[](int index) const { return Index::operator[](index); } }; class EMPTY_BASES_DECL Iterator : public Index, public Indexer { friend class SString; public: operator const CIterator &() const { return *(const CIterator *)this; } operator CIterator &() { return *(CIterator *)this; } operator const SBuffer::Iterator &() const { return *(const SBuffer::Iterator *)this; } operator SBuffer::Iterator &() { return *(SBuffer::Iterator *)this; } Iterator() { } Iterator(SString *string, int index) : Index(string, index) { SUPPORTS_DAC; } // explicitly resolve these for gcc WCHAR operator*() const { return Index::operator*(); } void operator->() const { Index::operator->(); } WCHAR operator[](int index) const { return Index::operator[](index); } }; CIterator Begin() const; CIterator End() const; Iterator Begin(); Iterator End(); // ------------------------------------------------------------------ // Conversion: // ------------------------------------------------------------------ // Get a const pointer to the string in the current representation. // This pointer can not be cached because it will become invalid if // the SString changes representation or reallocates its buffer. // You can always get a unicode string. This will force a conversion // if necessary. const WCHAR *GetUnicode() const; const WCHAR *GetUnicode(const CIterator &i) const; void LowerCase(); void UpperCase(); // Helper function to convert string in-place to lower-case (no allocation overhead for SString instance) static void LowerCase(__inout_z LPWSTR wszString); // You can always get a UTF8 string. This will force a conversion // if necessary. const UTF8 *GetUTF8() const; // Converts/copies into the given output string void ConvertToUnicode(SString &dest) const; COUNT_T ConvertToUTF8(SString &dest) const; //------------------------------------------------------------------- // Accessing the string contents directly //------------------------------------------------------------------- // To write directly to the SString's underlying buffer: // 1) Call OpenXXXBuffer() and pass it the count of characters // you need. (Not including the null-terminator). // 2) That returns a pointer to the raw buffer which you can write to. // 3) When you are done writing to the pointer, call CloseBuffer() // and pass it the count of characters you actually wrote (not including // the null). The pointer from step 1 is now invalid. // example usage: // void GetName(SString & str) { // char * p = str.OpenUTF8Buffer(3); // strcpy(p, "Cat"); // str.CloseBuffer(); // } // Regarding the null-terminator: // 1) Note that we wrote 4 characters (3 + a null). That's ok. OpenBuffer // allocates 1 extra byte for the null. // 2) If we only wrote 3 characters and no null, that's ok too. CloseBuffer() // will add a null-terminator. // You should open the buffer, write the data, and immediately close it. // No sstring operations are valid while the buffer is opened. // // In a debug build, Open/Close will do lots of little checks to make sure // you don't buffer overflow while it's opened. In a retail build, this // is a very streamlined action. // Open the raw buffer for writing countChars characters (not including the null). WCHAR *OpenUnicodeBuffer(COUNT_T maxCharCount); UTF8 *OpenUTF8Buffer(COUNT_T maxSingleCharCount); //Returns the unicode string, the caller is responsible for lifetime of the string WCHAR *GetCopyOfUnicodeString(); // Get the max size that can be passed to OpenUnicodeBuffer without causing allocations. COUNT_T GetUnicodeAllocation(); // Call after OpenXXXBuffer(). // Provide the count of characters actually used (not including the // null terminator). This will make sure the SString's size is correct // and that we have a null-terminator. void CloseBuffer(COUNT_T finalCount); // Close the buffer. Assumes that we completely filled the buffer // that OpenBuffer() gave back. If we didn't write all the characters, // call CloseBuffer(int) instead. void CloseBuffer(); #ifdef DACCESS_COMPILE // DAC access to string functions. // Note that other accessors above are not DAC-safe and will return TARGET pointers into // the string instead of copying the string over to the host. // @dbgtodo dac support: Prevent usage of such DAC-unsafe SString APIs in DAC code // Instantiate a copy of the raw buffer in the host and return a pointer to it void * DacGetRawContent() const; // Instantiate a copy of the raw buffer in the host. Requires that the underlying // representation is already unicode. const WCHAR * DacGetRawUnicode() const; // Copy the string from the target into the provided buffer, converting to unicode if necessary bool DacGetUnicode(COUNT_T bufChars, _Inout_updates_z_(bufChars) WCHAR * buffer, COUNT_T * needChars) const; void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) const { SUPPORTS_DAC; SBuffer::EnumMemoryRegions(flags); } #endif //--------------------------------------------------------------------- // Utilities //--------------------------------------------------------------------- // WARNING: The MBCS version of printf function are factory for globalization // issues when used to format Unicode strings (%S). The Unicode versions are // preferred in this case. void Printf(const CHAR *format, ...); void VPrintf(const CHAR *format, va_list args); void AppendPrintf(const CHAR *format, ...); void AppendVPrintf(const CHAR *format, va_list args); public: BOOL LoadResource(CCompRC::ResourceCategory eCategory, int resourceID); HRESULT LoadResourceAndReturnHR(CCompRC::ResourceCategory eCategory, int resourceID); HRESULT LoadResourceAndReturnHR(CCompRC* pResourceDLL, CCompRC::ResourceCategory eCategory, int resourceID); BOOL FormatMessage(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, const SString &arg1 = Empty(), const SString &arg2 = Empty(), const SString &arg3 = Empty(), const SString &arg4 = Empty(), const SString &arg5 = Empty(), const SString &arg6 = Empty(), const SString &arg7 = Empty(), const SString &arg8 = Empty(), const SString &arg9 = Empty(), const SString &arg10 = Empty()); #if 1 // @todo - get rid of this and move it outside of SString void MakeFullNamespacePath(const SString &nameSpace, const SString &name); #endif //-------------------------------------------------------------------- // Operators //-------------------------------------------------------------------- operator const WCHAR * () const { WRAPPER_NO_CONTRACT; return GetUnicode(); } WCHAR operator[](int index) { WRAPPER_NO_CONTRACT; return Begin()[index]; } WCHAR operator[](int index) const { WRAPPER_NO_CONTRACT; return Begin()[index]; } SString &operator= (const SString &s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } SString &operator+= (const SString &s) { WRAPPER_NO_CONTRACT; Append(s); return *this; } // ------------------------------------------------------------------- // Check functions // ------------------------------------------------------------------- CHECK CheckIteratorRange(const CIterator &i) const; CHECK CheckIteratorRange(const CIterator &i, COUNT_T length) const; CHECK CheckEmpty() const; static CHECK CheckCount(COUNT_T count); static CHECK CheckRepresentation(int representation); #if CHECK_INVARIANTS static CHECK CheckASCIIString(const ASCII *string); static CHECK CheckASCIIString(const ASCII *string, COUNT_T count); CHECK Check() const; CHECK Invariant() const; CHECK InternalInvariant() const; #endif // CHECK_INVARIANTS // Helpers for CRT function equivalance. static int __cdecl _stricmp(const CHAR *buffer1, const CHAR *buffer2); static int __cdecl _strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); static int __cdecl _wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2); static int __cdecl _wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); // C++ convenience overloads static int _tstricmp(const CHAR *buffer1, const CHAR *buffer2); static int _tstricmp(const WCHAR *buffer1, const WCHAR *buffer2); static int _tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count); static int _tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count); // ------------------------------------------------------------------- // Internal routines // ------------------------------------------------------------------- protected: // Use this via InlineSString SString(void *buffer, COUNT_T size); private: static int CaseCompareHelperA(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); static int CaseCompareHelper(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count, BOOL stopOnNull, BOOL stopOnCount); // Internal helpers: static const BYTE s_EmptyBuffer[2]; static UINT s_ACP; SPTR_DECL(SString,s_Empty); COUNT_T GetRawCount() const; // Get buffer as appropriate string rep ASCII *GetRawASCII() const; UTF8 *GetRawUTF8() const; ANSI *GetRawANSI() const; WCHAR *GetRawUnicode() const; void InitEmpty(); Representation GetRepresentation() const; void SetRepresentation(Representation representation); BOOL IsRepresentation(Representation representation) const; BOOL IsFixedSize() const; BOOL IsIteratable() const; BOOL IsSingleByte() const; int GetCharacterSizeShift() const; COUNT_T SizeToCount(COUNT_T size) const; COUNT_T CountToSize(COUNT_T count) const; COUNT_T GetBufferSizeInCharIncludeNullChar() const; BOOL IsLiteral() const; BOOL IsAllocated() const; BOOL IsBufferOpen() const; BOOL IsASCIIScanned() const; void SetASCIIScanned() const; void SetNormalized() const; BOOL IsNormalized() const; void ClearNormalized() const; void EnsureWritable() const; void ConvertToFixed() const; void ConvertToIteratable() const; void ConvertASCIIToUnicode(SString &dest) const; void ConvertToUnicode() const; void ConvertToUnicode(const CIterator &i) const; void ConvertToUTF8() const; const SString &GetCompatibleString(const SString &s, SString &scratch) const; const SString &GetCompatibleString(const SString &s, SString &scratch, const CIterator &i) const; BOOL ScanASCII() const; void NullTerminate(); void Resize(COUNT_T count, Representation representation, Preserve preserve = DONT_PRESERVE); void OpenBuffer(Representation representation, COUNT_T countChars); }; // =========================================================================== // InlineSString is used for stack allocation of strings, or when the string contents // are expected or known to be small. Note that it still supports expandability via // heap allocation if necessary. // =========================================================================== template class EMPTY_BASES_DECL InlineSString : public SString { private: DAC_ALIGNAS(SString) BYTE m_inline[SBUFFER_PADDED_SIZE(MEMSIZE)]; public: FORCEINLINE InlineSString() : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; } FORCEINLINE InlineSString(const SString &s) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(s); } FORCEINLINE InlineSString(const SString &s1, const SString &s2) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(s1, s2); } FORCEINLINE InlineSString(const SString &s1, const SString &s2, const SString &s3) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(s1, s2, s3); } FORCEINLINE InlineSString(const SString &s1, const SString &s2, const SString &s3, const SString &s4) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(s1, s2, s3, s4); } FORCEINLINE InlineSString(const SString &s, const CIterator &start, const CIterator &end) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(s, start, end); } FORCEINLINE InlineSString(const SString &s, const CIterator &i, COUNT_T length) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(s, i, length); } FORCEINLINE InlineSString(const WCHAR *string) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(string); } FORCEINLINE InlineSString(const WCHAR *string, COUNT_T count) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(string, count); } FORCEINLINE InlineSString(enum tagASCII, const CHAR *string) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; SetASCII(string); } FORCEINLINE InlineSString(enum tagASCII, const CHAR *string, COUNT_T count) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; SetASCII(string, count); } FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 *string) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; SetUTF8(string); } FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 *string, COUNT_T count) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; SetUTF8(string, count); } FORCEINLINE InlineSString(WCHAR character) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; Set(character); } FORCEINLINE InlineSString(tagUTF8 dummytag, const UTF8 character) : SString(m_inline, SBUFFER_PADDED_SIZE(MEMSIZE)) { WRAPPER_NO_CONTRACT; SetUTF8(character); } FORCEINLINE InlineSString &operator= (const SString &s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } FORCEINLINE InlineSString &operator= (const InlineSString &s) { WRAPPER_NO_CONTRACT; Set(s); return *this; } }; // ================================================================================ // StackSString is a lot like CQuickBytes. Use it to create an SString object // using some stack space as a preallocated buffer. // ================================================================================ typedef InlineSString<512> StackSString; // This is a smaller version for when it is known that the string that's going to // be needed is small and it's preferable not to take up the stack space. typedef InlineSString<32> SmallStackSString; // To be used specifically for path strings. #ifdef _DEBUG // This is a smaller version for debug builds to exercise the buffer allocation path typedef InlineSString<32> PathString; typedef InlineSString<2 * 32> LongPathString; #else // Set it to the current MAX_PATH typedef InlineSString<260> PathString; typedef InlineSString<2 * 260> LongPathString; #endif // ================================================================================ // Quick macro to create an SString around a literal string. // usage: // s = SL("My literal String"); // ================================================================================ #define SL(_literal) SString(SString::Literal, _literal) // ================================================================================ // Special contract definition - THROWS_UNLESS_NORMALIZED // this is used for operations which might fail for generalized strings but // not if the string has already been converted to unicode. Rather than just // setting this on all conversions to unicode, we only set it when explicitly // asked. This should expose more potential problems. // ================================================================================ #define THROWS_UNLESS_NORMALIZED \ if (IsNormalized()) NOTHROW; else THROWS #define THROWS_UNLESS_BOTH_NORMALIZED(s) \ if (IsNormalized() && s.IsNormalized()) NOTHROW; else THROWS #define FAULTS_UNLESS_NORMALIZED(stmt) \ if (IsNormalized()) FORBID_FAULT; else INJECT_FAULT(stmt) #define FAULTS_UNLESS_BOTH_NORMALIZED(s, stmt) \ if (IsNormalized() && s.IsNormalized()) FORBID_FAULT; else INJECT_FAULT(stmt) // ================================================================================ // Inline definitions // ================================================================================ #include #endif // _SSTRING_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/sstring.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // #ifndef _SSTRING_INL_ #define _SSTRING_INL_ #include "sstring.h" #if defined(_MSC_VER) #pragma inline_depth (20) #endif #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4702) // Disable bogus unreachable code warning #endif // _MSC_VER //#define SSTRING_EXTRA_CHECKS #ifdef SSTRING_EXTRA_CHECKS #define SS_CONTRACT CONTRACT #define SS_CONTRACT_VOID CONTRACT_VOID #define SS_CONTRACT_END CONTRACT_END #define SS_RETURN RETURN #define SS_CONSTRUCTOR_CHECK CONSTRUCTOR_CHECK #define SS_PRECONDITION PRECONDITION #define SS_POSTCONDITION POSTCONDITION #else //SSTRING_EXTRA_CHECKS #define SS_CONTRACT(x) CONTRACTL #define SS_CONTRACT_VOID CONTRACTL #define SS_CONTRACT_END CONTRACTL_END #define SS_RETURN return #define SS_CONSTRUCTOR_CHECK #define SS_PRECONDITION(x) #define SS_POSTCONDITION(x) //Do I need this instance check at all? #endif // --------------------------------------------------------------------------- // Inline implementations. Pay no attention to that man behind the curtain. // --------------------------------------------------------------------------- //---------------------------------------------------------------------------- // Default constructor. Sets the string to the empty string. //---------------------------------------------------------------------------- inline SString::SString() : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { CONSTRUCTOR_CHECK; POSTCONDITION(IsEmpty()); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; RETURN; #else STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #endif } inline SString::SString(void *buffer, COUNT_T size) : SBuffer(Prealloc, buffer, size) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(buffer)); PRECONDITION(CheckSize(size)); SS_POSTCONDITION(IsEmpty()); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; if (size < sizeof(WCHAR)) { // Ignore the useless buffer SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); } else { SBuffer::TweakSize(sizeof(WCHAR)); GetRawUnicode()[0] = 0; } SS_RETURN; } inline SString::SString(const SString &s) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s.Check()); SS_POSTCONDITION(Equals(s)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(s); SS_RETURN; } inline SString::SString(const SString &s1, const SString &s2) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s1.Check()); PRECONDITION(s2.Check()); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(s1, s2); SS_RETURN; } inline SString::SString(const SString &s1, const SString &s2, const SString &s3) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s1.Check()); PRECONDITION(s2.Check()); PRECONDITION(s3.Check()); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(s1, s2, s3); SS_RETURN; } inline SString::SString(const SString &s1, const SString &s2, const SString &s3, const SString &s4) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s1.Check()); PRECONDITION(s2.Check()); PRECONDITION(s3.Check()); PRECONDITION(s4.Check()); THROWS; } SS_CONTRACT_END; Set(s1, s2, s3, s4); SS_RETURN; } inline SString::SString(const SString &s, const CIterator &i, COUNT_T count) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s.Check()); PRECONDITION(i.Check()); PRECONDITION(CheckCount(count)); SS_POSTCONDITION(s.Match(i, *this)); SS_POSTCONDITION(GetRawCount() == count); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(s, i, count); SS_RETURN; } inline SString::SString(const SString &s, const CIterator &start, const CIterator &end) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(s.Check()); PRECONDITION(start.Check()); PRECONDITION(s.CheckIteratorRange(start)); PRECONDITION(end.Check()); PRECONDITION(s.CheckIteratorRange(end)); PRECONDITION(start <= end); SS_POSTCONDITION(s.Match(start, *this)); SS_POSTCONDITION(GetRawCount() == (COUNT_T) (end - start)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(s, start, end); SS_RETURN; } inline SString::SString(const WCHAR *string) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(string, NULL_OK)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(string); SS_RETURN; } inline SString::SString(const WCHAR *string, COUNT_T count) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(string, NULL_OK)); PRECONDITION(CheckCount(count)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(string, count); SS_RETURN; } inline SString::SString(enum tagASCII, const ASCII *string) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(string, NULL_OK)); PRECONDITION(CheckASCIIString(string)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; SetASCII(string); SS_RETURN; } inline SString::SString(enum tagASCII, const ASCII *string, COUNT_T count) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(string, NULL_OK)); PRECONDITION(CheckASCIIString(string, count)); PRECONDITION(CheckCount(count)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; SetASCII(string, count); SS_RETURN; } inline SString::SString(tagUTF8 dummytag, const UTF8 *string) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; // !!! Check for illegal UTF8 encoding? PRECONDITION(CheckPointer(string, NULL_OK)); THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } SS_CONTRACT_END; SetUTF8(string); SS_RETURN; } inline SString::SString(tagUTF8 dummytag, const UTF8 *string, COUNT_T count) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; // !!! Check for illegal UTF8 encoding? PRECONDITION(CheckPointer(string, NULL_OK)); PRECONDITION(CheckCount(count)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; SetUTF8(string, count); SS_RETURN; } inline SString::SString(WCHAR character) : SBuffer(Immutable, s_EmptyBuffer, sizeof(s_EmptyBuffer)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(character); SS_RETURN; } inline SString::SString(tagLiteral dummytag, const ASCII *literal) : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (strlen(literal)+1)*sizeof(CHAR)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(literal)); PRECONDITION(CheckASCIIString(literal)); NOTHROW; GC_NOTRIGGER; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; SetRepresentation(REPRESENTATION_ASCII); SS_RETURN; } inline SString::SString(tagUTF8Literal dummytag, const UTF8 *literal) : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (strlen(literal)+1)*sizeof(CHAR)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(literal)); NOTHROW; GC_NOTRIGGER; } SS_CONTRACT_END; SetRepresentation(REPRESENTATION_UTF8); SS_RETURN; } inline SString::SString(tagLiteral dummytag, const WCHAR *literal) : SBuffer(Immutable, (const BYTE *) literal, (COUNT_T) (wcslen(literal)+1)*sizeof(WCHAR)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(literal)); NOTHROW; GC_NOTRIGGER; } SS_CONTRACT_END; SetRepresentation(REPRESENTATION_UNICODE); SetNormalized(); SS_RETURN; } inline SString::SString(tagLiteral dummytag, const WCHAR *literal, COUNT_T count) : SBuffer(Immutable, (const BYTE *) literal, (count + 1) * sizeof(WCHAR)) { SS_CONTRACT_VOID { SS_CONSTRUCTOR_CHECK; PRECONDITION(CheckPointer(literal)); NOTHROW; GC_NOTRIGGER; } SS_CONTRACT_END; SetRepresentation(REPRESENTATION_UNICODE); SetNormalized(); SS_RETURN; } //----------------------------------------------------------------------------- // Set this string to s // s - source string //----------------------------------------------------------------------------- inline void SString::Set(const SString &s) { SS_CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(s.Check()); SS_POSTCONDITION(Equals(s)); THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } SS_CONTRACT_END; SBuffer::Set(s); SetRepresentation(s.GetRepresentation()); ClearNormalized(); SS_RETURN; } //----------------------------------------------------------------------------- // Set this string to concatenation of s1 and s2 //----------------------------------------------------------------------------- inline void SString::Set(const SString &s1, const SString &s2) { SS_CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(s1.Check()); PRECONDITION(s2.Check()); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Preallocate(s1.GetCount() + s2.GetCount()); Set(s1); Append(s2); SS_RETURN; } //----------------------------------------------------------------------------- // Set this string to concatenation of s1, s2, and s3 //----------------------------------------------------------------------------- inline void SString::Set(const SString &s1, const SString &s2, const SString &s3) { SS_CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(s1.Check()); PRECONDITION(s2.Check()); PRECONDITION(s3.Check()); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount()); Set(s1); Append(s2); Append(s3); SS_RETURN; } //----------------------------------------------------------------------------- // Set this string to concatenation of s1, s2, s3, and s4 //----------------------------------------------------------------------------- inline void SString::Set(const SString &s1, const SString &s2, const SString &s3, const SString &s4) { SS_CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(s1.Check()); PRECONDITION(s2.Check()); PRECONDITION(s3.Check()); PRECONDITION(s4.Check()); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Preallocate(s1.GetCount() + s2.GetCount() + s3.GetCount() + s4.GetCount()); Set(s1); Append(s2); Append(s3); Append(s4); SS_RETURN; } //----------------------------------------------------------------------------- // Set this string to the substring from s. // s - the source string // start - the character to start at // length - number of characters to copy from s. //----------------------------------------------------------------------------- inline void SString::Set(const SString &s, const CIterator &i, COUNT_T count) { SS_CONTRACT_VOID { INSTANCE_CHECK; PRECONDITION(s.Check()); PRECONDITION(i.Check()); PRECONDITION(CheckCount(count)); SS_POSTCONDITION(s.Match(i, *this)); SS_POSTCONDITION(GetRawCount() == count); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; // @todo: detect case where we can reuse literal? Resize(count, s.GetRepresentation()); SBuffer::Copy(SBuffer::Begin(), i.m_ptr, count<= start); SS_POSTCONDITION(s.Match(start, *this)); SS_POSTCONDITION(GetRawCount() == (COUNT_T) (end - start)); THROWS; GC_NOTRIGGER; } SS_CONTRACT_END; Set(s, start, end - start); SS_RETURN; } // Return a global empty string inline const SString &SString::Empty() { #ifdef SSTRING_EXTRA_CHECKS CONTRACTL { // POSTCONDITION(RETVAL.IsEmpty()); PRECONDITION(CheckStartup()); NOTHROW; GC_NOTRIGGER; CANNOT_TAKE_LOCK; SUPPORTS_DAC; } CONTRACTL_END; #else STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_CANNOT_TAKE_LOCK; STATIC_CONTRACT_SUPPORTS_DAC; #endif _ASSERTE(s_Empty != NULL); // Did you call SString::Startup()? return *s_Empty; } // Get a const pointer to the internal buffer as a unicode string. inline const WCHAR *SString::GetUnicode() const { SS_CONTRACT(const WCHAR *) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckPointer(RETVAL)); if (IsRepresentation(REPRESENTATION_UNICODE)) NOTHROW; else THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } SS_CONTRACT_END; ConvertToUnicode(); SS_RETURN GetRawUnicode(); } // Get a const pointer to the internal buffer as a UTF8 string. inline const UTF8 *SString::GetUTF8() const { SS_CONTRACT(const UTF8 *) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckPointer(RETVAL)); if (IsRepresentation(REPRESENTATION_UTF8)) NOTHROW; else THROWS; GC_NOTRIGGER; SUPPORTS_DAC; } SS_CONTRACT_END; ConvertToUTF8(); SS_RETURN GetRawUTF8(); } // Normalize the string to unicode. This will make many operations nonfailing. inline void SString::Normalize() const { SS_CONTRACT_VOID { INSTANCE_CHECK; SS_POSTCONDITION(IsNormalized()); THROWS_UNLESS_NORMALIZED; GC_NOTRIGGER; } SS_CONTRACT_END; ConvertToUnicode(); SetNormalized(); SS_RETURN; } // Get a const pointer to the internal buffer as a unicode string. inline const WCHAR *SString::GetUnicode(const CIterator &i) const { SS_CONTRACT(const WCHAR *) { INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); THROWS_UNLESS_NORMALIZED; GC_NOTRIGGER; } SS_CONTRACT_END; PRECONDITION(CheckPointer(this)); ConvertToUnicode(i); SS_RETURN i.GetUnicode(); } // Append s to the end of this string. inline void SString::Append(const SString &s) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(s.Check()); THROWS; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; Insert(End(), s); SS_RETURN; } inline void SString::Append(const WCHAR *string) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckPointer(string)); THROWS; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; // Wrap the string in temporary SString without copying it SString s(SString::Literal, string); s.ClearImmutable(); Append(s); SS_RETURN; } inline void SString::AppendASCII(const CHAR *string) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckPointer(string)); THROWS; } SS_CONTRACT_END; StackSString s(SString::Ascii, string); Append(s); SS_RETURN; } inline void SString::AppendUTF8(const CHAR *string) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckPointer(string)); THROWS; } SS_CONTRACT_END; StackSString s(SString::Utf8, string); Append(s); SS_RETURN; } inline void SString::Append(const WCHAR c) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); THROWS; } SS_CONTRACT_END; InlineSString<2 * sizeof(c)> s(c); Append(s); SS_RETURN; } inline void SString::AppendUTF8(const CHAR c) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); THROWS; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; InlineSString<2 * sizeof(c)> s(SString::Utf8, c); Append(s); SS_RETURN; } // Turn this on to test that these if you are testing common scenarios dealing with // ASCII strings that do not touch the cases where this family of function differs // in behavior for expected reasons. //#define VERIFY_CRT_EQUIVALNCE 1 // Helpers for CRT function equivalance. /* static */ inline int __cdecl SString::_stricmp(const CHAR *buffer1, const CHAR *buffer2) { WRAPPER_NO_CONTRACT; int returnValue = CaseCompareHelperA(buffer1, buffer2, 0, TRUE, FALSE); #ifdef VERIFY_CRT_EQUIVALNCE _ASSERTE((returnValue == 0) == (::_stricmp(buffer1, buffer2) == 0)); #endif return returnValue; } /* static */ inline int __cdecl SString::_strnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) { WRAPPER_NO_CONTRACT; int returnValue = CaseCompareHelperA(buffer1, buffer2, count, TRUE, TRUE); #ifdef VERIFY_CRT_EQUIVALNCE _ASSERTE((returnValue == 0) == (::_strnicmp(buffer1, buffer2, count) == 0)); #endif return returnValue; } /* static */ inline int __cdecl SString::_wcsicmp(const WCHAR *buffer1, const WCHAR *buffer2) { WRAPPER_NO_CONTRACT; int returnValue = CaseCompareHelper(buffer1, buffer2, 0, TRUE, FALSE); #ifdef VERIFY_CRT_EQUIVALNCE _ASSERTE((returnValue == 0) == (::_wcsicmp(buffer1, buffer2) == 0)); #endif return returnValue; } /* static */ inline int __cdecl SString::_wcsnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) { WRAPPER_NO_CONTRACT; int returnValue = CaseCompareHelper(buffer1, buffer2, count, TRUE, TRUE); #ifdef VERIFY_CRT_EQUIVALNCE _ASSERTE((returnValue == 0) == (::_wcsnicmp(buffer1, buffer2, count) == 0)); #endif return returnValue; } inline int SString::_tstricmp(const CHAR *buffer1, const CHAR *buffer2) { return _stricmp(buffer1, buffer2); } inline int SString::_tstricmp(const WCHAR *buffer1, const WCHAR *buffer2) { return _wcsicmp(buffer1, buffer2); } inline int SString::_tstrnicmp(const CHAR *buffer1, const CHAR *buffer2, COUNT_T count) { return _strnicmp(buffer1, buffer2, count); } inline int SString::_tstrnicmp(const WCHAR *buffer1, const WCHAR *buffer2, COUNT_T count) { return _wcsnicmp(buffer1, buffer2, count); } inline BOOL SString::Match(const CIterator &i, WCHAR c) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); NOTHROW; } SS_CONTRACT_END; // End() will not throw here CONTRACT_VIOLATION(ThrowsViolation); SS_RETURN (i < End() && i[0] == c); } inline BOOL SString::Skip(CIterator &i, const SString &s) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); PRECONDITION(s.Check()); THROWS_UNLESS_BOTH_NORMALIZED(s); } SS_CONTRACT_END; if (Match(i, s)) { i += s.GetRawCount(); SS_RETURN TRUE; } else SS_RETURN FALSE; } inline BOOL SString::Skip(CIterator &i, WCHAR c) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; INSTANCE_CHECK; PRECONDITION(CheckIteratorRange(i)); NOTHROW; } SS_CONTRACT_END; if (Match(i, c)) { i++; SS_RETURN TRUE; } else SS_RETURN FALSE; } // Find string within this string. Return TRUE and update iterator if found inline BOOL SString::Find(CIterator &i, const WCHAR *string) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); SS_POSTCONDITION(RETVAL == Match(i, SString(string))); THROWS; } SS_CONTRACT_END; StackSString s(string); SS_RETURN Find(i, s); } inline BOOL SString::FindASCII(CIterator &i, const CHAR *string) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); THROWS; } SS_CONTRACT_END; StackSString s(SString::Ascii, string); SS_RETURN Find(i, s); } inline BOOL SString::FindUTF8(CIterator &i, const CHAR *string) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); THROWS; } SS_CONTRACT_END; StackSString s(SString::Utf8, string); SS_RETURN Find(i, s); } inline BOOL SString::FindBack(CIterator &i, const WCHAR *string) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); SS_POSTCONDITION(RETVAL == Match(i, SString(string))); THROWS; } SS_CONTRACT_END; StackSString s(string); SS_RETURN FindBack(i, s); } inline BOOL SString::FindBackASCII(CIterator &i, const CHAR *string) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); THROWS; } SS_CONTRACT_END; StackSString s(SString::Ascii, string); SS_RETURN FindBack(i, s); } inline BOOL SString::FindBackUTF8(CIterator &i, const CHAR *string) const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); SS_POSTCONDITION(RETVAL == Match(i, SString(SString::Ascii, string))); THROWS; } SS_CONTRACT_END; StackSString s(SString::Utf8, string); SS_RETURN FindBack(i, s); } // Insert string at iterator position inline void SString::Insert(const Iterator &i, const SString &s) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(s.Check()); THROWS; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; Replace(i, 0, s); SS_RETURN; } inline void SString::Insert(const Iterator &i, const WCHAR *string) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); THROWS; } SS_CONTRACT_END; StackSString s(string); Replace(i, 0, s); SS_RETURN; } inline void SString::InsertASCII(const Iterator &i, const CHAR *string) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); THROWS; } SS_CONTRACT_END; StackSString s(SString::Ascii, string); Replace(i, 0, s); SS_RETURN; } inline void SString::InsertUTF8(const Iterator &i, const CHAR *string) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i)); PRECONDITION(CheckPointer(string)); THROWS; } SS_CONTRACT_END; StackSString s(SString::Utf8, string); Replace(i, 0, s); SS_RETURN; } // Delete string at iterator position inline void SString::Delete(const Iterator &i, COUNT_T length) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckIteratorRange(i, length)); THROWS; SUPPORTS_DAC_HOST_ONLY; } SS_CONTRACT_END; Replace(i, length, Empty()); SS_RETURN; } // Preallocate some space for the string buffer inline void SString::Preallocate(COUNT_T characters) const { WRAPPER_NO_CONTRACT; // Assume unicode since we may get converted SBuffer::Preallocate(characters * sizeof(WCHAR)); } // Trim unused space from the buffer inline void SString::Trim() const { WRAPPER_NO_CONTRACT; if (GetRawCount() == 0) { // Share the global empty string buffer. const_cast(this)->SBuffer::SetImmutable(s_EmptyBuffer, sizeof(s_EmptyBuffer)); } else { SBuffer::Trim(); } } // RETURN true if the string is empty. inline BOOL SString::IsEmpty() const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); NOTHROW; SUPPORTS_DAC; } SS_CONTRACT_END; SS_RETURN (GetRawCount() == 0); } // RETURN true if the string rep is ASCII. inline BOOL SString::IsASCII() const { SS_CONTRACT(BOOL) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); NOTHROW; } SS_CONTRACT_END; SS_RETURN IsRepresentation(REPRESENTATION_ASCII); } // Get the number of characters in the string (excluding the terminating NULL) inline COUNT_T SString::GetCount() const { SS_CONTRACT(COUNT_T) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckCount(RETVAL)); THROWS_UNLESS_NORMALIZED; SUPPORTS_DAC; } SS_CONTRACT_END; ConvertToFixed(); SS_RETURN SizeToCount(GetSize()); } // Private helpers: // Return the current size of the string (even if it is multibyte) inline COUNT_T SString::GetRawCount() const { WRAPPER_NO_CONTRACT; return SizeToCount(GetSize()); } // Private helpers: // get string contents as a particular character set: inline ASCII *SString::GetRawASCII() const { LIMITED_METHOD_DAC_CONTRACT; return (ASCII *) m_buffer; } inline UTF8 *SString::GetRawUTF8() const { LIMITED_METHOD_DAC_CONTRACT; return (UTF8 *) m_buffer; } inline ANSI *SString::GetRawANSI() const { LIMITED_METHOD_DAC_CONTRACT; return (ANSI *) m_buffer; } inline WCHAR *SString::GetRawUnicode() const { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC_HOST_ONLY; return (WCHAR *)m_buffer; } // Private helper: // get the representation (ansi, unicode, utf8) inline SString::Representation SString::GetRepresentation() const { WRAPPER_NO_CONTRACT; return (Representation) SBuffer::GetRepresentationField(); } // Private helper. // Set the representation. inline void SString::SetRepresentation(SString::Representation representation) { #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { GC_NOTRIGGER; NOTHROW; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckRepresentation(representation)); POSTCONDITION(GetRepresentation() == representation); } CONTRACT_END; #else //SSTRING_EXTRA_CHECKS STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #endif //SSTRING_EXTRA_CHECKS SBuffer::SetRepresentationField((int) representation); SS_RETURN; } // Private helper: // Get the amount to shift the byte size to get a character count inline int SString::GetCharacterSizeShift() const { WRAPPER_NO_CONTRACT; // Note that the flag is backwards; we want the default // value to match the default representation (empty) return (GetRepresentation()&REPRESENTATION_SINGLE_MASK) == 0; } //---------------------------------------------------------------------------- // Private helper. // We know the buffer should be m_count characters. Place a null terminator // in the buffer to make our internal string null-terminated at that length. //---------------------------------------------------------------------------- FORCEINLINE void SString::NullTerminate() { SUPPORTS_DAC_HOST_ONLY; #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { POSTCONDITION(CheckPointer(this)); NOTHROW; GC_NOTRIGGER; } CONTRACT_END; #else //SSTRING_EXTRA_CHECKS STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; #endif //SSTRING_EXTRA_CHECKS BYTE *end = m_buffer + GetSize(); if (GetRepresentation()&REPRESENTATION_SINGLE_MASK) { ((CHAR *)end)[-1] = 0; } else { ((WCHAR *)end)[-1] = 0; } SS_RETURN; } //---------------------------------------------------------------------------- // private helper // Return true if the string is a literal. // A literal string has immutable memory. //---------------------------------------------------------------------------- inline BOOL SString::IsLiteral() const { WRAPPER_NO_CONTRACT; return SBuffer::IsImmutable() && (m_buffer != s_EmptyBuffer); } //---------------------------------------------------------------------------- // private helper: // RETURN true if the string allocated (and should delete) its buffer. // IsAllocated() will RETURN false for Literal strings and // stack-based strings (the buffer is on the stack) //---------------------------------------------------------------------------- inline BOOL SString::IsAllocated() const { WRAPPER_NO_CONTRACT; return SBuffer::IsAllocated(); } //---------------------------------------------------------------------------- // Return true after we call OpenBuffer(), but before we close it. // All SString operations are illegal while the buffer is open. //---------------------------------------------------------------------------- #if _DEBUG inline BOOL SString::IsBufferOpen() const { WRAPPER_NO_CONTRACT; return SBuffer::IsOpened(); } #endif //---------------------------------------------------------------------------- // Return true if we've scanned the string to see if it is in the ASCII subset. //---------------------------------------------------------------------------- inline BOOL SString::IsASCIIScanned() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return SBuffer::IsFlag1(); } //---------------------------------------------------------------------------- // Set that we've scanned the string to see if it is in the ASCII subset. //---------------------------------------------------------------------------- inline void SString::SetASCIIScanned() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC_HOST_ONLY; const_cast(this)->SBuffer::SetFlag1(); } //---------------------------------------------------------------------------- // Return true if we've normalized the string to unicode //---------------------------------------------------------------------------- inline BOOL SString::IsNormalized() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return SBuffer::IsFlag3(); } //---------------------------------------------------------------------------- // Set that we've normalized the string to unicode //---------------------------------------------------------------------------- inline void SString::SetNormalized() const { WRAPPER_NO_CONTRACT; const_cast(this)->SBuffer::SetFlag3(); } //---------------------------------------------------------------------------- // Clear normalization //---------------------------------------------------------------------------- inline void SString::ClearNormalized() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC_HOST_ONLY; const_cast(this)->SBuffer::ClearFlag3(); } //---------------------------------------------------------------------------- // Private helper. // Check to see if the string representation has single byte size //---------------------------------------------------------------------------- inline BOOL SString::IsSingleByte() const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; return ((GetRepresentation()&REPRESENTATION_SINGLE_MASK) != 0); } //---------------------------------------------------------------------------- // Private helper. // Check to see if the string representation has fixed size characters //---------------------------------------------------------------------------- inline BOOL SString::IsFixedSize() const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SUPPORTS_DAC; if (GetRepresentation()&REPRESENTATION_VARIABLE_MASK) return FALSE; else return TRUE; } //---------------------------------------------------------------------------- // Private helper. // Check to see if the string representation is appropriate for iteration //---------------------------------------------------------------------------- inline BOOL SString::IsIteratable() const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_SUPPORTS_DAC; // Note that in many cases ANSI may be fixed width. However we // currently still do not allow iterating on them, because we would have to // do character-by-character conversion on a character dereference (which must // go to unicode) . We may want to adjust this going forward to // depending on perf in the non-ASCII but fixed width ANSI case. return ((GetRepresentation()&REPRESENTATION_VARIABLE_MASK) == 0); } //---------------------------------------------------------------------------- // Private helper // Return the size of the given string in bytes // in the given representation. // count does not include the null-terminator, but the RETURN value does. //---------------------------------------------------------------------------- inline COUNT_T SString::CountToSize(COUNT_T count) const { SS_CONTRACT(COUNT_T) { GC_NOTRIGGER; PRECONDITION(CheckCount(count)); SS_POSTCONDITION(SizeToCount(RETVAL) == count); NOTHROW; SUPPORTS_DAC; } SS_CONTRACT_END; SS_RETURN (count+1) << GetCharacterSizeShift(); } //---------------------------------------------------------------------------- // Private helper. // Return the maxmimum count of characters that could fit in a buffer of // 'size' bytes in the given representation. // 'size' includes the null terminator, but the RETURN value does not. //---------------------------------------------------------------------------- inline COUNT_T SString::SizeToCount(COUNT_T size) const { SS_CONTRACT(COUNT_T) { GC_NOTRIGGER; PRECONDITION(CheckSize(size)); SS_POSTCONDITION(CountToSize(RETVAL) == size); NOTHROW; SUPPORTS_DAC; } SS_CONTRACT_END; SS_RETURN (size >> GetCharacterSizeShift()) - 1; } //---------------------------------------------------------------------------- // Private helper. // Return the maxmimum count of characters that could fit in the current // buffer including NULL terminator. //---------------------------------------------------------------------------- inline COUNT_T SString::GetBufferSizeInCharIncludeNullChar() const { STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_SUPPORTS_DAC; return (GetSize() >> GetCharacterSizeShift()); } //---------------------------------------------------------------------------- // Assert helper // Assert that the iterator is within the given string. //---------------------------------------------------------------------------- inline CHECK SString::CheckIteratorRange(const CIterator &i) const { CANNOT_HAVE_CONTRACT; CHECK(i >= Begin()); CHECK(i <= End()); // Note that it's OK to look at the terminating null CHECK_OK; } //---------------------------------------------------------------------------- // Assert helper // Assert that the iterator is within the given string. //---------------------------------------------------------------------------- inline CHECK SString::CheckIteratorRange(const CIterator &i, COUNT_T length) const { CANNOT_HAVE_CONTRACT; CHECK(i >= Begin()); CHECK(i + length <= End()); // Note that it's OK to look at the terminating null CHECK_OK; } //---------------------------------------------------------------------------- // Assert that the string is empty //---------------------------------------------------------------------------- inline CHECK SString::CheckEmpty() const { CANNOT_HAVE_CONTRACT; CHECK(IsEmpty()); CHECK_OK; } //---------------------------------------------------------------------------- // Check the range of a count //---------------------------------------------------------------------------- inline CHECK SString::CheckCount(COUNT_T count) { CANNOT_HAVE_CONTRACT; CHECK(CheckSize(count*sizeof(WCHAR))); CHECK_OK; } //---------------------------------------------------------------------------- // Check the representation field //---------------------------------------------------------------------------- inline CHECK SString::CheckRepresentation(int representation) { CANNOT_HAVE_CONTRACT; CHECK(representation == REPRESENTATION_EMPTY || representation == REPRESENTATION_UNICODE || representation == REPRESENTATION_ASCII || representation == REPRESENTATION_UTF8); CHECK((representation & REPRESENTATION_MASK) == representation); CHECK_OK; } #if CHECK_INVARIANTS //---------------------------------------------------------------------------- // Assert helper. Check that the string only uses the ASCII subset of // codes. //---------------------------------------------------------------------------- inline CHECK SString::CheckASCIIString(const CHAR *string) { CANNOT_HAVE_CONTRACT; if (string != NULL) CHECK(CheckASCIIString(string, (int) strlen(string))); CHECK_OK; } inline CHECK SString::CheckASCIIString(const CHAR *string, COUNT_T count) { CANNOT_HAVE_CONTRACT; #if _DEBUG const CHAR *sEnd = string + count; while (string < sEnd) { CHECK_MSG((*string & 0x80) == 0x00, "Found non-ASCII character in string."); string++; } #endif CHECK_OK; } //---------------------------------------------------------------------------- // Check routine and invariants. //---------------------------------------------------------------------------- inline CHECK SString::Check() const { CANNOT_HAVE_CONTRACT; CHECK(SBuffer::Check()); CHECK_OK; } inline CHECK SString::Invariant() const { CANNOT_HAVE_CONTRACT; CHECK(SBuffer::Invariant()); CHECK_OK; } inline CHECK SString::InternalInvariant() const { CANNOT_HAVE_CONTRACT; CHECK(SBuffer::InternalInvariant()); CHECK(SBuffer::GetSize() >= 2); if (IsNormalized()) CHECK(IsRepresentation(REPRESENTATION_UNICODE)); CHECK_OK; } #endif // CHECK_INVARIANTS //---------------------------------------------------------------------------- // Return a writeable buffer that can store 'countChars'+1 unicode characters. // Call CloseBuffer when done. //---------------------------------------------------------------------------- inline WCHAR *SString::OpenUnicodeBuffer(COUNT_T countChars) { SS_CONTRACT(WCHAR*) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckCount(countChars)); #if _DEBUG SS_POSTCONDITION(IsBufferOpen()); #endif SS_POSTCONDITION(GetRawCount() == countChars); SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_UNICODE || countChars == 0); SS_POSTCONDITION(CheckPointer(RETVAL)); THROWS; } SS_CONTRACT_END; OpenBuffer(REPRESENTATION_UNICODE, countChars); SS_RETURN GetRawUnicode(); } //---------------------------------------------------------------------------- // Return a copy of the underlying buffer, the caller is responsible for managing // the returned memory //---------------------------------------------------------------------------- inline WCHAR *SString::GetCopyOfUnicodeString() { SS_CONTRACT(WCHAR*) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckPointer(buffer)); THROWS; } SS_CONTRACT_END; NewArrayHolder buffer = NULL; buffer = new WCHAR[GetCount() +1]; wcscpy_s(buffer, GetCount() + 1, GetUnicode()); SS_RETURN buffer.Extract(); } //---------------------------------------------------------------------------- // Return a writeable buffer that can store 'countChars'+1 ansi characters. // Call CloseBuffer when done. //---------------------------------------------------------------------------- inline UTF8 *SString::OpenUTF8Buffer(COUNT_T countBytes) { SS_CONTRACT(UTF8*) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION(CheckCount(countBytes)); #if _DEBUG SS_POSTCONDITION(IsBufferOpen()); #endif SS_POSTCONDITION(GetRawCount() == countBytes); SS_POSTCONDITION(GetRepresentation() == REPRESENTATION_UTF8 || countBytes == 0); SS_POSTCONDITION(CheckPointer(RETVAL)); THROWS; } SS_CONTRACT_END; OpenBuffer(REPRESENTATION_UTF8, countBytes); SS_RETURN GetRawUTF8(); } //---------------------------------------------------------------------------- // Private helper to open a raw buffer. // Called by public functions to open the buffer in the specific // representation. // While the buffer is opened, all other operations are illegal. Call // CloseBuffer() when done. //---------------------------------------------------------------------------- inline void SString::OpenBuffer(SString::Representation representation, COUNT_T countChars) { #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); PRECONDITION_MSG(!IsBufferOpen(), "Can't nest calls to OpenBuffer()"); PRECONDITION(CheckRepresentation(representation)); PRECONDITION(CheckSize(countChars)); #if _DEBUG POSTCONDITION(IsBufferOpen()); #endif POSTCONDITION(GetRawCount() == countChars); POSTCONDITION(GetRepresentation() == representation || countChars == 0); THROWS; } CONTRACT_END; #else STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_THROWS; #endif Resize(countChars, representation); SBuffer::OpenRawBuffer(CountToSize(countChars)); SS_RETURN; } //---------------------------------------------------------------------------- // Get the max size that can be passed to OpenUnicodeBuffer without causing // allocations. //---------------------------------------------------------------------------- inline COUNT_T SString::GetUnicodeAllocation() { CONTRACTL { INSTANCE_CHECK; NOTHROW; GC_NOTRIGGER; } CONTRACTL_END; COUNT_T allocation = GetAllocation(); return ( (allocation > sizeof(WCHAR)) ? (allocation - sizeof(WCHAR)) / sizeof(WCHAR) : 0 ); } //---------------------------------------------------------------------------- // Close an open buffer. Assumes that we wrote exactly number of characters // we requested in OpenBuffer. //---------------------------------------------------------------------------- inline void SString::CloseBuffer() { SS_CONTRACT_VOID { GC_NOTRIGGER; #if _DEBUG PRECONDITION_MSG(IsBufferOpen(), "Can only CloseBuffer() after a call to OpenBuffer()"); #endif SS_POSTCONDITION(CheckPointer(this)); THROWS; } SS_CONTRACT_END; SBuffer::CloseRawBuffer(); NullTerminate(); SS_RETURN; } //---------------------------------------------------------------------------- // CloseBuffer() tells the SString that we're done using the unsafe buffer. // countChars is the count of characters actually used (so we can set m_count). // This is important if we request a buffer larger than what we actually // used. //---------------------------------------------------------------------------- inline void SString::CloseBuffer(COUNT_T finalCount) { SS_CONTRACT_VOID { GC_NOTRIGGER; #if _DEBUG PRECONDITION_MSG(IsBufferOpen(), "Can only CloseBuffer() after a call to OpenBuffer()"); #endif PRECONDITION(CheckSize(finalCount)); SS_POSTCONDITION(CheckPointer(this)); SS_POSTCONDITION(GetRawCount() == finalCount); THROWS; } SS_CONTRACT_END; SBuffer::CloseRawBuffer(CountToSize(finalCount)); NullTerminate(); SS_RETURN; } //---------------------------------------------------------------------------- // EnsureWritable // Ensures that the buffer is writable //---------------------------------------------------------------------------- inline void SString::EnsureWritable() const { #ifdef SSTRING_EXTRA_CHECKS CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); POSTCONDITION(!IsLiteral()); THROWS; } CONTRACT_END; #else //SSTRING_EXTRA_CHECKS STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_THROWS; #endif //SSTRING_EXTRA_CHECKS if (IsLiteral()) const_cast(this)->Resize(GetRawCount(), GetRepresentation(), PRESERVE); SS_RETURN; } //----------------------------------------------------------------------------- // Convert the internal representation to be a fixed size //----------------------------------------------------------------------------- inline void SString::ConvertToFixed() const { SS_CONTRACT_VOID { GC_NOTRIGGER; SS_PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(IsFixedSize()); THROWS_UNLESS_NORMALIZED; SUPPORTS_DAC; } SS_CONTRACT_END; // If we're already fixed size, great. if (IsFixedSize()) SS_RETURN; // See if we can coerce it to ASCII. if (ScanASCII()) SS_RETURN; // Convert to unicode then. ConvertToUnicode(); SS_RETURN; } //----------------------------------------------------------------------------- // Convert the internal representation to be an iteratable one (current // requirements here are that it be trivially convertible to unicode chars.) //----------------------------------------------------------------------------- inline void SString::ConvertToIteratable() const { SS_CONTRACT_VOID { GC_NOTRIGGER; SS_PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(IsIteratable()); THROWS_UNLESS_NORMALIZED; SUPPORTS_DAC; } SS_CONTRACT_END; // If we're already iteratable, great. if (IsIteratable()) SS_RETURN; // See if we can coerce it to ASCII. if (ScanASCII()) SS_RETURN; // Convert to unicode then. ConvertToUnicode(); SS_RETURN; } //----------------------------------------------------------------------------- // Create CIterators on the string. //----------------------------------------------------------------------------- FORCEINLINE SString::CIterator SString::Begin() const { SS_CONTRACT(SString::CIterator) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckValue(RETVAL)); THROWS_UNLESS_NORMALIZED; } SS_CONTRACT_END; ConvertToIteratable(); SS_RETURN CIterator(this, 0); } FORCEINLINE SString::CIterator SString::End() const { SS_CONTRACT(SString::CIterator) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckValue(RETVAL)); THROWS_UNLESS_NORMALIZED; } SS_CONTRACT_END; ConvertToIteratable(); SS_RETURN CIterator(this, GetCount()); } //----------------------------------------------------------------------------- // Create Iterators on the string. //----------------------------------------------------------------------------- FORCEINLINE SString::Iterator SString::Begin() { SS_CONTRACT(SString::Iterator) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckValue(RETVAL)); THROWS; // EnsureMutable always throws SUPPORTS_DAC; } SS_CONTRACT_END; ConvertToIteratable(); EnsureMutable(); SS_RETURN Iterator(this, 0); } FORCEINLINE SString::Iterator SString::End() { SS_CONTRACT(SString::Iterator) { GC_NOTRIGGER; PRECONDITION(CheckPointer(this)); SS_POSTCONDITION(CheckValue(RETVAL)); THROWS; // EnsureMutable always Throws SUPPORTS_DAC; } SS_CONTRACT_END; ConvertToIteratable(); EnsureMutable(); SS_RETURN Iterator(this, GetCount()); } //----------------------------------------------------------------------------- // CIterator support routines //----------------------------------------------------------------------------- inline SString::Index::Index() { LIMITED_METHOD_CONTRACT; } inline SString::Index::Index(SString *string, SCOUNT_T index) : SBuffer::Index(string, index<GetCharacterSizeShift()) { SS_CONTRACT_VOID { GC_NOTRIGGER; PRECONDITION(CheckPointer(string)); PRECONDITION(string->IsIteratable()); PRECONDITION(DoCheck(0)); SS_POSTCONDITION(CheckPointer(this)); // POSTCONDITION(Subtract(string->Begin()) == index); contract violation - fix later NOTHROW; CANNOT_TAKE_LOCK; SUPPORTS_DAC; } SS_CONTRACT_END; m_characterSizeShift = string->GetCharacterSizeShift(); SS_RETURN; } inline BYTE &SString::Index::GetAt(SCOUNT_T delta) const { LIMITED_METHOD_DAC_CONTRACT; return m_ptr[delta<>m_characterSizeShift); } inline CHECK SString::Index::DoCheck(SCOUNT_T delta) const { CANNOT_HAVE_CONTRACT; #if _DEBUG const SString *string = (const SString *) GetContainerDebug(); CHECK(m_ptr + (delta<= string->m_buffer); CHECK(m_ptr + (delta<m_buffer + string->GetSize()); #endif CHECK_OK; } inline void SString::Index::Resync(const SString *string, BYTE *ptr) const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; SBuffer::Index::Resync(string, ptr); const_cast(this)->m_characterSizeShift = string->GetCharacterSizeShift(); } inline const WCHAR *SString::Index::GetUnicode() const { LIMITED_METHOD_CONTRACT; return (const WCHAR *) m_ptr; } inline const CHAR *SString::Index::GetASCII() const { LIMITED_METHOD_CONTRACT; return (const CHAR *) m_ptr; } inline WCHAR SString::Index::operator*() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; if (m_characterSizeShift == 0) return *(CHAR*)&GetAt(0); else return *(WCHAR*)&GetAt(0); } inline void SString::Index::operator->() const { LIMITED_METHOD_CONTRACT; } inline WCHAR SString::Index::operator[](int index) const { WRAPPER_NO_CONTRACT; if (m_characterSizeShift == 0) return *(CHAR*)&GetAt(index); else return *(WCHAR*)&GetAt(index); } #ifdef _MSC_VER #pragma warning(pop) #endif // _MSC_VER #endif // _SSTRING_INL_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stack.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // This is a generic growable stack of T. #ifndef GENERIC_STACK_H #define GENERIC_STACK_H 1 #include template class Stack { T* m_elems; unsigned m_elemsSize; unsigned m_elemsCount; static const unsigned InitSize = 8; void GrowForPush() { if (m_elemsCount == m_elemsSize) { m_elemsSize = max(InitSize, 2*m_elemsSize); T* newElems = new T[m_elemsSize]; if (m_elemsCount != 0) { _ASSERTE(m_elems != NULL); for (unsigned k = 0; k < m_elemsCount; k++) newElems[k] = m_elems[k]; delete[] m_elems; } m_elems = newElems; } } public: Stack(unsigned sz = 0) : m_elems(NULL), m_elemsSize(sz), m_elemsCount(0) { if (sz > 0) { m_elems = new T[sz]; } } ~Stack() { if (m_elems != NULL) delete[] m_elems; } void Push(T t) { GrowForPush(); m_elems[m_elemsCount] = t; m_elemsCount++; } bool IsEmpty() { return m_elemsCount == 0; } T Pop() { _ASSERTE(m_elemsCount > 0); m_elemsCount--; return m_elems[m_elemsCount]; } T Peek() { _ASSERTE(m_elemsCount > 0); return m_elems[m_elemsCount-1]; } // Caller should take care to only side-effect the return reference if they are *sure* // that the stack will not be popped in the interim! T& PeekRef() { _ASSERTE(m_elemsCount > 0); return m_elems[m_elemsCount-1]; } }; #endif // GENERIC_STACK_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stackframe.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __STACKFRAME_H #define __STACKFRAME_H #include "regdisp.h" struct StackFrame { const static UINT_PTR maxVal = (UINT_PTR)(INT_PTR)-1; StackFrame() : SP(NULL) { } StackFrame(UINT_PTR sp) { SP = sp; } void Clear() { SP = NULL; } void SetMaxVal() { SP = maxVal; } bool IsNull() { return (SP == NULL); } bool IsMaxVal() { return (SP == maxVal); } bool operator==(StackFrame sf) { return (SP == sf.SP); } bool operator!=(StackFrame sf) { return (SP != sf.SP); } bool operator<(StackFrame sf) { return (SP < sf.SP); } bool operator<=(StackFrame sf) { return (SP <= sf.SP); } bool operator>(StackFrame sf) { return (SP > sf.SP); } bool operator>=(StackFrame sf) { return (SP >= sf.SP); } static inline StackFrame FromEstablisherFrame(UINT_PTR EstablisherFrame) { return StackFrame(EstablisherFrame); } static inline StackFrame FromRegDisplay(REGDISPLAY* pRD) { return StackFrame(GetRegdisplaySP(pRD)); } UINT_PTR SP; }; //--------------------------------------------------------------------------------------- // // On WIN64, all the stack range tracking done by the Exception Handling (EH) subsystem is based on the // establisher frame given by the OS. On IA64, the establisher frame is the caller SP and the current BSP. // On X64, it is the initial SP before any dynamic stack allocation, i.e. it is the SP when a function exits // the prolog. The EH subsystem uses the same format. // // The stackwalker needs to get information from the EH subsystem in order to skip funclets. Unfortunately, // stackwalking is based on the current SP, i.e. the SP when the control flow leaves a function via a // function call. Thus, for stack frames with dynamic stack allocations on X64, the SP values used by the // stackwalker and the EH subsystem don't match. // // To work around this problem, we need to somehow bridge the different SP values. We do so by using the // caller SP instead of the current SP for comparisons during a stackwalk on X64. Creating a new type // explicitly spells out the important distinction that this is NOT in the same format as the // OS establisher frame. // // Notes: // In the long term, we should look at merging the two SP formats and have one consistent abstraction. // struct CallerStackFrame : StackFrame { CallerStackFrame() : StackFrame() { } CallerStackFrame(UINT_PTR sp) : StackFrame(sp) { } #ifdef FEATURE_EH_FUNCLETS static inline CallerStackFrame FromRegDisplay(REGDISPLAY* pRD) { _ASSERTE(pRD->IsCallerSPValid || pRD->IsCallerContextValid); return CallerStackFrame(GetSP(pRD->pCallerContext)); } #endif // FEATURE_EH_FUNCLETS }; #endif // __STACKFRAME_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stacktrace.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- #ifndef __STACK_TRACE_H__ #define __STACK_TRACE_H__ HINSTANCE LoadImageHlp(); HINSTANCE LoadDbgHelp(); #include // //--- Constants --------------------------------------------------------------- // #define cchMaxAssertModuleLen 60 #define cchMaxAssertSymbolLen 257 #define cfrMaxAssertStackLevels 20 #define cchMaxAssertExprLen 257 #ifdef HOST_64BIT #define cchMaxAssertStackLevelStringLen \ ((3 * 8) + cchMaxAssertModuleLen + cchMaxAssertSymbolLen + 13) // 3 addresses of at most 8 char, module, symbol, and the extra chars: // 0x
: ! + 0x\n //FMT_ADDR_BARE is defined as "%08x`%08x" on Win64, and as //"%08x" on 32 bit platforms. Hence the difference in the definitions. #else #define cchMaxAssertStackLevelStringLen \ ((2 * 8) + cchMaxAssertModuleLen + cchMaxAssertSymbolLen + 12) // 2 addresses of at most 8 char, module, symbol, and the extra chars: // 0x
: ! + 0x\n #endif // //--- Prototypes -------------------------------------------------------------- // /**************************************************************************** * MagicDeinit * *-------------* * Description: * Cleans up for the symbol loading code. Should be called before * exiting in order to free the dynamically loaded imagehlp.dll ******************************************************************** robch */ void MagicDeinit(void); /**************************************************************************** * GetStringFromStackLevels * *--------------------------* * Description: * Retrieves a string from the stack frame. If more than one frame, they * are separated by newlines. Each fram appears in this format: * * 0x
: ! + 0x ******************************************************************** robch */ void GetStringFromStackLevels(UINT ifrStart, UINT cfrTotal, _Out_writes_(cchMaxAssertStackLevelStringLen * cfrTotal) CHAR *pszString, struct _CONTEXT * pContext = NULL); /**************************************************************************** * GetStringFromAddr * *-------------------* * Description: * Builds a string from an address in the format: * * 0x
: ! + 0x ******************************************************************** robch */ void GetStringFromAddr(DWORD_PTR dwAddr, _Out_writes_(cchMaxAssertStackLevelStringLen) LPSTR szString); #if defined(HOST_X86) && !defined(TARGET_UNIX) /**************************************************************************** * ClrCaptureContext * *-------------------* * Description: * Exactly the contents of RtlCaptureContext for Win7 - Win2K doesn't * support this, so we need it for CoreCLR 4, if we require Win2K support ****************************************************************************/ extern "C" void __stdcall ClrCaptureContext(_Out_ PCONTEXT ctx); #else // HOST_X86 && !TARGET_UNIX #define ClrCaptureContext RtlCaptureContext #endif // HOST_X86 && !TARGET_UNIX #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/static_assert.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // static_assert.h // // Static assertion infrastructure // --------------------------------------------------------------------------- //-------------------------------------------------------------------------------- // static_assert represents a check which should be made at compile time. It // can only be done on a constant expression. //-------------------------------------------------------------------------------- #ifndef __STATIC_ASSERT_H__ #define __STATIC_ASSERT_H__ // Replaces previous uses of C_ASSERT and COMPILE_TIME_ASSERT #define static_assert_no_msg( cond ) static_assert( cond, #cond ) #endif // __STATIC_ASSERT_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/staticcontract.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // StaticContract.h // --------------------------------------------------------------------------- #ifndef __STATIC_CONTRACT_H_ #define __STATIC_CONTRACT_H_ // Make sure we have the WCHAR defines available. #include "palclr.h" #define SCAN_WIDEN2(x) L ## x #define SCAN_WIDEN(x) SCAN_WIDEN2(x) #ifndef NOINLINE #if __GNUC__ #define NOINLINE __attribute__((noinline)) #else #define NOINLINE __declspec(noinline) #endif #endif // // PDB annotations for the static contract analysis tool. These are separated // from Contract.h to allow their inclusion in any part of the system. // #if defined(_DEBUG) && defined(TARGET_X86) #define METHOD_CANNOT_BE_FOLDED_DEBUG \ static int _noFold = 0; \ _noFold++; #else #define METHOD_CANNOT_BE_FOLDED_DEBUG #endif #ifdef TARGET_X86 // // currently, only x86 has a static contract analysis tool, so let's not // bloat the PDBs of all the other architectures too.. // #define ANNOTATION_TRY_BEGIN __annotation(W("TRY_BEGIN")) #define ANNOTATION_TRY_END __annotation(W("TRY_END")) #define ANNOTATION_HANDLER_BEGIN __annotation(W("HANDLER_BEGIN")) #define ANNOTATION_HANDLER_END __annotation(W("HANDLER_END")) #define ANNOTATION_NOTHROW __annotation(W("NOTHROW")) #define ANNOTATION_CANNOT_TAKE_LOCK __annotation(W("CANNOT_TAKE_LOCK")) #define ANNOTATION_WRAPPER __annotation(W("WRAPPER")) #define ANNOTATION_FAULT __annotation(W("FAULT")) #define ANNOTATION_FORBID_FAULT __annotation(W("FORBID_FAULT")) #define ANNOTATION_COOPERATIVE __annotation(W("MODE_COOPERATIVE")) #define ANNOTATION_MODE_COOPERATIVE __annotation(W("MODE_PREEMPTIVE")) #define ANNOTATION_MODE_ANY __annotation(W("MODE_ANY")) #define ANNOTATION_GC_TRIGGERS __annotation(W("GC_TRIGGERS")) #define ANNOTATION_IGNORE_THROW __annotation(W("THROWS"), W("NOTHROW"), W("CONDITIONAL_EXEMPT")) #define ANNOTATION_IGNORE_LOCK __annotation(W("CAN_TAKE_LOCK"), W("CANNOT_TAKE_LOCK"), W("CONDITIONAL_EXEMPT")) #define ANNOTATION_IGNORE_FAULT __annotation(W("FAULT"), W("FORBID_FAULT"), W("CONDITIONAL_EXEMPT")) #define ANNOTATION_IGNORE_TRIGGER __annotation(W("GC_TRIGGERS"), W("GC_NOTRIGGER"), W("CONDITIONAL_EXEMPT")) #define ANNOTATION_VIOLATION(violationmask) __annotation(W("VIOLATION(") L#violationmask W(")")) #define ANNOTATION_UNCHECKED(thecheck) __annotation(W("UNCHECKED(") L#thecheck W(")")) #define ANNOTATION_MARK_BLOCK_ANNOTATION __annotation(W("MARK")) #define ANNOTATION_USE_BLOCK_ANNOTATION __annotation(W("USE")) #define ANNOTATION_END_USE_BLOCK_ANNOTATION __annotation(W("END_USE")) // here is the plan: // // a special holder which implements a violation // #define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN __annotation(W("SPECIAL_HOLDER_BEGIN ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_SPECIAL_HOLDER_END __annotation(W("SPECIAL_HOLDER_END")) #define ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT __annotation(W("SPECIAL_HOLDER_DYNAMIC")) #define ANNOTATION_SO_PROBE_BEGIN(probeAmount) __annotation(W("SO_PROBE_BEGIN(") L#probeAmount W(")")) #define ANNOTATION_SO_PROBE_END __annotation(W("SO_PROBE_END")) // // these annotations are all function-name qualified // #define ANNOTATION_FN_LEAF __annotation(W("LEAF ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_WRAPPER __annotation(W("WRAPPER ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_THROWS __annotation(W("THROWS ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_NOTHROW __annotation(W("NOTHROW ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_CAN_TAKE_LOCK __annotation(W("CAN_TAKE_LOCK ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_CANNOT_TAKE_LOCK __annotation(W("CANNOT_TAKE_LOCK ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_FAULT __annotation(W("FAULT ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_FORBID_FAULT __annotation(W("FORBID_FAULT ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_GC_TRIGGERS __annotation(W("GC_TRIGGERS ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_GC_NOTRIGGER __annotation(W("GC_NOTRIGGER ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_MODE_COOPERATIVE __annotation(W("MODE_COOPERATIVE ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_MODE_PREEMPTIVE __annotation(W("MODE_PREEMPTIVE ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_MODE_ANY __annotation(W("MODE_ANY ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_HOST_NOCALLS __annotation(W("HOST_NOCALLS ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_FN_HOST_CALLS __annotation(W("HOST_CALLS ") SCAN_WIDEN(__FUNCTION__)) #define ANNOTATION_ENTRY_POINT __annotation(W("SO_EP ") SCAN_WIDEN(__FUNCTION__)) // for DacCop #define ANNOTATION_SUPPORTS_DAC __annotation(W("SUPPORTS_DAC")) #define ANNOTATION_SUPPORTS_DAC_HOST_ONLY __annotation(W("SUPPORTS_DAC_HOST_ONLY")) #ifdef _DEBUG // @todo : put correct annotation in and fixup the static analysis tool // This is used to flag debug-only functions that we want to ignore in our static analysis #define ANNOTATION_DEBUG_ONLY __annotation(W("DBG_ONLY")) #endif #else // TARGET_X86 #define ANNOTATION_TRY_BEGIN { } #define ANNOTATION_TRY_END { } #define ANNOTATION_HANDLER_BEGIN { } #define ANNOTATION_HANDLER_END { } #define ANNOTATION_NOTHROW { } #define ANNOTATION_CANNOT_TAKE_LOCK { } #define ANNOTATION_WRAPPER { } #define ANNOTATION_FAULT { } #define ANNOTATION_FORBID_FAULT { } #define ANNOTATION_COOPERATIVE { } #define ANNOTATION_MODE_COOPERATIVE { } #define ANNOTATION_MODE_ANY { } #define ANNOTATION_GC_TRIGGERS { } #define ANNOTATION_IGNORE_THROW { } #define ANNOTATION_IGNORE_LOCK { } #define ANNOTATION_IGNORE_FAULT { } #define ANNOTATION_IGNORE_TRIGGER { } #define ANNOTATION_VIOLATION(violationmask) { } #define ANNOTATION_UNCHECKED(thecheck) { } #define ANNOTATION_TRY_MARKER { } #define ANNOTATION_CATCH_MARKER { } #define ANNOTATION_FN_HOST_NOCALLS { } #define ANNOTATION_FN_HOST_CALLS { } #define ANNOTATION_FN_SPECIAL_HOLDER_BEGIN { } #define ANNOTATION_SPECIAL_HOLDER_END { } #define ANNOTATION_SPECIAL_HOLDER_CALLER_NEEDS_DYNAMIC_CONTRACT { } #define ANNOTATION_FN_LEAF { } #define ANNOTATION_FN_WRAPPER { } #define ANNOTATION_FN_THROWS { } #define ANNOTATION_FN_NOTHROW { } #define ANNOTATION_FN_CAN_TAKE_LOCK { } #define ANNOTATION_FN_CANNOT_TAKE_LOCK { } #define ANNOTATION_FN_FAULT { } #define ANNOTATION_FN_FORBID_FAULT { } #define ANNOTATION_FN_GC_TRIGGERS { } #define ANNOTATION_FN_GC_NOTRIGGER { } #define ANNOTATION_FN_MODE_COOPERATIVE { } #define ANNOTATION_FN_MODE_PREEMPTIVE { } #define ANNOTATION_FN_MODE_ANY { } #define ANNOTATION_FN_HOST_NOCALLS { } #define ANNOTATION_FN_HOST_CALLS { } #define ANNOTATION_SUPPORTS_DAC { } #define ANNOTATION_SUPPORTS_DAC_HOST_ONLY { } #define ANNOTATION_SO_PROBE_BEGIN(probeAmount) { } #define ANNOTATION_SO_PROBE_END { } #define ANNOTATION_ENTRY_POINT { } #ifdef _DEBUG #define ANNOTATION_DEBUG_ONLY { } #endif #endif // TARGET_X86 #define STATIC_CONTRACT_THROWS ANNOTATION_FN_THROWS #define STATIC_CONTRACT_NOTHROW ANNOTATION_FN_NOTHROW #define STATIC_CONTRACT_CAN_TAKE_LOCK ANNOTATION_FN_CAN_TAKE_LOCK #define STATIC_CONTRACT_CANNOT_TAKE_LOCK ANNOTATION_FN_CANNOT_TAKE_LOCK #define STATIC_CONTRACT_FAULT ANNOTATION_FN_FAULT #define STATIC_CONTRACT_FORBID_FAULT ANNOTATION_FN_FORBID_FAULT #define STATIC_CONTRACT_GC_TRIGGERS ANNOTATION_FN_GC_TRIGGERS #define STATIC_CONTRACT_GC_NOTRIGGER ANNOTATION_FN_GC_NOTRIGGER #define STATIC_CONTRACT_HOST_NOCALLS ANNOTATION_FN_HOST_NOCALLS #define STATIC_CONTRACT_HOST_CALLS ANNOTATION_FN_HOST_CALLS #define STATIC_CONTRACT_SUPPORTS_DAC ANNOTATION_SUPPORTS_DAC #define STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY ANNOTATION_SUPPORTS_DAC_HOST_ONLY #define STATIC_CONTRACT_MODE_COOPERATIVE ANNOTATION_FN_MODE_COOPERATIVE #define STATIC_CONTRACT_MODE_PREEMPTIVE ANNOTATION_FN_MODE_PREEMPTIVE #define STATIC_CONTRACT_MODE_ANY ANNOTATION_FN_MODE_ANY #define STATIC_CONTRACT_LEAF ANNOTATION_FN_LEAF #define STATIC_CONTRACT_LIMITED_METHOD ANNOTATION_FN_LEAF #define STATIC_CONTRACT_WRAPPER ANNOTATION_FN_WRAPPER #define STATIC_CONTRACT_ENTRY_POINT #ifdef _DEBUG #define STATIC_CONTRACT_DEBUG_ONLY \ ANNOTATION_DEBUG_ONLY; \ STATIC_CONTRACT_CANNOT_TAKE_LOCK; \ ANNOTATION_VIOLATION(TakesLockViolation); #else #define STATIC_CONTRACT_DEBUG_ONLY #endif #define STATIC_CONTRACT_VIOLATION(mask) \ ANNOTATION_VIOLATION(mask) #define SCAN_SCOPE_BEGIN \ METHOD_CANNOT_BE_FOLDED_DEBUG; \ ANNOTATION_FN_SPECIAL_HOLDER_BEGIN; #define SCAN_SCOPE_END \ METHOD_CANNOT_BE_FOLDED_DEBUG; \ ANNOTATION_SPECIAL_HOLDER_END; namespace StaticContract { struct ScanThrowMarkerStandard { NOINLINE ScanThrowMarkerStandard() { METHOD_CANNOT_BE_FOLDED_DEBUG; STATIC_CONTRACT_THROWS; STATIC_CONTRACT_GC_NOTRIGGER; } static void used() { } }; struct ScanThrowMarkerTerminal { NOINLINE ScanThrowMarkerTerminal() { METHOD_CANNOT_BE_FOLDED_DEBUG; } static void used() { } }; struct ScanThrowMarkerIgnore { NOINLINE ScanThrowMarkerIgnore() { METHOD_CANNOT_BE_FOLDED_DEBUG; } static void used() { } }; } typedef StaticContract::ScanThrowMarkerStandard ScanThrowMarker; // This is used to annotate code as throwing a terminal exception, and should // be used immediately before the throw so that infer that it can be inferred // that the block in which this annotation appears throws unconditionally. #define SCAN_THROW_MARKER do { ScanThrowMarker __throw_marker; } while (0) #define SCAN_IGNORE_THROW_MARKER \ typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker; if (0) ScanThrowMarker::used(); // Terminal exceptions are asynchronous and cannot be included in THROWS contract // analysis. As such, this uses typedef to reassign the ScanThrowMarker to a // non-annotating struct so that SCAN does not see the block as throwing. #define STATIC_CONTRACT_THROWS_TERMINAL \ typedef StaticContract::ScanThrowMarkerTerminal ScanThrowMarker; if (0) ScanThrowMarker::used(); #ifdef _MSC_VER #define SCAN_IGNORE_THROW typedef StaticContract::ScanThrowMarkerIgnore ScanThrowMarker; ANNOTATION_IGNORE_THROW #define SCAN_IGNORE_LOCK ANNOTATION_IGNORE_LOCK #define SCAN_IGNORE_FAULT ANNOTATION_IGNORE_FAULT #define SCAN_IGNORE_TRIGGER ANNOTATION_IGNORE_TRIGGER #else #define SCAN_IGNORE_THROW #define SCAN_IGNORE_LOCK #define SCAN_IGNORE_FAULT #define SCAN_IGNORE_TRIGGER #endif // we use BlockMarker's only for SCAN #if defined(_DEBUG) && defined(TARGET_X86) && !defined(DACCESS_COMPILE) template class BlockMarker { public: NOINLINE void MarkBlock() { ANNOTATION_MARK_BLOCK_ANNOTATION; METHOD_CANNOT_BE_FOLDED_DEBUG; return; } NOINLINE void UseMarkedBlockAnnotation() { ANNOTATION_USE_BLOCK_ANNOTATION; METHOD_CANNOT_BE_FOLDED_DEBUG; return; } NOINLINE void EndUseMarkedBlockAnnotation() { ANNOTATION_END_USE_BLOCK_ANNOTATION; METHOD_CANNOT_BE_FOLDED_DEBUG; return; } }; #define SCAN_BLOCKMARKER() BlockMarker<__COUNTER__> __blockMarker_onlyOneAllowedPerScope #define SCAN_BLOCKMARKER_MARK() __blockMarker_onlyOneAllowedPerScope.MarkBlock() #define SCAN_BLOCKMARKER_USE() __blockMarker_onlyOneAllowedPerScope.UseMarkedBlockAnnotation() #define SCAN_BLOCKMARKER_END_USE() __blockMarker_onlyOneAllowedPerScope.EndUseMarkedBlockAnnotation() #define SCAN_BLOCKMARKER_N(num) BlockMarker<__COUNTER__> __blockMarker_onlyOneAllowedPerScope##num #define SCAN_BLOCKMARKER_MARK_N(num) __blockMarker_onlyOneAllowedPerScope##num.MarkBlock() #define SCAN_BLOCKMARKER_USE_N(num) __blockMarker_onlyOneAllowedPerScope##num.UseMarkedBlockAnnotation() #define SCAN_BLOCKMARKER_END_USE_N(num) __blockMarker_onlyOneAllowedPerScope##num.EndUseMarkedBlockAnnotation() #define SCAN_EHMARKER() BlockMarker<__COUNTER__> __marker_onlyOneAllowedPerScope #define SCAN_EHMARKER_TRY() __annotation(W("SCOPE(BLOCK);SCAN_TRY_BEGIN")); __marker_onlyOneAllowedPerScope.MarkBlock() #define SCAN_EHMARKER_END_TRY() __annotation(W("SCOPE(BLOCK);SCAN_TRY_END")) #define SCAN_EHMARKER_CATCH() __marker_onlyOneAllowedPerScope.UseMarkedBlockAnnotation() #define SCAN_EHMARKER_END_CATCH() __marker_onlyOneAllowedPerScope.EndUseMarkedBlockAnnotation() #else #define SCAN_BLOCKMARKER() #define SCAN_BLOCKMARKER_MARK() #define SCAN_BLOCKMARKER_USE() #define SCAN_BLOCKMARKER_END_USE() #define SCAN_BLOCKMARKER_N(num) #define SCAN_BLOCKMARKER_MARK_N(num) #define SCAN_BLOCKMARKER_USE_N(num) #define SCAN_BLOCKMARKER_END_USE_N(num) #define SCAN_EHMARKER() #define SCAN_EHMARKER_TRY() #define SCAN_EHMARKER_END_TRY() #define SCAN_EHMARKER_CATCH() #define SCAN_EHMARKER_END_CATCH() #endif // // @todo remove this... if there really are cases where a function just shouldn't have a contract, then perhaps // we can add a more descriptive name for it... // #define CANNOT_HAVE_CONTRACT __annotation(W("NO_CONTRACT")) #endif // __STATIC_CONTRACT_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stdmacros.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // common.h - precompiled headers include for the COM+ Execution Engine // // // Make sure _ASSERTE is defined before including this header file // Other than that, please keep this header self-contained so that it can be included in // all dlls // #ifndef _stdmacros_h_ #define _stdmacros_h_ #include "specstrings.h" #include "contract.h" #ifndef _ASSERTE #error Please define _ASSERTE before including StdMacros.h #endif #ifdef _DEBUG #define DEBUG_ARG(x) , x #define DEBUG_ARG1(x) x #else #define DEBUG_ARG(x) #define DEBUG_ARG1(x) #endif #ifdef DACCESS_COMPILE #define DAC_ARG(x) , x #else #define DAC_ARG(x) #endif /********************************************/ /* Portability macros */ /********************************************/ #ifdef TARGET_AMD64 #define AMD64_FIRST_ARG(x) x , #define AMD64_ARG(x) , x #define AMD64_ONLY(x) x #define NOT_AMD64(x) #define NOT_AMD64_ARG(x) #else #define AMD64_FIRST_ARG(x) #define AMD64_ARG(x) #define AMD64_ONLY(x) #define NOT_AMD64(x) x #define NOT_AMD64_ARG(x) , x #endif #ifdef TARGET_X86 #define X86_FIRST_ARG(x) x , #define X86_ARG(x) , x #define X86_ONLY(x) x #define NOT_X86(x) #define NOT_X86_ARG(x) #else #define X86_FIRST_ARG(x) #define X86_ARG(x) #define X86_ONLY(x) #define NOT_X86(x) x #define NOT_X86_ARG(x) , x #endif #ifdef HOST_64BIT #define BIT64_ARG(x) , x #define BIT64_ONLY(x) x #define NOT_BIT64(x) #define NOT_BIT64_ARG(x) #else #define BIT64_ARG(x) #define BIT64_ONLY(x) #define NOT_BIT64(x) x #define NOT_BIT64_ARG(x) , x #endif // HOST_64BIT #ifdef TARGET_ARM #define ARM_FIRST_ARG(x) x , #define ARM_ARG(x) , x #define ARM_ONLY(x) x #define NOT_ARM(x) #define NOT_ARM_ARG(x) #else #define ARM_FIRST_ARG(x) #define ARM_ARG(x) #define ARM_ONLY(x) #define NOT_ARM(x) x #define NOT_ARM_ARG(x) , x #endif #ifdef TARGET_ARM64 #define ARM64_FIRST_ARG(x) x , #define ARM64_ARG(x) , x #define ARM64_ONLY(x) x #define NOT_ARM64(x) #define NOT_ARM64_ARG(x) #else #define ARM64_FIRST_ARG(x) #define ARM64_ARG(x) #define ARM64_ONLY(x) #define NOT_ARM64(x) x #define NOT_ARM64_ARG(x) , x #endif #ifdef TARGET_LOONGARCH64 #define LOONGARCH64_FIRST_ARG(x) x , #define LOONGARCH64_ARG(x) , x #define LOONGARCH64_ONLY(x) x #define NOT_LOONGARCH64(x) #define NOT_LOONGARCH64_ARG(x) #else #define LOONGARCH64_FIRST_ARG(x) #define LOONGARCH64_ARG(x) #define LOONGARCH64_ONLY(x) #define NOT_LOONGARCH64(x) x #define NOT_LOONGARCH64_ARG(x) , x #endif #ifdef TARGET_64BIT #define LOG2_PTRSIZE 3 #else #define LOG2_PTRSIZE 2 #endif #ifdef HOST_64BIT #define INVALID_POINTER_CC 0xcccccccccccccccc #define INVALID_POINTER_CD 0xcdcdcdcdcdcdcdcd #define FMT_ADDR " %08x`%08x " #define LFMT_ADDR W(" %08x`%08x ") #define DBG_ADDR(ptr) (DWORD)(((UINT_PTR) (ptr)) >> 32), (DWORD)(((UINT_PTR) (ptr)) & 0xffffffff) #else // HOST_64BIT #define INVALID_POINTER_CC 0xcccccccc #define INVALID_POINTER_CD 0xcdcdcdcd #define FMT_ADDR " %08x " #define LFMT_ADDR W(" %08x ") #define DBG_ADDR(ptr) (DWORD)((UINT_PTR)(ptr)) #endif // HOST_64BIT #ifdef TARGET_ARM #define ALIGN_ACCESS ((1<= val ); // check for overflow return result; } template inline T ALIGN_UP(T val, size_t alignment) { WRAPPER_NO_CONTRACT; return (T)ALIGN_UP((size_t)val, alignment); } inline size_t ALIGN_DOWN( size_t val, size_t alignment ) { LIMITED_METHOD_CONTRACT; // alignment must be a power of 2 for this implementation to work (need modulo otherwise) _ASSERTE( 0 == (alignment & (alignment - 1)) ); size_t result = val & ~(alignment - 1); return result; } inline void* ALIGN_DOWN( void* val, size_t alignment ) { WRAPPER_NO_CONTRACT; return (void*) ALIGN_DOWN( (size_t)val, alignment ); } inline uint8_t* ALIGN_DOWN( uint8_t* val, size_t alignment ) { WRAPPER_NO_CONTRACT; return (uint8_t*) ALIGN_DOWN( (size_t)val, alignment ); } inline BOOL IS_ALIGNED( size_t val, size_t alignment ) { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; // alignment must be a power of 2 for this implementation to work (need modulo otherwise) _ASSERTE( 0 == (alignment & (alignment - 1)) ); return 0 == (val & (alignment - 1)); } inline BOOL IS_ALIGNED( const void* val, size_t alignment ) { WRAPPER_NO_CONTRACT; return IS_ALIGNED( (size_t) val, alignment ); } // Rounds a ULONG up to the nearest power of two number. inline ULONG RoundUpToPower2(ULONG x) { if (x == 0) return 1; x = x - 1; x = x | (x >> 1); x = x | (x >> 2); x = x | (x >> 4); x = x | (x >> 8); x = x | (x >> 16); return x + 1; } #ifdef ALIGN_ACCESS // NOTE: pSrc is evaluated three times!!! #define MAYBE_UNALIGNED_READ(pSrc, bits) (IS_ALIGNED((size_t)(pSrc), sizeof(UINT##bits)) ? \ (*(UINT##bits*) (pSrc)) : \ (GET_UNALIGNED_##bits(pSrc)) ) #define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { if (IS_ALIGNED((size_t)(pDst), sizeof(UINT##bits))) \ *(UINT##bits*)(pDst) = (UINT##bits)(expr); else \ SET_UNALIGNED_##bits(pDst, (UINT##bits)(expr)); } while (0) // these are necessary for MAYBE_UNALIGNED_XXX to work with UINT_PTR #define GET_UNALIGNED__PTR(x) GET_UNALIGNED_PTR(x) #define SET_UNALIGNED__PTR(p,x) SET_UNALIGNED_PTR(p,x) #else // ALIGN_ACCESS #define MAYBE_UNALIGNED_READ(pSrc, bits) (*(UINT##bits*)(pSrc)) #define MAYBE_UNALIGNED_WRITE(pDst, bits, expr) do { *(UINT##bits*)(pDst) = (UINT##bits)(expr); } while(0) #endif // ALIGN_ACCESS // // define some useful macros for logging object // #define FMT_OBJECT "object" FMT_ADDR #define FMT_HANDLE "handle" FMT_ADDR #define FMT_CLASS "%s" #define FMT_REG "r%d " #define FMT_STK "sp%s0x%02x " #define FMT_PIPTR "%s%s pointer " #define DBG_GET_CLASS_NAME(pMT) \ (((pMT) == NULL) ? NULL : (pMT)->GetClass()->GetDebugClassName()) #define DBG_CLASS_NAME_MT(pMT) \ (DBG_GET_CLASS_NAME(pMT) == NULL) ? "" : DBG_GET_CLASS_NAME(pMT) #define DBG_GET_MT_FROM_OBJ(obj) \ (MethodTable*)((size_t)((Object*) (obj))->GetGCSafeMethodTable()) #define DBG_CLASS_NAME_OBJ(obj) \ ((obj) == NULL) ? "null" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) #define DBG_CLASS_NAME_IPTR2(obj,iptr) \ ((iptr) != 0) ? "" : DBG_CLASS_NAME_MT(DBG_GET_MT_FROM_OBJ(obj)) #define DBG_CLASS_NAME_IPTR(obj,iptr) \ ((obj) == NULL) ? "null" : DBG_CLASS_NAME_IPTR2(obj,iptr) #define DBG_STK(off) \ (off >= 0) ? "+" : "-", \ (off >= 0) ? off : -off #define DBG_PIN_NAME(pin) \ (pin) ? "pinned " : "" #define DBG_IPTR_NAME(iptr) \ (iptr) ? "interior" : "base" #define LOG_HANDLE_OBJECT_CLASS(str1, hnd, str2, obj) \ str1 FMT_HANDLE str2 FMT_OBJECT FMT_CLASS "\n", \ DBG_ADDR(hnd), DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj) #define LOG_OBJECT_CLASS(obj) \ FMT_OBJECT FMT_CLASS "\n", \ DBG_ADDR(obj), DBG_CLASS_NAME_OBJ(obj) #define LOG_PIPTR_OBJECT_CLASS(obj, pin, iptr) \ FMT_PIPTR FMT_ADDR FMT_CLASS "\n", \ DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr), \ DBG_ADDR(obj), DBG_CLASS_NAME_IPTR(obj,iptr) #define LOG_HANDLE_OBJECT(str1, hnd, str2, obj) \ str1 FMT_HANDLE str2 FMT_OBJECT "\n", \ DBG_ADDR(hnd), DBG_ADDR(obj) #define LOG_PIPTR_OBJECT(obj, pin, iptr) \ FMT_PIPTR FMT_ADDR "\n", \ DBG_PIN_NAME(pin), DBG_IPTR_NAME(iptr), \ DBG_ADDR(obj) #define UNIQUE_LABEL_DEF(a,x) a##x #define UNIQUE_LABEL_DEF_X(a,x) UNIQUE_LABEL_DEF(a,x) #ifdef _MSC_VER #define UNIQUE_LABEL(a) UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __COUNTER__) #else #define UNIQUE_LABEL(a) UNIQUE_LABEL_DEF_X(_unique_label_##a##_, __LINE__) #endif // This is temporary. LKG should provide these macros and we should then // remove STRUNCATE and _TRUNCATE from here. /* error codes */ #if !defined(STRUNCATE) #define STRUNCATE 80 #endif /* _TRUNCATE */ #if !defined(_TRUNCATE) #define _TRUNCATE ((size_t)-1) #endif #endif //_stdmacros_h_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stgpool.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // StgPool.h // // // Pools are used to reduce the amount of data actually required in the database. // This allows for duplicate string and binary values to be folded into one // copy shared by the rest of the database. Strings are tracked in a hash // table when insert/changing data to find duplicates quickly. The strings // are then persisted consecutively in a stream in the database format. // //***************************************************************************** #ifndef __StgPool_h__ #define __StgPool_h__ #ifdef _MSC_VER #pragma warning (disable : 4355) // warning C4355: 'this' : used in base member initializer list #endif #include "stgpooli.h" // Internal helpers. #include "corerror.h" // Error codes. #include "metamodelpub.h" #include "ex.h" #include "sarray.h" #include "memoryrange.h" #include "../md/datablob.h" //***************************************************************************** // NOTE: // One limitation with the pools, we have no way to removing strings from // the pool. To remove, you need to know the ref count on the string, and // need the ability to compact the pool and reset all references. //***************************************************************************** //********** Constants ******************************************************** const int DFT_STRING_HEAP_SIZE = 1024; const int DFT_GUID_HEAP_SIZE = 32; const int DFT_BLOB_HEAP_SIZE = 1024; const int DFT_VARIANT_HEAP_SIZE = 512; const int DFT_CODE_HEAP_SIZE = 8192; // Forwards. class StgStringPool; class StgBlobPool; class StgCodePool; // Perform binary search on index table. // class RIDBinarySearch : public CBinarySearch { public: RIDBinarySearch(const UINT32 *pBase, int iCount) : CBinarySearch(pBase, iCount) { LIMITED_METHOD_CONTRACT; } // RIDBinarySearch::RIDBinarySearch int Compare(UINT32 const *pFirst, UINT32 const *pSecond) { LIMITED_METHOD_CONTRACT; if (*pFirst < *pSecond) return -1; if (*pFirst > *pSecond) return 1; return 0; } // RIDBinarySearch::Compare }; // class RIDBinarySearch //***************************************************************************** // This class provides common definitions for heap segments. It is both the // base class for the heap, and the class for heap extensions (additional // memory that must be allocated to grow the heap). //***************************************************************************** class StgPoolSeg { friend class VerifyLayoutsMD; public: StgPoolSeg() : m_pSegData((BYTE*)m_zeros), m_pNextSeg(NULL), m_cbSegSize(0), m_cbSegNext(0) {LIMITED_METHOD_CONTRACT; } ~StgPoolSeg() { LIMITED_METHOD_CONTRACT; _ASSERTE(m_pSegData == m_zeros);_ASSERTE(m_pNextSeg == NULL); } protected: BYTE *m_pSegData; // Pointer to the data. StgPoolSeg *m_pNextSeg; // Pointer to next segment, or NULL. // Size of the segment buffer. If this is last segment (code:m_pNextSeg is NULL), then it's the // allocation size. If this is not the last segment, then this is shrunk to segment data size // (code:m_cbSegNext). ULONG m_cbSegSize; ULONG m_cbSegNext; // Offset of next available byte in segment. // Segment relative. friend class StgPool; friend class StgStringPool; friend class StgGuidPool; friend class StgBlobPool; friend class RecordPool; public: const BYTE *GetSegData() const { LIMITED_METHOD_CONTRACT; return m_pSegData; } const StgPoolSeg* GetNextSeg() const { LIMITED_METHOD_CONTRACT; return m_pNextSeg; } // Returns size of the segment. It can be bigger than the size of represented data by this segment if // this is the last segment. ULONG GetSegSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegSize; } // Returns size of represented data in this segment. ULONG GetDataSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegNext; } static const BYTE m_zeros[64]; // array of zeros for "0" indices. // The size should be at least maximum of all MD table record sizes // (MD\Runtime\MDColumnDescriptors.cpp) which is currently 28 B. }; // class StgPoolSeg namespace MetaData { // Forward declarations class StringHeapRO; class StringHeapRW; class BlobHeapRO; }; // namespace MetaData // // // StgPoolReadOnly // // //***************************************************************************** // This is the read only StgPool class //***************************************************************************** class StgPoolReadOnly : public StgPoolSeg { friend class CBlobPoolHash; friend class MetaData::StringHeapRO; friend class MetaData::StringHeapRW; friend class MetaData::BlobHeapRO; friend class VerifyLayoutsMD; public: StgPoolReadOnly() { LIMITED_METHOD_CONTRACT; }; ~StgPoolReadOnly(); //***************************************************************************** // Init the pool from existing data. //***************************************************************************** __checkReturn HRESULT InitOnMemReadOnly( // Return code. void *pData, // Predefined data. ULONG iSize); // Size of data. //***************************************************************************** // Prepare to shut down or reinitialize. //***************************************************************************** virtual void Uninit(); //***************************************************************************** // Return the size of the pool. //***************************************************************************** virtual UINT32 GetPoolSize() const { LIMITED_METHOD_CONTRACT; return m_cbSegSize; } //***************************************************************************** // Indicate if heap is empty. //***************************************************************************** virtual int IsEmpty() // true if empty. { LIMITED_METHOD_CONTRACT; _ASSERTE(!"This implementation should never be called!!!"); return FALSE; } //***************************************************************************** // true if the heap is read only. //***************************************************************************** virtual int IsReadOnly() { LIMITED_METHOD_CONTRACT; return true ;}; //***************************************************************************** // Is the given cookie a valid offset, index, etc? //***************************************************************************** virtual int IsValidCookie(UINT32 nCookie) { WRAPPER_NO_CONTRACT; return (IsValidOffset(nCookie)); } #ifdef _PREFAST_ #pragma warning(push) #pragma warning(disable:6387) // Suppress PREFast warning: '*pszString' might be '0': this does not adhere to the specification for the function // *pszString may be NULL only if method fails, but warning 6387 doesn't respect __success(SUCCEEDED(return)) which is part of HRESULT definition #endif //***************************************************************************** // Return a pointer to a null terminated string given an offset previously // handed out by AddString or FindString. //***************************************************************************** __checkReturn inline HRESULT GetString( UINT32 nIndex, _Outptr_ LPCSTR *pszString) { HRESULT hr; // Size of the data in the heap will be ignored, because we have verified during creation of the string // heap (code:Initialize) and when adding new strings (e.g. code:AddString, // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it // for each string in the heap MetaData::DataBlob stringData; // Get data from the heap (clears stringData on error) IfFailGo(GetData( nIndex, &stringData)); _ASSERTE(hr == S_OK); // Raw data are always at least 1 byte long, otherwise it would be invalid offset and hr != S_OK PREFAST_ASSUME(stringData.GetDataPointer() != NULL); // Fills output string *pszString = reinterpret_cast(stringData.GetDataPointer()); //_ASSERTE(stringData.GetSize() > strlen(*pszString)); return hr; ErrExit: // Clears output string on error *pszString = NULL; return hr; } //***************************************************************************** // Return a pointer to a null terminated string given an offset previously // handed out by AddString or FindString. Only valid for use if the Storage pool is actually ReadOnly, and not derived //***************************************************************************** __checkReturn inline HRESULT GetStringReadOnly( UINT32 nIndex, _Outptr_ LPCSTR *pszString) { HRESULT hr; // Size of the data in the heap will be ignored, because we have verified during creation of the string // heap (code:Initialize) and when adding new strings (e.g. code:AddString, // code:AddTemporaryStringBuffer), that the heap is null-terminated, therefore we don't have to check it // for each string in the heap MetaData::DataBlob stringData; // Get data from the heap (clears stringData on error) IfFailGo(GetDataReadOnly( nIndex, &stringData)); _ASSERTE(hr == S_OK); // Raw data are always at least 1 byte long, otherwise it would be invalid offset and hr != S_OK PREFAST_ASSUME(stringData.GetDataPointer() != NULL); // Fills output string *pszString = reinterpret_cast(stringData.GetDataPointer()); //_ASSERTE(stringData.GetSize() > strlen(*pszString)); return hr; ErrExit: // Clears output string on error *pszString = NULL; return hr; } #ifdef _PREFAST_ #pragma warning(pop) #endif //***************************************************************************** // Convert a string to UNICODE into the caller's buffer. //***************************************************************************** __checkReturn virtual HRESULT GetStringW( // Return code. ULONG iOffset, // Offset of string in pool. _Out_writes_(cchBuffer) LPWSTR szOut, // Output buffer for string. int cchBuffer); // Size of output buffer. //***************************************************************************** // Copy a GUID into the caller's buffer. //***************************************************************************** __checkReturn HRESULT GetGuid( UINT32 nIndex, // 1-based index of Guid in pool. GUID UNALIGNED **ppGuid) // Output buffer for Guid. { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; HRESULT hr; MetaData::DataBlob heapData; if (nIndex == 0) { *ppGuid = (GUID *)m_zeros; return S_OK; } S_UINT32 nOffset = S_UINT32(nIndex - 1) * S_UINT32(sizeof(GUID)); if (nOffset.IsOverflow() || !IsValidOffset(nOffset.Value())) { Debug_ReportError("Invalid index passed - integer overflow."); IfFailGo(CLDB_E_INDEX_NOTFOUND); } if (FAILED(GetData(nOffset.Value(), &heapData))) { if (nOffset.Value() == 0) { Debug_ReportError("Invalid index 0 passed."); IfFailGo(CLDB_E_INDEX_NOTFOUND); } Debug_ReportInternalError("Invalid index passed."); IfFailGo(CLDB_E_INTERNALERROR); } _ASSERTE(heapData.GetSize() >= sizeof(GUID)); *ppGuid = (GUID UNALIGNED *)heapData.GetDataPointer(); return S_OK; ErrExit: *ppGuid = (GUID *)m_zeros; return hr; } // StgPoolReadOnly::GetGuid //***************************************************************************** // Return a pointer to a null terminated blob given an offset previously // handed out by Addblob or Findblob. //***************************************************************************** __checkReturn virtual HRESULT GetBlob( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); protected: //***************************************************************************** // Check whether a given offset is valid in the pool. //***************************************************************************** virtual int IsValidOffset(UINT32 nOffset) {LIMITED_METHOD_CONTRACT; return (nOffset == 0) || ((m_pSegData != m_zeros) && (nOffset < m_cbSegSize)); } //***************************************************************************** // Get a pointer to an offset within the heap. Inline for base segment, // helper for extension segments. //***************************************************************************** __checkReturn FORCEINLINE HRESULT GetDataReadOnly(UINT32 nOffset, __inout MetaData::DataBlob *pData) { LIMITED_METHOD_CONTRACT; _ASSERTE(IsReadOnly()); // If off the end of the heap, return the 'nul' item from the beginning. if (nOffset >= m_cbSegSize) { Debug_ReportError("Invalid offset passed."); pData->Clear(); return CLDB_E_INDEX_NOTFOUND; } pData->Init(m_pSegData + nOffset, m_cbSegSize - nOffset); return S_OK; } // StgPoolReadOnly::GetDataReadOnly //***************************************************************************** // Get a pointer to an offset within the heap. Inline for base segment, // helper for extension segments. //***************************************************************************** __checkReturn virtual HRESULT GetData(UINT32 nOffset, __inout MetaData::DataBlob *pData) { WRAPPER_NO_CONTRACT; return GetDataReadOnly(nOffset, pData); } // StgPoolReadOnly::GetData }; // class StgPoolReadOnly // // // StgBlobPoolReadOnly // // //***************************************************************************** // This is the read only StgBlobPool class //***************************************************************************** class StgBlobPoolReadOnly : public StgPoolReadOnly { public: //***************************************************************************** // Return a pointer to a null terminated blob given an offset //***************************************************************************** __checkReturn virtual HRESULT GetBlob( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); protected: //***************************************************************************** // Check whether a given offset is valid in the pool. //***************************************************************************** virtual int IsValidOffset(UINT32 nOffset) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; MetaData::DataBlob data; return (StgBlobPoolReadOnly::GetBlob(nOffset, &data) == S_OK); } }; // class StgBlobPoolReadOnly // // // StgPool // // //***************************************************************************** // This base class provides common pool management code, such as allocation // of dynamic memory. //***************************************************************************** class StgPool : public StgPoolReadOnly { friend class StgStringPool; friend class StgBlobPool; friend class RecordPool; friend class CBlobPoolHash; friend class VerifyLayoutsMD; public: StgPool(ULONG ulGrowInc=512, UINT32 nAlignment=4) : m_ulGrowInc(ulGrowInc), m_pCurSeg(this), m_cbCurSegOffset(0), m_bFree(true), m_bReadOnly(false), m_nVariableAlignmentMask(nAlignment-1), m_cbStartOffsetOfEdit(0), m_fValidOffsetOfEdit(0) { LIMITED_METHOD_CONTRACT; } virtual ~StgPool(); protected: HRESULT Align(UINT32 nValue, UINT32 *pnAlignedValue) const { LIMITED_METHOD_CONTRACT; *pnAlignedValue = (nValue + m_nVariableAlignmentMask) & ~m_nVariableAlignmentMask; if (*pnAlignedValue < nValue) { return COR_E_OVERFLOW; } return S_OK; } public: //***************************************************************************** // Init the pool for use. This is called for the create empty case. //***************************************************************************** __checkReturn virtual HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0); // Estimated item count. //***************************************************************************** // Init the pool from existing data. //***************************************************************************** __checkReturn virtual HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. int bReadOnly); // true if append is forbidden. //***************************************************************************** // Called when the pool must stop accessing memory passed to InitOnMem(). //***************************************************************************** __checkReturn virtual HRESULT TakeOwnershipOfInitMem(); //***************************************************************************** // Clear out this pool. Cannot use until you call InitNew. //***************************************************************************** virtual void Uninit(); //***************************************************************************** // Called to copy the pool to writable memory, reset the r/o bit. //***************************************************************************** __checkReturn virtual HRESULT ConvertToRW(); //***************************************************************************** // Turn hashing off or on. Implemented as required in subclass. //***************************************************************************** __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** // Allocate memory if we don't have any, or grow what we have. If successful, // then at least iRequired bytes will be allocated. //***************************************************************************** bool Grow( // true if successful. ULONG iRequired); // Min required bytes to allocate. //***************************************************************************** // Add a segment to the chain of segments. //***************************************************************************** __checkReturn virtual HRESULT AddSegment( // S_OK or error. const void *pData, // The data. ULONG cbData, // Size of the data. bool bCopy); // If true, make a copy of the data. //***************************************************************************** // Trim any empty final segment. //***************************************************************************** void Trim(); // //***************************************************************************** // Return the size in bytes of the persistent version of this pool. If // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; _ASSERTE(pcbSaveSize != NULL); // Size is offset of last seg + size of last seg. UINT32 cbSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; if (FAILED(Align(cbSize, pcbSaveSize))) { *pcbSaveSize = 0; Debug_ReportInternalError("Aligned size of string heap overflows - we should prevent creating such heaps."); return CLDB_E_INTERNALERROR; } return S_OK; } //***************************************************************************** // Return the size in bytes of the edits contained in the persistent version of this pool. //***************************************************************************** __checkReturn HRESULT GetEditSaveSize( UINT32 *pcbSaveSize) const // Return save size of this pool. { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; _ASSERTE(pcbSaveSize != NULL); UINT32 cbSize = 0; if (HaveEdits()) { // Size is offset of last seg + size of last seg. // An offset of zero in the pool will give us a zero length blob. The first // "real" user string is at offset 1. Wherever this delta gets applied, it will // already have this zero length blob. Let's make sure we don't sent it another one. #ifdef _DEBUG MetaData::DataBlob debug_data; HRESULT hr = const_cast(this)->GetData(0, &debug_data); _ASSERTE(hr == S_OK); _ASSERTE(debug_data.ContainsData(1)); _ASSERTE(*(debug_data.GetDataPointer()) == 0); #endif //_DEBUG UINT32 nOffsetOfEdit = GetOffsetOfEdit(); if (nOffsetOfEdit == 0) nOffsetOfEdit = 1; cbSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset - nOffsetOfEdit; } if (FAILED(Align(cbSize, pcbSaveSize))) { *pcbSaveSize = 0; Debug_ReportInternalError("Aligned size of string heap overflows - we should prevent creating such heaps."); return CLDB_E_INTERNALERROR; } return S_OK; } // StgPool::GetEditSaveSize //***************************************************************************** // The entire pool is written to the given stream. The stream is aligned // to a 4 byte boundary. //***************************************************************************** __checkReturn virtual HRESULT PersistToStream( // Return code. IStream *pIStream) // The stream to write to. DAC_UNEXPECTED(); //***************************************************************************** // A portion of the pool is written to the stream. Must not be optimized. //***************************************************************************** __checkReturn virtual HRESULT PersistPartialToStream( // Return code. IStream *pIStream, // The stream to write to. ULONG iOffset); // Starting byte. //***************************************************************************** // Get the size of the data block obtained from the pool. // Needed for generic persisting of data blocks. // Override in concrete pool classes to return the correct size. //***************************************************************************** virtual ULONG GetSizeOfData( void const * data ) { LIMITED_METHOD_CONTRACT; return 0; } //***************************************************************************** // Return the size of the pool. //***************************************************************************** virtual UINT32 GetPoolSize() const {LIMITED_METHOD_CONTRACT; return m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; } //***************************************************************************** // Indicate if heap is empty. //***************************************************************************** virtual int IsEmpty() // true if empty. {LIMITED_METHOD_CONTRACT; return (m_pSegData == m_zeros); } //***************************************************************************** // true if the heap is read only. //***************************************************************************** int IsReadOnly() {LIMITED_METHOD_CONTRACT; return (m_bReadOnly == false); } //***************************************************************************** // Is the given cookie a valid offset, index, etc? //***************************************************************************** virtual int IsValidCookie(UINT32 nCookie) { WRAPPER_NO_CONTRACT; return (IsValidOffset(nCookie)); } //***************************************************************************** // Get a pointer to an offset within the heap. Inline for base segment, // helper for extension segments. //***************************************************************************** __checkReturn FORCEINLINE HRESULT GetData(UINT32 nOffset, MetaData::DataBlob *pData) { WRAPPER_NO_CONTRACT; if (nOffset < m_cbSegNext) { pData->Init(m_pSegData + nOffset, m_cbSegNext - nOffset); return S_OK; } else { return GetData_i(nOffset, pData); } } // StgPool::GetData // Copies data from pSourcePool starting at index nStartSourceIndex. __checkReturn HRESULT CopyPool( UINT32 nStartSourceIndex, const StgPool *pSourcePool); //***************************************************************************** // Copies data from the pool into a buffer. It will correctly walk the different // segments for the copy //***************************************************************************** private: __checkReturn HRESULT CopyData( UINT32 nOffset, BYTE *pBuffer, UINT32 cbBuffer, UINT32 *pcbWritten) const; public: //***************************************************************************** // Helpers for dump utilities. //***************************************************************************** UINT32 GetRawSize() const { LIMITED_METHOD_CONTRACT; // Size is offset of last seg + size of last seg. return m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; } BOOL HaveEdits() const {LIMITED_METHOD_CONTRACT; return m_fValidOffsetOfEdit;} UINT32 GetOffsetOfEdit() const {LIMITED_METHOD_CONTRACT; return m_cbStartOffsetOfEdit;} void ResetOffsetOfEdit() {LIMITED_METHOD_CONTRACT; m_fValidOffsetOfEdit=FALSE;} protected: //***************************************************************************** // Check whether a given offset is valid in the pool. //***************************************************************************** virtual int IsValidOffset(UINT32 nOffset) { WRAPPER_NO_CONTRACT; return (nOffset == 0) || ((m_pSegData != m_zeros) && (nOffset < GetNextOffset())); } // Following virtual because a) this header included outside the project, and // non-virtual function call (in non-expanded inline function!!) generates // an external def, which causes linkage errors. __checkReturn virtual HRESULT GetData_i(UINT32 nOffset, MetaData::DataBlob *pData); // Get pointer to next location to which to write. BYTE *GetNextLocation() {LIMITED_METHOD_CONTRACT; return (m_pCurSeg->m_pSegData + m_pCurSeg->m_cbSegNext); } // Get pool-relative offset of next location to which to write. ULONG GetNextOffset() {LIMITED_METHOD_CONTRACT; return (m_cbCurSegOffset + m_pCurSeg->m_cbSegNext); } // Get count of bytes available in tail segment of pool. ULONG GetCbSegAvailable() {LIMITED_METHOD_CONTRACT; return (m_pCurSeg->m_cbSegSize - m_pCurSeg->m_cbSegNext); } // Allocate space from the segment. void SegAllocate(ULONG cb) { LIMITED_METHOD_CONTRACT; _ASSERTE(cb <= GetCbSegAvailable()); if (!m_fValidOffsetOfEdit) { m_cbStartOffsetOfEdit = GetNextOffset(); m_fValidOffsetOfEdit = TRUE; } m_pCurSeg->m_cbSegNext += cb; }// SegAllocate ULONG m_ulGrowInc; // How many bytes at a time. StgPoolSeg *m_pCurSeg; // Current seg for append -- end of chain. ULONG m_cbCurSegOffset; // Base offset of current seg. unsigned m_bFree : 1; // True if we should free base data. // Extension data is always freed. unsigned m_bReadOnly : 1; // True if we shouldn't append. UINT32 m_nVariableAlignmentMask; // Alignment mask (variable 0, 1 or 3). UINT32 m_cbStartOffsetOfEdit; // Place in the pool where edits started BOOL m_fValidOffsetOfEdit; // Is the pool edit offset valid }; // // // StgStringPool // // //***************************************************************************** // This string pool class collects user strings into a big consecutive heap. // Internally it manages this data in a hash table at run time to help throw // out duplicates. The list of strings is kept in memory while adding, and // finally flushed to a stream at the caller's request. //***************************************************************************** class StgStringPool : public StgPool { friend class VerifyLayoutsMD; public: StgStringPool() : StgPool(DFT_STRING_HEAP_SIZE), m_Hash(this), m_bHash(true) { LIMITED_METHOD_CONTRACT; // force some code in debug. _ASSERTE(m_bHash); } //***************************************************************************** // Create a new, empty string pool. //***************************************************************************** __checkReturn HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0); // Estimated item count. //***************************************************************************** // Load a string heap from persisted memory. If a copy of the data is made // (so that it may be updated), then a new hash table is generated which can // be used to eliminate duplicates with new strings. //***************************************************************************** __checkReturn HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. int bReadOnly); // true if append is forbidden. //***************************************************************************** // Clears the hash table then calls the base class. //***************************************************************************** void Uninit(); //***************************************************************************** // Turn hashing off or on. If you turn hashing on, then any existing data is // thrown away and all data is rehashed during this call. //***************************************************************************** __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** // The string will be added to the pool. The offset of the string in the pool // is returned in *piOffset. If the string is already in the pool, then the // offset will be to the existing copy of the string. // // The first version essentially adds a zero-terminated sequence of bytes // to the pool. MBCS pairs will not be converted to the appropriate UTF8 // sequence. The second version converts from Unicode. //***************************************************************************** __checkReturn HRESULT AddString( LPCSTR szString, // The string to add to pool. UINT32 *pnOffset); // Return offset of string here. __checkReturn HRESULT AddStringW( LPCWSTR szString, // The string to add to pool. UINT32 *pnOffset); // Return offset of string here. //***************************************************************************** // Look for the string and return its offset if found. //***************************************************************************** __checkReturn HRESULT FindString( // S_OK, S_FALSE. LPCSTR szString, // The string to find in pool. ULONG *piOffset) // Return offset of string here. { WRAPPER_NO_CONTRACT; STRINGHASH *pHash; // Hash item for lookup. if ((pHash = m_Hash.Find(szString)) == 0) return (S_FALSE); *piOffset = pHash->iOffset; return (S_OK); } //***************************************************************************** // How many objects are there in the pool? If the count is 0, you don't need // to persist anything at all to disk. //***************************************************************************** int Count() { WRAPPER_NO_CONTRACT; _ASSERTE(m_bHash); return (m_Hash.Count()); } //***************************************************************************** // String heap is considered empty if the only thing it has is the initial // empty string, or if after organization, there are no strings. //***************************************************************************** int IsEmpty() // true if empty. { WRAPPER_NO_CONTRACT; return (GetNextOffset() <= 1); } //***************************************************************************** // Return the size in bytes of the persistent version of this pool. If // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { LIMITED_METHOD_CONTRACT; _ASSERTE(pcbSaveSize != NULL); // Size is offset of last seg + size of last seg. S_UINT32 cbSize = S_UINT32(m_pCurSeg->m_cbSegNext + m_cbCurSegOffset); cbSize.AlignUp(4); if (cbSize.IsOverflow()) { *pcbSaveSize = 0; Debug_ReportInternalError("Aligned size of string heap overflows - we should prevent creating such heaps."); return CLDB_E_INTERNALERROR; } *pcbSaveSize = cbSize.Value(); return S_OK; } //***************************************************************************** // Get the size of the string obtained from the pool. // Needed for generic persisting of data blocks. //***************************************************************************** virtual ULONG GetSizeOfData( void const * data ) { LIMITED_METHOD_CONTRACT; return ULONG( strlen( reinterpret_cast< LPCSTR >( data ) ) + 1 ); // using strlen since the string is UTF8 } private: __checkReturn HRESULT RehashStrings(); private: CStringPoolHash m_Hash; // Hash table for lookups. int m_bHash; // true to keep hash table. }; // class StgStringPool // // // StgGuidPool // // //***************************************************************************** // This Guid pool class collects user Guids into a big consecutive heap. // Internally it manages this data in a hash table at run time to help throw // out duplicates. The list of Guids is kept in memory while adding, and // finally flushed to a stream at the caller's request. //***************************************************************************** class StgGuidPool : public StgPool { friend class VerifyLayoutsMD; public: StgGuidPool() : StgPool(DFT_GUID_HEAP_SIZE), m_Hash(this), m_bHash(true) { LIMITED_METHOD_CONTRACT; } //***************************************************************************** // Init the pool for use. This is called for the create empty case. //***************************************************************************** __checkReturn HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0); // Estimated item count. //***************************************************************************** // Load a Guid heap from persisted memory. If a copy of the data is made // (so that it may be updated), then a new hash table is generated which can // be used to eliminate duplicates with new Guids. //***************************************************************************** __checkReturn HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. int bReadOnly); // true if append is forbidden. //***************************************************************************** // Clears the hash table then calls the base class. //***************************************************************************** void Uninit(); //***************************************************************************** // Add a segment to the chain of segments. //***************************************************************************** __checkReturn virtual HRESULT AddSegment( // S_OK or error. const void *pData, // The data. ULONG cbData, // Size of the data. bool bCopy); // If true, make a copy of the data. //***************************************************************************** // Turn hashing off or on. If you turn hashing on, then any existing data is // thrown away and all data is rehashed during this call. //***************************************************************************** __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** // The Guid will be added to the pool. The index of the Guid in the pool // is returned in *piIndex. If the Guid is already in the pool, then the // index will be to the existing copy of the Guid. //***************************************************************************** __checkReturn HRESULT AddGuid( const GUID *pGuid, // The Guid to add to pool. UINT32 *pnIndex); // Return index of Guid here. //***************************************************************************** // Get the size of the GUID obtained from the pool. // Needed for generic persisting of data blocks. //***************************************************************************** virtual ULONG GetSizeOfData( void const * data ) { LIMITED_METHOD_CONTRACT; return sizeof( GUID ); } //***************************************************************************** // How many objects are there in the pool? If the count is 0, you don't need // to persist anything at all to disk. //***************************************************************************** int Count() { WRAPPER_NO_CONTRACT; _ASSERTE(m_bHash); return (m_Hash.Count()); } //***************************************************************************** // Indicate if heap is empty. This has to be based on the size of the data // we are keeping. If you open in r/o mode on memory, there is no hash // table. //***************************************************************************** virtual int IsEmpty() // true if empty. { WRAPPER_NO_CONTRACT; return (GetNextOffset() == 0); } //***************************************************************************** // Is the index valid for the GUID? //***************************************************************************** virtual int IsValidCookie(UINT32 nCookie) { WRAPPER_NO_CONTRACT; return ((nCookie == 0) || IsValidOffset((nCookie - 1) * sizeof(GUID))); } //***************************************************************************** // Return the size of the heap. //***************************************************************************** ULONG GetNextIndex() { LIMITED_METHOD_CONTRACT; return (GetNextOffset() / sizeof(GUID)); } //***************************************************************************** // Return the size in bytes of the persistent version of this pool. If // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; _ASSERTE(pcbSaveSize != NULL); // Size is offset of last seg + size of last seg. *pcbSaveSize = m_pCurSeg->m_cbSegNext + m_cbCurSegOffset; // Should be aligned. _ASSERTE(*pcbSaveSize == ALIGN4BYTE(*pcbSaveSize)); return S_OK; } private: __checkReturn HRESULT RehashGuids(); private: DAC_ALIGNAS(StgPool) // Align first member to alignment of base class CGuidPoolHash m_Hash; // Hash table for lookups. int m_bHash; // true to keep hash table. }; // class StgGuidPool // // // StgBlobPool // // //***************************************************************************** // Just like the string pool, this pool manages a list of items, throws out // duplicates using a hash table, and can be persisted to a stream. The only // difference is that instead of saving null terminated strings, this code // manages binary values of up to 64K in size. Any data you have larger than // this should be stored someplace else with a pointer in the record to the // external source. //***************************************************************************** class StgBlobPool : public StgPool { friend class VerifyLayoutsMD; using StgPool::InitNew; using StgPool::InitOnMem; public: StgBlobPool(ULONG ulGrowInc=DFT_BLOB_HEAP_SIZE) : StgPool(ulGrowInc), m_Hash(this) { LIMITED_METHOD_CONTRACT; } //***************************************************************************** // Init the pool for use. This is called for the create empty case. //***************************************************************************** __checkReturn HRESULT InitNew( // Return code. ULONG cbSize=0, // Estimated size. ULONG cItems=0, // Estimated item count. BOOL fAddEmptryItem=TRUE); // Should we add an empty item at offset 0 //***************************************************************************** // Init the blob pool for use. This is called for both create and read case. // If there is existing data and bCopyData is true, then the data is rehashed // to eliminate dupes in future adds. //***************************************************************************** __checkReturn HRESULT InitOnMem( // Return code. void *pData, // Predefined data. ULONG iSize, // Size of data. int bReadOnly); // true if append is forbidden. //***************************************************************************** // Clears the hash table then calls the base class. //***************************************************************************** void Uninit(); //***************************************************************************** // The blob will be added to the pool. The offset of the blob in the pool // is returned in *piOffset. If the blob is already in the pool, then the // offset will be to the existing copy of the blob. //***************************************************************************** __checkReturn HRESULT AddBlob( const MetaData::DataBlob *pData, UINT32 *pnOffset); //***************************************************************************** // Return a pointer to a null terminated blob given an offset previously // handed out by Addblob or Findblob. //***************************************************************************** __checkReturn virtual HRESULT GetBlob( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); __checkReturn HRESULT GetBlobWithSizePrefix( UINT32 nOffset, // Offset of blob in pool. MetaData::DataBlob *pData); //***************************************************************************** // Turn hashing off or on. If you turn hashing on, then any existing data is // thrown away and all data is rehashed during this call. //***************************************************************************** __checkReturn virtual HRESULT SetHash(int bHash); //***************************************************************************** // Get the size of the blob obtained from the pool. // Needed for generic persisting of data blocks. //***************************************************************************** virtual ULONG GetSizeOfData( void const * data ) { WRAPPER_NO_CONTRACT; void const * blobdata = 0; ULONG blobsize = CPackedLen::GetLength( data, & blobdata ); // the size is encoded at the beginning of the block return blobsize + static_cast< ULONG >( reinterpret_cast< BYTE const * >( blobdata ) - reinterpret_cast< BYTE const * >( data ) ); } //***************************************************************************** // How many objects are there in the pool? If the count is 0, you don't need // to persist anything at all to disk. //***************************************************************************** int Count() { WRAPPER_NO_CONTRACT; return (m_Hash.Count()); } //***************************************************************************** // String heap is considered empty if the only thing it has is the initial // empty string, or if after organization, there are no strings. //***************************************************************************** virtual int IsEmpty() // true if empty. { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; return (GetNextOffset() <= 1); } //***************************************************************************** // Return the size in bytes of the persistent version of this pool. If // PersistToStream were the next call, the amount of bytes written to pIStream // has to be same as the return value from this function. //***************************************************************************** __checkReturn virtual HRESULT GetSaveSize( UINT32 *pcbSaveSize) const { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; return StgPool::GetSaveSize(pcbSaveSize); } protected: //***************************************************************************** // Check whether a given offset is valid in the pool. //***************************************************************************** virtual int IsValidOffset(UINT32 nOffset) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FORBID_FAULT; MetaData::DataBlob data; return (StgBlobPool::GetBlob(nOffset, &data) == S_OK); } private: __checkReturn HRESULT RehashBlobs(); DAC_ALIGNAS(StgPool) // Align first member to alignment of base class CBlobPoolHash m_Hash; // Hash table for lookups. }; // class StgBlobPool #ifdef _MSC_VER #pragma warning (default : 4355) #endif //***************************************************************************** // Unfortunately the CreateStreamOnHGlobal is a little too smart in that // it gets its size from GlobalSize. This means that even if you give it the // memory for the stream, it has to be globally allocated. We don't want this // because we have the stream read only in the middle of a memory mapped file. // CreateStreamOnMemory and the corresponding, internal only stream object solves // that problem. //***************************************************************************** class CInMemoryStream : public IStream { public: CInMemoryStream() : m_pMem(0), m_cbSize(0), m_cbCurrent(0), m_cRef(1), m_dataCopy(NULL) { LIMITED_METHOD_CONTRACT; } virtual ~CInMemoryStream() {} void InitNew( void *pMem, ULONG cbSize) { LIMITED_METHOD_CONTRACT; m_pMem = pMem; m_cbSize = cbSize; m_cbCurrent = 0; } ULONG STDMETHODCALLTYPE AddRef() { LIMITED_METHOD_CONTRACT; return InterlockedIncrement(&m_cRef); } ULONG STDMETHODCALLTYPE Release(); __checkReturn HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppOut); __checkReturn HRESULT STDMETHODCALLTYPE Read(void *pv, ULONG cb, ULONG *pcbRead); __checkReturn HRESULT STDMETHODCALLTYPE Write(const void *pv, ULONG cb, ULONG *pcbWritten); __checkReturn HRESULT STDMETHODCALLTYPE Seek(LARGE_INTEGER dlibMove,DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); __checkReturn HRESULT STDMETHODCALLTYPE SetSize(ULARGE_INTEGER libNewSize) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; return (BadError(E_NOTIMPL)); } __checkReturn HRESULT STDMETHODCALLTYPE CopyTo( IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); __checkReturn HRESULT STDMETHODCALLTYPE Commit( DWORD grfCommitFlags) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; return (BadError(E_NOTIMPL)); } __checkReturn HRESULT STDMETHODCALLTYPE Revert() { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; return (BadError(E_NOTIMPL)); } __checkReturn HRESULT STDMETHODCALLTYPE LockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; return (BadError(E_NOTIMPL)); } __checkReturn HRESULT STDMETHODCALLTYPE UnlockRegion( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; return (BadError(E_NOTIMPL)); } __checkReturn HRESULT STDMETHODCALLTYPE Stat( STATSTG *pstatstg, DWORD grfStatFlag) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; pstatstg->cbSize.QuadPart = m_cbSize; return (S_OK); } __checkReturn HRESULT STDMETHODCALLTYPE Clone( IStream **ppstm) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; //E_OUTOFMEMORY; return (BadError(E_NOTIMPL)); } __checkReturn static HRESULT CreateStreamOnMemory( // Return code. void *pMem, // Memory to create stream on. ULONG cbSize, // Size of data. IStream **ppIStream, // Return stream object here. BOOL fDeleteMemoryOnRelease = FALSE ); __checkReturn static HRESULT CreateStreamOnMemoryCopy( void *pMem, ULONG cbSize, IStream **ppIStream); private: void *m_pMem; // Memory for the read. ULONG m_cbSize; // Size of the memory. ULONG m_cbCurrent; // Current offset. LONG m_cRef; // Ref count. BYTE *m_dataCopy; // Optional copy of the data. }; // class CInMemoryStream //***************************************************************************** // CGrowableStream is a simple IStream implementation that grows as // its written to. All the memory is contiguous, so read access is // fast. A grow does a realloc, so be aware of that if you're going to // use this. //***************************************************************************** // DPTR instead of VPTR because we don't actually call any of the virtuals. typedef DPTR(class CGrowableStream) PTR_CGrowableStream; class CGrowableStream : public IStream { public: //Constructs a new GrowableStream // multiplicativeGrowthRate - when the stream grows it will be at least this // multiple of its old size. Values greater than 1 ensure O(N) amortized // performance growing the stream to size N, 1 ensures O(N^2) amortized perf // but gives the tightest memory usage. Valid range is [1.0, 2.0]. // additiveGrowthRate - when the stream grows it will increase in size by at least // this number of bytes. Larger numbers cause fewer re-allocations at the cost of // increased memory usage. CGrowableStream(float multiplicativeGrowthRate = 2.0, DWORD additiveGrowthRate = 4096); #ifndef DACCESS_COMPILE virtual ~CGrowableStream(); #endif // Expose the total raw buffer. // This can be used by DAC to get the raw contents. // This becomes potentiallyinvalid on the next call on the class, because the underlying storage can be // reallocated. MemoryRange GetRawBuffer() const { SUPPORTS_DAC; PTR_VOID p = m_swBuffer; return MemoryRange(p, m_dwBufferSize); } private: // Raw pointer to buffer. This may change as the buffer grows and gets reallocated. PTR_BYTE m_swBuffer; // Total size of the buffer in bytes. DWORD m_dwBufferSize; // Current index in the buffer. This can be moved around by Seek. DWORD m_dwBufferIndex; // Logical length of the stream DWORD m_dwStreamLength; // Reference count LONG m_cRef; // growth rate parameters determine new stream size when it must grow float m_multiplicativeGrowthRate; int m_additiveGrowthRate; // Ensures the stream is physically and logically at least newLogicalSize // in size HRESULT EnsureCapacity(DWORD newLogicalSize); // IStream methods public: #ifndef DACCESS_COMPILE ULONG STDMETHODCALLTYPE AddRef() { LIMITED_METHOD_CONTRACT; return InterlockedIncrement(&m_cRef); } ULONG STDMETHODCALLTYPE Release(); __checkReturn HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppOut); STDMETHOD(Read)( void * pv, ULONG cb, ULONG * pcbRead); STDMETHOD(Write)( const void * pv, ULONG cb, ULONG * pcbWritten); STDMETHOD(Seek)( LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER * plibNewPosition); STDMETHOD(SetSize)(ULARGE_INTEGER libNewSize); STDMETHOD(CopyTo)( IStream * pstm, ULARGE_INTEGER cb, ULARGE_INTEGER * pcbRead, ULARGE_INTEGER * pcbWritten) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } STDMETHOD(Commit)( DWORD grfCommitFlags) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return NOERROR; } STDMETHOD(Revert)( void) {STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } STDMETHOD(LockRegion)( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } STDMETHOD(UnlockRegion)( ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) {STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_FAULT; return E_NOTIMPL; } STDMETHOD(Stat)( STATSTG * pstatstg, DWORD grfStatFlag); // Make a deep copy of the stream into a new CGrowableStream instance STDMETHOD(Clone)( IStream ** ppstm); #endif // DACCESS_COMPILE }; // class CGrowableStream #endif // __StgPool_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stgpooli.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // StgPooli.h // // // This is helper code for the string and blob pools. It is here because it is // secondary to the pooling interface and reduces clutter in the main file. // //***************************************************************************** #ifndef __StgPooli_h__ #define __StgPooli_h__ #include "utilcode.h" // Base hashing code. // // // CPackedLen // // //***************************************************************************** // Helper class to pack and unpack lengths. //***************************************************************************** struct CPackedLen { enum {MAX_LEN = 0x1fffffff}; static int Size(ULONG len) { LIMITED_METHOD_CONTRACT; // Smallest. if (len <= 0x7F) return 1; // Medium. if (len <= 0x3FFF) return 2; // Large (too large?). _ASSERTE(len <= MAX_LEN); return 4; } // Get a pointer to the data, and store the length. static void const *GetData(void const *pData, ULONG *pLength); // Get the length value encoded at *pData. Update ppData to point past data. static ULONG GetLength(void const *pData, void const **ppData=0); // Get the length value encoded at *pData, and the size of that encoded value. static ULONG GetLength(void const *pData, int *pSizeOfLength); // Pack a length at *pData; return a pointer to the next byte. static void* PutLength(void *pData, ULONG len); // This is used for just getting an encoded length, and verifies that // there is no buffer or integer overflow. static HRESULT SafeGetLength( // S_OK, or error void const *pDataSource, // First byte of length. void const *pDataSourceEnd, // End of valid source data memory ULONG *pLength, // Encoded value void const **ppDataNext); // Pointer immediately following encoded length static HRESULT SafeGetLength( // S_OK, or error BYTE const *pDataSource, // First byte of length. BYTE const *pDataSourceEnd, // End of valid source data memory ULONG *pLength, // Encoded value BYTE const **ppDataNext) // Pointer immediately following encoded length { return SafeGetLength( reinterpret_cast(pDataSource), reinterpret_cast(pDataSourceEnd), pLength, reinterpret_cast(ppDataNext)); } // This performs the same tasks as GetLength above in addition to checking // that the value in *pcbData does not extend *ppData beyond pDataSourceEnd // and does not cause an integer overflow. static HRESULT SafeGetData( void const *pDataSource, // First byte of length. void const *pDataSourceEnd, // End of valid source data memory ULONG *pcbData, // Length of data void const **ppData); // Start of data static HRESULT SafeGetData( BYTE const *pDataSource, // First byte of length. BYTE const *pDataSourceEnd, // End of valid source data memory ULONG *pcbData, // Length of data BYTE const **ppData) // Start of data { return SafeGetData( reinterpret_cast(pDataSource), reinterpret_cast(pDataSourceEnd), pcbData, reinterpret_cast(ppData)); } // This is the same as GetData above except it takes a byte count instead // of pointer to determine the source data length. static HRESULT SafeGetData( // S_OK, or error void const *pDataSource, // First byte of data ULONG cbDataSource, // Count of valid bytes in data source ULONG *pcbData, // Length of data void const **ppData); // Start of data static HRESULT SafeGetData( BYTE const *pDataSource, // First byte of length. ULONG cbDataSource, // Count of valid bytes in data source ULONG *pcbData, // Length of data BYTE const **ppData) // Start of data { return SafeGetData( reinterpret_cast(pDataSource), cbDataSource, pcbData, reinterpret_cast(ppData)); } }; class StgPoolReadOnly; //***************************************************************************** // This hash class will handle strings inside of a chunk of the pool. //***************************************************************************** struct STRINGHASH : HASHLINK { ULONG iOffset; // Offset of this item. }; class CStringPoolHash : public CChainedHash { friend class VerifyLayoutsMD; public: CStringPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) { LIMITED_METHOD_CONTRACT; } virtual bool InUse(STRINGHASH *pItem) { LIMITED_METHOD_CONTRACT; return (pItem->iOffset != 0xffffffff); } virtual void SetFree(STRINGHASH *pItem) { LIMITED_METHOD_CONTRACT; pItem->iOffset = 0xffffffff; } virtual ULONG Hash(const void *pData) { WRAPPER_NO_CONTRACT; return (HashStringA(reinterpret_cast(pData))); } virtual int Cmp(const void *pData, void *pItem); private: StgPoolReadOnly *m_Pool; // String pool which this hashes. }; //***************************************************************************** // This version is for byte streams with a 2 byte WORD giving the length of // the data. //***************************************************************************** typedef STRINGHASH BLOBHASH; class CBlobPoolHash : public CChainedHash { friend class VerifyLayoutsMD; public: CBlobPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) { LIMITED_METHOD_CONTRACT; } virtual bool InUse(BLOBHASH *pItem) { LIMITED_METHOD_CONTRACT; return (pItem->iOffset != 0xffffffff); } virtual void SetFree(BLOBHASH *pItem) { LIMITED_METHOD_CONTRACT; pItem->iOffset = 0xffffffff; } virtual ULONG Hash(const void *pData) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_FORBID_FAULT; ULONG ulSize; ulSize = CPackedLen::GetLength(pData); ulSize += CPackedLen::Size(ulSize); return (HashBytes(reinterpret_cast(pData), ulSize)); } virtual int Cmp(const void *pData, void *pItem); private: StgPoolReadOnly *m_Pool; // Blob pool which this hashes. }; //***************************************************************************** // This hash class will handle guids inside of a chunk of the pool. //***************************************************************************** struct GUIDHASH : HASHLINK { ULONG iIndex; // Index of this item. }; class CGuidPoolHash : public CChainedHash { friend class VerifyLayoutsMD; public: CGuidPoolHash(StgPoolReadOnly *pool) : m_Pool(pool) { LIMITED_METHOD_CONTRACT; } virtual bool InUse(GUIDHASH *pItem) { LIMITED_METHOD_CONTRACT; return (pItem->iIndex != 0xffffffff); } virtual void SetFree(GUIDHASH *pItem) { LIMITED_METHOD_CONTRACT; pItem->iIndex = 0xffffffff; } virtual ULONG Hash(const void *pData) { WRAPPER_NO_CONTRACT; return (HashBytes(reinterpret_cast(pData), sizeof(GUID))); } virtual int Cmp(const void *pData, void *pItem); private: StgPoolReadOnly *m_Pool; // The GUID pool which this hashes. }; #endif // __StgPooli_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stresslog.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /*************************************************************************************/ /* StressLog.h */ /*************************************************************************************/ /* StressLog is a binary, memory based circular queue of logging messages. It is intended to be used in retail builds during stress runs (activated by registry key), so to help find bugs that only turn up during stress runs. It is meant to have very low overhead and can not cause deadlocks, etc. It is however thread safe */ /* The log has a very simple structure, and it meant to be dumped from a NTSD extension (eg. strike). There is no memory allocation system calls etc to purtub things */ // ****************************************************************************** // WARNING!!!: These classes are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/stresslog.h // Parser: https://github.com/dotnet/diagnostics/blob/main/src/SOS/Strike/stressLogDump.cpp // ****************************************************************************** /*************************************************************************************/ #ifndef StressLog_h #define StressLog_h 1 #include "log.h" #if defined(STRESS_LOG) && !defined(FEATURE_NO_STRESSLOG) #ifndef STRESS_LOG_ANALYZER #include "holder.h" #include "staticcontract.h" #include "mscoree.h" #include "clrinternal.h" #ifdef STRESS_LOG_READONLY #include // offsetof #else //STRESS_LOG_READONLY #include "clrhost.h" #endif //STRESS_LOG_READONLY #ifndef _ASSERTE #define _ASSERTE(expr) #endif #else #include // offsetof #endif // STRESS_LOG_ANALYZER /* The STRESS_LOG* macros work like printf. In fact the use printf in their implementation so all printf format specifications work. In addition the Stress log dumper knows about certain suffixes for the %p format specification (normally used to print a pointer) %pM // The pointer is a MethodDesc %pT // The pointer is a type (MethodTable) %pV // The pointer is a C++ Vtable pointer (useful for distinguishing different types of frames %pK // The pointer is a code address (used for stack track) */ /* STRESS_LOG_VA was added to allow sending GC trace output to the stress log. msg must be enclosed in ()'s and contain a format string followed by 0 to 12 arguments. The arguments must be numbers or string literals. This was done because GC Trace uses dprintf which doesn't contain info on how many arguments are getting passed in and using va_args would require parsing the format string during the GC */ #define STRESS_LOG_VA(dprintfLevel,msg) do { \ if (StressLog::LogOn(LF_GC, LL_ALWAYS)) \ StressLog::LogMsg(LL_ALWAYS, LF_ALWAYS|(dprintfLevel<<16)|LF_GC, StressLogMsg msg); \ LOGALWAYS(msg); \ } while(0) #define STRESS_LOG0(facility, level, msg) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 0, msg); \ LOG((facility, level, msg)); \ } while(0) #define STRESS_LOG1(facility, level, msg, data1) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 1, msg, (void*)(size_t)(data1));\ LOG((facility, level, msg, data1)); \ } while(0) #define STRESS_LOG2(facility, level, msg, data1, data2) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 2, msg, \ (void*)(size_t)(data1), (void*)(size_t)(data2)); \ LOG((facility, level, msg, data1, data2)); \ } while(0) #define STRESS_LOG2_CHECK_EE_STARTED(facility, level, msg, data1, data2) do { \ if (g_fEEStarted) \ STRESS_LOG2(facility, level, msg, data1, data2); \ else \ LOG((facility, level, msg, data1, data2)); \ } while(0) #define STRESS_LOG3(facility, level, msg, data1, data2, data3) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 3, msg, \ (void*)(size_t)(data1),(void*)(size_t)(data2),(void*)(size_t)(data3)); \ LOG((facility, level, msg, data1, data2, data3)); \ } while(0) #define STRESS_LOG4(facility, level, msg, data1, data2, data3, data4) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 4, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4)); \ LOG((facility, level, msg, data1, data2, data3, data4)); \ } while(0) #define STRESS_LOG5(facility, level, msg, data1, data2, data3, data4, data5) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 5, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ (void*)(size_t)(data5)); \ LOG((facility, level, msg, data1, data2, data3, data4, data5)); \ } while(0) #define STRESS_LOG6(facility, level, msg, data1, data2, data3, data4, data5, data6) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 6, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ (void*)(size_t)(data5), (void*)(size_t)(data6)); \ LOG((facility, level, msg, data1, data2, data3, data4, data5, data6)); \ } while(0) #define STRESS_LOG7(facility, level, msg, data1, data2, data3, data4, data5, data6, data7) do { \ if (StressLog::LogOn(facility, level)) \ StressLog::LogMsg(level, facility, 7, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ (void*)(size_t)(data5), (void*)(size_t)(data6), (void*)(size_t)(data7)); \ LOG((facility, level, msg, data1, data2, data3, data4, data5, data6, data7)); \ } while(0) #define STRESS_LOG_COND0(facility, level, cond, msg) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 0, msg); \ LOG((facility, level, msg)); \ } while(0) #define STRESS_LOG_COND1(facility, level, cond, msg, data1) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 1, msg, (void*)(size_t)(data1)); \ LOG((facility, level, msg, data1)); \ } while(0) #define STRESS_LOG_COND2(facility, level, cond, msg, data1, data2) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 2, msg, \ (void*)(size_t)(data1), (void*)(size_t)(data2)); \ LOG((facility, level, msg, data1, data2)); \ } while(0) #define STRESS_LOG_COND3(facility, level, cond, msg, data1, data2, data3) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 3, msg, \ (void*)(size_t)(data1),(void*)(size_t)(data2),(void*)(size_t)(data3)); \ LOG((facility, level, msg, data1, data2, data3)); \ } while(0) #define STRESS_LOG_COND4(facility, level, cond, msg, data1, data2, data3, data4) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 4, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4)); \ LOG((facility, level, msg, data1, data2, data3, data4)); \ } while(0) #define STRESS_LOG_COND5(facility, level, cond, msg, data1, data2, data3, data4, data5) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 5, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ (void*)(size_t)(data5)); \ LOG((facility, level, msg, data1, data2, data3, data4, data5)); \ } while(0) #define STRESS_LOG_COND6(facility, level, cond, msg, data1, data2, data3, data4, data5, data6) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 6, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ (void*)(size_t)(data5), (void*)(size_t)(data6)); \ LOG((facility, level, msg, data1, data2, data3, data4, data5, data6)); \ } while(0) #define STRESS_LOG_COND7(facility, level, cond, msg, data1, data2, data3, data4, data5, data6, data7) do { \ if (StressLog::LogOn(facility, level) && (cond)) \ StressLog::LogMsg(level, facility, 7, msg, (void*)(size_t)(data1), \ (void*)(size_t)(data2),(void*)(size_t)(data3),(void*)(size_t)(data4), \ (void*)(size_t)(data5), (void*)(size_t)(data6), (void*)(size_t)(data7)); \ LOG((facility, level, msg, data1, data2, data3, data4, data5, data6, data7)); \ } while(0) #define STRESS_LOG_RESERVE_MEM(numChunks) do { \ if (StressLog::StressLogOn(LF_ALL, LL_ALWAYS)) \ {StressLog::ReserveStressLogChunks (numChunks);} \ } while(0) // !!! WARNING !!! // !!! DO NOT ADD STRESS_LOG8, as the stress log infrastructure supports a maximum of 7 arguments // !!! WARNING !!! #define STRESS_LOG_PLUG_MOVE(plug_start, plug_end, plug_delta) do { \ if (StressLog::LogOn(LF_GC, LL_INFO1000)) \ StressLog::LogMsg(LL_INFO1000, LF_GC, 3, ThreadStressLog::gcPlugMoveMsg(), \ (void*)(size_t)(plug_start), (void*)(size_t)(plug_end), (void*)(size_t)(plug_delta)); \ LOG((LF_GC, LL_INFO10000, ThreadStressLog::gcPlugMoveMsg(), (plug_start), (plug_end), (plug_delta))); \ } while(0) #define STRESS_LOG_ROOT_PROMOTE(root_addr, objPtr, methodTable) do { \ if (StressLog::LogOn(LF_GC|LF_GCROOTS, LL_INFO1000)) \ StressLog::LogMsg(LL_INFO1000, LF_GC|LF_GCROOTS, 3, ThreadStressLog::gcRootPromoteMsg(), \ (void*)(size_t)(root_addr), (void*)(size_t)(objPtr), (void*)(size_t)(methodTable)); \ LOG((LF_GC|LF_GCROOTS, LL_INFO1000000, ThreadStressLog::gcRootPromoteMsg(), (root_addr), (objPtr), (methodTable))); \ } while(0) #define STRESS_LOG_ROOT_RELOCATE(root_addr, old_value, new_value, methodTable) do { \ if (StressLog::LogOn(LF_GC|LF_GCROOTS, LL_INFO1000) && ((size_t)(old_value) != (size_t)(new_value))) \ StressLog::LogMsg(LL_INFO1000, LF_GC|LF_GCROOTS, 4, ThreadStressLog::gcRootMsg(), \ (void*)(size_t)(root_addr), (void*)(size_t)(old_value), \ (void*)(size_t)(new_value), (void*)(size_t)(methodTable)); \ LOG((LF_GC|LF_GCROOTS, LL_INFO10000, ThreadStressLog::gcRootMsg(), (root_addr), (old_value), (new_value), (methodTable))); \ } while(0) #define STRESS_LOG_GC_START(gcCount, Gen, collectClasses) do { \ if (StressLog::LogOn(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10)) \ StressLog::LogMsg(LL_INFO10, LF_GCROOTS|LF_GC|LF_GCALLOC, 3, ThreadStressLog::gcStartMsg(), \ (void*)(size_t)(gcCount), (void*)(size_t)(Gen), (void*)(size_t)(collectClasses)); \ LOG((LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10, ThreadStressLog::gcStartMsg(), (gcCount), (Gen), (collectClasses))); \ } while(0) #define STRESS_LOG_GC_END(gcCount, Gen, collectClasses) do { \ if (StressLog::LogOn(LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10)) \ StressLog::LogMsg(LL_INFO10, LF_GCROOTS|LF_GC|LF_GCALLOC, 3, ThreadStressLog::gcEndMsg(), \ (void*)(size_t)(gcCount), (void*)(size_t)(Gen), (void*)(size_t)(collectClasses), 0); \ LOG((LF_GCROOTS|LF_GC|LF_GCALLOC, LL_INFO10, ThreadStressLog::gcEndMsg(), (gcCount), (Gen), (collectClasses))); \ } while(0) #if defined(_DEBUG) #define MAX_CALL_STACK_TRACE 20 #define STRESS_LOG_OOM_STACK(size) do { \ CantAllocHolder caHolder; \ if (StressLog::LogOn(LF_EEMEM, LL_ALWAYS)) \ { \ StressLog::LogMsgOL("OOM on alloc of size %x \n", (void*)(size_t)(size)); \ StressLog::LogCallStack ("OOM"); \ } \ } while(0) #define STRESS_LOG_GC_STACK do { \ if (StressLog::LogOn(LF_GC |LF_GCINFO, LL_ALWAYS)) \ { \ StressLog::LogMsgOL("GC is triggered \n"); \ StressLog::LogCallStack ("GC"); \ } \ } while(0) #else //!_DEBUG #define STRESS_LOG_OOM_STACK(size) #define STRESS_LOG_GC_STACK #endif //_DEBUG void ReplacePid(LPCWSTR original, LPWSTR replaced, size_t replacedLength); class ThreadStressLog; struct StressLogMsg; /*************************************************************************************/ /* a log is a circular queue of messages */ class StressLog { public: static void Initialize(unsigned facilities, unsigned level, unsigned maxBytesPerThread, unsigned maxBytesTotal, void* moduleBase, LPWSTR logFilename = nullptr); static void Terminate(BOOL fProcessDetach=FALSE); static void ThreadDetach(); // call at DllMain THREAD_DETACH if you want to recycle thread logs #ifndef STRESS_LOG_ANALYZER static int NewChunk () { return InterlockedIncrement (&theLog.totalChunk); } static int ChunkDeleted () { return InterlockedDecrement (&theLog.totalChunk); } #endif //STRESS_LOG_ANALYZER //the result is not 100% accurate. If multiple threads call this function at the same time, //we could allow the total size be bigger than required. But the memory won't grow forever //and this is not critical so we don't try to fix the race static BOOL AllowNewChunk (LONG numChunksInCurThread); //preallocate Stress log chunks for current thread. The memory we could preallocate is still //bounded by per thread size limit and total size limit. If chunksToReserve is 0, we will try to //preallocate up to per thread size limit static BOOL ReserveStressLogChunks (unsigned chunksToReserve); // used by out of process debugger to dump the stress log to 'fileName' // IDebugDataSpaces is the NTSD execution callback for getting process memory. // This function is defined in the tools\strike\stressLogDump.cpp file static HRESULT Dump(ULONG64 logAddr, const char* fileName, struct IDebugDataSpaces* memCallBack); static BOOL StressLogOn(unsigned facility, unsigned level); static BOOL ETWLogOn(unsigned facility, unsigned level); static BOOL LogOn(unsigned facility, unsigned level); // private: unsigned facilitiesToLog; // Bitvector of facilities to log (see loglf.h) unsigned levelToLog; // log level (see log.h) unsigned MaxSizePerThread; // maximum number of bytes each thread should have before wrapping unsigned MaxSizeTotal; // maximum memory allowed for stress log Volatile totalChunk; // current number of total chunks allocated Volatile logs; // the list of logs for every thread. unsigned padding; // Preserve the layout for SOS Volatile deadCount; // count of dead threads in the log CRITSEC_COOKIE lock; // lock unsigned __int64 tickFrequency; // number of ticks per second unsigned __int64 startTimeStamp; // start time from when tick counter started FILETIME startTime; // time the application started SIZE_T moduleOffset; // Used to compute format strings. struct ModuleDesc { uint8_t* baseAddress; size_t size; }; static const size_t MAX_MODULES = 5; ModuleDesc modules[MAX_MODULES]; // descriptor of the modules images #if defined(HOST_64BIT) #define MEMORY_MAPPED_STRESSLOG #ifdef HOST_WINDOWS #define MEMORY_MAPPED_STRESSLOG_BASE_ADDRESS (void*)0x400000000000 #else #define MEMORY_MAPPED_STRESSLOG_BASE_ADDRESS nullptr #endif #endif #ifdef STRESS_LOG_ANALYZER static size_t writing_base_address; static size_t reading_base_address; template static T* TranslateMemoryMappedPointer(T* input) { if (input == nullptr) { return nullptr; } return ((T*)(((uint8_t*)input) - writing_base_address + reading_base_address)); } #else template static T* TranslateMemoryMappedPointer(T* input) { return input; } #endif #ifdef MEMORY_MAPPED_STRESSLOG // // Intentionally avoid unmapping the file during destructor to avoid a race // condition between additional logging in other thread and the destructor. // // The operating system will make sure the file get unmapped during process shutdown // LPVOID hMapView; static void* AllocMemoryMapped(size_t n); struct StressLogHeader { size_t headerSize; // size of this header including size field and moduleImage uint32_t magic; // must be 'STRL' uint32_t version; // must be 0x00010001 uint8_t* memoryBase; // base address of the memory mapped file uint8_t* memoryCur; // highest address currently used uint8_t* memoryLimit; // limit that can be used Volatile logs; // the list of logs for every thread. uint64_t tickFrequency; // number of ticks per second uint64_t startTimeStamp; // start time from when tick counter started uint64_t threadsWithNoLog; // threads that didn't get a log uint64_t reserved[15]; // for future expansion ModuleDesc modules[MAX_MODULES]; // descriptor of the modules images uint8_t moduleImage[64*1024*1024];// copy of the module images described by modules field }; StressLogHeader* stressLogHeader; // header to find things in the memory mapped file #endif // MEMORY_MAPPED_STRESSLOG static thread_local ThreadStressLog* t_pCurrentThreadLog; // private: static void Enter(CRITSEC_COOKIE dummy = NULL); static void Leave(CRITSEC_COOKIE dummy = NULL); static ThreadStressLog* CreateThreadStressLog(); static ThreadStressLog* CreateThreadStressLogHelper(); static BOOL InlinedStressLogOn(unsigned facility, unsigned level); static BOOL InlinedETWLogOn(unsigned facility, unsigned level); static void LogMsg(unsigned level, unsigned facility, int cArgs, const char* format, ... ); static void LogMsg(unsigned level, unsigned facility, const StressLogMsg& msg); static void AddModule(uint8_t* moduleBase); // Support functions for STRESS_LOG_VA // We disable the warning "conversion from 'type' to 'type' of greater size" since everything will // end up on the stack, and LogMsg will know the size of the variable based on the format string. #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4312 ) #endif static void LogMsgOL(const char* format) { LogMsg(LL_ALWAYS, LF_GC, 0, format); } template < typename T1 > static void LogMsgOL(const char* format, T1 data1) { static_assert_no_msg(sizeof(T1) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 1, format, (void*)(size_t)data1); } template < typename T1, typename T2 > static void LogMsgOL(const char* format, T1 data1, T2 data2) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 2, format, (void*)(size_t)data1, (void*)(size_t)data2); } template < typename T1, typename T2, typename T3 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 3, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3); } template < typename T1, typename T2, typename T3, typename T4 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 4, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4); } template < typename T1, typename T2, typename T3, typename T4, typename T5 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 5, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 6, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 7, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 8, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7, (void*)(size_t)data8); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 9, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7, (void*)(size_t)data8, (void*)(size_t)data9); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9, T10 data10) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*) && sizeof(T10) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 10, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7, (void*)(size_t)data8, (void*)(size_t)data9, (void*)(size_t)data10); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9, T10 data10, T11 data11) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*) && sizeof(T10) <= sizeof(void*) && sizeof(T11) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 11, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7, (void*)(size_t)data8, (void*)(size_t)data9, (void*)(size_t)data10, (void*)(size_t)data11); } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12 > static void LogMsgOL(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9, T10 data10, T11 data11, T12 data12) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*) && sizeof(T10) <= sizeof(void*) && sizeof(T11) <= sizeof(void*) && sizeof(T12) <= sizeof(void*)); LogMsg(LL_ALWAYS, LF_GC, 12, format, (void*)(size_t)data1, (void*)(size_t)data2, (void*)(size_t)data3, (void*)(size_t)data4, (void*)(size_t)data5, (void*)(size_t)data6, (void*)(size_t)data7, (void*)(size_t)data8, (void*)(size_t)data9, (void*)(size_t)data10, (void*)(size_t)data11, (void*)(size_t)data12); } #ifdef _MSC_VER #pragma warning( pop ) #endif // We can only log the stacktrace on DEBUG builds! #ifdef _DEBUG typedef USHORT (__stdcall *PFNRtlCaptureStackBackTrace)( IN ULONG FramesToSkip, IN ULONG FramesToCapture, OUT PVOID * BackTrace, OUT PULONG BackTraceHash); PFNRtlCaptureStackBackTrace RtlCaptureStackBackTrace; static void LogCallStack(const char *const callTag); #endif //_DEBUG // private: // static variables static StressLog theLog; // We only have one log, and this is it }; #ifndef STRESS_LOG_ANALYZER typedef Holder> StressLogLockHolder; #endif //!STRESS_LOG_ANALYZER #if defined(DACCESS_COMPILE) inline BOOL StressLog::LogOn(unsigned facility, unsigned level) { STATIC_CONTRACT_LEAF; STATIC_CONTRACT_SUPPORTS_DAC; // StressLog isn't dacized, and besides we don't want to log to it in DAC builds. return FALSE; } #endif /*************************************************************************************/ /* private classes */ #if defined(_MSC_VER) #pragma warning(disable:4200 4201) // don't warn about 0 sized array below or unnamed structures #endif // The order of fields is important. Keep the prefix length as the first field. // And make sure the timeStamp field is naturally aligned, so we don't waste // space on 32-bit platforms struct StressMsg { static const size_t formatOffsetBits = 26; union { struct { uint32_t numberOfArgs : 3; // at most 7 arguments here uint32_t formatOffset : formatOffsetBits; // offset of string in mscorwks uint32_t numberOfArgsX : 3; // extend number of args in a backward compat way }; uint32_t fmtOffsCArgs; // for optimized access }; uint32_t facility; // facility used to log the entry uint64_t timeStamp; // time when mssg was logged void* args[0]; // size given by numberOfArgs static const size_t maxArgCnt = 63; static const size_t maxOffset = 1 << formatOffsetBits; static size_t maxMsgSize () { return sizeof(StressMsg) + maxArgCnt*sizeof(void*); } friend class ThreadStressLog; friend class StressLog; }; #ifdef HOST_64BIT #define STRESSLOG_CHUNK_SIZE (32 * 1024) #else //HOST_64BIT #define STRESSLOG_CHUNK_SIZE (16 * 1024) #endif //HOST_64BIT #define GC_STRESSLOG_MULTIPLY 5 // a chunk of memory for stress log struct StressLogChunk { StressLogChunk * prev; StressLogChunk * next; char buf[STRESSLOG_CHUNK_SIZE]; DWORD dwSig1; DWORD dwSig2; #if !defined(STRESS_LOG_READONLY) #ifdef MEMORY_MAPPED_STRESSLOG static bool s_memoryMapped; #endif //MEMORY_MAPPED_STRESSLOG #ifdef HOST_WINDOWS static HANDLE s_LogChunkHeap; #endif //HOST_WINDOWS void * operator new (size_t size) throw() { if (IsInCantAllocStressLogRegion ()) { return NULL; } #ifdef MEMORY_MAPPED_STRESSLOG if (s_memoryMapped) return StressLog::AllocMemoryMapped(size); #endif //MEMORY_MAPPED_STRESSLOG #ifdef HOST_WINDOWS _ASSERTE(s_LogChunkHeap); return HeapAlloc(s_LogChunkHeap, 0, size); #else return malloc(size); #endif //HOST_WINDOWS } void operator delete (void * chunk) { #ifdef MEMORY_MAPPED_STRESSLOG if (s_memoryMapped) return; #endif //MEMORY_MAPPED_STRESSLOG #ifdef HOST_WINDOWS _ASSERTE(s_LogChunkHeap); HeapFree (s_LogChunkHeap, 0, chunk); #else free(chunk); #endif //HOST_WINDOWS } #endif //!STRESS_LOG_READONLY StressLogChunk (StressLogChunk * p = NULL, StressLogChunk * n = NULL) :prev (p), next (n), dwSig1 (0xCFCFCFCF), dwSig2 (0xCFCFCFCF) {} char * StartPtr () { return buf; } char * EndPtr () { return buf + STRESSLOG_CHUNK_SIZE; } BOOL IsValid () const { return dwSig1 == 0xCFCFCFCF && dwSig2 == 0xCFCFCFCF; } }; // This class implements a circular stack of variable sized elements // .The buffer between startPtr-endPtr is used in a circular manner // to store instances of the variable-sized struct StressMsg. // The StressMsg are always aligned to endPtr, while the space // left between startPtr and the last element is 0-padded. // .curPtr points to the most recently written log message // .readPtr points to the next log message to be dumped // .hasWrapped is TRUE while dumping the log, if we had wrapped // past the endPtr marker, back to startPtr // The AdvanceRead/AdvanceWrite operations simply update the // readPtr / curPtr fields. thecaller is responsible for reading/writing // to the corresponding field class ThreadStressLog { #ifdef STRESS_LOG_ANALYZER public: #endif ThreadStressLog* next; // we keep a linked list of these uint64_t threadId; // the id for the thread using this buffer uint8_t isDead; // Is this thread dead uint8_t readHasWrapped; // set when read ptr has passed chunkListTail uint8_t writeHasWrapped; // set when write ptr has passed chunkListHead StressMsg* curPtr; // where packets are being put on the queue StressMsg* readPtr; // where we are reading off the queue (used during dumping) StressLogChunk * chunkListHead; //head of a list of stress log chunks StressLogChunk * chunkListTail; //tail of a list of stress log chunks StressLogChunk * curReadChunk; //the stress log chunk we are currently reading StressLogChunk * curWriteChunk; //the stress log chunk we are currently writing long chunkListLength; // how many stress log chunks are in this stress log #ifdef STRESS_LOG_READONLY FORCEINLINE StressMsg* AdvanceRead(); #endif //STRESS_LOG_READONLY FORCEINLINE StressMsg* AdvanceWrite(int cArgs); #ifdef STRESS_LOG_READONLY inline StressMsg* AdvReadPastBoundary(); #endif //STRESS_LOG_READONLY inline StressMsg* AdvWritePastBoundary(int cArgs); #ifdef STRESS_LOG_READONLY ThreadStressLog* FindLatestThreadLog() const; #endif //STRESS_LOG_READONLY friend class StressLog; #if !defined(STRESS_LOG_READONLY) && !defined(STRESS_LOG_ANALYZER) FORCEINLINE BOOL GrowChunkList () { _ASSERTE (chunkListLength >= 1); if (!StressLog::AllowNewChunk (chunkListLength)) { return FALSE; } StressLogChunk * newChunk = new StressLogChunk (chunkListTail, chunkListHead); if (newChunk == NULL) { return FALSE; } StressLog::NewChunk (); chunkListLength++; chunkListHead->prev = newChunk; chunkListTail->next = newChunk; chunkListHead = newChunk; return TRUE; } #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER public: #if !defined(STRESS_LOG_READONLY) && !defined(STRESS_LOG_ANALYZER) ThreadStressLog () { chunkListHead = chunkListTail = curWriteChunk = NULL; StressLogChunk * newChunk = new StressLogChunk; //OOM or in cantalloc region if (newChunk == NULL) { return; } StressLog::NewChunk (); newChunk->prev = newChunk; newChunk->next = newChunk; chunkListHead = chunkListTail = newChunk; next = NULL; threadId = 0; isDead = TRUE; curPtr = NULL; readPtr = NULL; writeHasWrapped = FALSE; curReadChunk = NULL; curWriteChunk = NULL; chunkListLength = 1; } #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER #if defined(MEMORY_MAPPED_STRESSLOG) && !defined(STRESS_LOG_ANALYZER) void* __cdecl operator new(size_t n, const NoThrow&) NOEXCEPT; void __cdecl operator delete (void * chunk); #endif ~ThreadStressLog () { //no thing to do if the list is empty (failed to initialize) if (chunkListHead == NULL) { return; } #if !defined(STRESS_LOG_READONLY) && !defined(STRESS_LOG_ANALYZER) _ASSERTE (chunkListLength >= 1 && chunkListLength <= StressLog::theLog.totalChunk); #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER StressLogChunk * chunk = chunkListHead; do { StressLogChunk * tmp = chunk; chunk = chunk->next; delete tmp; #if !defined(STRESS_LOG_READONLY) && !defined(STRESS_LOG_ANALYZER) StressLog::ChunkDeleted (); #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER } while (chunk != chunkListHead); } void Activate () { #ifndef STRESS_LOG_READONLY //there is no need to zero buffers because we could handle garbage contents threadId = GetCurrentThreadId (); isDead = FALSE; curWriteChunk = chunkListTail; curPtr = (StressMsg *)curWriteChunk->EndPtr (); writeHasWrapped = FALSE; #else //STRESS_LOG_READONLY curReadChunk = curWriteChunk; readPtr = curPtr; readHasWrapped = FALSE; // the last written log, if it wrapped around may have partially overwritten // a previous record. Update curPtr to reflect the last safe beginning of a record, // but curPtr shouldn't wrap around, otherwise it'll break our assumptions about stress // log curPtr = (StressMsg*)((char*)curPtr - StressMsg::maxMsgSize()); if (curPtr < (StressMsg*)curWriteChunk->StartPtr()) { curPtr = (StressMsg *)curWriteChunk->StartPtr(); } //corner case: the log is empty if (readPtr == (StressMsg *)curReadChunk->EndPtr ()) { AdvReadPastBoundary(); } #endif //!STRESS_LOG_READONLY } BOOL IsValid () const { return chunkListHead != NULL && (!curWriteChunk || StressLog::TranslateMemoryMappedPointer(curWriteChunk)->IsValid ()); } #ifdef STRESS_LOG_READONLY // Called while dumping. Returns true after all messages in log were dumped FORCEINLINE BOOL CompletedDump () { return readPtr->timeStamp == 0 //if read has passed end of list but write has not passed head of list yet, we are done //if write has also wrapped, we are at the end if read pointer passed write pointer || (readHasWrapped && (!writeHasWrapped || (curReadChunk == curWriteChunk && readPtr >= curPtr))); } #endif //STRESS_LOG_READONLY #include "gcmsg.inl" static const char* TaskSwitchMsg() { STATIC_CONTRACT_LEAF; return "StressLog TaskSwitch Marker\n"; } void LogMsg(unsigned facility, int cArgs, const char* format, ...); FORCEINLINE void LogMsg (unsigned facility, int cArgs, const char* format, va_list Args); #ifdef STRESS_LOG_READONLY static size_t OffsetOfNext () {return offsetof (ThreadStressLog, next);} static size_t OffsetOfListHead () {return offsetof (ThreadStressLog, chunkListHead);} #endif //STRESS_LOG_READONLY }; #ifdef STRESS_LOG_READONLY /*********************************************************************************/ // Called when dumping the log (by StressLog::Dump()) // Updates readPtr to point to next stress messaage to be dumped // For convenience it returns the new value of readPtr inline StressMsg* ThreadStressLog::AdvanceRead() { STATIC_CONTRACT_LEAF; // advance the marker readPtr = (StressMsg*)((char*)readPtr + sizeof(StressMsg) + readPtr->numberOfArgs*sizeof(void*)); // wrap around if we need to if (readPtr >= (StressMsg *)curReadChunk->EndPtr ()) { AdvReadPastBoundary(); } return readPtr; } // It's the factored-out slow codepath for AdvanceRead() and // is only called by AdvanceRead(). // Updates readPtr to and returns the first stress message >= startPtr inline StressMsg* ThreadStressLog::AdvReadPastBoundary() { STATIC_CONTRACT_LEAF; //if we pass boundary of tail list, we need to set has Wrapped if (curReadChunk == chunkListTail) { readHasWrapped = TRUE; //If write has not wrapped, we know the contents from list head to //cur pointer is garbage, we don't need to read them if (!writeHasWrapped) { return readPtr; } } curReadChunk = curReadChunk->next; void** p = (void**)curReadChunk->StartPtr(); while (*p == NULL && (size_t)(p-(void**)curReadChunk->StartPtr ()) < (StressMsg::maxMsgSize()/sizeof(void*))) { ++p; } // if we failed to find a valid start of a StressMsg fallback to startPtr (since timeStamp==0) if (*p == NULL) { p = (void**) curReadChunk->StartPtr (); } readPtr = (StressMsg*)p; return readPtr; } #endif //STRESS_LOG_READONLY /*********************************************************************************/ // Called at runtime when writing the log (by StressLog::LogMsg()) // Updates curPtr to point to the next spot in the log where we can write // a stress message with cArgs arguments // For convenience it returns a pointer to the empty slot where we can // write the next stress message. // cArgs is the number of arguments in the message to be written. inline StressMsg* ThreadStressLog::AdvanceWrite(int cArgs) { STATIC_CONTRACT_LEAF; // _ASSERTE(cArgs <= StressMsg::maxArgCnt); // advance the marker StressMsg* p = (StressMsg*)((char*)curPtr - sizeof(StressMsg) - cArgs*sizeof(void*)); //past start of current chunk //wrap around if we need to if (p < (StressMsg*)curWriteChunk->StartPtr ()) { return AdvWritePastBoundary(cArgs); } else { return p; } } // It's the factored-out slow codepath for AdvanceWrite() and // is only called by AdvanceWrite(). // Returns the stress message flushed against endPtr // In addition it writes NULLs b/w the startPtr and curPtr inline StressMsg* ThreadStressLog::AdvWritePastBoundary(int cArgs) { STATIC_CONTRACT_WRAPPER; #if !defined(STRESS_LOG_READONLY) && !defined(STRESS_LOG_ANALYZER) //zeroed out remaining buffer memset (curWriteChunk->StartPtr (), 0, (BYTE *)curPtr - (BYTE *)curWriteChunk->StartPtr ()); //if we are already at head of the list, try to grow the list if (curWriteChunk == chunkListHead) { GrowChunkList (); } #endif //!STRESS_LOG_READONLY && !STRESS_LOG_ANALYZER curWriteChunk = curWriteChunk->prev; #ifndef STRESS_LOG_READONLY if (curWriteChunk == chunkListTail) { writeHasWrapped = TRUE; } #endif //STRESS_LOG_READONLY return (StressMsg*)((char*)curWriteChunk->EndPtr () - sizeof(StressMsg) - cArgs * sizeof(void*)); } struct StressLogMsg { int m_cArgs; const char* m_format; void* m_args[16]; StressLogMsg(const char* format) : m_cArgs(0), m_format(format) { } template < typename T1 > StressLogMsg(const char* format, T1 data1) : m_cArgs(1), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; } template < typename T1, typename T2 > StressLogMsg(const char* format, T1 data1, T2 data2) : m_cArgs(2), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; } template < typename T1, typename T2, typename T3 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3) : m_cArgs(3), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; } template < typename T1, typename T2, typename T3, typename T4 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4) : m_cArgs(4), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; } template < typename T1, typename T2, typename T3, typename T4, typename T5 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5) : m_cArgs(5), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6) : m_cArgs(6), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7) : m_cArgs(7), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; m_args[6] = (void*)(size_t)data7; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8) : m_cArgs(8), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; m_args[6] = (void*)(size_t)data7; m_args[7] = (void*)(size_t)data8; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9) : m_cArgs(9), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; m_args[6] = (void*)(size_t)data7; m_args[7] = (void*)(size_t)data8; m_args[8] = (void*)(size_t)data9; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9, T10 data10) : m_cArgs(10), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*) && sizeof(T10) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; m_args[6] = (void*)(size_t)data7; m_args[7] = (void*)(size_t)data8; m_args[8] = (void*)(size_t)data9; m_args[9] = (void*)(size_t)data10; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9, T10 data10, T11 data11) : m_cArgs(11), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*) && sizeof(T10) <= sizeof(void*) && sizeof(T11) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; m_args[6] = (void*)(size_t)data7; m_args[7] = (void*)(size_t)data8; m_args[8] = (void*)(size_t)data9; m_args[9] = (void*)(size_t)data10; m_args[10] = (void*)(size_t)data11; } template < typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10, typename T11, typename T12 > StressLogMsg(const char* format, T1 data1, T2 data2, T3 data3, T4 data4, T5 data5, T6 data6, T7 data7, T8 data8, T9 data9, T10 data10, T11 data11, T12 data12) : m_cArgs(12), m_format(format) { static_assert_no_msg(sizeof(T1) <= sizeof(void*) && sizeof(T2) <= sizeof(void*) && sizeof(T3) <= sizeof(void*) && sizeof(T4) <= sizeof(void*) && sizeof(T5) <= sizeof(void*) && sizeof(T6) <= sizeof(void*) && sizeof(T7) <= sizeof(void*) && sizeof(T8) <= sizeof(void*) && sizeof(T9) <= sizeof(void*) && sizeof(T10) <= sizeof(void*) && sizeof(T11) <= sizeof(void*) && sizeof(T12) <= sizeof(void*)); m_args[0] = (void*)(size_t)data1; m_args[1] = (void*)(size_t)data2; m_args[2] = (void*)(size_t)data3; m_args[3] = (void*)(size_t)data4; m_args[4] = (void*)(size_t)data5; m_args[5] = (void*)(size_t)data6; m_args[6] = (void*)(size_t)data7; m_args[7] = (void*)(size_t)data8; m_args[8] = (void*)(size_t)data9; m_args[9] = (void*)(size_t)data10; m_args[10] = (void*)(size_t)data11; m_args[11] = (void*)(size_t)data12; } }; #else // STRESS_LOG #define STRESS_LOG_VA(level,msg) do { } while(0) #define STRESS_LOG0(facility, level, msg) do { } while(0) #define STRESS_LOG1(facility, level, msg, data1) do { } while(0) #define STRESS_LOG2(facility, level, msg, data1, data2) do { } while(0) #define STRESS_LOG2_CHECK_EE_STARTED(facility, level, msg, data1, data2)do { } while(0) #define STRESS_LOG3(facility, level, msg, data1, data2, data3) do { } while(0) #define STRESS_LOG4(facility, level, msg, data1, data2, data3, data4) do { } while(0) #define STRESS_LOG5(facility, level, msg, data1, data2, data3, data4, data5) do { } while(0) #define STRESS_LOG6(facility, level, msg, data1, data2, data3, data4, data5, data6) do { } while(0) #define STRESS_LOG7(facility, level, msg, data1, data2, data3, data4, data5, data6, data7) do { } while(0) #define STRESS_LOG_PLUG_MOVE(plug_start, plug_end, plug_delta) do { } while(0) #define STRESS_LOG_ROOT_PROMOTE(root_addr, objPtr, methodTable) do { } while(0) #define STRESS_LOG_ROOT_RELOCATE(root_addr, old_value, new_value, methodTable) do { } while(0) #define STRESS_LOG_GC_START(gcCount, Gen, collectClasses) do { } while(0) #define STRESS_LOG_GC_END(gcCount, Gen, collectClasses) do { } while(0) #define STRESS_LOG_OOM_STACK(size) do { } while(0) #define STRESS_LOG_GC_STACK(size) do { } while(0) #define STRESS_LOG_RESERVE_MEM(numChunks) do {} while (0) #endif // STRESS_LOG #endif // StressLog_h ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stringarraylist.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef STRINGARRAYLIST_H_ #define STRINGARRAYLIST_H_ // // StringArrayList is a simple class which is used to contain a growable // list of Strings, stored in chunks. Based on top of ArrayList #include "arraylist.h" class StringArrayList { ArrayList m_Elements; public: DWORD GetCount() const; SString& operator[] (DWORD idx) const; SString& Get (DWORD idx) const; #ifndef DACCESS_COMPILE void Append(const SString& string); void AppendIfNotThere(const SString& string); #endif ~StringArrayList(); }; #include "stringarraylist.inl" #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/stringarraylist.inl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include "ex.h" inline SString& StringArrayList::operator[] (DWORD idx) const { WRAPPER_NO_CONTRACT; return Get(idx); } inline SString& StringArrayList::Get (DWORD idx) const { WRAPPER_NO_CONTRACT; PTR_SString ppRet=(PTR_SString)m_Elements.Get(idx); return *ppRet; } inline DWORD StringArrayList::GetCount() const { WRAPPER_NO_CONTRACT; return m_Elements.GetCount(); } #ifndef DACCESS_COMPILE inline void StringArrayList::Append(const SString& string) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; NewHolder pAdd=new SString(string); pAdd->Normalize(); IfFailThrow(m_Elements.Append(pAdd)); pAdd.SuppressRelease(); } inline void StringArrayList::AppendIfNotThere(const SString& string) { CONTRACTL { THROWS; GC_NOTRIGGER; } CONTRACTL_END; for (DWORD i=0;i #include // // Holder classes for types returned from and used in strong name APIs // // Holder for any memory allocated by the strong name APIs template void VoidStrongNameFreeBuffer(_In_ T *pBuffer) { StrongNameFreeBuffer(reinterpret_cast(pBuffer)); } template using StrongNameBufferHolder = SpecializedWrapper<_TYPE, VoidStrongNameFreeBuffer<_TYPE>>; #endif // !__STRONGNAME_HOLDERS_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/strongnameinternal.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Strong name APIs which are not exposed publicly, but are built into StrongName.lib // #ifndef _STRONGNAME_INTERNAL_H #define _STRONGNAME_INTERNAL_H // Public key blob binary format. typedef struct { unsigned int SigAlgID; // (ALG_ID) signature algorithm used to create the signature unsigned int HashAlgID; // (ALG_ID) hash algorithm used to create the signature ULONG cbPublicKey; // length of the key in bytes BYTE PublicKey[1]; // variable length byte array containing the key value in format output by CryptoAPI } PublicKeyBlob; // Determine the number of bytes in a public key DWORD StrongNameSizeOfPublicKey(const PublicKeyBlob &keyPublicKey); bool StrongNameIsValidPublicKey(_In_reads_(cbPublicKeyBlob) const BYTE *pbPublicKeyBlob, DWORD cbPublicKeyBlob); bool StrongNameIsValidPublicKey(const PublicKeyBlob &keyPublicKey); // Determine if a public key is the ECMA key bool StrongNameIsEcmaKey(_In_reads_(cbKey) const BYTE *pbKey, DWORD cbKey); bool StrongNameIsEcmaKey(const PublicKeyBlob &keyPublicKey); HRESULT StrongNameTokenFromPublicKey(BYTE* pbPublicKeyBlob, // [in] public key blob ULONG cbPublicKeyBlob, BYTE** ppbStrongNameToken, // [out] strong name token ULONG* pcbStrongNameToken); VOID StrongNameFreeBuffer(BYTE* pbMemory); #endif // !_STRONGNAME_INTERNAL_H ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/switches.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // switches.h switch configuration of common runtime features // #define STRESS_HEAP #define VERIFY_HEAP #define GC_CONFIG_DRIVEN // define this to test data safety for the DAC. See code:DataTest::TestDataSafety. #define TEST_DATA_CONSISTENCY #if !defined(STRESS_LOG) && !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) #define STRESS_LOG #endif #if defined(_DEBUG) && !defined(DACCESS_COMPILE) #define USE_CHECKED_OBJECTREFS #endif #ifndef TARGET_64BIT #define FAT_DISPATCH_TOKENS #endif #define FEATURE_SHARE_GENERIC_CODE #if defined(_DEBUG) && !defined(DACCESS_COMPILE) #define LOGGING #endif #if !defined(FEATURE_UTILCODE_NO_DEPENDENCIES) // Failpoint support #if defined(_DEBUG) && !defined(DACCESS_COMPILE) && !defined(TARGET_UNIX) #define FAILPOINTS_ENABLED #endif #endif //!defined(FEATURE_UTILCODE_NO_DEPENDENCIES) #if 0 // Enable to track details of EESuspension #define TIME_SUSPEND #endif // 0 #ifndef DACCESS_COMPILE // Enabled to track GC statistics #define GC_STATS #endif #if defined(TARGET_X86) || defined(TARGET_ARM) #define USE_LAZY_PREFERRED_RANGE 0 #elif defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_S390X) || defined(TARGET_LOONGARCH64) || defined(TARGET_POWERPC64) #if defined(HOST_UNIX) // In PAL we have a smechanism that reserves memory on start up that is // close to libcoreclr and intercepts calls to VirtualAlloc to serve back // from this area. #define USE_LAZY_PREFERRED_RANGE 0 #else // On Windows we lazily try to reserve memory close to coreclr.dll. #define USE_LAZY_PREFERRED_RANGE 1 #endif #else #error Please add a new #elif clause and define all portability macros for the new platform #endif #if defined(HOST_64BIT) #define JIT_IS_ALIGNED #endif // ALLOW_SXS_JIT enables AltJit support for JIT-ing, via COMPlus_AltJit / COMPlus_AltJitName. // ALLOW_SXS_JIT_NGEN enables AltJit support for NGEN, via COMPlus_AltJitNgen / COMPlus_AltJitName. // Note that if ALLOW_SXS_JIT_NGEN is defined, then ALLOW_SXS_JIT must be defined. #define ALLOW_SXS_JIT #define ALLOW_SXS_JIT_NGEN #if !defined(TARGET_UNIX) // PLATFORM_SUPPORTS_THREADSUSPEND is defined for platforms where it is safe to call // SuspendThread. This API is dangerous on non-Windows platforms, as it can lead to // deadlocks, due to low level OS resources that the PAL is not aware of, or due to // the fact that PAL-unaware code in the process may hold onto some OS resources. #define PLATFORM_SUPPORTS_SAFE_THREADSUSPEND #endif // !TARGET_UNIX #if defined(STRESS_HEAP) && defined(_DEBUG) && defined(FEATURE_HIJACK) #define HAVE_GCCOVER #endif // Some platforms may see spurious AVs when GcCoverage is enabled because of races. // Enable further processing to see if they recur. #if defined(HAVE_GCCOVER) && (defined(TARGET_X86) || defined(TARGET_AMD64)) && !defined(TARGET_UNIX) #define GCCOVER_TOLERATE_SPURIOUS_AV #endif //Turns on a startup delay to allow simulation of slower and faster startup times. #define ENABLE_STARTUP_DELAY #ifdef _DEBUG //hurray DAC makes everything more fun - you can't have defines that control whether //or not data members are visible which differ between DAC and non-DAC builds. //All of the _DATA defines match DAC and non-DAC, the other defines here are off in the DAC. #if defined(PROFILING_SUPPORTED_DATA) || defined(PROFILING_SUPPORTED) // See code:ProfControlBlock#TestOnlyELT. #define PROF_TEST_ONLY_FORCE_ELT_DATA // See code:ProfControlBlock#TestOnlyObjectAllocated. #define PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED_DATA #endif // PROFILING_SUPPORTED_DATA || PROFILING_SUPPORTED #if defined(PROFILING_SUPPORTED) // See code:ProfControlBlock#TestOnlyELT. #define PROF_TEST_ONLY_FORCE_ELT // See code:ProfControlBlock#TestOnlyObjectAllocated. #define PROF_TEST_ONLY_FORCE_OBJECT_ALLOCATED #endif // PROFILING_SUPPORTED #endif // _DEBUG // MUST NEVER CHECK IN WITH THIS ENABLED. // This is just for convenience in doing performance investigations in a checked-out enlistment. // #define FEATURE_ENABLE_NO_RANGE_CHECKS // This controls whether a compilation-timing feature that relies on Windows APIs, if available, else direct // hardware instructions (rdtsc), for accessing high-resolution hardware timers is enabled. This is disabled // in Silverlight (just to avoid thinking about whether the extra code space is worthwhile). #define FEATURE_JIT_TIMER // This feature in RyuJIT supersedes the FEATURE_JIT_TIMER. In addition to supporting the time log file, this // feature also supports using COMPlus_JitTimeLogCsv=a.csv, which will dump method-level and phase-level timing // statistics. Also see comments on FEATURE_JIT_TIMER. #define FEATURE_JIT_METHOD_PERF #ifndef FEATURE_USE_ASM_GC_WRITE_BARRIERS // If we're not using assembly write barriers, then this turns on a performance measurement // mode that gathers and prints statistics about # of GC write barriers invokes. // #define FEATURE_COUNT_GC_WRITE_BARRIERS #endif // Enables a mode in which GC is completely conservative in stacks and registers: all stack slots and registers // are treated as potential pinned interior pointers. When enabled, the runtime flag COMPLUS_GCCONSERVATIVE // determines dynamically whether GC is conservative. Note that appdomain unload, LCG and unloadable assemblies // do not work reliably with conservative GC. #define FEATURE_CONSERVATIVE_GC 1 #if (defined(TARGET_ARM) && (!defined(ARM_SOFTFP) || defined(CONFIGURABLE_ARM_ABI))) || defined(TARGET_ARM64) #define FEATURE_HFA #endif // ARM requires that 64-bit primitive types are aligned at 64-bit boundaries for interlocked-like operations. // Additionally the platform ABI requires these types and composite type containing them to be similarly // aligned when passed as arguments. #ifdef TARGET_ARM #define FEATURE_64BIT_ALIGNMENT #endif // Prefer double alignment for structs and arrays with doubles. Put arrays of doubles more agressively // into large object heap for performance because large object heap is 8 byte aligned #if !defined(FEATURE_64BIT_ALIGNMENT) && !defined(HOST_64BIT) #define FEATURE_DOUBLE_ALIGNMENT_HINT #endif #define FEATURE_MINIMETADATA_IN_TRIAGEDUMPS // If defined, support interpretation. #if !defined(TARGET_UNIX) #define FEATURE_STACK_SAMPLING #endif // defined (ALLOW_SXS_JIT) ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/targetosarch.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef targetosarch_h #define targetosarch_h class TargetOS { public: #ifdef TARGET_WINDOWS #define TARGET_WINDOWS_POSSIBLY_SUPPORTED static const bool IsWindows = true; static const bool IsUnix = false; static const bool IsMacOS = false; #elif defined(TARGET_UNIX) #define TARGET_UNIX_POSSIBLY_SUPPORTED static const bool IsWindows = false; static const bool IsUnix = true; #if defined(TARGET_OSX) static const bool IsMacOS = true; #else static const bool IsMacOS = false; #endif #else #define TARGET_WINDOWS_POSSIBLY_SUPPORTED #define TARGET_UNIX_POSSIBLY_SUPPORTED #define TARGET_OS_RUNTIMEDETERMINED static bool OSSettingConfigured; static bool IsWindows; static bool IsUnix; static bool IsMacOS; #endif }; class TargetArchitecture { public: #ifdef TARGET_ARM static const bool IsX86 = false; static const bool IsX64 = false; static const bool IsArm64 = false; static const bool IsArm32 = true; static const bool IsArmArch = true; static const bool IsLoongArch64 = false; #elif defined(TARGET_ARM64) static const bool IsX86 = false; static const bool IsX64 = false; static const bool IsArm64 = true; static const bool IsArm32 = false; static const bool IsArmArch = true; static const bool IsLoongArch64 = false; #elif defined(TARGET_AMD64) static const bool IsX86 = false; static const bool IsX64 = true; static const bool IsArm64 = false; static const bool IsArm32 = false; static const bool IsArmArch = false; static const bool IsLoongArch64 = false; #elif defined(TARGET_X86) static const bool IsX86 = true; static const bool IsX64 = false; static const bool IsArm64 = false; static const bool IsArm32 = false; static const bool IsArmArch = false; static const bool IsLoongArch64 = false; #elif defined(TARGET_LOONGARCH64) static const bool IsX86 = false; static const bool IsX64 = false; static const bool IsArm64 = false; static const bool IsArm32 = false; static const bool IsArmArch = false; static const bool IsLoongArch64 = true; #else #error Unknown architecture #endif }; #endif // targetosarch_h ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/thekey.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma once // This file allows customization of the strongname key used to replace the ECMA key static const BYTE g_rbTheKey[] = { 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, 0x07,0xd1,0xfa,0x57,0xc4,0xae,0xd9,0xf0,0xa3,0x2e,0x84,0xaa,0x0f,0xae,0xfd,0x0d, 0xe9,0xe8,0xfd,0x6a,0xec,0x8f,0x87,0xfb,0x03,0x76,0x6c,0x83,0x4c,0x99,0x92,0x1e, 0xb2,0x3b,0xe7,0x9a,0xd9,0xd5,0xdc,0xc1,0xdd,0x9a,0xd2,0x36,0x13,0x21,0x02,0x90, 0x0b,0x72,0x3c,0xf9,0x80,0x95,0x7f,0xc4,0xe1,0x77,0x10,0x8f,0xc6,0x07,0x77,0x4f, 0x29,0xe8,0x32,0x0e,0x92,0xea,0x05,0xec,0xe4,0xe8,0x21,0xc0,0xa5,0xef,0xe8,0xf1, 0x64,0x5c,0x4c,0x0c,0x93,0xc1,0xab,0x99,0x28,0x5d,0x62,0x2c,0xaa,0x65,0x2c,0x1d, 0xfa,0xd6,0x3d,0x74,0x5d,0x6f,0x2d,0xe5,0xf1,0x7e,0x5e,0xaf,0x0f,0xc4,0x96,0x3d, 0x26,0x1c,0x8a,0x12,0x43,0x65,0x18,0x20,0x6d,0xc0,0x93,0x34,0x4d,0x5a,0xd2,0x93 }; static const BYTE g_rbTheKeyToken[] = {0xb0,0x3f,0x5f,0x7f,0x11,0xd5,0x0a,0x3a}; static const BYTE g_rbTheSilverlightPlatformKey[] = { 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, 0x8d,0x56,0xc7,0x6f,0x9e,0x86,0x49,0x38,0x30,0x49,0xf3,0x83,0xc4,0x4b,0xe0,0xec, 0x20,0x41,0x81,0x82,0x2a,0x6c,0x31,0xcf,0x5e,0xb7,0xef,0x48,0x69,0x44,0xd0,0x32, 0x18,0x8e,0xa1,0xd3,0x92,0x07,0x63,0x71,0x2c,0xcb,0x12,0xd7,0x5f,0xb7,0x7e,0x98, 0x11,0x14,0x9e,0x61,0x48,0xe5,0xd3,0x2f,0xba,0xab,0x37,0x61,0x1c,0x18,0x78,0xdd, 0xc1,0x9e,0x20,0xef,0x13,0x5d,0x0c,0xb2,0xcf,0xf2,0xbf,0xec,0x3d,0x11,0x58,0x10, 0xc3,0xd9,0x06,0x96,0x38,0xfe,0x4b,0xe2,0x15,0xdb,0xf7,0x95,0x86,0x19,0x20,0xe5, 0xab,0x6f,0x7d,0xb2,0xe2,0xce,0xef,0x13,0x6a,0xc2,0x3d,0x5d,0xd2,0xbf,0x03,0x17, 0x00,0xae,0xc2,0x32,0xf6,0xc6,0xb1,0xc7,0x85,0xb4,0x30,0x5c,0x12,0x3b,0x37,0xab }; static const BYTE g_rbTheSilverlightPlatformKeyToken[] = {0x7c,0xec,0x85,0xd7,0xbe,0xa7,0x79,0x8e}; static const BYTE g_rbTheSilverlightKey[] = { 0x00,0x24,0x00,0x00,0x04,0x80,0x00,0x00,0x94,0x00,0x00,0x00,0x06,0x02,0x00,0x00, 0x00,0x24,0x00,0x00,0x52,0x53,0x41,0x31,0x00,0x04,0x00,0x00,0x01,0x00,0x01,0x00, 0xb5,0xfc,0x90,0xe7,0x02,0x7f,0x67,0x87,0x1e,0x77,0x3a,0x8f,0xde,0x89,0x38,0xc8, 0x1d,0xd4,0x02,0xba,0x65,0xb9,0x20,0x1d,0x60,0x59,0x3e,0x96,0xc4,0x92,0x65,0x1e, 0x88,0x9c,0xc1,0x3f,0x14,0x15,0xeb,0xb5,0x3f,0xac,0x11,0x31,0xae,0x0b,0xd3,0x33, 0xc5,0xee,0x60,0x21,0x67,0x2d,0x97,0x18,0xea,0x31,0xa8,0xae,0xbd,0x0d,0xa0,0x07, 0x2f,0x25,0xd8,0x7d,0xba,0x6f,0xc9,0x0f,0xfd,0x59,0x8e,0xd4,0xda,0x35,0xe4,0x4c, 0x39,0x8c,0x45,0x43,0x07,0xe8,0xe3,0x3b,0x84,0x26,0x14,0x3d,0xae,0xc9,0xf5,0x96, 0x83,0x6f,0x97,0xc8,0xf7,0x47,0x50,0xe5,0x97,0x5c,0x64,0xe2,0x18,0x9f,0x45,0xde, 0xf4,0x6b,0x2a,0x2b,0x12,0x47,0xad,0xc3,0x65,0x2b,0xf5,0xc3,0x08,0x05,0x5d,0xa9 }; static const BYTE g_rbTheSilverlightKeyToken[] = {0x31,0xBF,0x38,0x56,0xAD,0x36,0x4E,0x35}; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/tls.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // TLS.H - // // // Encapsulates TLS access for maximum performance. // // ************************************************************************************** // WARNING!!!: These values are used by SOS in the diagnostics repo and need to the same. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/tls.h // ************************************************************************************** #ifndef __tls_h__ #define __tls_h__ #define OFFSETOF__TLS__tls_CurrentThread (0x0) #define OFFSETOF__TLS__tls_EETlsData (2*sizeof(void*)) #ifdef TARGET_64BIT #define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x58 #else #define WINNT_OFFSETOF__TEB__ThreadLocalStoragePointer 0x2c #endif #endif // __tls_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/unreachable.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // --------------------------------------------------------------------------- // unreachable.h // --------------------------------------------------------------------------- #ifndef __UNREACHABLE_H__ #define __UNREACHABLE_H__ #if defined(_MSC_VER) || defined(_PREFIX_) #if defined(TARGET_AMD64) // Empty methods that consist of UNREACHABLE() result in a zero-sized declspec(noreturn) method // which causes the pdb file to make the next method declspec(noreturn) as well, thus breaking BBT // Remove when we get a VC compiler that fixes VSW 449170 # define __UNREACHABLE() do { DebugBreak(); __assume(0); } while (0) #else # define __UNREACHABLE() __assume(0) #endif #else #define __UNREACHABLE() __builtin_unreachable() #endif #endif // __UNREACHABLE_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/utilcode.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // UtilCode.h // // Utility functions implemented in UtilCode.lib. // //***************************************************************************** #ifndef __UtilCode_h__ #define __UtilCode_h__ #include "crtwrap.h" #include "winwrap.h" #include #include #include #include #include #include #include "clrtypes.h" #include "safewrap.h" #include "volatile.h" #include #include "clrhost.h" #include "debugmacros.h" #include "corhlprpriv.h" #include "check.h" #include "safemath.h" #include "new.hpp" #ifdef PAL_STDCPP_COMPAT #include #else #include "clr_std/type_traits" #endif #include "contract.h" #include #include "clrnt.h" #include "random.h" #define WINDOWS_KERNEL32_DLLNAME_A "kernel32" #define WINDOWS_KERNEL32_DLLNAME_W W("kernel32") #define CoreLibName_W W("System.Private.CoreLib") #define CoreLibName_IL_W W("System.Private.CoreLib.dll") #define CoreLibName_NI_W W("System.Private.CoreLib.ni.dll") #define CoreLibName_TLB_W W("System.Private.CoreLib.tlb") #define CoreLibName_A "System.Private.CoreLib" #define CoreLibName_IL_A "System.Private.CoreLib.dll" #define CoreLibName_NI_A "System.Private.CoreLib.ni.dll" #define CoreLibName_TLB_A "System.Private.CoreLib.tlb" #define CoreLibNameLen 22 #define CoreLibSatelliteName_A "System.Private.CoreLib.resources" #define CoreLibSatelliteNameLen 32 class StringArrayList; #if !defined(_DEBUG_IMPL) && defined(_DEBUG) && !defined(DACCESS_COMPILE) #define _DEBUG_IMPL 1 #endif #ifdef TARGET_ARM // Under ARM we generate code only with Thumb encoding. In order to ensure we execute such code in the correct // mode we must ensure the low-order bit is set in any code address we'll call as a sub-routine. In C++ this // is handled automatically for us by the compiler. When generating and working with code generated // dynamically we have to be careful to set or mask-out this bit as appropriate. #ifndef THUMB_CODE #define THUMB_CODE 1 #endif // Given a WORD extract the bitfield [lowbit, highbit] (i.e. BitExtract(0xffff, 15, 0) == 0xffff). inline WORD BitExtract(WORD wValue, DWORD highbit, DWORD lowbit) { _ASSERTE((highbit < 16) && (lowbit < 16) && (highbit >= lowbit)); return (wValue >> lowbit) & ((1 << ((highbit - lowbit) + 1)) - 1); } // Determine whether an ARM Thumb mode instruction is 32-bit or 16-bit based on the first WORD of the // instruction. inline bool Is32BitInstruction(WORD opcode) { return BitExtract(opcode, 15, 11) >= 0x1d; } template inline ResultType DataPointerToThumbCode(SourceType pCode) { return (ResultType)(((UINT_PTR)pCode) | THUMB_CODE); } template inline ResultType ThumbCodeToDataPointer(SourceType pCode) { return (ResultType)(((UINT_PTR)pCode) & ~THUMB_CODE); } #endif // TARGET_ARM // Convert from a PCODE to the corresponding PINSTR. On many architectures this will be the identity function; // on ARM, this will mask off the THUMB bit. inline TADDR PCODEToPINSTR(PCODE pc) { #ifdef TARGET_ARM return ThumbCodeToDataPointer(pc); #else return dac_cast(pc); #endif } // Convert from a PINSTR to the corresponding PCODE. On many architectures this will be the identity function; // on ARM, this will raise the THUMB bit. inline PCODE PINSTRToPCODE(TADDR addr) { #ifdef TARGET_ARM return DataPointerToThumbCode(addr); #else return dac_cast(addr); #endif } typedef LPCSTR LPCUTF8; typedef LPSTR LPUTF8; #include "nsutilpriv.h" #include "stdmacros.h" //********** Macros. ********************************************************** #ifndef FORCEINLINE #if _MSC_VER < 1200 #define FORCEINLINE inline #else #define FORCEINLINE __forceinline #endif #endif #ifndef DEBUG_NOINLINE #if defined(_DEBUG) #define DEBUG_NOINLINE NOINLINE #else #define DEBUG_NOINLINE #endif #endif #include // for offsetof #include #define IS_DIGIT(ch) (((ch) >= W('0')) && ((ch) <= W('9'))) #define DIGIT_TO_INT(ch) ((ch) - W('0')) #define INT_TO_DIGIT(i) ((WCHAR)(W('0') + (i))) // Helper will 4 byte align a value, rounding up. #define ALIGN4BYTE(val) (((val) + 3) & ~0x3) #ifdef _DEBUG #define DEBUGARG(x) , x #else #define DEBUGARG(x) #endif #ifndef sizeofmember // Returns the size of a class or struct member. #define sizeofmember(c,m) (sizeof(((c*)0)->m)) #endif //=--------------------------------------------------------------------------= // Prefast helpers. // #include "safemath.h" //=--------------------------------------------------------------------------= // string helpers. // // given and ANSI String, copy it into a wide buffer. // be careful about scoping when using this macro! // // how to use the below two macros: // // ... // LPSTR pszA; // pszA = MyGetAnsiStringRoutine(); // MAKE_WIDEPTR_FROMANSI(pwsz, pszA); // MyUseWideStringRoutine(pwsz); // ... // // similarily for MAKE_ANSIPTR_FROMWIDE. note that the first param does not // have to be declared, and no clean up must be done. // // We'll define an upper limit that allows multiplication by 4 (the max // bytes/char in UTF-8) but still remains positive, and allows some room for pad. // Under normal circumstances, we should never get anywhere near this limit. #define MAKE_MAX_LENGTH 0x1fffff00 #ifndef MAKE_TOOLONGACTION #define MAKE_TOOLONGACTION ThrowHR(COR_E_OVERFLOW) #endif #ifndef MAKE_TRANSLATIONFAILED #define MAKE_TRANSLATIONFAILED ThrowWin32(ERROR_NO_UNICODE_TRANSLATION) #endif // This version throws on conversion errors (ie, no best fit character // mapping to characters that look similar, and no use of the default char // ('?') when printing out unrepresentable characters. Use this method for // most development in the EE, especially anything like metadata or class // names. See the BESTFIT version if you're printing out info to the console. #define MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, codepage) \ int __l##ptrname = (int)wcslen(widestr); \ if (__l##ptrname > MAKE_MAX_LENGTH) \ MAKE_TOOLONGACTION; \ __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \ CQuickBytes __CQuickBytes##ptrname; \ __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \ BOOL __b##ptrname; \ DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, &__b##ptrname); \ if (__b##ptrname || (__cBytes##ptrname == 0 && (widestr[0] != W('\0')))) { \ MAKE_TRANSLATIONFAILED; \ } \ LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr() // This version does best fit character mapping and also allows the use // of the default char ('?') for any Unicode character that isn't // representable. This is reasonable for writing to the console, but // shouldn't be used for most string conversions. #define MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, codepage) \ int __l##ptrname = (int)wcslen(widestr); \ if (__l##ptrname > MAKE_MAX_LENGTH) \ MAKE_TOOLONGACTION; \ __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \ CQuickBytes __CQuickBytes##ptrname; \ __CQuickBytes##ptrname.AllocThrows(__l##ptrname); \ DWORD __cBytes##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, -1, (LPSTR)__CQuickBytes##ptrname.Ptr(), __l##ptrname, NULL, NULL); \ if (__cBytes##ptrname == 0 && __l##ptrname != 0) { \ MAKE_TRANSLATIONFAILED; \ } \ LPSTR ptrname = (LPSTR)__CQuickBytes##ptrname.Ptr() // Use for anything critical other than output to console, where weird // character mappings are unacceptable. #define MAKE_ANSIPTR_FROMWIDE(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE(ptrname, widestr, CP_ACP) // Use for output to the console. #define MAKE_ANSIPTR_FROMWIDE_BESTFIT(ptrname, widestr) MAKE_MULTIBYTE_FROMWIDE_BESTFIT(ptrname, widestr, CP_ACP) #define MAKE_WIDEPTR_FROMANSI(ptrname, ansistr) \ CQuickBytes __qb##ptrname; \ int __l##ptrname; \ __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \ if (__l##ptrname > MAKE_MAX_LENGTH) \ MAKE_TOOLONGACTION; \ LPWSTR ptrname = (LPWSTR) __qb##ptrname.AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \ if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) == 0) { \ MAKE_TRANSLATIONFAILED; \ } #define MAKE_WIDEPTR_FROMANSI_NOTHROW(ptrname, ansistr) \ CQuickBytes __qb##ptrname; \ LPWSTR ptrname = 0; \ int __l##ptrname; \ __l##ptrname = WszMultiByteToWideChar(CP_ACP, 0, ansistr, -1, 0, 0); \ if (__l##ptrname <= MAKE_MAX_LENGTH) { \ ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \ if (ptrname) { \ if (WszMultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, ansistr, -1, ptrname, __l##ptrname) != 0) { \ ptrname[__l##ptrname] = 0; \ } else { \ ptrname = 0; \ } \ } \ } #define MAKE_UTF8PTR_FROMWIDE(ptrname, widestr) CQuickBytes _##ptrname; _##ptrname.ConvertUnicode_Utf8(widestr); LPSTR ptrname = (LPSTR) _##ptrname.Ptr(); #define MAKE_UTF8PTR_FROMWIDE_NOTHROW(ptrname, widestr) \ CQuickBytes __qb##ptrname; \ int __l##ptrname = (int)wcslen(widestr); \ LPUTF8 ptrname = 0; \ if (__l##ptrname <= MAKE_MAX_LENGTH) { \ __l##ptrname = (int)((__l##ptrname + 1) * 2 * sizeof(char)); \ ptrname = (LPUTF8) __qb##ptrname.AllocNoThrow(__l##ptrname); \ } \ if (ptrname) { \ INT32 __lresult##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __l##ptrname-1, NULL, NULL); \ DWORD __dwCaptureLastError##ptrname = ::GetLastError(); \ if ((__lresult##ptrname==0) && (((LPCWSTR)widestr)[0] != W('\0'))) { \ if (__dwCaptureLastError##ptrname==ERROR_INSUFFICIENT_BUFFER) { \ INT32 __lsize##ptrname=WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, NULL, 0, NULL, NULL); \ ptrname = (LPSTR) __qb##ptrname .AllocNoThrow(__lsize##ptrname); \ if (ptrname) { \ if (WszWideCharToMultiByte(CP_UTF8, 0, widestr, -1, ptrname, __lsize##ptrname, NULL, NULL) != 0) { \ ptrname[__l##ptrname] = 0; \ } else { \ ptrname = 0; \ } \ } \ } \ else { \ ptrname = 0; \ } \ } \ } \ #define MAKE_WIDEPTR_FROMUTF8N(ptrname, utf8str, n8chrs) \ CQuickBytes __qb##ptrname; \ int __l##ptrname; \ __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \ if (__l##ptrname > MAKE_MAX_LENGTH) \ MAKE_TOOLONGACTION; \ LPWSTR ptrname = (LPWSTR) __qb##ptrname .AllocThrows((__l##ptrname+1)*sizeof(WCHAR)); \ if (0==WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname)) { \ MAKE_TRANSLATIONFAILED; \ } \ ptrname[__l##ptrname] = 0; #define MAKE_WIDEPTR_FROMUTF8(ptrname, utf8str) CQuickBytes _##ptrname; _##ptrname.ConvertUtf8_Unicode(utf8str); LPCWSTR ptrname = (LPCWSTR) _##ptrname.Ptr(); #define MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, n8chrs) \ CQuickBytes __qb##ptrname; \ int __l##ptrname; \ LPWSTR ptrname = 0; \ __l##ptrname = WszMultiByteToWideChar(CP_UTF8, 0, utf8str, n8chrs, 0, 0); \ if (__l##ptrname <= MAKE_MAX_LENGTH) { \ ptrname = (LPWSTR) __qb##ptrname.AllocNoThrow((__l##ptrname+1)*sizeof(WCHAR)); \ if (ptrname) { \ if (WszMultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8str, n8chrs, ptrname, __l##ptrname) != 0) { \ ptrname[__l##ptrname] = 0; \ } else { \ ptrname = 0; \ } \ } \ } #define MAKE_WIDEPTR_FROMUTF8_NOTHROW(ptrname, utf8str) MAKE_WIDEPTR_FROMUTF8N_NOTHROW(ptrname, utf8str, -1) // This method takes the number of characters #define MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, codepage) \ CQuickBytes __qb##ptrname; \ int __l##ptrname; \ __l##ptrname = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, NULL, 0, NULL, NULL); \ if (__l##ptrname > MAKE_MAX_LENGTH) \ MAKE_TOOLONGACTION; \ ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \ BOOL __b##ptrname; \ DWORD _pCnt = WszWideCharToMultiByte(codepage, WC_NO_BEST_FIT_CHARS, widestr, _nCharacters, ptrname, __l##ptrname, NULL, &__b##ptrname); \ if (__b##ptrname || (_pCnt == 0 && _nCharacters > 0)) { \ MAKE_TRANSLATIONFAILED; \ } \ ptrname[__l##ptrname] = 0; #define MAKE_MULTIBYTE_FROMWIDEN_BESTFIT(ptrname, widestr, _nCharacters, _pCnt, codepage) \ CQuickBytes __qb##ptrname; \ int __l##ptrname; \ __l##ptrname = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, NULL, 0, NULL, NULL); \ if (__l##ptrname > MAKE_MAX_LENGTH) \ MAKE_TOOLONGACTION; \ ptrname = (LPUTF8) __qb##ptrname .AllocThrows(__l##ptrname+1); \ DWORD _pCnt = WszWideCharToMultiByte(codepage, 0, widestr, _nCharacters, ptrname, __l##ptrname, NULL, NULL); \ if (_pCnt == 0 && _nCharacters > 0) { \ MAKE_TRANSLATIONFAILED; \ } \ ptrname[__l##ptrname] = 0; #define MAKE_ANSIPTR_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt) \ MAKE_MULTIBYTE_FROMWIDEN(ptrname, widestr, _nCharacters, _pCnt, CP_ACP) const SIZE_T MaxSigned32BitDecString = ARRAY_SIZE("-2147483648") - 1; const SIZE_T MaxUnsigned32BitDecString = ARRAY_SIZE("4294967295") - 1; const SIZE_T MaxIntegerDecHexString = ARRAY_SIZE("-9223372036854775808") - 1; const SIZE_T Max16BitHexString = ARRAY_SIZE("1234") - 1; const SIZE_T Max32BitHexString = ARRAY_SIZE("12345678") - 1; const SIZE_T Max64BitHexString = ARRAY_SIZE("1234567812345678") - 1; template inline WCHAR* FormatInteger(WCHAR* str, size_t strCount, const char* fmt, I v) { static_assert(std::is_integral::value, "Integral type required."); assert(str != NULL && fmt != NULL); // Represents the most amount of space needed to format // an integral type (i.e., %d or %llx). char tmp[MaxIntegerDecHexString + 1]; int cnt = sprintf_s(tmp, ARRAY_SIZE(tmp), fmt, v); assert(0 <= cnt); WCHAR* end = str + strCount; for (int i = 0; i < cnt; ++i) { if (str == end) return NULL; *str++ = (WCHAR)tmp[i]; } *str = W('\0'); return str; } inline LPWSTR DuplicateString( LPCWSTR wszString, size_t cchString) { STATIC_CONTRACT_NOTHROW; LPWSTR wszDup = NULL; if (wszString != NULL) { wszDup = new (nothrow) WCHAR[cchString + 1]; if (wszDup != NULL) { wcscpy_s(wszDup, cchString + 1, wszString); } } return wszDup; } inline LPWSTR DuplicateString( LPCWSTR wszString) { STATIC_CONTRACT_NOTHROW; if (wszString != NULL) { return DuplicateString(wszString, wcslen(wszString)); } else { return NULL; } } void DECLSPEC_NORETURN ThrowOutOfMemory(); inline LPWSTR DuplicateStringThrowing( LPCWSTR wszString, size_t cchString) { STATIC_CONTRACT_THROWS; if (wszString == NULL) return NULL; LPWSTR wszDup = DuplicateString(wszString, cchString); if (wszDup == NULL) ThrowOutOfMemory(); return wszDup; } inline LPWSTR DuplicateStringThrowing( LPCWSTR wszString) { STATIC_CONTRACT_THROWS; if (wszString == NULL) return NULL; LPWSTR wszDup = DuplicateString(wszString); if (wszDup == NULL) ThrowOutOfMemory(); return wszDup; } //***************************************************************************** // Placement new is used to new and object at an exact location. The pointer // is simply returned to the caller without actually using the heap. The // advantage here is that you cause the ctor() code for the object to be run. // This is ideal for heaps of C++ objects that need to get init'd multiple times. // Example: // void *pMem = GetMemFromSomePlace(); // Foo *p = new (pMem) Foo; // DoSomething(p); // p->~Foo(); //***************************************************************************** #ifndef __PLACEMENT_NEW_INLINE #define __PLACEMENT_NEW_INLINE inline void *__cdecl operator new(size_t, void *_P) { LIMITED_METHOD_DAC_CONTRACT; return (_P); } #endif // __PLACEMENT_NEW_INLINE /********************************************************************************/ /* portability helpers */ #ifdef TARGET_64BIT #define IN_TARGET_64BIT(x) x #define IN_TARGET_32BIT(x) #else #define IN_TARGET_64BIT(x) #define IN_TARGET_32BIT(x) x #endif void * __cdecl operator new(size_t n); _Ret_bytecap_(n) void * __cdecl operator new[](size_t n); void __cdecl operator delete(void *p) NOEXCEPT; void __cdecl operator delete[](void *p) NOEXCEPT; #ifdef _DEBUG_IMPL HRESULT _OutOfMemory(LPCSTR szFile, int iLine); #define OutOfMemory() _OutOfMemory(__FILE__, __LINE__) #else inline HRESULT OutOfMemory() { LIMITED_METHOD_CONTRACT; return (E_OUTOFMEMORY); } #endif //***************************************************************************** // Handle accessing localizable resource strings //***************************************************************************** typedef LPCWSTR LocaleID; typedef WCHAR LocaleIDValue[LOCALE_NAME_MAX_LENGTH]; // Notes about the culture callbacks: // - The language we're operating in can change at *runtime*! // - A process may operate in *multiple* languages. // (ex: Each thread may have it's own language) // - If we don't care what language we're in (or have no way of knowing), // then return a 0-length name and UICULTUREID_DONTCARE for the culture ID. // - GetCultureName() and the GetCultureId() must be in sync (refer to the // same language). // - We have two functions separate functions for better performance. // - The name is used to resolve a directory for MsCorRC.dll. // - The id is used as a key to map to a dll hinstance. // Callback to obtain both the culture name and the culture's parent culture name typedef HRESULT (*FPGETTHREADUICULTURENAMES)(__inout StringArrayList* pCultureNames); const LPCWSTR UICULTUREID_DONTCARE = NULL; typedef int (*FPGETTHREADUICULTUREID)(LocaleIDValue*); HMODULE CLRLoadLibrary(LPCWSTR lpLibFileName); HMODULE CLRLoadLibraryEx(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); BOOL CLRFreeLibrary(HMODULE hModule); // Load a string using the resources for the current module. STDAPI UtilLoadStringRC(UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax, int bQuiet=FALSE); // Specify callbacks so that UtilLoadStringRC can find out which language we're in. // If no callbacks specified (or both parameters are NULL), we default to the // resource dll in the root (which is probably english). void SetResourceCultureCallbacks( FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames, FPGETTHREADUICULTUREID fpGetThreadUICultureId ); void GetResourceCultureCallbacks( FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, FPGETTHREADUICULTUREID* fpGetThreadUICultureId ); //***************************************************************************** // Use this class by privately deriving from noncopyable to disallow copying of // your class. //***************************************************************************** class noncopyable { protected: noncopyable() {} ~noncopyable() {} private: noncopyable(const noncopyable&); const noncopyable& operator=(const noncopyable&); }; //***************************************************************************** // Must associate each handle to an instance of a resource dll with the int // that it represents //***************************************************************************** typedef HINSTANCE HRESOURCEDLL; class CCulturedHInstance { LocaleIDValue m_LangId; HRESOURCEDLL m_hInst; BOOL m_fMissing; public: CCulturedHInstance() { LIMITED_METHOD_CONTRACT; m_hInst = NULL; m_fMissing = FALSE; } BOOL HasID(LocaleID id) { _ASSERTE(m_hInst != NULL || m_fMissing); if (id == UICULTUREID_DONTCARE) return FALSE; return wcscmp(id, m_LangId) == 0; } HRESOURCEDLL GetLibraryHandle() { return m_hInst; } BOOL IsSet() { return m_hInst != NULL; } BOOL IsMissing() { return m_fMissing; } void SetMissing(LocaleID id) { _ASSERTE(m_hInst == NULL); SetId(id); m_fMissing = TRUE; } void Set(LocaleID id, HRESOURCEDLL hInst) { _ASSERTE(m_hInst == NULL); _ASSERTE(m_fMissing == FALSE); SetId(id); m_hInst = hInst; } private: void SetId(LocaleID id) { if (id != UICULTUREID_DONTCARE) { wcsncpy_s(m_LangId, ARRAY_SIZE(m_LangId), id, ARRAY_SIZE(m_LangId)); m_LangId[STRING_LENGTH(m_LangId)] = W('\0'); } else { m_LangId[0] = W('\0'); } } }; #ifndef DACCESS_COMPILE void AddThreadPreferredUILanguages(StringArrayList* pArray); #endif //***************************************************************************** // CCompRC manages string Resource access for COM+. This includes loading // the MsCorRC.dll for resources as well allowing each thread to use a // a different localized version. //***************************************************************************** class CCompRC { public: enum ResourceCategory { // must be present Required, // present in Desktop CLR and Core CLR + debug pack, an error // If missing, get a generic error message instead Error, // present in Desktop CLR and Core CLR + debug pack, normal operation (e.g tracing) // if missing, get a generic "resource not found" message instead Debugging, // present in Desktop CLR, optional for CoreCLR DesktopCLR, // might not be present, non essential Optional }; CCompRC() { // This constructor will be fired up on startup. Make sure it doesn't // do anything besides zero-out out values. m_fpGetThreadUICultureId = NULL; m_fpGetThreadUICultureNames = NULL; m_pHash = NULL; m_nHashSize = 0; m_csMap = NULL; m_pResourceFile = NULL; }// CCompRC HRESULT Init(LPCWSTR pResourceFile); void Destroy(); HRESULT LoadString(ResourceCategory eCategory, UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax , int *pcwchUsed=NULL); HRESULT LoadString(ResourceCategory eCategory, LocaleID langId, UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax, int *pcwchUsed); void SetResourceCultureCallbacks( FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames, FPGETTHREADUICULTUREID fpGetThreadUICultureId ); void GetResourceCultureCallbacks( FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, FPGETTHREADUICULTUREID* fpGetThreadUICultureId ); // Get the default resource location (mscorrc.dll) static CCompRC* GetDefaultResourceDll(); static void GetDefaultCallbacks( FPGETTHREADUICULTURENAMES* fpGetThreadUICultureNames, FPGETTHREADUICULTUREID* fpGetThreadUICultureId) { WRAPPER_NO_CONTRACT; m_DefaultResourceDll.GetResourceCultureCallbacks( fpGetThreadUICultureNames, fpGetThreadUICultureId); } static void SetDefaultCallbacks( FPGETTHREADUICULTURENAMES fpGetThreadUICultureNames, FPGETTHREADUICULTUREID fpGetThreadUICultureId) { WRAPPER_NO_CONTRACT; // Either both are NULL or neither are NULL _ASSERTE((fpGetThreadUICultureNames != NULL) == (fpGetThreadUICultureId != NULL)); m_DefaultResourceDll.SetResourceCultureCallbacks( fpGetThreadUICultureNames, fpGetThreadUICultureId); } private: // String resources packaged as PE files only exist on Windows #ifdef HOST_WINDOWS HRESULT GetLibrary(LocaleID langId, HRESOURCEDLL* phInst); #ifndef DACCESS_COMPILE HRESULT LoadLibraryHelper(HRESOURCEDLL *pHInst, SString& rcPath); HRESULT LoadLibraryThrows(HRESOURCEDLL * pHInst); HRESULT LoadLibrary(HRESOURCEDLL * pHInst); HRESULT LoadResourceFile(HRESOURCEDLL * pHInst, LPCWSTR lpFileName); #endif // DACCESS_COMPILE #endif // HOST_WINDOWS // We do not have global constructors any more static LONG m_dwDefaultInitialized; static CCompRC m_DefaultResourceDll; static LPCWSTR m_pDefaultResource; // We must map between a thread's int and a dll instance. // Since we only expect 1 language almost all of the time, we'll special case // that and then use a variable size map for everything else. CCulturedHInstance m_Primary; CCulturedHInstance * m_pHash; int m_nHashSize; CRITSEC_COOKIE m_csMap; LPCWSTR m_pResourceFile; // Main accessors for hash HRESOURCEDLL LookupNode(LocaleID langId, BOOL &fMissing); HRESULT AddMapNode(LocaleID langId, HRESOURCEDLL hInst, BOOL fMissing = FALSE); FPGETTHREADUICULTUREID m_fpGetThreadUICultureId; FPGETTHREADUICULTURENAMES m_fpGetThreadUICultureNames; }; HRESULT UtilLoadResourceString(CCompRC::ResourceCategory eCategory, UINT iResourceID, _Out_writes_ (iMax) LPWSTR szBuffer, int iMax); // The HRESULT_FROM_WIN32 macro evaluates its arguments three times. // TODO: All HRESULT_FROM_WIN32(GetLastError()) should be replaced by calls to // this helper function avoid code bloat inline HRESULT HRESULT_FROM_GetLastError() { WRAPPER_NO_CONTRACT; DWORD dw = GetLastError(); // Make sure we return a failure if (dw == ERROR_SUCCESS) { _ASSERTE(!"We were expecting to get an error code, but a success code is being returned. Check this code path for Everett!"); return E_FAIL; } else return HRESULT_FROM_WIN32(dw); } inline HRESULT HRESULT_FROM_GetLastErrorNA() { WRAPPER_NO_CONTRACT; DWORD dw = GetLastError(); // Make sure we return a failure if (dw == ERROR_SUCCESS) return E_FAIL; else return HRESULT_FROM_WIN32(dw); } inline HRESULT BadError(HRESULT hr) { LIMITED_METHOD_CONTRACT; _ASSERTE(!"Serious Error"); return (hr); } #define TESTANDRETURN(test, hrVal) \ { \ int ___test = (int)(test); \ if (! ___test) \ return hrVal; \ } #define TESTANDRETURNPOINTER(pointer) \ TESTANDRETURN((pointer)!=NULL, E_POINTER) #define TESTANDRETURNMEMORY(pointer) \ TESTANDRETURN((pointer)!=NULL, E_OUTOFMEMORY) #define TESTANDRETURNHR(hr) \ TESTANDRETURN(SUCCEEDED(hr), hr) #define TESTANDRETURNARG(argtest) \ TESTANDRETURN(argtest, E_INVALIDARG) // Quick validity check for HANDLEs that are returned by Win32 APIs that // use INVALID_HANDLE_VALUE instead of NULL to indicate an error inline BOOL IsValidHandle(HANDLE h) { LIMITED_METHOD_CONTRACT; return ((h != NULL) && (h != INVALID_HANDLE_VALUE)); } // Count the bits in a value in order iBits time. inline int CountBits(int iNum) { LIMITED_METHOD_CONTRACT; int iBits; for (iBits=0; iNum; iBits++) iNum = iNum & (iNum - 1); return (iBits); } #include "bitposition.h" // Convert the currency to a decimal and canonicalize. inline void VarDecFromCyCanonicalize(CY cyIn, DECIMAL* dec) { WRAPPER_NO_CONTRACT; (*(ULONG*)dec) = 0; DECIMAL_HI32(*dec) = 0; if (cyIn.int64 == 0) // For compatibility, a currency of 0 emits the Decimal "0.0000" (scale set to 4). { DECIMAL_SCALE(*dec) = 4; DECIMAL_LO32(*dec) = 0; DECIMAL_MID32(*dec) = 0; return; } if (cyIn.int64 < 0) { DECIMAL_SIGN(*dec) = DECIMAL_NEG; cyIn.int64 = -cyIn.int64; } BYTE scale = 4; ULONGLONG absoluteCy = (ULONGLONG)cyIn.int64; while (scale != 0 && ((absoluteCy % 10) == 0)) { scale--; absoluteCy /= 10; } DECIMAL_SCALE(*dec) = scale; DECIMAL_LO32(*dec) = (ULONG)absoluteCy; DECIMAL_MID32(*dec) = (ULONG)(absoluteCy >> 32); } //***************************************************************************** // // Paths functions. Use these instead of the CRT. // //***************************************************************************** //******************************************************************************* // Split a path into individual components - points to each section of the string //******************************************************************************* void SplitPathInterior( _In_ LPCWSTR wszPath, _Out_opt_ LPCWSTR *pwszDrive, _Out_opt_ size_t *pcchDrive, _Out_opt_ LPCWSTR *pwszDir, _Out_opt_ size_t *pcchDir, _Out_opt_ LPCWSTR *pwszFileName, _Out_opt_ size_t *pcchFileName, _Out_opt_ LPCWSTR *pwszExt, _Out_opt_ size_t *pcchExt); #include "ostype.h" #define CLRGetTickCount64() GetTickCount64() // // Allocate free memory within the range [pMinAddr..pMaxAddr] using // ClrVirtualQuery to find free memory and ClrVirtualAlloc to allocate it. // BYTE * ClrVirtualAllocWithinRange(const BYTE *pMinAddr, const BYTE *pMaxAddr, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); // // Allocate free memory with specific alignment // LPVOID ClrVirtualAllocAligned(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect, SIZE_T alignment); #ifdef HOST_WINDOWS struct CPU_Group_Info { DWORD_PTR active_mask; WORD nr_active; // at most 64 WORD begin; DWORD groupWeight; DWORD activeThreadWeight; }; class CPUGroupInfo { private: static LONG m_initialization; static WORD m_nGroups; static WORD m_nProcessors; static BOOL m_enableGCCPUGroups; static BOOL m_threadUseAllCpuGroups; static BOOL m_threadAssignCpuGroups; static WORD m_initialGroup; static CPU_Group_Info *m_CPUGroupInfoArray; static BOOL InitCPUGroupInfoArray(); static void InitCPUGroupInfo(); static BOOL IsInitialized(); public: static void EnsureInitialized(); static BOOL CanEnableGCCPUGroups(); static BOOL CanEnableThreadUseAllCpuGroups(); static BOOL CanAssignCpuGroupsToThreads(); static WORD GetNumActiveProcessors(); static void GetGroupForProcessor(WORD processor_number, WORD *group_number, WORD *group_processor_number); static DWORD CalculateCurrentProcessorNumber(); static bool GetCPUGroupInfo(PUSHORT total_groups, DWORD* max_procs_per_group); //static void PopulateCPUUsageArray(void * infoBuffer, ULONG infoSize); #if !defined(FEATURE_NATIVEAOT) public: static BOOL GetLogicalProcessorInformationEx(LOGICAL_PROCESSOR_RELATIONSHIP relationship, SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *slpiex, PDWORD count); static BOOL SetThreadGroupAffinity(HANDLE h, const GROUP_AFFINITY *groupAffinity, GROUP_AFFINITY *previousGroupAffinity); static BOOL GetThreadGroupAffinity(HANDLE h, GROUP_AFFINITY *groupAffinity); static BOOL GetSystemTimes(FILETIME *idleTime, FILETIME *kernelTime, FILETIME *userTime); static void ChooseCPUGroupAffinity(GROUP_AFFINITY *gf); static void ClearCPUGroupAffinity(GROUP_AFFINITY *gf); static BOOL GetCPUGroupRange(WORD group_number, WORD* group_begin, WORD* group_size); #endif }; DWORD_PTR GetCurrentProcessCpuMask(); #endif // HOST_WINDOWS int GetTotalProcessorCount(); //****************************************************************************** // Returns the number of processors that a process has been configured to run on //****************************************************************************** int GetCurrentProcessCpuCount(); uint32_t GetOsPageSize(); //***************************************************************************** // Return != 0 if the bit at the specified index in the array is on and 0 if // it is off. //***************************************************************************** inline int GetBit(PTR_BYTE pcBits,int iBit) { LIMITED_METHOD_CONTRACT; return (pcBits[iBit>>3] & (1 << (iBit & 0x7))); } #ifdef DACCESS_COMPILE inline int GetBit(BYTE const * pcBits,int iBit) { WRAPPER_NO_CONTRACT; return GetBit(dac_cast(pcBits), iBit); } #endif //***************************************************************************** // Set the state of the bit at the specified index based on the value of bOn. //***************************************************************************** inline void SetBit(PTR_BYTE pcBits,int iBit,int bOn) { LIMITED_METHOD_CONTRACT; if (bOn) pcBits[iBit>>3] |= (1 << (iBit & 0x7)); else pcBits[iBit>>3] &= ~(1 << (iBit & 0x7)); } #ifdef DACCESS_COMPILE inline void SetBit(BYTE * pcBits,int iBit,int bOn) { WRAPPER_NO_CONTRACT; SetBit(dac_cast(pcBits), iBit, bOn); } #endif template class SimpleListNode { public: SimpleListNode(const T& _t) { data = _t; next = 0; } T data; SimpleListNode* next; }; template class SimpleList { public: typedef SimpleListNode NodeType; SimpleList() { head = NULL; } void LinkHead(NodeType* pNode) { pNode->next = head; head = pNode; } NodeType* UnlinkHead() { NodeType* ret = head; if (head) { head = head->next; } return ret; } NodeType* Head() { return head; } protected: NodeType* head; }; //***************************************************************************** // This class implements a dynamic array of structures for which the order of // the elements is unimportant. This means that any item placed in the list // may be swapped to any other location in the list at any time. If the order // of the items you place in the array is important, then use the CStructArray // class. //***************************************************************************** template class CUnorderedArrayWithAllocator { int m_iCount; // # of elements used in the list. int m_iSize; // # of elements allocated in the list. public: #ifndef DACCESS_COMPILE T *m_pTable; // Pointer to the list of elements. #else TADDR m_pTable; // Pointer to the list of elements. #endif public: #ifndef DACCESS_COMPILE CUnorderedArrayWithAllocator() : m_iCount(0), m_iSize(0), m_pTable(NULL) { LIMITED_METHOD_CONTRACT; } ~CUnorderedArrayWithAllocator() { LIMITED_METHOD_CONTRACT; // Free the chunk of memory. if (m_pTable != NULL) ALLOCATOR::Free(this, m_pTable); } void Clear() { WRAPPER_NO_CONTRACT; m_iCount = 0; if (m_iSize > iGrowInc) { T* tmp = ALLOCATOR::AllocNoThrow(this, iGrowInc); if (tmp) { ALLOCATOR::Free(this, m_pTable); m_pTable = tmp; m_iSize = iGrowInc; } } } void Clear(int iFirst, int iCount) { WRAPPER_NO_CONTRACT; int iSize; if (iFirst + iCount < m_iCount) memmove(&m_pTable[iFirst], &m_pTable[iFirst + iCount], sizeof(T) * (m_iCount - (iFirst + iCount))); m_iCount -= iCount; iSize = ((m_iCount / iGrowInc) * iGrowInc) + ((m_iCount % iGrowInc != 0) ? iGrowInc : 0); if (m_iSize > iGrowInc && iSize < m_iSize) { T *tmp = ALLOCATOR::AllocNoThrow(this, iSize); if (tmp) { memcpy (tmp, m_pTable, iSize * sizeof(T)); delete [] m_pTable; m_pTable = tmp; m_iSize = iSize; } } _ASSERTE(m_iCount <= m_iSize); } T *Table() { LIMITED_METHOD_CONTRACT; return (m_pTable); } T *Append() { CONTRACTL { NOTHROW; } CONTRACTL_END; // The array should grow, if we can't fit one more element into the array. if (m_iSize <= m_iCount && GrowNoThrow() == NULL) return (NULL); return (&m_pTable[m_iCount++]); } T *AppendThrowing() { CONTRACTL { THROWS; } CONTRACTL_END; // The array should grow, if we can't fit one more element into the array. if (m_iSize <= m_iCount) Grow(); return (&m_pTable[m_iCount++]); } void Delete(const T &Entry) { LIMITED_METHOD_CONTRACT; --m_iCount; for (int i=0; i <= m_iCount; ++i) if (m_pTable[i] == Entry) { m_pTable[i] = m_pTable[m_iCount]; return; } // Just in case we didn't find it. ++m_iCount; } void DeleteByIndex(int i) { LIMITED_METHOD_CONTRACT; --m_iCount; m_pTable[i] = m_pTable[m_iCount]; } void Swap(int i,int j) { LIMITED_METHOD_CONTRACT; T tmp; if (i == j) return; tmp = m_pTable[i]; m_pTable[i] = m_pTable[j]; m_pTable[j] = tmp; } #else TADDR Table() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; return (m_pTable); } void EnumMemoryRegions(void) { SUPPORTS_DAC; DacEnumMemoryRegion(m_pTable, m_iCount * sizeof(T)); } #endif // #ifndef DACCESS_COMPILE USHORT Count() { LIMITED_METHOD_CONTRACT; SUPPORTS_DAC; _ASSERTE(FitsIn(m_iCount)); return static_cast(m_iCount); } private: T *Grow(); T *GrowNoThrow(); }; #ifndef DACCESS_COMPILE //***************************************************************************** // Increase the size of the array. //***************************************************************************** template T *CUnorderedArrayWithAllocator::GrowNoThrow() // NULL if can't grow. { WRAPPER_NO_CONTRACT; T *pTemp; // try to allocate memory for reallocation. if ((pTemp = ALLOCATOR::AllocNoThrow(this, m_iSize+iGrowInc)) == NULL) return (NULL); memcpy (pTemp, m_pTable, m_iSize*sizeof(T)); ALLOCATOR::Free(this, m_pTable); m_pTable = pTemp; m_iSize += iGrowInc; _ASSERTE(m_iSize > 0); return (pTemp); } template T *CUnorderedArrayWithAllocator::Grow() // exception if can't grow. { WRAPPER_NO_CONTRACT; T *pTemp; // try to allocate memory for reallocation. pTemp = ALLOCATOR::AllocThrowing(this, m_iSize+iGrowInc); if (m_iSize > 0) memcpy (pTemp, m_pTable, m_iSize*sizeof(T)); ALLOCATOR::Free(this, m_pTable); m_pTable = pTemp; m_iSize += iGrowInc; _ASSERTE(m_iSize > 0); return (pTemp); } #endif // #ifndef DACCESS_COMPILE template class CUnorderedArray__Allocator { public: static T *AllocThrowing (void*, int nElements) { return new T[nElements]; } static T *AllocNoThrow (void*, int nElements) { return new (nothrow) T[nElements]; } static void Free (void*, T *pTable) { delete [] pTable; } }; template class CUnorderedArray : public CUnorderedArrayWithAllocator > { public: CUnorderedArray () { LIMITED_METHOD_CONTRACT; } }; //Used by the debugger. Included here in hopes somebody else might, too typedef CUnorderedArray SIZE_T_UNORDERED_ARRAY; //***************************************************************************** // This class implements a dynamic array of structures for which the insert // order is important. Inserts will slide all elements after the location // down, deletes slide all values over the deleted item. If the order of the // items in the array is unimportant to you, then CUnorderedArray may provide // the same feature set at lower cost. //***************************************************************************** class CStructArray { BYTE *m_pList; // Pointer to the list of elements. int m_iCount; // # of elements used in the list. int m_iSize; // # of elements allocated in the list. int m_iGrowInc; // Growth increment. short m_iElemSize; // Size of an array element. bool m_bFree; // true if data is automatically maintained. public: CStructArray(short iElemSize, short iGrowInc = 1) : m_pList(NULL), m_iCount(0), m_iSize(0), m_iGrowInc(iGrowInc), m_iElemSize(iElemSize), m_bFree(true) { LIMITED_METHOD_CONTRACT; } ~CStructArray() { WRAPPER_NO_CONTRACT; Clear(); } void *Insert(int iIndex); void *InsertThrowing(int iIndex); void *Append(); void *AppendThrowing(); int AllocateBlock(int iCount); void AllocateBlockThrowing(int iCount); void Delete(int iIndex); void *Ptr() { LIMITED_METHOD_CONTRACT; return (m_pList); } void *Get(int iIndex) { WRAPPER_NO_CONTRACT; _ASSERTE(iIndex < m_iCount); return (BYTE*) Ptr() + (iIndex * (size_t)m_iElemSize); } size_t Size() { LIMITED_METHOD_CONTRACT; return (m_iCount * (size_t)m_iElemSize); } int Count() { LIMITED_METHOD_CONTRACT; return (m_iCount); } void Clear(); void ClearCount() { LIMITED_METHOD_CONTRACT; m_iCount = 0; } void InitOnMem(short iElemSize, void *pList, int iCount, int iSize, int iGrowInc=1) { LIMITED_METHOD_CONTRACT; m_iElemSize = iElemSize; m_iGrowInc = (short) iGrowInc; m_pList = (BYTE*)pList; m_iCount = iCount; m_iSize = iSize; m_bFree = false; } private: void Grow(int iCount); }; //***************************************************************************** // This template simplifies access to a CStructArray by removing void * and // adding some operator overloads. //***************************************************************************** template class CDynArray : public CStructArray { public: CDynArray(short iGrowInc=16) : CStructArray(sizeof(T), iGrowInc) { LIMITED_METHOD_CONTRACT; } T *Insert(int iIndex) { WRAPPER_NO_CONTRACT; return ((T *)CStructArray::Insert((int)iIndex)); } T *InsertThrowing(int iIndex) { WRAPPER_NO_CONTRACT; return ((T *)CStructArray::InsertThrowing((int)iIndex)); } T *Append() { WRAPPER_NO_CONTRACT; return ((T *)CStructArray::Append()); } T *AppendThrowing() { WRAPPER_NO_CONTRACT; return ((T *)CStructArray::AppendThrowing()); } T *Ptr() { WRAPPER_NO_CONTRACT; return ((T *)CStructArray::Ptr()); } T *Get(int iIndex) { WRAPPER_NO_CONTRACT; return (Ptr() + iIndex); } T &operator[](int iIndex) { WRAPPER_NO_CONTRACT; return (*(Ptr() + iIndex)); } int ItemIndex(T *p) { WRAPPER_NO_CONTRACT; return (((int)(LONG_PTR)p - (int)(LONG_PTR)Ptr()) / sizeof(T)); } void Move(int iFrom, int iTo) { WRAPPER_NO_CONTRACT; T tmp; _ASSERTE(iFrom >= 0 && iFrom < Count() && iTo >= 0 && iTo < Count()); tmp = *(Ptr() + iFrom); if (iTo > iFrom) memmove(Ptr() + iFrom, Ptr() + iFrom + 1, (iTo - iFrom) * sizeof(T)); else memmove(Ptr() + iTo + 1, Ptr() + iTo, (iFrom - iTo) * sizeof(T)); *(Ptr() + iTo) = tmp; } }; // Some common arrays. typedef CDynArray INTARRAY; typedef CDynArray SHORTARRAY; typedef CDynArray LONGARRAY; typedef CDynArray USHORTARRAY; typedef CDynArray ULONGARRAY; typedef CDynArray BYTEARRAY; typedef CDynArray TOKENARRAY; //***************************************************************************** //***************************************************************************** template class CQuickSort { protected: T *m_pBase; // Base of array to sort. private: SSIZE_T m_iCount; // How many items in array. SSIZE_T m_iElemSize; // Size of one element. public: CQuickSort( T *pBase, // Address of first element. SSIZE_T iCount) : // How many there are. m_pBase(pBase), m_iCount(iCount), m_iElemSize(sizeof(T)) { LIMITED_METHOD_DAC_CONTRACT; } //***************************************************************************** // Call to sort the array. //***************************************************************************** inline void Sort() { WRAPPER_NO_CONTRACT; SortRange(0, m_iCount - 1); } protected: //***************************************************************************** // Override this function to do the comparison. //***************************************************************************** virtual FORCEINLINE int Compare( // -1, 0, or 1 T *psFirst, // First item to compare. T *psSecond) // Second item to compare. { LIMITED_METHOD_DAC_CONTRACT; return (memcmp(psFirst, psSecond, sizeof(T))); // return (::Compare(*psFirst, *psSecond)); } virtual FORCEINLINE void Swap( SSIZE_T iFirst, SSIZE_T iSecond) { LIMITED_METHOD_DAC_CONTRACT; if (iFirst == iSecond) return; T sTemp( m_pBase[iFirst] ); m_pBase[iFirst] = m_pBase[iSecond]; m_pBase[iSecond] = sTemp; } private: inline void SortRange( SSIZE_T iLeft, SSIZE_T iRight) { WRAPPER_NO_CONTRACT; SSIZE_T iLast; SSIZE_T i; // loop variable. for (;;) { // if less than two elements you're done. if (iLeft >= iRight) return; // ASSERT that we now have valid indices. This is statically provable // since this private function is only called with valid indices, // and iLeft and iRight only converge towards eachother. However, // PreFast can't detect this because it doesn't know about our callers. COMPILER_ASSUME(iLeft >= 0 && iLeft < m_iCount); COMPILER_ASSUME(iRight >= 0 && iRight < m_iCount); // The mid-element is the pivot, move it to the left. Swap(iLeft, (iLeft + iRight) / 2); iLast = iLeft; // move everything that is smaller than the pivot to the left. for (i = iLeft + 1; i <= iRight; i++) { if (Compare(&m_pBase[i], &m_pBase[iLeft]) < 0) { Swap(i, ++iLast); } } // Put the pivot to the point where it is in between smaller and larger elements. Swap(iLeft, iLast); // Sort each partition. SSIZE_T iLeftLast = iLast - 1; SSIZE_T iRightFirst = iLast + 1; if (iLeftLast - iLeft < iRight - iRightFirst) { // Left partition is smaller, sort it recursively SortRange(iLeft, iLeftLast); // Tail call to sort the right (bigger) partition iLeft = iRightFirst; //iRight = iRight; continue; } else { // Right partition is smaller, sort it recursively SortRange(iRightFirst, iRight); // Tail call to sort the left (bigger) partition //iLeft = iLeft; iRight = iLeftLast; continue; } } } }; //***************************************************************************** // Faster and simpler version of the binary search below. //***************************************************************************** template const T * BinarySearch(const T * pBase, int iCount, const T & find) { WRAPPER_NO_CONTRACT; int iFirst = 0; int iLast = iCount - 1; // It is faster to use linear search once we get down to a small number of elements. while (iLast - iFirst > 10) { int iMid = (iLast + iFirst) / 2; if (find < pBase[iMid]) iLast = iMid - 1; else iFirst = iMid; } for (int i = iFirst; i <= iLast; i++) { if (find == pBase[i]) return &pBase[i]; if (find < pBase[i]) break; } return NULL; } //***************************************************************************** // This template encapsulates a binary search algorithm on the given type // of data. //***************************************************************************** template class CBinarySearch { private: const T *m_pBase; // Base of array to sort. int m_iCount; // How many items in array. public: CBinarySearch( const T *pBase, // Address of first element. int iCount) : // Value to find. m_pBase(pBase), m_iCount(iCount) { LIMITED_METHOD_CONTRACT; } //***************************************************************************** // Searches for the item passed to ctor. //***************************************************************************** const T *Find( // Pointer to found item in array. const T *psFind, // The key to find. int *piInsert = NULL) // Index to insert at. { WRAPPER_NO_CONTRACT; int iMid, iFirst, iLast; // Loop control. int iCmp; // Comparison. iFirst = 0; iLast = m_iCount - 1; while (iFirst <= iLast) { iMid = (iLast + iFirst) / 2; iCmp = Compare(psFind, &m_pBase[iMid]); if (iCmp == 0) { if (piInsert != NULL) *piInsert = iMid; return (&m_pBase[iMid]); } else if (iCmp < 0) iLast = iMid - 1; else iFirst = iMid + 1; } if (piInsert != NULL) *piInsert = iFirst; return (NULL); } //***************************************************************************** // Override this function to do the comparison if a comparison operator is // not valid for your data type (such as a struct). //***************************************************************************** virtual int Compare( // -1, 0, or 1 const T *psFirst, // Key you are looking for. const T *psSecond) // Item to compare to. { LIMITED_METHOD_CONTRACT; return (memcmp(psFirst, psSecond, sizeof(T))); // return (::Compare(*psFirst, *psSecond)); } }; //***************************************************************************** // The information that the hash table implementation stores at the beginning // of every record that can be but in the hash table. //***************************************************************************** typedef DPTR(struct HASHENTRY) PTR_HASHENTRY; struct HASHENTRY { ULONG iPrev; // Previous bucket in the chain. ULONG iNext; // Next bucket in the chain. }; typedef DPTR(struct FREEHASHENTRY) PTR_FREEHASHENTRY; struct FREEHASHENTRY : HASHENTRY { ULONG iFree; }; //***************************************************************************** // Used by the FindFirst/FindNextEntry functions. These api's allow you to // do a sequential scan of all entries. //***************************************************************************** struct HASHFIND { ULONG iBucket; // The next bucket to look in. ULONG iNext; }; //***************************************************************************** // IMPORTANT: This data structure is deprecated, please do not add any new uses. // The hashtable implementation that should be used instead is code:SHash. // If code:SHash does not work for you, talk to mailto:clrdeag. //***************************************************************************** // This is a class that implements a chain and bucket hash table. // // The data is actually supplied as an array of structures by the user of this class. // This allows the buckets to use small indices to point to the chain, instead of pointers. // // Each entry in the array contains a HASHENTRY structure immediately // followed by the key used to hash the structure. // // The HASHENTRY part of every structure is used to implement the chain of // entries in a single bucket. // // This implementation does not support rehashing the buckets if the table grows // to big. // @TODO: Fix this by adding an abstract function Hash() which must be implemented // by all clients. // //***************************************************************************** class CHashTable { friend class DebuggerRCThread; //RCthread actually needs access to //fields of derrived class DebuggerPatchTable protected: TADDR m_pcEntries; // Pointer to the array of structs. ULONG m_iEntrySize; // Size of the structs. ULONG m_iBuckets; // # of chains we are hashing into. PTR_ULONG m_piBuckets; // Ptr to the array of bucket chains. INDEBUG(unsigned m_maxSearch;) // For evaluating perf characteristics HASHENTRY *EntryPtr(ULONG iEntry) { LIMITED_METHOD_DAC_CONTRACT; return (PTR_HASHENTRY(m_pcEntries + (iEntry * (size_t)m_iEntrySize))); } ULONG ItemIndex(HASHENTRY *p) { SUPPORTS_DAC; LIMITED_METHOD_CONTRACT; return (ULONG)((dac_cast(p) - m_pcEntries) / m_iEntrySize); } public: CHashTable( ULONG iBuckets) : // # of chains we are hashing into. m_pcEntries((TADDR)NULL), m_iBuckets(iBuckets) { LIMITED_METHOD_CONTRACT; m_piBuckets = NULL; INDEBUG(m_maxSearch = 0;) } CHashTable() : // # of chains we are hashing into. m_pcEntries((TADDR)NULL), m_iBuckets(5) { LIMITED_METHOD_CONTRACT; m_piBuckets = NULL; INDEBUG(m_maxSearch = 0;) } #ifndef DACCESS_COMPILE ~CHashTable() { LIMITED_METHOD_CONTRACT; if (m_piBuckets != NULL) { delete [] m_piBuckets; m_piBuckets = NULL; } } //***************************************************************************** // This is the second part of construction where we do all of the work that // can fail. We also take the array of structs here because the calling class // presumably needs to allocate it in its NewInit. //***************************************************************************** HRESULT NewInit( // Return status. BYTE *pcEntries, // Array of structs we are managing. ULONG iEntrySize); // Size of the entries. //***************************************************************************** // This can be called to change the pointer to the table that the hash table // is managing. You might call this if (for example) you realloc the size // of the table and its pointer is different. //***************************************************************************** void SetTable( BYTE *pcEntries) // Array of structs we are managing. { LIMITED_METHOD_CONTRACT; m_pcEntries = (TADDR)pcEntries; } //***************************************************************************** // Clear the hash table as if there were nothing in it. //***************************************************************************** void Clear() { LIMITED_METHOD_CONTRACT; _ASSERTE(m_piBuckets != NULL); memset(m_piBuckets, 0xff, m_iBuckets * sizeof(ULONG)); } //***************************************************************************** // Add the struct at the specified index in m_pcEntries to the hash chains. //***************************************************************************** BYTE *Add( // New entry. ULONG iHash, // Hash value of entry to add. ULONG iIndex); // Index of struct in m_pcEntries. //***************************************************************************** // Delete the struct at the specified index in m_pcEntries from the hash chains. //***************************************************************************** void Delete( ULONG iHash, // Hash value of entry to delete. ULONG iIndex); // Index of struct in m_pcEntries. void Delete( ULONG iHash, // Hash value of entry to delete. HASHENTRY *psEntry); // The struct to delete. //***************************************************************************** // The item at the specified index has been moved, update the previous and // next item. //***************************************************************************** void Move( ULONG iHash, // Hash value for the item. ULONG iNew); // New location. #endif // #ifndef DACCESS_COMPILE //***************************************************************************** // Return a boolean indicating whether or not this hash table has been inited. //***************************************************************************** int IsInited() { LIMITED_METHOD_CONTRACT; return (m_piBuckets != NULL); } //***************************************************************************** // Search the hash table for an entry with the specified key value. //***************************************************************************** BYTE *Find( // Index of struct in m_pcEntries. ULONG iHash, // Hash value of the item. SIZE_T key); // The key to match. //***************************************************************************** // Search the hash table for the next entry with the specified key value. //***************************************************************************** ULONG FindNext( // Index of struct in m_pcEntries. SIZE_T key, // The key to match. ULONG iIndex); // Index of previous match. //***************************************************************************** // Returns the first entry in the first hash bucket and inits the search // struct. Use the FindNextEntry function to continue walking the list. The // return order is not guaranteed. //***************************************************************************** BYTE *FindFirstEntry( // First entry found, or 0. HASHFIND *psSrch) // Search object. { WRAPPER_NO_CONTRACT; if (m_piBuckets == 0) return (0); psSrch->iBucket = 1; psSrch->iNext = m_piBuckets[0]; return (FindNextEntry(psSrch)); } //***************************************************************************** // Returns the next entry in the list. //***************************************************************************** BYTE *FindNextEntry( // The next entry, or0 for end of list. HASHFIND *psSrch); // Search object. #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags, ULONG numEntries); #endif protected: virtual BOOL Cmp(SIZE_T key1, const HASHENTRY * pc2) = 0; }; class CNewData { public: static BYTE *Alloc(int iSize, int iMaxSize) { WRAPPER_NO_CONTRACT; return (new BYTE[iSize]); } static void Free(BYTE *pPtr, int iSize) { LIMITED_METHOD_CONTRACT; delete [] pPtr; } static BYTE *Grow(BYTE *&pPtr, int iCurSize) { WRAPPER_NO_CONTRACT; BYTE *p; S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize)); //check for overflow if(newSize.IsOverflow()) p = NULL; else p = new (nothrow) BYTE[newSize.Value()]; if (p == 0) return (0); memcpy (p, pPtr, iCurSize); delete [] pPtr; pPtr = p; return pPtr; } static void Clean(BYTE * pData, int iSize) { } static int RoundSize(int iSize) { LIMITED_METHOD_CONTRACT; return (iSize); } static int GrowSize(int iCurSize) { LIMITED_METHOD_CONTRACT; int newSize = (3 * iCurSize) / 2; return (newSize < 256) ? 256 : newSize; } }; class CNewDataNoThrow { public: static BYTE *Alloc(int iSize, int iMaxSize) { WRAPPER_NO_CONTRACT; return (new (nothrow) BYTE[iSize]); } static void Free(BYTE *pPtr, int iSize) { LIMITED_METHOD_CONTRACT; delete [] pPtr; } static BYTE *Grow(BYTE *&pPtr, int iCurSize) { WRAPPER_NO_CONTRACT; BYTE *p; S_SIZE_T newSize = S_SIZE_T(iCurSize) + S_SIZE_T(GrowSize(iCurSize)); //check for overflow if(newSize.IsOverflow()) p = NULL; else p = new (nothrow) BYTE[newSize.Value()]; if (p == 0) return (0); memcpy (p, pPtr, iCurSize); delete [] pPtr; pPtr = p; return pPtr; } static void Clean(BYTE * pData, int iSize) { } static int RoundSize(int iSize) { LIMITED_METHOD_CONTRACT; return (iSize); } static int GrowSize(int iCurSize) { LIMITED_METHOD_CONTRACT; int newSize = (3 * iCurSize) / 2; return (newSize < 256) ? 256 : newSize; } }; //***************************************************************************** // IMPORTANT: This data structure is deprecated, please do not add any new uses. // The hashtable implementation that should be used instead is code:SHash. // If code:SHash does not work for you, talk to mailto:clrdeag. //***************************************************************************** // CHashTable expects the data to be in a single array - this is provided by // CHashTableAndData. // The array is allocated using the MemMgr type. CNewData and // CNewDataNoThrow can be used for this. //***************************************************************************** template class CHashTableAndData : public CHashTable { public: DAC_ALIGNAS(CHashTable) ULONG m_iFree; // Index into m_pcEntries[] of next available slot ULONG m_iEntries; // size of m_pcEntries[] public: CHashTableAndData() : CHashTable() { LIMITED_METHOD_CONTRACT; } CHashTableAndData( ULONG iBuckets) : // # of chains we are hashing into. CHashTable(iBuckets) { LIMITED_METHOD_CONTRACT; } #ifndef DACCESS_COMPILE ~CHashTableAndData() { WRAPPER_NO_CONTRACT; if (m_pcEntries != NULL) MemMgr::Free((BYTE*)m_pcEntries, MemMgr::RoundSize(m_iEntries * m_iEntrySize)); } //***************************************************************************** // This is the second part of construction where we do all of the work that // can fail. We also take the array of structs here because the calling class // presumably needs to allocate it in its NewInit. //***************************************************************************** HRESULT NewInit( // Return status. ULONG iEntries, // # of entries. ULONG iEntrySize, // Size of the entries. int iMaxSize); // Max size of data. //***************************************************************************** // Clear the hash table as if there were nothing in it. //***************************************************************************** void Clear() { WRAPPER_NO_CONTRACT; m_iFree = 0; InitFreeChain(0, m_iEntries); CHashTable::Clear(); } //***************************************************************************** // Grabs a slot for the new entry to be added. // The caller should fill in the non-HASHENTRY part of the returned slot //***************************************************************************** BYTE *Add( ULONG iHash) // Hash value of entry to add. { WRAPPER_NO_CONTRACT; FREEHASHENTRY *psEntry; // Make the table bigger if necessary. if (m_iFree == UINT32_MAX && !Grow()) return (NULL); // Add the first entry from the free list to the hash chain. psEntry = (FREEHASHENTRY *) CHashTable::Add(iHash, m_iFree); m_iFree = psEntry->iFree; // If we're recycling memory, give our memory-allocator a chance to re-init it. // Each entry is prefixed with a header - we don't want to trash that. SIZE_T cbHeader = sizeof(FREEHASHENTRY); MemMgr::Clean((BYTE*) psEntry + cbHeader, (int) (m_iEntrySize - cbHeader)); return ((BYTE *) psEntry); } //***************************************************************************** // Delete the struct at the specified index in m_pcEntries from the hash chains. //***************************************************************************** void Delete( ULONG iHash, // Hash value of entry to delete. ULONG iIndex) // Index of struct in m_pcEntries. { WRAPPER_NO_CONTRACT; CHashTable::Delete(iHash, iIndex); ((FREEHASHENTRY *) EntryPtr(iIndex))->iFree = m_iFree; m_iFree = iIndex; } void Delete( ULONG iHash, // Hash value of entry to delete. HASHENTRY *psEntry) // The struct to delete. { WRAPPER_NO_CONTRACT; CHashTable::Delete(iHash, psEntry); ((FREEHASHENTRY *) psEntry)->iFree = m_iFree; m_iFree = ItemIndex(psEntry); } #endif // #ifndef DACCESS_COMPILE // This is a sad legacy workaround. The debugger's patch table (implemented as this // class) is shared across process. We publish the runtime offsets of // some key fields. Since those fields are private, we have to provide // accessors here. So if you're not using these functions, don't start. // We can hopefully remove them. // Note that we can't just make RCThread a friend of this class (we tried // originally) because the inheritance chain has a private modifier, // so DebuggerPatchTable::m_pcEntries is illegal. static SIZE_T helper_GetOffsetOfEntries() { LIMITED_METHOD_CONTRACT; return offsetof(CHashTableAndData, m_pcEntries); } static SIZE_T helper_GetOffsetOfCount() { LIMITED_METHOD_CONTRACT; return offsetof(CHashTableAndData, m_iEntries); } #ifdef DACCESS_COMPILE void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) { SUPPORTS_DAC; CHashTable::EnumMemoryRegions(flags, m_iEntries); } #endif private: void InitFreeChain(ULONG iStart,ULONG iEnd); int Grow(); }; #ifndef DACCESS_COMPILE //***************************************************************************** // This is the second part of construction where we do all of the work that // can fail. We also take the array of structs here because the calling class // presumably needs to allocate it in its NewInit. //***************************************************************************** template HRESULT CHashTableAndData::NewInit(// Return status. ULONG iEntries, // # of entries. ULONG iEntrySize, // Size of the entries. int iMaxSize) // Max size of data. { WRAPPER_NO_CONTRACT; BYTE *pcEntries; HRESULT hr; // note that this function can throw because it depends on the ::Alloc // Allocate the memory for the entries. if ((pcEntries = MemMgr::Alloc(MemMgr::RoundSize(iEntries * iEntrySize), MemMgr::RoundSize(iMaxSize))) == 0) return (E_OUTOFMEMORY); m_iEntries = iEntries; // Init the base table. if (FAILED(hr = CHashTable::NewInit(pcEntries, iEntrySize))) MemMgr::Free(pcEntries, MemMgr::RoundSize(iEntries * iEntrySize)); else { // Init the free chain. m_iFree = 0; InitFreeChain(0, iEntries); } return (hr); } //***************************************************************************** // Initialize a range of records such that they are linked together to be put // on the free chain. //***************************************************************************** template void CHashTableAndData::InitFreeChain( ULONG iStart, // Index to start initializing. ULONG iEnd) // Index to stop initializing { LIMITED_METHOD_CONTRACT; BYTE* pcPtr; _ASSERTE(iEnd > iStart); pcPtr = (BYTE*)m_pcEntries + iStart * (size_t)m_iEntrySize; for (++iStart; iStart < iEnd; ++iStart) { ((FREEHASHENTRY *) pcPtr)->iFree = iStart; pcPtr += m_iEntrySize; } ((FREEHASHENTRY *) pcPtr)->iFree = UINT32_MAX; } //***************************************************************************** // Attempt to increase the amount of space available for the record heap. //***************************************************************************** template int CHashTableAndData::Grow() // 1 if successful, 0 if not. { WRAPPER_NO_CONTRACT; int iCurSize; // Current size in bytes. int iEntries; // New # of entries. _ASSERTE(m_pcEntries != NULL); _ASSERTE(m_iFree == UINT32_MAX); // Compute the current size and new # of entries. S_UINT32 iTotEntrySize = S_UINT32(m_iEntries) * S_UINT32(m_iEntrySize); if( iTotEntrySize.IsOverflow() ) { _ASSERTE( !"CHashTableAndData overflow!" ); return (0); } iCurSize = MemMgr::RoundSize( iTotEntrySize.Value() ); iEntries = (iCurSize + MemMgr::GrowSize(iCurSize)) / m_iEntrySize; if ( (iEntries < 0) || ((ULONG)iEntries <= m_iEntries) ) { _ASSERTE( !"CHashTableAndData overflow!" ); return (0); } // Try to expand the array. if (MemMgr::Grow(*(BYTE**)&m_pcEntries, iCurSize) == 0) return (0); // Init the newly allocated space. InitFreeChain(m_iEntries, iEntries); m_iFree = m_iEntries; m_iEntries = iEntries; return (1); } #endif // #ifndef DACCESS_COMPILE //***************************************************************************** //***************************************************************************** inline COUNT_T HashCOUNT_T(COUNT_T currentHash, COUNT_T data) { LIMITED_METHOD_DAC_CONTRACT; return ((currentHash << 5) + currentHash) ^ data; } inline COUNT_T HashPtr(COUNT_T currentHash, PTR_VOID ptr) { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return HashCOUNT_T(currentHash, COUNT_T(SIZE_T(dac_cast(ptr)))); } inline ULONG HashBytes(BYTE const *pbData, size_t iSize) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; BYTE const *pbDataEnd = pbData + iSize; for (/**/ ; pbData < pbDataEnd; pbData++) { hash = ((hash << 5) + hash) ^ *pbData; } return hash; } // Helper function for hashing a string char by char. inline ULONG HashStringA(LPCSTR szStr) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; int c; while ((c = *szStr) != 0) { hash = ((hash << 5) + hash) ^ c; ++szStr; } return hash; } inline ULONG HashString(LPCWSTR szStr) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; int c; while ((c = *szStr) != 0) { hash = ((hash << 5) + hash) ^ c; ++szStr; } return hash; } inline ULONG HashStringN(LPCWSTR szStr, SIZE_T cchStr) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; // hash the string two characters at a time ULONG *ptr = (ULONG *)szStr; // we assume that szStr is null-terminated _ASSERTE(cchStr <= wcslen(szStr)); SIZE_T cDwordCount = (cchStr + 1) / 2; for (SIZE_T i = 0; i < cDwordCount; i++) { hash = ((hash << 5) + hash) ^ ptr[i]; } return hash; } // Case-insensitive string hash function. inline ULONG HashiStringA(LPCSTR szStr) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; while (*szStr != 0) { hash = ((hash << 5) + hash) ^ toupper(*szStr); szStr++; } return hash; } // Case-insensitive string hash function. inline ULONG HashiString(LPCWSTR szStr) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; while (*szStr != 0) { hash = ((hash << 5) + hash) ^ towupper(*szStr); szStr++; } return hash; } // Case-insensitive string hash function. inline ULONG HashiStringN(LPCWSTR szStr, DWORD count) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; while (*szStr != 0 && count--) { hash = ((hash << 5) + hash) ^ towupper(*szStr); szStr++; } return hash; } // Case-insensitive string hash function when all of the // characters in the string are known to be below 0x80. // Knowing this is much more efficient than calling // towupper above. inline ULONG HashiStringKnownLower80(LPCWSTR szStr) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; int c; int mask = ~0x20; while ((c = *szStr)!=0) { //If we have a lowercase character, ANDing off 0x20 //(mask) will make it an uppercase character. if (c>='a' && c<='z') { c&=mask; } hash = ((hash << 5) + hash) ^ c; ++szStr; } return hash; } inline ULONG HashiStringNKnownLower80(LPCWSTR szStr, DWORD count) { LIMITED_METHOD_CONTRACT; ULONG hash = 5381; int c; int mask = ~0x20; while ((c = *szStr) !=0 && count--) { //If we have a lowercase character, ANDing off 0x20 //(mask) will make it an uppercase character. if (c>='a' && c<='z') { c&=mask; } hash = ((hash << 5) + hash) ^ c; ++szStr; } return hash; } //***************************************************************************** // IMPORTANT: This data structure is deprecated, please do not add any new uses. // The hashtable implementation that should be used instead is code:SHash. // If code:SHash does not work for you, talk to mailto:clrdeag. //***************************************************************************** // This class implements a closed hashing table. Values are hashed to a bucket, // and if that bucket is full already, then the value is placed in the next // free bucket starting after the desired target (with wrap around). If the // table becomes 75% full, it is grown and rehashed to reduce lookups. This // class is best used in a reltively small lookup table where hashing is // not going to cause many collisions. By not having the collision chain // logic, a lot of memory is saved. // // The user of the template is required to supply several methods which decide // how each element can be marked as free, deleted, or used. It would have // been possible to write this with more internal logic, but that would require // either (a) more overhead to add status on top of elements, or (b) hard // coded types like one for strings, one for ints, etc... This gives you the // flexibility of adding logic to your type. //***************************************************************************** class CClosedHashBase { BYTE *EntryPtr(int iEntry) { LIMITED_METHOD_CONTRACT; return (m_rgData + (iEntry * (size_t)m_iEntrySize)); } BYTE *EntryPtr(int iEntry, BYTE *rgData) { LIMITED_METHOD_CONTRACT; return (rgData + (iEntry * (size_t)m_iEntrySize)); } public: enum ELEMENTSTATUS { FREE, // Item is not in use right now. DELETED, // Item is deleted. USED // Item is in use. }; CClosedHashBase( int iBuckets, // How many buckets should we start with. int iEntrySize, // Size of an entry. bool bPerfect) : // true if bucket size will hash with no collisions. m_bPerfect(bPerfect), m_iBuckets(iBuckets), m_iEntrySize(iEntrySize), m_iCount(0), m_iCollisions(0), m_rgData(0) { LIMITED_METHOD_CONTRACT; m_iSize = iBuckets + 7; } virtual ~CClosedHashBase() { WRAPPER_NO_CONTRACT; Clear(); } virtual void Clear() { LIMITED_METHOD_CONTRACT; delete [] m_rgData; m_iCount = 0; m_iCollisions = 0; m_rgData = 0; } //***************************************************************************** // Accessors for getting at the underlying data. Be careful to use Count() // only when you want the number of buckets actually used. //***************************************************************************** int Count() { LIMITED_METHOD_CONTRACT; return (m_iCount); } int Collisions() { LIMITED_METHOD_CONTRACT; return (m_iCollisions); } int Buckets() { LIMITED_METHOD_CONTRACT; return (m_iBuckets); } void SetBuckets(int iBuckets, bool bPerfect=false) { LIMITED_METHOD_CONTRACT; _ASSERTE(m_rgData == 0); m_iBuckets = iBuckets; m_iSize = m_iBuckets + 7; m_bPerfect = bPerfect; } BYTE *Data() { LIMITED_METHOD_CONTRACT; return (m_rgData); } //***************************************************************************** // Add a new item to hash table given the key value. If this new entry // exceeds maximum size, then the table will grow and be re-hashed, which // may cause a memory error. //***************************************************************************** BYTE *Add( // New item to fill out on success. void *pData) // The value to hash on. { WRAPPER_NO_CONTRACT; // If we haven't allocated any memory, or it is too small, fix it. if (!m_rgData || ((m_iCount + 1) > (m_iSize * 3 / 4) && !m_bPerfect)) { if (!ReHash()) return (0); } return (DoAdd(pData, m_rgData, m_iBuckets, m_iSize, m_iCollisions, m_iCount)); } //***************************************************************************** // Delete the given value. This will simply mark the entry as deleted (in // order to keep the collision chain intact). There is an optimization that // consecutive deleted entries leading up to a free entry are themselves freed // to reduce collisions later on. //***************************************************************************** void Delete( void *pData); // Key value to delete. //***************************************************************************** // Callback function passed to DeleteLoop. //***************************************************************************** typedef BOOL (* DELETELOOPFUNC)( // Delete current item? BYTE *pEntry, // Bucket entry to evaluate void *pCustomizer); // User-defined value //***************************************************************************** // Iterates over all active values, passing each one to pDeleteLoopFunc. // If pDeleteLoopFunc returns TRUE, the entry is deleted. This is safer // and faster than using FindNext() and Delete(). //***************************************************************************** void DeleteLoop( DELETELOOPFUNC pDeleteLoopFunc, // Decides whether to delete item void *pCustomizer); // Extra value passed to deletefunc. //***************************************************************************** // Lookup a key value and return a pointer to the element if found. //***************************************************************************** BYTE *Find( // The item if found, 0 if not. void *pData); // The key to lookup. //***************************************************************************** // Look for an item in the table. If it isn't found, then create a new one and // return that. //***************************************************************************** BYTE *FindOrAdd( // The item if found, 0 if not. void *pData, // The key to lookup. bool &bNew); // true if created. //***************************************************************************** // The following functions are used to traverse each used entry. This code // will skip over deleted and free entries freeing the caller up from such // logic. //***************************************************************************** BYTE *GetFirst() // The first entry, 0 if none. { WRAPPER_NO_CONTRACT; int i; // Loop control. // If we've never allocated the table there can't be any to get. if (m_rgData == 0) return (0); // Find the first one. for (i=0; i class CChainedHash { friend class VerifyLayoutsMD; public: CChainedHash(int iBuckets=32) : m_rgData(0), m_iBuckets(iBuckets), m_iCount(0), m_iMaxChain(0), m_iFree(0) { LIMITED_METHOD_CONTRACT; m_iSize = iBuckets + (iBuckets / 2); } ~CChainedHash() { LIMITED_METHOD_CONTRACT; if (m_rgData) delete [] m_rgData; } void SetBuckets(int iBuckets) { LIMITED_METHOD_CONTRACT; _ASSERTE(m_rgData == 0); // if iBuckets==0, then we'll allocate a zero size array and AV on dereference. _ASSERTE(iBuckets > 0); m_iBuckets = iBuckets; m_iSize = iBuckets + (iBuckets / 2); } T *Add(void const *pData) { WRAPPER_NO_CONTRACT; ULONG iHash; int iBucket; T *pItem; // Build the list if required. if (m_rgData == 0 || m_iFree == 0xffffffff) { if (!ReHash()) return (0); } // Hash the item and pick a bucket. iHash = Hash(pData); iBucket = iHash % m_iBuckets; // Use the bucket if it is free. if (InUse(&m_rgData[iBucket]) == false) { pItem = &m_rgData[iBucket]; pItem->iNext = 0xffffffff; } // Else take one off of the free list for use. else { ULONG iEntry; // Pull an item from the free list. iEntry = m_iFree; pItem = &m_rgData[m_iFree]; m_iFree = pItem->iNext; // Link the new node in after the bucket. pItem->iNext = m_rgData[iBucket].iNext; m_rgData[iBucket].iNext = iEntry; } ++m_iCount; return (pItem); } T *Find(void const *pData, bool bAddIfNew=false) { WRAPPER_NO_CONTRACT; ULONG iHash; int iBucket; T *pItem; // Check states for lookup. if (m_rgData == 0) { // If we won't be adding, then we are through. if (bAddIfNew == false) return (0); // Otherwise, create the table. if (!ReHash()) return (0); } // Hash the item and pick a bucket. iHash = Hash(pData); iBucket = iHash % m_iBuckets; // If it isn't in use, then there it wasn't found. if (!InUse(&m_rgData[iBucket])) { if (bAddIfNew == false) pItem = 0; else { pItem = &m_rgData[iBucket]; pItem->iNext = 0xffffffff; ++m_iCount; } } // Scan the list for the one we want. else { ULONG iChain = 0; for (pItem=(T *) &m_rgData[iBucket]; pItem; pItem=GetNext(pItem)) { if (Cmp(pData, pItem) == 0) break; ++iChain; } if (!pItem && bAddIfNew) { ULONG iEntry; // Record maximum chain length. if (iChain > m_iMaxChain) m_iMaxChain = iChain; // Now need more room. if (m_iFree == 0xffffffff) { if (!ReHash()) return (0); } // Pull an item from the free list. iEntry = m_iFree; pItem = &m_rgData[m_iFree]; m_iFree = pItem->iNext; // Link the new node in after the bucket. pItem->iNext = m_rgData[iBucket].iNext; m_rgData[iBucket].iNext = iEntry; ++m_iCount; } } return (pItem); } int Count() { LIMITED_METHOD_CONTRACT; return (m_iCount); } int Buckets() { LIMITED_METHOD_CONTRACT; return (m_iBuckets); } ULONG MaxChainLength() { LIMITED_METHOD_CONTRACT; return (m_iMaxChain); } virtual void Clear() { LIMITED_METHOD_CONTRACT; // Free up the memory. if (m_rgData) { delete [] m_rgData; m_rgData = 0; } m_rgData = 0; m_iFree = 0; m_iCount = 0; m_iMaxChain = 0; } virtual bool InUse(T *pItem)=0; virtual void SetFree(T *pItem)=0; virtual ULONG Hash(void const *pData)=0; virtual int Cmp(void const *pData, void *pItem)=0; private: inline T *GetNext(T *pItem) { LIMITED_METHOD_CONTRACT; if (pItem->iNext != 0xffffffff) return ((T *) &m_rgData[pItem->iNext]); return (0); } bool ReHash() { WRAPPER_NO_CONTRACT; T *rgTemp; int iNewSize; // If this is a first time allocation, then just malloc it. if (!m_rgData) { if ((m_rgData = new (nothrow) T[m_iSize]) == 0) return (false); int i; for (i=0; iiNext = i + 1; ((T *) &m_rgData[m_iSize - 1])->iNext = 0xffffffff; return (true); } // Otherwise we need more room on the free chain, so allocate some. iNewSize = m_iSize + (m_iSize / 2); // Allocate/realloc memory. if ((rgTemp = new (nothrow) T[iNewSize]) == 0) return (false); memcpy (rgTemp,m_rgData,m_iSize*sizeof(T)); delete [] m_rgData; // Init new entries, save the new free chain, and reset internals. m_iFree = m_iSize; for (int i=m_iFree; iiNext = i + 1; } ((T *) &rgTemp[iNewSize - 1])->iNext = 0xffffffff; m_rgData = rgTemp; m_iSize = iNewSize; return (true); } private: T *m_rgData; // Data to store items in. int m_iBuckets; // How many buckets we want. int m_iSize; // How many are allocated. int m_iCount; // How many are we using. ULONG m_iMaxChain; // Max chain length. ULONG m_iFree; // Free chain. }; //***************************************************************************** // //********** String helper functions. // //***************************************************************************** //***************************************************************************** // Checks if string length exceeds the specified limit //***************************************************************************** inline BOOL IsStrLongerThan(_In_ _In_z_ char* pstr, unsigned N) { LIMITED_METHOD_CONTRACT; unsigned i = 0; if(pstr) { for(i=0; (i < N)&&(pstr[i]); i++); } return (i >= N); } //***************************************************************************** // Class to parse a list of simple assembly names and then find a match //***************************************************************************** class AssemblyNamesList { struct AssemblyName { LPUTF8 m_assemblyName; AssemblyName *m_next; // Next name }; AssemblyName *m_pNames; // List of names public: bool IsInList(LPCUTF8 assemblyName); bool IsEmpty() { LIMITED_METHOD_CONTRACT; return m_pNames == 0; } AssemblyNamesList(_In_ LPWSTR list); ~AssemblyNamesList(); }; //***************************************************************************** // Class to parse a list of method names and then find a match //***************************************************************************** struct CORINFO_SIG_INFO; class MethodNamesListBase { struct MethodName { LPUTF8 methodName; // NULL means wildcard LPUTF8 className; // NULL means wildcard int numArgs; // number of args for the method, -1 is wildcard MethodName *next; // Next name }; MethodName *pNames; // List of names bool IsInList(LPCUTF8 methodName, LPCUTF8 className, int numArgs); public: void Init() { LIMITED_METHOD_CONTRACT; pNames = 0; } void Init(_In_ _In_z_ LPWSTR list) { WRAPPER_NO_CONTRACT; pNames = 0; Insert(list); } void Destroy(); void Insert(_In_ _In_z_ LPWSTR list); bool IsInList(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL); bool IsInList(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo); bool IsEmpty() { LIMITED_METHOD_CONTRACT; return pNames == 0; } }; class MethodNamesList : public MethodNamesListBase { public: MethodNamesList() { WRAPPER_NO_CONTRACT; Init(); } MethodNamesList(_In_ LPWSTR list) { WRAPPER_NO_CONTRACT; Init(list); } ~MethodNamesList() { WRAPPER_NO_CONTRACT; Destroy(); } }; #include "clrconfig.h" /**************************************************************************/ /* simple wrappers around the CLRConfig and MethodNameList routines that make the lookup lazy */ /* to be used as static variable - no constructor/destructor, assumes zero initialized memory */ class ConfigDWORD { public: inline DWORD val(const CLRConfig::ConfigDWORDInfo & info) { WRAPPER_NO_CONTRACT; // make sure that the memory was zero initialized _ASSERTE(m_inited == 0 || m_inited == 1); if (!m_inited) init(info); return m_value; } private: void init(const CLRConfig::ConfigDWORDInfo & info); private: DWORD m_value; BYTE m_inited; }; /**************************************************************************/ class ConfigString { public: inline LPWSTR val(const CLRConfig::ConfigStringInfo & info) { WRAPPER_NO_CONTRACT; // make sure that the memory was zero initialized _ASSERTE(m_inited == 0 || m_inited == 1); if (!m_inited) init(info); return m_value; } bool isInitialized() { WRAPPER_NO_CONTRACT; // make sure that the memory was zero initialized _ASSERTE(m_inited == 0 || m_inited == 1); return m_inited == 1; } private: void init(const CLRConfig::ConfigStringInfo & info); private: LPWSTR m_value; BYTE m_inited; }; /**************************************************************************/ class ConfigMethodSet { public: bool isEmpty() { WRAPPER_NO_CONTRACT; _ASSERTE(m_inited == 1); return m_list.IsEmpty(); } bool contains(LPCUTF8 methodName, LPCUTF8 className, PCCOR_SIGNATURE sig = NULL); bool contains(LPCUTF8 methodName, LPCUTF8 className, CORINFO_SIG_INFO* pSigInfo); inline void ensureInit(const CLRConfig::ConfigStringInfo & info) { WRAPPER_NO_CONTRACT; // make sure that the memory was zero initialized _ASSERTE(m_inited == 0 || m_inited == 1); if (!m_inited) init(info); } private: void init(const CLRConfig::ConfigStringInfo & info); private: MethodNamesListBase m_list; BYTE m_inited; }; // 38 characters + 1 null terminating. #define GUID_STR_BUFFER_LEN (ARRAY_SIZE("{12345678-1234-1234-1234-123456789abc}")) //***************************************************************************** // Convert a GUID into a pointer to a string //***************************************************************************** int GuidToLPSTR( REFGUID guid, // [IN] The GUID to convert. LPSTR szGuid, // [OUT] String into which the GUID is stored DWORD cchGuid); // [IN] Size in chars of szGuid template int GuidToLPSTR(REFGUID guid, CHAR (&s)[N]) { return GuidToLPSTR(guid, s, N); } //***************************************************************************** // Convert a pointer to a string into a GUID. //***************************************************************************** BOOL LPCSTRToGuid( LPCSTR szGuid, // [IN] String to convert. GUID* pGuid); // [OUT] Buffer for converted GUID. //***************************************************************************** // Convert a GUID into a pointer to a string //***************************************************************************** int GuidToLPWSTR( REFGUID guid, // [IN] The GUID to convert. LPWSTR szGuid, // [OUT] String into which the GUID is stored DWORD cchGuid); // [IN] Size in wide chars of szGuid template int GuidToLPWSTR(REFGUID guid, WCHAR (&s)[N]) { return GuidToLPWSTR(guid, s, N); } //***************************************************************************** // Parse a Wide char string into a GUID //***************************************************************************** BOOL LPCWSTRToGuid( LPCWSTR szGuid, // [IN] String to convert. GUID* pGuid); // [OUT] Buffer for converted GUID. typedef VPTR(class RangeList) PTR_RangeList; class RangeList { public: VPTR_BASE_CONCRETE_VTABLE_CLASS(RangeList) #ifndef DACCESS_COMPILE RangeList(); ~RangeList(); #else RangeList() { LIMITED_METHOD_CONTRACT; } #endif // Wrappers to make the virtual calls DAC-safe. BOOL AddRange(const BYTE *start, const BYTE *end, void *id) { return this->AddRangeWorker(start, end, id); } void RemoveRanges(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { return this->RemoveRangesWorker(id, start, end); } BOOL IsInRange(TADDR address, TADDR *pID = NULL) { SUPPORTS_DAC; return this->IsInRangeWorker(address, pID); } #ifndef DACCESS_COMPILE // You can overload these two for synchronization (as LockedRangeList does) virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id); // If both "start" and "end" are NULL, then this method deletes all ranges with // the given id (i.e. the original behaviour). Otherwise, it ignores the given // id and deletes all ranges falling in the region [start, end). virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL); #else virtual BOOL AddRangeWorker(const BYTE *start, const BYTE *end, void *id) { return TRUE; } virtual void RemoveRangesWorker(void *id, const BYTE *start = NULL, const BYTE *end = NULL) { } #endif // !DACCESS_COMPILE virtual BOOL IsInRangeWorker(TADDR address, TADDR *pID = NULL); #ifdef DACCESS_COMPILE void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags); #endif enum { RANGE_COUNT = 10 }; private: struct Range { TADDR start; TADDR end; TADDR id; }; struct RangeListBlock { Range ranges[RANGE_COUNT]; DPTR(RangeListBlock) next; #ifdef DACCESS_COMPILE void EnumMemoryRegions(enum CLRDataEnumMemoryFlags flags); #endif }; void InitBlock(RangeListBlock *block); RangeListBlock m_starterBlock; DPTR(RangeListBlock) m_firstEmptyBlock; TADDR m_firstEmptyRange; }; // // A private function to do the equavilent of a CoCreateInstance in // cases where we can't make the real call. Use this when, for // instance, you need to create a symbol reader in the Runtime but // we're not CoInitialized. Obviously, this is only good for COM // objects for which CoCreateInstance is just a glorified // find-and-load-me operation. // HRESULT FakeCoCreateInstanceEx(REFCLSID rclsid, LPCWSTR wszDllPath, REFIID riid, void ** ppv, HMODULE * phmodDll); // Provided for backward compatibility and for code that doesn't need the HMODULE of the // DLL that was loaded to create the COM object. See comment at implementation of // code:FakeCoCreateInstanceEx for more details. inline HRESULT FakeCoCreateInstance(REFCLSID rclsid, REFIID riid, void ** ppv) { CONTRACTL { NOTHROW; } CONTRACTL_END; return FakeCoCreateInstanceEx(rclsid, NULL, riid, ppv, NULL); }; //***************************************************************************** // Gets the directory based on the location of the module. This routine // is called at COR setup time. Set is called during EEStartup and by the // MetaData dispenser. //***************************************************************************** HRESULT GetInternalSystemDirectory(_Out_writes_to_opt_(*pdwLength,*pdwLength) LPWSTR buffer, __inout DWORD* pdwLength); LPCWSTR GetInternalSystemDirectory(_Out_opt_ DWORD * pdwLength = NULL); //***************************************************************************** // This function validates the given Method/Field/Standalone signature. (util.cpp) //***************************************************************************** struct IMDInternalImport; HRESULT validateTokenSig( mdToken tk, // [IN] Token whose signature needs to be validated. PCCOR_SIGNATURE pbSig, // [IN] Signature. ULONG cbSig, // [IN] Size in bytes of the signature. DWORD dwFlags, // [IN] Method flags. IMDInternalImport* pImport); // [IN] Internal MD Import interface ptr //***************************************************************************** // Determine the version number of the runtime that was used to build the // specified image. The pMetadata pointer passed in is the pointer to the // metadata contained in the image. //***************************************************************************** HRESULT GetImageRuntimeVersionString(PVOID pMetaData, LPCSTR* pString); //***************************************************************************** // The registry keys and values that contain the information regarding // the default registered unmanaged debugger. //***************************************************************************** #define kDebugApplicationsPoliciesKey W("SOFTWARE\\Policies\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications") #define kDebugApplicationsKey W("SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\DebugApplications") #define kUnmanagedDebuggerKey W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug") #define kUnmanagedDebuggerValue W("Debugger") #define kUnmanagedDebuggerAutoValue W("Auto") #define kUnmanagedDebuggerAutoExclusionListKey W("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\AeDebug\\AutoExclusionList") BOOL GetRegistryLongValue(HKEY hKeyParent, // Parent key. LPCWSTR szKey, // Key name to look at. LPCWSTR szName, // Name of value to get. long *pValue, // Put value here, if found. BOOL fReadNonVirtualizedKey); // Whether to read 64-bit hive on WOW64 HRESULT GetCurrentModuleFileName(SString& pBuffer); //***************************************************************************** // Retrieve information regarding what registered default debugger //***************************************************************************** void GetDebuggerSettingInfo(SString &debuggerKeyValue, BOOL *pfAuto); HRESULT GetDebuggerSettingInfoWorker(_Out_writes_to_opt_(*pcchDebuggerString, *pcchDebuggerString) LPWSTR wszDebuggerString, DWORD * pcchDebuggerString, BOOL * pfAuto); void TrimWhiteSpace(__inout_ecount(*pcch) LPCWSTR *pwsz, __inout LPDWORD pcch); void OutputDebugStringUtf8(LPCUTF8 utf8str); //***************************************************************************** // Convert a UTF8 string to Unicode, into a CQuickArray. //***************************************************************************** HRESULT Utf2Quick( LPCUTF8 pStr, // The string to convert. CQuickArray &rStr, // The QuickArray to convert it into. int iCurLen = 0); // Initial characters in the array to leave (default 0). //***************************************************************************** // Extract the movl 64-bit unsigned immediate from an IA64 bundle // (Format X2) //***************************************************************************** UINT64 GetIA64Imm64(UINT64 * pBundle); UINT64 GetIA64Imm64(UINT64 qword0, UINT64 qword1); //***************************************************************************** // Deposit the movl 64-bit unsigned immediate into an IA64 bundle // (Format X2) //***************************************************************************** void PutIA64Imm64(UINT64 * pBundle, UINT64 imm64); //***************************************************************************** // Extract the IP-Relative signed 25-bit immediate from an IA64 bundle // (Formats B1, B2 or B3) // Note that due to branch target alignment requirements // the lowest four bits in the result will always be zero. //***************************************************************************** INT32 GetIA64Rel25(UINT64 * pBundle, UINT32 slot); INT32 GetIA64Rel25(UINT64 qword0, UINT64 qword1, UINT32 slot); //***************************************************************************** // Deposit the IP-Relative signed 25-bit immediate into an IA64 bundle // (Formats B1, B2 or B3) // Note that due to branch target alignment requirements // the lowest four bits are required to be zero. //***************************************************************************** void PutIA64Rel25(UINT64 * pBundle, UINT32 slot, INT32 imm25); //***************************************************************************** // Extract the IP-Relative signed 64-bit immediate from an IA64 bundle // (Formats X3 or X4) //***************************************************************************** INT64 GetIA64Rel64(UINT64 * pBundle); INT64 GetIA64Rel64(UINT64 qword0, UINT64 qword1); //***************************************************************************** // Deposit the IP-Relative signed 64-bit immediate into a IA64 bundle // (Formats X3 or X4) //***************************************************************************** void PutIA64Rel64(UINT64 * pBundle, INT64 imm64); //***************************************************************************** // Extract the 32-bit immediate from movw/movt Thumb2 sequence //***************************************************************************** UINT32 GetThumb2Mov32(UINT16 * p); //***************************************************************************** // Deposit the 32-bit immediate into movw/movt Thumb2 sequence //***************************************************************************** void PutThumb2Mov32(UINT16 * p, UINT32 imm32); //***************************************************************************** // Extract the 24-bit rel offset from bl instruction //***************************************************************************** INT32 GetThumb2BlRel24(UINT16 * p); //***************************************************************************** // Extract the 24-bit rel offset from bl instruction //***************************************************************************** void PutThumb2BlRel24(UINT16 * p, INT32 imm24); //***************************************************************************** // Extract the PC-Relative offset from a b or bl instruction //***************************************************************************** INT32 GetArm64Rel28(UINT32 * pCode); //***************************************************************************** // Extract the PC-Relative page address from an adrp instruction //***************************************************************************** INT32 GetArm64Rel21(UINT32 * pCode); //***************************************************************************** // Extract the page offset from an add instruction //***************************************************************************** INT32 GetArm64Rel12(UINT32 * pCode); //***************************************************************************** // Deposit the PC-Relative offset 'imm28' into a b or bl instruction //***************************************************************************** void PutArm64Rel28(UINT32 * pCode, INT32 imm28); //***************************************************************************** // Deposit the PC-Relative page address 'imm21' into an adrp instruction //***************************************************************************** void PutArm64Rel21(UINT32 * pCode, INT32 imm21); //***************************************************************************** // Deposit the page offset 'imm12' into an add instruction //***************************************************************************** void PutArm64Rel12(UINT32 * pCode, INT32 imm12); //***************************************************************************** // Returns whether the offset fits into bl instruction //***************************************************************************** inline bool FitsInThumb2BlRel24(INT32 imm24) { return ((imm24 << 7) >> 7) == imm24; } //***************************************************************************** // Returns whether the offset fits into an Arm64 b or bl instruction //***************************************************************************** inline bool FitsInRel28(INT32 val32) { return (val32 >= -0x08000000) && (val32 < 0x08000000); } //***************************************************************************** // Returns whether the offset fits into an Arm64 adrp instruction //***************************************************************************** inline bool FitsInRel21(INT32 val32) { return (val32 >= 0) && (val32 <= 0x001FFFFF); } //***************************************************************************** // Returns whether the offset fits into an Arm64 add instruction //***************************************************************************** inline bool FitsInRel12(INT32 val32) { return (val32 >= 0) && (val32 <= 0x00000FFF); } //***************************************************************************** // Returns whether the offset fits into an Arm64 b or bl instruction //***************************************************************************** inline bool FitsInRel28(INT64 val64) { return (val64 >= -0x08000000LL) && (val64 < 0x08000000LL); } // // TEB access can be dangerous when using fibers because a fiber may // run on multiple threads. If the TEB pointer is retrieved and saved // and then a fiber is moved to a different thread, when it accesses // the saved TEB pointer, it will be looking at the TEB state for a // different fiber. // // These accessors serve the purpose of retrieving information from the // TEB in a manner that ensures that the current fiber will not switch // threads while the access is occurring. // class ClrTeb { public: #if defined(HOST_UNIX) // returns pointer that uniquely identifies the fiber static void* GetFiberPtrId() { LIMITED_METHOD_CONTRACT; // not fiber for HOST_UNIX - use the regular thread ID return (void *)(size_t)GetCurrentThreadId(); } static void* GetStackBase() { return PAL_GetStackBase(); } static void* GetStackLimit() { return PAL_GetStackLimit(); } #else // HOST_UNIX // returns pointer that uniquely identifies the fiber static void* GetFiberPtrId() { LIMITED_METHOD_CONTRACT; // stackbase is the unique fiber identifier return NtCurrentTeb()->NtTib.StackBase; } static void* GetStackBase() { LIMITED_METHOD_CONTRACT; return NtCurrentTeb()->NtTib.StackBase; } static void* GetStackLimit() { LIMITED_METHOD_CONTRACT; return NtCurrentTeb()->NtTib.StackLimit; } static void* GetOleReservedPtr() { LIMITED_METHOD_CONTRACT; return NtCurrentTeb()->ReservedForOle; } #endif // HOST_UNIX }; #if !defined(DACCESS_COMPILE) extern thread_local size_t t_ThreadType; // check if current thread is a GC thread (concurrent or server) inline BOOL IsGCSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; STATIC_CONTRACT_CANNOT_TAKE_LOCK; return !!(t_ThreadType & ThreadType_GC); } // check if current thread is a Gate thread inline BOOL IsGateSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_Gate); } // check if current thread is a debugger helper thread inline BOOL IsDbgHelperSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_DbgHelper); } // check if current thread is a debugger helper thread inline BOOL IsETWRundownSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_ETWRundownThread); } // check if current thread is a generic instantiation lookup compare thread inline BOOL IsGenericInstantiationLookupCompareThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_GenericInstantiationCompare); } // check if current thread is a thread which is performing shutdown inline BOOL IsShutdownSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_Shutdown); } inline BOOL IsThreadPoolIOCompletionSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_Threadpool_IOCompletion); } inline BOOL IsThreadPoolWorkerSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_Threadpool_Worker); } inline BOOL IsWaitSpecialThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_Wait); } // check if current thread is a thread which is performing shutdown inline BOOL IsSuspendEEThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_DynamicSuspendEE); } inline BOOL IsFinalizerThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_Finalizer); } inline BOOL IsShutdownHelperThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_ShutdownHelper); } inline BOOL IsProfilerAttachThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; return !!(t_ThreadType & ThreadType_ProfAPI_Attach); } // set special type for current thread void ClrFlsSetThreadType(TlsThreadTypeFlag flag); void ClrFlsClearThreadType(TlsThreadTypeFlag flag); #endif //!DACCESS_COMPILE HRESULT SetThreadName(HANDLE hThread, PCWSTR lpThreadDescription); inline BOOL IsGCThread () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; STATIC_CONTRACT_SUPPORTS_DAC; #if !defined(DACCESS_COMPILE) return IsGCSpecialThread () || IsSuspendEEThread (); #else return FALSE; #endif } class ClrFlsThreadTypeSwitch { public: ClrFlsThreadTypeSwitch (TlsThreadTypeFlag flag) { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; #ifndef DACCESS_COMPILE m_flag = flag; m_fPreviouslySet = (t_ThreadType & flag); // In debug builds, remember the full group of flags that were set at the time // the constructor was called. This will be used in ASSERTs in the destructor INDEBUG(m_nPreviousFlagGroup = t_ThreadType); if (!m_fPreviouslySet) { ClrFlsSetThreadType(flag); } #endif // DACCESS_COMPILE } ~ClrFlsThreadTypeSwitch () { STATIC_CONTRACT_NOTHROW; STATIC_CONTRACT_GC_NOTRIGGER; STATIC_CONTRACT_MODE_ANY; #ifndef DACCESS_COMPILE // This holder should only be used to set (and thus restore) ONE thread type flag // at a time. If more than that one flag was modified since this holder was // instantiated, then this holder still restores only the flag it knows about. To // prevent confusion, assert if some other flag was modified, so the user doesn't // expect the holder to restore the entire original set of flags. // // The expression below says that the only difference between the previous flag // group and the current flag group should be m_flag (or no difference at all, if // m_flag's state didn't actually change). _ASSERTE(((m_nPreviousFlagGroup ^ t_ThreadType) | (size_t) m_flag) == (size_t) m_flag); if (m_fPreviouslySet) { ClrFlsSetThreadType(m_flag); } else { ClrFlsClearThreadType(m_flag); } #endif // DACCESS_COMPILE } private: TlsThreadTypeFlag m_flag; BOOL m_fPreviouslySet; INDEBUG(size_t m_nPreviousFlagGroup); }; //********************************************************************************* #include "contract.inl" namespace util { // compare adapters // template < typename T > struct less { bool operator()( T const & first, T const & second ) const { return first < second; } }; template < typename T > struct greater { bool operator()( T const & first, T const & second ) const { return first > second; } }; // sort adapters // template< typename Iter, typename Pred > void sort( Iter begin, Iter end, Pred pred ); template< typename T, typename Pred > void sort( T * begin, T * end, Pred pred ) { struct sort_helper : CQuickSort< T > { sort_helper( T * begin, T * end, Pred pred ) : CQuickSort< T >( begin, end - begin ) , m_pred( pred ) {} virtual int Compare( T * first, T * second ) { return m_pred( *first, *second ) ? -1 : ( m_pred( *second, *first ) ? 1 : 0 ); } Pred m_pred; }; sort_helper sort_obj( begin, end, pred ); sort_obj.Sort(); } template < typename Iter > void sort( Iter begin, Iter end ); template < typename T > void sort( T * begin, T * end ) { util::sort( begin, end, util::less< T >() ); } // binary search adapters // template < typename Iter, typename T, typename Pred > Iter lower_bound( Iter begin, Iter end, T const & val, Pred pred ); template < typename T, typename Pred > T * lower_bound( T * begin, T * end, T const & val, Pred pred ) { for (; begin != end; ) { T * mid = begin + ( end - begin ) / 2; if ( pred( *mid, val ) ) begin = ++mid; else end = mid; } return begin; } template < typename Iter, typename T > Iter lower_bound( Iter begin, Iter end, T const & val ); template < typename T > T * lower_bound( T * begin, T * end, T const & val ) { return util::lower_bound( begin, end, val, util::less< T >() ); } } /* ------------------------------------------------------------------------ * * Overloaded operators for the executable heap * ------------------------------------------------------------------------ */ #ifdef HOST_WINDOWS struct CExecutable { int x; }; extern const CExecutable executable; void * __cdecl operator new(size_t n, const CExecutable&); void * __cdecl operator new[](size_t n, const CExecutable&); void * __cdecl operator new(size_t n, const CExecutable&, const NoThrow&); void * __cdecl operator new[](size_t n, const CExecutable&, const NoThrow&); // // Executable heap delete to match the executable heap new above. // template void DeleteExecutable(T *p) { if (p != NULL) { p->T::~T(); HeapFree(ClrGetProcessExecutableHeap(), 0, p); } } #endif // HOST_WINDOWS INDEBUG(BOOL DbgIsExecutable(LPVOID lpMem, SIZE_T length);) BOOL ThreadWillCreateGuardPage(SIZE_T sizeReservedStack, SIZE_T sizeCommittedStack); #ifdef FEATURE_COMINTEROP FORCEINLINE void HolderSysFreeString(BSTR str) { CONTRACT_VIOLATION(ThrowsViolation); SysFreeString(str); } typedef Wrapper BSTRHolder; #endif BOOL IsIPInModule(PTR_VOID pModuleBaseAddress, PCODE ip); namespace UtilCode { // These are type-safe versions of Interlocked[Compare]Exchange // They avoid invoking struct cast operations via reinterpreting // the struct's address as a LONG* or LONGLONG* and dereferencing it. // // If we had a global ::operator & (unary), we would love to use that // to ensure we were not also accidentally getting a structs's provided // operator &. TODO: probe with a static_assert? template struct InterlockedCompareExchangeHelper; template struct InterlockedCompareExchangeHelper { static inline T InterlockedExchange( T volatile * target, T value) { static_assert_no_msg(sizeof(T) == sizeof(LONG)); LONG res = ::InterlockedExchange( reinterpret_cast(target), *reinterpret_cast(/*::operator*/&(value))); return *reinterpret_cast(&res); } static inline T InterlockedCompareExchange( T volatile * destination, T exchange, T comparand) { static_assert_no_msg(sizeof(T) == sizeof(LONG)); LONG res = ::InterlockedCompareExchange( reinterpret_cast(destination), *reinterpret_cast(/*::operator*/&(exchange)), *reinterpret_cast(/*::operator*/&(comparand))); return *reinterpret_cast(&res); } }; template struct InterlockedCompareExchangeHelper { static inline T InterlockedExchange( T volatile * target, T value) { static_assert_no_msg(sizeof(T) == sizeof(LONGLONG)); LONGLONG res = ::InterlockedExchange64( reinterpret_cast(target), *reinterpret_cast(/*::operator*/&(value))); return *reinterpret_cast(&res); } static inline T InterlockedCompareExchange( T volatile * destination, T exchange, T comparand) { static_assert_no_msg(sizeof(T) == sizeof(LONGLONG)); LONGLONG res = ::InterlockedCompareExchange64( reinterpret_cast(destination), *reinterpret_cast(/*::operator*/&(exchange)), *reinterpret_cast(/*::operator*/&(comparand))); return *reinterpret_cast(&res); } }; } template inline T InterlockedExchangeT( T volatile * target, T value) { return ::UtilCode::InterlockedCompareExchangeHelper::InterlockedExchange( target, value); } template inline T InterlockedCompareExchangeT( T volatile * destination, T exchange, T comparand) { return ::UtilCode::InterlockedCompareExchangeHelper::InterlockedCompareExchange( destination, exchange, comparand); } // Pointer variants for Interlocked[Compare]ExchangePointer // If the underlying type is a const type, we have to remove its constness // since Interlocked[Compare]ExchangePointer doesn't take const void * arguments. template inline T* InterlockedExchangeT( T* volatile * target, T* value) { //STATIC_ASSERT(value == 0); typedef typename std::remove_const::type * non_const_ptr_t; return reinterpret_cast(InterlockedExchangePointer( reinterpret_cast(const_cast(target)), reinterpret_cast(const_cast(value)))); } template inline T* InterlockedCompareExchangeT( T* volatile * destination, T* exchange, T* comparand) { //STATIC_ASSERT(exchange == 0); typedef typename std::remove_const::type * non_const_ptr_t; return reinterpret_cast(InterlockedCompareExchangePointer( reinterpret_cast(const_cast(destination)), reinterpret_cast(const_cast(exchange)), reinterpret_cast(const_cast(comparand)))); } // NULL pointer variants of the above to avoid having to cast NULL // to the appropriate pointer type. template inline T* InterlockedExchangeT( T* volatile * target, std::nullptr_t value) // When nullptr is provided as argument. { //STATIC_ASSERT(value == 0); return InterlockedExchangeT(target, static_cast(value)); } template inline T* InterlockedCompareExchangeT( T* volatile * destination, std::nullptr_t exchange, // When nullptr is provided as argument. T* comparand) { //STATIC_ASSERT(exchange == 0); return InterlockedCompareExchangeT(destination, static_cast(exchange), comparand); } template inline T* InterlockedCompareExchangeT( T* volatile * destination, T* exchange, std::nullptr_t comparand) // When nullptr is provided as argument. { //STATIC_ASSERT(comparand == 0); return InterlockedCompareExchangeT(destination, exchange, static_cast(comparand)); } // NULL pointer variants of the above to avoid having to cast NULL // to the appropriate pointer type. template inline T* InterlockedExchangeT( T* volatile * target, int value) // When NULL is provided as argument. { //STATIC_ASSERT(value == 0); return InterlockedExchangeT(target, nullptr); } template inline T* InterlockedCompareExchangeT( T* volatile * destination, int exchange, // When NULL is provided as argument. T* comparand) { //STATIC_ASSERT(exchange == 0); return InterlockedCompareExchangeT(destination, nullptr, comparand); } template inline T* InterlockedCompareExchangeT( T* volatile * destination, T* exchange, int comparand) // When NULL is provided as argument. { //STATIC_ASSERT(comparand == 0); return InterlockedCompareExchangeT(destination, exchange, nullptr); } #undef InterlockedExchangePointer #define InterlockedExchangePointer Use_InterlockedExchangeT #undef InterlockedCompareExchangePointer #define InterlockedCompareExchangePointer Use_InterlockedCompareExchangeT // Returns the directory for clr module. So, if path was for "C:\Dir1\Dir2\Filename.DLL", // then this would return "C:\Dir1\Dir2\" (note the trailing backslash). HRESULT GetClrModuleDirectory(SString& wszPath); namespace Clr { namespace Util { #ifdef HOST_WINDOWS namespace Com { HRESULT FindInprocServer32UsingCLSID(REFCLSID rclsid, SString & ssInprocServer32Name); } #endif // HOST_WINDOWS }} inline DWORD GetLoadWithAlteredSearchPathFlag() { LIMITED_METHOD_CONTRACT; #ifdef LOAD_WITH_ALTERED_SEARCH_PATH return LOAD_WITH_ALTERED_SEARCH_PATH; #else return 0; #endif } // clr::SafeAddRef and clr::SafeRelease helpers. namespace clr { //================================================================================================================= template static inline typename std::enable_if< std::is_pointer::value, ItfT >::type SafeAddRef(ItfT pItf) { STATIC_CONTRACT_LIMITED_METHOD; if (pItf != nullptr) { pItf->AddRef(); } return pItf; } //================================================================================================================= template typename std::enable_if< std::is_pointer::value && std::is_reference::value, ULONG >::type SafeRelease(ItfT pItf) { STATIC_CONTRACT_LIMITED_METHOD; ULONG res = 0; if (pItf != nullptr) { res = pItf->Release(); pItf = nullptr; } return res; } //================================================================================================================= template typename std::enable_if< std::is_pointer::value && !std::is_reference::value, ULONG >::type SafeRelease(ItfT pItf) { STATIC_CONTRACT_LIMITED_METHOD; ULONG res = 0; if (pItf != nullptr) { res = pItf->Release(); } return res; } } // clr::SafeDelete namespace clr { //================================================================================================================= template static inline typename std::enable_if< std::is_pointer::value, PtrT >::type SafeDelete(PtrT & ptr) { STATIC_CONTRACT_LIMITED_METHOD; if (ptr != nullptr) { delete ptr; ptr = nullptr; } } } // ====================================================================================== // Spinning support (used by VM and by MetaData via file:..\Utilcode\UTSem.cpp) struct SpinConstants { DWORD dwInitialDuration; DWORD dwMaximumDuration; DWORD dwBackoffFactor; DWORD dwRepetitions; DWORD dwMonitorSpinCount; }; extern SpinConstants g_SpinConstants; #endif // __UtilCode_h__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/utsem.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* ---------------------------------------------------------------------------- ---------------------------------------------------------------------------- */ #ifndef __UTSEM_H__ #define __UTSEM_H__ // ------------------------------------------------------------- // INCLUDES // ------------------------------------------------------------- #include "utilcode.h" /* ---------------------------------------------------------------------------- @class UTSemReadWrite An instance of class UTSemReadWrite provides multi-read XOR single-write (a.k.a. shared vs. exclusive) lock capabilities, with protection against writer starvation. A thread MUST NOT call any of the Lock methods if it already holds a Lock. (Doing so may result in a deadlock.) ---------------------------------------------------------------------------- */ class UTSemReadWrite { public: UTSemReadWrite(); // Constructor ~UTSemReadWrite(); // Destructor HRESULT Init(); HRESULT LockRead(); // Lock the object for reading HRESULT LockWrite(); // Lock the object for writing void UnlockRead(); // Unlock the object for reading void UnlockWrite(); // Unlock the object for writing #ifdef _DEBUG BOOL Debug_IsLockedForRead(); BOOL Debug_IsLockedForWrite(); #endif //_DEBUG private: Volatile m_dwFlag; // internal state, see implementation HANDLE m_hReadWaiterSemaphore; // semaphore for awakening read waiters HANDLE m_hWriteWaiterEvent; // event for awakening write waiters }; // class UTSemReadWrite #endif // __UTSEM_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/volatile.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Volatile.h // // // Defines the Volatile type, which provides uniform volatile-ness on // Visual C++ and GNU C++. // // Visual C++ treats accesses to volatile variables as follows: no read or write // can be removed by the compiler, no global memory access can be moved backwards past // a volatile read, and no global memory access can be moved forward past a volatile // write. // // The GCC volatile semantic is straight out of the C standard: the compiler is not // allowed to remove accesses to volatile variables, and it is not allowed to reorder // volatile accesses relative to other volatile accesses. It is allowed to freely // reorder non-volatile accesses relative to volatile accesses. // // We have lots of code that assumes that ordering of non-volatile accesses will be // constrained relative to volatile accesses. For example, this pattern appears all // over the place: // // static volatile int lock = 0; // // while (InterlockedCompareExchange(&lock, 0, 1)) // { // //spin // } // // //read and write variables protected by the lock // // lock = 0; // // This depends on the reads and writes in the critical section not moving past the // final statement, which releases the lock. If this should happen, then you have an // unintended race. // // The solution is to ban the use of the "volatile" keyword, and instead define our // own type Volatile, which acts like a variable of type T except that accesses to // the variable are always given VC++'s volatile semantics. // // (NOTE: The code above is not intended to be an example of how a spinlock should be // implemented; it has many flaws, and should not be used. This code is intended only // to illustrate where we might get into trouble with GCC's volatile semantics.) // // @TODO: many of the variables marked volatile in the CLR do not actually need to be // volatile. For example, if a variable is just always passed to Interlocked functions // (such as a refcount variable), there is no need for it to be volatile. A future // cleanup task should be to examine each volatile variable and make them non-volatile // if possible. // // @TODO: link to a "Memory Models for CLR Devs" doc here (this doc does not yet exist). // #ifndef _VOLATILE_H_ #define _VOLATILE_H_ #include "staticcontract.h" // // This code is extremely compiler- and CPU-specific, and will need to be altered to // support new compilers and/or CPUs. Here we enforce that we can only compile using // VC++, or GCC on x86 or AMD64. // #if !defined(_MSC_VER) && !defined(__GNUC__) #error The Volatile type is currently only defined for Visual C++ and GNU C++ #endif #if defined(__GNUC__) && !defined(HOST_X86) && !defined(HOST_AMD64) && !defined(HOST_ARM) && !defined(HOST_ARM64) && !defined(HOST_LOONGARCH64) && !defined(HOST_RISCV64) && !defined(HOST_S390X) && !defined(HOST_POWERPC64) #error The Volatile type is currently only defined for GCC when targeting x86, AMD64, ARM, ARM64, LOONGARCH64, RISCV64, PPC64LE, or S390X CPUs #endif #if defined(__GNUC__) #if defined(HOST_ARMV6) // DMB ISH not valid on ARMv6 #define VOLATILE_MEMORY_BARRIER() asm volatile ("mcr p15, 0, r0, c7, c10, 5" : : : "memory") #elif defined(HOST_ARM) || defined(HOST_ARM64) // This is functionally equivalent to the MemoryBarrier() macro used on ARM on Windows. #define VOLATILE_MEMORY_BARRIER() asm volatile ("dmb ish" : : : "memory") #elif defined(HOST_LOONGARCH64) #define VOLATILE_MEMORY_BARRIER() asm volatile ("dbar 0 " : : : "memory") #elif defined(HOST_RISCV64) #define VOLATILE_MEMORY_BARRIER() asm volatile ("fence rw,rw" : : : "memory") #else // // For GCC, we prevent reordering by the compiler by inserting the following after a volatile // load (to prevent subsequent operations from moving before the read), and before a volatile // write (to prevent prior operations from moving past the write). We don't need to do anything // special to prevent CPU reorderings, because the x86 and AMD64 architectures are already // sufficiently constrained for our purposes. If we ever need to run on weaker CPU architectures // (such as PowerPC), then we will need to do more work. // // Please do not use this macro outside of this file. It is subject to change or removal without // notice. // #define VOLATILE_MEMORY_BARRIER() asm volatile ("" : : : "memory") #endif // HOST_ARM || HOST_ARM64 #elif (defined(HOST_ARM) || defined(HOST_ARM64)) && _ISO_VOLATILE // ARM & ARM64 have a very weak memory model and very few tools to control that model. We're forced to perform a full // memory barrier to preserve the volatile semantics. Technically this is only necessary on MP systems but we // currently don't have a cheap way to determine the number of CPUs from this header file. Revisit this if it // turns out to be a performance issue for the uni-proc case. #define VOLATILE_MEMORY_BARRIER() MemoryBarrier() #else // // On VC++, reorderings at the compiler and machine level are prevented by the use of the // "volatile" keyword in VolatileLoad and VolatileStore. This should work on any CPU architecture // targeted by VC++ with /iso_volatile-. // #define VOLATILE_MEMORY_BARRIER() #endif // __GNUC__ template struct RemoveVolatile { typedef T type; }; template struct RemoveVolatile { typedef T type; }; // // VolatileLoad loads a T from a pointer to T. It is guaranteed that this load will not be optimized // away by the compiler, and that any operation that occurs after this load, in program order, will // not be moved before this load. In general it is not guaranteed that the load will be atomic, though // this is the case for most aligned scalar data types. If you need atomic loads or stores, you need // to consult the compiler and CPU manuals to find which circumstances allow atomicity. // // Starting at version 3.8, clang errors out on initializing of type int * to volatile int *. To fix this, we add two templates to cast away volatility // Helper structures for casting away volatileness #if defined(HOST_ARM64) && defined(_MSC_VER) #include #endif template inline T VolatileLoad(T const * pt) { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #ifndef DACCESS_COMPILE #if defined(HOST_ARM64) && defined(__GNUC__) T val; static const unsigned lockFreeAtomicSizeMask = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8); if((1 << sizeof(T)) & lockFreeAtomicSizeMask) { __atomic_load((T const *)pt, const_cast::type *>(&val), __ATOMIC_ACQUIRE); } else { val = *(T volatile const *)pt; asm volatile ("dmb ishld" : : : "memory"); } #elif defined(HOST_ARM64) && defined(_MSC_VER) // silence warnings on casts in branches that are not taken. #pragma warning(push) #pragma warning(disable : 4311) #pragma warning(disable : 4312) T val; T* pv = &val; switch (sizeof(T)) { case 1: *(unsigned __int8* )pv = __ldar8 ((unsigned __int8 volatile*)pt); break; case 2: *(unsigned __int16*)pv = __ldar16((unsigned __int16 volatile*)pt); break; case 4: *(unsigned __int32*)pv = __ldar32((unsigned __int32 volatile*)pt); break; case 8: *(unsigned __int64*)pv = __ldar64((unsigned __int64 volatile*)pt); break; default: val = *(T volatile const*)pt; __dmb(_ARM64_BARRIER_ISHLD); } #pragma warning(pop) #else T val = *(T volatile const *)pt; VOLATILE_MEMORY_BARRIER(); #endif #else T val = *pt; #endif return val; } template inline T VolatileLoadWithoutBarrier(T const * pt) { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #ifndef DACCESS_COMPILE T val = *(T volatile const *)pt; #else T val = *pt; #endif return val; } template class Volatile; template inline T VolatileLoad(Volatile const * pt) { STATIC_CONTRACT_SUPPORTS_DAC; return pt->Load(); } // // VolatileStore stores a T into the target of a pointer to T. It is guaranteed that this store will // not be optimized away by the compiler, and that any operation that occurs before this store, in program // order, will not be moved after this store. In general, it is not guaranteed that the store will be // atomic, though this is the case for most aligned scalar data types. If you need atomic loads or stores, // you need to consult the compiler and CPU manuals to find which circumstances allow atomicity. // template inline void VolatileStore(T* pt, T val) { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #ifndef DACCESS_COMPILE #if defined(HOST_ARM64) && defined(__GNUC__) static const unsigned lockFreeAtomicSizeMask = (1 << 1) | (1 << 2) | (1 << 4) | (1 << 8); if((1 << sizeof(T)) & lockFreeAtomicSizeMask) { __atomic_store((T volatile *)pt, &val, __ATOMIC_RELEASE); } else { VOLATILE_MEMORY_BARRIER(); *(T volatile *)pt = val; } #elif defined(HOST_ARM64) && defined(_MSC_VER) // silence warnings on casts in branches that are not taken. #pragma warning(push) #pragma warning(disable : 4311) #pragma warning(disable : 4312) T* pv = &val; switch (sizeof(T)) { case 1: __stlr8 ((unsigned __int8 volatile*)pt, *(unsigned __int8* )pv); break; case 2: __stlr16((unsigned __int16 volatile*)pt, *(unsigned __int16*)pv); break; case 4: __stlr32((unsigned __int32 volatile*)pt, *(unsigned __int32*)pv); break; case 8: __stlr64((unsigned __int64 volatile*)pt, *(unsigned __int64*)pv); break; default: __dmb(_ARM64_BARRIER_ISH); *(T volatile *)pt = val; } #pragma warning(pop) #else VOLATILE_MEMORY_BARRIER(); *(T volatile *)pt = val; #endif #else *pt = val; #endif } template inline void VolatileStoreWithoutBarrier(T* pt, T val) { STATIC_CONTRACT_SUPPORTS_DAC_HOST_ONLY; #ifndef DACCESS_COMPILE *(T volatile *)pt = val; #else *pt = val; #endif } // // Memory ordering barrier that waits for loads in progress to complete. // Any effects of loads or stores that appear after, in program order, will "happen after" relative to this. // Other operations such as computation or instruction prefetch are not affected. // // Architectural mapping: // arm64 : dmb ishld // arm : dmb ish // x86/64 : compiler fence inline void VolatileLoadBarrier() { #if defined(HOST_ARM64) && defined(__GNUC__) asm volatile ("dmb ishld" : : : "memory"); #elif defined(HOST_ARM64) && defined(_MSC_VER) __dmb(_ARM64_BARRIER_ISHLD); #else VOLATILE_MEMORY_BARRIER(); #endif } // // Volatile implements accesses with our volatile semantics over a variable of type T. // Wherever you would have used a "volatile Foo" or, equivalently, "Foo volatile", use Volatile // instead. If Foo is a pointer type, use VolatilePtr. // // Note that there are still some things that don't work with a Volatile, // that would have worked with a "volatile T". For example, you can't cast a Volatile to a float. // You must instead cast to an int, then to a float. Or you can call Load on the Volatile, and // cast the result to a float. In general, calling Load or Store explicitly will work around // any problems that can't be solved by operator overloading. // // @TODO: it's not clear that we actually *want* any operator overloading here. It's in here primarily // to ease the task of converting all of the old uses of the volatile keyword, but in the long // run it's probably better if users of this class are forced to call Load() and Store() explicitly. // This would make it much more clear where the memory barriers are, and which operations are actually // being performed, but it will have to wait for another cleanup effort. // template class Volatile { // To enable the DAC table to correctly handle volatile DAC-ized statics while also being computed at compile time, we need to // give the dac table type access to the internal field directly to take the address of it. friend struct _DacGlobals; private: // // The data which we are treating as volatile // T m_val; public: // // Default constructor. // inline Volatile() = default; // // Allow initialization of Volatile from a T // inline Volatile(const T& val) { STATIC_CONTRACT_SUPPORTS_DAC; ((volatile T &)m_val) = val; } // // Copy constructor // inline Volatile(const Volatile& other) { STATIC_CONTRACT_SUPPORTS_DAC; ((volatile T &)m_val) = other.Load(); } // // Loads the value of the volatile variable. See code:VolatileLoad for the semantics of this operation. // inline T Load() const { STATIC_CONTRACT_SUPPORTS_DAC; return VolatileLoad(&m_val); } // // Loads the value of the volatile variable atomically without erecting the memory barrier. // inline T LoadWithoutBarrier() const { STATIC_CONTRACT_SUPPORTS_DAC; return ((volatile T &)m_val); } // // Stores a new value to the volatile variable. See code:VolatileStore for the semantics of this // operation. // inline void Store(const T& val) { STATIC_CONTRACT_SUPPORTS_DAC; VolatileStore(&m_val, val); } // // Stores a new value to the volatile variable atomically without erecting the memory barrier. // inline void StoreWithoutBarrier(const T& val) const { STATIC_CONTRACT_SUPPORTS_DAC; ((volatile T &)m_val) = val; } // // Gets a pointer to the volatile variable. This is dangerous, as it permits the variable to be // accessed without using Load and Store, but it is necessary for passing Volatile to APIs like // InterlockedIncrement. // inline volatile T* GetPointer() { return (volatile T*)&m_val; } // // Gets the raw value of the variable. This is dangerous, as it permits the variable to be // accessed without using Load and Store // inline T& RawValue() { return m_val; } // // Allow casts from Volatile to T. Note that this allows implicit casts, so you can // pass a Volatile directly to a method that expects a T. // inline operator T() const { STATIC_CONTRACT_SUPPORTS_DAC; return this->Load(); } // // Assignment from T // inline Volatile& operator=(T val) {Store(val); return *this;} // // Get the address of the volatile variable. This is dangerous, as it allows the value of the // volatile variable to be accessed directly, without going through Load and Store, but it is // necessary for passing Volatile to APIs like InterlockedIncrement. Note that we are returning // a pointer to a volatile T here, so we cannot accidentally pass this pointer to an API that // expects a normal pointer. // inline T volatile * operator&() {return this->GetPointer();} inline T volatile const * operator&() const {return this->GetPointer();} // // Comparison operators // template inline bool operator==(const TOther& other) const {return this->Load() == other;} template inline bool operator!=(const TOther& other) const {return this->Load() != other;} // // Miscellaneous operators. Add more as necessary. // inline Volatile& operator+=(T val) {Store(this->Load() + val); return *this;} inline Volatile& operator-=(T val) {Store(this->Load() - val); return *this;} inline Volatile& operator|=(T val) {Store(this->Load() | val); return *this;} inline Volatile& operator&=(T val) {Store(this->Load() & val); return *this;} inline bool operator!() const { STATIC_CONTRACT_SUPPORTS_DAC; return !this->Load();} // // Prefix increment // inline Volatile& operator++() {this->Store(this->Load()+1); return *this;} // // Postfix increment // inline T operator++(int) {T val = this->Load(); this->Store(val+1); return val;} // // Prefix decrement // inline Volatile& operator--() {this->Store(this->Load()-1); return *this;} // // Postfix decrement // inline T operator--(int) {T val = this->Load(); this->Store(val-1); return val;} }; // // A VolatilePtr builds on Volatile by adding operators appropriate to pointers. // Wherever you would have used "Foo * volatile", use "VolatilePtr" instead. // // VolatilePtr also allows the substution of other types for the underlying pointer. This // allows you to wrap a VolatilePtr around a custom type that looks like a pointer. For example, // if what you want is a "volatile DPTR", use "VolatilePtr>". // template class VolatilePtr : public Volatile

{ public: // // Default constructor. Results in an uninitialized pointer! // inline VolatilePtr() { STATIC_CONTRACT_SUPPORTS_DAC; } // // Allow assignment from the pointer type. // inline VolatilePtr(P val) : Volatile

(val) { STATIC_CONTRACT_SUPPORTS_DAC; } // // Copy constructor // inline VolatilePtr(const VolatilePtr& other) : Volatile

(other) { STATIC_CONTRACT_SUPPORTS_DAC; } // // Cast to the pointer type // inline operator P() const { STATIC_CONTRACT_SUPPORTS_DAC; return (P)this->Load(); } // // Member access // inline P operator->() const { STATIC_CONTRACT_SUPPORTS_DAC; return (P)this->Load(); } // // Dereference the pointer // inline T& operator*() const { STATIC_CONTRACT_SUPPORTS_DAC; return *(P)this->Load(); } // // Access the pointer as an array // template inline T& operator[](TIndex index) { STATIC_CONTRACT_SUPPORTS_DAC; return ((P)this->Load())[index]; } }; // // From here on out, we ban the use of the "volatile" keyword. If you found this while trying to define // a volatile variable, go to the top of this file and start reading. // #ifdef volatile #undef volatile #endif // ***** Temporarily removing this to unblock integration with new VC++ bits //#define volatile (DoNotUseVolatileKeyword) volatile // The substitution for volatile above is defined in such a way that we can still explicitly access the // volatile keyword without error using the macros below. Use with care. //#define REMOVE_DONOTUSE_ERROR(x) //#define RAW_KEYWORD(x) REMOVE_DONOTUSE_ERROR x #define RAW_KEYWORD(x) x #ifdef DACCESS_COMPILE // No need to use volatile in DAC builds - DAC is single-threaded and the target // process is suspended. #define VOLATILE(T) T #else // Disable use of Volatile for GC/HandleTable code except on platforms where it's absolutely necessary. #if defined(_MSC_VER) && !defined(HOST_ARM) && !defined(HOST_ARM64) #define VOLATILE(T) T RAW_KEYWORD(volatile) #else #define VOLATILE(T) Volatile #endif #endif // DACCESS_COMPILE // VolatilePtr-specific clr::SafeAddRef and clr::SafeRelease namespace clr { template < typename ItfT, typename PtrT > inline #ifdef __checkReturn // Volatile.h is used in corunix headers, which don't define/nullify SAL. __checkReturn #endif VolatilePtr& SafeAddRef(VolatilePtr& pItf) { STATIC_CONTRACT_LIMITED_METHOD; SafeAddRef(pItf.Load()); return pItf; } template < typename ItfT, typename PtrT > inline ULONG SafeRelease(VolatilePtr& pItf) { STATIC_CONTRACT_LIMITED_METHOD; return SafeRelease(pItf.Load()); } } #endif //_VOLATILE_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/vptr_list.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // Any class with a vtable that needs to be instantiated // during debugging data access must be listed here. VPTR_CLASS(EEJitManager) #ifdef FEATURE_READYTORUN VPTR_CLASS(ReadyToRunJitManager) #endif VPTR_CLASS(EECodeManager) VPTR_CLASS(RangeList) VPTR_CLASS(LockedRangeList) #ifdef EnC_SUPPORTED VPTR_CLASS(EditAndContinueModule) #endif VPTR_CLASS(Module) VPTR_CLASS(ReflectionModule) VPTR_CLASS(AppDomain) VPTR_CLASS(SystemDomain) VPTR_CLASS(PrecodeStubManager) VPTR_CLASS(StubLinkStubManager) VPTR_CLASS(ThePreStubManager) VPTR_CLASS(ThunkHeapStubManager) VPTR_CLASS(VirtualCallStubManager) VPTR_CLASS(VirtualCallStubManagerManager) VPTR_CLASS(JumpStubStubManager) VPTR_CLASS(RangeSectionStubManager) VPTR_CLASS(ILStubManager) VPTR_CLASS(InteropDispatchStubManager) VPTR_CLASS(DelegateInvokeStubManager) #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) VPTR_CLASS(TailCallStubManager) #endif VPTR_CLASS(CallCountingStubManager) VPTR_CLASS(PEImageLayout) VPTR_CLASS(ConvertedImageLayout) VPTR_CLASS(LoadedImageLayout) VPTR_CLASS(FlatImageLayout) #ifdef FEATURE_COMINTEROP VPTR_CLASS(ComMethodFrame) VPTR_CLASS(ComPlusMethodFrame) VPTR_CLASS(ComPrestubMethodFrame) #endif // FEATURE_COMINTEROP #ifdef FEATURE_INTERPRETER VPTR_CLASS(InterpreterFrame) #endif // FEATURE_INTERPRETER VPTR_CLASS(DebuggerClassInitMarkFrame) VPTR_CLASS(DebuggerSecurityCodeMarkFrame) VPTR_CLASS(DebuggerExitFrame) VPTR_CLASS(DebuggerU2MCatchHandlerFrame) VPTR_CLASS(FaultingExceptionFrame) VPTR_CLASS(FuncEvalFrame) VPTR_CLASS(HelperMethodFrame) VPTR_CLASS(HelperMethodFrame_1OBJ) VPTR_CLASS(HelperMethodFrame_2OBJ) VPTR_CLASS(HelperMethodFrame_3OBJ) VPTR_CLASS(HelperMethodFrame_PROTECTOBJ) #ifdef FEATURE_HIJACK VPTR_CLASS(HijackFrame) #endif VPTR_CLASS(InlinedCallFrame) VPTR_CLASS(MulticastFrame) VPTR_CLASS(PInvokeCalliFrame) VPTR_CLASS(PrestubMethodFrame) VPTR_CLASS(ProtectByRefsFrame) VPTR_CLASS(ProtectValueClassFrame) #ifdef FEATURE_HIJACK VPTR_CLASS(ResumableFrame) VPTR_CLASS(RedirectedThreadFrame) #endif VPTR_CLASS(StubDispatchFrame) VPTR_CLASS(CallCountingHelperFrame) VPTR_CLASS(ExternalMethodFrame) #ifdef FEATURE_READYTORUN VPTR_CLASS(DynamicHelperFrame) #endif #if defined(TARGET_X86) && !defined(UNIX_X86_ABI) VPTR_CLASS(TailCallFrame) #endif VPTR_CLASS(ExceptionFilterFrame) #ifdef _DEBUG VPTR_CLASS(AssumeByrefFromJITStack) #endif #ifdef DEBUGGING_SUPPORTED VPTR_CLASS(Debugger) VPTR_CLASS(EEDbgInterfaceImpl) #endif // DEBUGGING_SUPPORTED VPTR_CLASS(DebuggerController) VPTR_CLASS(DebuggerMethodInfoTable) VPTR_CLASS(DebuggerPatchTable) VPTR_CLASS(LoaderCodeHeap) VPTR_CLASS(HostCodeHeap) VPTR_CLASS(GlobalLoaderAllocator) VPTR_CLASS(AssemblyLoaderAllocator) ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/win64unwind.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef _WIN64UNWIND_H_ #define _WIN64UNWIND_H_ // // Define AMD64 exception handling structures and function prototypes. // // Define unwind operation codes. // typedef enum _UNWIND_OP_CODES { UWOP_PUSH_NONVOL = 0, UWOP_ALLOC_LARGE, UWOP_ALLOC_SMALL, UWOP_SET_FPREG, UWOP_SAVE_NONVOL, UWOP_SAVE_NONVOL_FAR, UWOP_EPILOG, UWOP_SPARE_CODE, UWOP_SAVE_XMM128, UWOP_SAVE_XMM128_FAR, UWOP_PUSH_MACHFRAME, #ifdef TARGET_UNIX // UWOP_SET_FPREG_LARGE is a CLR Unix-only extension to the Windows AMD64 unwind codes. // It is not part of the standard Windows AMD64 unwind codes specification. // UWOP_SET_FPREG allows for a maximum of a 240 byte offset between RSP and the // frame pointer, when the frame pointer is established. UWOP_SET_FPREG_LARGE // has a 32-bit range scaled by 16. When UWOP_SET_FPREG_LARGE is used, // UNWIND_INFO.FrameRegister must be set to the frame pointer register, and // UNWIND_INFO.FrameOffset must be set to 15 (its maximum value). UWOP_SET_FPREG_LARGE // is followed by two UNWIND_CODEs that are combined to form a 32-bit offset (the same // as UWOP_SAVE_NONVOL_FAR). This offset is then scaled by 16. The result must be less // than 2^32 (that is, the top 4 bits of the unscaled 32-bit number must be zero). This // result is used as the frame pointer register offset from RSP at the time the frame pointer // is established. Either UWOP_SET_FPREG or UWOP_SET_FPREG_LARGE can be used, but not both. UWOP_SET_FPREG_LARGE, #endif // TARGET_UNIX } UNWIND_OP_CODES, *PUNWIND_OP_CODES; static const UCHAR UnwindOpExtraSlotTable[] = { 0, // UWOP_PUSH_NONVOL 1, // UWOP_ALLOC_LARGE (or 3, special cased in lookup code) 0, // UWOP_ALLOC_SMALL 0, // UWOP_SET_FPREG 1, // UWOP_SAVE_NONVOL 2, // UWOP_SAVE_NONVOL_FAR 1, // UWOP_EPILOG 2, // UWOP_SPARE_CODE // previously 64-bit UWOP_SAVE_XMM_FAR 1, // UWOP_SAVE_XMM128 2, // UWOP_SAVE_XMM128_FAR 0, // UWOP_PUSH_MACHFRAME #ifdef TARGET_UNIX 2, // UWOP_SET_FPREG_LARGE #endif // TARGET_UNIX }; // // Define unwind code structure. // typedef union _UNWIND_CODE { struct { UCHAR CodeOffset; UCHAR UnwindOp : 4; UCHAR OpInfo : 4; }; struct { UCHAR OffsetLow; UCHAR UnwindOp : 4; UCHAR OffsetHigh : 4; } EpilogueCode; USHORT FrameOffset; } UNWIND_CODE, *PUNWIND_CODE; // // Define unwind information flags. // #define UNW_FLAG_NHANDLER 0x0 #define UNW_FLAG_EHANDLER 0x1 #define UNW_FLAG_UHANDLER 0x2 #define UNW_FLAG_CHAININFO 0x4 #ifdef TARGET_X86 typedef struct _UNWIND_INFO { ULONG FunctionLength; } UNWIND_INFO, *PUNWIND_INFO; #else // TARGET_X86 typedef struct _UNWIND_INFO { UCHAR Version : 3; UCHAR Flags : 5; UCHAR SizeOfProlog; UCHAR CountOfUnwindCodes; UCHAR FrameRegister : 4; UCHAR FrameOffset : 4; UNWIND_CODE UnwindCode[1]; // // The unwind codes are followed by an optional DWORD aligned field that // contains the exception handler address or the address of chained unwind // information. If an exception handler address is specified, then it is // followed by the language specified exception handler data. // // union { // ULONG ExceptionHandler; // ULONG FunctionEntry; // }; // // ULONG ExceptionData[]; // } UNWIND_INFO, *PUNWIND_INFO; #endif // TARGET_X86 #endif // _WIN64UNWIND_H_ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/winwrap.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. //***************************************************************************** // WinWrap.h // // This file contains wrapper functions for Win32 API's that take strings. // // The Common Language Runtime internally uses UNICODE as the internal state // and string format. This file will undef the mapping macros so that one // cannot mistakingly call a method that isn't going to work. Instead, you // have to call the correct wrapper API. // //***************************************************************************** #ifndef __WIN_WRAP_H__ #define __WIN_WRAP_H__ //********** Macros. ********************************************************** #if !defined(WIN32_LEAN_AND_MEAN) #define WIN32_LEAN_AND_MEAN #endif // // WinCE uniformly uses cdecl calling convention on x86. __stdcall is defined as __cdecl in SDK. // STDCALL macro is meant to be used where we have hard dependency on __stdcall calling convention // - the unification with __cdecl does not apply to STDCALL. // #define STDCALL _stdcall //********** Includes. ******************************************************** #include #include #include #include #include "longfilepathwrappers.h" #if defined(_PREFAST_) || defined(SOURCE_FORMATTING) // // For PREFAST we don't want the C_ASSERT to be expanded since it always // involves the comparison of two constants which causes PREfast warning 326 // #undef C_ASSERT #define C_ASSERT(expr) #endif #include "palclr.h" #if !defined(__TODO_PORT_TO_WRAPPERS__) //***************************************************************************** // Undefine all of the windows wrappers so you can't use them. //***************************************************************************** // winbase.h #undef GetBinaryType #undef GetShortPathName #undef GetEnvironmentStrings #undef FreeEnvironmentStrings #undef FormatMessage #undef lstrcmp #undef lstrcmpi #undef lstrcpyn #undef lstrlen #undef CreateMutex #undef OpenMutex #undef CreateEvent #undef OpenEvent #undef CreateSemaphore #undef OpenSemaphore #undef CreateWaitableTimer #undef CreateFileMapping #undef LoadLibrary #undef LoadLibraryEx #undef GetModuleFileName #undef GetModuleHandle #undef GetModuleHandleEx #undef CreateProcess #undef GetCommandLine #undef GetEnvironmentVariable #undef SetEnvironmentVariable #undef ExpandEnvironmentStrings #undef OutputDebugString #undef FindResource #undef FindResourceEx #undef BeginUpdateResource #undef UpdateResource #undef EndUpdateResource #undef GetPrivateProfileInt #undef GetSystemDirectory #undef GetTempPath #undef GetTempFileName #undef GetFullPathName #undef CreateFile #undef GetFileAttributes #undef GetFileAttributesEx #undef FindFirstFileEx #undef FindFirstFile #undef FindNextFile #undef CopyFile #undef CopyFileEx #undef MoveFile #undef CreateHardLink #undef CreateNamedPipe #undef WaitNamedPipe #undef LookupPrivilegeValue #undef GetVersionEx // winuser.h #undef MAKEINTRESOURCE #undef GetUserObjectInformation #undef GetMessage #undef SendMessage #undef CharLower #undef MessageBox #undef GetClassName #undef LoadString #undef GetCalendarInfo #undef GetDateFormat #undef GetTimeFormat #undef LCMapString #endif // !defined(__TODO_PORT_TO_WRAPPERS__) // // NT supports the wide entry points. So we redefine the wrappers right back // to the *W entry points as macros. This way no client code needs a wrapper on NT. // // winbase.h #define WszFormatMessage FormatMessageW #define WszCreateMutex CreateMutexW #define WszOpenMutex OpenMutexW #define WszCreateEvent CreateEventW #define WszOpenEvent OpenEventW #define WszCreateWaitableTimer CreateWaitableTimerW #define WszCreateFileMapping CreateFileMappingW #define WszGetModuleHandle GetModuleHandleW #define WszGetModuleHandleEx GetModuleHandleExW #define WszGetCommandLine GetCommandLineW #define WszSetEnvironmentVariable SetEnvironmentVariableW #define WszExpandEnvironmentStrings ExpandEnvironmentStringsW #define WszOutputDebugString OutputDebugStringW #define WszFindResource FindResourceW #define WszFindResourceEx FindResourceExW #define WszBeginUpdateResource BeginUpdateResourceW #define WszUpdateResource UpdateResourceW #define WszEndUpdateResource EndUpdateResourceW #define WszGetPrivateProfileInt GetPrivateProfileIntW #define WszGetSystemDirectory GetSystemDirectoryW #define WszCreateNamedPipe CreateNamedPipeW #define WszWaitNamedPipe WaitNamedPipeW #define WszLookupPrivilegeValue LookupPrivilegeValueW // winuser.h #define WszMAKEINTRESOURCE MAKEINTRESOURCEW #define WszGetUserObjectInformation GetUserObjectInformationW #define WszGetMessage GetMessageW #define WszSendMessage SendMessageW #define WszCharLower CharLowerW #define WszGetClassName GetClassNameW #define WszLoadString LoadStringW #define WszRegOpenKeyEx RegOpenKeyExW #define WszRegOpenKey(hKey, wszSubKey, phkRes) RegOpenKeyExW(hKey, wszSubKey, 0, KEY_ALL_ACCESS, phkRes) #define WszRegQueryValue RegQueryValueW #define WszRegQueryValueEx RegQueryValueExW #define WszRegQueryInfoKey RegQueryInfoKeyW #define WszRegEnumValue RegEnumValueW #define WszRegEnumKeyEx RegEnumKeyExW #define WszGetCalendarInfo GetCalendarInfoW #define WszGetDateFormat GetDateFormatW #define WszGetTimeFormat GetTimeFormatW #define WszLCMapString LCMapStringW #define WszMultiByteToWideChar MultiByteToWideChar #define WszWideCharToMultiByte WideCharToMultiByte #define WszCreateSemaphore(_secattr, _count, _maxcount, _name) CreateSemaphoreExW((_secattr), (_count), (_maxcount), (_name), 0, MAXIMUM_ALLOWED | SYNCHRONIZE | SEMAPHORE_MODIFY_STATE) #undef GetFileVersionInfo #define GetFileVersionInfo(_filename, _handle, _len, _data) GetFileVersionInfoEx(0, (_filename), (_handle), (_len), (_data)) #undef GetFileVersionInfoSize #define GetFileVersionInfoSize(_filename, _handle) GetFileVersionInfoSizeEx(0, (_filename), (_handle)) #ifndef _T #define _T(str) W(str) #endif //File and Directory Functions which need special handling for LongFile Names //Note only the functions which are currently used are defined #define WszLoadLibrary LoadLibraryExWrapper #define WszLoadLibraryEx LoadLibraryExWrapper #define WszCreateFile CreateFileWrapper #define WszGetFileAttributes GetFileAttributesWrapper #define WszGetFileAttributesEx GetFileAttributesExWrapper //Can not use extended syntax #define WszGetFullPathName GetFullPathNameW //Long Files will not work on these till redstone #define WszGetTempPath GetTempPathWrapper //APIS which have a buffer as an out parameter #define WszGetEnvironmentVariable GetEnvironmentVariableWrapper #define WszSearchPath SearchPathWrapper #define WszGetModuleFileName GetModuleFileNameWrapper //***************************************************************************** // Prototypes for API's. //***************************************************************************** extern DWORD g_dwMaxDBCSCharByteSize; void EnsureCharSetInfoInitialized(); inline DWORD GetMaxDBCSCharByteSize() { // contract.h not visible here __annotation(W("WRAPPER ") W("GetMaxDBCSCharByteSize")); #ifndef HOST_UNIX EnsureCharSetInfoInitialized(); _ASSERTE(g_dwMaxDBCSCharByteSize != 0); return (g_dwMaxDBCSCharByteSize); #else // HOST_UNIX return 3; #endif // HOST_UNIX } #ifndef Wsz_mbstowcs #define Wsz_mbstowcs(szOut, szIn, iSize) WszMultiByteToWideChar(CP_ACP, 0, szIn, -1, szOut, iSize) #endif #ifndef Wsz_wcstombs #define Wsz_wcstombs(szOut, szIn, iSize) WszWideCharToMultiByte(CP_ACP, 0, szIn, -1, szOut, iSize, 0, 0) #endif // For all platforms: BOOL WszCreateProcess( LPCWSTR lpApplicationName, LPCWSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation ); #if defined(HOST_X86) && defined(_MSC_VER) // // Windows SDK does not use intrinsics on x86. Redefine the interlocked operations to use intrinsics. // #include "intrin.h" #define InterlockedIncrement _InterlockedIncrement #define InterlockedDecrement _InterlockedDecrement #define InterlockedExchange _InterlockedExchange #define InterlockedCompareExchange _InterlockedCompareExchange #define InterlockedExchangeAdd _InterlockedExchangeAdd #define InterlockedCompareExchange64 _InterlockedCompareExchange64 #define InterlockedAnd _InterlockedAnd #define InterlockedOr _InterlockedOr // // There is no _InterlockedCompareExchangePointer intrinsic in VC++ for x86. // winbase.h #defines InterlockedCompareExchangePointer as __InlineInterlockedCompareExchangePointer, // which calls the Win32 InterlockedCompareExchange, not the intrinsic _InterlockedCompareExchange. // We want the intrinsic, so we #undef the Windows version of this API, and define our own. // #ifdef InterlockedCompareExchangePointer #undef InterlockedCompareExchangePointer #endif FORCEINLINE PVOID InterlockedCompareExchangePointer ( __inout PVOID volatile *Destination, _In_opt_ PVOID ExChange, _In_opt_ PVOID Comperand ) { return((PVOID)(LONG_PTR)_InterlockedCompareExchange((LONG volatile *)Destination, (LONG)(LONG_PTR)ExChange, (LONG)(LONG_PTR)Comperand)); } #endif // HOST_X86 && _MSC_VER #if defined(HOST_X86) & !defined(InterlockedIncrement64) // Interlockedxxx64 that do not have intrinsics are only supported on Windows Server 2003 // or higher for X86 so define our own portable implementation #undef InterlockedIncrement64 #define InterlockedIncrement64 __InterlockedIncrement64 #undef InterlockedDecrement64 #define InterlockedDecrement64 __InterlockedDecrement64 #undef InterlockedExchange64 #define InterlockedExchange64 __InterlockedExchange64 #undef InterlockedExchangeAdd64 #define InterlockedExchangeAdd64 __InterlockedExchangeAdd64 __forceinline LONGLONG __InterlockedIncrement64(LONGLONG volatile *Addend) { LONGLONG Old; do { Old = *Addend; } while (InterlockedCompareExchange64(Addend, Old + 1, Old) != Old); return Old + 1; } __forceinline LONGLONG __InterlockedDecrement64(LONGLONG volatile *Addend) { LONGLONG Old; do { Old = *Addend; } while (InterlockedCompareExchange64(Addend, Old - 1, Old) != Old); return Old - 1; } __forceinline LONGLONG __InterlockedExchange64(LONGLONG volatile * Target, LONGLONG Value) { LONGLONG Old; do { Old = *Target; } while (InterlockedCompareExchange64(Target, Value, Old) != Old); return Old; } __forceinline LONGLONG __InterlockedExchangeAdd64(LONGLONG volatile * Addend, LONGLONG Value) { LONGLONG Old; do { Old = *Addend; } while (InterlockedCompareExchange64(Addend, Old + Value, Old) != Old); return Old; } #endif // HOST_X86 #endif // __WIN_WRAP_H__ ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/xclrdata.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** clrdata.idl - Common Language Runtime data access interfaces for ** ** clients needing to access runtime state from outside ** ** runtime, such as out-of-process debuggers. ** ** ** ** The access interface defines two different types of code running: ** ** The host is the user of the access interface. ** ** The target is the target of the access. ** ** ** ** The host and target can be have different instruction sets, ** ** pointer sizes, runtime versions and so on. ** ** ** *****************************************************************************/ import "clrdata.idl"; cpp_quote("#if 0") typedef UINT32 mdToken; typedef mdToken mdTypeDef; typedef mdToken mdMethodDef; typedef mdToken mdFieldDef; typedef ULONG CorElementType; #define EXCEPTION_MAXIMUM_PARAMETERS 15 // maximum number of exception parameters // The following definition is pasted in from winnt.h, which doesn't // import cleanly as a whole. typedef struct _EXCEPTION_RECORD64 { DWORD ExceptionCode; DWORD ExceptionFlags; DWORD64 ExceptionRecord; DWORD64 ExceptionAddress; DWORD NumberParameters; DWORD __unusedAlignment; DWORD64 ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS]; } EXCEPTION_RECORD64, *PEXCEPTION_RECORD64; cpp_quote("#endif") /* ------------------------------------------------------------------------- * * Forward declarations. * ------------------------------------------------------------------------- */ /* * The following interfaces (with an "IX" prefix instead of the conventional * "I") are works in progress. They will change at least once before Whidbey * ships. */ #pragma warning(push) #pragma warning(disable:28718) //Unable to annotate as this is not a local interface interface IXCLRDataProcess; interface IXCLRDataAppDomain; interface IXCLRDataAssembly; interface IXCLRDataModule; interface IXCLRDataModule2; interface IXCLRDataTypeDefinition; interface IXCLRDataTypeInstance; interface IXCLRDataMethodDefinition; interface IXCLRDataMethodInstance; interface IXCLRDataTask; interface IXCLRDataStackWalk; interface IXCLRDataFrame; interface IXCLRDataFrame2; interface IXCLRDataExceptionState; interface IXCLRDataExceptionNotification; interface IXCLRDataValue; interface IXCLRDataTarget3; interface IXCLRDataDisplay; #pragma warning(pop) typedef struct { CLRDATA_ADDRESS startAddress; CLRDATA_ADDRESS endAddress; } CLRDATA_ADDRESS_RANGE; /* * Many enumerators are based on an opaque state bundle. */ typedef ULONG64 CLRDATA_ENUM; /* * Exception code used for notifications in this interface. */ cpp_quote("#define CLRDATA_NOTIFY_EXCEPTION 0xe0444143") /* * General requests shared by two or more interfaces. */ typedef enum { CLRDATA_REQUEST_REVISION = 0xe0000000, } CLRDataGeneralRequest; /* * The following three sets of flags share * many common definitions are so are * grouped into a block. */ typedef enum { CLRDATA_TYPE_DEFAULT = 0x00000000, // Identify particular kinds of types. These flags // are shared between type, field and value. CLRDATA_TYPE_IS_PRIMITIVE = 0x00000001, CLRDATA_TYPE_IS_VALUE_TYPE = 0x00000002, CLRDATA_TYPE_IS_STRING = 0x00000004, CLRDATA_TYPE_IS_ARRAY = 0x00000008, CLRDATA_TYPE_IS_REFERENCE = 0x00000010, CLRDATA_TYPE_IS_POINTER = 0x00000020, CLRDATA_TYPE_IS_ENUM = 0x00000040, // Alias for all field kinds. CLRDATA_TYPE_ALL_KINDS = 0x7f, } CLRDataTypeFlag; typedef enum { CLRDATA_FIELD_DEFAULT = 0x00000000, // Identify particular kinds of types. These flags // are shared between type, field and value. CLRDATA_FIELD_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, CLRDATA_FIELD_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, CLRDATA_FIELD_IS_STRING = CLRDATA_TYPE_IS_STRING, CLRDATA_FIELD_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, CLRDATA_FIELD_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, CLRDATA_FIELD_IS_POINTER = CLRDATA_TYPE_IS_POINTER, CLRDATA_FIELD_IS_ENUM = CLRDATA_TYPE_IS_ENUM, // Alias for all field kinds. CLRDATA_FIELD_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, // Identify field properties. These flags are // shared between field and value. CLRDATA_FIELD_IS_INHERITED = 0x00000080, CLRDATA_FIELD_IS_LITERAL = 0x00000100, // Identify field storage location. These flags are // shared between field and value. CLRDATA_FIELD_FROM_INSTANCE = 0x00000200, CLRDATA_FIELD_FROM_TASK_LOCAL = 0x00000400, CLRDATA_FIELD_FROM_STATIC = 0x00000800, // Alias for all types of field locations. CLRDATA_FIELD_ALL_LOCATIONS = 0x00000e00, // Alias for all fields from all locations. CLRDATA_FIELD_ALL_FIELDS = 0x00000eff, } CLRDataFieldFlag; typedef enum { CLRDATA_VALUE_DEFAULT = 0x00000000, // Identify particular kinds of types. These flags // are shared between type, field and value. CLRDATA_VALUE_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, CLRDATA_VALUE_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, CLRDATA_VALUE_IS_STRING = CLRDATA_TYPE_IS_STRING, CLRDATA_VALUE_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, CLRDATA_VALUE_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, CLRDATA_VALUE_IS_POINTER = CLRDATA_TYPE_IS_POINTER, CLRDATA_VALUE_IS_ENUM = CLRDATA_TYPE_IS_ENUM, // Alias for all value kinds. CLRDATA_VALUE_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, // Identify field properties. These flags are // shared between field and value. CLRDATA_VALUE_IS_INHERITED = CLRDATA_FIELD_IS_INHERITED, CLRDATA_VALUE_IS_LITERAL = CLRDATA_FIELD_IS_LITERAL, // Identify field storage location. These flags are // shared between field and value. CLRDATA_VALUE_FROM_INSTANCE = CLRDATA_FIELD_FROM_INSTANCE, CLRDATA_VALUE_FROM_TASK_LOCAL = CLRDATA_FIELD_FROM_TASK_LOCAL, CLRDATA_VALUE_FROM_STATIC = CLRDATA_FIELD_FROM_STATIC, // Alias for all types of field locations. CLRDATA_VALUE_ALL_LOCATIONS = CLRDATA_FIELD_ALL_LOCATIONS, // Alias for all fields from all locations. CLRDATA_VALUE_ALL_FIELDS = CLRDATA_FIELD_ALL_FIELDS, // Identify whether the value is a boxed object. CLRDATA_VALUE_IS_BOXED = 0x00001000, } CLRDataValueFlag; [ object, local, uuid(59d9b5e1-4a6f-4531-84c3-51d12da22fd4), pointer_default(unique) ] interface IXCLRDataTarget3 : ICLRDataTarget2 { /* * Ask the target to recover metadata for * an image. May not succeed. */ HRESULT GetMetaData([in] LPCWSTR imagePath, [in] ULONG32 imageTimestamp, [in] ULONG32 imageSize, [in] GUID* mvid, [in] ULONG32 mdRva, [in] ULONG32 flags, [in] ULONG32 bufferSize, [out, size_is(bufferSize), length_is(*dataSize)] BYTE* buffer, [out] ULONG32* dataSize); }; /* * Flags used for *ByName methods. */ typedef enum { CLRDATA_BYNAME_CASE_SENSITIVE = 0x00000000, CLRDATA_BYNAME_CASE_INSENSITIVE = 0x00000001, } CLRDataByNameFlag; /* * Flags used in GetName methods. */ typedef enum { CLRDATA_GETNAME_DEFAULT = 0x00000000, CLRDATA_GETNAME_NO_NAMESPACES = 0x00000001, CLRDATA_GETNAME_NO_PARAMETERS = 0x00000002, } CLRDataGetNameFlag; typedef enum { CLRDATA_PROCESS_DEFAULT = 0x00000000, CLRDATA_PROCESS_IN_GC = 0x00000001, } CLRDataProcessFlag; typedef enum { CLRDATA_ADDRESS_UNRECOGNIZED, CLRDATA_ADDRESS_MANAGED_METHOD, CLRDATA_ADDRESS_RUNTIME_MANAGED_CODE, CLRDATA_ADDRESS_RUNTIME_UNMANAGED_CODE, CLRDATA_ADDRESS_GC_DATA, CLRDATA_ADDRESS_RUNTIME_MANAGED_STUB, CLRDATA_ADDRESS_RUNTIME_UNMANAGED_STUB, } CLRDataAddressType; typedef enum { CLRDATA_NOTIFY_ON_MODULE_LOAD = 0x00000001, CLRDATA_NOTIFY_ON_MODULE_UNLOAD = 0x00000002, CLRDATA_NOTIFY_ON_EXCEPTION = 0x00000004, CLRDATA_NOTIFY_ON_EXCEPTION_CATCH_ENTER = 0x00000008, } CLRDataOtherNotifyFlag; /* * Data buffer and flags for follow-stub data. */ typedef struct { ULONG64 Data[8]; } CLRDATA_FOLLOW_STUB_BUFFER; typedef enum { CLRDATA_FOLLOW_STUB_DEFAULT = 0x00000000, } CLRDataFollowStubInFlag; typedef enum { CLRDATA_FOLLOW_STUB_INTERMEDIATE = 0x00000000, CLRDATA_FOLLOW_STUB_EXIT = 0x00000001, } CLRDataFollowStubOutFlag; typedef enum { CLRNATIVEIMAGE_PE_INFO = 0x00000001, CLRNATIVEIMAGE_COR_INFO = 0x00000002, CLRNATIVEIMAGE_FIXUP_TABLES = 0x00000004, CLRNATIVEIMAGE_FIXUP_HISTOGRAM = 0x00000008, CLRNATIVEIMAGE_MODULE = 0x00000010, CLRNATIVEIMAGE_METHODS = 0x00000020, CLRNATIVEIMAGE_DISASSEMBLE_CODE = 0x00000040, CLRNATIVEIMAGE_IL = 0x00000080, CLRNATIVEIMAGE_METHODTABLES = 0x00000100, CLRNATIVEIMAGE_NATIVE_INFO = 0x00000200, CLRNATIVEIMAGE_MODULE_TABLES = 0x00000400, CLRNATIVEIMAGE_FROZEN_SEGMENT = 0x00000800, CLRNATIVEIMAGE_PE_FILE = 0x00001000, CLRNATIVEIMAGE_GC_INFO = 0x00002000, CLRNATIVEIMAGE_EECLASSES = 0x00004000, CLRNATIVEIMAGE_NATIVE_TABLES = 0x00008000, CLRNATIVEIMAGE_PRECODES = 0x00010000, CLRNATIVEIMAGE_TYPEDESCS = 0x00020000, CLRNATIVEIMAGE_VERBOSE_TYPES = 0x00040000, CLRNATIVEIMAGE_METHODDESCS = 0x00080000, CLRNATIVEIMAGE_METADATA = 0x00100000, CLRNATIVEIMAGE_DISABLE_NAMES = 0x00200000, CLRNATIVEIMAGE_DISABLE_REBASING = 0x00400000, CLRNATIVEIMAGE_SLIM_MODULE_TBLS = 0x00800000, CLRNATIVEIMAGE_RESOURCES = 0x01000000, CLRNATIVEIMAGE_FILE_OFFSET = 0x02000000, CLRNATIVEIMAGE_DEBUG_TRACE = 0x04000000, CLRNATIVEIMAGE_RELOCATIONS = 0x08000000, CLRNATIVEIMAGE_FIXUP_THUNKS = 0x10000000, CLRNATIVEIMAGE_DEBUG_COVERAGE = 0x80000000 } CLRNativeImageDumpOptions; cpp_quote("#ifdef __cplusplus") cpp_quote("inline CLRNativeImageDumpOptions operator|=(CLRNativeImageDumpOptions& lhs, CLRNativeImageDumpOptions rhs) { return (lhs = (CLRNativeImageDumpOptions)( ((unsigned)lhs) | ((unsigned)rhs) )); }") cpp_quote("#endif") typedef enum { CLRDATAHINT_DISPLAY_HINTS_NONE = 0, //array hints 0x000000ff CLRDATAHINT_DISPLAY_ARRAY_AS_TABLE = 0x00000001, CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY = 0x00000002, CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY_IDX = 0x00000003, //print idx as field 1 CLRDATAHINT_DISPLAY_ARRAY_AS_MAP = 0x00000004, CLRDATAHINT_DISPLAY_ARRAY_HINT_MASK = 0x000000ff, //structure hints CLRDATAHINT_DISPLAY_STRUCT_AS_TABLE = 0x00000100, CLRDATAHINT_DISPLAY_STRUCT_HINT_MASK = 0x0000ff00, //separate fields with tabs CLRDATAHINT_DISPLAY_SEP_TAB = 0x00000000, //separate fields with spaces CLRDATAHINT_DISPLAY_SEP_SPACE = 0x01000000, //separate first field by a tab, and all other fields with spaces CLRDATAHINT_DISPLAY_SEP_TAB_SPACE = 0x02000000, CLRDATAHINT_DISPLAY_SEP_MASK = 0xff000000, } CLRDataDisplayHints; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning for interface IXCLRDataProcess */ /* * This interface supports the loading of dependencies and processing of PE * files for the NativeImageDumper. */ [ object, local, uuid(E5F3039D-2C0C-4230-A69E-12AF1C3E563C) ] interface IXCLRLibrarySupport : IUnknown { //loads a dependency. It can fail if the image needs to be relocated. HRESULT LoadHardboundDependency(const WCHAR * name, REFGUID mvid, [out]SIZE_T *loadedBase); HRESULT LoadSoftboundDependency(const WCHAR * name, const BYTE * assemblymetadataBinding, const BYTE * hash, ULONG hashLength, [out]SIZE_T *loadedBase); }; interface IXCLRDisassemblySupport; typedef SIZE_T (__stdcall *CDSTranslateAddrCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, WCHAR *, SIZE_T, DWORDLONG *); typedef SIZE_T (__stdcall *CDSTranslateFixupCB)(IXCLRDisassemblySupport *, CLRDATA_ADDRESS, SIZE_T, WCHAR *, SIZE_T, DWORDLONG *); typedef SIZE_T (__stdcall *CDSTranslateConstCB)(IXCLRDisassemblySupport *, DWORD, WCHAR *, SIZE_T); typedef SIZE_T (__stdcall *CDSTranslateRegrelCB)(IXCLRDisassemblySupport *, unsigned rega, CLRDATA_ADDRESS, WCHAR *, SIZE_T, DWORD *); [ object, local, uuid(1F0F7134-D3F3-47DE-8E9B-C2FD358A2936) ] interface IXCLRDisassemblySupport : IUnknown { HRESULT SetTranslateAddrCallback([in] CDSTranslateAddrCB cb); HRESULT PvClientSet([in] void * pv); SIZE_T CbDisassemble(CLRDATA_ADDRESS, const void *, SIZE_T); SIZE_T Cinstruction(); BOOL FSelectInstruction(SIZE_T); SIZE_T CchFormatInstr(WCHAR *, SIZE_T); void *PvClient(); HRESULT SetTranslateFixupCallback([in]CDSTranslateFixupCB cb); HRESULT SetTranslateConstCallback([in]CDSTranslateConstCB cb); HRESULT SetTranslateRegrelCallback([in]CDSTranslateRegrelCB cb); BOOL TargetIsAddress(); }; /* * This interface is passed to CLRDataCreateInstance::DumpNativeImage. It * handles display of the logical data in the ngen image. */ [ object, local, uuid(A3C1704A-4559-4a67-8D28-E8F4FE3B3F62) ] interface IXCLRDataDisplay : IUnknown { HRESULT ErrorPrintF(const char * const fmt, ...); HRESULT NativeImageDimensions(SIZE_T base, SIZE_T size, DWORD sectionAlign); HRESULT Section(const char * const name, SIZE_T rva, SIZE_T size); HRESULT GetDumpOptions([out] CLRNativeImageDumpOptions * pOptions); //Start and end the document HRESULT StartDocument(); HRESULT EndDocument(); //XML-Constructs that do not map to actual fields or structures //A category is a top level section of the ngen output. For example, //"Sections", "Directories", "CLR Info", etc. HRESULT StartCategory(const char * const name); HRESULT EndCategory(); //starts an element containing either xml text or other elements. Only //used within arrays and lists. Otherwise use StartVStructure. HRESULT StartElement(const char * const name); HRESULT EndElement(); //like a Structure, but without a name and size. Used within categories //and structures. HRESULT StartVStructure(const char * const name ); HRESULT StartVStructureWithOffset( const char * const name, unsigned fieldOffset, unsigned fieldSize ); HRESULT EndVStructure(); //An element that contains xml text. HRESULT StartTextElement(const char * const name); HRESULT EndTextElement(); HRESULT WriteXmlText(const char * const fmt, ...); HRESULT WriteXmlTextBlock(const char * const fmt, ...); HRESULT WriteEmptyElement(const char * const element); //produces ptr HRESULT WriteElementPointer(const char * const element, SIZE_T ptr); HRESULT WriteElementPointerAnnotated(const char * const element, SIZE_T ptr, const WCHAR * const annotation ); //produces HRESULT WriteElementAddress(const char * const element, SIZE_T base, SIZE_T size); HRESULT WriteElementAddressNamed(const char * const element, const char * const name, SIZE_T base, SIZE_T size); HRESULT WriteElementAddressNamedW(const char * const element, const WCHAR * const name, SIZE_T base, SIZE_T size); HRESULT WriteElementString(const char * const element, const char * const data); HRESULT WriteElementStringW(const char * const element, const WCHAR * const data); HRESULT WriteElementInt(const char * const element, int value); HRESULT WriteElementUInt(const char * const element, DWORD value); HRESULT WriteElementEnumerated(const char * const element, DWORD value, const WCHAR * const mnemonic); //writes value if value != suppressIfEqual. //in text mode the whole element is suppressed (and a "" is appended if //inside an array or list. HRESULT WriteElementIntWithSuppress( const char * const element, int value, int suppressIfEqual ); //For text, it produces "(element)" or "" instead of "true" or "false". HRESULT WriteElementFlag(const char * const element, BOOL flag); //if countPrefix is not Null, displays a total at the end in text mode. //Arrays have headings in both text and xml. Lists are "repeated elements" HRESULT StartArray( const char * const name, const WCHAR * const fmt); HRESULT EndArray( const char * const countPrefix ); HRESULT StartList( const WCHAR * const fmt ); HRESULT EndList(); //XML-Constructs that represent real C++ Data structure HRESULT StartArrayWithOffset( const char * const name, unsigned fieldOffset, unsigned fieldSize, const WCHAR * const fmt ); #if 0 //writes value if value != suppressIfEqual. //in text mode the whole element is suppressed (and a "" is appended if //inside an array or list. HRESULT WriteFieldIntWithSuppress( const char * const element, unsigned offset, int value, int suppressIfEqual ); #endif HRESULT WriteFieldString(const char * const element, unsigned fieldOffset, unsigned fieldSize, const char * const data); HRESULT WriteFieldStringW(const char * const element, unsigned fieldOffset, unsigned fieldSize, const WCHAR * const data); //produces ptr HRESULT WriteFieldPointer(const char * const element, unsigned fieldOffset, unsigned fieldSize, SIZE_T ptr); //produces ptr+size HRESULT WriteFieldPointerWithSize(const char * const element, unsigned fieldOffset, unsigned fieldSize, SIZE_T ptr, SIZE_T size); HRESULT WriteFieldInt(const char * const element, unsigned fieldOffset, unsigned fieldSize, int value); HRESULT WriteFieldUInt(const char * const element, unsigned fieldOffset, unsigned fieldSize, DWORD value); HRESULT WriteFieldEnumerated(const char * const element, unsigned fieldOffset, unsigned fieldSize, DWORD value, const WCHAR * const mnemonic); HRESULT WriteFieldEmpty(const char * const element, unsigned fieldOffset, unsigned fieldSize); HRESULT WriteFieldFlag(const char * const element, unsigned fieldOffset, unsigned fieldSize, BOOL flag); HRESULT WriteFieldPointerAnnotated(const char * const element, unsigned fieldOffset, unsigned fieldSize, SIZE_T ptr, const WCHAR * const annotation); //produces HRESULT WriteFieldAddress(const char * const element, unsigned fieldOffset, unsigned fieldSize, SIZE_T base, SIZE_T size); //For text, it produces "(element)" or "" instead of "true" or "false". #if 0 HRESULT WriteFieldFlag(const char * const element, unsigned offset, BOOL flag); HRESULT WriteFieldInt(const char * const element, unsigned offset, int value); HRESULT WriteFieldUInt(const char * const element, unsigned offset, DWORD value); HRESULT WriteFieldEnumerated(const char * const element, unsigned offset, DWORD value, const WCHAR * const mnemonic); #endif //structures are like categories and elements, but they have a base and //size. HRESULT StartStructure( const char * const name, SIZE_T ptr, SIZE_T size ); HRESULT StartStructureWithNegSpace( const char * const name, SIZE_T ptr, SIZE_T startPtr, SIZE_T totalSize ); HRESULT StartStructureWithOffset( const char * const name, unsigned fieldOffset, unsigned fieldSize, SIZE_T ptr, SIZE_T size ); HRESULT EndStructure(); #if 0 //produces ptr+size HRESULT WriteElementPointerWithSize(const char * const element, SIZE_T ptr, SIZE_T size); HRESULT WriteElementInt(const char * const element, int value); HRESULT WriteFixupDescription(SIZE_T ptr, DWORD tagged, SIZE_T handle, const char * const name ); //structures are like categories and elements, but they have a base and //size. HRESULT StartStructure( const char * const name, SIZE_T ptr, SIZE_T size ); HRESULT EndStructure(); #endif }; /* * Interface representing the process itself. Can be obtained via * CLRDataCreateInstance. */ [ object, local, uuid(5c552ab6-fc09-4cb3-8e36-22fa03c798b7) ] interface IXCLRDataProcess : IUnknown { /* * Flush any cached data for this process. All ICLR* interfaces obtained * for this process will become invalid with this call. */ HRESULT Flush(); /* * Begin enumeration of tasks. * Returns S_FALSE if the enumeration is empty. */ HRESULT StartEnumTasks([out] CLRDATA_ENUM* handle); /* * Get the next entry in the enumeration. * Returns S_FALSE if there isn't a next entry. */ HRESULT EnumTask([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataTask** task); /* * Release the enumerator. */ HRESULT EndEnumTasks([in] CLRDATA_ENUM handle); /* * Get the managed task running on the given OS thread ID */ HRESULT GetTaskByOSThreadID([in] ULONG32 osThreadID, [out] IXCLRDataTask** task); /* * Get the managed task corresponding to the given task ID. */ HRESULT GetTaskByUniqueID([in] ULONG64 taskID, [out] IXCLRDataTask** task); /* * Get state flags, defined in CLRDataProcessFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataProcess* process); /* * Get the managed object representing the process. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); /* * Mark the process so that it attempts to reach the * desired execution state the next time it executes. */ HRESULT GetDesiredExecutionState([out] ULONG32* state); HRESULT SetDesiredExecutionState([in] ULONG32 state); /* * Return an indicator of the type of data referred * to by the given address. */ HRESULT GetAddressType([in] CLRDATA_ADDRESS address, [out] CLRDataAddressType* type); /* * Get a name for the given address if * the address refers to non-managed-method information. * Method names can be retrieved by using GetMethodInstanceByAddress * and GetName on the method instance. * * Returns S_FALSE if the buffer is not large enough for the name, * and sets nameLen to be the buffer length needed. */ HRESULT GetRuntimeNameByAddress([in] CLRDATA_ADDRESS address, [in] ULONG32 flags, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[], [out] CLRDATA_ADDRESS* displacement); /* * App domain enumeration. */ HRESULT StartEnumAppDomains([out] CLRDATA_ENUM* handle); HRESULT EnumAppDomain([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataAppDomain** appDomain); HRESULT EndEnumAppDomains([in] CLRDATA_ENUM handle); /* * Find an app domain by its unique ID. */ HRESULT GetAppDomainByUniqueID([in] ULONG64 id, [out] IXCLRDataAppDomain** appDomain); /* * Assembly enumeration. */ HRESULT StartEnumAssemblies([out] CLRDATA_ENUM* handle); HRESULT EnumAssembly([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataAssembly **assembly); HRESULT EndEnumAssemblies([in] CLRDATA_ENUM handle); /* * Module enumeration. */ HRESULT StartEnumModules([out] CLRDATA_ENUM* handle); HRESULT EnumModule([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataModule **mod); HRESULT EndEnumModules([in] CLRDATA_ENUM handle); /* * Look up a module by address. */ HRESULT GetModuleByAddress([in] CLRDATA_ADDRESS address, [out] IXCLRDataModule** mod); /* * Look up method instances by native code address. */ HRESULT StartEnumMethodInstancesByAddress([in] CLRDATA_ADDRESS address, [in] IXCLRDataAppDomain* appDomain, [out] CLRDATA_ENUM* handle); HRESULT EnumMethodInstanceByAddress([in] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance** method); HRESULT EndEnumMethodInstancesByAddress([in] CLRDATA_ENUM handle); /* * Look up the name and value of a piece of data by its address. */ HRESULT GetDataByAddress([in] CLRDATA_ADDRESS address, [in] ULONG32 flags, [in] IXCLRDataAppDomain* appDomain, [in] IXCLRDataTask* tlsTask, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[], [out] IXCLRDataValue** value, [out] CLRDATA_ADDRESS* displacement); /* * Get managed state, if any, for the given system exception. * OBSOLETE, DO NOT USE. */ HRESULT GetExceptionStateByExceptionRecord([in] EXCEPTION_RECORD64* record, [out] IXCLRDataExceptionState **exState); /* * Translate a system exception record into * a particular kind of notification if possible. */ HRESULT TranslateExceptionRecordToNotification([in] EXCEPTION_RECORD64* record, [in] IXCLRDataExceptionNotification* notify); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Create a simple value based on the given * type and address information. */ HRESULT CreateMemoryValue([in] IXCLRDataAppDomain* appDomain, [in] IXCLRDataTask* tlsTask, [in] IXCLRDataTypeInstance* type, [in] CLRDATA_ADDRESS addr, [out] IXCLRDataValue** value); /* * Update all existing notifications for a module. * If module is NULL all modules are affected. */ HRESULT SetAllTypeNotifications(IXCLRDataModule* mod, ULONG32 flags); HRESULT SetAllCodeNotifications(IXCLRDataModule* mod, ULONG32 flags); /* * Request notification when a type is * loaded or unloaded. * If mods is NULL singleMod is used as * the module for all tokens. * If flags is NULL singleFlags is used as * the flags for all tokens. */ HRESULT GetTypeNotifications([in] ULONG32 numTokens, [in, size_is(numTokens)] IXCLRDataModule* mods[], [in] IXCLRDataModule* singleMod, [in, size_is(numTokens)] mdTypeDef tokens[], [out, size_is(numTokens)] ULONG32 flags[]); HRESULT SetTypeNotifications([in] ULONG32 numTokens, [in, size_is(numTokens)] IXCLRDataModule* mods[], [in] IXCLRDataModule* singleMod, [in, size_is(numTokens)] mdTypeDef tokens[], [in, size_is(numTokens)] ULONG32 flags[], [in] ULONG32 singleFlags); /* * Request notification when code is generated or * discarded for a method. * If mods is NULL singleMod is used as * the module for all tokens. * If flags is NULL singleFlags is used as * the flags for all tokens. */ HRESULT GetCodeNotifications([in] ULONG32 numTokens, [in, size_is(numTokens)] IXCLRDataModule* mods[], [in] IXCLRDataModule* singleMod, [in, size_is(numTokens)] mdMethodDef tokens[], [out, size_is(numTokens)] ULONG32 flags[]); HRESULT SetCodeNotifications([in] ULONG32 numTokens, [in, size_is(numTokens)] IXCLRDataModule* mods[], [in] IXCLRDataModule* singleMod, [in, size_is(numTokens)] mdMethodDef tokens[], [in, size_is(numTokens)] ULONG32 flags[], [in] ULONG32 singleFlags); /* * Control notifications other than code and * type notifications. */ HRESULT GetOtherNotificationFlags([out] ULONG32* flags); HRESULT SetOtherNotificationFlags([in] ULONG32 flags); /* * Look up method definitions by IL code address. */ HRESULT StartEnumMethodDefinitionsByAddress([in] CLRDATA_ADDRESS address, [out] CLRDATA_ENUM* handle); HRESULT EnumMethodDefinitionByAddress([in] CLRDATA_ENUM* handle, [out] IXCLRDataMethodDefinition** method); HRESULT EndEnumMethodDefinitionsByAddress([in] CLRDATA_ENUM handle); /* * Given an address which is a CLR stub * (and potentially state from a previous follow) * determine the next execution address at which * to check whether the stub has been exited. * OBSOLETE: Use FollowStub2. */ HRESULT FollowStub([in] ULONG32 inFlags, [in] CLRDATA_ADDRESS inAddr, [in] CLRDATA_FOLLOW_STUB_BUFFER* inBuffer, [out] CLRDATA_ADDRESS* outAddr, [out] CLRDATA_FOLLOW_STUB_BUFFER* outBuffer, [out] ULONG32* outFlags); /* Requires revision 7. */ HRESULT FollowStub2([in] IXCLRDataTask* task, [in] ULONG32 inFlags, [in] CLRDATA_ADDRESS inAddr, [in] CLRDATA_FOLLOW_STUB_BUFFER* inBuffer, [out] CLRDATA_ADDRESS* outAddr, [out] CLRDATA_FOLLOW_STUB_BUFFER* outBuffer, [out] ULONG32* outFlags); HRESULT DumpNativeImage([in] CLRDATA_ADDRESS loadedBase, [in] LPCWSTR name, [in] IXCLRDataDisplay* display, [in] IXCLRLibrarySupport* libSupport, [in] IXCLRDisassemblySupport* dis); } #pragma warning(pop) /* * Types used in IXCLRDataProcess2 and IXCLRDataExceptionNotification3 */ typedef enum { GC_MARK_END = 1, GC_EVENT_TYPE_MAX, } GcEvt_t; typedef struct { GcEvt_t typ; [switch_is(typ)] union { [case(GC_MARK_END)] int condemnedGeneration; }; } GcEvtArgs; [ object, local, uuid(5c552ab6-fc09-4cb3-8e36-22fa03c798b8) ] interface IXCLRDataProcess2 : IXCLRDataProcess { /* * Request notification when a GC is triggered. * GcEvtArgs specifies exactly which GC events * are of interest. */ /* * On entry gcEvtArgs is a mask, specifying all events of * interest, in accordance with GcNotification::IsMatch * On exit it represents the first entry matching the input. */ HRESULT GetGcNotification([in, out] GcEvtArgs* gcEvtArgs); HRESULT SetGcNotification([in] GcEvtArgs gcEvtArgs); } typedef enum { CLRDATA_DOMAIN_DEFAULT = 0x00000000, } CLRDataAppDomainFlag; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataAppDomain */ [ object, local, uuid(7CA04601-C702-4670-A63C-FA44F7DA7BD5) ] interface IXCLRDataAppDomain : IUnknown { /* * Get the process that contains this app domain. */ HRESULT GetProcess([out] IXCLRDataProcess** process); /* * Get the app domain's name. */ HRESULT GetName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get a unique, stable identifier for this object. */ HRESULT GetUniqueID([out] ULONG64* id); /* * Get state flags, defined in CLRDataAppDomainFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataAppDomain* appDomain); /* * Get the managed object representing the app domain. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); } #pragma warning(pop) typedef enum { CLRDATA_ASSEMBLY_DEFAULT = 0x00000000, } CLRDataAssemblyFlag; #pragma warning(push) #pragma warning(disable:28718) [ object, local, uuid(2FA17588-43C2-46ab-9B51-C8F01E39C9AC) ] interface IXCLRDataAssembly : IUnknown { /* * Enumerate modules in the assembly. */ HRESULT StartEnumModules([out] CLRDATA_ENUM* handle); HRESULT EnumModule([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataModule **mod); HRESULT EndEnumModules([in] CLRDATA_ENUM handle); /* * Get the assembly's base name. */ HRESULT GetName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get the full path and filename for the assembly, * if there is one. */ HRESULT GetFileName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get state flags, defined in CLRDataAssemblyFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataAssembly* assembly); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Enumerate the app domains using this assembly. */ HRESULT StartEnumAppDomains([out] CLRDATA_ENUM* handle); HRESULT EnumAppDomain([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataAppDomain** appDomain); HRESULT EndEnumAppDomains([in] CLRDATA_ENUM handle); /* * Get the metadata display name for the assembly. * Requires revision 2. */ HRESULT GetDisplayName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); } #pragma warning(pop) typedef enum { CLRDATA_MODULE_DEFAULT = 0x00000000, CLRDATA_MODULE_IS_DYNAMIC = 0x00000001, CLRDATA_MODULE_IS_MEMORY_STREAM = 0x00000002, CLRDATA_MODULE_IS_MAIN_MODULE = 0x00000004, } CLRDataModuleFlag; typedef enum { CLRDATA_MODULE_PE_FILE, CLRDATA_MODULE_PREJIT_FILE, CLRDATA_MODULE_MEMORY_STREAM, CLRDATA_MODULE_OTHER } CLRDataModuleExtentType; typedef struct { CLRDATA_ADDRESS base; ULONG32 length; CLRDataModuleExtentType type; } CLRDATA_MODULE_EXTENT; typedef enum { CLRDATA_TYPENOTIFY_NONE = 0x00000000, CLRDATA_TYPENOTIFY_LOADED = 0x00000001, CLRDATA_TYPENOTIFY_UNLOADED = 0x00000002, } CLRDataTypeNotification; typedef enum { CLRDATA_METHNOTIFY_NONE = 0x00000000, CLRDATA_METHNOTIFY_GENERATED = 0x00000001, CLRDATA_METHNOTIFY_DISCARDED = 0x00000002, } CLRDataMethodCodeNotification; #pragma warning(push) #pragma warning(disable:28718) /* * Represents a loaded module. * * Can be QI'd for a metadata interface or a symbol-store interface. */ [ object, local, uuid(88E32849-0A0A-4cb0-9022-7CD2E9E139E2) ] interface IXCLRDataModule : IUnknown { /* * Enumerate assemblies this module is part of. * Module-to-assembly is an enumeration as a * shared module might be part of more than one assembly. */ HRESULT StartEnumAssemblies([out] CLRDATA_ENUM* handle); HRESULT EnumAssembly([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataAssembly **assembly); HRESULT EndEnumAssemblies([in] CLRDATA_ENUM handle); /* * Enumerate types in this module. */ HRESULT StartEnumTypeDefinitions([out] CLRDATA_ENUM* handle); HRESULT EnumTypeDefinition([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeDefinition **typeDefinition); HRESULT EndEnumTypeDefinitions([in] CLRDATA_ENUM handle); HRESULT StartEnumTypeInstances([in] IXCLRDataAppDomain* appDomain, [out] CLRDATA_ENUM* handle); HRESULT EnumTypeInstance([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeInstance **typeInstance); HRESULT EndEnumTypeInstances([in] CLRDATA_ENUM handle); /* * Look up types by name. */ HRESULT StartEnumTypeDefinitionsByName([in] LPCWSTR name, [in] ULONG32 flags, [out] CLRDATA_ENUM* handle); HRESULT EnumTypeDefinitionByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeDefinition** type); HRESULT EndEnumTypeDefinitionsByName([in] CLRDATA_ENUM handle); HRESULT StartEnumTypeInstancesByName([in] LPCWSTR name, [in] ULONG32 flags, [in] IXCLRDataAppDomain* appDomain, [out] CLRDATA_ENUM* handle); HRESULT EnumTypeInstanceByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeInstance** type); HRESULT EndEnumTypeInstancesByName([in] CLRDATA_ENUM handle); /* * Get a type definition by metadata token. */ HRESULT GetTypeDefinitionByToken([in] mdTypeDef token, [out] IXCLRDataTypeDefinition** typeDefinition); /* * Look up methods by name. */ HRESULT StartEnumMethodDefinitionsByName([in] LPCWSTR name, [in] ULONG32 flags, [out] CLRDATA_ENUM* handle); HRESULT EnumMethodDefinitionByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodDefinition** method); HRESULT EndEnumMethodDefinitionsByName([in] CLRDATA_ENUM handle); HRESULT StartEnumMethodInstancesByName([in] LPCWSTR name, [in] ULONG32 flags, [in] IXCLRDataAppDomain* appDomain, [out] CLRDATA_ENUM* handle); HRESULT EnumMethodInstanceByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance** method); HRESULT EndEnumMethodInstancesByName([in] CLRDATA_ENUM handle); /* * Get a method definition by metadata token. */ HRESULT GetMethodDefinitionByToken([in] mdMethodDef token, [out] IXCLRDataMethodDefinition** methodDefinition); /* * Look up pieces of data by name. */ HRESULT StartEnumDataByName([in] LPCWSTR name, [in] ULONG32 flags, [in] IXCLRDataAppDomain* appDomain, [in] IXCLRDataTask* tlsTask, [out] CLRDATA_ENUM* handle); HRESULT EnumDataByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value); HRESULT EndEnumDataByName([in] CLRDATA_ENUM handle); /* * Get the module's base name. */ HRESULT GetName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get the full path and filename for the module, * if there is one. */ HRESULT GetFileName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get state flags, defined in CLRDataModuleFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataModule* mod); /* * Get the memory regions associated with this module. */ HRESULT StartEnumExtents([out] CLRDATA_ENUM* handle); HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, [out] CLRDATA_MODULE_EXTENT* extent); HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Enumerate the app domains using this module. */ HRESULT StartEnumAppDomains([out] CLRDATA_ENUM* handle); HRESULT EnumAppDomain([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataAppDomain** appDomain); HRESULT EndEnumAppDomains([in] CLRDATA_ENUM handle); /* * Get the module's version ID. * Requires revision 3. */ HRESULT GetVersionId([out] GUID* vid); } #pragma warning(pop) /* * Represents additional APIs for a loaded module. * */ [ object, local, uuid(34625881-7EB3-4524-817B-8DB9D064C760) ] interface IXCLRDataModule2 : IUnknown { /* * SetJITCompilerFlags sets the flags that control the JIT compiler. If the set of flags is invalid, * the function will fail. This function can only be called from within the LoadModule callback * for the given module. */ HRESULT SetJITCompilerFlags( [in] DWORD dwFlags ); } #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataTypeDefinition */ [ object, local, uuid(4675666C-C275-45b8-9F6C-AB165D5C1E09) ] interface IXCLRDataTypeDefinition : IUnknown { /* * Get the module this type is part of. */ HRESULT GetModule([out] IXCLRDataModule **mod); /* * Enumerate the methods for this type. */ HRESULT StartEnumMethodDefinitions([out] CLRDATA_ENUM* handle); HRESULT EnumMethodDefinition([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodDefinition **methodDefinition); HRESULT EndEnumMethodDefinitions([in] CLRDATA_ENUM handle); /* * Look up methods by name. */ HRESULT StartEnumMethodDefinitionsByName([in] LPCWSTR name, [in] ULONG32 flags, [out] CLRDATA_ENUM* handle); HRESULT EnumMethodDefinitionByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodDefinition** method); HRESULT EndEnumMethodDefinitionsByName([in] CLRDATA_ENUM handle); /* * Get a method definition by metadata token. */ HRESULT GetMethodDefinitionByToken([in] mdMethodDef token, [out] IXCLRDataMethodDefinition** methodDefinition); /* * Enumerate instances of this definition. */ HRESULT StartEnumInstances([in] IXCLRDataAppDomain* appDomain, [out] CLRDATA_ENUM* handle); HRESULT EnumInstance([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeInstance **instance); HRESULT EndEnumInstances([in] CLRDATA_ENUM handle); /* * Get the namespace-qualified name for this type definition. */ HRESULT GetName([in] ULONG32 flags, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Get the metadata token and scope. */ HRESULT GetTokenAndScope([out] mdTypeDef* token, [out] IXCLRDataModule **mod); /* * Get standard element type. */ HRESULT GetCorElementType([out] CorElementType* type); /* * Get state flags, defined in CLRDataTypeFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataTypeDefinition* type); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * If this is an array type, return the number * of dimensions in the array. */ HRESULT GetArrayRank([out] ULONG32* rank); /* * Get the base type of this type, if any. */ HRESULT GetBase([out] IXCLRDataTypeDefinition** base); /* * Get the number of fields in the type. */ HRESULT GetNumFields([in] ULONG32 flags, [out] ULONG32* numFields); /* * Enumerate the fields for this type. * OBSOLETE: Use EnumField2. */ HRESULT StartEnumFields([in] ULONG32 flags, [out] CLRDATA_ENUM* handle); HRESULT EnumField([in, out] CLRDATA_ENUM* handle, [in] ULONG32 nameBufLen, [out] ULONG32* nameLen, [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags, [out] mdFieldDef* token); HRESULT EndEnumFields([in] CLRDATA_ENUM handle); HRESULT StartEnumFieldsByName([in] LPCWSTR name, [in] ULONG32 nameFlags, [in] ULONG32 fieldFlags, [out] CLRDATA_ENUM* handle); HRESULT EnumFieldByName([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags, [out] mdFieldDef* token); HRESULT EndEnumFieldsByName([in] CLRDATA_ENUM handle); /* * Look up information for a specific field by token. */ HRESULT GetFieldByToken([in] mdFieldDef token, [in] ULONG32 nameBufLen, [out] ULONG32* nameLen, [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags); /* * Request notification when the given type is * loaded or unloaded. */ HRESULT GetTypeNotification([out] ULONG32* flags); HRESULT SetTypeNotification([in] ULONG32 flags); HRESULT EnumField2([in, out] CLRDATA_ENUM* handle, [in] ULONG32 nameBufLen, [out] ULONG32* nameLen, [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags, [out] IXCLRDataModule** tokenScope, [out] mdFieldDef* token); HRESULT EnumFieldByName2([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags, [out] IXCLRDataModule** tokenScope, [out] mdFieldDef* token); HRESULT GetFieldByToken2([in] IXCLRDataModule* tokenScope, [in] mdFieldDef token, [in] ULONG32 nameBufLen, [out] ULONG32* nameLen, [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] IXCLRDataTypeDefinition** type, [out] ULONG32* flags); } #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) [ object, local, uuid(4D078D91-9CB3-4b0d-97AC-28C8A5A82597) ] interface IXCLRDataTypeInstance : IUnknown { /* * Enumerate method instances within this type. */ HRESULT StartEnumMethodInstances([out] CLRDATA_ENUM* handle); HRESULT EnumMethodInstance([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance** methodInstance); HRESULT EndEnumMethodInstances([in] CLRDATA_ENUM handle); /* * Look up method instances by name. */ HRESULT StartEnumMethodInstancesByName([in] LPCWSTR name, [in] ULONG32 flags, [out] CLRDATA_ENUM* handle); HRESULT EnumMethodInstanceByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance** method); HRESULT EndEnumMethodInstancesByName([in] CLRDATA_ENUM handle); /* * Get the number of static fields in the type. * OBSOLETE: Use GetNumStaticFields2. */ HRESULT GetNumStaticFields([out] ULONG32* numFields); /* * Get one static field of the type. * * Because static field ordering is not fixed, can also return name * information and/or the metadata token, if the caller passes * in appropriate values. * OBSOLETE: Use EnumStaticField. */ HRESULT GetStaticFieldByIndex([in] ULONG32 index, [in] IXCLRDataTask* tlsTask, [out] IXCLRDataValue **field, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[], [out] mdFieldDef* token); /* * Look up fields by name. * OBSOLETE: Use EnumStaticFieldByName2. */ HRESULT StartEnumStaticFieldsByName([in] LPCWSTR name, [in] ULONG32 flags, [in] IXCLRDataTask* tlsTask, [out] CLRDATA_ENUM* handle); HRESULT EnumStaticFieldByName([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value); HRESULT EndEnumStaticFieldsByName([in] CLRDATA_ENUM handle); /* * Enumerate this type's parameterization. */ HRESULT GetNumTypeArguments([out] ULONG32* numTypeArgs); HRESULT GetTypeArgumentByIndex([in] ULONG32 index, [out] IXCLRDataTypeInstance** typeArg); /* * Get the fully qualified name for this type instance. */ HRESULT GetName([in] ULONG32 flags, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Get the module for this type instance. */ HRESULT GetModule([out] IXCLRDataModule **mod); /* * Get the definition matching this instance. */ HRESULT GetDefinition([out] IXCLRDataTypeDefinition **typeDefinition); /* * Get state flags, defined in CLRDataTypeFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataTypeInstance* type); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Get the number of static fields in the type. */ HRESULT GetNumStaticFields2([in] ULONG32 flags, [out] ULONG32* numFields); /* * Enumerate values for the static fields of this type. */ HRESULT StartEnumStaticFields([in] ULONG32 flags, [in] IXCLRDataTask* tlsTask, [out] CLRDATA_ENUM* handle); HRESULT EnumStaticField([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value); HRESULT EndEnumStaticFields([in] CLRDATA_ENUM handle); HRESULT StartEnumStaticFieldsByName2([in] LPCWSTR name, [in] ULONG32 nameFlags, [in] ULONG32 fieldFlags, [in] IXCLRDataTask* tlsTask, [out] CLRDATA_ENUM* handle); HRESULT EnumStaticFieldByName2([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value); HRESULT EndEnumStaticFieldsByName2([in] CLRDATA_ENUM handle); /* * Retrieve a static field by field metadata token. */ HRESULT GetStaticFieldByToken([in] mdFieldDef token, [in] IXCLRDataTask* tlsTask, [out] IXCLRDataValue **field, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Get the base type of this type, if any. */ HRESULT GetBase([out] IXCLRDataTypeInstance** base); HRESULT EnumStaticField2([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[], [out] IXCLRDataModule** tokenScope, [out] mdFieldDef* token); HRESULT EnumStaticFieldByName3([in,out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** value, [out] IXCLRDataModule** tokenScope, [out] mdFieldDef* token); HRESULT GetStaticFieldByToken2([in] IXCLRDataModule* tokenScope, [in] mdFieldDef token, [in] IXCLRDataTask* tlsTask, [out] IXCLRDataValue **field, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); } #pragma warning(pop) typedef enum { CLRDATA_SOURCE_TYPE_INVALID = 0x00, // To indicate that nothing else applies } CLRDataSourceType; /* * Special IL offset values for special regions. */ typedef enum { CLRDATA_IL_OFFSET_NO_MAPPING = -1, CLRDATA_IL_OFFSET_PROLOG = -2, CLRDATA_IL_OFFSET_EPILOG = -3 } CLRDATA_IL_OFFSET_MARKER; typedef struct { ULONG32 ilOffset; CLRDATA_ADDRESS startAddress; CLRDATA_ADDRESS endAddress; CLRDataSourceType type; } CLRDATA_IL_ADDRESS_MAP; typedef enum { CLRDATA_METHOD_DEFAULT = 0x00000000, // Method has a 'this' pointer. CLRDATA_METHOD_HAS_THIS = 0x00000001, } CLRDataMethodFlag; typedef enum { CLRDATA_METHDEF_IL } CLRDataMethodDefinitionExtentType; typedef struct { CLRDATA_ADDRESS startAddress; CLRDATA_ADDRESS endAddress; ULONG32 enCVersion; CLRDataMethodDefinitionExtentType type; } CLRDATA_METHDEF_EXTENT; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataMethodDefinition */ [ object, local, uuid(AAF60008-FB2C-420b-8FB1-42D244A54A97) ] interface IXCLRDataMethodDefinition : IUnknown { /* * Get the type this method is part of. */ HRESULT GetTypeDefinition([out] IXCLRDataTypeDefinition **typeDefinition); /* * Enumerate instances of this definition. */ HRESULT StartEnumInstances([in] IXCLRDataAppDomain* appDomain, [out] CLRDATA_ENUM* handle); HRESULT EnumInstance([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataMethodInstance **instance); HRESULT EndEnumInstances([in] CLRDATA_ENUM handle); /* * Get the method's name. */ HRESULT GetName([in] ULONG32 flags, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get the metadata token and scope. */ HRESULT GetTokenAndScope([out] mdMethodDef* token, [out] IXCLRDataModule **mod); /* * Get state flags, defined in CLRDataMethodFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataMethodDefinition* method); /* * Get the latest EnC version of this method. */ HRESULT GetLatestEnCVersion([out] ULONG32* version); /* * Get the IL code regions associated with this method. */ HRESULT StartEnumExtents([out] CLRDATA_ENUM* handle); HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, [out] CLRDATA_METHDEF_EXTENT* extent); HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); /* * Request notification when code is generated or * discarded for the method. */ HRESULT GetCodeNotification([out] ULONG32* flags); HRESULT SetCodeNotification([in] ULONG32 flags); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Gets the most representative start address of * the native code for this method. * A method may have multiple entry points, so this * address is not guaranteed to be hit by all entries. * Requires revision 1. */ HRESULT GetRepresentativeEntryAddress([out] CLRDATA_ADDRESS* addr); HRESULT HasClassOrMethodInstantiation([out] BOOL* bGeneric); } #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataMethodInstance */ [ object, local, uuid(ECD73800-22CA-4b0d-AB55-E9BA7E6318A5) ] interface IXCLRDataMethodInstance : IUnknown { /* * Get the type instance for this method. */ HRESULT GetTypeInstance([out] IXCLRDataTypeInstance **typeInstance); /* * Get the definition that matches this instance. */ HRESULT GetDefinition([out] IXCLRDataMethodDefinition **methodDefinition); /* * Get the metadata token and scope. */ HRESULT GetTokenAndScope([out] mdMethodDef* token, [out] IXCLRDataModule **mod); /* * Get the fully qualified name for this method instance. */ HRESULT GetName([in] ULONG32 flags, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Get state flags, defined in CLRDataMethodFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataMethodInstance* method); /* * Get the EnC version of this instance. */ HRESULT GetEnCVersion([out] ULONG32* version); /* * Enumerate this method's parameterization. */ HRESULT GetNumTypeArguments([out] ULONG32* numTypeArgs); HRESULT GetTypeArgumentByIndex([in] ULONG32 index, [out] IXCLRDataTypeInstance** typeArg); /* * Access the IL <-> address mapping information. */ HRESULT GetILOffsetsByAddress([in] CLRDATA_ADDRESS address, [in] ULONG32 offsetsLen, [out] ULONG32 *offsetsNeeded, [out, size_is(offsetsLen)] ULONG32 ilOffsets[]); HRESULT GetAddressRangesByILOffset([in] ULONG32 ilOffset, [in] ULONG32 rangesLen, [out] ULONG32 *rangesNeeded, [out, size_is(rangesLen)] CLRDATA_ADDRESS_RANGE addressRanges[]); HRESULT GetILAddressMap([in] ULONG32 mapLen, [out] ULONG32 *mapNeeded, [out, size_is(mapLen)] CLRDATA_IL_ADDRESS_MAP maps[]); /* * Get the native code regions associated with this method. */ HRESULT StartEnumExtents([out] CLRDATA_ENUM* handle); HRESULT EnumExtent([in, out] CLRDATA_ENUM* handle, [out] CLRDATA_ADDRESS_RANGE* extent); HRESULT EndEnumExtents([in] CLRDATA_ENUM handle); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Gets the most representative start address of * the native code for this method. * A method may have multiple entry points, so this * address is not guaranteed to be hit by all entries. * Requires revision 1. */ HRESULT GetRepresentativeEntryAddress([out] CLRDATA_ADDRESS* addr); } #pragma warning(pop) typedef enum { CLRDATA_TASK_DEFAULT = 0x00000000, CLRDATA_TASK_WAITING_FOR_GC = 0x00000001, } CLRDataTaskFlag; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataMethodInstance */ /* * Interface representing a task (thread or fiber) in the process. */ [ object, local, uuid(A5B0BEEA-EC62-4618-8012-A24FFC23934C) ] interface IXCLRDataTask : IUnknown { /* * Get the process for this task. */ HRESULT GetProcess([out] IXCLRDataProcess** process); /* * Get the application domain that the task is * currently running in. This can change over time. */ HRESULT GetCurrentAppDomain([out] IXCLRDataAppDomain **appDomain); /* * Get a unique, stable identifier for this task. */ HRESULT GetUniqueID([out] ULONG64* id); /* * Get state flags, defined in CLRDataTaskFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Determine whether the given interface represents * the same target state. */ HRESULT IsSameObject([in] IXCLRDataTask* task); /* * Get the managed object representing the task. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); /* * Mark the task so that it attempts to reach the * given execution state the next time it executes. */ HRESULT GetDesiredExecutionState([out] ULONG32* state); HRESULT SetDesiredExecutionState([in] ULONG32 state); /* * Create a stack walker to walk this task's stack. The * flags parameter takes a bitfield of values from the * CLRDataSimpleFrameType enum. */ HRESULT CreateStackWalk([in] ULONG32 flags, [out] IXCLRDataStackWalk** stackWalk); /* * Get the current OS thread ID for this task. If this task is on a fiber, * the ID may change over time. */ HRESULT GetOSThreadID([out] ULONG32* id); /* * Get the current context for this task, controlled by the given flags. * Returns S_FALSE if the size is not large enough. */ HRESULT GetContext([in] ULONG32 contextFlags, [in] ULONG32 contextBufSize, [out] ULONG32* contextSize, [out, size_is(contextBufSize)] BYTE contextBuf[]); /* * Destructively set the current context for this task. */ HRESULT SetContext([in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE context[]); /* * Get the current exception state for the * task, if any. This may be the first element * in a list of exception states if there are * nested exceptions. */ HRESULT GetCurrentExceptionState([out] IXCLRDataExceptionState **exception); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Get the task's name if it has one. * Requires revision 1. */ HRESULT GetName([in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get the last exception state for the * task, if any. If an exception is currently * being processed the last exception state may * be the same as the current exception state. * Requires revision 2. */ HRESULT GetLastExceptionState([out] IXCLRDataExceptionState **exception); } #pragma warning(pop) typedef enum { /* Frame not recognized */ CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, /* Frame corresponds to a managed method */ CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, /* Frame corresponds to runtime-controlled managed code */ CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE = 0x4, /* Frame corresponds to runtime-controlled unmanaged code */ CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE = 0x8 } CLRDataSimpleFrameType; typedef enum { /* These are tentative values...they will likely change as * implementation progresses. */ CLRDATA_DETFRAME_UNRECOGNIZED, CLRDATA_DETFRAME_UNKNOWN_STUB, CLRDATA_DETFRAME_CLASS_INIT, CLRDATA_DETFRAME_EXCEPTION_FILTER, CLRDATA_DETFRAME_SECURITY, CLRDATA_DETFRAME_CONTEXT_POLICY, CLRDATA_DETFRAME_INTERCEPTION, CLRDATA_DETFRAME_PROCESS_START, CLRDATA_DETFRAME_THREAD_START, CLRDATA_DETFRAME_TRANSITION_TO_MANAGED, CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED, CLRDATA_DETFRAME_COM_INTEROP_STUB, CLRDATA_DETFRAME_DEBUGGER_EVAL, CLRDATA_DETFRAME_CONTEXT_SWITCH, CLRDATA_DETFRAME_FUNC_EVAL, CLRDATA_DETFRAME_FINALLY /* There will be others */ } CLRDataDetailedFrameType; /* * StackWalk requests. */ typedef enum { CLRDATA_STACK_WALK_REQUEST_SET_FIRST_FRAME = 0xe1000000, } CLRDataStackWalkRequest; /* * SetContext flags. */ typedef enum { /* Context being set is the result of stack unwinding. */ CLRDATA_STACK_SET_UNWIND_CONTEXT = 0x00000000, /* Context being set is the "current" context. */ CLRDATA_STACK_SET_CURRENT_CONTEXT = 0x00000001, } CLRDataStackSetContextFlag; /* * Stack-walker interface. */ [ object, local, uuid(E59D8D22-ADA7-49a2-89B5-A415AFCFC95F) ] interface IXCLRDataStackWalk : IUnknown { /* * Get the current context of this stack walk. * This is the original context with any unwinding * applied to it. As unwinding may only restore * a subset of the registers, such as only non-volatile * registers, the context may not exactly match the * register state at the time of the actual call. */ HRESULT GetContext([in] ULONG32 contextFlags, [in] ULONG32 contextBufSize, [out] ULONG32* contextSize, [out, size_is(contextBufSize)] BYTE contextBuf[]); /* * Change the current context of this stack walk, allowing the * debugger to move it to an arbitrary context. Does not actually * alter the current context of the thread whose stack is being walked. * OBSOLETE: Use SetContext2. */ HRESULT SetContext([in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE context[]); /* * Attempt to advance the stack walk to the next frame that * matches the stack walk's filter. If the current frame type is * CLRDATA_UNRECOGNIZED_FRAME, Next() will be unable to * advance. (The debugger will have to walk the unrecognized frame * itself, reset the walk's context, and try again.) * * Upon creation, the stack walk is positioned "before" the first * frame on the stack. Debuggers must call Next() to advance to * the first frame before any other functions will work. The * function will output S_FALSE when there are no more frames that * meet its filter criteria. */ HRESULT Next(); /* * Return the number of bytes skipped by the last call to Next(). * If Next() moved to the very next frame, outputs 0. * * Note that calling GetStackSizeSkipped() after any function other * than Next() has no meaning. */ HRESULT GetStackSizeSkipped([out] ULONG64* stackSizeSkipped); /* * Return information about the type of the current frame */ HRESULT GetFrameType([out] CLRDataSimpleFrameType* simpleType, [out] CLRDataDetailedFrameType* detailedType); /* * Return the current frame, if it is recognized. */ HRESULT GetFrame([out] IXCLRDataFrame** frame); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Change the current context of this stack walk, allowing the * debugger to move it to an arbitrary context. Does not actually * alter the current context of the thread whose stack is being walked. */ HRESULT SetContext2([in] ULONG32 flags, [in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE context[]); } #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataFrame */ [ object, local, uuid(271498C2-4085-4766-BC3A-7F8ED188A173) ] interface IXCLRDataFrame : IUnknown { /* * Return information about the type of this frame. */ HRESULT GetFrameType([out] CLRDataSimpleFrameType* simpleType, [out] CLRDataDetailedFrameType* detailedType); /* * Get the stack walk context as of this frame. * This is the original context with any unwinding * applied to it. As unwinding may only restore * a subset of the registers, such as only non-volatile * registers, the context may not exactly match the * register state at the time of the actual call. */ HRESULT GetContext([in] ULONG32 contextFlags, [in] ULONG32 contextBufSize, [out] ULONG32* contextSize, [out, size_is(contextBufSize)] BYTE contextBuf[]); /* * Return the app domain of this frame */ HRESULT GetAppDomain([out] IXCLRDataAppDomain** appDomain); /* * Return the number of arguments on the stack. */ HRESULT GetNumArguments([out] ULONG32* numArgs); /* * Return an argument by (0-based) index. * The name parameter is filled in if name information is available. */ HRESULT GetArgumentByIndex([in] ULONG32 index, [out] IXCLRDataValue** arg, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Return the number of local variables on the stack. */ HRESULT GetNumLocalVariables([out] ULONG32* numLocals); /* * Return a local variable by (0-based) index. * The name parameter is filled in if name information is available. */ HRESULT GetLocalVariableByIndex([in] ULONG32 index, [out] IXCLRDataValue** localVariable, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR name[]); /* * Get a name for the frame's current instruction pointer. * This is either a method's name or a runtime code name. * * Returns S_FALSE if the buffer is not large enough for the name, * and sets nameLen to be the buffer length needed. */ HRESULT GetCodeName([in] ULONG32 flags, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Gets the method instance corresponding to this frame. */ HRESULT GetMethodInstance([out] IXCLRDataMethodInstance** method); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Enumerate the full parameterization of the frame's * type and method. */ HRESULT GetNumTypeArguments([out] ULONG32* numTypeArgs); HRESULT GetTypeArgumentByIndex([in] ULONG32 index, [out] IXCLRDataTypeInstance** typeArg); } #pragma warning(pop) [ object, local, uuid(1C4D9A4B-702D-4CF6-B290-1DB6F43050D0) ] interface IXCLRDataFrame2 : IUnknown { /* * Retun generic token if available. */ HRESULT GetExactGenericArgsToken([out] IXCLRDataValue** genericToken); } typedef enum { CLRDATA_EXCEPTION_DEFAULT = 0x00000000, // Exception is occurring during processing // of other exception states. CLRDATA_EXCEPTION_NESTED = 0x00000001, // Exception state is not completely available. // This can happen when the state is no longer // active or before a state is fully initialized. CLRDATA_EXCEPTION_PARTIAL = 0x00000002, } CLRDataExceptionStateFlag; typedef enum { CLRDATA_EXBASE_EXCEPTION, CLRDATA_EXBASE_OUT_OF_MEMORY, CLRDATA_EXBASE_INVALID_ARGUMENT, } CLRDataBaseExceptionType; typedef enum { CLRDATA_EXSAME_SECOND_CHANCE = 0x00000000, CLRDATA_EXSAME_FIRST_CHANCE = 0x00000001, } CLRDataExceptionSameFlag; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataExceptionState */ [ object, local, uuid(75DA9E4C-BD33-43C8-8F5C-96E8A5241F57) ] interface IXCLRDataExceptionState : IUnknown { /* * Get state flags, defined in CLRDataExceptionStateFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * For nested exceptions, get the exception that * was being handled when this exception occurred. */ HRESULT GetPrevious([out] IXCLRDataExceptionState** exState); /* * Get the managed object representing the exception. */ HRESULT GetManagedObject([out] IXCLRDataValue** value); /* * Get the standard base type of the exception. */ HRESULT GetBaseType([out] CLRDataBaseExceptionType* type); /* * Get exception information. */ HRESULT GetCode([out] ULONG32* code); HRESULT GetString([in] ULONG32 bufLen, [out] ULONG32 *strLen, [out, size_is(bufLen)] WCHAR str[]); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Determine whether the given interface represents * the same exception state. * OBSOLETE: Use IsSameState2. * Requires revision 1. */ HRESULT IsSameState([in] EXCEPTION_RECORD64* exRecord, [in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE cxRecord[]); /* * Determine whether the given interface represents * the same exception state. * Requires revision 2. */ HRESULT IsSameState2([in] ULONG32 flags, [in] EXCEPTION_RECORD64* exRecord, [in] ULONG32 contextSize, [in, size_is(contextSize)] BYTE cxRecord[]); /* * Gets the task this exception state is associated with. * Requires revision 2. */ HRESULT GetTask([out] IXCLRDataTask** task); } #pragma warning(pop) typedef enum { CLRDATA_VLOC_MEMORY = 0x00000000, CLRDATA_VLOC_REGISTER = 0x00000001, } ClrDataValueLocationFlag; #pragma warning(push) #pragma warning(disable:28718) /* suppress warning 28718 for interface IXCLRDataValue */ /* * Object inspection interface. */ [ object, local, uuid(96EC93C7-1000-4e93-8991-98D8766E6666) ] interface IXCLRDataValue : IUnknown { /* * Get state flags, defined in CLRDataValueFlag. */ HRESULT GetFlags([out] ULONG32* flags); /* * Get the address of the object. * Fails unless the object is a single contiguous * piece of data in memory. * OBSOLETE: Use GetLocation instead. */ HRESULT GetAddress([out] CLRDATA_ADDRESS* address); /* * Return the size (in bytes) of the object. */ HRESULT GetSize([out] ULONG64* size); /* * Copy between an object and a buffer. * Returns S_FALSE if the buffer was not at least as large * as the object. */ HRESULT GetBytes([in] ULONG32 bufLen, [out] ULONG32 *dataSize, [out, size_is(bufLen)] BYTE buffer[]); HRESULT SetBytes([in] ULONG32 bufLen, [out] ULONG32 *dataSize, [in, size_is(bufLen)] BYTE buffer[]); /* * Get the type of the object */ HRESULT GetType([out] IXCLRDataTypeInstance **typeInstance); /* * Get the number of fields in the object. * OBSOLETE: Use GetNumFields2. */ HRESULT GetNumFields([out] ULONG32 *numFields); /* * Gets one field of the object. * * Because field ordering is not fixed, can also return name * information and/or the metadata token, if the caller passes in * appropriate values. * OBSOLETE: Use EnumField. */ HRESULT GetFieldByIndex([in] ULONG32 index, [out] IXCLRDataValue **field, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[], [out] mdFieldDef* token); HRESULT Request([in] ULONG32 reqCode, [in] ULONG32 inBufferSize, [in, size_is(inBufferSize)] BYTE* inBuffer, [in] ULONG32 outBufferSize, [out, size_is(outBufferSize)] BYTE* outBuffer); /* * Get the number of fields in the value. * If a type is passed in only fields defined * by that type are enumerated. */ HRESULT GetNumFields2([in] ULONG32 flags, [in] IXCLRDataTypeInstance* fromType, [out] ULONG32* numFields); /* * Enumerate the fields for this value. * If a type is passed in only fields defined * by that type are enumerated. */ HRESULT StartEnumFields([in] ULONG32 flags, [in] IXCLRDataTypeInstance* fromType, [out] CLRDATA_ENUM* handle); HRESULT EnumField([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** field, [in] ULONG32 nameBufLen, [out] ULONG32* nameLen, [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] mdFieldDef* token); HRESULT EndEnumFields([in] CLRDATA_ENUM handle); HRESULT StartEnumFieldsByName([in] LPCWSTR name, [in] ULONG32 nameFlags, [in] ULONG32 fieldFlags, [in] IXCLRDataTypeInstance* fromType, [out] CLRDATA_ENUM* handle); HRESULT EnumFieldByName([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** field, [out] mdFieldDef* token); HRESULT EndEnumFieldsByName([in] CLRDATA_ENUM handle); /* * Retrieve a field by field metadata token. */ HRESULT GetFieldByToken([in] mdFieldDef token, [out] IXCLRDataValue **field, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Get the value implicitly associated with this value. * For pointers or reference values this is the value * pointed/referred to. * For boxed values this is the contained value. * For other values there is no associated value. */ HRESULT GetAssociatedValue([out] IXCLRDataValue** assocValue); /* * Get the type implicitly associated with this value. * For pointers or reference types this is the type * pointed/referred to. * For boxed values this is the type of the contained value. * For arrays this is the element type. * For other values there is no associated type. */ HRESULT GetAssociatedType([out] IXCLRDataTypeInstance** assocType); /* * String methods that only work for string data values. */ /* * Return the length and contents of the string. */ HRESULT GetString([in] ULONG32 bufLen, [out] ULONG32 *strLen, [out, size_is(bufLen)] WCHAR str[]); /* * Array methods that only work for array data values. */ /* * Return the definition of the array. */ HRESULT GetArrayProperties([out] ULONG32 *rank, [out] ULONG32 *totalElements, [in] ULONG32 numDim, [out, size_is(numDim)] ULONG32 dims[], [in] ULONG32 numBases, [out, size_is(numBases)] LONG32 bases[]); /* * Return a value representing the given element in the array. */ HRESULT GetArrayElement([in] ULONG32 numInd, [in, size_is(numInd)] LONG32 indices[], [out] IXCLRDataValue **value); HRESULT EnumField2([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** field, [in] ULONG32 nameBufLen, [out] ULONG32* nameLen, [out, size_is(nameBufLen)] WCHAR nameBuf[], [out] IXCLRDataModule** tokenScope, [out] mdFieldDef* token); HRESULT EnumFieldByName2([in, out] CLRDATA_ENUM* handle, [out] IXCLRDataValue** field, [out] IXCLRDataModule** tokenScope, [out] mdFieldDef* token); HRESULT GetFieldByToken2([in] IXCLRDataModule* tokenScope, [in] mdFieldDef token, [out] IXCLRDataValue **field, [in] ULONG32 bufLen, [out] ULONG32 *nameLen, [out, size_is(bufLen)] WCHAR nameBuf[]); /* * Returns the locations the value's * data is spread across. * Placeholder values, such as values for variables * which are dead, may not have any locations. * Memory locations return the memory address in arg. * Register locations do not return an indication * of which register. * Requires revision 3. */ HRESULT GetNumLocations([out] ULONG32* numLocs); HRESULT GetLocationByIndex([in] ULONG32 loc, [out] ULONG32* flags, [out] CLRDATA_ADDRESS* arg); } #pragma warning(pop) [ object, local, uuid(2D95A079-42A1-4837-818F-0B97D7048E0E) ] interface IXCLRDataExceptionNotification : IUnknown { /* * New code was generated or discarded for a method. */ HRESULT OnCodeGenerated([in] IXCLRDataMethodInstance* method); HRESULT OnCodeDiscarded([in] IXCLRDataMethodInstance* method); /* * The process or task reached the desired execution state. */ HRESULT OnProcessExecution([in] ULONG32 state); HRESULT OnTaskExecution([in] IXCLRDataTask* task, [in] ULONG32 state); /* * The given module was loaded or unloaded. */ HRESULT OnModuleLoaded([in] IXCLRDataModule* mod); HRESULT OnModuleUnloaded([in] IXCLRDataModule* mod); /* * The given type was loaded or unloaded. */ HRESULT OnTypeLoaded([in] IXCLRDataTypeInstance* typeInst); HRESULT OnTypeUnloaded([in] IXCLRDataTypeInstance* typeInst); } [ object, local, uuid(31201a94-4337-49b7-aef7-0c755054091f) ] interface IXCLRDataExceptionNotification2 : IXCLRDataExceptionNotification { /* * The given app domain was loaded or unloaded. */ HRESULT OnAppDomainLoaded([in] IXCLRDataAppDomain* domain); HRESULT OnAppDomainUnloaded([in] IXCLRDataAppDomain* domain); /* * A managed exception has been raised. */ HRESULT OnException([in] IXCLRDataExceptionState* exception); } [ object, local, uuid(31201a94-4337-49b7-aef7-0c7550540920) ] interface IXCLRDataExceptionNotification3 : IXCLRDataExceptionNotification2 { /* * The specified GC event was triggered. The GC event is passed in an * opaque structure, whose structure is given by buffSize */ HRESULT OnGcEvent([in] GcEvtArgs gcEvtArgs); } [ object, local, uuid(C25E926E-5F09-4AA2-BBAD-B7FC7F10CFD7) ] interface IXCLRDataExceptionNotification4 : IXCLRDataExceptionNotification3 { /* * A managed catch clause is about to be executed */ HRESULT ExceptionCatcherEnter([in] IXCLRDataMethodInstance* catchingMethod, DWORD catcherNativeOffset); } [ object, local, uuid(e77a39ea-3548-44d9-b171-8569ed1a9423) ] interface IXCLRDataExceptionNotification5 : IXCLRDataExceptionNotification4 { /* * New code was generated for a method. The given address is the start address of * the native newly jitted code. */ HRESULT OnCodeGenerated2([in] IXCLRDataMethodInstance* method, [in] CLRDATA_ADDRESS nativeCodeLocation); } ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/xcordebug.idl ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************** ** ** ** XCordebug.idl - Experimental (undocumented) Debugging interfaces. ** ** ** *****************************************************************************/ /* ------------------------------------------------------------------------- * * Imported types * ------------------------------------------------------------------------- */ import "cordebug.idl"; // @dbgtodo : proper API docs here. // - include failure semantics of Filter. What does failure mean? // /* Comments to add to ICorDebugDataTarget docs: * Whenever the target process changes, the debugger client must * call ICorDebugProcess4::ProcessStateChanged before issuing any other * ICorDebug API calls. */ [ object, local, uuid(E930C679-78AF-4953-8AB7-B0AABF0F9F80), pointer_default(unique) ] interface ICorDebugProcess4 : IUnknown { /* * Process native debug events. */ HRESULT Filter( [in, length_is(countBytes), size_is(countBytes)] const BYTE pRecord[], [in] DWORD countBytes, [in] CorDebugRecordFormat format, [in] DWORD dwFlags, [in] DWORD dwThreadId, [in] ICorDebugManagedCallback * pCallback, [in, out] CORDB_CONTINUE_STATUS * pContinueStatus); /* * Debugger calls this to notify ICorDebug that the process is running. * * Notes: * ProcessStateChanged(PROCESS_RUNNING) has similar semantics to ICorDebugProcess::Continue(); */ HRESULT ProcessStateChanged([in] CorDebugStateChange eChange); }; ================================================ FILE: src/ManagedProfiler/external/coreclr/inc/yieldprocessornormalized.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #pragma once // Undefine YieldProcessor to encourage using the normalized versions below instead. System_YieldProcessor() can be used where // the intention is to use the system-default implementation of YieldProcessor(). #define HAS_SYSTEM_YIELDPROCESSOR FORCEINLINE void System_YieldProcessor() { YieldProcessor(); } #ifdef YieldProcessor #undef YieldProcessor #endif #define YieldProcessor Dont_Use_YieldProcessor #define DISABLE_COPY(T) \ T(const T &) = delete; \ T &operator =(const T &) = delete #define DISABLE_CONSTRUCT_COPY(T) \ T() = delete; \ DISABLE_COPY(T) class YieldProcessorNormalization { public: static const unsigned int TargetNsPerNormalizedYield = 37; static const unsigned int TargetMaxNsPerSpinIteration = 272; // These are maximums for the computed values for normalization based their calculation static const unsigned int MaxYieldsPerNormalizedYield = TargetNsPerNormalizedYield * 10; static const unsigned int MaxOptimalMaxNormalizedYieldsPerSpinIteration = TargetMaxNsPerSpinIteration * 3 / (TargetNsPerNormalizedYield * 2) + 1; private: static bool s_isMeasurementScheduled; static unsigned int s_yieldsPerNormalizedYield; static unsigned int s_optimalMaxNormalizedYieldsPerSpinIteration; public: static bool IsMeasurementScheduled() { return s_isMeasurementScheduled; } static void PerformMeasurement(); private: static void ScheduleMeasurementIfNecessary(); public: static unsigned int GetOptimalMaxNormalizedYieldsPerSpinIteration() { return s_optimalMaxNormalizedYieldsPerSpinIteration; } static void FireMeasurementEvents(); private: static double AtomicLoad(double *valueRef); static void AtomicStore(double *valueRef, double value); DISABLE_CONSTRUCT_COPY(YieldProcessorNormalization); friend class YieldProcessorNormalizationInfo; friend void YieldProcessorNormalizedForPreSkylakeCount(unsigned int); }; class YieldProcessorNormalizationInfo { private: unsigned int yieldsPerNormalizedYield; unsigned int optimalMaxNormalizedYieldsPerSpinIteration; unsigned int optimalMaxYieldsPerSpinIteration; public: YieldProcessorNormalizationInfo() : yieldsPerNormalizedYield(YieldProcessorNormalization::s_yieldsPerNormalizedYield), optimalMaxNormalizedYieldsPerSpinIteration(YieldProcessorNormalization::s_optimalMaxNormalizedYieldsPerSpinIteration), optimalMaxYieldsPerSpinIteration(yieldsPerNormalizedYield * optimalMaxNormalizedYieldsPerSpinIteration) { YieldProcessorNormalization::ScheduleMeasurementIfNecessary(); } DISABLE_COPY(YieldProcessorNormalizationInfo); friend void YieldProcessorNormalized(const YieldProcessorNormalizationInfo &); friend void YieldProcessorNormalized(const YieldProcessorNormalizationInfo &, unsigned int); friend void YieldProcessorNormalizedForPreSkylakeCount(const YieldProcessorNormalizationInfo &, unsigned int); friend void YieldProcessorWithBackOffNormalized(const YieldProcessorNormalizationInfo &, unsigned int); }; // See YieldProcessorNormalized() for preliminary info. Typical usage: // if (!condition) // { // YieldProcessorNormalizationInfo normalizationInfo; // do // { // YieldProcessorNormalized(normalizationInfo); // } while (!condition); // } FORCEINLINE void YieldProcessorNormalized(const YieldProcessorNormalizationInfo &normalizationInfo) { unsigned int n = normalizationInfo.yieldsPerNormalizedYield; _ASSERTE(n != 0); do { System_YieldProcessor(); } while (--n != 0); } // Delays execution of the current thread for a short duration. Unlike YieldProcessor(), an effort is made to normalize the // delay across processors. The actual delay may be meaningful in several ways, including but not limited to the following: // - The delay should be long enough that a tiny spin-wait like the following has a decent likelihood of observing a new value // for the condition (when changed by a different thread) on each iteration, otherwise it may unnecessary increase CPU usage // and decrease scalability of the operation. // while(!condition) // { // YieldProcessorNormalized(); // } // - The delay should be short enough that a tiny spin-wait like above would not miss multiple cross-thread changes to the // condition, otherwise it may unnecessarily increase latency of the operation // - In reasonably short spin-waits, the actual delay may not matter much. In unreasonably long spin-waits that progress in // yield count per iteration for each failed check of the condition, the progression can significantly magnify the second // issue above on later iterations. // - This function and variants are intended to provide a decent balance between the above issues, as ideal solutions to each // issue have trade-offs between them. If latency of the operation is far more important in the scenario, consider using // System_YieldProcessor() instead, which would issue a delay that is typically <= the delay issued by this method. FORCEINLINE void YieldProcessorNormalized() { YieldProcessorNormalized(YieldProcessorNormalizationInfo()); } // See YieldProcessorNormalized(count) for preliminary info. Typical usage: // if (!moreExpensiveCondition) // { // YieldProcessorNormalizationInfo normalizationInfo; // do // { // YieldProcessorNormalized(normalizationInfo, 2); // } while (!moreExpensiveCondition); // } FORCEINLINE void YieldProcessorNormalized(const YieldProcessorNormalizationInfo &normalizationInfo, unsigned int count) { _ASSERTE(count != 0); if (sizeof(SIZE_T) <= sizeof(unsigned int)) { // On platforms with a small SIZE_T, prevent overflow on the multiply below const unsigned int MaxCount = UINT_MAX / YieldProcessorNormalization::MaxYieldsPerNormalizedYield; if (count > MaxCount) { count = MaxCount; } } SIZE_T n = (SIZE_T)count * normalizationInfo.yieldsPerNormalizedYield; _ASSERTE(n != 0); do { System_YieldProcessor(); } while (--n != 0); } // See YieldProcessorNormalized() for preliminary info. This function repeats the delay 'count' times. This overload is // preferred over the single-count overload when multiple yields are desired per spin-wait iteration. Typical usage: // while(!moreExpensiveCondition) // { // YieldProcessorNormalized(2); // } FORCEINLINE void YieldProcessorNormalized(unsigned int count) { YieldProcessorNormalized(YieldProcessorNormalizationInfo(), count); } // Please DO NOT use this function in new code! See YieldProcessorNormalizedForPreSkylakeCount(preSkylakeCount) for preliminary // info. Typical usage: // if (!condition) // { // YieldProcessorNormalizationInfo normalizationInfo; // do // { // YieldProcessorNormalizedForPreSkylakeCount(normalizationInfo, 100); // } while (!condition); // } FORCEINLINE void YieldProcessorNormalizedForPreSkylakeCount( const YieldProcessorNormalizationInfo &normalizationInfo, unsigned int preSkylakeCount) { _ASSERTE(preSkylakeCount != 0); if (sizeof(SIZE_T) <= sizeof(unsigned int)) { // On platforms with a small SIZE_T, prevent overflow on the multiply below const unsigned int MaxCount = UINT_MAX / YieldProcessorNormalization::MaxYieldsPerNormalizedYield; if (preSkylakeCount > MaxCount) { preSkylakeCount = MaxCount; } } const unsigned int PreSkylakeCountToSkylakeCountDivisor = 8; SIZE_T n = (SIZE_T)preSkylakeCount * normalizationInfo.yieldsPerNormalizedYield / PreSkylakeCountToSkylakeCountDivisor; if (n == 0) { n = 1; } do { System_YieldProcessor(); } while (--n != 0); } // Please DO NOT use this function in new code! This function is to be used for old spin-wait loops that have not been retuned // for recent processors, and especially where the yield count may be unreasonably high. The function scales the yield count in // an attempt to normalize the total delay across processors, to approximately the total delay that would be issued on a // pre-Skylake processor. New code should be tuned with YieldProcessorNormalized() or variants instead. Typical usage: // while(!condition) // { // YieldProcessorNormalizedForPreSkylakeCount(100); // } FORCEINLINE void YieldProcessorNormalizedForPreSkylakeCount(unsigned int preSkylakeCount) { // This function does not forward to the one above because it is used by some code under utilcode, where // YieldProcessorNormalizationInfo cannot be used since normalization does not happen in some of its consumers. So this // version uses the fields in YieldProcessorNormalization directly. _ASSERTE(preSkylakeCount != 0); if (sizeof(SIZE_T) <= sizeof(unsigned int)) { // On platforms with a small SIZE_T, prevent overflow on the multiply below const unsigned int MaxCount = UINT_MAX / YieldProcessorNormalization::MaxYieldsPerNormalizedYield; if (preSkylakeCount > MaxCount) { preSkylakeCount = MaxCount; } } const unsigned int PreSkylakeCountToSkylakeCountDivisor = 8; SIZE_T n = (SIZE_T)preSkylakeCount * YieldProcessorNormalization::s_yieldsPerNormalizedYield / PreSkylakeCountToSkylakeCountDivisor; if (n == 0) { n = 1; } do { System_YieldProcessor(); } while (--n != 0); } // See YieldProcessorNormalized() for preliminary info. This function is to be used when there is a decent possibility that the // condition would not be satisfied within a short duration. The current implementation increases the delay per spin-wait // iteration exponentially up to a limit. Typical usage: // if (!conditionThatMayNotBeSatisfiedSoon) // { // YieldProcessorNormalizationInfo normalizationInfo; // do // { // YieldProcessorWithBackOffNormalized(normalizationInfo); // maybe Sleep(0) occasionally // } while (!conditionThatMayNotBeSatisfiedSoon); // } FORCEINLINE void YieldProcessorWithBackOffNormalized( const YieldProcessorNormalizationInfo &normalizationInfo, unsigned int spinIteration) { // This shift value should be adjusted based on the asserted conditions below const UINT8 MaxShift = 3; static_assert_no_msg( ((unsigned int)1 << MaxShift) <= YieldProcessorNormalization::MaxOptimalMaxNormalizedYieldsPerSpinIteration); static_assert_no_msg( ((unsigned int)1 << (MaxShift + 1)) > YieldProcessorNormalization::MaxOptimalMaxNormalizedYieldsPerSpinIteration); unsigned int n; if (spinIteration <= MaxShift && ((unsigned int)1 << spinIteration) < normalizationInfo.optimalMaxNormalizedYieldsPerSpinIteration) { n = ((unsigned int)1 << spinIteration) * normalizationInfo.yieldsPerNormalizedYield; } else { n = normalizationInfo.optimalMaxYieldsPerSpinIteration; } _ASSERTE(n != 0); do { System_YieldProcessor(); } while (--n != 0); } #undef DISABLE_CONSTRUCT_COPY #undef DISABLE_COPY ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/clrdata.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0626 */ /* Compiler settings for clrdata.idl: Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0626 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __clrdata_h__ #define __clrdata_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif #ifndef DECLSPEC_XFGVIRT #if _CONTROL_FLOW_GUARD_XFG #define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func)) #else #define DECLSPEC_XFGVIRT(base, func) #endif #endif /* Forward Declarations */ #ifndef __ICLRDataTarget_FWD_DEFINED__ #define __ICLRDataTarget_FWD_DEFINED__ typedef interface ICLRDataTarget ICLRDataTarget; #endif /* __ICLRDataTarget_FWD_DEFINED__ */ #ifndef __ICLRDataTarget2_FWD_DEFINED__ #define __ICLRDataTarget2_FWD_DEFINED__ typedef interface ICLRDataTarget2 ICLRDataTarget2; #endif /* __ICLRDataTarget2_FWD_DEFINED__ */ #ifndef __ICLRDataTarget3_FWD_DEFINED__ #define __ICLRDataTarget3_FWD_DEFINED__ typedef interface ICLRDataTarget3 ICLRDataTarget3; #endif /* __ICLRDataTarget3_FWD_DEFINED__ */ #ifndef __ICLRRuntimeLocator_FWD_DEFINED__ #define __ICLRRuntimeLocator_FWD_DEFINED__ typedef interface ICLRRuntimeLocator ICLRRuntimeLocator; #endif /* __ICLRRuntimeLocator_FWD_DEFINED__ */ #ifndef __ICLRMetadataLocator_FWD_DEFINED__ #define __ICLRMetadataLocator_FWD_DEFINED__ typedef interface ICLRMetadataLocator ICLRMetadataLocator; #endif /* __ICLRMetadataLocator_FWD_DEFINED__ */ #ifndef __ICLRDataEnumMemoryRegionsCallback_FWD_DEFINED__ #define __ICLRDataEnumMemoryRegionsCallback_FWD_DEFINED__ typedef interface ICLRDataEnumMemoryRegionsCallback ICLRDataEnumMemoryRegionsCallback; #endif /* __ICLRDataEnumMemoryRegionsCallback_FWD_DEFINED__ */ #ifndef __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ #define __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ typedef interface ICLRDataEnumMemoryRegionsCallback2 ICLRDataEnumMemoryRegionsCallback2; #endif /* __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ */ #ifndef __ICLRDataLoggingCallback_FWD_DEFINED__ #define __ICLRDataLoggingCallback_FWD_DEFINED__ typedef interface ICLRDataLoggingCallback ICLRDataLoggingCallback; #endif /* __ICLRDataLoggingCallback_FWD_DEFINED__ */ #ifndef __ICLRDataEnumMemoryRegions_FWD_DEFINED__ #define __ICLRDataEnumMemoryRegions_FWD_DEFINED__ typedef interface ICLRDataEnumMemoryRegions ICLRDataEnumMemoryRegions; #endif /* __ICLRDataEnumMemoryRegions_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_clrdata_0000_0000 */ /* [local] */ typedef ULONG64 CLRDATA_ADDRESS; STDAPI CLRDataCreateInstance(REFIID iid, ICLRDataTarget* target, void** iface); typedef HRESULT (STDAPICALLTYPE* PFN_CLRDataCreateInstance)(REFIID iid, ICLRDataTarget* target, void** iface); extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0000_v0_0_s_ifspec; #ifndef __ICLRDataTarget_INTERFACE_DEFINED__ #define __ICLRDataTarget_INTERFACE_DEFINED__ /* interface ICLRDataTarget */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICLRDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3E11CCEE-D08B-43e5-AF01-32717A64DA03") ICLRDataTarget : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetMachineType( /* [out] */ ULONG32 *machineType) = 0; virtual HRESULT STDMETHODCALLTYPE GetPointerSize( /* [out] */ ULONG32 *pointerSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetImageBase( /* [string][in] */ LPCWSTR imagePath, /* [out] */ CLRDATA_ADDRESS *baseAddress) = 0; virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesRead) = 0; virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesWritten) = 0; virtual HRESULT STDMETHODCALLTYPE GetTLSValue( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS *value) = 0; virtual HRESULT STDMETHODCALLTYPE SetTLSValue( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( /* [out] */ ULONG32 *threadID) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *context) = 0; virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE *context) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; }; #else /* C style interface */ typedef struct ICLRDataTargetVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataTarget * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataTarget * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataTarget * This); DECLSPEC_XFGVIRT(ICLRDataTarget, GetMachineType) HRESULT ( STDMETHODCALLTYPE *GetMachineType )( ICLRDataTarget * This, /* [out] */ ULONG32 *machineType); DECLSPEC_XFGVIRT(ICLRDataTarget, GetPointerSize) HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( ICLRDataTarget * This, /* [out] */ ULONG32 *pointerSize); DECLSPEC_XFGVIRT(ICLRDataTarget, GetImageBase) HRESULT ( STDMETHODCALLTYPE *GetImageBase )( ICLRDataTarget * This, /* [string][in] */ LPCWSTR imagePath, /* [out] */ CLRDATA_ADDRESS *baseAddress); DECLSPEC_XFGVIRT(ICLRDataTarget, ReadVirtual) HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICLRDataTarget * This, /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesRead); DECLSPEC_XFGVIRT(ICLRDataTarget, WriteVirtual) HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( ICLRDataTarget * This, /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesWritten); DECLSPEC_XFGVIRT(ICLRDataTarget, GetTLSValue) HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( ICLRDataTarget * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS *value); DECLSPEC_XFGVIRT(ICLRDataTarget, SetTLSValue) HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( ICLRDataTarget * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value); DECLSPEC_XFGVIRT(ICLRDataTarget, GetCurrentThreadID) HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICLRDataTarget * This, /* [out] */ ULONG32 *threadID); DECLSPEC_XFGVIRT(ICLRDataTarget, GetThreadContext) HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICLRDataTarget * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *context); DECLSPEC_XFGVIRT(ICLRDataTarget, SetThreadContext) HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICLRDataTarget * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE *context); DECLSPEC_XFGVIRT(ICLRDataTarget, Request) HRESULT ( STDMETHODCALLTYPE *Request )( ICLRDataTarget * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); END_INTERFACE } ICLRDataTargetVtbl; interface ICLRDataTarget { CONST_VTBL struct ICLRDataTargetVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataTarget_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataTarget_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataTarget_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataTarget_GetMachineType(This,machineType) \ ( (This)->lpVtbl -> GetMachineType(This,machineType) ) #define ICLRDataTarget_GetPointerSize(This,pointerSize) \ ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) #define ICLRDataTarget_GetImageBase(This,imagePath,baseAddress) \ ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) #define ICLRDataTarget_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) #define ICLRDataTarget_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) #define ICLRDataTarget_GetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) #define ICLRDataTarget_SetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) #define ICLRDataTarget_GetCurrentThreadID(This,threadID) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) #define ICLRDataTarget_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) #define ICLRDataTarget_SetThreadContext(This,threadID,contextSize,context) \ ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define ICLRDataTarget_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataTarget_INTERFACE_DEFINED__ */ #ifndef __ICLRDataTarget2_INTERFACE_DEFINED__ #define __ICLRDataTarget2_INTERFACE_DEFINED__ /* interface ICLRDataTarget2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICLRDataTarget2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("6d05fae3-189c-4630-a6dc-1c251e1c01ab") ICLRDataTarget2 : public ICLRDataTarget { public: virtual HRESULT STDMETHODCALLTYPE AllocVirtual( /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags, /* [in] */ ULONG32 protectFlags, /* [out] */ CLRDATA_ADDRESS *virt) = 0; virtual HRESULT STDMETHODCALLTYPE FreeVirtual( /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags) = 0; }; #else /* C style interface */ typedef struct ICLRDataTarget2Vtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataTarget2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataTarget2 * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataTarget2 * This); DECLSPEC_XFGVIRT(ICLRDataTarget, GetMachineType) HRESULT ( STDMETHODCALLTYPE *GetMachineType )( ICLRDataTarget2 * This, /* [out] */ ULONG32 *machineType); DECLSPEC_XFGVIRT(ICLRDataTarget, GetPointerSize) HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( ICLRDataTarget2 * This, /* [out] */ ULONG32 *pointerSize); DECLSPEC_XFGVIRT(ICLRDataTarget, GetImageBase) HRESULT ( STDMETHODCALLTYPE *GetImageBase )( ICLRDataTarget2 * This, /* [string][in] */ LPCWSTR imagePath, /* [out] */ CLRDATA_ADDRESS *baseAddress); DECLSPEC_XFGVIRT(ICLRDataTarget, ReadVirtual) HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICLRDataTarget2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesRead); DECLSPEC_XFGVIRT(ICLRDataTarget, WriteVirtual) HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( ICLRDataTarget2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesWritten); DECLSPEC_XFGVIRT(ICLRDataTarget, GetTLSValue) HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( ICLRDataTarget2 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS *value); DECLSPEC_XFGVIRT(ICLRDataTarget, SetTLSValue) HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( ICLRDataTarget2 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value); DECLSPEC_XFGVIRT(ICLRDataTarget, GetCurrentThreadID) HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICLRDataTarget2 * This, /* [out] */ ULONG32 *threadID); DECLSPEC_XFGVIRT(ICLRDataTarget, GetThreadContext) HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICLRDataTarget2 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *context); DECLSPEC_XFGVIRT(ICLRDataTarget, SetThreadContext) HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICLRDataTarget2 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE *context); DECLSPEC_XFGVIRT(ICLRDataTarget, Request) HRESULT ( STDMETHODCALLTYPE *Request )( ICLRDataTarget2 * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); DECLSPEC_XFGVIRT(ICLRDataTarget2, AllocVirtual) HRESULT ( STDMETHODCALLTYPE *AllocVirtual )( ICLRDataTarget2 * This, /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags, /* [in] */ ULONG32 protectFlags, /* [out] */ CLRDATA_ADDRESS *virt); DECLSPEC_XFGVIRT(ICLRDataTarget2, FreeVirtual) HRESULT ( STDMETHODCALLTYPE *FreeVirtual )( ICLRDataTarget2 * This, /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags); END_INTERFACE } ICLRDataTarget2Vtbl; interface ICLRDataTarget2 { CONST_VTBL struct ICLRDataTarget2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataTarget2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataTarget2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataTarget2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataTarget2_GetMachineType(This,machineType) \ ( (This)->lpVtbl -> GetMachineType(This,machineType) ) #define ICLRDataTarget2_GetPointerSize(This,pointerSize) \ ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) #define ICLRDataTarget2_GetImageBase(This,imagePath,baseAddress) \ ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) #define ICLRDataTarget2_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) #define ICLRDataTarget2_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) #define ICLRDataTarget2_GetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) #define ICLRDataTarget2_SetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) #define ICLRDataTarget2_GetCurrentThreadID(This,threadID) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) #define ICLRDataTarget2_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) #define ICLRDataTarget2_SetThreadContext(This,threadID,contextSize,context) \ ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define ICLRDataTarget2_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define ICLRDataTarget2_AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) \ ( (This)->lpVtbl -> AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) ) #define ICLRDataTarget2_FreeVirtual(This,addr,size,typeFlags) \ ( (This)->lpVtbl -> FreeVirtual(This,addr,size,typeFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataTarget2_INTERFACE_DEFINED__ */ #ifndef __ICLRDataTarget3_INTERFACE_DEFINED__ #define __ICLRDataTarget3_INTERFACE_DEFINED__ /* interface ICLRDataTarget3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICLRDataTarget3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("a5664f95-0af4-4a1b-960e-2f3346b4214c") ICLRDataTarget3 : public ICLRDataTarget2 { public: virtual HRESULT STDMETHODCALLTYPE GetExceptionRecord( /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *bufferUsed, /* [size_is][out] */ BYTE *buffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetExceptionContextRecord( /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *bufferUsed, /* [size_is][out] */ BYTE *buffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetExceptionThreadID( /* [out] */ ULONG32 *threadID) = 0; }; #else /* C style interface */ typedef struct ICLRDataTarget3Vtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataTarget3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataTarget3 * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataTarget3 * This); DECLSPEC_XFGVIRT(ICLRDataTarget, GetMachineType) HRESULT ( STDMETHODCALLTYPE *GetMachineType )( ICLRDataTarget3 * This, /* [out] */ ULONG32 *machineType); DECLSPEC_XFGVIRT(ICLRDataTarget, GetPointerSize) HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( ICLRDataTarget3 * This, /* [out] */ ULONG32 *pointerSize); DECLSPEC_XFGVIRT(ICLRDataTarget, GetImageBase) HRESULT ( STDMETHODCALLTYPE *GetImageBase )( ICLRDataTarget3 * This, /* [string][in] */ LPCWSTR imagePath, /* [out] */ CLRDATA_ADDRESS *baseAddress); DECLSPEC_XFGVIRT(ICLRDataTarget, ReadVirtual) HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesRead); DECLSPEC_XFGVIRT(ICLRDataTarget, WriteVirtual) HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( ICLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesWritten); DECLSPEC_XFGVIRT(ICLRDataTarget, GetTLSValue) HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( ICLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS *value); DECLSPEC_XFGVIRT(ICLRDataTarget, SetTLSValue) HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( ICLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value); DECLSPEC_XFGVIRT(ICLRDataTarget, GetCurrentThreadID) HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICLRDataTarget3 * This, /* [out] */ ULONG32 *threadID); DECLSPEC_XFGVIRT(ICLRDataTarget, GetThreadContext) HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *context); DECLSPEC_XFGVIRT(ICLRDataTarget, SetThreadContext) HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE *context); DECLSPEC_XFGVIRT(ICLRDataTarget, Request) HRESULT ( STDMETHODCALLTYPE *Request )( ICLRDataTarget3 * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); DECLSPEC_XFGVIRT(ICLRDataTarget2, AllocVirtual) HRESULT ( STDMETHODCALLTYPE *AllocVirtual )( ICLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags, /* [in] */ ULONG32 protectFlags, /* [out] */ CLRDATA_ADDRESS *virt); DECLSPEC_XFGVIRT(ICLRDataTarget2, FreeVirtual) HRESULT ( STDMETHODCALLTYPE *FreeVirtual )( ICLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags); DECLSPEC_XFGVIRT(ICLRDataTarget3, GetExceptionRecord) HRESULT ( STDMETHODCALLTYPE *GetExceptionRecord )( ICLRDataTarget3 * This, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *bufferUsed, /* [size_is][out] */ BYTE *buffer); DECLSPEC_XFGVIRT(ICLRDataTarget3, GetExceptionContextRecord) HRESULT ( STDMETHODCALLTYPE *GetExceptionContextRecord )( ICLRDataTarget3 * This, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *bufferUsed, /* [size_is][out] */ BYTE *buffer); DECLSPEC_XFGVIRT(ICLRDataTarget3, GetExceptionThreadID) HRESULT ( STDMETHODCALLTYPE *GetExceptionThreadID )( ICLRDataTarget3 * This, /* [out] */ ULONG32 *threadID); END_INTERFACE } ICLRDataTarget3Vtbl; interface ICLRDataTarget3 { CONST_VTBL struct ICLRDataTarget3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataTarget3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataTarget3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataTarget3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataTarget3_GetMachineType(This,machineType) \ ( (This)->lpVtbl -> GetMachineType(This,machineType) ) #define ICLRDataTarget3_GetPointerSize(This,pointerSize) \ ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) #define ICLRDataTarget3_GetImageBase(This,imagePath,baseAddress) \ ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) #define ICLRDataTarget3_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) #define ICLRDataTarget3_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) #define ICLRDataTarget3_GetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) #define ICLRDataTarget3_SetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) #define ICLRDataTarget3_GetCurrentThreadID(This,threadID) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) #define ICLRDataTarget3_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) #define ICLRDataTarget3_SetThreadContext(This,threadID,contextSize,context) \ ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define ICLRDataTarget3_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define ICLRDataTarget3_AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) \ ( (This)->lpVtbl -> AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) ) #define ICLRDataTarget3_FreeVirtual(This,addr,size,typeFlags) \ ( (This)->lpVtbl -> FreeVirtual(This,addr,size,typeFlags) ) #define ICLRDataTarget3_GetExceptionRecord(This,bufferSize,bufferUsed,buffer) \ ( (This)->lpVtbl -> GetExceptionRecord(This,bufferSize,bufferUsed,buffer) ) #define ICLRDataTarget3_GetExceptionContextRecord(This,bufferSize,bufferUsed,buffer) \ ( (This)->lpVtbl -> GetExceptionContextRecord(This,bufferSize,bufferUsed,buffer) ) #define ICLRDataTarget3_GetExceptionThreadID(This,threadID) \ ( (This)->lpVtbl -> GetExceptionThreadID(This,threadID) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataTarget3_INTERFACE_DEFINED__ */ #ifndef __ICLRRuntimeLocator_INTERFACE_DEFINED__ #define __ICLRRuntimeLocator_INTERFACE_DEFINED__ /* interface ICLRRuntimeLocator */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICLRRuntimeLocator; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("b760bf44-9377-4597-8be7-58083bdc5146") ICLRRuntimeLocator : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetRuntimeBase( /* [out] */ CLRDATA_ADDRESS *baseAddress) = 0; }; #else /* C style interface */ typedef struct ICLRRuntimeLocatorVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRRuntimeLocator * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRRuntimeLocator * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRRuntimeLocator * This); DECLSPEC_XFGVIRT(ICLRRuntimeLocator, GetRuntimeBase) HRESULT ( STDMETHODCALLTYPE *GetRuntimeBase )( ICLRRuntimeLocator * This, /* [out] */ CLRDATA_ADDRESS *baseAddress); END_INTERFACE } ICLRRuntimeLocatorVtbl; interface ICLRRuntimeLocator { CONST_VTBL struct ICLRRuntimeLocatorVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRRuntimeLocator_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRRuntimeLocator_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRRuntimeLocator_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRRuntimeLocator_GetRuntimeBase(This,baseAddress) \ ( (This)->lpVtbl -> GetRuntimeBase(This,baseAddress) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRRuntimeLocator_INTERFACE_DEFINED__ */ #ifndef __ICLRMetadataLocator_INTERFACE_DEFINED__ #define __ICLRMetadataLocator_INTERFACE_DEFINED__ /* interface ICLRMetadataLocator */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICLRMetadataLocator; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("aa8fa804-bc05-4642-b2c5-c353ed22fc63") ICLRMetadataLocator : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetMetadata( /* [in] */ LPCWSTR imagePath, /* [in] */ ULONG32 imageTimestamp, /* [in] */ ULONG32 imageSize, /* [in] */ GUID *mvid, /* [in] */ ULONG32 mdRva, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufferSize, /* [length_is][size_is][out] */ BYTE *buffer, /* [out] */ ULONG32 *dataSize) = 0; }; #else /* C style interface */ typedef struct ICLRMetadataLocatorVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRMetadataLocator * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRMetadataLocator * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRMetadataLocator * This); DECLSPEC_XFGVIRT(ICLRMetadataLocator, GetMetadata) HRESULT ( STDMETHODCALLTYPE *GetMetadata )( ICLRMetadataLocator * This, /* [in] */ LPCWSTR imagePath, /* [in] */ ULONG32 imageTimestamp, /* [in] */ ULONG32 imageSize, /* [in] */ GUID *mvid, /* [in] */ ULONG32 mdRva, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufferSize, /* [length_is][size_is][out] */ BYTE *buffer, /* [out] */ ULONG32 *dataSize); END_INTERFACE } ICLRMetadataLocatorVtbl; interface ICLRMetadataLocator { CONST_VTBL struct ICLRMetadataLocatorVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRMetadataLocator_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRMetadataLocator_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRMetadataLocator_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRMetadataLocator_GetMetadata(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) \ ( (This)->lpVtbl -> GetMetadata(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRMetadataLocator_INTERFACE_DEFINED__ */ #ifndef __ICLRDataEnumMemoryRegionsCallback_INTERFACE_DEFINED__ #define __ICLRDataEnumMemoryRegionsCallback_INTERFACE_DEFINED__ /* interface ICLRDataEnumMemoryRegionsCallback */ /* [uuid][local][object] */ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsCallback; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("BCDD6908-BA2D-4ec5-96CF-DF4D5CDCB4A4") ICLRDataEnumMemoryRegionsCallback : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegion( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 size) = 0; }; #else /* C style interface */ typedef struct ICLRDataEnumMemoryRegionsCallbackVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataEnumMemoryRegionsCallback * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataEnumMemoryRegionsCallback * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataEnumMemoryRegionsCallback * This); DECLSPEC_XFGVIRT(ICLRDataEnumMemoryRegionsCallback, EnumMemoryRegion) HRESULT ( STDMETHODCALLTYPE *EnumMemoryRegion )( ICLRDataEnumMemoryRegionsCallback * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 size); END_INTERFACE } ICLRDataEnumMemoryRegionsCallbackVtbl; interface ICLRDataEnumMemoryRegionsCallback { CONST_VTBL struct ICLRDataEnumMemoryRegionsCallbackVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataEnumMemoryRegionsCallback_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataEnumMemoryRegionsCallback_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataEnumMemoryRegionsCallback_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataEnumMemoryRegionsCallback_EnumMemoryRegion(This,address,size) \ ( (This)->lpVtbl -> EnumMemoryRegion(This,address,size) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataEnumMemoryRegionsCallback_INTERFACE_DEFINED__ */ #ifndef __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ #define __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ /* interface ICLRDataEnumMemoryRegionsCallback2 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsCallback2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3721A26F-8B91-4D98-A388-DB17B356FADB") ICLRDataEnumMemoryRegionsCallback2 : public ICLRDataEnumMemoryRegionsCallback { public: virtual HRESULT STDMETHODCALLTYPE UpdateMemoryRegion( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 bufferSize, /* [size_is][in] */ BYTE *buffer) = 0; }; #else /* C style interface */ typedef struct ICLRDataEnumMemoryRegionsCallback2Vtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataEnumMemoryRegionsCallback2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataEnumMemoryRegionsCallback2 * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataEnumMemoryRegionsCallback2 * This); DECLSPEC_XFGVIRT(ICLRDataEnumMemoryRegionsCallback, EnumMemoryRegion) HRESULT ( STDMETHODCALLTYPE *EnumMemoryRegion )( ICLRDataEnumMemoryRegionsCallback2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 size); DECLSPEC_XFGVIRT(ICLRDataEnumMemoryRegionsCallback2, UpdateMemoryRegion) HRESULT ( STDMETHODCALLTYPE *UpdateMemoryRegion )( ICLRDataEnumMemoryRegionsCallback2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 bufferSize, /* [size_is][in] */ BYTE *buffer); END_INTERFACE } ICLRDataEnumMemoryRegionsCallback2Vtbl; interface ICLRDataEnumMemoryRegionsCallback2 { CONST_VTBL struct ICLRDataEnumMemoryRegionsCallback2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataEnumMemoryRegionsCallback2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataEnumMemoryRegionsCallback2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataEnumMemoryRegionsCallback2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataEnumMemoryRegionsCallback2_EnumMemoryRegion(This,address,size) \ ( (This)->lpVtbl -> EnumMemoryRegion(This,address,size) ) #define ICLRDataEnumMemoryRegionsCallback2_UpdateMemoryRegion(This,address,bufferSize,buffer) \ ( (This)->lpVtbl -> UpdateMemoryRegion(This,address,bufferSize,buffer) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ */ #ifndef __ICLRDataLoggingCallback_INTERFACE_DEFINED__ #define __ICLRDataLoggingCallback_INTERFACE_DEFINED__ /* interface ICLRDataLoggingCallback */ /* [uuid][local][object] */ EXTERN_C const IID IID_ICLRDataLoggingCallback; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F315248D-8B79-49DB-B184-37426559F703") ICLRDataLoggingCallback : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE LogMessage( /* [in] */ LPCSTR message) = 0; }; #else /* C style interface */ typedef struct ICLRDataLoggingCallbackVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataLoggingCallback * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataLoggingCallback * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataLoggingCallback * This); DECLSPEC_XFGVIRT(ICLRDataLoggingCallback, LogMessage) HRESULT ( STDMETHODCALLTYPE *LogMessage )( ICLRDataLoggingCallback * This, /* [in] */ LPCSTR message); END_INTERFACE } ICLRDataLoggingCallbackVtbl; interface ICLRDataLoggingCallback { CONST_VTBL struct ICLRDataLoggingCallbackVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataLoggingCallback_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataLoggingCallback_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataLoggingCallback_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataLoggingCallback_LogMessage(This,message) \ ( (This)->lpVtbl -> LogMessage(This,message) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataLoggingCallback_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_clrdata_0000_0008 */ /* [local] */ typedef enum CLRDataEnumMemoryFlags { CLRDATA_ENUM_MEM_DEFAULT = 0, CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, CLRDATA_ENUM_MEM_HEAP = 0x1, CLRDATA_ENUM_MEM_TRIAGE = 0x2, CLRDATA_ENUM_MEM_HEAP2 = 0x3 } CLRDataEnumMemoryFlags; extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0008_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_clrdata_0000_0008_v0_0_s_ifspec; #ifndef __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ #define __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ /* interface ICLRDataEnumMemoryRegions */ /* [uuid][local][object] */ EXTERN_C const IID IID_ICLRDataEnumMemoryRegions; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("471c35b4-7c2f-4ef0-a945-00f8c38056f1") ICLRDataEnumMemoryRegions : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumMemoryRegions( /* [in] */ ICLRDataEnumMemoryRegionsCallback *callback, /* [in] */ ULONG32 miniDumpFlags, /* [in] */ CLRDataEnumMemoryFlags clrFlags) = 0; }; #else /* C style interface */ typedef struct ICLRDataEnumMemoryRegionsVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDataEnumMemoryRegions * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDataEnumMemoryRegions * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( ICLRDataEnumMemoryRegions * This); DECLSPEC_XFGVIRT(ICLRDataEnumMemoryRegions, EnumMemoryRegions) HRESULT ( STDMETHODCALLTYPE *EnumMemoryRegions )( ICLRDataEnumMemoryRegions * This, /* [in] */ ICLRDataEnumMemoryRegionsCallback *callback, /* [in] */ ULONG32 miniDumpFlags, /* [in] */ CLRDataEnumMemoryFlags clrFlags); END_INTERFACE } ICLRDataEnumMemoryRegionsVtbl; interface ICLRDataEnumMemoryRegions { CONST_VTBL struct ICLRDataEnumMemoryRegionsVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDataEnumMemoryRegions_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDataEnumMemoryRegions_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDataEnumMemoryRegions_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDataEnumMemoryRegions_EnumMemoryRegions(This,callback,miniDumpFlags,clrFlags) \ ( (This)->lpVtbl -> EnumMemoryRegions(This,callback,miniDumpFlags,clrFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDataEnumMemoryRegions_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/clrinternal.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.00.0603 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif // __RPCNDR_H_VERSION__ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __clrinternal_h__ #define __clrinternal_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __IPrivateManagedExceptionReporting_FWD_DEFINED__ #define __IPrivateManagedExceptionReporting_FWD_DEFINED__ typedef interface IPrivateManagedExceptionReporting IPrivateManagedExceptionReporting; #endif /* __IPrivateManagedExceptionReporting_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #include "mscoree.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_clrinternal_0000_0000 */ /* [local] */ EXTERN_GUID(CLR_ID_V4_DESKTOP, 0x267f3989, 0xd786, 0x4b9a, 0x9a, 0xf6, 0xd1, 0x9e, 0x42, 0xd5, 0x57, 0xec); EXTERN_GUID(CLR_ID_CORECLR, 0x8CB8E075, 0x0A91, 0x408E, 0x92, 0x28, 0xD6, 0x6E, 0x00, 0xA3, 0xBF, 0xF6 ); EXTERN_GUID(CLR_ID_PHONE_CLR, 0xE7237E9C, 0x31C0, 0x488C, 0xAD, 0x48, 0x32, 0x4D, 0x3E, 0x7E, 0xD9, 0x2A); EXTERN_GUID(CLR_ID_ONECORE_CLR, 0xb1ee760d, 0x6c4a, 0x4533, 0xba, 0x41, 0x6f, 0x4f, 0x66, 0x1f, 0xab, 0xaf); EXTERN_GUID(IID_IPrivateManagedExceptionReporting, 0xad76a023, 0x332d, 0x4298, 0x80, 0x01, 0x07, 0xaa, 0x93, 0x50, 0xdc, 0xa4); typedef void *CRITSEC_COOKIE; typedef /* [public] */ enum __MIDL___MIDL_itf_clrinternal_0000_0000_0001 { CRST_DEFAULT = 0, CRST_REENTRANCY = 0x1, CRST_UNSAFE_SAMELEVEL = 0x2, CRST_UNSAFE_COOPGC = 0x4, CRST_UNSAFE_ANYMODE = 0x8, CRST_DEBUGGER_THREAD = 0x10, CRST_HOST_BREAKABLE = 0x20, CRST_TAKEN_DURING_SHUTDOWN = 0x80, CRST_GC_NOTRIGGER_WHEN_TAKEN = 0x100, CRST_DEBUG_ONLY_CHECK_FORBID_SUSPEND_THREAD = 0x200 } CrstFlags; extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_clrinternal_0000_0000_v0_0_s_ifspec; #ifndef __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ #define __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ /* interface IPrivateManagedExceptionReporting */ /* [object][local][unique][helpstring][uuid] */ EXTERN_C const IID IID_IPrivateManagedExceptionReporting; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AD76A023-332D-4298-8001-07AA9350DCA4") IPrivateManagedExceptionReporting : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetBucketParametersForCurrentException( /* [out] */ BucketParameters *pParams) = 0; }; #else /* C style interface */ typedef struct IPrivateManagedExceptionReportingVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IPrivateManagedExceptionReporting * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IPrivateManagedExceptionReporting * This); ULONG ( STDMETHODCALLTYPE *Release )( IPrivateManagedExceptionReporting * This); HRESULT ( STDMETHODCALLTYPE *GetBucketParametersForCurrentException )( IPrivateManagedExceptionReporting * This, /* [out] */ BucketParameters *pParams); END_INTERFACE } IPrivateManagedExceptionReportingVtbl; interface IPrivateManagedExceptionReporting { CONST_VTBL struct IPrivateManagedExceptionReportingVtbl *lpVtbl; }; #ifdef COBJMACROS #define IPrivateManagedExceptionReporting_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IPrivateManagedExceptionReporting_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IPrivateManagedExceptionReporting_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IPrivateManagedExceptionReporting_GetBucketParametersForCurrentException(This,pParams) \ ( (This)->lpVtbl -> GetBucketParametersForCurrentException(This,pParams) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IPrivateManagedExceptionReporting_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/cordebug.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0622 */ /* Compiler settings for cordebug.idl: Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __cordebug_h__ #define __cordebug_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __ICorDebugDataTarget_FWD_DEFINED__ #define __ICorDebugDataTarget_FWD_DEFINED__ typedef interface ICorDebugDataTarget ICorDebugDataTarget; #endif /* __ICorDebugDataTarget_FWD_DEFINED__ */ #ifndef __ICorDebugStaticFieldSymbol_FWD_DEFINED__ #define __ICorDebugStaticFieldSymbol_FWD_DEFINED__ typedef interface ICorDebugStaticFieldSymbol ICorDebugStaticFieldSymbol; #endif /* __ICorDebugStaticFieldSymbol_FWD_DEFINED__ */ #ifndef __ICorDebugInstanceFieldSymbol_FWD_DEFINED__ #define __ICorDebugInstanceFieldSymbol_FWD_DEFINED__ typedef interface ICorDebugInstanceFieldSymbol ICorDebugInstanceFieldSymbol; #endif /* __ICorDebugInstanceFieldSymbol_FWD_DEFINED__ */ #ifndef __ICorDebugVariableSymbol_FWD_DEFINED__ #define __ICorDebugVariableSymbol_FWD_DEFINED__ typedef interface ICorDebugVariableSymbol ICorDebugVariableSymbol; #endif /* __ICorDebugVariableSymbol_FWD_DEFINED__ */ #ifndef __ICorDebugMemoryBuffer_FWD_DEFINED__ #define __ICorDebugMemoryBuffer_FWD_DEFINED__ typedef interface ICorDebugMemoryBuffer ICorDebugMemoryBuffer; #endif /* __ICorDebugMemoryBuffer_FWD_DEFINED__ */ #ifndef __ICorDebugMergedAssemblyRecord_FWD_DEFINED__ #define __ICorDebugMergedAssemblyRecord_FWD_DEFINED__ typedef interface ICorDebugMergedAssemblyRecord ICorDebugMergedAssemblyRecord; #endif /* __ICorDebugMergedAssemblyRecord_FWD_DEFINED__ */ #ifndef __ICorDebugSymbolProvider_FWD_DEFINED__ #define __ICorDebugSymbolProvider_FWD_DEFINED__ typedef interface ICorDebugSymbolProvider ICorDebugSymbolProvider; #endif /* __ICorDebugSymbolProvider_FWD_DEFINED__ */ #ifndef __ICorDebugSymbolProvider2_FWD_DEFINED__ #define __ICorDebugSymbolProvider2_FWD_DEFINED__ typedef interface ICorDebugSymbolProvider2 ICorDebugSymbolProvider2; #endif /* __ICorDebugSymbolProvider2_FWD_DEFINED__ */ #ifndef __ICorDebugVirtualUnwinder_FWD_DEFINED__ #define __ICorDebugVirtualUnwinder_FWD_DEFINED__ typedef interface ICorDebugVirtualUnwinder ICorDebugVirtualUnwinder; #endif /* __ICorDebugVirtualUnwinder_FWD_DEFINED__ */ #ifndef __ICorDebugDataTarget2_FWD_DEFINED__ #define __ICorDebugDataTarget2_FWD_DEFINED__ typedef interface ICorDebugDataTarget2 ICorDebugDataTarget2; #endif /* __ICorDebugDataTarget2_FWD_DEFINED__ */ #ifndef __ICorDebugLoadedModule_FWD_DEFINED__ #define __ICorDebugLoadedModule_FWD_DEFINED__ typedef interface ICorDebugLoadedModule ICorDebugLoadedModule; #endif /* __ICorDebugLoadedModule_FWD_DEFINED__ */ #ifndef __ICorDebugDataTarget3_FWD_DEFINED__ #define __ICorDebugDataTarget3_FWD_DEFINED__ typedef interface ICorDebugDataTarget3 ICorDebugDataTarget3; #endif /* __ICorDebugDataTarget3_FWD_DEFINED__ */ #ifndef __ICorDebugDataTarget4_FWD_DEFINED__ #define __ICorDebugDataTarget4_FWD_DEFINED__ typedef interface ICorDebugDataTarget4 ICorDebugDataTarget4; #endif /* __ICorDebugDataTarget4_FWD_DEFINED__ */ #ifndef __ICorDebugMutableDataTarget_FWD_DEFINED__ #define __ICorDebugMutableDataTarget_FWD_DEFINED__ typedef interface ICorDebugMutableDataTarget ICorDebugMutableDataTarget; #endif /* __ICorDebugMutableDataTarget_FWD_DEFINED__ */ #ifndef __ICorDebugMetaDataLocator_FWD_DEFINED__ #define __ICorDebugMetaDataLocator_FWD_DEFINED__ typedef interface ICorDebugMetaDataLocator ICorDebugMetaDataLocator; #endif /* __ICorDebugMetaDataLocator_FWD_DEFINED__ */ #ifndef __ICorDebugManagedCallback_FWD_DEFINED__ #define __ICorDebugManagedCallback_FWD_DEFINED__ typedef interface ICorDebugManagedCallback ICorDebugManagedCallback; #endif /* __ICorDebugManagedCallback_FWD_DEFINED__ */ #ifndef __ICorDebugManagedCallback3_FWD_DEFINED__ #define __ICorDebugManagedCallback3_FWD_DEFINED__ typedef interface ICorDebugManagedCallback3 ICorDebugManagedCallback3; #endif /* __ICorDebugManagedCallback3_FWD_DEFINED__ */ #ifndef __ICorDebugManagedCallback4_FWD_DEFINED__ #define __ICorDebugManagedCallback4_FWD_DEFINED__ typedef interface ICorDebugManagedCallback4 ICorDebugManagedCallback4; #endif /* __ICorDebugManagedCallback4_FWD_DEFINED__ */ #ifndef __ICorDebugManagedCallback2_FWD_DEFINED__ #define __ICorDebugManagedCallback2_FWD_DEFINED__ typedef interface ICorDebugManagedCallback2 ICorDebugManagedCallback2; #endif /* __ICorDebugManagedCallback2_FWD_DEFINED__ */ #ifndef __ICorDebugUnmanagedCallback_FWD_DEFINED__ #define __ICorDebugUnmanagedCallback_FWD_DEFINED__ typedef interface ICorDebugUnmanagedCallback ICorDebugUnmanagedCallback; #endif /* __ICorDebugUnmanagedCallback_FWD_DEFINED__ */ #ifndef __ICorDebug_FWD_DEFINED__ #define __ICorDebug_FWD_DEFINED__ typedef interface ICorDebug ICorDebug; #endif /* __ICorDebug_FWD_DEFINED__ */ #ifndef __ICorDebugRemoteTarget_FWD_DEFINED__ #define __ICorDebugRemoteTarget_FWD_DEFINED__ typedef interface ICorDebugRemoteTarget ICorDebugRemoteTarget; #endif /* __ICorDebugRemoteTarget_FWD_DEFINED__ */ #ifndef __ICorDebugRemote_FWD_DEFINED__ #define __ICorDebugRemote_FWD_DEFINED__ typedef interface ICorDebugRemote ICorDebugRemote; #endif /* __ICorDebugRemote_FWD_DEFINED__ */ #ifndef __ICorDebug2_FWD_DEFINED__ #define __ICorDebug2_FWD_DEFINED__ typedef interface ICorDebug2 ICorDebug2; #endif /* __ICorDebug2_FWD_DEFINED__ */ #ifndef __ICorDebugController_FWD_DEFINED__ #define __ICorDebugController_FWD_DEFINED__ typedef interface ICorDebugController ICorDebugController; #endif /* __ICorDebugController_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomain_FWD_DEFINED__ #define __ICorDebugAppDomain_FWD_DEFINED__ typedef interface ICorDebugAppDomain ICorDebugAppDomain; #endif /* __ICorDebugAppDomain_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomain2_FWD_DEFINED__ #define __ICorDebugAppDomain2_FWD_DEFINED__ typedef interface ICorDebugAppDomain2 ICorDebugAppDomain2; #endif /* __ICorDebugAppDomain2_FWD_DEFINED__ */ #ifndef __ICorDebugEnum_FWD_DEFINED__ #define __ICorDebugEnum_FWD_DEFINED__ typedef interface ICorDebugEnum ICorDebugEnum; #endif /* __ICorDebugEnum_FWD_DEFINED__ */ #ifndef __ICorDebugGuidToTypeEnum_FWD_DEFINED__ #define __ICorDebugGuidToTypeEnum_FWD_DEFINED__ typedef interface ICorDebugGuidToTypeEnum ICorDebugGuidToTypeEnum; #endif /* __ICorDebugGuidToTypeEnum_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomain3_FWD_DEFINED__ #define __ICorDebugAppDomain3_FWD_DEFINED__ typedef interface ICorDebugAppDomain3 ICorDebugAppDomain3; #endif /* __ICorDebugAppDomain3_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomain4_FWD_DEFINED__ #define __ICorDebugAppDomain4_FWD_DEFINED__ typedef interface ICorDebugAppDomain4 ICorDebugAppDomain4; #endif /* __ICorDebugAppDomain4_FWD_DEFINED__ */ #ifndef __ICorDebugAssembly_FWD_DEFINED__ #define __ICorDebugAssembly_FWD_DEFINED__ typedef interface ICorDebugAssembly ICorDebugAssembly; #endif /* __ICorDebugAssembly_FWD_DEFINED__ */ #ifndef __ICorDebugAssembly2_FWD_DEFINED__ #define __ICorDebugAssembly2_FWD_DEFINED__ typedef interface ICorDebugAssembly2 ICorDebugAssembly2; #endif /* __ICorDebugAssembly2_FWD_DEFINED__ */ #ifndef __ICorDebugAssembly3_FWD_DEFINED__ #define __ICorDebugAssembly3_FWD_DEFINED__ typedef interface ICorDebugAssembly3 ICorDebugAssembly3; #endif /* __ICorDebugAssembly3_FWD_DEFINED__ */ #ifndef __ICorDebugHeapEnum_FWD_DEFINED__ #define __ICorDebugHeapEnum_FWD_DEFINED__ typedef interface ICorDebugHeapEnum ICorDebugHeapEnum; #endif /* __ICorDebugHeapEnum_FWD_DEFINED__ */ #ifndef __ICorDebugHeapSegmentEnum_FWD_DEFINED__ #define __ICorDebugHeapSegmentEnum_FWD_DEFINED__ typedef interface ICorDebugHeapSegmentEnum ICorDebugHeapSegmentEnum; #endif /* __ICorDebugHeapSegmentEnum_FWD_DEFINED__ */ #ifndef __ICorDebugGCReferenceEnum_FWD_DEFINED__ #define __ICorDebugGCReferenceEnum_FWD_DEFINED__ typedef interface ICorDebugGCReferenceEnum ICorDebugGCReferenceEnum; #endif /* __ICorDebugGCReferenceEnum_FWD_DEFINED__ */ #ifndef __ICorDebugProcess_FWD_DEFINED__ #define __ICorDebugProcess_FWD_DEFINED__ typedef interface ICorDebugProcess ICorDebugProcess; #endif /* __ICorDebugProcess_FWD_DEFINED__ */ #ifndef __ICorDebugProcess2_FWD_DEFINED__ #define __ICorDebugProcess2_FWD_DEFINED__ typedef interface ICorDebugProcess2 ICorDebugProcess2; #endif /* __ICorDebugProcess2_FWD_DEFINED__ */ #ifndef __ICorDebugProcess3_FWD_DEFINED__ #define __ICorDebugProcess3_FWD_DEFINED__ typedef interface ICorDebugProcess3 ICorDebugProcess3; #endif /* __ICorDebugProcess3_FWD_DEFINED__ */ #ifndef __ICorDebugProcess5_FWD_DEFINED__ #define __ICorDebugProcess5_FWD_DEFINED__ typedef interface ICorDebugProcess5 ICorDebugProcess5; #endif /* __ICorDebugProcess5_FWD_DEFINED__ */ #ifndef __ICorDebugDebugEvent_FWD_DEFINED__ #define __ICorDebugDebugEvent_FWD_DEFINED__ typedef interface ICorDebugDebugEvent ICorDebugDebugEvent; #endif /* __ICorDebugDebugEvent_FWD_DEFINED__ */ #ifndef __ICorDebugProcess6_FWD_DEFINED__ #define __ICorDebugProcess6_FWD_DEFINED__ typedef interface ICorDebugProcess6 ICorDebugProcess6; #endif /* __ICorDebugProcess6_FWD_DEFINED__ */ #ifndef __ICorDebugProcess7_FWD_DEFINED__ #define __ICorDebugProcess7_FWD_DEFINED__ typedef interface ICorDebugProcess7 ICorDebugProcess7; #endif /* __ICorDebugProcess7_FWD_DEFINED__ */ #ifndef __ICorDebugProcess8_FWD_DEFINED__ #define __ICorDebugProcess8_FWD_DEFINED__ typedef interface ICorDebugProcess8 ICorDebugProcess8; #endif /* __ICorDebugProcess8_FWD_DEFINED__ */ #ifndef __ICorDebugProcess10_FWD_DEFINED__ #define __ICorDebugProcess10_FWD_DEFINED__ typedef interface ICorDebugProcess10 ICorDebugProcess10; #endif /* __ICorDebugProcess10_FWD_DEFINED__ */ #ifndef __ICorDebugMemoryRangeEnum_FWD_DEFINED__ #define __ICorDebugMemoryRangeEnum_FWD_DEFINED__ typedef interface ICorDebugMemoryRangeEnum ICorDebugMemoryRangeEnum; #endif /* __ICorDebugMemoryRangeEnum_FWD_DEFINED__ */ #ifndef __ICorDebugProcess11_FWD_DEFINED__ #define __ICorDebugProcess11_FWD_DEFINED__ typedef interface ICorDebugProcess11 ICorDebugProcess11; #endif /* __ICorDebugProcess11_FWD_DEFINED__ */ #ifndef __ICorDebugModuleDebugEvent_FWD_DEFINED__ #define __ICorDebugModuleDebugEvent_FWD_DEFINED__ typedef interface ICorDebugModuleDebugEvent ICorDebugModuleDebugEvent; #endif /* __ICorDebugModuleDebugEvent_FWD_DEFINED__ */ #ifndef __ICorDebugExceptionDebugEvent_FWD_DEFINED__ #define __ICorDebugExceptionDebugEvent_FWD_DEFINED__ typedef interface ICorDebugExceptionDebugEvent ICorDebugExceptionDebugEvent; #endif /* __ICorDebugExceptionDebugEvent_FWD_DEFINED__ */ #ifndef __ICorDebugBreakpoint_FWD_DEFINED__ #define __ICorDebugBreakpoint_FWD_DEFINED__ typedef interface ICorDebugBreakpoint ICorDebugBreakpoint; #endif /* __ICorDebugBreakpoint_FWD_DEFINED__ */ #ifndef __ICorDebugFunctionBreakpoint_FWD_DEFINED__ #define __ICorDebugFunctionBreakpoint_FWD_DEFINED__ typedef interface ICorDebugFunctionBreakpoint ICorDebugFunctionBreakpoint; #endif /* __ICorDebugFunctionBreakpoint_FWD_DEFINED__ */ #ifndef __ICorDebugModuleBreakpoint_FWD_DEFINED__ #define __ICorDebugModuleBreakpoint_FWD_DEFINED__ typedef interface ICorDebugModuleBreakpoint ICorDebugModuleBreakpoint; #endif /* __ICorDebugModuleBreakpoint_FWD_DEFINED__ */ #ifndef __ICorDebugValueBreakpoint_FWD_DEFINED__ #define __ICorDebugValueBreakpoint_FWD_DEFINED__ typedef interface ICorDebugValueBreakpoint ICorDebugValueBreakpoint; #endif /* __ICorDebugValueBreakpoint_FWD_DEFINED__ */ #ifndef __ICorDebugStepper_FWD_DEFINED__ #define __ICorDebugStepper_FWD_DEFINED__ typedef interface ICorDebugStepper ICorDebugStepper; #endif /* __ICorDebugStepper_FWD_DEFINED__ */ #ifndef __ICorDebugStepper2_FWD_DEFINED__ #define __ICorDebugStepper2_FWD_DEFINED__ typedef interface ICorDebugStepper2 ICorDebugStepper2; #endif /* __ICorDebugStepper2_FWD_DEFINED__ */ #ifndef __ICorDebugRegisterSet_FWD_DEFINED__ #define __ICorDebugRegisterSet_FWD_DEFINED__ typedef interface ICorDebugRegisterSet ICorDebugRegisterSet; #endif /* __ICorDebugRegisterSet_FWD_DEFINED__ */ #ifndef __ICorDebugRegisterSet2_FWD_DEFINED__ #define __ICorDebugRegisterSet2_FWD_DEFINED__ typedef interface ICorDebugRegisterSet2 ICorDebugRegisterSet2; #endif /* __ICorDebugRegisterSet2_FWD_DEFINED__ */ #ifndef __ICorDebugThread_FWD_DEFINED__ #define __ICorDebugThread_FWD_DEFINED__ typedef interface ICorDebugThread ICorDebugThread; #endif /* __ICorDebugThread_FWD_DEFINED__ */ #ifndef __ICorDebugThread2_FWD_DEFINED__ #define __ICorDebugThread2_FWD_DEFINED__ typedef interface ICorDebugThread2 ICorDebugThread2; #endif /* __ICorDebugThread2_FWD_DEFINED__ */ #ifndef __ICorDebugThread3_FWD_DEFINED__ #define __ICorDebugThread3_FWD_DEFINED__ typedef interface ICorDebugThread3 ICorDebugThread3; #endif /* __ICorDebugThread3_FWD_DEFINED__ */ #ifndef __ICorDebugThread4_FWD_DEFINED__ #define __ICorDebugThread4_FWD_DEFINED__ typedef interface ICorDebugThread4 ICorDebugThread4; #endif /* __ICorDebugThread4_FWD_DEFINED__ */ #ifndef __ICorDebugThread5_FWD_DEFINED__ #define __ICorDebugThread5_FWD_DEFINED__ typedef interface ICorDebugThread5 ICorDebugThread5; #endif /* __ICorDebugThread5_FWD_DEFINED__ */ #ifndef __ICorDebugStackWalk_FWD_DEFINED__ #define __ICorDebugStackWalk_FWD_DEFINED__ typedef interface ICorDebugStackWalk ICorDebugStackWalk; #endif /* __ICorDebugStackWalk_FWD_DEFINED__ */ #ifndef __ICorDebugChain_FWD_DEFINED__ #define __ICorDebugChain_FWD_DEFINED__ typedef interface ICorDebugChain ICorDebugChain; #endif /* __ICorDebugChain_FWD_DEFINED__ */ #ifndef __ICorDebugFrame_FWD_DEFINED__ #define __ICorDebugFrame_FWD_DEFINED__ typedef interface ICorDebugFrame ICorDebugFrame; #endif /* __ICorDebugFrame_FWD_DEFINED__ */ #ifndef __ICorDebugInternalFrame_FWD_DEFINED__ #define __ICorDebugInternalFrame_FWD_DEFINED__ typedef interface ICorDebugInternalFrame ICorDebugInternalFrame; #endif /* __ICorDebugInternalFrame_FWD_DEFINED__ */ #ifndef __ICorDebugInternalFrame2_FWD_DEFINED__ #define __ICorDebugInternalFrame2_FWD_DEFINED__ typedef interface ICorDebugInternalFrame2 ICorDebugInternalFrame2; #endif /* __ICorDebugInternalFrame2_FWD_DEFINED__ */ #ifndef __ICorDebugILFrame_FWD_DEFINED__ #define __ICorDebugILFrame_FWD_DEFINED__ typedef interface ICorDebugILFrame ICorDebugILFrame; #endif /* __ICorDebugILFrame_FWD_DEFINED__ */ #ifndef __ICorDebugILFrame2_FWD_DEFINED__ #define __ICorDebugILFrame2_FWD_DEFINED__ typedef interface ICorDebugILFrame2 ICorDebugILFrame2; #endif /* __ICorDebugILFrame2_FWD_DEFINED__ */ #ifndef __ICorDebugILFrame3_FWD_DEFINED__ #define __ICorDebugILFrame3_FWD_DEFINED__ typedef interface ICorDebugILFrame3 ICorDebugILFrame3; #endif /* __ICorDebugILFrame3_FWD_DEFINED__ */ #ifndef __ICorDebugILFrame4_FWD_DEFINED__ #define __ICorDebugILFrame4_FWD_DEFINED__ typedef interface ICorDebugILFrame4 ICorDebugILFrame4; #endif /* __ICorDebugILFrame4_FWD_DEFINED__ */ #ifndef __ICorDebugNativeFrame_FWD_DEFINED__ #define __ICorDebugNativeFrame_FWD_DEFINED__ typedef interface ICorDebugNativeFrame ICorDebugNativeFrame; #endif /* __ICorDebugNativeFrame_FWD_DEFINED__ */ #ifndef __ICorDebugNativeFrame2_FWD_DEFINED__ #define __ICorDebugNativeFrame2_FWD_DEFINED__ typedef interface ICorDebugNativeFrame2 ICorDebugNativeFrame2; #endif /* __ICorDebugNativeFrame2_FWD_DEFINED__ */ #ifndef __ICorDebugModule3_FWD_DEFINED__ #define __ICorDebugModule3_FWD_DEFINED__ typedef interface ICorDebugModule3 ICorDebugModule3; #endif /* __ICorDebugModule3_FWD_DEFINED__ */ #ifndef __ICorDebugModule4_FWD_DEFINED__ #define __ICorDebugModule4_FWD_DEFINED__ typedef interface ICorDebugModule4 ICorDebugModule4; #endif /* __ICorDebugModule4_FWD_DEFINED__ */ #ifndef __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ #define __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ typedef interface ICorDebugRuntimeUnwindableFrame ICorDebugRuntimeUnwindableFrame; #endif /* __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ */ #ifndef __ICorDebugModule_FWD_DEFINED__ #define __ICorDebugModule_FWD_DEFINED__ typedef interface ICorDebugModule ICorDebugModule; #endif /* __ICorDebugModule_FWD_DEFINED__ */ #ifndef __ICorDebugModule2_FWD_DEFINED__ #define __ICorDebugModule2_FWD_DEFINED__ typedef interface ICorDebugModule2 ICorDebugModule2; #endif /* __ICorDebugModule2_FWD_DEFINED__ */ #ifndef __ICorDebugFunction_FWD_DEFINED__ #define __ICorDebugFunction_FWD_DEFINED__ typedef interface ICorDebugFunction ICorDebugFunction; #endif /* __ICorDebugFunction_FWD_DEFINED__ */ #ifndef __ICorDebugFunction2_FWD_DEFINED__ #define __ICorDebugFunction2_FWD_DEFINED__ typedef interface ICorDebugFunction2 ICorDebugFunction2; #endif /* __ICorDebugFunction2_FWD_DEFINED__ */ #ifndef __ICorDebugFunction3_FWD_DEFINED__ #define __ICorDebugFunction3_FWD_DEFINED__ typedef interface ICorDebugFunction3 ICorDebugFunction3; #endif /* __ICorDebugFunction3_FWD_DEFINED__ */ #ifndef __ICorDebugFunction4_FWD_DEFINED__ #define __ICorDebugFunction4_FWD_DEFINED__ typedef interface ICorDebugFunction4 ICorDebugFunction4; #endif /* __ICorDebugFunction4_FWD_DEFINED__ */ #ifndef __ICorDebugCode_FWD_DEFINED__ #define __ICorDebugCode_FWD_DEFINED__ typedef interface ICorDebugCode ICorDebugCode; #endif /* __ICorDebugCode_FWD_DEFINED__ */ #ifndef __ICorDebugCode2_FWD_DEFINED__ #define __ICorDebugCode2_FWD_DEFINED__ typedef interface ICorDebugCode2 ICorDebugCode2; #endif /* __ICorDebugCode2_FWD_DEFINED__ */ #ifndef __ICorDebugCode3_FWD_DEFINED__ #define __ICorDebugCode3_FWD_DEFINED__ typedef interface ICorDebugCode3 ICorDebugCode3; #endif /* __ICorDebugCode3_FWD_DEFINED__ */ #ifndef __ICorDebugCode4_FWD_DEFINED__ #define __ICorDebugCode4_FWD_DEFINED__ typedef interface ICorDebugCode4 ICorDebugCode4; #endif /* __ICorDebugCode4_FWD_DEFINED__ */ #ifndef __ICorDebugILCode_FWD_DEFINED__ #define __ICorDebugILCode_FWD_DEFINED__ typedef interface ICorDebugILCode ICorDebugILCode; #endif /* __ICorDebugILCode_FWD_DEFINED__ */ #ifndef __ICorDebugILCode2_FWD_DEFINED__ #define __ICorDebugILCode2_FWD_DEFINED__ typedef interface ICorDebugILCode2 ICorDebugILCode2; #endif /* __ICorDebugILCode2_FWD_DEFINED__ */ #ifndef __ICorDebugClass_FWD_DEFINED__ #define __ICorDebugClass_FWD_DEFINED__ typedef interface ICorDebugClass ICorDebugClass; #endif /* __ICorDebugClass_FWD_DEFINED__ */ #ifndef __ICorDebugClass2_FWD_DEFINED__ #define __ICorDebugClass2_FWD_DEFINED__ typedef interface ICorDebugClass2 ICorDebugClass2; #endif /* __ICorDebugClass2_FWD_DEFINED__ */ #ifndef __ICorDebugEval_FWD_DEFINED__ #define __ICorDebugEval_FWD_DEFINED__ typedef interface ICorDebugEval ICorDebugEval; #endif /* __ICorDebugEval_FWD_DEFINED__ */ #ifndef __ICorDebugEval2_FWD_DEFINED__ #define __ICorDebugEval2_FWD_DEFINED__ typedef interface ICorDebugEval2 ICorDebugEval2; #endif /* __ICorDebugEval2_FWD_DEFINED__ */ #ifndef __ICorDebugValue_FWD_DEFINED__ #define __ICorDebugValue_FWD_DEFINED__ typedef interface ICorDebugValue ICorDebugValue; #endif /* __ICorDebugValue_FWD_DEFINED__ */ #ifndef __ICorDebugValue2_FWD_DEFINED__ #define __ICorDebugValue2_FWD_DEFINED__ typedef interface ICorDebugValue2 ICorDebugValue2; #endif /* __ICorDebugValue2_FWD_DEFINED__ */ #ifndef __ICorDebugValue3_FWD_DEFINED__ #define __ICorDebugValue3_FWD_DEFINED__ typedef interface ICorDebugValue3 ICorDebugValue3; #endif /* __ICorDebugValue3_FWD_DEFINED__ */ #ifndef __ICorDebugGenericValue_FWD_DEFINED__ #define __ICorDebugGenericValue_FWD_DEFINED__ typedef interface ICorDebugGenericValue ICorDebugGenericValue; #endif /* __ICorDebugGenericValue_FWD_DEFINED__ */ #ifndef __ICorDebugReferenceValue_FWD_DEFINED__ #define __ICorDebugReferenceValue_FWD_DEFINED__ typedef interface ICorDebugReferenceValue ICorDebugReferenceValue; #endif /* __ICorDebugReferenceValue_FWD_DEFINED__ */ #ifndef __ICorDebugHeapValue_FWD_DEFINED__ #define __ICorDebugHeapValue_FWD_DEFINED__ typedef interface ICorDebugHeapValue ICorDebugHeapValue; #endif /* __ICorDebugHeapValue_FWD_DEFINED__ */ #ifndef __ICorDebugHeapValue2_FWD_DEFINED__ #define __ICorDebugHeapValue2_FWD_DEFINED__ typedef interface ICorDebugHeapValue2 ICorDebugHeapValue2; #endif /* __ICorDebugHeapValue2_FWD_DEFINED__ */ #ifndef __ICorDebugHeapValue3_FWD_DEFINED__ #define __ICorDebugHeapValue3_FWD_DEFINED__ typedef interface ICorDebugHeapValue3 ICorDebugHeapValue3; #endif /* __ICorDebugHeapValue3_FWD_DEFINED__ */ #ifndef __ICorDebugHeapValue4_FWD_DEFINED__ #define __ICorDebugHeapValue4_FWD_DEFINED__ typedef interface ICorDebugHeapValue4 ICorDebugHeapValue4; #endif /* __ICorDebugHeapValue4_FWD_DEFINED__ */ #ifndef __ICorDebugObjectValue_FWD_DEFINED__ #define __ICorDebugObjectValue_FWD_DEFINED__ typedef interface ICorDebugObjectValue ICorDebugObjectValue; #endif /* __ICorDebugObjectValue_FWD_DEFINED__ */ #ifndef __ICorDebugObjectValue2_FWD_DEFINED__ #define __ICorDebugObjectValue2_FWD_DEFINED__ typedef interface ICorDebugObjectValue2 ICorDebugObjectValue2; #endif /* __ICorDebugObjectValue2_FWD_DEFINED__ */ #ifndef __ICorDebugDelegateObjectValue_FWD_DEFINED__ #define __ICorDebugDelegateObjectValue_FWD_DEFINED__ typedef interface ICorDebugDelegateObjectValue ICorDebugDelegateObjectValue; #endif /* __ICorDebugDelegateObjectValue_FWD_DEFINED__ */ #ifndef __ICorDebugBoxValue_FWD_DEFINED__ #define __ICorDebugBoxValue_FWD_DEFINED__ typedef interface ICorDebugBoxValue ICorDebugBoxValue; #endif /* __ICorDebugBoxValue_FWD_DEFINED__ */ #ifndef __ICorDebugStringValue_FWD_DEFINED__ #define __ICorDebugStringValue_FWD_DEFINED__ typedef interface ICorDebugStringValue ICorDebugStringValue; #endif /* __ICorDebugStringValue_FWD_DEFINED__ */ #ifndef __ICorDebugArrayValue_FWD_DEFINED__ #define __ICorDebugArrayValue_FWD_DEFINED__ typedef interface ICorDebugArrayValue ICorDebugArrayValue; #endif /* __ICorDebugArrayValue_FWD_DEFINED__ */ #ifndef __ICorDebugVariableHome_FWD_DEFINED__ #define __ICorDebugVariableHome_FWD_DEFINED__ typedef interface ICorDebugVariableHome ICorDebugVariableHome; #endif /* __ICorDebugVariableHome_FWD_DEFINED__ */ #ifndef __ICorDebugHandleValue_FWD_DEFINED__ #define __ICorDebugHandleValue_FWD_DEFINED__ typedef interface ICorDebugHandleValue ICorDebugHandleValue; #endif /* __ICorDebugHandleValue_FWD_DEFINED__ */ #ifndef __ICorDebugContext_FWD_DEFINED__ #define __ICorDebugContext_FWD_DEFINED__ typedef interface ICorDebugContext ICorDebugContext; #endif /* __ICorDebugContext_FWD_DEFINED__ */ #ifndef __ICorDebugComObjectValue_FWD_DEFINED__ #define __ICorDebugComObjectValue_FWD_DEFINED__ typedef interface ICorDebugComObjectValue ICorDebugComObjectValue; #endif /* __ICorDebugComObjectValue_FWD_DEFINED__ */ #ifndef __ICorDebugObjectEnum_FWD_DEFINED__ #define __ICorDebugObjectEnum_FWD_DEFINED__ typedef interface ICorDebugObjectEnum ICorDebugObjectEnum; #endif /* __ICorDebugObjectEnum_FWD_DEFINED__ */ #ifndef __ICorDebugBreakpointEnum_FWD_DEFINED__ #define __ICorDebugBreakpointEnum_FWD_DEFINED__ typedef interface ICorDebugBreakpointEnum ICorDebugBreakpointEnum; #endif /* __ICorDebugBreakpointEnum_FWD_DEFINED__ */ #ifndef __ICorDebugStepperEnum_FWD_DEFINED__ #define __ICorDebugStepperEnum_FWD_DEFINED__ typedef interface ICorDebugStepperEnum ICorDebugStepperEnum; #endif /* __ICorDebugStepperEnum_FWD_DEFINED__ */ #ifndef __ICorDebugProcessEnum_FWD_DEFINED__ #define __ICorDebugProcessEnum_FWD_DEFINED__ typedef interface ICorDebugProcessEnum ICorDebugProcessEnum; #endif /* __ICorDebugProcessEnum_FWD_DEFINED__ */ #ifndef __ICorDebugThreadEnum_FWD_DEFINED__ #define __ICorDebugThreadEnum_FWD_DEFINED__ typedef interface ICorDebugThreadEnum ICorDebugThreadEnum; #endif /* __ICorDebugThreadEnum_FWD_DEFINED__ */ #ifndef __ICorDebugFrameEnum_FWD_DEFINED__ #define __ICorDebugFrameEnum_FWD_DEFINED__ typedef interface ICorDebugFrameEnum ICorDebugFrameEnum; #endif /* __ICorDebugFrameEnum_FWD_DEFINED__ */ #ifndef __ICorDebugChainEnum_FWD_DEFINED__ #define __ICorDebugChainEnum_FWD_DEFINED__ typedef interface ICorDebugChainEnum ICorDebugChainEnum; #endif /* __ICorDebugChainEnum_FWD_DEFINED__ */ #ifndef __ICorDebugModuleEnum_FWD_DEFINED__ #define __ICorDebugModuleEnum_FWD_DEFINED__ typedef interface ICorDebugModuleEnum ICorDebugModuleEnum; #endif /* __ICorDebugModuleEnum_FWD_DEFINED__ */ #ifndef __ICorDebugValueEnum_FWD_DEFINED__ #define __ICorDebugValueEnum_FWD_DEFINED__ typedef interface ICorDebugValueEnum ICorDebugValueEnum; #endif /* __ICorDebugValueEnum_FWD_DEFINED__ */ #ifndef __ICorDebugVariableHomeEnum_FWD_DEFINED__ #define __ICorDebugVariableHomeEnum_FWD_DEFINED__ typedef interface ICorDebugVariableHomeEnum ICorDebugVariableHomeEnum; #endif /* __ICorDebugVariableHomeEnum_FWD_DEFINED__ */ #ifndef __ICorDebugCodeEnum_FWD_DEFINED__ #define __ICorDebugCodeEnum_FWD_DEFINED__ typedef interface ICorDebugCodeEnum ICorDebugCodeEnum; #endif /* __ICorDebugCodeEnum_FWD_DEFINED__ */ #ifndef __ICorDebugTypeEnum_FWD_DEFINED__ #define __ICorDebugTypeEnum_FWD_DEFINED__ typedef interface ICorDebugTypeEnum ICorDebugTypeEnum; #endif /* __ICorDebugTypeEnum_FWD_DEFINED__ */ #ifndef __ICorDebugType_FWD_DEFINED__ #define __ICorDebugType_FWD_DEFINED__ typedef interface ICorDebugType ICorDebugType; #endif /* __ICorDebugType_FWD_DEFINED__ */ #ifndef __ICorDebugType2_FWD_DEFINED__ #define __ICorDebugType2_FWD_DEFINED__ typedef interface ICorDebugType2 ICorDebugType2; #endif /* __ICorDebugType2_FWD_DEFINED__ */ #ifndef __ICorDebugErrorInfoEnum_FWD_DEFINED__ #define __ICorDebugErrorInfoEnum_FWD_DEFINED__ typedef interface ICorDebugErrorInfoEnum ICorDebugErrorInfoEnum; #endif /* __ICorDebugErrorInfoEnum_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomainEnum_FWD_DEFINED__ #define __ICorDebugAppDomainEnum_FWD_DEFINED__ typedef interface ICorDebugAppDomainEnum ICorDebugAppDomainEnum; #endif /* __ICorDebugAppDomainEnum_FWD_DEFINED__ */ #ifndef __ICorDebugAssemblyEnum_FWD_DEFINED__ #define __ICorDebugAssemblyEnum_FWD_DEFINED__ typedef interface ICorDebugAssemblyEnum ICorDebugAssemblyEnum; #endif /* __ICorDebugAssemblyEnum_FWD_DEFINED__ */ #ifndef __ICorDebugBlockingObjectEnum_FWD_DEFINED__ #define __ICorDebugBlockingObjectEnum_FWD_DEFINED__ typedef interface ICorDebugBlockingObjectEnum ICorDebugBlockingObjectEnum; #endif /* __ICorDebugBlockingObjectEnum_FWD_DEFINED__ */ #ifndef __ICorDebugMDA_FWD_DEFINED__ #define __ICorDebugMDA_FWD_DEFINED__ typedef interface ICorDebugMDA ICorDebugMDA; #endif /* __ICorDebugMDA_FWD_DEFINED__ */ #ifndef __ICorDebugEditAndContinueErrorInfo_FWD_DEFINED__ #define __ICorDebugEditAndContinueErrorInfo_FWD_DEFINED__ typedef interface ICorDebugEditAndContinueErrorInfo ICorDebugEditAndContinueErrorInfo; #endif /* __ICorDebugEditAndContinueErrorInfo_FWD_DEFINED__ */ #ifndef __ICorDebugEditAndContinueSnapshot_FWD_DEFINED__ #define __ICorDebugEditAndContinueSnapshot_FWD_DEFINED__ typedef interface ICorDebugEditAndContinueSnapshot ICorDebugEditAndContinueSnapshot; #endif /* __ICorDebugEditAndContinueSnapshot_FWD_DEFINED__ */ #ifndef __ICorDebugExceptionObjectCallStackEnum_FWD_DEFINED__ #define __ICorDebugExceptionObjectCallStackEnum_FWD_DEFINED__ typedef interface ICorDebugExceptionObjectCallStackEnum ICorDebugExceptionObjectCallStackEnum; #endif /* __ICorDebugExceptionObjectCallStackEnum_FWD_DEFINED__ */ #ifndef __ICorDebugExceptionObjectValue_FWD_DEFINED__ #define __ICorDebugExceptionObjectValue_FWD_DEFINED__ typedef interface ICorDebugExceptionObjectValue ICorDebugExceptionObjectValue; #endif /* __ICorDebugExceptionObjectValue_FWD_DEFINED__ */ #ifndef __CorDebug_FWD_DEFINED__ #define __CorDebug_FWD_DEFINED__ #ifdef __cplusplus typedef class CorDebug CorDebug; #else typedef struct CorDebug CorDebug; #endif /* __cplusplus */ #endif /* __CorDebug_FWD_DEFINED__ */ #ifndef __EmbeddedCLRCorDebug_FWD_DEFINED__ #define __EmbeddedCLRCorDebug_FWD_DEFINED__ #ifdef __cplusplus typedef class EmbeddedCLRCorDebug EmbeddedCLRCorDebug; #else typedef struct EmbeddedCLRCorDebug EmbeddedCLRCorDebug; #endif /* __cplusplus */ #endif /* __EmbeddedCLRCorDebug_FWD_DEFINED__ */ #ifndef __ICorDebugValue_FWD_DEFINED__ #define __ICorDebugValue_FWD_DEFINED__ typedef interface ICorDebugValue ICorDebugValue; #endif /* __ICorDebugValue_FWD_DEFINED__ */ #ifndef __ICorDebugReferenceValue_FWD_DEFINED__ #define __ICorDebugReferenceValue_FWD_DEFINED__ typedef interface ICorDebugReferenceValue ICorDebugReferenceValue; #endif /* __ICorDebugReferenceValue_FWD_DEFINED__ */ #ifndef __ICorDebugHeapValue_FWD_DEFINED__ #define __ICorDebugHeapValue_FWD_DEFINED__ typedef interface ICorDebugHeapValue ICorDebugHeapValue; #endif /* __ICorDebugHeapValue_FWD_DEFINED__ */ #ifndef __ICorDebugStringValue_FWD_DEFINED__ #define __ICorDebugStringValue_FWD_DEFINED__ typedef interface ICorDebugStringValue ICorDebugStringValue; #endif /* __ICorDebugStringValue_FWD_DEFINED__ */ #ifndef __ICorDebugGenericValue_FWD_DEFINED__ #define __ICorDebugGenericValue_FWD_DEFINED__ typedef interface ICorDebugGenericValue ICorDebugGenericValue; #endif /* __ICorDebugGenericValue_FWD_DEFINED__ */ #ifndef __ICorDebugBoxValue_FWD_DEFINED__ #define __ICorDebugBoxValue_FWD_DEFINED__ typedef interface ICorDebugBoxValue ICorDebugBoxValue; #endif /* __ICorDebugBoxValue_FWD_DEFINED__ */ #ifndef __ICorDebugArrayValue_FWD_DEFINED__ #define __ICorDebugArrayValue_FWD_DEFINED__ typedef interface ICorDebugArrayValue ICorDebugArrayValue; #endif /* __ICorDebugArrayValue_FWD_DEFINED__ */ #ifndef __ICorDebugFrame_FWD_DEFINED__ #define __ICorDebugFrame_FWD_DEFINED__ typedef interface ICorDebugFrame ICorDebugFrame; #endif /* __ICorDebugFrame_FWD_DEFINED__ */ #ifndef __ICorDebugILFrame_FWD_DEFINED__ #define __ICorDebugILFrame_FWD_DEFINED__ typedef interface ICorDebugILFrame ICorDebugILFrame; #endif /* __ICorDebugILFrame_FWD_DEFINED__ */ #ifndef __ICorDebugInternalFrame_FWD_DEFINED__ #define __ICorDebugInternalFrame_FWD_DEFINED__ typedef interface ICorDebugInternalFrame ICorDebugInternalFrame; #endif /* __ICorDebugInternalFrame_FWD_DEFINED__ */ #ifndef __ICorDebugInternalFrame2_FWD_DEFINED__ #define __ICorDebugInternalFrame2_FWD_DEFINED__ typedef interface ICorDebugInternalFrame2 ICorDebugInternalFrame2; #endif /* __ICorDebugInternalFrame2_FWD_DEFINED__ */ #ifndef __ICorDebugNativeFrame_FWD_DEFINED__ #define __ICorDebugNativeFrame_FWD_DEFINED__ typedef interface ICorDebugNativeFrame ICorDebugNativeFrame; #endif /* __ICorDebugNativeFrame_FWD_DEFINED__ */ #ifndef __ICorDebugNativeFrame2_FWD_DEFINED__ #define __ICorDebugNativeFrame2_FWD_DEFINED__ typedef interface ICorDebugNativeFrame2 ICorDebugNativeFrame2; #endif /* __ICorDebugNativeFrame2_FWD_DEFINED__ */ #ifndef __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ #define __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ typedef interface ICorDebugRuntimeUnwindableFrame ICorDebugRuntimeUnwindableFrame; #endif /* __ICorDebugRuntimeUnwindableFrame_FWD_DEFINED__ */ #ifndef __ICorDebugManagedCallback2_FWD_DEFINED__ #define __ICorDebugManagedCallback2_FWD_DEFINED__ typedef interface ICorDebugManagedCallback2 ICorDebugManagedCallback2; #endif /* __ICorDebugManagedCallback2_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomain2_FWD_DEFINED__ #define __ICorDebugAppDomain2_FWD_DEFINED__ typedef interface ICorDebugAppDomain2 ICorDebugAppDomain2; #endif /* __ICorDebugAppDomain2_FWD_DEFINED__ */ #ifndef __ICorDebugAppDomain3_FWD_DEFINED__ #define __ICorDebugAppDomain3_FWD_DEFINED__ typedef interface ICorDebugAppDomain3 ICorDebugAppDomain3; #endif /* __ICorDebugAppDomain3_FWD_DEFINED__ */ #ifndef __ICorDebugAssembly2_FWD_DEFINED__ #define __ICorDebugAssembly2_FWD_DEFINED__ typedef interface ICorDebugAssembly2 ICorDebugAssembly2; #endif /* __ICorDebugAssembly2_FWD_DEFINED__ */ #ifndef __ICorDebugProcess2_FWD_DEFINED__ #define __ICorDebugProcess2_FWD_DEFINED__ typedef interface ICorDebugProcess2 ICorDebugProcess2; #endif /* __ICorDebugProcess2_FWD_DEFINED__ */ #ifndef __ICorDebugStepper2_FWD_DEFINED__ #define __ICorDebugStepper2_FWD_DEFINED__ typedef interface ICorDebugStepper2 ICorDebugStepper2; #endif /* __ICorDebugStepper2_FWD_DEFINED__ */ #ifndef __ICorDebugThread2_FWD_DEFINED__ #define __ICorDebugThread2_FWD_DEFINED__ typedef interface ICorDebugThread2 ICorDebugThread2; #endif /* __ICorDebugThread2_FWD_DEFINED__ */ #ifndef __ICorDebugThread3_FWD_DEFINED__ #define __ICorDebugThread3_FWD_DEFINED__ typedef interface ICorDebugThread3 ICorDebugThread3; #endif /* __ICorDebugThread3_FWD_DEFINED__ */ #ifndef __ICorDebugILFrame2_FWD_DEFINED__ #define __ICorDebugILFrame2_FWD_DEFINED__ typedef interface ICorDebugILFrame2 ICorDebugILFrame2; #endif /* __ICorDebugILFrame2_FWD_DEFINED__ */ #ifndef __ICorDebugModule2_FWD_DEFINED__ #define __ICorDebugModule2_FWD_DEFINED__ typedef interface ICorDebugModule2 ICorDebugModule2; #endif /* __ICorDebugModule2_FWD_DEFINED__ */ #ifndef __ICorDebugFunction2_FWD_DEFINED__ #define __ICorDebugFunction2_FWD_DEFINED__ typedef interface ICorDebugFunction2 ICorDebugFunction2; #endif /* __ICorDebugFunction2_FWD_DEFINED__ */ #ifndef __ICorDebugClass2_FWD_DEFINED__ #define __ICorDebugClass2_FWD_DEFINED__ typedef interface ICorDebugClass2 ICorDebugClass2; #endif /* __ICorDebugClass2_FWD_DEFINED__ */ #ifndef __ICorDebugEval2_FWD_DEFINED__ #define __ICorDebugEval2_FWD_DEFINED__ typedef interface ICorDebugEval2 ICorDebugEval2; #endif /* __ICorDebugEval2_FWD_DEFINED__ */ #ifndef __ICorDebugValue2_FWD_DEFINED__ #define __ICorDebugValue2_FWD_DEFINED__ typedef interface ICorDebugValue2 ICorDebugValue2; #endif /* __ICorDebugValue2_FWD_DEFINED__ */ #ifndef __ICorDebugObjectValue2_FWD_DEFINED__ #define __ICorDebugObjectValue2_FWD_DEFINED__ typedef interface ICorDebugObjectValue2 ICorDebugObjectValue2; #endif /* __ICorDebugObjectValue2_FWD_DEFINED__ */ #ifndef __ICorDebugHandleValue_FWD_DEFINED__ #define __ICorDebugHandleValue_FWD_DEFINED__ typedef interface ICorDebugHandleValue ICorDebugHandleValue; #endif /* __ICorDebugHandleValue_FWD_DEFINED__ */ #ifndef __ICorDebugHeapValue2_FWD_DEFINED__ #define __ICorDebugHeapValue2_FWD_DEFINED__ typedef interface ICorDebugHeapValue2 ICorDebugHeapValue2; #endif /* __ICorDebugHeapValue2_FWD_DEFINED__ */ #ifndef __ICorDebugComObjectValue_FWD_DEFINED__ #define __ICorDebugComObjectValue_FWD_DEFINED__ typedef interface ICorDebugComObjectValue ICorDebugComObjectValue; #endif /* __ICorDebugComObjectValue_FWD_DEFINED__ */ #ifndef __ICorDebugModule3_FWD_DEFINED__ #define __ICorDebugModule3_FWD_DEFINED__ typedef interface ICorDebugModule3 ICorDebugModule3; #endif /* __ICorDebugModule3_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #include "objidl.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_cordebug_0000_0000 */ /* [local] */ #if 0 typedef UINT32 mdToken; typedef mdToken mdModule; typedef SIZE_T mdScope; typedef mdToken mdTypeDef; typedef mdToken mdSourceFile; typedef mdToken mdMemberRef; typedef mdToken mdMethodDef; typedef mdToken mdFieldDef; typedef mdToken mdSignature; typedef ULONG CorElementType; typedef SIZE_T PCCOR_SIGNATURE; typedef SIZE_T LPDEBUG_EVENT; typedef SIZE_T LPSTARTUPINFOW; typedef SIZE_T LPPROCESS_INFORMATION; typedef const void *LPCVOID; #endif typedef /* [wire_marshal] */ void *HPROCESS; typedef /* [wire_marshal] */ void *HTHREAD; typedef UINT64 TASKID; typedef DWORD CONNID; #ifndef _COR_IL_MAP #define _COR_IL_MAP typedef struct _COR_IL_MAP { ULONG32 oldOffset; ULONG32 newOffset; BOOL fAccurate; } COR_IL_MAP; #endif //_COR_IL_MAP #ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_ #define _COR_DEBUG_IL_TO_NATIVE_MAP_ typedef enum CorDebugIlToNativeMappingTypes { NO_MAPPING = -1, PROLOG = -2, EPILOG = -3 } CorDebugIlToNativeMappingTypes; typedef struct COR_DEBUG_IL_TO_NATIVE_MAP { ULONG32 ilOffset; ULONG32 nativeStartOffset; ULONG32 nativeEndOffset; } COR_DEBUG_IL_TO_NATIVE_MAP; #endif // _COR_DEBUG_IL_TO_NATIVE_MAP_ #define REMOTE_DEBUGGING_DLL_ENTRY L"Software\\Microsoft\\.NETFramework\\Debugger\\ActivateRemoteDebugging" typedef enum CorDebugJITCompilerFlags { CORDEBUG_JIT_DEFAULT = 0x1, CORDEBUG_JIT_DISABLE_OPTIMIZATION = 0x3, CORDEBUG_JIT_ENABLE_ENC = 0x7 } CorDebugJITCompilerFlags; typedef enum CorDebugJITCompilerFlagsDecprecated { CORDEBUG_JIT_TRACK_DEBUG_INFO = 0x1 } CorDebugJITCompilerFlagsDeprecated; typedef enum CorDebugNGENPolicy { DISABLE_LOCAL_NIC = 1 } CorDebugNGENPolicy; #pragma warning(push) #pragma warning(disable:28718) #pragma warning(pop) typedef ULONG64 CORDB_ADDRESS; typedef ULONG64 CORDB_REGISTER; typedef DWORD CORDB_CONTINUE_STATUS; typedef enum CorDebugBlockingReason { BLOCKING_NONE = 0, BLOCKING_MONITOR_CRITICAL_SECTION = 0x1, BLOCKING_MONITOR_EVENT = 0x2 } CorDebugBlockingReason; typedef struct CorDebugBlockingObject { ICorDebugValue *pBlockingObject; DWORD dwTimeout; CorDebugBlockingReason blockingReason; } CorDebugBlockingObject; typedef struct CorDebugExceptionObjectStackFrame { ICorDebugModule *pModule; CORDB_ADDRESS ip; mdMethodDef methodDef; BOOL isLastForeignExceptionFrame; } CorDebugExceptionObjectStackFrame; typedef struct CorDebugGuidToTypeMapping { GUID iid; ICorDebugType *pType; } CorDebugGuidToTypeMapping; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0000_v0_0_s_ifspec; #ifndef __ICorDebugDataTarget_INTERFACE_DEFINED__ #define __ICorDebugDataTarget_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget */ /* [unique][uuid][local][object] */ typedef enum CorDebugPlatform { CORDB_PLATFORM_WINDOWS_X86 = 0, CORDB_PLATFORM_WINDOWS_AMD64 = ( CORDB_PLATFORM_WINDOWS_X86 + 1 ) , CORDB_PLATFORM_WINDOWS_IA64 = ( CORDB_PLATFORM_WINDOWS_AMD64 + 1 ) , CORDB_PLATFORM_MAC_PPC = ( CORDB_PLATFORM_WINDOWS_IA64 + 1 ) , CORDB_PLATFORM_MAC_X86 = ( CORDB_PLATFORM_MAC_PPC + 1 ) , CORDB_PLATFORM_WINDOWS_ARM = ( CORDB_PLATFORM_MAC_X86 + 1 ) , CORDB_PLATFORM_MAC_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM + 1 ) , CORDB_PLATFORM_WINDOWS_ARM64 = ( CORDB_PLATFORM_MAC_AMD64 + 1 ) , CORDB_PLATFORM_POSIX_AMD64 = ( CORDB_PLATFORM_WINDOWS_ARM64 + 1 ) , CORDB_PLATFORM_POSIX_X86 = ( CORDB_PLATFORM_POSIX_AMD64 + 1 ) , CORDB_PLATFORM_POSIX_ARM = ( CORDB_PLATFORM_POSIX_X86 + 1 ) , CORDB_PLATFORM_POSIX_ARM64 = ( CORDB_PLATFORM_POSIX_ARM + 1 ) , CORDB_PLATFORM_POSIX_LOONGARCH64 = ( CORDB_PLATFORM_POSIX_ARM64 + 1 ) } CorDebugPlatform; EXTERN_C const IID IID_ICorDebugDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FE06DC28-49FB-4636-A4A3-E80DB4AE116C") ICorDebugDataTarget : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetPlatform( /* [out] */ CorDebugPlatform *pTargetPlatform) = 0; virtual HRESULT STDMETHODCALLTYPE ReadVirtual( /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext) = 0; }; #else /* C style interface */ typedef struct ICorDebugDataTargetVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget * This); HRESULT ( STDMETHODCALLTYPE *GetPlatform )( ICorDebugDataTarget * This, /* [out] */ CorDebugPlatform *pTargetPlatform); HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICorDebugDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext); END_INTERFACE } ICorDebugDataTargetVtbl; interface ICorDebugDataTarget { CONST_VTBL struct ICorDebugDataTargetVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugDataTarget_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget_GetPlatform(This,pTargetPlatform) \ ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) #define ICorDebugDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) #define ICorDebugDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugDataTarget_INTERFACE_DEFINED__ */ #ifndef __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ #define __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ /* interface ICorDebugStaticFieldSymbol */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStaticFieldSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CBF9DA63-F68D-4BBB-A21C-15A45EAADF5B") ICorDebugStaticFieldSymbol : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pRVA) = 0; }; #else /* C style interface */ typedef struct ICorDebugStaticFieldSymbolVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStaticFieldSymbol * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStaticFieldSymbol * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStaticFieldSymbol * This); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugStaticFieldSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugStaticFieldSymbol * This, /* [out] */ ULONG32 *pcbSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugStaticFieldSymbol * This, /* [out] */ CORDB_ADDRESS *pRVA); END_INTERFACE } ICorDebugStaticFieldSymbolVtbl; interface ICorDebugStaticFieldSymbol { CONST_VTBL struct ICorDebugStaticFieldSymbolVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugStaticFieldSymbol_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStaticFieldSymbol_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStaticFieldSymbol_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStaticFieldSymbol_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugStaticFieldSymbol_GetSize(This,pcbSize) \ ( (This)->lpVtbl -> GetSize(This,pcbSize) ) #define ICorDebugStaticFieldSymbol_GetAddress(This,pRVA) \ ( (This)->lpVtbl -> GetAddress(This,pRVA) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugStaticFieldSymbol_INTERFACE_DEFINED__ */ #ifndef __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ #define __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ /* interface ICorDebugInstanceFieldSymbol */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugInstanceFieldSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A074096B-3ADC-4485-81DA-68C7A4EA52DB") ICorDebugInstanceFieldSymbol : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ ULONG32 *pcbOffset) = 0; }; #else /* C style interface */ typedef struct ICorDebugInstanceFieldSymbolVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInstanceFieldSymbol * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInstanceFieldSymbol * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInstanceFieldSymbol * This); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugInstanceFieldSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugInstanceFieldSymbol * This, /* [out] */ ULONG32 *pcbSize); HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugInstanceFieldSymbol * This, /* [out] */ ULONG32 *pcbOffset); END_INTERFACE } ICorDebugInstanceFieldSymbolVtbl; interface ICorDebugInstanceFieldSymbol { CONST_VTBL struct ICorDebugInstanceFieldSymbolVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugInstanceFieldSymbol_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInstanceFieldSymbol_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInstanceFieldSymbol_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInstanceFieldSymbol_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugInstanceFieldSymbol_GetSize(This,pcbSize) \ ( (This)->lpVtbl -> GetSize(This,pcbSize) ) #define ICorDebugInstanceFieldSymbol_GetOffset(This,pcbOffset) \ ( (This)->lpVtbl -> GetOffset(This,pcbOffset) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugInstanceFieldSymbol_INTERFACE_DEFINED__ */ #ifndef __ICorDebugVariableSymbol_INTERFACE_DEFINED__ #define __ICorDebugVariableSymbol_INTERFACE_DEFINED__ /* interface ICorDebugVariableSymbol */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugVariableSymbol; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("707E8932-1163-48D9-8A93-F5B1F480FBB7") ICorDebugVariableSymbol : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetValue( /* [in] */ ULONG32 offset, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [out] */ ULONG32 *pcbValue, /* [length_is][size_is][out] */ BYTE pValue[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ ULONG32 offset, /* [in] */ DWORD threadID, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [size_is][in] */ BYTE pValue[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( /* [out] */ ULONG32 *pSlotIndex) = 0; }; #else /* C style interface */ typedef struct ICorDebugVariableSymbolVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableSymbol * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableSymbol * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableSymbol * This); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugVariableSymbol * This, /* [out] */ ULONG32 *pcbValue); HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 offset, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [out] */ ULONG32 *pcbValue, /* [length_is][size_is][out] */ BYTE pValue[ ]); HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugVariableSymbol * This, /* [in] */ ULONG32 offset, /* [in] */ DWORD threadID, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 cbValue, /* [size_is][in] */ BYTE pValue[ ]); HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( ICorDebugVariableSymbol * This, /* [out] */ ULONG32 *pSlotIndex); END_INTERFACE } ICorDebugVariableSymbolVtbl; interface ICorDebugVariableSymbol { CONST_VTBL struct ICorDebugVariableSymbolVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugVariableSymbol_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableSymbol_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableSymbol_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableSymbol_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugVariableSymbol_GetSize(This,pcbValue) \ ( (This)->lpVtbl -> GetSize(This,pcbValue) ) #define ICorDebugVariableSymbol_GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) \ ( (This)->lpVtbl -> GetValue(This,offset,cbContext,context,cbValue,pcbValue,pValue) ) #define ICorDebugVariableSymbol_SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) \ ( (This)->lpVtbl -> SetValue(This,offset,threadID,cbContext,context,cbValue,pValue) ) #define ICorDebugVariableSymbol_GetSlotIndex(This,pSlotIndex) \ ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugVariableSymbol_INTERFACE_DEFINED__ */ #ifndef __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ #define __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ /* interface ICorDebugMemoryBuffer */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMemoryBuffer; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("677888B3-D160-4B8C-A73B-D79E6AAA1D13") ICorDebugMemoryBuffer : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetStartAddress( /* [out] */ LPCVOID *address) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcbBufferLength) = 0; }; #else /* C style interface */ typedef struct ICorDebugMemoryBufferVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMemoryBuffer * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMemoryBuffer * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMemoryBuffer * This); HRESULT ( STDMETHODCALLTYPE *GetStartAddress )( ICorDebugMemoryBuffer * This, /* [out] */ LPCVOID *address); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugMemoryBuffer * This, /* [out] */ ULONG32 *pcbBufferLength); END_INTERFACE } ICorDebugMemoryBufferVtbl; interface ICorDebugMemoryBuffer { CONST_VTBL struct ICorDebugMemoryBufferVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugMemoryBuffer_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMemoryBuffer_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMemoryBuffer_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMemoryBuffer_GetStartAddress(This,address) \ ( (This)->lpVtbl -> GetStartAddress(This,address) ) #define ICorDebugMemoryBuffer_GetSize(This,pcbBufferLength) \ ( (This)->lpVtbl -> GetSize(This,pcbBufferLength) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugMemoryBuffer_INTERFACE_DEFINED__ */ #ifndef __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ #define __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ /* interface ICorDebugMergedAssemblyRecord */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMergedAssemblyRecord; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FAA8637B-3BBE-4671-8E26-3B59875B922A") ICorDebugMergedAssemblyRecord : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetSimpleName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetVersion( /* [out] */ USHORT *pMajor, /* [out] */ USHORT *pMinor, /* [out] */ USHORT *pBuild, /* [out] */ USHORT *pRevision) = 0; virtual HRESULT STDMETHODCALLTYPE GetCulture( /* [in] */ ULONG32 cchCulture, /* [out] */ ULONG32 *pcchCulture, /* [length_is][size_is][out] */ WCHAR szCulture[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetPublicKey( /* [in] */ ULONG32 cbPublicKey, /* [out] */ ULONG32 *pcbPublicKey, /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetPublicKeyToken( /* [in] */ ULONG32 cbPublicKeyToken, /* [out] */ ULONG32 *pcbPublicKeyToken, /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetIndex( /* [out] */ ULONG32 *pIndex) = 0; }; #else /* C style interface */ typedef struct ICorDebugMergedAssemblyRecordVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMergedAssemblyRecord * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMergedAssemblyRecord * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMergedAssemblyRecord * This); HRESULT ( STDMETHODCALLTYPE *GetSimpleName )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetVersion )( ICorDebugMergedAssemblyRecord * This, /* [out] */ USHORT *pMajor, /* [out] */ USHORT *pMinor, /* [out] */ USHORT *pBuild, /* [out] */ USHORT *pRevision); HRESULT ( STDMETHODCALLTYPE *GetCulture )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cchCulture, /* [out] */ ULONG32 *pcchCulture, /* [length_is][size_is][out] */ WCHAR szCulture[ ]); HRESULT ( STDMETHODCALLTYPE *GetPublicKey )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cbPublicKey, /* [out] */ ULONG32 *pcbPublicKey, /* [length_is][size_is][out] */ BYTE pbPublicKey[ ]); HRESULT ( STDMETHODCALLTYPE *GetPublicKeyToken )( ICorDebugMergedAssemblyRecord * This, /* [in] */ ULONG32 cbPublicKeyToken, /* [out] */ ULONG32 *pcbPublicKeyToken, /* [length_is][size_is][out] */ BYTE pbPublicKeyToken[ ]); HRESULT ( STDMETHODCALLTYPE *GetIndex )( ICorDebugMergedAssemblyRecord * This, /* [out] */ ULONG32 *pIndex); END_INTERFACE } ICorDebugMergedAssemblyRecordVtbl; interface ICorDebugMergedAssemblyRecord { CONST_VTBL struct ICorDebugMergedAssemblyRecordVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugMergedAssemblyRecord_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMergedAssemblyRecord_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMergedAssemblyRecord_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMergedAssemblyRecord_GetSimpleName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetSimpleName(This,cchName,pcchName,szName) ) #define ICorDebugMergedAssemblyRecord_GetVersion(This,pMajor,pMinor,pBuild,pRevision) \ ( (This)->lpVtbl -> GetVersion(This,pMajor,pMinor,pBuild,pRevision) ) #define ICorDebugMergedAssemblyRecord_GetCulture(This,cchCulture,pcchCulture,szCulture) \ ( (This)->lpVtbl -> GetCulture(This,cchCulture,pcchCulture,szCulture) ) #define ICorDebugMergedAssemblyRecord_GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) \ ( (This)->lpVtbl -> GetPublicKey(This,cbPublicKey,pcbPublicKey,pbPublicKey) ) #define ICorDebugMergedAssemblyRecord_GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) \ ( (This)->lpVtbl -> GetPublicKeyToken(This,cbPublicKeyToken,pcbPublicKeyToken,pbPublicKeyToken) ) #define ICorDebugMergedAssemblyRecord_GetIndex(This,pIndex) \ ( (This)->lpVtbl -> GetIndex(This,pIndex) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugMergedAssemblyRecord_INTERFACE_DEFINED__ */ #ifndef __ICorDebugSymbolProvider_INTERFACE_DEFINED__ #define __ICorDebugSymbolProvider_INTERFACE_DEFINED__ /* interface ICorDebugSymbolProvider */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugSymbolProvider; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3948A999-FD8A-4C38-A708-8A71E9B04DBB") ICorDebugSymbolProvider : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetStaticFieldSymbols( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetInstanceFieldSymbols( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodLocalSymbols( /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodParameterSymbols( /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMergedAssemblyRecords( /* [in] */ ULONG32 cRequestedRecords, /* [out] */ ULONG32 *pcFetchedRecords, /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodProps( /* [in] */ ULONG32 codeRva, /* [out] */ mdToken *pMethodToken, /* [out] */ ULONG32 *pcGenericParams, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeProps( /* [in] */ ULONG32 vtableRva, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeRange( /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartAddress, ULONG32 *pCodeSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageBytes( /* [in] */ CORDB_ADDRESS rva, /* [in] */ ULONG32 length, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectSize( /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [out] */ ULONG32 *pObjectSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyImageMetadata( /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; }; #else /* C style interface */ typedef struct ICorDebugSymbolProviderVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugSymbolProvider * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugSymbolProvider * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugSymbolProvider * This); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugStaticFieldSymbol *pSymbols[ ]); HRESULT ( STDMETHODCALLTYPE *GetInstanceFieldSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugInstanceFieldSymbol *pSymbols[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodLocalSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodParameterSymbols )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 nativeRVA, /* [in] */ ULONG32 cRequestedSymbols, /* [out] */ ULONG32 *pcFetchedSymbols, /* [length_is][size_is][out] */ ICorDebugVariableSymbol *pSymbols[ ]); HRESULT ( STDMETHODCALLTYPE *GetMergedAssemblyRecords )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cRequestedRecords, /* [out] */ ULONG32 *pcFetchedRecords, /* [length_is][size_is][out] */ ICorDebugMergedAssemblyRecord *pRecords[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodProps )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 codeRva, /* [out] */ mdToken *pMethodToken, /* [out] */ ULONG32 *pcGenericParams, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]); HRESULT ( STDMETHODCALLTYPE *GetTypeProps )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 vtableRva, /* [in] */ ULONG32 cbSignature, /* [out] */ ULONG32 *pcbSignature, /* [length_is][size_is][out] */ BYTE signature[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeRange )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartAddress, ULONG32 *pCodeSize); HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageBytes )( ICorDebugSymbolProvider * This, /* [in] */ CORDB_ADDRESS rva, /* [in] */ ULONG32 length, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorDebugSymbolProvider * This, /* [in] */ ULONG32 cbSignature, /* [size_is][in] */ BYTE typeSig[ ], /* [out] */ ULONG32 *pObjectSize); HRESULT ( STDMETHODCALLTYPE *GetAssemblyImageMetadata )( ICorDebugSymbolProvider * This, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); END_INTERFACE } ICorDebugSymbolProviderVtbl; interface ICorDebugSymbolProvider { CONST_VTBL struct ICorDebugSymbolProviderVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugSymbolProvider_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugSymbolProvider_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugSymbolProvider_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugSymbolProvider_GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ ( (This)->lpVtbl -> GetStaticFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ ( (This)->lpVtbl -> GetInstanceFieldSymbols(This,cbSignature,typeSig,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ ( (This)->lpVtbl -> GetMethodLocalSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) \ ( (This)->lpVtbl -> GetMethodParameterSymbols(This,nativeRVA,cRequestedSymbols,pcFetchedSymbols,pSymbols) ) #define ICorDebugSymbolProvider_GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) \ ( (This)->lpVtbl -> GetMergedAssemblyRecords(This,cRequestedRecords,pcFetchedRecords,pRecords) ) #define ICorDebugSymbolProvider_GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) \ ( (This)->lpVtbl -> GetMethodProps(This,codeRva,pMethodToken,pcGenericParams,cbSignature,pcbSignature,signature) ) #define ICorDebugSymbolProvider_GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) \ ( (This)->lpVtbl -> GetTypeProps(This,vtableRva,cbSignature,pcbSignature,signature) ) #define ICorDebugSymbolProvider_GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) \ ( (This)->lpVtbl -> GetCodeRange(This,codeRva,pCodeStartAddress,pCodeSize) ) #define ICorDebugSymbolProvider_GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) \ ( (This)->lpVtbl -> GetAssemblyImageBytes(This,rva,length,ppMemoryBuffer) ) #define ICorDebugSymbolProvider_GetObjectSize(This,cbSignature,typeSig,pObjectSize) \ ( (This)->lpVtbl -> GetObjectSize(This,cbSignature,typeSig,pObjectSize) ) #define ICorDebugSymbolProvider_GetAssemblyImageMetadata(This,ppMemoryBuffer) \ ( (This)->lpVtbl -> GetAssemblyImageMetadata(This,ppMemoryBuffer) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugSymbolProvider_INTERFACE_DEFINED__ */ #ifndef __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ #define __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ /* interface ICorDebugSymbolProvider2 */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugSymbolProvider2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F9801807-4764-4330-9E67-4F685094165E") ICorDebugSymbolProvider2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetGenericDictionaryInfo( /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetFrameProps( /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartRva, /* [out] */ ULONG32 *pParentFrameStartRva) = 0; }; #else /* C style interface */ typedef struct ICorDebugSymbolProvider2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugSymbolProvider2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugSymbolProvider2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugSymbolProvider2 * This); HRESULT ( STDMETHODCALLTYPE *GetGenericDictionaryInfo )( ICorDebugSymbolProvider2 * This, /* [out] */ ICorDebugMemoryBuffer **ppMemoryBuffer); HRESULT ( STDMETHODCALLTYPE *GetFrameProps )( ICorDebugSymbolProvider2 * This, /* [in] */ ULONG32 codeRva, /* [out] */ ULONG32 *pCodeStartRva, /* [out] */ ULONG32 *pParentFrameStartRva); END_INTERFACE } ICorDebugSymbolProvider2Vtbl; interface ICorDebugSymbolProvider2 { CONST_VTBL struct ICorDebugSymbolProvider2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugSymbolProvider2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugSymbolProvider2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugSymbolProvider2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugSymbolProvider2_GetGenericDictionaryInfo(This,ppMemoryBuffer) \ ( (This)->lpVtbl -> GetGenericDictionaryInfo(This,ppMemoryBuffer) ) #define ICorDebugSymbolProvider2_GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) \ ( (This)->lpVtbl -> GetFrameProps(This,codeRva,pCodeStartRva,pParentFrameStartRva) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugSymbolProvider2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ #define __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ /* interface ICorDebugVirtualUnwinder */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugVirtualUnwinder; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F69126B7-C787-4F6B-AE96-A569786FC670") ICorDebugVirtualUnwinder : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContextBuf, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; }; #else /* C style interface */ typedef struct ICorDebugVirtualUnwinderVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVirtualUnwinder * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVirtualUnwinder * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVirtualUnwinder * This); HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugVirtualUnwinder * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContextBuf, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugVirtualUnwinder * This); END_INTERFACE } ICorDebugVirtualUnwinderVtbl; interface ICorDebugVirtualUnwinder { CONST_VTBL struct ICorDebugVirtualUnwinderVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugVirtualUnwinder_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVirtualUnwinder_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVirtualUnwinder_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVirtualUnwinder_GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) \ ( (This)->lpVtbl -> GetContext(This,contextFlags,cbContextBuf,contextSize,contextBuf) ) #define ICorDebugVirtualUnwinder_Next(This) \ ( (This)->lpVtbl -> Next(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugVirtualUnwinder_INTERFACE_DEFINED__ */ #ifndef __ICorDebugDataTarget2_INTERFACE_DEFINED__ #define __ICorDebugDataTarget2_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget2 */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2eb364da-605b-4e8d-b333-3394c4828d41") ICorDebugDataTarget2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetImageFromPointer( /* [in] */ CORDB_ADDRESS addr, /* [out] */ CORDB_ADDRESS *pImageBase, /* [out] */ ULONG32 *pSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetImageLocation( /* [in] */ CORDB_ADDRESS baseAddress, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSymbolProviderForImage( /* [in] */ CORDB_ADDRESS imageBaseAddress, /* [out] */ ICorDebugSymbolProvider **ppSymProvider) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateThreadIDs( /* [in] */ ULONG32 cThreadIds, /* [out] */ ULONG32 *pcThreadIds, /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE CreateVirtualUnwinder( /* [in] */ DWORD nativeThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE initialContext[ ], /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder) = 0; }; #else /* C style interface */ typedef struct ICorDebugDataTarget2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget2 * This); HRESULT ( STDMETHODCALLTYPE *GetImageFromPointer )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS addr, /* [out] */ CORDB_ADDRESS *pImageBase, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetImageLocation )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS baseAddress, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetSymbolProviderForImage )( ICorDebugDataTarget2 * This, /* [in] */ CORDB_ADDRESS imageBaseAddress, /* [out] */ ICorDebugSymbolProvider **ppSymProvider); HRESULT ( STDMETHODCALLTYPE *EnumerateThreadIDs )( ICorDebugDataTarget2 * This, /* [in] */ ULONG32 cThreadIds, /* [out] */ ULONG32 *pcThreadIds, /* [length_is][size_is][out] */ ULONG32 pThreadIds[ ]); HRESULT ( STDMETHODCALLTYPE *CreateVirtualUnwinder )( ICorDebugDataTarget2 * This, /* [in] */ DWORD nativeThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 cbContext, /* [size_is][in] */ BYTE initialContext[ ], /* [out] */ ICorDebugVirtualUnwinder **ppUnwinder); END_INTERFACE } ICorDebugDataTarget2Vtbl; interface ICorDebugDataTarget2 { CONST_VTBL struct ICorDebugDataTarget2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugDataTarget2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget2_GetImageFromPointer(This,addr,pImageBase,pSize) \ ( (This)->lpVtbl -> GetImageFromPointer(This,addr,pImageBase,pSize) ) #define ICorDebugDataTarget2_GetImageLocation(This,baseAddress,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetImageLocation(This,baseAddress,cchName,pcchName,szName) ) #define ICorDebugDataTarget2_GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) \ ( (This)->lpVtbl -> GetSymbolProviderForImage(This,imageBaseAddress,ppSymProvider) ) #define ICorDebugDataTarget2_EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) \ ( (This)->lpVtbl -> EnumerateThreadIDs(This,cThreadIds,pcThreadIds,pThreadIds) ) #define ICorDebugDataTarget2_CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) \ ( (This)->lpVtbl -> CreateVirtualUnwinder(This,nativeThreadID,contextFlags,cbContext,initialContext,ppUnwinder) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugDataTarget2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugLoadedModule_INTERFACE_DEFINED__ #define __ICorDebugLoadedModule_INTERFACE_DEFINED__ /* interface ICorDebugLoadedModule */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugLoadedModule; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("817F343A-6630-4578-96C5-D11BC0EC5EE2") ICorDebugLoadedModule : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; }; #else /* C style interface */ typedef struct ICorDebugLoadedModuleVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugLoadedModule * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugLoadedModule * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugLoadedModule * This); HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( ICorDebugLoadedModule * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugLoadedModule * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugLoadedModule * This, /* [out] */ ULONG32 *pcBytes); END_INTERFACE } ICorDebugLoadedModuleVtbl; interface ICorDebugLoadedModule { CONST_VTBL struct ICorDebugLoadedModuleVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugLoadedModule_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugLoadedModule_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugLoadedModule_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugLoadedModule_GetBaseAddress(This,pAddress) \ ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) #define ICorDebugLoadedModule_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugLoadedModule_GetSize(This,pcBytes) \ ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugLoadedModule_INTERFACE_DEFINED__ */ #ifndef __ICorDebugDataTarget3_INTERFACE_DEFINED__ #define __ICorDebugDataTarget3_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget3 */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D05E60C3-848C-4E7D-894E-623320FF6AFA") ICorDebugDataTarget3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetLoadedModules( /* [in] */ ULONG32 cRequestedModules, /* [out] */ ULONG32 *pcFetchedModules, /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugDataTarget3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget3 * This); HRESULT ( STDMETHODCALLTYPE *GetLoadedModules )( ICorDebugDataTarget3 * This, /* [in] */ ULONG32 cRequestedModules, /* [out] */ ULONG32 *pcFetchedModules, /* [length_is][size_is][out] */ ICorDebugLoadedModule *pLoadedModules[ ]); END_INTERFACE } ICorDebugDataTarget3Vtbl; interface ICorDebugDataTarget3 { CONST_VTBL struct ICorDebugDataTarget3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugDataTarget3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget3_GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) \ ( (This)->lpVtbl -> GetLoadedModules(This,cRequestedModules,pcFetchedModules,pLoadedModules) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugDataTarget3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugDataTarget4_INTERFACE_DEFINED__ #define __ICorDebugDataTarget4_INTERFACE_DEFINED__ /* interface ICorDebugDataTarget4 */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugDataTarget4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E799DC06-E099-4713-BDD9-906D3CC02CF2") ICorDebugDataTarget4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE VirtualUnwind( /* [in] */ DWORD threadId, /* [in] */ ULONG32 contextSize, /* [size_is][out][in] */ BYTE *context) = 0; }; #else /* C style interface */ typedef struct ICorDebugDataTarget4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDataTarget4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDataTarget4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDataTarget4 * This); HRESULT ( STDMETHODCALLTYPE *VirtualUnwind )( ICorDebugDataTarget4 * This, /* [in] */ DWORD threadId, /* [in] */ ULONG32 contextSize, /* [size_is][out][in] */ BYTE *context); END_INTERFACE } ICorDebugDataTarget4Vtbl; interface ICorDebugDataTarget4 { CONST_VTBL struct ICorDebugDataTarget4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugDataTarget4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDataTarget4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDataTarget4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDataTarget4_VirtualUnwind(This,threadId,contextSize,context) \ ( (This)->lpVtbl -> VirtualUnwind(This,threadId,contextSize,context) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugDataTarget4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ #define __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ /* interface ICorDebugMutableDataTarget */ /* [unique][local][uuid][object] */ EXTERN_C const IID IID_ICorDebugMutableDataTarget; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A1B8A756-3CB6-4CCB-979F-3DF999673A59") ICorDebugMutableDataTarget : public ICorDebugDataTarget { public: virtual HRESULT STDMETHODCALLTYPE WriteVirtual( /* [in] */ CORDB_ADDRESS address, /* [size_is][in] */ const BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested) = 0; virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ const BYTE *pContext) = 0; virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged( /* [in] */ DWORD dwThreadId, /* [in] */ CORDB_CONTINUE_STATUS continueStatus) = 0; }; #else /* C style interface */ typedef struct ICorDebugMutableDataTargetVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMutableDataTarget * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMutableDataTarget * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMutableDataTarget * This); HRESULT ( STDMETHODCALLTYPE *GetPlatform )( ICorDebugMutableDataTarget * This, /* [out] */ CorDebugPlatform *pTargetPlatform); HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( ICorDebugMutableDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [length_is][size_is][out] */ BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *pBytesRead); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *pContext); HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( ICorDebugMutableDataTarget * This, /* [in] */ CORDB_ADDRESS address, /* [size_is][in] */ const BYTE *pBuffer, /* [in] */ ULONG32 bytesRequested); HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ const BYTE *pContext); HRESULT ( STDMETHODCALLTYPE *ContinueStatusChanged )( ICorDebugMutableDataTarget * This, /* [in] */ DWORD dwThreadId, /* [in] */ CORDB_CONTINUE_STATUS continueStatus); END_INTERFACE } ICorDebugMutableDataTargetVtbl; interface ICorDebugMutableDataTarget { CONST_VTBL struct ICorDebugMutableDataTargetVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugMutableDataTarget_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMutableDataTarget_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMutableDataTarget_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMutableDataTarget_GetPlatform(This,pTargetPlatform) \ ( (This)->lpVtbl -> GetPlatform(This,pTargetPlatform) ) #define ICorDebugMutableDataTarget_ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) \ ( (This)->lpVtbl -> ReadVirtual(This,address,pBuffer,bytesRequested,pBytesRead) ) #define ICorDebugMutableDataTarget_GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) \ ( (This)->lpVtbl -> GetThreadContext(This,dwThreadID,contextFlags,contextSize,pContext) ) #define ICorDebugMutableDataTarget_WriteVirtual(This,address,pBuffer,bytesRequested) \ ( (This)->lpVtbl -> WriteVirtual(This,address,pBuffer,bytesRequested) ) #define ICorDebugMutableDataTarget_SetThreadContext(This,dwThreadID,contextSize,pContext) \ ( (This)->lpVtbl -> SetThreadContext(This,dwThreadID,contextSize,pContext) ) #define ICorDebugMutableDataTarget_ContinueStatusChanged(This,dwThreadId,continueStatus) \ ( (This)->lpVtbl -> ContinueStatusChanged(This,dwThreadId,continueStatus) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugMutableDataTarget_INTERFACE_DEFINED__ */ #ifndef __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ #define __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ /* interface ICorDebugMetaDataLocator */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugMetaDataLocator; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("7cef8ba9-2ef7-42bf-973f-4171474f87d9") ICorDebugMetaDataLocator : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetMetaData( /* [in] */ LPCWSTR wszImagePath, /* [in] */ DWORD dwImageTimeStamp, /* [in] */ DWORD dwImageSize, /* [in] */ ULONG32 cchPathBuffer, /* [annotation][out] */ _Out_ ULONG32 *pcchPathBuffer, /* [annotation][length_is][size_is][out] */ _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugMetaDataLocatorVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMetaDataLocator * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMetaDataLocator * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMetaDataLocator * This); HRESULT ( STDMETHODCALLTYPE *GetMetaData )( ICorDebugMetaDataLocator * This, /* [in] */ LPCWSTR wszImagePath, /* [in] */ DWORD dwImageTimeStamp, /* [in] */ DWORD dwImageSize, /* [in] */ ULONG32 cchPathBuffer, /* [annotation][out] */ _Out_ ULONG32 *pcchPathBuffer, /* [annotation][length_is][size_is][out] */ _Out_writes_to_(cchPathBuffer, *pcchPathBuffer) WCHAR wszPathBuffer[ ]); END_INTERFACE } ICorDebugMetaDataLocatorVtbl; interface ICorDebugMetaDataLocator { CONST_VTBL struct ICorDebugMetaDataLocatorVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugMetaDataLocator_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMetaDataLocator_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMetaDataLocator_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMetaDataLocator_GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) \ ( (This)->lpVtbl -> GetMetaData(This,wszImagePath,dwImageTimeStamp,dwImageSize,cchPathBuffer,pcchPathBuffer,wszPathBuffer) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugMetaDataLocator_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0015 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0015_v0_0_s_ifspec; #ifndef __ICorDebugManagedCallback_INTERFACE_DEFINED__ #define __ICorDebugManagedCallback_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback */ /* [unique][uuid][local][object] */ typedef enum CorDebugStepReason { STEP_NORMAL = 0, STEP_RETURN = ( STEP_NORMAL + 1 ) , STEP_CALL = ( STEP_RETURN + 1 ) , STEP_EXCEPTION_FILTER = ( STEP_CALL + 1 ) , STEP_EXCEPTION_HANDLER = ( STEP_EXCEPTION_FILTER + 1 ) , STEP_INTERCEPT = ( STEP_EXCEPTION_HANDLER + 1 ) , STEP_EXIT = ( STEP_INTERCEPT + 1 ) } CorDebugStepReason; typedef enum LoggingLevelEnum { LTraceLevel0 = 0, LTraceLevel1 = ( LTraceLevel0 + 1 ) , LTraceLevel2 = ( LTraceLevel1 + 1 ) , LTraceLevel3 = ( LTraceLevel2 + 1 ) , LTraceLevel4 = ( LTraceLevel3 + 1 ) , LStatusLevel0 = 20, LStatusLevel1 = ( LStatusLevel0 + 1 ) , LStatusLevel2 = ( LStatusLevel1 + 1 ) , LStatusLevel3 = ( LStatusLevel2 + 1 ) , LStatusLevel4 = ( LStatusLevel3 + 1 ) , LWarningLevel = 40, LErrorLevel = 50, LPanicLevel = 100 } LoggingLevelEnum; typedef enum LogSwitchCallReason { SWITCH_CREATE = 0, SWITCH_MODIFY = ( SWITCH_CREATE + 1 ) , SWITCH_DELETE = ( SWITCH_MODIFY + 1 ) } LogSwitchCallReason; EXTERN_C const IID IID_ICorDebugManagedCallback; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3d6f5f60-7538-11d3-8d5b-00104b35e7ef") ICorDebugManagedCallback : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Breakpoint( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint) = 0; virtual HRESULT STDMETHODCALLTYPE StepComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugStepper *pStepper, /* [in] */ CorDebugStepReason reason) = 0; virtual HRESULT STDMETHODCALLTYPE Break( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; virtual HRESULT STDMETHODCALLTYPE Exception( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ BOOL unhandled) = 0; virtual HRESULT STDMETHODCALLTYPE EvalComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval) = 0; virtual HRESULT STDMETHODCALLTYPE EvalException( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval) = 0; virtual HRESULT STDMETHODCALLTYPE CreateProcess( /* [in] */ ICorDebugProcess *pProcess) = 0; virtual HRESULT STDMETHODCALLTYPE ExitProcess( /* [in] */ ICorDebugProcess *pProcess) = 0; virtual HRESULT STDMETHODCALLTYPE CreateThread( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; virtual HRESULT STDMETHODCALLTYPE ExitThread( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread) = 0; virtual HRESULT STDMETHODCALLTYPE LoadModule( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule) = 0; virtual HRESULT STDMETHODCALLTYPE UnloadModule( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule) = 0; virtual HRESULT STDMETHODCALLTYPE LoadClass( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c) = 0; virtual HRESULT STDMETHODCALLTYPE UnloadClass( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c) = 0; virtual HRESULT STDMETHODCALLTYPE DebuggerError( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ HRESULT errorHR, /* [in] */ DWORD errorCode) = 0; virtual HRESULT STDMETHODCALLTYPE LogMessage( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pMessage) = 0; virtual HRESULT STDMETHODCALLTYPE LogSwitch( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ ULONG ulReason, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pParentName) = 0; virtual HRESULT STDMETHODCALLTYPE CreateAppDomain( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; virtual HRESULT STDMETHODCALLTYPE ExitAppDomain( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; virtual HRESULT STDMETHODCALLTYPE LoadAssembly( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly) = 0; virtual HRESULT STDMETHODCALLTYPE UnloadAssembly( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly) = 0; virtual HRESULT STDMETHODCALLTYPE ControlCTrap( /* [in] */ ICorDebugProcess *pProcess) = 0; virtual HRESULT STDMETHODCALLTYPE NameChange( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread) = 0; virtual HRESULT STDMETHODCALLTYPE UpdateModuleSymbols( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule, /* [in] */ IStream *pSymbolStream) = 0; virtual HRESULT STDMETHODCALLTYPE EditAndContinueRemap( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ BOOL fAccurate) = 0; virtual HRESULT STDMETHODCALLTYPE BreakpointSetError( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint, /* [in] */ DWORD dwError) = 0; }; #else /* C style interface */ typedef struct ICorDebugManagedCallbackVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback * This); HRESULT ( STDMETHODCALLTYPE *Breakpoint )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint); HRESULT ( STDMETHODCALLTYPE *StepComplete )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugStepper *pStepper, /* [in] */ CorDebugStepReason reason); HRESULT ( STDMETHODCALLTYPE *Break )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); HRESULT ( STDMETHODCALLTYPE *Exception )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ BOOL unhandled); HRESULT ( STDMETHODCALLTYPE *EvalComplete )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval); HRESULT ( STDMETHODCALLTYPE *EvalException )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugEval *pEval); HRESULT ( STDMETHODCALLTYPE *CreateProcess )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); HRESULT ( STDMETHODCALLTYPE *ExitProcess )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); HRESULT ( STDMETHODCALLTYPE *CreateThread )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); HRESULT ( STDMETHODCALLTYPE *ExitThread )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *thread); HRESULT ( STDMETHODCALLTYPE *LoadModule )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule); HRESULT ( STDMETHODCALLTYPE *UnloadModule )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule); HRESULT ( STDMETHODCALLTYPE *LoadClass )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c); HRESULT ( STDMETHODCALLTYPE *UnloadClass )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugClass *c); HRESULT ( STDMETHODCALLTYPE *DebuggerError )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ HRESULT errorHR, /* [in] */ DWORD errorCode); HRESULT ( STDMETHODCALLTYPE *LogMessage )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pMessage); HRESULT ( STDMETHODCALLTYPE *LogSwitch )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ LONG lLevel, /* [in] */ ULONG ulReason, /* [in] */ WCHAR *pLogSwitchName, /* [in] */ WCHAR *pParentName); HRESULT ( STDMETHODCALLTYPE *CreateAppDomain )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain); HRESULT ( STDMETHODCALLTYPE *ExitAppDomain )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugAppDomain *pAppDomain); HRESULT ( STDMETHODCALLTYPE *LoadAssembly )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly); HRESULT ( STDMETHODCALLTYPE *UnloadAssembly )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugAssembly *pAssembly); HRESULT ( STDMETHODCALLTYPE *ControlCTrap )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugProcess *pProcess); HRESULT ( STDMETHODCALLTYPE *NameChange )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread); HRESULT ( STDMETHODCALLTYPE *UpdateModuleSymbols )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugModule *pModule, /* [in] */ IStream *pSymbolStream); HRESULT ( STDMETHODCALLTYPE *EditAndContinueRemap )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ BOOL fAccurate); HRESULT ( STDMETHODCALLTYPE *BreakpointSetError )( ICorDebugManagedCallback * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugBreakpoint *pBreakpoint, /* [in] */ DWORD dwError); END_INTERFACE } ICorDebugManagedCallbackVtbl; interface ICorDebugManagedCallback { CONST_VTBL struct ICorDebugManagedCallbackVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugManagedCallback_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback_Breakpoint(This,pAppDomain,pThread,pBreakpoint) \ ( (This)->lpVtbl -> Breakpoint(This,pAppDomain,pThread,pBreakpoint) ) #define ICorDebugManagedCallback_StepComplete(This,pAppDomain,pThread,pStepper,reason) \ ( (This)->lpVtbl -> StepComplete(This,pAppDomain,pThread,pStepper,reason) ) #define ICorDebugManagedCallback_Break(This,pAppDomain,thread) \ ( (This)->lpVtbl -> Break(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_Exception(This,pAppDomain,pThread,unhandled) \ ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,unhandled) ) #define ICorDebugManagedCallback_EvalComplete(This,pAppDomain,pThread,pEval) \ ( (This)->lpVtbl -> EvalComplete(This,pAppDomain,pThread,pEval) ) #define ICorDebugManagedCallback_EvalException(This,pAppDomain,pThread,pEval) \ ( (This)->lpVtbl -> EvalException(This,pAppDomain,pThread,pEval) ) #define ICorDebugManagedCallback_CreateProcess(This,pProcess) \ ( (This)->lpVtbl -> CreateProcess(This,pProcess) ) #define ICorDebugManagedCallback_ExitProcess(This,pProcess) \ ( (This)->lpVtbl -> ExitProcess(This,pProcess) ) #define ICorDebugManagedCallback_CreateThread(This,pAppDomain,thread) \ ( (This)->lpVtbl -> CreateThread(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_ExitThread(This,pAppDomain,thread) \ ( (This)->lpVtbl -> ExitThread(This,pAppDomain,thread) ) #define ICorDebugManagedCallback_LoadModule(This,pAppDomain,pModule) \ ( (This)->lpVtbl -> LoadModule(This,pAppDomain,pModule) ) #define ICorDebugManagedCallback_UnloadModule(This,pAppDomain,pModule) \ ( (This)->lpVtbl -> UnloadModule(This,pAppDomain,pModule) ) #define ICorDebugManagedCallback_LoadClass(This,pAppDomain,c) \ ( (This)->lpVtbl -> LoadClass(This,pAppDomain,c) ) #define ICorDebugManagedCallback_UnloadClass(This,pAppDomain,c) \ ( (This)->lpVtbl -> UnloadClass(This,pAppDomain,c) ) #define ICorDebugManagedCallback_DebuggerError(This,pProcess,errorHR,errorCode) \ ( (This)->lpVtbl -> DebuggerError(This,pProcess,errorHR,errorCode) ) #define ICorDebugManagedCallback_LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) \ ( (This)->lpVtbl -> LogMessage(This,pAppDomain,pThread,lLevel,pLogSwitchName,pMessage) ) #define ICorDebugManagedCallback_LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) \ ( (This)->lpVtbl -> LogSwitch(This,pAppDomain,pThread,lLevel,ulReason,pLogSwitchName,pParentName) ) #define ICorDebugManagedCallback_CreateAppDomain(This,pProcess,pAppDomain) \ ( (This)->lpVtbl -> CreateAppDomain(This,pProcess,pAppDomain) ) #define ICorDebugManagedCallback_ExitAppDomain(This,pProcess,pAppDomain) \ ( (This)->lpVtbl -> ExitAppDomain(This,pProcess,pAppDomain) ) #define ICorDebugManagedCallback_LoadAssembly(This,pAppDomain,pAssembly) \ ( (This)->lpVtbl -> LoadAssembly(This,pAppDomain,pAssembly) ) #define ICorDebugManagedCallback_UnloadAssembly(This,pAppDomain,pAssembly) \ ( (This)->lpVtbl -> UnloadAssembly(This,pAppDomain,pAssembly) ) #define ICorDebugManagedCallback_ControlCTrap(This,pProcess) \ ( (This)->lpVtbl -> ControlCTrap(This,pProcess) ) #define ICorDebugManagedCallback_NameChange(This,pAppDomain,pThread) \ ( (This)->lpVtbl -> NameChange(This,pAppDomain,pThread) ) #define ICorDebugManagedCallback_UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) \ ( (This)->lpVtbl -> UpdateModuleSymbols(This,pAppDomain,pModule,pSymbolStream) ) #define ICorDebugManagedCallback_EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) \ ( (This)->lpVtbl -> EditAndContinueRemap(This,pAppDomain,pThread,pFunction,fAccurate) ) #define ICorDebugManagedCallback_BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) \ ( (This)->lpVtbl -> BreakpointSetError(This,pAppDomain,pThread,pBreakpoint,dwError) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugManagedCallback_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0016 */ /* [local] */ #pragma warning(pop) #pragma warning(push) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0016_v0_0_s_ifspec; #ifndef __ICorDebugManagedCallback3_INTERFACE_DEFINED__ #define __ICorDebugManagedCallback3_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugManagedCallback3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("264EA0FC-2591-49AA-868E-835E6515323F") ICorDebugManagedCallback3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CustomNotification( /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugAppDomain *pAppDomain) = 0; }; #else /* C style interface */ typedef struct ICorDebugManagedCallback3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback3 * This); HRESULT ( STDMETHODCALLTYPE *CustomNotification )( ICorDebugManagedCallback3 * This, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugAppDomain *pAppDomain); END_INTERFACE } ICorDebugManagedCallback3Vtbl; interface ICorDebugManagedCallback3 { CONST_VTBL struct ICorDebugManagedCallback3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugManagedCallback3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback3_CustomNotification(This,pThread,pAppDomain) \ ( (This)->lpVtbl -> CustomNotification(This,pThread,pAppDomain) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugManagedCallback3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugManagedCallback4_INTERFACE_DEFINED__ #define __ICorDebugManagedCallback4_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugManagedCallback4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("322911AE-16A5-49BA-84A3-ED69678138A3") ICorDebugManagedCallback4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE BeforeGarbageCollection( /* [in] */ ICorDebugProcess *pProcess) = 0; virtual HRESULT STDMETHODCALLTYPE AfterGarbageCollection( /* [in] */ ICorDebugProcess *pProcess) = 0; virtual HRESULT STDMETHODCALLTYPE DataBreakpoint( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugThread *pThread, /* [in] */ BYTE *pContext, /* [in] */ ULONG32 contextSize) = 0; }; #else /* C style interface */ typedef struct ICorDebugManagedCallback4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback4 * This); HRESULT ( STDMETHODCALLTYPE *BeforeGarbageCollection )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess); HRESULT ( STDMETHODCALLTYPE *AfterGarbageCollection )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess); HRESULT ( STDMETHODCALLTYPE *DataBreakpoint )( ICorDebugManagedCallback4 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ ICorDebugThread *pThread, /* [in] */ BYTE *pContext, /* [in] */ ULONG32 contextSize); END_INTERFACE } ICorDebugManagedCallback4Vtbl; interface ICorDebugManagedCallback4 { CONST_VTBL struct ICorDebugManagedCallback4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugManagedCallback4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback4_BeforeGarbageCollection(This,pProcess) \ ( (This)->lpVtbl -> BeforeGarbageCollection(This,pProcess) ) #define ICorDebugManagedCallback4_AfterGarbageCollection(This,pProcess) \ ( (This)->lpVtbl -> AfterGarbageCollection(This,pProcess) ) #define ICorDebugManagedCallback4_DataBreakpoint(This,pProcess,pThread,pContext,contextSize) \ ( (This)->lpVtbl -> DataBreakpoint(This,pProcess,pThread,pContext,contextSize) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugManagedCallback4_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0018 */ /* [local] */ #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0018_v0_0_s_ifspec; #ifndef __ICorDebugManagedCallback2_INTERFACE_DEFINED__ #define __ICorDebugManagedCallback2_INTERFACE_DEFINED__ /* interface ICorDebugManagedCallback2 */ /* [unique][uuid][local][object] */ typedef enum CorDebugExceptionCallbackType { DEBUG_EXCEPTION_FIRST_CHANCE = 1, DEBUG_EXCEPTION_USER_FIRST_CHANCE = 2, DEBUG_EXCEPTION_CATCH_HANDLER_FOUND = 3, DEBUG_EXCEPTION_UNHANDLED = 4 } CorDebugExceptionCallbackType; typedef enum CorDebugExceptionFlags { DEBUG_EXCEPTION_NONE = 0, DEBUG_EXCEPTION_CAN_BE_INTERCEPTED = 0x1 } CorDebugExceptionFlags; typedef enum CorDebugExceptionUnwindCallbackType { DEBUG_EXCEPTION_UNWIND_BEGIN = 1, DEBUG_EXCEPTION_INTERCEPTED = 2 } CorDebugExceptionUnwindCallbackType; EXTERN_C const IID IID_ICorDebugManagedCallback2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("250E5EEA-DB5C-4C76-B6F3-8C46F12E3203") ICorDebugManagedCallback2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE FunctionRemapOpportunity( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pOldFunction, /* [in] */ ICorDebugFunction *pNewFunction, /* [in] */ ULONG32 oldILOffset) = 0; virtual HRESULT STDMETHODCALLTYPE CreateConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId, /* [in] */ WCHAR *pConnName) = 0; virtual HRESULT STDMETHODCALLTYPE ChangeConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId) = 0; virtual HRESULT STDMETHODCALLTYPE DestroyConnection( /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId) = 0; virtual HRESULT STDMETHODCALLTYPE Exception( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFrame *pFrame, /* [in] */ ULONG32 nOffset, /* [in] */ CorDebugExceptionCallbackType dwEventType, /* [in] */ DWORD dwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionUnwind( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, /* [in] */ DWORD dwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE FunctionRemapComplete( /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction) = 0; virtual HRESULT STDMETHODCALLTYPE MDANotification( /* [in] */ ICorDebugController *pController, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugMDA *pMDA) = 0; }; #else /* C style interface */ typedef struct ICorDebugManagedCallback2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugManagedCallback2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugManagedCallback2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugManagedCallback2 * This); HRESULT ( STDMETHODCALLTYPE *FunctionRemapOpportunity )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pOldFunction, /* [in] */ ICorDebugFunction *pNewFunction, /* [in] */ ULONG32 oldILOffset); HRESULT ( STDMETHODCALLTYPE *CreateConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId, /* [in] */ WCHAR *pConnName); HRESULT ( STDMETHODCALLTYPE *ChangeConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId); HRESULT ( STDMETHODCALLTYPE *DestroyConnection )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugProcess *pProcess, /* [in] */ CONNID dwConnectionId); HRESULT ( STDMETHODCALLTYPE *Exception )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFrame *pFrame, /* [in] */ ULONG32 nOffset, /* [in] */ CorDebugExceptionCallbackType dwEventType, /* [in] */ DWORD dwFlags); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwind )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ CorDebugExceptionUnwindCallbackType dwEventType, /* [in] */ DWORD dwFlags); HRESULT ( STDMETHODCALLTYPE *FunctionRemapComplete )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugAppDomain *pAppDomain, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugFunction *pFunction); HRESULT ( STDMETHODCALLTYPE *MDANotification )( ICorDebugManagedCallback2 * This, /* [in] */ ICorDebugController *pController, /* [in] */ ICorDebugThread *pThread, /* [in] */ ICorDebugMDA *pMDA); END_INTERFACE } ICorDebugManagedCallback2Vtbl; interface ICorDebugManagedCallback2 { CONST_VTBL struct ICorDebugManagedCallback2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugManagedCallback2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugManagedCallback2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugManagedCallback2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugManagedCallback2_FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) \ ( (This)->lpVtbl -> FunctionRemapOpportunity(This,pAppDomain,pThread,pOldFunction,pNewFunction,oldILOffset) ) #define ICorDebugManagedCallback2_CreateConnection(This,pProcess,dwConnectionId,pConnName) \ ( (This)->lpVtbl -> CreateConnection(This,pProcess,dwConnectionId,pConnName) ) #define ICorDebugManagedCallback2_ChangeConnection(This,pProcess,dwConnectionId) \ ( (This)->lpVtbl -> ChangeConnection(This,pProcess,dwConnectionId) ) #define ICorDebugManagedCallback2_DestroyConnection(This,pProcess,dwConnectionId) \ ( (This)->lpVtbl -> DestroyConnection(This,pProcess,dwConnectionId) ) #define ICorDebugManagedCallback2_Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) \ ( (This)->lpVtbl -> Exception(This,pAppDomain,pThread,pFrame,nOffset,dwEventType,dwFlags) ) #define ICorDebugManagedCallback2_ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) \ ( (This)->lpVtbl -> ExceptionUnwind(This,pAppDomain,pThread,dwEventType,dwFlags) ) #define ICorDebugManagedCallback2_FunctionRemapComplete(This,pAppDomain,pThread,pFunction) \ ( (This)->lpVtbl -> FunctionRemapComplete(This,pAppDomain,pThread,pFunction) ) #define ICorDebugManagedCallback2_MDANotification(This,pController,pThread,pMDA) \ ( (This)->lpVtbl -> MDANotification(This,pController,pThread,pMDA) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugManagedCallback2_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0019 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0019_v0_0_s_ifspec; #ifndef __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ #define __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ /* interface ICorDebugUnmanagedCallback */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugUnmanagedCallback; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5263E909-8CB5-11d3-BD2F-0000F80849BD") ICorDebugUnmanagedCallback : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE DebugEvent( /* [in] */ LPDEBUG_EVENT pDebugEvent, /* [in] */ BOOL fOutOfBand) = 0; }; #else /* C style interface */ typedef struct ICorDebugUnmanagedCallbackVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugUnmanagedCallback * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugUnmanagedCallback * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugUnmanagedCallback * This); HRESULT ( STDMETHODCALLTYPE *DebugEvent )( ICorDebugUnmanagedCallback * This, /* [in] */ LPDEBUG_EVENT pDebugEvent, /* [in] */ BOOL fOutOfBand); END_INTERFACE } ICorDebugUnmanagedCallbackVtbl; interface ICorDebugUnmanagedCallback { CONST_VTBL struct ICorDebugUnmanagedCallbackVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugUnmanagedCallback_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugUnmanagedCallback_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugUnmanagedCallback_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugUnmanagedCallback_DebugEvent(This,pDebugEvent,fOutOfBand) \ ( (This)->lpVtbl -> DebugEvent(This,pDebugEvent,fOutOfBand) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugUnmanagedCallback_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0020 */ /* [local] */ typedef enum CorDebugCreateProcessFlags { DEBUG_NO_SPECIAL_OPTIONS = 0 } CorDebugCreateProcessFlags; typedef enum CorDebugHandleType { HANDLE_STRONG = 1, HANDLE_WEAK_TRACK_RESURRECTION = 2, HANDLE_PINNED = 3 } CorDebugHandleType; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0020_v0_0_s_ifspec; #ifndef __ICorDebug_INTERFACE_DEFINED__ #define __ICorDebug_INTERFACE_DEFINED__ /* interface ICorDebug */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebug; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3d6f5f61-7538-11d3-8d5b-00104b35e7ef") ICorDebug : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Initialize( void) = 0; virtual HRESULT STDMETHODCALLTYPE Terminate( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetManagedHandler( /* [in] */ ICorDebugManagedCallback *pCallback) = 0; virtual HRESULT STDMETHODCALLTYPE SetUnmanagedHandler( /* [in] */ ICorDebugUnmanagedCallback *pCallback) = 0; virtual HRESULT STDMETHODCALLTYPE CreateProcess( /* [in] */ LPCWSTR lpApplicationName, /* [in] */ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, /* [in] */ BOOL bInheritHandles, /* [in] */ DWORD dwCreationFlags, /* [in] */ PVOID lpEnvironment, /* [in] */ LPCWSTR lpCurrentDirectory, /* [in] */ LPSTARTUPINFOW lpStartupInfo, /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE DebugActiveProcess( /* [in] */ DWORD id, /* [in] */ BOOL win32Attach, /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateProcesses( /* [out] */ ICorDebugProcessEnum **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [in] */ DWORD dwProcessId, /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE CanLaunchOrAttach( /* [in] */ DWORD dwProcessId, /* [in] */ BOOL win32DebuggingEnabled) = 0; }; #else /* C style interface */ typedef struct ICorDebugVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebug * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebug * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebug * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorDebug * This); HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebug * This); HRESULT ( STDMETHODCALLTYPE *SetManagedHandler )( ICorDebug * This, /* [in] */ ICorDebugManagedCallback *pCallback); HRESULT ( STDMETHODCALLTYPE *SetUnmanagedHandler )( ICorDebug * This, /* [in] */ ICorDebugUnmanagedCallback *pCallback); HRESULT ( STDMETHODCALLTYPE *CreateProcess )( ICorDebug * This, /* [in] */ LPCWSTR lpApplicationName, /* [in] */ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, /* [in] */ BOOL bInheritHandles, /* [in] */ DWORD dwCreationFlags, /* [in] */ PVOID lpEnvironment, /* [in] */ LPCWSTR lpCurrentDirectory, /* [in] */ LPSTARTUPINFOW lpStartupInfo, /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *DebugActiveProcess )( ICorDebug * This, /* [in] */ DWORD id, /* [in] */ BOOL win32Attach, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *EnumerateProcesses )( ICorDebug * This, /* [out] */ ICorDebugProcessEnum **ppProcess); HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebug * This, /* [in] */ DWORD dwProcessId, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *CanLaunchOrAttach )( ICorDebug * This, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL win32DebuggingEnabled); END_INTERFACE } ICorDebugVtbl; interface ICorDebug { CONST_VTBL struct ICorDebugVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebug_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebug_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebug_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebug_Initialize(This) \ ( (This)->lpVtbl -> Initialize(This) ) #define ICorDebug_Terminate(This) \ ( (This)->lpVtbl -> Terminate(This) ) #define ICorDebug_SetManagedHandler(This,pCallback) \ ( (This)->lpVtbl -> SetManagedHandler(This,pCallback) ) #define ICorDebug_SetUnmanagedHandler(This,pCallback) \ ( (This)->lpVtbl -> SetUnmanagedHandler(This,pCallback) ) #define ICorDebug_CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ ( (This)->lpVtbl -> CreateProcess(This,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) #define ICorDebug_DebugActiveProcess(This,id,win32Attach,ppProcess) \ ( (This)->lpVtbl -> DebugActiveProcess(This,id,win32Attach,ppProcess) ) #define ICorDebug_EnumerateProcesses(This,ppProcess) \ ( (This)->lpVtbl -> EnumerateProcesses(This,ppProcess) ) #define ICorDebug_GetProcess(This,dwProcessId,ppProcess) \ ( (This)->lpVtbl -> GetProcess(This,dwProcessId,ppProcess) ) #define ICorDebug_CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) \ ( (This)->lpVtbl -> CanLaunchOrAttach(This,dwProcessId,win32DebuggingEnabled) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebug_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0021 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0021_v0_0_s_ifspec; #ifndef __ICorDebugRemoteTarget_INTERFACE_DEFINED__ #define __ICorDebugRemoteTarget_INTERFACE_DEFINED__ /* interface ICorDebugRemoteTarget */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRemoteTarget; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("C3ED8383-5A49-4cf5-B4B7-01864D9E582D") ICorDebugRemoteTarget : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetHostName( /* [in] */ ULONG32 cchHostName, /* [annotation][out] */ _Out_ ULONG32 *pcchHostName, /* [annotation][length_is][size_is][out] */ _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugRemoteTargetVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRemoteTarget * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRemoteTarget * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRemoteTarget * This); HRESULT ( STDMETHODCALLTYPE *GetHostName )( ICorDebugRemoteTarget * This, /* [in] */ ULONG32 cchHostName, /* [annotation][out] */ _Out_ ULONG32 *pcchHostName, /* [annotation][length_is][size_is][out] */ _Out_writes_to_opt_(cchHostName, *pcchHostName) WCHAR szHostName[ ]); END_INTERFACE } ICorDebugRemoteTargetVtbl; interface ICorDebugRemoteTarget { CONST_VTBL struct ICorDebugRemoteTargetVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugRemoteTarget_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRemoteTarget_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRemoteTarget_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRemoteTarget_GetHostName(This,cchHostName,pcchHostName,szHostName) \ ( (This)->lpVtbl -> GetHostName(This,cchHostName,pcchHostName,szHostName) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugRemoteTarget_INTERFACE_DEFINED__ */ #ifndef __ICorDebugRemote_INTERFACE_DEFINED__ #define __ICorDebugRemote_INTERFACE_DEFINED__ /* interface ICorDebugRemote */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRemote; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D5EBB8E2-7BBE-4c1d-98A6-A3C04CBDEF64") ICorDebugRemote : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CreateProcessEx( /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ LPCWSTR lpApplicationName, /* [annotation][in] */ _In_ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, /* [in] */ BOOL bInheritHandles, /* [in] */ DWORD dwCreationFlags, /* [in] */ PVOID lpEnvironment, /* [in] */ LPCWSTR lpCurrentDirectory, /* [in] */ LPSTARTUPINFOW lpStartupInfo, /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE DebugActiveProcessEx( /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL fWin32Attach, /* [out] */ ICorDebugProcess **ppProcess) = 0; }; #else /* C style interface */ typedef struct ICorDebugRemoteVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRemote * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRemote * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRemote * This); HRESULT ( STDMETHODCALLTYPE *CreateProcessEx )( ICorDebugRemote * This, /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ LPCWSTR lpApplicationName, /* [annotation][in] */ _In_ LPWSTR lpCommandLine, /* [in] */ LPSECURITY_ATTRIBUTES lpProcessAttributes, /* [in] */ LPSECURITY_ATTRIBUTES lpThreadAttributes, /* [in] */ BOOL bInheritHandles, /* [in] */ DWORD dwCreationFlags, /* [in] */ PVOID lpEnvironment, /* [in] */ LPCWSTR lpCurrentDirectory, /* [in] */ LPSTARTUPINFOW lpStartupInfo, /* [in] */ LPPROCESS_INFORMATION lpProcessInformation, /* [in] */ CorDebugCreateProcessFlags debuggingFlags, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *DebugActiveProcessEx )( ICorDebugRemote * This, /* [in] */ ICorDebugRemoteTarget *pRemoteTarget, /* [in] */ DWORD dwProcessId, /* [in] */ BOOL fWin32Attach, /* [out] */ ICorDebugProcess **ppProcess); END_INTERFACE } ICorDebugRemoteVtbl; interface ICorDebugRemote { CONST_VTBL struct ICorDebugRemoteVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugRemote_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRemote_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRemote_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRemote_CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) \ ( (This)->lpVtbl -> CreateProcessEx(This,pRemoteTarget,lpApplicationName,lpCommandLine,lpProcessAttributes,lpThreadAttributes,bInheritHandles,dwCreationFlags,lpEnvironment,lpCurrentDirectory,lpStartupInfo,lpProcessInformation,debuggingFlags,ppProcess) ) #define ICorDebugRemote_DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) \ ( (This)->lpVtbl -> DebugActiveProcessEx(This,pRemoteTarget,dwProcessId,fWin32Attach,ppProcess) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugRemote_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0023 */ /* [local] */ typedef struct _COR_VERSION { DWORD dwMajor; DWORD dwMinor; DWORD dwBuild; DWORD dwSubBuild; } COR_VERSION; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0023_v0_0_s_ifspec; #ifndef __ICorDebug2_INTERFACE_DEFINED__ #define __ICorDebug2_INTERFACE_DEFINED__ /* interface ICorDebug2 */ /* [unique][uuid][local][object] */ typedef enum CorDebugInterfaceVersion { CorDebugInvalidVersion = 0, CorDebugVersion_1_0 = ( CorDebugInvalidVersion + 1 ) , ver_ICorDebugManagedCallback = CorDebugVersion_1_0, ver_ICorDebugUnmanagedCallback = CorDebugVersion_1_0, ver_ICorDebug = CorDebugVersion_1_0, ver_ICorDebugController = CorDebugVersion_1_0, ver_ICorDebugAppDomain = CorDebugVersion_1_0, ver_ICorDebugAssembly = CorDebugVersion_1_0, ver_ICorDebugProcess = CorDebugVersion_1_0, ver_ICorDebugBreakpoint = CorDebugVersion_1_0, ver_ICorDebugFunctionBreakpoint = CorDebugVersion_1_0, ver_ICorDebugModuleBreakpoint = CorDebugVersion_1_0, ver_ICorDebugValueBreakpoint = CorDebugVersion_1_0, ver_ICorDebugStepper = CorDebugVersion_1_0, ver_ICorDebugRegisterSet = CorDebugVersion_1_0, ver_ICorDebugThread = CorDebugVersion_1_0, ver_ICorDebugChain = CorDebugVersion_1_0, ver_ICorDebugFrame = CorDebugVersion_1_0, ver_ICorDebugILFrame = CorDebugVersion_1_0, ver_ICorDebugNativeFrame = CorDebugVersion_1_0, ver_ICorDebugModule = CorDebugVersion_1_0, ver_ICorDebugFunction = CorDebugVersion_1_0, ver_ICorDebugCode = CorDebugVersion_1_0, ver_ICorDebugClass = CorDebugVersion_1_0, ver_ICorDebugEval = CorDebugVersion_1_0, ver_ICorDebugValue = CorDebugVersion_1_0, ver_ICorDebugGenericValue = CorDebugVersion_1_0, ver_ICorDebugReferenceValue = CorDebugVersion_1_0, ver_ICorDebugHeapValue = CorDebugVersion_1_0, ver_ICorDebugObjectValue = CorDebugVersion_1_0, ver_ICorDebugBoxValue = CorDebugVersion_1_0, ver_ICorDebugStringValue = CorDebugVersion_1_0, ver_ICorDebugArrayValue = CorDebugVersion_1_0, ver_ICorDebugContext = CorDebugVersion_1_0, ver_ICorDebugEnum = CorDebugVersion_1_0, ver_ICorDebugObjectEnum = CorDebugVersion_1_0, ver_ICorDebugBreakpointEnum = CorDebugVersion_1_0, ver_ICorDebugStepperEnum = CorDebugVersion_1_0, ver_ICorDebugProcessEnum = CorDebugVersion_1_0, ver_ICorDebugThreadEnum = CorDebugVersion_1_0, ver_ICorDebugFrameEnum = CorDebugVersion_1_0, ver_ICorDebugChainEnum = CorDebugVersion_1_0, ver_ICorDebugModuleEnum = CorDebugVersion_1_0, ver_ICorDebugValueEnum = CorDebugVersion_1_0, ver_ICorDebugCodeEnum = CorDebugVersion_1_0, ver_ICorDebugTypeEnum = CorDebugVersion_1_0, ver_ICorDebugErrorInfoEnum = CorDebugVersion_1_0, ver_ICorDebugAppDomainEnum = CorDebugVersion_1_0, ver_ICorDebugAssemblyEnum = CorDebugVersion_1_0, ver_ICorDebugEditAndContinueErrorInfo = CorDebugVersion_1_0, ver_ICorDebugEditAndContinueSnapshot = CorDebugVersion_1_0, CorDebugVersion_1_1 = ( CorDebugVersion_1_0 + 1 ) , CorDebugVersion_2_0 = ( CorDebugVersion_1_1 + 1 ) , ver_ICorDebugManagedCallback2 = CorDebugVersion_2_0, ver_ICorDebugAppDomain2 = CorDebugVersion_2_0, ver_ICorDebugAssembly2 = CorDebugVersion_2_0, ver_ICorDebugProcess2 = CorDebugVersion_2_0, ver_ICorDebugStepper2 = CorDebugVersion_2_0, ver_ICorDebugRegisterSet2 = CorDebugVersion_2_0, ver_ICorDebugThread2 = CorDebugVersion_2_0, ver_ICorDebugILFrame2 = CorDebugVersion_2_0, ver_ICorDebugInternalFrame = CorDebugVersion_2_0, ver_ICorDebugModule2 = CorDebugVersion_2_0, ver_ICorDebugFunction2 = CorDebugVersion_2_0, ver_ICorDebugCode2 = CorDebugVersion_2_0, ver_ICorDebugClass2 = CorDebugVersion_2_0, ver_ICorDebugValue2 = CorDebugVersion_2_0, ver_ICorDebugEval2 = CorDebugVersion_2_0, ver_ICorDebugObjectValue2 = CorDebugVersion_2_0, CorDebugVersion_4_0 = ( CorDebugVersion_2_0 + 1 ) , ver_ICorDebugThread3 = CorDebugVersion_4_0, ver_ICorDebugThread4 = CorDebugVersion_4_0, ver_ICorDebugStackWalk = CorDebugVersion_4_0, ver_ICorDebugNativeFrame2 = CorDebugVersion_4_0, ver_ICorDebugInternalFrame2 = CorDebugVersion_4_0, ver_ICorDebugRuntimeUnwindableFrame = CorDebugVersion_4_0, ver_ICorDebugHeapValue3 = CorDebugVersion_4_0, ver_ICorDebugBlockingObjectEnum = CorDebugVersion_4_0, ver_ICorDebugValue3 = CorDebugVersion_4_0, CorDebugVersion_4_5 = ( CorDebugVersion_4_0 + 1 ) , ver_ICorDebugComObjectValue = CorDebugVersion_4_5, ver_ICorDebugAppDomain3 = CorDebugVersion_4_5, ver_ICorDebugCode3 = CorDebugVersion_4_5, ver_ICorDebugILFrame3 = CorDebugVersion_4_5, CorDebugLatestVersion = CorDebugVersion_4_5 } CorDebugInterfaceVersion; EXTERN_C const IID IID_ICorDebug2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("ECCCCF2E-B286-4b3e-A983-860A8793D105") ICorDebug2 : public IUnknown { public: }; #else /* C style interface */ typedef struct ICorDebug2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebug2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebug2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebug2 * This); END_INTERFACE } ICorDebug2Vtbl; interface ICorDebug2 { CONST_VTBL struct ICorDebug2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebug2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebug2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebug2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebug2_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0024 */ /* [local] */ typedef enum CorDebugThreadState { THREAD_RUN = 0, THREAD_SUSPEND = ( THREAD_RUN + 1 ) } CorDebugThreadState; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0024_v0_0_s_ifspec; #ifndef __ICorDebugController_INTERFACE_DEFINED__ #define __ICorDebugController_INTERFACE_DEFINED__ /* interface ICorDebugController */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugController; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3d6f5f62-7538-11d3-8d5b-00104b35e7ef") ICorDebugController : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Stop( /* [in] */ DWORD dwTimeoutIgnored) = 0; virtual HRESULT STDMETHODCALLTYPE Continue( /* [in] */ BOOL fIsOutOfBand) = 0; virtual HRESULT STDMETHODCALLTYPE IsRunning( /* [out] */ BOOL *pbRunning) = 0; virtual HRESULT STDMETHODCALLTYPE HasQueuedCallbacks( /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateThreads( /* [out] */ ICorDebugThreadEnum **ppThreads) = 0; virtual HRESULT STDMETHODCALLTYPE SetAllThreadsDebugState( /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread) = 0; virtual HRESULT STDMETHODCALLTYPE Detach( void) = 0; virtual HRESULT STDMETHODCALLTYPE Terminate( /* [in] */ UINT exitCode) = 0; virtual HRESULT STDMETHODCALLTYPE CanCommitChanges( /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; virtual HRESULT STDMETHODCALLTYPE CommitChanges( /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError) = 0; }; #else /* C style interface */ typedef struct ICorDebugControllerVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugController * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugController * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugController * This); HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugController * This, /* [in] */ DWORD dwTimeoutIgnored); HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugController * This, /* [in] */ BOOL fIsOutOfBand); HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugController * This, /* [out] */ BOOL *pbRunning); HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugController * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugController * This, /* [out] */ ICorDebugThreadEnum **ppThreads); HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugController * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugController * This); HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugController * This, /* [in] */ UINT exitCode); HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugController * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugController * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); END_INTERFACE } ICorDebugControllerVtbl; interface ICorDebugController { CONST_VTBL struct ICorDebugControllerVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugController_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugController_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugController_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugController_Stop(This,dwTimeoutIgnored) \ ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugController_Continue(This,fIsOutOfBand) \ ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugController_IsRunning(This,pbRunning) \ ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugController_HasQueuedCallbacks(This,pThread,pbQueued) \ ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugController_EnumerateThreads(This,ppThreads) \ ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugController_SetAllThreadsDebugState(This,state,pExceptThisThread) \ ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugController_Detach(This) \ ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugController_Terminate(This,exitCode) \ ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugController_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugController_CommitChanges(This,cSnapshots,pSnapshots,pError) \ ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugController_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0025 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0025_v0_0_s_ifspec; #ifndef __ICorDebugAppDomain_INTERFACE_DEFINED__ #define __ICorDebugAppDomain_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3d6f5f63-7538-11d3-8d5b-00104b35e7ef") ICorDebugAppDomain : public ICorDebugController { public: virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateAssemblies( /* [out] */ ICorDebugAssemblyEnum **ppAssemblies) = 0; virtual HRESULT STDMETHODCALLTYPE GetModuleFromMetaDataInterface( /* [in] */ IUnknown *pIMetaData, /* [out] */ ICorDebugModule **ppModule) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateBreakpoints( /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateSteppers( /* [out] */ ICorDebugStepperEnum **ppSteppers) = 0; virtual HRESULT STDMETHODCALLTYPE IsAttached( /* [out] */ BOOL *pbAttached) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; virtual HRESULT STDMETHODCALLTYPE Attach( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ ULONG32 *pId) = 0; }; #else /* C style interface */ typedef struct ICorDebugAppDomainVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain * This); HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugAppDomain * This, /* [in] */ DWORD dwTimeoutIgnored); HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugAppDomain * This, /* [in] */ BOOL fIsOutOfBand); HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugAppDomain * This, /* [out] */ BOOL *pbRunning); HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugAppDomain * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugAppDomain * This, /* [out] */ ICorDebugThreadEnum **ppThreads); HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugAppDomain * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugAppDomain * This); HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugAppDomain * This, /* [in] */ UINT exitCode); HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugAppDomain * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugAppDomain * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugAppDomain * This, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *EnumerateAssemblies )( ICorDebugAppDomain * This, /* [out] */ ICorDebugAssemblyEnum **ppAssemblies); HRESULT ( STDMETHODCALLTYPE *GetModuleFromMetaDataInterface )( ICorDebugAppDomain * This, /* [in] */ IUnknown *pIMetaData, /* [out] */ ICorDebugModule **ppModule); HRESULT ( STDMETHODCALLTYPE *EnumerateBreakpoints )( ICorDebugAppDomain * This, /* [out] */ ICorDebugBreakpointEnum **ppBreakpoints); HRESULT ( STDMETHODCALLTYPE *EnumerateSteppers )( ICorDebugAppDomain * This, /* [out] */ ICorDebugStepperEnum **ppSteppers); HRESULT ( STDMETHODCALLTYPE *IsAttached )( ICorDebugAppDomain * This, /* [out] */ BOOL *pbAttached); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugAppDomain * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugAppDomain * This, /* [out] */ ICorDebugValue **ppObject); HRESULT ( STDMETHODCALLTYPE *Attach )( ICorDebugAppDomain * This); HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugAppDomain * This, /* [out] */ ULONG32 *pId); END_INTERFACE } ICorDebugAppDomainVtbl; interface ICorDebugAppDomain { CONST_VTBL struct ICorDebugAppDomainVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAppDomain_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain_Stop(This,dwTimeoutIgnored) \ ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugAppDomain_Continue(This,fIsOutOfBand) \ ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugAppDomain_IsRunning(This,pbRunning) \ ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugAppDomain_HasQueuedCallbacks(This,pThread,pbQueued) \ ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugAppDomain_EnumerateThreads(This,ppThreads) \ ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugAppDomain_SetAllThreadsDebugState(This,state,pExceptThisThread) \ ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugAppDomain_Detach(This) \ ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugAppDomain_Terminate(This,exitCode) \ ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugAppDomain_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugAppDomain_CommitChanges(This,cSnapshots,pSnapshots,pError) \ ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugAppDomain_GetProcess(This,ppProcess) \ ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugAppDomain_EnumerateAssemblies(This,ppAssemblies) \ ( (This)->lpVtbl -> EnumerateAssemblies(This,ppAssemblies) ) #define ICorDebugAppDomain_GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) \ ( (This)->lpVtbl -> GetModuleFromMetaDataInterface(This,pIMetaData,ppModule) ) #define ICorDebugAppDomain_EnumerateBreakpoints(This,ppBreakpoints) \ ( (This)->lpVtbl -> EnumerateBreakpoints(This,ppBreakpoints) ) #define ICorDebugAppDomain_EnumerateSteppers(This,ppSteppers) \ ( (This)->lpVtbl -> EnumerateSteppers(This,ppSteppers) ) #define ICorDebugAppDomain_IsAttached(This,pbAttached) \ ( (This)->lpVtbl -> IsAttached(This,pbAttached) ) #define ICorDebugAppDomain_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugAppDomain_GetObject(This,ppObject) \ ( (This)->lpVtbl -> GetObject(This,ppObject) ) #define ICorDebugAppDomain_Attach(This) \ ( (This)->lpVtbl -> Attach(This) ) #define ICorDebugAppDomain_GetID(This,pId) \ ( (This)->lpVtbl -> GetID(This,pId) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAppDomain_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0026 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0026_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0026_v0_0_s_ifspec; #ifndef __ICorDebugAppDomain2_INTERFACE_DEFINED__ #define __ICorDebugAppDomain2_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("096E81D5-ECDA-4202-83F5-C65980A9EF75") ICorDebugAppDomain2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetArrayOrPointerType( /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nRank, /* [in] */ ICorDebugType *pTypeArg, /* [out] */ ICorDebugType **ppType) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionPointerType( /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType) = 0; }; #else /* C style interface */ typedef struct ICorDebugAppDomain2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain2 * This); HRESULT ( STDMETHODCALLTYPE *GetArrayOrPointerType )( ICorDebugAppDomain2 * This, /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nRank, /* [in] */ ICorDebugType *pTypeArg, /* [out] */ ICorDebugType **ppType); HRESULT ( STDMETHODCALLTYPE *GetFunctionPointerType )( ICorDebugAppDomain2 * This, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType); END_INTERFACE } ICorDebugAppDomain2Vtbl; interface ICorDebugAppDomain2 { CONST_VTBL struct ICorDebugAppDomain2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAppDomain2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain2_GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) \ ( (This)->lpVtbl -> GetArrayOrPointerType(This,elementType,nRank,pTypeArg,ppType) ) #define ICorDebugAppDomain2_GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) \ ( (This)->lpVtbl -> GetFunctionPointerType(This,nTypeArgs,ppTypeArgs,ppType) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAppDomain2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugEnum_INTERFACE_DEFINED__ #define __ICorDebugEnum_INTERFACE_DEFINED__ /* interface ICorDebugEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB01-8A68-11d2-983C-0000F808342D") ICorDebugEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorDebugEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; }; #else /* C style interface */ typedef struct ICorDebugEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugEnum * This, /* [out] */ ULONG *pcelt); END_INTERFACE } ICorDebugEnumVtbl; interface ICorDebugEnum { CONST_VTBL struct ICorDebugEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ #define __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ /* interface ICorDebugGuidToTypeEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGuidToTypeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("6164D242-1015-4BD6-8CBE-D0DBD4B8275A") ICorDebugGuidToTypeEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugGuidToTypeEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGuidToTypeEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGuidToTypeEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGuidToTypeEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugGuidToTypeEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugGuidToTypeEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugGuidToTypeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugGuidToTypeEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugGuidToTypeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugGuidToTypeMapping values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugGuidToTypeEnumVtbl; interface ICorDebugGuidToTypeEnum { CONST_VTBL struct ICorDebugGuidToTypeEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugGuidToTypeEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGuidToTypeEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGuidToTypeEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGuidToTypeEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugGuidToTypeEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugGuidToTypeEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugGuidToTypeEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugGuidToTypeEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugGuidToTypeEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugAppDomain3_INTERFACE_DEFINED__ #define __ICorDebugAppDomain3_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("8CB96A16-B588-42E2-B71C-DD849FC2ECCC") ICorDebugAppDomain3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypesForIIDs( /* [in] */ ULONG32 cReqTypes, /* [size_is][in] */ GUID *iidsToResolve, /* [out] */ ICorDebugTypeEnum **ppTypesEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCachedWinRTTypes( /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum) = 0; }; #else /* C style interface */ typedef struct ICorDebugAppDomain3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain3 * This); HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypesForIIDs )( ICorDebugAppDomain3 * This, /* [in] */ ULONG32 cReqTypes, /* [size_is][in] */ GUID *iidsToResolve, /* [out] */ ICorDebugTypeEnum **ppTypesEnum); HRESULT ( STDMETHODCALLTYPE *GetCachedWinRTTypes )( ICorDebugAppDomain3 * This, /* [out] */ ICorDebugGuidToTypeEnum **ppGuidToTypeEnum); END_INTERFACE } ICorDebugAppDomain3Vtbl; interface ICorDebugAppDomain3 { CONST_VTBL struct ICorDebugAppDomain3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAppDomain3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain3_GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) \ ( (This)->lpVtbl -> GetCachedWinRTTypesForIIDs(This,cReqTypes,iidsToResolve,ppTypesEnum) ) #define ICorDebugAppDomain3_GetCachedWinRTTypes(This,ppGuidToTypeEnum) \ ( (This)->lpVtbl -> GetCachedWinRTTypes(This,ppGuidToTypeEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAppDomain3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugAppDomain4_INTERFACE_DEFINED__ #define __ICorDebugAppDomain4_INTERFACE_DEFINED__ /* interface ICorDebugAppDomain4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomain4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FB99CC40-83BE-4724-AB3B-768E796EBAC2") ICorDebugAppDomain4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetObjectForCCW( /* [in] */ CORDB_ADDRESS ccwPointer, /* [out] */ ICorDebugValue **ppManagedObject) = 0; }; #else /* C style interface */ typedef struct ICorDebugAppDomain4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomain4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomain4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomain4 * This); HRESULT ( STDMETHODCALLTYPE *GetObjectForCCW )( ICorDebugAppDomain4 * This, /* [in] */ CORDB_ADDRESS ccwPointer, /* [out] */ ICorDebugValue **ppManagedObject); END_INTERFACE } ICorDebugAppDomain4Vtbl; interface ICorDebugAppDomain4 { CONST_VTBL struct ICorDebugAppDomain4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAppDomain4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomain4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomain4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomain4_GetObjectForCCW(This,ccwPointer,ppManagedObject) \ ( (This)->lpVtbl -> GetObjectForCCW(This,ccwPointer,ppManagedObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAppDomain4_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0030 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0030_v0_0_s_ifspec; #ifndef __ICorDebugAssembly_INTERFACE_DEFINED__ #define __ICorDebugAssembly_INTERFACE_DEFINED__ /* interface ICorDebugAssembly */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("df59507c-d47a-459e-bce2-6427eac8fd06") ICorDebugAssembly : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateModules( /* [out] */ ICorDebugModuleEnum **ppModules) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeBase( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugAssemblyVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly * This); HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugAssembly * This, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( ICorDebugAssembly * This, /* [out] */ ICorDebugAppDomain **ppAppDomain); HRESULT ( STDMETHODCALLTYPE *EnumerateModules )( ICorDebugAssembly * This, /* [out] */ ICorDebugModuleEnum **ppModules); HRESULT ( STDMETHODCALLTYPE *GetCodeBase )( ICorDebugAssembly * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugAssembly * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); END_INTERFACE } ICorDebugAssemblyVtbl; interface ICorDebugAssembly { CONST_VTBL struct ICorDebugAssemblyVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAssembly_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly_GetProcess(This,ppProcess) \ ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugAssembly_GetAppDomain(This,ppAppDomain) \ ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) #define ICorDebugAssembly_EnumerateModules(This,ppModules) \ ( (This)->lpVtbl -> EnumerateModules(This,ppModules) ) #define ICorDebugAssembly_GetCodeBase(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetCodeBase(This,cchName,pcchName,szName) ) #define ICorDebugAssembly_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAssembly_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0031 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0031_v0_0_s_ifspec; #ifndef __ICorDebugAssembly2_INTERFACE_DEFINED__ #define __ICorDebugAssembly2_INTERFACE_DEFINED__ /* interface ICorDebugAssembly2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("426d1f9e-6dd4-44c8-aec7-26cdbaf4e398") ICorDebugAssembly2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsFullyTrusted( /* [out] */ BOOL *pbFullyTrusted) = 0; }; #else /* C style interface */ typedef struct ICorDebugAssembly2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly2 * This); HRESULT ( STDMETHODCALLTYPE *IsFullyTrusted )( ICorDebugAssembly2 * This, /* [out] */ BOOL *pbFullyTrusted); END_INTERFACE } ICorDebugAssembly2Vtbl; interface ICorDebugAssembly2 { CONST_VTBL struct ICorDebugAssembly2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAssembly2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly2_IsFullyTrusted(This,pbFullyTrusted) \ ( (This)->lpVtbl -> IsFullyTrusted(This,pbFullyTrusted) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAssembly2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugAssembly3_INTERFACE_DEFINED__ #define __ICorDebugAssembly3_INTERFACE_DEFINED__ /* interface ICorDebugAssembly3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssembly3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("76361AB2-8C86-4FE9-96F2-F73D8843570A") ICorDebugAssembly3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetContainerAssembly( ICorDebugAssembly **ppAssembly) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateContainedAssemblies( ICorDebugAssemblyEnum **ppAssemblies) = 0; }; #else /* C style interface */ typedef struct ICorDebugAssembly3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssembly3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssembly3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssembly3 * This); HRESULT ( STDMETHODCALLTYPE *GetContainerAssembly )( ICorDebugAssembly3 * This, ICorDebugAssembly **ppAssembly); HRESULT ( STDMETHODCALLTYPE *EnumerateContainedAssemblies )( ICorDebugAssembly3 * This, ICorDebugAssemblyEnum **ppAssemblies); END_INTERFACE } ICorDebugAssembly3Vtbl; interface ICorDebugAssembly3 { CONST_VTBL struct ICorDebugAssembly3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAssembly3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssembly3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssembly3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssembly3_GetContainerAssembly(This,ppAssembly) \ ( (This)->lpVtbl -> GetContainerAssembly(This,ppAssembly) ) #define ICorDebugAssembly3_EnumerateContainedAssemblies(This,ppAssemblies) \ ( (This)->lpVtbl -> EnumerateContainedAssemblies(This,ppAssemblies) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAssembly3_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0033 */ /* [local] */ #ifndef _DEF_COR_TYPEID_ #define _DEF_COR_TYPEID_ typedef struct COR_TYPEID { UINT64 token1; UINT64 token2; } COR_TYPEID; #endif // _DEF_COR_TYPEID_ typedef struct _COR_HEAPOBJECT { CORDB_ADDRESS address; ULONG64 size; COR_TYPEID type; } COR_HEAPOBJECT; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0033_v0_0_s_ifspec; #ifndef __ICorDebugHeapEnum_INTERFACE_DEFINED__ #define __ICorDebugHeapEnum_INTERFACE_DEFINED__ /* interface ICorDebugHeapEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("76D7DAB8-D044-11DF-9A15-7E29DFD72085") ICorDebugHeapEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugHeapEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugHeapEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugHeapEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugHeapEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugHeapEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugHeapEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_HEAPOBJECT objects[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugHeapEnumVtbl; interface ICorDebugHeapEnum { CONST_VTBL struct ICorDebugHeapEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHeapEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugHeapEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugHeapEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugHeapEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugHeapEnum_Next(This,celt,objects,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHeapEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0034 */ /* [local] */ typedef enum CorDebugGenerationTypes { CorDebug_Gen0 = 0, CorDebug_Gen1 = 1, CorDebug_Gen2 = 2, CorDebug_LOH = 3, CorDebug_POH = 4 } CorDebugGenerationTypes; typedef struct _COR_SEGMENT { CORDB_ADDRESS start; CORDB_ADDRESS end; CorDebugGenerationTypes type; ULONG heap; } COR_SEGMENT; typedef enum CorDebugGCType { CorDebugWorkstationGC = 0, CorDebugServerGC = ( CorDebugWorkstationGC + 1 ) } CorDebugGCType; typedef struct _COR_HEAPINFO { BOOL areGCStructuresValid; DWORD pointerSize; DWORD numHeaps; BOOL concurrent; CorDebugGCType gcType; } COR_HEAPINFO; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0034_v0_0_s_ifspec; #ifndef __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ #define __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ /* interface ICorDebugHeapSegmentEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapSegmentEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A2FA0F8E-D045-11DF-AC8E-CE2ADFD72085") ICorDebugHeapSegmentEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugHeapSegmentEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapSegmentEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapSegmentEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapSegmentEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugHeapSegmentEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugHeapSegmentEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugHeapSegmentEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugHeapSegmentEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugHeapSegmentEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_SEGMENT segments[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugHeapSegmentEnumVtbl; interface ICorDebugHeapSegmentEnum { CONST_VTBL struct ICorDebugHeapSegmentEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHeapSegmentEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapSegmentEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapSegmentEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapSegmentEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugHeapSegmentEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugHeapSegmentEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugHeapSegmentEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugHeapSegmentEnum_Next(This,celt,segments,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,segments,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHeapSegmentEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0035 */ /* [local] */ typedef enum CorGCReferenceType { CorHandleStrong = ( 1 << 0 ) , CorHandleStrongPinning = ( 1 << 1 ) , CorHandleWeakShort = ( 1 << 2 ) , CorHandleWeakLong = ( 1 << 3 ) , CorHandleWeakRefCount = ( 1 << 4 ) , CorHandleStrongRefCount = ( 1 << 5 ) , CorHandleStrongDependent = ( 1 << 6 ) , CorHandleStrongAsyncPinned = ( 1 << 7 ) , CorHandleStrongSizedByref = ( 1 << 8 ) , CorHandleWeakNativeCom = ( 1 << 9 ) , CorHandleWeakWinRT = CorHandleWeakNativeCom, CorReferenceStack = 0x80000001, CorReferenceFinalizer = 80000002, CorHandleStrongOnly = 0x1e3, CorHandleWeakOnly = 0x21c, CorHandleAll = 0x7fffffff } CorGCReferenceType; #ifndef _DEF_COR_GC_REFERENCE_ #define _DEF_COR_GC_REFERENCE_ typedef struct COR_GC_REFERENCE { ICorDebugAppDomain *Domain; ICorDebugValue *Location; CorGCReferenceType Type; UINT64 ExtraData; } COR_GC_REFERENCE; #endif // _DEF_COR_GC_REFERENCE_ extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0035_v0_0_s_ifspec; #ifndef __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ #define __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ /* interface ICorDebugGCReferenceEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGCReferenceEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("7F3C24D3-7E1D-4245-AC3A-F72F8859C80C") ICorDebugGCReferenceEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugGCReferenceEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGCReferenceEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGCReferenceEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGCReferenceEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugGCReferenceEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugGCReferenceEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugGCReferenceEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugGCReferenceEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugGCReferenceEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_GC_REFERENCE roots[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugGCReferenceEnumVtbl; interface ICorDebugGCReferenceEnum { CONST_VTBL struct ICorDebugGCReferenceEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugGCReferenceEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGCReferenceEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGCReferenceEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGCReferenceEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugGCReferenceEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugGCReferenceEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugGCReferenceEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugGCReferenceEnum_Next(This,celt,roots,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,roots,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugGCReferenceEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0036 */ /* [local] */ #ifndef _DEF_COR_ARRAY_LAYOUT_ #define _DEF_COR_ARRAY_LAYOUT_ typedef struct COR_ARRAY_LAYOUT { COR_TYPEID componentID; CorElementType componentType; ULONG32 firstElementOffset; ULONG32 elementSize; ULONG32 countOffset; ULONG32 rankSize; ULONG32 numRanks; ULONG32 rankOffset; } COR_ARRAY_LAYOUT; #endif // _DEF_COR_ARRAY_LAYOUT_ #ifndef _DEF_COR_TYPE_LAYOUT_ #define _DEF_COR_TYPE_LAYOUT_ typedef struct COR_TYPE_LAYOUT { COR_TYPEID parentID; ULONG32 objectSize; ULONG32 numFields; ULONG32 boxOffset; CorElementType type; } COR_TYPE_LAYOUT; #endif // _DEF_COR_TYPE_LAYOUT_ #ifndef _DEF_COR_FIELD_ #define _DEF_COR_FIELD_ typedef struct COR_FIELD { mdFieldDef token; ULONG32 offset; COR_TYPEID id; CorElementType fieldType; } COR_FIELD; #endif // _DEF_COR_FIELD_ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0036_v0_0_s_ifspec; #ifndef __ICorDebugProcess_INTERFACE_DEFINED__ #define __ICorDebugProcess_INTERFACE_DEFINED__ /* interface ICorDebugProcess */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3d6f5f64-7538-11d3-8d5b-00104b35e7ef") ICorDebugProcess : public ICorDebugController { public: virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ DWORD *pdwProcessId) = 0; virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HPROCESS *phProcessHandle) = 0; virtual HRESULT STDMETHODCALLTYPE GetThread( /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugThread **ppThread) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateObjects( /* [out] */ ICorDebugObjectEnum **ppObjects) = 0; virtual HRESULT STDMETHODCALLTYPE IsTransitionStub( /* [in] */ CORDB_ADDRESS address, /* [out] */ BOOL *pbTransitionStub) = 0; virtual HRESULT STDMETHODCALLTYPE IsOSSuspended( /* [in] */ DWORD threadID, /* [out] */ BOOL *pbSuspended) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE ReadMemory( /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ SIZE_T *read) = 0; virtual HRESULT STDMETHODCALLTYPE WriteMemory( /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [size_is][in] */ BYTE buffer[ ], /* [out] */ SIZE_T *written) = 0; virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( /* [in] */ DWORD threadID) = 0; virtual HRESULT STDMETHODCALLTYPE EnableLogMessages( /* [in] */ BOOL fOnOff) = 0; virtual HRESULT STDMETHODCALLTYPE ModifyLogSwitch( /* [annotation][in] */ _In_ WCHAR *pLogSwitchName, /* [in] */ LONG lLevel) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateAppDomains( /* [out] */ ICorDebugAppDomainEnum **ppAppDomains) = 0; virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; virtual HRESULT STDMETHODCALLTYPE ThreadForFiberCookie( /* [in] */ DWORD fiberCookie, /* [out] */ ICorDebugThread **ppThread) = 0; virtual HRESULT STDMETHODCALLTYPE GetHelperThreadID( /* [out] */ DWORD *pThreadID) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcessVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess * This); HRESULT ( STDMETHODCALLTYPE *Stop )( ICorDebugProcess * This, /* [in] */ DWORD dwTimeoutIgnored); HRESULT ( STDMETHODCALLTYPE *Continue )( ICorDebugProcess * This, /* [in] */ BOOL fIsOutOfBand); HRESULT ( STDMETHODCALLTYPE *IsRunning )( ICorDebugProcess * This, /* [out] */ BOOL *pbRunning); HRESULT ( STDMETHODCALLTYPE *HasQueuedCallbacks )( ICorDebugProcess * This, /* [in] */ ICorDebugThread *pThread, /* [out] */ BOOL *pbQueued); HRESULT ( STDMETHODCALLTYPE *EnumerateThreads )( ICorDebugProcess * This, /* [out] */ ICorDebugThreadEnum **ppThreads); HRESULT ( STDMETHODCALLTYPE *SetAllThreadsDebugState )( ICorDebugProcess * This, /* [in] */ CorDebugThreadState state, /* [in] */ ICorDebugThread *pExceptThisThread); HRESULT ( STDMETHODCALLTYPE *Detach )( ICorDebugProcess * This); HRESULT ( STDMETHODCALLTYPE *Terminate )( ICorDebugProcess * This, /* [in] */ UINT exitCode); HRESULT ( STDMETHODCALLTYPE *CanCommitChanges )( ICorDebugProcess * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); HRESULT ( STDMETHODCALLTYPE *CommitChanges )( ICorDebugProcess * This, /* [in] */ ULONG cSnapshots, /* [size_is][in] */ ICorDebugEditAndContinueSnapshot *pSnapshots[ ], /* [out] */ ICorDebugErrorInfoEnum **pError); HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugProcess * This, /* [out] */ DWORD *pdwProcessId); HRESULT ( STDMETHODCALLTYPE *GetHandle )( ICorDebugProcess * This, /* [out] */ HPROCESS *phProcessHandle); HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugProcess * This, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugThread **ppThread); HRESULT ( STDMETHODCALLTYPE *EnumerateObjects )( ICorDebugProcess * This, /* [out] */ ICorDebugObjectEnum **ppObjects); HRESULT ( STDMETHODCALLTYPE *IsTransitionStub )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [out] */ BOOL *pbTransitionStub); HRESULT ( STDMETHODCALLTYPE *IsOSSuspended )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [out] */ BOOL *pbSuspended); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]); HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugProcess * This, /* [in] */ DWORD threadID, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]); HRESULT ( STDMETHODCALLTYPE *ReadMemory )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ SIZE_T *read); HRESULT ( STDMETHODCALLTYPE *WriteMemory )( ICorDebugProcess * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ DWORD size, /* [size_is][in] */ BYTE buffer[ ], /* [out] */ SIZE_T *written); HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( ICorDebugProcess * This, /* [in] */ DWORD threadID); HRESULT ( STDMETHODCALLTYPE *EnableLogMessages )( ICorDebugProcess * This, /* [in] */ BOOL fOnOff); HRESULT ( STDMETHODCALLTYPE *ModifyLogSwitch )( ICorDebugProcess * This, /* [annotation][in] */ _In_ WCHAR *pLogSwitchName, /* [in] */ LONG lLevel); HRESULT ( STDMETHODCALLTYPE *EnumerateAppDomains )( ICorDebugProcess * This, /* [out] */ ICorDebugAppDomainEnum **ppAppDomains); HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugProcess * This, /* [out] */ ICorDebugValue **ppObject); HRESULT ( STDMETHODCALLTYPE *ThreadForFiberCookie )( ICorDebugProcess * This, /* [in] */ DWORD fiberCookie, /* [out] */ ICorDebugThread **ppThread); HRESULT ( STDMETHODCALLTYPE *GetHelperThreadID )( ICorDebugProcess * This, /* [out] */ DWORD *pThreadID); END_INTERFACE } ICorDebugProcessVtbl; interface ICorDebugProcess { CONST_VTBL struct ICorDebugProcessVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess_Stop(This,dwTimeoutIgnored) \ ( (This)->lpVtbl -> Stop(This,dwTimeoutIgnored) ) #define ICorDebugProcess_Continue(This,fIsOutOfBand) \ ( (This)->lpVtbl -> Continue(This,fIsOutOfBand) ) #define ICorDebugProcess_IsRunning(This,pbRunning) \ ( (This)->lpVtbl -> IsRunning(This,pbRunning) ) #define ICorDebugProcess_HasQueuedCallbacks(This,pThread,pbQueued) \ ( (This)->lpVtbl -> HasQueuedCallbacks(This,pThread,pbQueued) ) #define ICorDebugProcess_EnumerateThreads(This,ppThreads) \ ( (This)->lpVtbl -> EnumerateThreads(This,ppThreads) ) #define ICorDebugProcess_SetAllThreadsDebugState(This,state,pExceptThisThread) \ ( (This)->lpVtbl -> SetAllThreadsDebugState(This,state,pExceptThisThread) ) #define ICorDebugProcess_Detach(This) \ ( (This)->lpVtbl -> Detach(This) ) #define ICorDebugProcess_Terminate(This,exitCode) \ ( (This)->lpVtbl -> Terminate(This,exitCode) ) #define ICorDebugProcess_CanCommitChanges(This,cSnapshots,pSnapshots,pError) \ ( (This)->lpVtbl -> CanCommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugProcess_CommitChanges(This,cSnapshots,pSnapshots,pError) \ ( (This)->lpVtbl -> CommitChanges(This,cSnapshots,pSnapshots,pError) ) #define ICorDebugProcess_GetID(This,pdwProcessId) \ ( (This)->lpVtbl -> GetID(This,pdwProcessId) ) #define ICorDebugProcess_GetHandle(This,phProcessHandle) \ ( (This)->lpVtbl -> GetHandle(This,phProcessHandle) ) #define ICorDebugProcess_GetThread(This,dwThreadId,ppThread) \ ( (This)->lpVtbl -> GetThread(This,dwThreadId,ppThread) ) #define ICorDebugProcess_EnumerateObjects(This,ppObjects) \ ( (This)->lpVtbl -> EnumerateObjects(This,ppObjects) ) #define ICorDebugProcess_IsTransitionStub(This,address,pbTransitionStub) \ ( (This)->lpVtbl -> IsTransitionStub(This,address,pbTransitionStub) ) #define ICorDebugProcess_IsOSSuspended(This,threadID,pbSuspended) \ ( (This)->lpVtbl -> IsOSSuspended(This,threadID,pbSuspended) ) #define ICorDebugProcess_GetThreadContext(This,threadID,contextSize,context) \ ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextSize,context) ) #define ICorDebugProcess_SetThreadContext(This,threadID,contextSize,context) \ ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define ICorDebugProcess_ReadMemory(This,address,size,buffer,read) \ ( (This)->lpVtbl -> ReadMemory(This,address,size,buffer,read) ) #define ICorDebugProcess_WriteMemory(This,address,size,buffer,written) \ ( (This)->lpVtbl -> WriteMemory(This,address,size,buffer,written) ) #define ICorDebugProcess_ClearCurrentException(This,threadID) \ ( (This)->lpVtbl -> ClearCurrentException(This,threadID) ) #define ICorDebugProcess_EnableLogMessages(This,fOnOff) \ ( (This)->lpVtbl -> EnableLogMessages(This,fOnOff) ) #define ICorDebugProcess_ModifyLogSwitch(This,pLogSwitchName,lLevel) \ ( (This)->lpVtbl -> ModifyLogSwitch(This,pLogSwitchName,lLevel) ) #define ICorDebugProcess_EnumerateAppDomains(This,ppAppDomains) \ ( (This)->lpVtbl -> EnumerateAppDomains(This,ppAppDomains) ) #define ICorDebugProcess_GetObject(This,ppObject) \ ( (This)->lpVtbl -> GetObject(This,ppObject) ) #define ICorDebugProcess_ThreadForFiberCookie(This,fiberCookie,ppThread) \ ( (This)->lpVtbl -> ThreadForFiberCookie(This,fiberCookie,ppThread) ) #define ICorDebugProcess_GetHelperThreadID(This,pThreadID) \ ( (This)->lpVtbl -> GetHelperThreadID(This,pThreadID) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0037 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0037_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0037_v0_0_s_ifspec; #ifndef __ICorDebugProcess2_INTERFACE_DEFINED__ #define __ICorDebugProcess2_INTERFACE_DEFINED__ /* interface ICorDebugProcess2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AD1B3588-0EF0-4744-A496-AA09A9F80371") ICorDebugProcess2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetThreadForTaskID( /* [in] */ TASKID taskid, /* [out] */ ICorDebugThread2 **ppThread) = 0; virtual HRESULT STDMETHODCALLTYPE GetVersion( /* [out] */ COR_VERSION *version) = 0; virtual HRESULT STDMETHODCALLTYPE SetUnmanagedBreakpoint( /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG32 bufsize, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *bufLen) = 0; virtual HRESULT STDMETHODCALLTYPE ClearUnmanagedBreakpoint( /* [in] */ CORDB_ADDRESS address) = 0; virtual HRESULT STDMETHODCALLTYPE SetDesiredNGENCompilerFlags( /* [in] */ DWORD pdwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetDesiredNGENCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetReferenceValueFromGCHandle( /* [in] */ UINT_PTR handle, /* [out] */ ICorDebugReferenceValue **pOutValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess2 * This); HRESULT ( STDMETHODCALLTYPE *GetThreadForTaskID )( ICorDebugProcess2 * This, /* [in] */ TASKID taskid, /* [out] */ ICorDebugThread2 **ppThread); HRESULT ( STDMETHODCALLTYPE *GetVersion )( ICorDebugProcess2 * This, /* [out] */ COR_VERSION *version); HRESULT ( STDMETHODCALLTYPE *SetUnmanagedBreakpoint )( ICorDebugProcess2 * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG32 bufsize, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *bufLen); HRESULT ( STDMETHODCALLTYPE *ClearUnmanagedBreakpoint )( ICorDebugProcess2 * This, /* [in] */ CORDB_ADDRESS address); HRESULT ( STDMETHODCALLTYPE *SetDesiredNGENCompilerFlags )( ICorDebugProcess2 * This, /* [in] */ DWORD pdwFlags); HRESULT ( STDMETHODCALLTYPE *GetDesiredNGENCompilerFlags )( ICorDebugProcess2 * This, /* [out] */ DWORD *pdwFlags); HRESULT ( STDMETHODCALLTYPE *GetReferenceValueFromGCHandle )( ICorDebugProcess2 * This, /* [in] */ UINT_PTR handle, /* [out] */ ICorDebugReferenceValue **pOutValue); END_INTERFACE } ICorDebugProcess2Vtbl; interface ICorDebugProcess2 { CONST_VTBL struct ICorDebugProcess2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess2_GetThreadForTaskID(This,taskid,ppThread) \ ( (This)->lpVtbl -> GetThreadForTaskID(This,taskid,ppThread) ) #define ICorDebugProcess2_GetVersion(This,version) \ ( (This)->lpVtbl -> GetVersion(This,version) ) #define ICorDebugProcess2_SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) \ ( (This)->lpVtbl -> SetUnmanagedBreakpoint(This,address,bufsize,buffer,bufLen) ) #define ICorDebugProcess2_ClearUnmanagedBreakpoint(This,address) \ ( (This)->lpVtbl -> ClearUnmanagedBreakpoint(This,address) ) #define ICorDebugProcess2_SetDesiredNGENCompilerFlags(This,pdwFlags) \ ( (This)->lpVtbl -> SetDesiredNGENCompilerFlags(This,pdwFlags) ) #define ICorDebugProcess2_GetDesiredNGENCompilerFlags(This,pdwFlags) \ ( (This)->lpVtbl -> GetDesiredNGENCompilerFlags(This,pdwFlags) ) #define ICorDebugProcess2_GetReferenceValueFromGCHandle(This,handle,pOutValue) \ ( (This)->lpVtbl -> GetReferenceValueFromGCHandle(This,handle,pOutValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugProcess3_INTERFACE_DEFINED__ #define __ICorDebugProcess3_INTERFACE_DEFINED__ /* interface ICorDebugProcess3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2EE06488-C0D4-42B1-B26D-F3795EF606FB") ICorDebugProcess3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetEnableCustomNotification( ICorDebugClass *pClass, BOOL fEnable) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess3 * This); HRESULT ( STDMETHODCALLTYPE *SetEnableCustomNotification )( ICorDebugProcess3 * This, ICorDebugClass *pClass, BOOL fEnable); END_INTERFACE } ICorDebugProcess3Vtbl; interface ICorDebugProcess3 { CONST_VTBL struct ICorDebugProcess3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess3_SetEnableCustomNotification(This,pClass,fEnable) \ ( (This)->lpVtbl -> SetEnableCustomNotification(This,pClass,fEnable) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugProcess5_INTERFACE_DEFINED__ #define __ICorDebugProcess5_INTERFACE_DEFINED__ /* interface ICorDebugProcess5 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("21e9d9c0-fcb8-11df-8cff-0800200c9a66") ICorDebugProcess5 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetGCHeapInformation( /* [out] */ COR_HEAPINFO *pHeapInfo) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateHeap( /* [out] */ ICorDebugHeapEnum **ppObjects) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateHeapRegions( /* [out] */ ICorDebugHeapSegmentEnum **ppRegions) = 0; virtual HRESULT STDMETHODCALLTYPE GetObject( /* [in] */ CORDB_ADDRESS addr, /* [out] */ ICorDebugObjectValue **pObject) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateGCReferences( /* [in] */ BOOL enumerateWeakReferences, /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateHandles( /* [in] */ CorGCReferenceType types, /* [out] */ ICorDebugGCReferenceEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeID( /* [in] */ CORDB_ADDRESS obj, /* [out] */ COR_TYPEID *pId) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeForTypeID( /* [in] */ COR_TYPEID id, /* [out] */ ICorDebugType **ppType) = 0; virtual HRESULT STDMETHODCALLTYPE GetArrayLayout( /* [in] */ COR_TYPEID id, /* [out] */ COR_ARRAY_LAYOUT *pLayout) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeLayout( /* [in] */ COR_TYPEID id, /* [out] */ COR_TYPE_LAYOUT *pLayout) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeFields( /* [in] */ COR_TYPEID id, ULONG32 celt, COR_FIELD fields[ ], ULONG32 *pceltNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE EnableNGENPolicy( /* [in] */ CorDebugNGENPolicy ePolicy) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess5 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess5 * This); HRESULT ( STDMETHODCALLTYPE *GetGCHeapInformation )( ICorDebugProcess5 * This, /* [out] */ COR_HEAPINFO *pHeapInfo); HRESULT ( STDMETHODCALLTYPE *EnumerateHeap )( ICorDebugProcess5 * This, /* [out] */ ICorDebugHeapEnum **ppObjects); HRESULT ( STDMETHODCALLTYPE *EnumerateHeapRegions )( ICorDebugProcess5 * This, /* [out] */ ICorDebugHeapSegmentEnum **ppRegions); HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugProcess5 * This, /* [in] */ CORDB_ADDRESS addr, /* [out] */ ICorDebugObjectValue **pObject); HRESULT ( STDMETHODCALLTYPE *EnumerateGCReferences )( ICorDebugProcess5 * This, /* [in] */ BOOL enumerateWeakReferences, /* [out] */ ICorDebugGCReferenceEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *EnumerateHandles )( ICorDebugProcess5 * This, /* [in] */ CorGCReferenceType types, /* [out] */ ICorDebugGCReferenceEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetTypeID )( ICorDebugProcess5 * This, /* [in] */ CORDB_ADDRESS obj, /* [out] */ COR_TYPEID *pId); HRESULT ( STDMETHODCALLTYPE *GetTypeForTypeID )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ ICorDebugType **ppType); HRESULT ( STDMETHODCALLTYPE *GetArrayLayout )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ COR_ARRAY_LAYOUT *pLayout); HRESULT ( STDMETHODCALLTYPE *GetTypeLayout )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, /* [out] */ COR_TYPE_LAYOUT *pLayout); HRESULT ( STDMETHODCALLTYPE *GetTypeFields )( ICorDebugProcess5 * This, /* [in] */ COR_TYPEID id, ULONG32 celt, COR_FIELD fields[ ], ULONG32 *pceltNeeded); HRESULT ( STDMETHODCALLTYPE *EnableNGENPolicy )( ICorDebugProcess5 * This, /* [in] */ CorDebugNGENPolicy ePolicy); END_INTERFACE } ICorDebugProcess5Vtbl; interface ICorDebugProcess5 { CONST_VTBL struct ICorDebugProcess5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess5_GetGCHeapInformation(This,pHeapInfo) \ ( (This)->lpVtbl -> GetGCHeapInformation(This,pHeapInfo) ) #define ICorDebugProcess5_EnumerateHeap(This,ppObjects) \ ( (This)->lpVtbl -> EnumerateHeap(This,ppObjects) ) #define ICorDebugProcess5_EnumerateHeapRegions(This,ppRegions) \ ( (This)->lpVtbl -> EnumerateHeapRegions(This,ppRegions) ) #define ICorDebugProcess5_GetObject(This,addr,pObject) \ ( (This)->lpVtbl -> GetObject(This,addr,pObject) ) #define ICorDebugProcess5_EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) \ ( (This)->lpVtbl -> EnumerateGCReferences(This,enumerateWeakReferences,ppEnum) ) #define ICorDebugProcess5_EnumerateHandles(This,types,ppEnum) \ ( (This)->lpVtbl -> EnumerateHandles(This,types,ppEnum) ) #define ICorDebugProcess5_GetTypeID(This,obj,pId) \ ( (This)->lpVtbl -> GetTypeID(This,obj,pId) ) #define ICorDebugProcess5_GetTypeForTypeID(This,id,ppType) \ ( (This)->lpVtbl -> GetTypeForTypeID(This,id,ppType) ) #define ICorDebugProcess5_GetArrayLayout(This,id,pLayout) \ ( (This)->lpVtbl -> GetArrayLayout(This,id,pLayout) ) #define ICorDebugProcess5_GetTypeLayout(This,id,pLayout) \ ( (This)->lpVtbl -> GetTypeLayout(This,id,pLayout) ) #define ICorDebugProcess5_GetTypeFields(This,id,celt,fields,pceltNeeded) \ ( (This)->lpVtbl -> GetTypeFields(This,id,celt,fields,pceltNeeded) ) #define ICorDebugProcess5_EnableNGENPolicy(This,ePolicy) \ ( (This)->lpVtbl -> EnableNGENPolicy(This,ePolicy) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess5_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0040 */ /* [local] */ typedef enum CorDebugRecordFormat { FORMAT_WINDOWS_EXCEPTIONRECORD32 = 1, FORMAT_WINDOWS_EXCEPTIONRECORD64 = 2 } CorDebugRecordFormat; typedef enum CorDebugDecodeEventFlagsWindows { IS_FIRST_CHANCE = 1 } CorDebugDecodeEventFlagsWindows; typedef enum CorDebugDebugEventKind { DEBUG_EVENT_KIND_MODULE_LOADED = 1, DEBUG_EVENT_KIND_MODULE_UNLOADED = 2, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_FIRST_CHANCE = 3, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_USER_FIRST_CHANCE = 4, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_CATCH_HANDLER_FOUND = 5, DEBUG_EVENT_KIND_MANAGED_EXCEPTION_UNHANDLED = 6 } CorDebugDebugEventKind; typedef enum CorDebugStateChange { PROCESS_RUNNING = 0x1, FLUSH_ALL = 0x2 } CorDebugStateChange; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0040_v0_0_s_ifspec; #ifndef __ICorDebugDebugEvent_INTERFACE_DEFINED__ #define __ICorDebugDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugDebugEvent */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("41BD395D-DE99-48F1-BF7A-CC0F44A6D281") ICorDebugDebugEvent : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetEventKind( /* [out] */ CorDebugDebugEventKind *pDebugEventKind) = 0; virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; }; #else /* C style interface */ typedef struct ICorDebugDebugEventVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDebugEvent * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDebugEvent * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDebugEvent * This); HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); END_INTERFACE } ICorDebugDebugEventVtbl; interface ICorDebugDebugEvent { CONST_VTBL struct ICorDebugDebugEventVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugDebugEvent_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDebugEvent_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDebugEvent_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDebugEvent_GetEventKind(This,pDebugEventKind) \ ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugDebugEvent_GetThread(This,ppThread) \ ( (This)->lpVtbl -> GetThread(This,ppThread) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugDebugEvent_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0041 */ /* [local] */ typedef enum CorDebugCodeInvokeKind { CODE_INVOKE_KIND_NONE = 0, CODE_INVOKE_KIND_RETURN = ( CODE_INVOKE_KIND_NONE + 1 ) , CODE_INVOKE_KIND_TAILCALL = ( CODE_INVOKE_KIND_RETURN + 1 ) } CorDebugCodeInvokeKind; typedef enum CorDebugCodeInvokePurpose { CODE_INVOKE_PURPOSE_NONE = 0, CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION = ( CODE_INVOKE_PURPOSE_NONE + 1 ) , CODE_INVOKE_PURPOSE_CLASS_INIT = ( CODE_INVOKE_PURPOSE_NATIVE_TO_MANAGED_TRANSITION + 1 ) , CODE_INVOKE_PURPOSE_INTERFACE_DISPATCH = ( CODE_INVOKE_PURPOSE_CLASS_INIT + 1 ) } CorDebugCodeInvokePurpose; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0041_v0_0_s_ifspec; #ifndef __ICorDebugProcess6_INTERFACE_DEFINED__ #define __ICorDebugProcess6_INTERFACE_DEFINED__ /* interface ICorDebugProcess6 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess6; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("11588775-7205-4CEB-A41A-93753C3153E9") ICorDebugProcess6 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE DecodeEvent( /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, /* [in] */ CorDebugRecordFormat format, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugDebugEvent **ppEvent) = 0; virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( /* [in] */ CorDebugStateChange change) = 0; virtual HRESULT STDMETHODCALLTYPE GetCode( /* [in] */ CORDB_ADDRESS codeAddress, /* [out] */ ICorDebugCode **ppCode) = 0; virtual HRESULT STDMETHODCALLTYPE EnableVirtualModuleSplitting( BOOL enableSplitting) = 0; virtual HRESULT STDMETHODCALLTYPE MarkDebuggerAttached( BOOL fIsAttached) = 0; virtual HRESULT STDMETHODCALLTYPE GetExportStepInfo( /* [in] */ LPCWSTR pszExportName, /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess6Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess6 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess6 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess6 * This); HRESULT ( STDMETHODCALLTYPE *DecodeEvent )( ICorDebugProcess6 * This, /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, /* [in] */ CorDebugRecordFormat format, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [out] */ ICorDebugDebugEvent **ppEvent); HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( ICorDebugProcess6 * This, /* [in] */ CorDebugStateChange change); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugProcess6 * This, /* [in] */ CORDB_ADDRESS codeAddress, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *EnableVirtualModuleSplitting )( ICorDebugProcess6 * This, BOOL enableSplitting); HRESULT ( STDMETHODCALLTYPE *MarkDebuggerAttached )( ICorDebugProcess6 * This, BOOL fIsAttached); HRESULT ( STDMETHODCALLTYPE *GetExportStepInfo )( ICorDebugProcess6 * This, /* [in] */ LPCWSTR pszExportName, /* [out] */ CorDebugCodeInvokeKind *pInvokeKind, /* [out] */ CorDebugCodeInvokePurpose *pInvokePurpose); END_INTERFACE } ICorDebugProcess6Vtbl; interface ICorDebugProcess6 { CONST_VTBL struct ICorDebugProcess6Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess6_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess6_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess6_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess6_DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) \ ( (This)->lpVtbl -> DecodeEvent(This,pRecord,countBytes,format,dwFlags,dwThreadId,ppEvent) ) #define ICorDebugProcess6_ProcessStateChanged(This,change) \ ( (This)->lpVtbl -> ProcessStateChanged(This,change) ) #define ICorDebugProcess6_GetCode(This,codeAddress,ppCode) \ ( (This)->lpVtbl -> GetCode(This,codeAddress,ppCode) ) #define ICorDebugProcess6_EnableVirtualModuleSplitting(This,enableSplitting) \ ( (This)->lpVtbl -> EnableVirtualModuleSplitting(This,enableSplitting) ) #define ICorDebugProcess6_MarkDebuggerAttached(This,fIsAttached) \ ( (This)->lpVtbl -> MarkDebuggerAttached(This,fIsAttached) ) #define ICorDebugProcess6_GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) \ ( (This)->lpVtbl -> GetExportStepInfo(This,pszExportName,pInvokeKind,pInvokePurpose) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess6_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0042 */ /* [local] */ typedef enum WriteableMetadataUpdateMode { LegacyCompatPolicy = 0, AlwaysShowUpdates = ( LegacyCompatPolicy + 1 ) } WriteableMetadataUpdateMode; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0042_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0042_v0_0_s_ifspec; #ifndef __ICorDebugProcess7_INTERFACE_DEFINED__ #define __ICorDebugProcess7_INTERFACE_DEFINED__ /* interface ICorDebugProcess7 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess7; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("9B2C54E4-119F-4D6F-B402-527603266D69") ICorDebugProcess7 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetWriteableMetadataUpdateMode( WriteableMetadataUpdateMode flags) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess7Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess7 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess7 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess7 * This); HRESULT ( STDMETHODCALLTYPE *SetWriteableMetadataUpdateMode )( ICorDebugProcess7 * This, WriteableMetadataUpdateMode flags); END_INTERFACE } ICorDebugProcess7Vtbl; interface ICorDebugProcess7 { CONST_VTBL struct ICorDebugProcess7Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess7_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess7_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess7_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess7_SetWriteableMetadataUpdateMode(This,flags) \ ( (This)->lpVtbl -> SetWriteableMetadataUpdateMode(This,flags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess7_INTERFACE_DEFINED__ */ #ifndef __ICorDebugProcess8_INTERFACE_DEFINED__ #define __ICorDebugProcess8_INTERFACE_DEFINED__ /* interface ICorDebugProcess8 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess8; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2E6F28C1-85EB-4141-80AD-0A90944B9639") ICorDebugProcess8 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnableExceptionCallbacksOutsideOfMyCode( /* [in] */ BOOL enableExceptionsOutsideOfJMC) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess8Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess8 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess8 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess8 * This); HRESULT ( STDMETHODCALLTYPE *EnableExceptionCallbacksOutsideOfMyCode )( ICorDebugProcess8 * This, /* [in] */ BOOL enableExceptionsOutsideOfJMC); END_INTERFACE } ICorDebugProcess8Vtbl; interface ICorDebugProcess8 { CONST_VTBL struct ICorDebugProcess8Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess8_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess8_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess8_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess8_EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) \ ( (This)->lpVtbl -> EnableExceptionCallbacksOutsideOfMyCode(This,enableExceptionsOutsideOfJMC) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess8_INTERFACE_DEFINED__ */ #ifndef __ICorDebugProcess10_INTERFACE_DEFINED__ #define __ICorDebugProcess10_INTERFACE_DEFINED__ /* interface ICorDebugProcess10 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess10; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("8F378F6F-1017-4461-9890-ECF64C54079F") ICorDebugProcess10 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents( BOOL fEnable) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess10Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess10 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess10 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess10 * This); HRESULT ( STDMETHODCALLTYPE *EnableGCNotificationEvents )( ICorDebugProcess10 * This, BOOL fEnable); END_INTERFACE } ICorDebugProcess10Vtbl; interface ICorDebugProcess10 { CONST_VTBL struct ICorDebugProcess10Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess10_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess10_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess10_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess10_EnableGCNotificationEvents(This,fEnable) \ ( (This)->lpVtbl -> EnableGCNotificationEvents(This,fEnable) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess10_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0045 */ /* [local] */ typedef struct _COR_MEMORY_RANGE { CORDB_ADDRESS start; CORDB_ADDRESS end; } COR_MEMORY_RANGE; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0045_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0045_v0_0_s_ifspec; #ifndef __ICorDebugMemoryRangeEnum_INTERFACE_DEFINED__ #define __ICorDebugMemoryRangeEnum_INTERFACE_DEFINED__ /* interface ICorDebugMemoryRangeEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugMemoryRangeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D1A0BCFC-5865-4437-BE3F-36F022951F8A") ICorDebugMemoryRangeEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_MEMORY_RANGE objects[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugMemoryRangeEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMemoryRangeEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMemoryRangeEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMemoryRangeEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugMemoryRangeEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugMemoryRangeEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugMemoryRangeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugMemoryRangeEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugMemoryRangeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_MEMORY_RANGE objects[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugMemoryRangeEnumVtbl; interface ICorDebugMemoryRangeEnum { CONST_VTBL struct ICorDebugMemoryRangeEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugMemoryRangeEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMemoryRangeEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMemoryRangeEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMemoryRangeEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugMemoryRangeEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugMemoryRangeEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugMemoryRangeEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugMemoryRangeEnum_Next(This,celt,objects,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugMemoryRangeEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugProcess11_INTERFACE_DEFINED__ #define __ICorDebugProcess11_INTERFACE_DEFINED__ /* interface ICorDebugProcess11 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess11; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("344B37AA-F2C0-4D3B-9909-91CCF787DA8C") ICorDebugProcess11 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumerateLoaderHeapMemoryRegions( /* [out] */ ICorDebugMemoryRangeEnum **ppRanges) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess11Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess11 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess11 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess11 * This); HRESULT ( STDMETHODCALLTYPE *EnumerateLoaderHeapMemoryRegions )( ICorDebugProcess11 * This, /* [out] */ ICorDebugMemoryRangeEnum **ppRanges); END_INTERFACE } ICorDebugProcess11Vtbl; interface ICorDebugProcess11 { CONST_VTBL struct ICorDebugProcess11Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess11_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess11_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess11_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess11_EnumerateLoaderHeapMemoryRegions(This,ppRanges) \ ( (This)->lpVtbl -> EnumerateLoaderHeapMemoryRegions(This,ppRanges) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess11_INTERFACE_DEFINED__ */ #ifndef __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ #define __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugModuleDebugEvent */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("51A15E8D-9FFF-4864-9B87-F4FBDEA747A2") ICorDebugModuleDebugEvent : public ICorDebugDebugEvent { public: virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; }; #else /* C style interface */ typedef struct ICorDebugModuleDebugEventVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleDebugEvent * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleDebugEvent * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleDebugEvent * This); HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugModuleDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugModuleDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugModuleDebugEvent * This, /* [out] */ ICorDebugModule **ppModule); END_INTERFACE } ICorDebugModuleDebugEventVtbl; interface ICorDebugModuleDebugEvent { CONST_VTBL struct ICorDebugModuleDebugEventVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModuleDebugEvent_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleDebugEvent_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleDebugEvent_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleDebugEvent_GetEventKind(This,pDebugEventKind) \ ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugModuleDebugEvent_GetThread(This,ppThread) \ ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugModuleDebugEvent_GetModule(This,ppModule) \ ( (This)->lpVtbl -> GetModule(This,ppModule) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModuleDebugEvent_INTERFACE_DEFINED__ */ #ifndef __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ #define __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ /* interface ICorDebugExceptionDebugEvent */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionDebugEvent; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AF79EC94-4752-419C-A626-5FB1CC1A5AB7") ICorDebugExceptionDebugEvent : public ICorDebugDebugEvent { public: virtual HRESULT STDMETHODCALLTYPE GetStackPointer( /* [out] */ CORDB_ADDRESS *pStackPointer) = 0; virtual HRESULT STDMETHODCALLTYPE GetNativeIP( /* [out] */ CORDB_ADDRESS *pIP) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ CorDebugExceptionFlags *pdwFlags) = 0; }; #else /* C style interface */ typedef struct ICorDebugExceptionDebugEventVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionDebugEvent * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionDebugEvent * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionDebugEvent * This); HRESULT ( STDMETHODCALLTYPE *GetEventKind )( ICorDebugExceptionDebugEvent * This, /* [out] */ CorDebugDebugEventKind *pDebugEventKind); HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugExceptionDebugEvent * This, /* [out] */ ICorDebugThread **ppThread); HRESULT ( STDMETHODCALLTYPE *GetStackPointer )( ICorDebugExceptionDebugEvent * This, /* [out] */ CORDB_ADDRESS *pStackPointer); HRESULT ( STDMETHODCALLTYPE *GetNativeIP )( ICorDebugExceptionDebugEvent * This, /* [out] */ CORDB_ADDRESS *pIP); HRESULT ( STDMETHODCALLTYPE *GetFlags )( ICorDebugExceptionDebugEvent * This, /* [out] */ CorDebugExceptionFlags *pdwFlags); END_INTERFACE } ICorDebugExceptionDebugEventVtbl; interface ICorDebugExceptionDebugEvent { CONST_VTBL struct ICorDebugExceptionDebugEventVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugExceptionDebugEvent_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionDebugEvent_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionDebugEvent_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionDebugEvent_GetEventKind(This,pDebugEventKind) \ ( (This)->lpVtbl -> GetEventKind(This,pDebugEventKind) ) #define ICorDebugExceptionDebugEvent_GetThread(This,ppThread) \ ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugExceptionDebugEvent_GetStackPointer(This,pStackPointer) \ ( (This)->lpVtbl -> GetStackPointer(This,pStackPointer) ) #define ICorDebugExceptionDebugEvent_GetNativeIP(This,pIP) \ ( (This)->lpVtbl -> GetNativeIP(This,pIP) ) #define ICorDebugExceptionDebugEvent_GetFlags(This,pdwFlags) \ ( (This)->lpVtbl -> GetFlags(This,pdwFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugExceptionDebugEvent_INTERFACE_DEFINED__ */ #ifndef __ICorDebugBreakpoint_INTERFACE_DEFINED__ #define __ICorDebugBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugBreakpoint */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAE8-8A68-11d2-983C-0000F808342D") ICorDebugBreakpoint : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Activate( /* [in] */ BOOL bActive) = 0; virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; }; #else /* C style interface */ typedef struct ICorDebugBreakpointVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBreakpoint * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBreakpoint * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBreakpoint * This); HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugBreakpoint * This, /* [in] */ BOOL bActive); HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugBreakpoint * This, /* [out] */ BOOL *pbActive); END_INTERFACE } ICorDebugBreakpointVtbl; interface ICorDebugBreakpoint { CONST_VTBL struct ICorDebugBreakpointVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugBreakpoint_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBreakpoint_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBreakpoint_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBreakpoint_Activate(This,bActive) \ ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugBreakpoint_IsActive(This,pbActive) \ ( (This)->lpVtbl -> IsActive(This,pbActive) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugBreakpoint_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ #define __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugFunctionBreakpoint */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunctionBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAE9-8A68-11d2-983C-0000F808342D") ICorDebugFunctionBreakpoint : public ICorDebugBreakpoint { public: virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ ULONG32 *pnOffset) = 0; }; #else /* C style interface */ typedef struct ICorDebugFunctionBreakpointVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunctionBreakpoint * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunctionBreakpoint * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunctionBreakpoint * This); HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugFunctionBreakpoint * This, /* [in] */ BOOL bActive); HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugFunctionBreakpoint * This, /* [out] */ BOOL *pbActive); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugFunctionBreakpoint * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugFunctionBreakpoint * This, /* [out] */ ULONG32 *pnOffset); END_INTERFACE } ICorDebugFunctionBreakpointVtbl; interface ICorDebugFunctionBreakpoint { CONST_VTBL struct ICorDebugFunctionBreakpointVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFunctionBreakpoint_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunctionBreakpoint_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunctionBreakpoint_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunctionBreakpoint_Activate(This,bActive) \ ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugFunctionBreakpoint_IsActive(This,pbActive) \ ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugFunctionBreakpoint_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugFunctionBreakpoint_GetOffset(This,pnOffset) \ ( (This)->lpVtbl -> GetOffset(This,pnOffset) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFunctionBreakpoint_INTERFACE_DEFINED__ */ #ifndef __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ #define __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugModuleBreakpoint */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAEA-8A68-11d2-983C-0000F808342D") ICorDebugModuleBreakpoint : public ICorDebugBreakpoint { public: virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; }; #else /* C style interface */ typedef struct ICorDebugModuleBreakpointVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleBreakpoint * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleBreakpoint * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleBreakpoint * This); HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugModuleBreakpoint * This, /* [in] */ BOOL bActive); HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugModuleBreakpoint * This, /* [out] */ BOOL *pbActive); HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugModuleBreakpoint * This, /* [out] */ ICorDebugModule **ppModule); END_INTERFACE } ICorDebugModuleBreakpointVtbl; interface ICorDebugModuleBreakpoint { CONST_VTBL struct ICorDebugModuleBreakpointVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModuleBreakpoint_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleBreakpoint_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleBreakpoint_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleBreakpoint_Activate(This,bActive) \ ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugModuleBreakpoint_IsActive(This,pbActive) \ ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugModuleBreakpoint_GetModule(This,ppModule) \ ( (This)->lpVtbl -> GetModule(This,ppModule) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModuleBreakpoint_INTERFACE_DEFINED__ */ #ifndef __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ #define __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ /* interface ICorDebugValueBreakpoint */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValueBreakpoint; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAEB-8A68-11d2-983C-0000F808342D") ICorDebugValueBreakpoint : public ICorDebugBreakpoint { public: virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ ICorDebugValue **ppValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugValueBreakpointVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValueBreakpoint * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValueBreakpoint * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValueBreakpoint * This); HRESULT ( STDMETHODCALLTYPE *Activate )( ICorDebugValueBreakpoint * This, /* [in] */ BOOL bActive); HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugValueBreakpoint * This, /* [out] */ BOOL *pbActive); HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugValueBreakpoint * This, /* [out] */ ICorDebugValue **ppValue); END_INTERFACE } ICorDebugValueBreakpointVtbl; interface ICorDebugValueBreakpoint { CONST_VTBL struct ICorDebugValueBreakpointVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugValueBreakpoint_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValueBreakpoint_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValueBreakpoint_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValueBreakpoint_Activate(This,bActive) \ ( (This)->lpVtbl -> Activate(This,bActive) ) #define ICorDebugValueBreakpoint_IsActive(This,pbActive) \ ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugValueBreakpoint_GetValue(This,ppValue) \ ( (This)->lpVtbl -> GetValue(This,ppValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugValueBreakpoint_INTERFACE_DEFINED__ */ #ifndef __ICorDebugStepper_INTERFACE_DEFINED__ #define __ICorDebugStepper_INTERFACE_DEFINED__ /* interface ICorDebugStepper */ /* [unique][uuid][local][object] */ typedef enum CorDebugIntercept { INTERCEPT_NONE = 0, INTERCEPT_CLASS_INIT = 0x1, INTERCEPT_EXCEPTION_FILTER = 0x2, INTERCEPT_SECURITY = 0x4, INTERCEPT_CONTEXT_POLICY = 0x8, INTERCEPT_INTERCEPTION = 0x10, INTERCEPT_ALL = 0xffff } CorDebugIntercept; typedef enum CorDebugUnmappedStop { STOP_NONE = 0, STOP_PROLOG = 0x1, STOP_EPILOG = 0x2, STOP_NO_MAPPING_INFO = 0x4, STOP_OTHER_UNMAPPED = 0x8, STOP_UNMANAGED = 0x10, STOP_ALL = 0xffff } CorDebugUnmappedStop; typedef struct COR_DEBUG_STEP_RANGE { ULONG32 startOffset; ULONG32 endOffset; } COR_DEBUG_STEP_RANGE; EXTERN_C const IID IID_ICorDebugStepper; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAEC-8A68-11d2-983C-0000F808342D") ICorDebugStepper : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; virtual HRESULT STDMETHODCALLTYPE Deactivate( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetInterceptMask( /* [in] */ CorDebugIntercept mask) = 0; virtual HRESULT STDMETHODCALLTYPE SetUnmappedStopMask( /* [in] */ CorDebugUnmappedStop mask) = 0; virtual HRESULT STDMETHODCALLTYPE Step( /* [in] */ BOOL bStepIn) = 0; virtual HRESULT STDMETHODCALLTYPE StepRange( /* [in] */ BOOL bStepIn, /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], /* [in] */ ULONG32 cRangeCount) = 0; virtual HRESULT STDMETHODCALLTYPE StepOut( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetRangeIL( /* [in] */ BOOL bIL) = 0; }; #else /* C style interface */ typedef struct ICorDebugStepperVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepper * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepper * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepper * This); HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugStepper * This, /* [out] */ BOOL *pbActive); HRESULT ( STDMETHODCALLTYPE *Deactivate )( ICorDebugStepper * This); HRESULT ( STDMETHODCALLTYPE *SetInterceptMask )( ICorDebugStepper * This, /* [in] */ CorDebugIntercept mask); HRESULT ( STDMETHODCALLTYPE *SetUnmappedStopMask )( ICorDebugStepper * This, /* [in] */ CorDebugUnmappedStop mask); HRESULT ( STDMETHODCALLTYPE *Step )( ICorDebugStepper * This, /* [in] */ BOOL bStepIn); HRESULT ( STDMETHODCALLTYPE *StepRange )( ICorDebugStepper * This, /* [in] */ BOOL bStepIn, /* [size_is][in] */ COR_DEBUG_STEP_RANGE ranges[ ], /* [in] */ ULONG32 cRangeCount); HRESULT ( STDMETHODCALLTYPE *StepOut )( ICorDebugStepper * This); HRESULT ( STDMETHODCALLTYPE *SetRangeIL )( ICorDebugStepper * This, /* [in] */ BOOL bIL); END_INTERFACE } ICorDebugStepperVtbl; interface ICorDebugStepper { CONST_VTBL struct ICorDebugStepperVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugStepper_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepper_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepper_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepper_IsActive(This,pbActive) \ ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugStepper_Deactivate(This) \ ( (This)->lpVtbl -> Deactivate(This) ) #define ICorDebugStepper_SetInterceptMask(This,mask) \ ( (This)->lpVtbl -> SetInterceptMask(This,mask) ) #define ICorDebugStepper_SetUnmappedStopMask(This,mask) \ ( (This)->lpVtbl -> SetUnmappedStopMask(This,mask) ) #define ICorDebugStepper_Step(This,bStepIn) \ ( (This)->lpVtbl -> Step(This,bStepIn) ) #define ICorDebugStepper_StepRange(This,bStepIn,ranges,cRangeCount) \ ( (This)->lpVtbl -> StepRange(This,bStepIn,ranges,cRangeCount) ) #define ICorDebugStepper_StepOut(This) \ ( (This)->lpVtbl -> StepOut(This) ) #define ICorDebugStepper_SetRangeIL(This,bIL) \ ( (This)->lpVtbl -> SetRangeIL(This,bIL) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugStepper_INTERFACE_DEFINED__ */ #ifndef __ICorDebugStepper2_INTERFACE_DEFINED__ #define __ICorDebugStepper2_INTERFACE_DEFINED__ /* interface ICorDebugStepper2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStepper2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("C5B6E9C3-E7D1-4a8e-873B-7F047F0706F7") ICorDebugStepper2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetJMC( /* [in] */ BOOL fIsJMCStepper) = 0; }; #else /* C style interface */ typedef struct ICorDebugStepper2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepper2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepper2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepper2 * This); HRESULT ( STDMETHODCALLTYPE *SetJMC )( ICorDebugStepper2 * This, /* [in] */ BOOL fIsJMCStepper); END_INTERFACE } ICorDebugStepper2Vtbl; interface ICorDebugStepper2 { CONST_VTBL struct ICorDebugStepper2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugStepper2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepper2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepper2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepper2_SetJMC(This,fIsJMCStepper) \ ( (This)->lpVtbl -> SetJMC(This,fIsJMCStepper) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugStepper2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugRegisterSet_INTERFACE_DEFINED__ #define __ICorDebugRegisterSet_INTERFACE_DEFINED__ /* interface ICorDebugRegisterSet */ /* [unique][uuid][local][object] */ typedef enum CorDebugRegister { REGISTER_INSTRUCTION_POINTER = 0, REGISTER_STACK_POINTER = ( REGISTER_INSTRUCTION_POINTER + 1 ) , REGISTER_FRAME_POINTER = ( REGISTER_STACK_POINTER + 1 ) , REGISTER_X86_EIP = 0, REGISTER_X86_ESP = ( REGISTER_X86_EIP + 1 ) , REGISTER_X86_EBP = ( REGISTER_X86_ESP + 1 ) , REGISTER_X86_EAX = ( REGISTER_X86_EBP + 1 ) , REGISTER_X86_ECX = ( REGISTER_X86_EAX + 1 ) , REGISTER_X86_EDX = ( REGISTER_X86_ECX + 1 ) , REGISTER_X86_EBX = ( REGISTER_X86_EDX + 1 ) , REGISTER_X86_ESI = ( REGISTER_X86_EBX + 1 ) , REGISTER_X86_EDI = ( REGISTER_X86_ESI + 1 ) , REGISTER_X86_FPSTACK_0 = ( REGISTER_X86_EDI + 1 ) , REGISTER_X86_FPSTACK_1 = ( REGISTER_X86_FPSTACK_0 + 1 ) , REGISTER_X86_FPSTACK_2 = ( REGISTER_X86_FPSTACK_1 + 1 ) , REGISTER_X86_FPSTACK_3 = ( REGISTER_X86_FPSTACK_2 + 1 ) , REGISTER_X86_FPSTACK_4 = ( REGISTER_X86_FPSTACK_3 + 1 ) , REGISTER_X86_FPSTACK_5 = ( REGISTER_X86_FPSTACK_4 + 1 ) , REGISTER_X86_FPSTACK_6 = ( REGISTER_X86_FPSTACK_5 + 1 ) , REGISTER_X86_FPSTACK_7 = ( REGISTER_X86_FPSTACK_6 + 1 ) , REGISTER_AMD64_RIP = 0, REGISTER_AMD64_RSP = ( REGISTER_AMD64_RIP + 1 ) , REGISTER_AMD64_RBP = ( REGISTER_AMD64_RSP + 1 ) , REGISTER_AMD64_RAX = ( REGISTER_AMD64_RBP + 1 ) , REGISTER_AMD64_RCX = ( REGISTER_AMD64_RAX + 1 ) , REGISTER_AMD64_RDX = ( REGISTER_AMD64_RCX + 1 ) , REGISTER_AMD64_RBX = ( REGISTER_AMD64_RDX + 1 ) , REGISTER_AMD64_RSI = ( REGISTER_AMD64_RBX + 1 ) , REGISTER_AMD64_RDI = ( REGISTER_AMD64_RSI + 1 ) , REGISTER_AMD64_R8 = ( REGISTER_AMD64_RDI + 1 ) , REGISTER_AMD64_R9 = ( REGISTER_AMD64_R8 + 1 ) , REGISTER_AMD64_R10 = ( REGISTER_AMD64_R9 + 1 ) , REGISTER_AMD64_R11 = ( REGISTER_AMD64_R10 + 1 ) , REGISTER_AMD64_R12 = ( REGISTER_AMD64_R11 + 1 ) , REGISTER_AMD64_R13 = ( REGISTER_AMD64_R12 + 1 ) , REGISTER_AMD64_R14 = ( REGISTER_AMD64_R13 + 1 ) , REGISTER_AMD64_R15 = ( REGISTER_AMD64_R14 + 1 ) , REGISTER_AMD64_XMM0 = ( REGISTER_AMD64_R15 + 1 ) , REGISTER_AMD64_XMM1 = ( REGISTER_AMD64_XMM0 + 1 ) , REGISTER_AMD64_XMM2 = ( REGISTER_AMD64_XMM1 + 1 ) , REGISTER_AMD64_XMM3 = ( REGISTER_AMD64_XMM2 + 1 ) , REGISTER_AMD64_XMM4 = ( REGISTER_AMD64_XMM3 + 1 ) , REGISTER_AMD64_XMM5 = ( REGISTER_AMD64_XMM4 + 1 ) , REGISTER_AMD64_XMM6 = ( REGISTER_AMD64_XMM5 + 1 ) , REGISTER_AMD64_XMM7 = ( REGISTER_AMD64_XMM6 + 1 ) , REGISTER_AMD64_XMM8 = ( REGISTER_AMD64_XMM7 + 1 ) , REGISTER_AMD64_XMM9 = ( REGISTER_AMD64_XMM8 + 1 ) , REGISTER_AMD64_XMM10 = ( REGISTER_AMD64_XMM9 + 1 ) , REGISTER_AMD64_XMM11 = ( REGISTER_AMD64_XMM10 + 1 ) , REGISTER_AMD64_XMM12 = ( REGISTER_AMD64_XMM11 + 1 ) , REGISTER_AMD64_XMM13 = ( REGISTER_AMD64_XMM12 + 1 ) , REGISTER_AMD64_XMM14 = ( REGISTER_AMD64_XMM13 + 1 ) , REGISTER_AMD64_XMM15 = ( REGISTER_AMD64_XMM14 + 1 ) , REGISTER_IA64_BSP = REGISTER_FRAME_POINTER, REGISTER_IA64_R0 = ( REGISTER_IA64_BSP + 1 ) , REGISTER_IA64_F0 = ( REGISTER_IA64_R0 + 128 ) , REGISTER_ARM_PC = 0, REGISTER_ARM_SP = ( REGISTER_ARM_PC + 1 ) , REGISTER_ARM_R0 = ( REGISTER_ARM_SP + 1 ) , REGISTER_ARM_R1 = ( REGISTER_ARM_R0 + 1 ) , REGISTER_ARM_R2 = ( REGISTER_ARM_R1 + 1 ) , REGISTER_ARM_R3 = ( REGISTER_ARM_R2 + 1 ) , REGISTER_ARM_R4 = ( REGISTER_ARM_R3 + 1 ) , REGISTER_ARM_R5 = ( REGISTER_ARM_R4 + 1 ) , REGISTER_ARM_R6 = ( REGISTER_ARM_R5 + 1 ) , REGISTER_ARM_R7 = ( REGISTER_ARM_R6 + 1 ) , REGISTER_ARM_R8 = ( REGISTER_ARM_R7 + 1 ) , REGISTER_ARM_R9 = ( REGISTER_ARM_R8 + 1 ) , REGISTER_ARM_R10 = ( REGISTER_ARM_R9 + 1 ) , REGISTER_ARM_R11 = ( REGISTER_ARM_R10 + 1 ) , REGISTER_ARM_R12 = ( REGISTER_ARM_R11 + 1 ) , REGISTER_ARM_LR = ( REGISTER_ARM_R12 + 1 ) , REGISTER_ARM_D0 = ( REGISTER_ARM_LR + 1 ) , REGISTER_ARM_D1 = ( REGISTER_ARM_D0 + 1 ) , REGISTER_ARM_D2 = ( REGISTER_ARM_D1 + 1 ) , REGISTER_ARM_D3 = ( REGISTER_ARM_D2 + 1 ) , REGISTER_ARM_D4 = ( REGISTER_ARM_D3 + 1 ) , REGISTER_ARM_D5 = ( REGISTER_ARM_D4 + 1 ) , REGISTER_ARM_D6 = ( REGISTER_ARM_D5 + 1 ) , REGISTER_ARM_D7 = ( REGISTER_ARM_D6 + 1 ) , REGISTER_ARM_D8 = ( REGISTER_ARM_D7 + 1 ) , REGISTER_ARM_D9 = ( REGISTER_ARM_D8 + 1 ) , REGISTER_ARM_D10 = ( REGISTER_ARM_D9 + 1 ) , REGISTER_ARM_D11 = ( REGISTER_ARM_D10 + 1 ) , REGISTER_ARM_D12 = ( REGISTER_ARM_D11 + 1 ) , REGISTER_ARM_D13 = ( REGISTER_ARM_D12 + 1 ) , REGISTER_ARM_D14 = ( REGISTER_ARM_D13 + 1 ) , REGISTER_ARM_D15 = ( REGISTER_ARM_D14 + 1 ) , REGISTER_ARM_D16 = ( REGISTER_ARM_D15 + 1 ) , REGISTER_ARM_D17 = ( REGISTER_ARM_D16 + 1 ) , REGISTER_ARM_D18 = ( REGISTER_ARM_D17 + 1 ) , REGISTER_ARM_D19 = ( REGISTER_ARM_D18 + 1 ) , REGISTER_ARM_D20 = ( REGISTER_ARM_D19 + 1 ) , REGISTER_ARM_D21 = ( REGISTER_ARM_D20 + 1 ) , REGISTER_ARM_D22 = ( REGISTER_ARM_D21 + 1 ) , REGISTER_ARM_D23 = ( REGISTER_ARM_D22 + 1 ) , REGISTER_ARM_D24 = ( REGISTER_ARM_D23 + 1 ) , REGISTER_ARM_D25 = ( REGISTER_ARM_D24 + 1 ) , REGISTER_ARM_D26 = ( REGISTER_ARM_D25 + 1 ) , REGISTER_ARM_D27 = ( REGISTER_ARM_D26 + 1 ) , REGISTER_ARM_D28 = ( REGISTER_ARM_D27 + 1 ) , REGISTER_ARM_D29 = ( REGISTER_ARM_D28 + 1 ) , REGISTER_ARM_D30 = ( REGISTER_ARM_D29 + 1 ) , REGISTER_ARM_D31 = ( REGISTER_ARM_D30 + 1 ) , REGISTER_ARM64_PC = 0, REGISTER_ARM64_SP = ( REGISTER_ARM64_PC + 1 ) , REGISTER_ARM64_FP = ( REGISTER_ARM64_SP + 1 ) , REGISTER_ARM64_X0 = ( REGISTER_ARM64_FP + 1 ) , REGISTER_ARM64_X1 = ( REGISTER_ARM64_X0 + 1 ) , REGISTER_ARM64_X2 = ( REGISTER_ARM64_X1 + 1 ) , REGISTER_ARM64_X3 = ( REGISTER_ARM64_X2 + 1 ) , REGISTER_ARM64_X4 = ( REGISTER_ARM64_X3 + 1 ) , REGISTER_ARM64_X5 = ( REGISTER_ARM64_X4 + 1 ) , REGISTER_ARM64_X6 = ( REGISTER_ARM64_X5 + 1 ) , REGISTER_ARM64_X7 = ( REGISTER_ARM64_X6 + 1 ) , REGISTER_ARM64_X8 = ( REGISTER_ARM64_X7 + 1 ) , REGISTER_ARM64_X9 = ( REGISTER_ARM64_X8 + 1 ) , REGISTER_ARM64_X10 = ( REGISTER_ARM64_X9 + 1 ) , REGISTER_ARM64_X11 = ( REGISTER_ARM64_X10 + 1 ) , REGISTER_ARM64_X12 = ( REGISTER_ARM64_X11 + 1 ) , REGISTER_ARM64_X13 = ( REGISTER_ARM64_X12 + 1 ) , REGISTER_ARM64_X14 = ( REGISTER_ARM64_X13 + 1 ) , REGISTER_ARM64_X15 = ( REGISTER_ARM64_X14 + 1 ) , REGISTER_ARM64_X16 = ( REGISTER_ARM64_X15 + 1 ) , REGISTER_ARM64_X17 = ( REGISTER_ARM64_X16 + 1 ) , REGISTER_ARM64_X18 = ( REGISTER_ARM64_X17 + 1 ) , REGISTER_ARM64_X19 = ( REGISTER_ARM64_X18 + 1 ) , REGISTER_ARM64_X20 = ( REGISTER_ARM64_X19 + 1 ) , REGISTER_ARM64_X21 = ( REGISTER_ARM64_X20 + 1 ) , REGISTER_ARM64_X22 = ( REGISTER_ARM64_X21 + 1 ) , REGISTER_ARM64_X23 = ( REGISTER_ARM64_X22 + 1 ) , REGISTER_ARM64_X24 = ( REGISTER_ARM64_X23 + 1 ) , REGISTER_ARM64_X25 = ( REGISTER_ARM64_X24 + 1 ) , REGISTER_ARM64_X26 = ( REGISTER_ARM64_X25 + 1 ) , REGISTER_ARM64_X27 = ( REGISTER_ARM64_X26 + 1 ) , REGISTER_ARM64_X28 = ( REGISTER_ARM64_X27 + 1 ) , REGISTER_ARM64_LR = ( REGISTER_ARM64_X28 + 1 ) , REGISTER_ARM64_V0 = ( REGISTER_ARM64_LR + 1 ) , REGISTER_ARM64_V1 = ( REGISTER_ARM64_V0 + 1 ) , REGISTER_ARM64_V2 = ( REGISTER_ARM64_V1 + 1 ) , REGISTER_ARM64_V3 = ( REGISTER_ARM64_V2 + 1 ) , REGISTER_ARM64_V4 = ( REGISTER_ARM64_V3 + 1 ) , REGISTER_ARM64_V5 = ( REGISTER_ARM64_V4 + 1 ) , REGISTER_ARM64_V6 = ( REGISTER_ARM64_V5 + 1 ) , REGISTER_ARM64_V7 = ( REGISTER_ARM64_V6 + 1 ) , REGISTER_ARM64_V8 = ( REGISTER_ARM64_V7 + 1 ) , REGISTER_ARM64_V9 = ( REGISTER_ARM64_V8 + 1 ) , REGISTER_ARM64_V10 = ( REGISTER_ARM64_V9 + 1 ) , REGISTER_ARM64_V11 = ( REGISTER_ARM64_V10 + 1 ) , REGISTER_ARM64_V12 = ( REGISTER_ARM64_V11 + 1 ) , REGISTER_ARM64_V13 = ( REGISTER_ARM64_V12 + 1 ) , REGISTER_ARM64_V14 = ( REGISTER_ARM64_V13 + 1 ) , REGISTER_ARM64_V15 = ( REGISTER_ARM64_V14 + 1 ) , REGISTER_ARM64_V16 = ( REGISTER_ARM64_V15 + 1 ) , REGISTER_ARM64_V17 = ( REGISTER_ARM64_V16 + 1 ) , REGISTER_ARM64_V18 = ( REGISTER_ARM64_V17 + 1 ) , REGISTER_ARM64_V19 = ( REGISTER_ARM64_V18 + 1 ) , REGISTER_ARM64_V20 = ( REGISTER_ARM64_V19 + 1 ) , REGISTER_ARM64_V21 = ( REGISTER_ARM64_V20 + 1 ) , REGISTER_ARM64_V22 = ( REGISTER_ARM64_V21 + 1 ) , REGISTER_ARM64_V23 = ( REGISTER_ARM64_V22 + 1 ) , REGISTER_ARM64_V24 = ( REGISTER_ARM64_V23 + 1 ) , REGISTER_ARM64_V25 = ( REGISTER_ARM64_V24 + 1 ) , REGISTER_ARM64_V26 = ( REGISTER_ARM64_V25 + 1 ) , REGISTER_ARM64_V27 = ( REGISTER_ARM64_V26 + 1 ) , REGISTER_ARM64_V28 = ( REGISTER_ARM64_V27 + 1 ) , REGISTER_ARM64_V29 = ( REGISTER_ARM64_V28 + 1 ) , REGISTER_ARM64_V30 = ( REGISTER_ARM64_V29 + 1 ) , REGISTER_ARM64_V31 = ( REGISTER_ARM64_V30 + 1 ) , REGISTER_LOONGARCH64_PC = 0, REGISTER_LOONGARCH64_SP = ( REGISTER_LOONGARCH64_PC + 1 ) , REGISTER_LOONGARCH64_FP = ( REGISTER_LOONGARCH64_SP + 1 ) , REGISTER_LOONGARCH64_RA = ( REGISTER_LOONGARCH64_FP + 1 ) , REGISTER_LOONGARCH64_TP = ( REGISTER_LOONGARCH64_RA + 1 ) , REGISTER_LOONGARCH64_A0 = ( REGISTER_LOONGARCH64_TP + 1 ) , REGISTER_LOONGARCH64_A1 = ( REGISTER_LOONGARCH64_A0 + 1 ) , REGISTER_LOONGARCH64_A2 = ( REGISTER_LOONGARCH64_A1 + 1 ) , REGISTER_LOONGARCH64_A3 = ( REGISTER_LOONGARCH64_A2 + 1 ) , REGISTER_LOONGARCH64_A4 = ( REGISTER_LOONGARCH64_A3 + 1 ) , REGISTER_LOONGARCH64_A5 = ( REGISTER_LOONGARCH64_A4 + 1 ) , REGISTER_LOONGARCH64_A6 = ( REGISTER_LOONGARCH64_A5 + 1 ) , REGISTER_LOONGARCH64_A7 = ( REGISTER_LOONGARCH64_A6 + 1 ) , REGISTER_LOONGARCH64_T0 = ( REGISTER_LOONGARCH64_A7 + 1 ) , REGISTER_LOONGARCH64_T1 = ( REGISTER_LOONGARCH64_T0 + 1 ) , REGISTER_LOONGARCH64_T2 = ( REGISTER_LOONGARCH64_T1 + 1 ) , REGISTER_LOONGARCH64_T3 = ( REGISTER_LOONGARCH64_T2 + 1 ) , REGISTER_LOONGARCH64_T4 = ( REGISTER_LOONGARCH64_T3 + 1 ) , REGISTER_LOONGARCH64_T5 = ( REGISTER_LOONGARCH64_T4 + 1 ) , REGISTER_LOONGARCH64_T6 = ( REGISTER_LOONGARCH64_T5 + 1 ) , REGISTER_LOONGARCH64_T7 = ( REGISTER_LOONGARCH64_T6 + 1 ) , REGISTER_LOONGARCH64_T8 = ( REGISTER_LOONGARCH64_T7 + 1 ) , REGISTER_LOONGARCH64_X0 = ( REGISTER_LOONGARCH64_T8 + 1 ) , REGISTER_LOONGARCH64_S0 = ( REGISTER_LOONGARCH64_X0 + 1 ) , REGISTER_LOONGARCH64_S1 = ( REGISTER_LOONGARCH64_S0 + 1 ) , REGISTER_LOONGARCH64_S2 = ( REGISTER_LOONGARCH64_S1 + 1 ) , REGISTER_LOONGARCH64_S3 = ( REGISTER_LOONGARCH64_S2 + 1 ) , REGISTER_LOONGARCH64_S4 = ( REGISTER_LOONGARCH64_S3 + 1 ) , REGISTER_LOONGARCH64_S5 = ( REGISTER_LOONGARCH64_S4 + 1 ) , REGISTER_LOONGARCH64_S6 = ( REGISTER_LOONGARCH64_S5 + 1 ) , REGISTER_LOONGARCH64_S7 = ( REGISTER_LOONGARCH64_S6 + 1 ) , REGISTER_LOONGARCH64_S8 = ( REGISTER_LOONGARCH64_S7 + 1 ) , REGISTER_LOONGARCH64_F0 = ( REGISTER_LOONGARCH64_S8 + 1 ) , REGISTER_LOONGARCH64_F1 = ( REGISTER_LOONGARCH64_F0 + 1 ) , REGISTER_LOONGARCH64_F2 = ( REGISTER_LOONGARCH64_F1 + 1 ) , REGISTER_LOONGARCH64_F3 = ( REGISTER_LOONGARCH64_F2 + 1 ) , REGISTER_LOONGARCH64_F4 = ( REGISTER_LOONGARCH64_F3 + 1 ) , REGISTER_LOONGARCH64_F5 = ( REGISTER_LOONGARCH64_F4 + 1 ) , REGISTER_LOONGARCH64_F6 = ( REGISTER_LOONGARCH64_F5 + 1 ) , REGISTER_LOONGARCH64_F7 = ( REGISTER_LOONGARCH64_F6 + 1 ) , REGISTER_LOONGARCH64_F8 = ( REGISTER_LOONGARCH64_F7 + 1 ) , REGISTER_LOONGARCH64_F9 = ( REGISTER_LOONGARCH64_F8 + 1 ) , REGISTER_LOONGARCH64_F10 = ( REGISTER_LOONGARCH64_F9 + 1 ) , REGISTER_LOONGARCH64_F11 = ( REGISTER_LOONGARCH64_F10 + 1 ) , REGISTER_LOONGARCH64_F12 = ( REGISTER_LOONGARCH64_F11 + 1 ) , REGISTER_LOONGARCH64_F13 = ( REGISTER_LOONGARCH64_F12 + 1 ) , REGISTER_LOONGARCH64_F14 = ( REGISTER_LOONGARCH64_F13 + 1 ) , REGISTER_LOONGARCH64_F15 = ( REGISTER_LOONGARCH64_F14 + 1 ) , REGISTER_LOONGARCH64_F16 = ( REGISTER_LOONGARCH64_F15 + 1 ) , REGISTER_LOONGARCH64_F17 = ( REGISTER_LOONGARCH64_F16 + 1 ) , REGISTER_LOONGARCH64_F18 = ( REGISTER_LOONGARCH64_F17 + 1 ) , REGISTER_LOONGARCH64_F19 = ( REGISTER_LOONGARCH64_F18 + 1 ) , REGISTER_LOONGARCH64_F20 = ( REGISTER_LOONGARCH64_F19 + 1 ) , REGISTER_LOONGARCH64_F21 = ( REGISTER_LOONGARCH64_F20 + 1 ) , REGISTER_LOONGARCH64_F22 = ( REGISTER_LOONGARCH64_F21 + 1 ) , REGISTER_LOONGARCH64_F23 = ( REGISTER_LOONGARCH64_F22 + 1 ) , REGISTER_LOONGARCH64_F24 = ( REGISTER_LOONGARCH64_F23 + 1 ) , REGISTER_LOONGARCH64_F25 = ( REGISTER_LOONGARCH64_F24 + 1 ) , REGISTER_LOONGARCH64_F26 = ( REGISTER_LOONGARCH64_F25 + 1 ) , REGISTER_LOONGARCH64_F27 = ( REGISTER_LOONGARCH64_F26 + 1 ) , REGISTER_LOONGARCH64_F28 = ( REGISTER_LOONGARCH64_F27 + 1 ) , REGISTER_LOONGARCH64_F29 = ( REGISTER_LOONGARCH64_F28 + 1 ) , REGISTER_LOONGARCH64_F30 = ( REGISTER_LOONGARCH64_F29 + 1 ) , REGISTER_LOONGARCH64_F31 = ( REGISTER_LOONGARCH64_F30 + 1 ) } CorDebugRegister; EXTERN_C const IID IID_ICorDebugRegisterSet; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB0B-8A68-11d2-983C-0000F808342D") ICorDebugRegisterSet : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( /* [out] */ ULONG64 *pAvailable) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegisters( /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetRegisters( /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetThreadContext( /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugRegisterSetVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRegisterSet * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRegisterSet * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRegisterSet * This); HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( ICorDebugRegisterSet * This, /* [out] */ ULONG64 *pAvailable); HRESULT ( STDMETHODCALLTYPE *GetRegisters )( ICorDebugRegisterSet * This, /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [length_is][size_is][out] */ CORDB_REGISTER regBuffer[ ]); HRESULT ( STDMETHODCALLTYPE *SetRegisters )( ICorDebugRegisterSet * This, /* [in] */ ULONG64 mask, /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorDebugRegisterSet * This, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][out][in] */ BYTE context[ ]); HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( ICorDebugRegisterSet * This, /* [in] */ ULONG32 contextSize, /* [size_is][length_is][in] */ BYTE context[ ]); END_INTERFACE } ICorDebugRegisterSetVtbl; interface ICorDebugRegisterSet { CONST_VTBL struct ICorDebugRegisterSetVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugRegisterSet_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRegisterSet_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRegisterSet_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRegisterSet_GetRegistersAvailable(This,pAvailable) \ ( (This)->lpVtbl -> GetRegistersAvailable(This,pAvailable) ) #define ICorDebugRegisterSet_GetRegisters(This,mask,regCount,regBuffer) \ ( (This)->lpVtbl -> GetRegisters(This,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet_SetRegisters(This,mask,regCount,regBuffer) \ ( (This)->lpVtbl -> SetRegisters(This,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet_GetThreadContext(This,contextSize,context) \ ( (This)->lpVtbl -> GetThreadContext(This,contextSize,context) ) #define ICorDebugRegisterSet_SetThreadContext(This,contextSize,context) \ ( (This)->lpVtbl -> SetThreadContext(This,contextSize,context) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugRegisterSet_INTERFACE_DEFINED__ */ #ifndef __ICorDebugRegisterSet2_INTERFACE_DEFINED__ #define __ICorDebugRegisterSet2_INTERFACE_DEFINED__ /* interface ICorDebugRegisterSet2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRegisterSet2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("6DC7BA3F-89BA-4459-9EC1-9D60937B468D") ICorDebugRegisterSet2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetRegistersAvailable( /* [in] */ ULONG32 numChunks, /* [size_is][out] */ BYTE availableRegChunks[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegisters( /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetRegisters( /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugRegisterSet2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRegisterSet2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRegisterSet2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRegisterSet2 * This); HRESULT ( STDMETHODCALLTYPE *GetRegistersAvailable )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 numChunks, /* [size_is][out] */ BYTE availableRegChunks[ ]); HRESULT ( STDMETHODCALLTYPE *GetRegisters )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][out] */ CORDB_REGISTER regBuffer[ ]); HRESULT ( STDMETHODCALLTYPE *SetRegisters )( ICorDebugRegisterSet2 * This, /* [in] */ ULONG32 maskCount, /* [size_is][in] */ BYTE mask[ ], /* [in] */ ULONG32 regCount, /* [size_is][in] */ CORDB_REGISTER regBuffer[ ]); END_INTERFACE } ICorDebugRegisterSet2Vtbl; interface ICorDebugRegisterSet2 { CONST_VTBL struct ICorDebugRegisterSet2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugRegisterSet2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRegisterSet2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRegisterSet2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRegisterSet2_GetRegistersAvailable(This,numChunks,availableRegChunks) \ ( (This)->lpVtbl -> GetRegistersAvailable(This,numChunks,availableRegChunks) ) #define ICorDebugRegisterSet2_GetRegisters(This,maskCount,mask,regCount,regBuffer) \ ( (This)->lpVtbl -> GetRegisters(This,maskCount,mask,regCount,regBuffer) ) #define ICorDebugRegisterSet2_SetRegisters(This,maskCount,mask,regCount,regBuffer) \ ( (This)->lpVtbl -> SetRegisters(This,maskCount,mask,regCount,regBuffer) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugRegisterSet2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugThread_INTERFACE_DEFINED__ #define __ICorDebugThread_INTERFACE_DEFINED__ /* interface ICorDebugThread */ /* [unique][uuid][local][object] */ typedef enum CorDebugUserState { USER_STOP_REQUESTED = 0x1, USER_SUSPEND_REQUESTED = 0x2, USER_BACKGROUND = 0x4, USER_UNSTARTED = 0x8, USER_STOPPED = 0x10, USER_WAIT_SLEEP_JOIN = 0x20, USER_SUSPENDED = 0x40, USER_UNSAFE_POINT = 0x80, USER_THREADPOOL = 0x100 } CorDebugUserState; EXTERN_C const IID IID_ICorDebugThread; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("938c6d66-7fb6-4f69-b389-425b8987329b") ICorDebugThread : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ DWORD *pdwThreadId) = 0; virtual HRESULT STDMETHODCALLTYPE GetHandle( /* [out] */ HTHREAD *phThreadHandle) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ ICorDebugAppDomain **ppAppDomain) = 0; virtual HRESULT STDMETHODCALLTYPE SetDebugState( /* [in] */ CorDebugThreadState state) = 0; virtual HRESULT STDMETHODCALLTYPE GetDebugState( /* [out] */ CorDebugThreadState *pState) = 0; virtual HRESULT STDMETHODCALLTYPE GetUserState( /* [out] */ CorDebugUserState *pState) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentException( /* [out] */ ICorDebugValue **ppExceptionObject) = 0; virtual HRESULT STDMETHODCALLTYPE ClearCurrentException( void) = 0; virtual HRESULT STDMETHODCALLTYPE CreateStepper( /* [out] */ ICorDebugStepper **ppStepper) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateChains( /* [out] */ ICorDebugChainEnum **ppChains) = 0; virtual HRESULT STDMETHODCALLTYPE GetActiveChain( /* [out] */ ICorDebugChain **ppChain) = 0; virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( /* [out] */ ICorDebugFrame **ppFrame) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; virtual HRESULT STDMETHODCALLTYPE CreateEval( /* [out] */ ICorDebugEval **ppEval) = 0; virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugValue **ppObject) = 0; }; #else /* C style interface */ typedef struct ICorDebugThreadVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread * This); HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugThread * This, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *GetID )( ICorDebugThread * This, /* [out] */ DWORD *pdwThreadId); HRESULT ( STDMETHODCALLTYPE *GetHandle )( ICorDebugThread * This, /* [out] */ HTHREAD *phThreadHandle); HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( ICorDebugThread * This, /* [out] */ ICorDebugAppDomain **ppAppDomain); HRESULT ( STDMETHODCALLTYPE *SetDebugState )( ICorDebugThread * This, /* [in] */ CorDebugThreadState state); HRESULT ( STDMETHODCALLTYPE *GetDebugState )( ICorDebugThread * This, /* [out] */ CorDebugThreadState *pState); HRESULT ( STDMETHODCALLTYPE *GetUserState )( ICorDebugThread * This, /* [out] */ CorDebugUserState *pState); HRESULT ( STDMETHODCALLTYPE *GetCurrentException )( ICorDebugThread * This, /* [out] */ ICorDebugValue **ppExceptionObject); HRESULT ( STDMETHODCALLTYPE *ClearCurrentException )( ICorDebugThread * This); HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugThread * This, /* [out] */ ICorDebugStepper **ppStepper); HRESULT ( STDMETHODCALLTYPE *EnumerateChains )( ICorDebugThread * This, /* [out] */ ICorDebugChainEnum **ppChains); HRESULT ( STDMETHODCALLTYPE *GetActiveChain )( ICorDebugThread * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( ICorDebugThread * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugThread * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); HRESULT ( STDMETHODCALLTYPE *CreateEval )( ICorDebugThread * This, /* [out] */ ICorDebugEval **ppEval); HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugThread * This, /* [out] */ ICorDebugValue **ppObject); END_INTERFACE } ICorDebugThreadVtbl; interface ICorDebugThread { CONST_VTBL struct ICorDebugThreadVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugThread_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread_GetProcess(This,ppProcess) \ ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugThread_GetID(This,pdwThreadId) \ ( (This)->lpVtbl -> GetID(This,pdwThreadId) ) #define ICorDebugThread_GetHandle(This,phThreadHandle) \ ( (This)->lpVtbl -> GetHandle(This,phThreadHandle) ) #define ICorDebugThread_GetAppDomain(This,ppAppDomain) \ ( (This)->lpVtbl -> GetAppDomain(This,ppAppDomain) ) #define ICorDebugThread_SetDebugState(This,state) \ ( (This)->lpVtbl -> SetDebugState(This,state) ) #define ICorDebugThread_GetDebugState(This,pState) \ ( (This)->lpVtbl -> GetDebugState(This,pState) ) #define ICorDebugThread_GetUserState(This,pState) \ ( (This)->lpVtbl -> GetUserState(This,pState) ) #define ICorDebugThread_GetCurrentException(This,ppExceptionObject) \ ( (This)->lpVtbl -> GetCurrentException(This,ppExceptionObject) ) #define ICorDebugThread_ClearCurrentException(This) \ ( (This)->lpVtbl -> ClearCurrentException(This) ) #define ICorDebugThread_CreateStepper(This,ppStepper) \ ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugThread_EnumerateChains(This,ppChains) \ ( (This)->lpVtbl -> EnumerateChains(This,ppChains) ) #define ICorDebugThread_GetActiveChain(This,ppChain) \ ( (This)->lpVtbl -> GetActiveChain(This,ppChain) ) #define ICorDebugThread_GetActiveFrame(This,ppFrame) \ ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) #define ICorDebugThread_GetRegisterSet(This,ppRegisters) \ ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugThread_CreateEval(This,ppEval) \ ( (This)->lpVtbl -> CreateEval(This,ppEval) ) #define ICorDebugThread_GetObject(This,ppObject) \ ( (This)->lpVtbl -> GetObject(This,ppObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugThread_INTERFACE_DEFINED__ */ #ifndef __ICorDebugThread2_INTERFACE_DEFINED__ #define __ICorDebugThread2_INTERFACE_DEFINED__ /* interface ICorDebugThread2 */ /* [unique][uuid][local][object] */ typedef struct _COR_ACTIVE_FUNCTION { ICorDebugAppDomain *pAppDomain; ICorDebugModule *pModule; ICorDebugFunction2 *pFunction; ULONG32 ilOffset; ULONG32 flags; } COR_ACTIVE_FUNCTION; EXTERN_C const IID IID_ICorDebugThread2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2BD956D9-7B07-4bef-8A98-12AA862417C5") ICorDebugThread2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetActiveFunctions( /* [in] */ ULONG32 cFunctions, /* [out] */ ULONG32 *pcFunctions, /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetConnectionID( /* [out] */ CONNID *pdwConnectionId) = 0; virtual HRESULT STDMETHODCALLTYPE GetTaskID( /* [out] */ TASKID *pTaskId) = 0; virtual HRESULT STDMETHODCALLTYPE GetVolatileOSThreadID( /* [out] */ DWORD *pdwTid) = 0; virtual HRESULT STDMETHODCALLTYPE InterceptCurrentException( /* [in] */ ICorDebugFrame *pFrame) = 0; }; #else /* C style interface */ typedef struct ICorDebugThread2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread2 * This); HRESULT ( STDMETHODCALLTYPE *GetActiveFunctions )( ICorDebugThread2 * This, /* [in] */ ULONG32 cFunctions, /* [out] */ ULONG32 *pcFunctions, /* [length_is][size_is][out][in] */ COR_ACTIVE_FUNCTION pFunctions[ ]); HRESULT ( STDMETHODCALLTYPE *GetConnectionID )( ICorDebugThread2 * This, /* [out] */ CONNID *pdwConnectionId); HRESULT ( STDMETHODCALLTYPE *GetTaskID )( ICorDebugThread2 * This, /* [out] */ TASKID *pTaskId); HRESULT ( STDMETHODCALLTYPE *GetVolatileOSThreadID )( ICorDebugThread2 * This, /* [out] */ DWORD *pdwTid); HRESULT ( STDMETHODCALLTYPE *InterceptCurrentException )( ICorDebugThread2 * This, /* [in] */ ICorDebugFrame *pFrame); END_INTERFACE } ICorDebugThread2Vtbl; interface ICorDebugThread2 { CONST_VTBL struct ICorDebugThread2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugThread2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread2_GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) \ ( (This)->lpVtbl -> GetActiveFunctions(This,cFunctions,pcFunctions,pFunctions) ) #define ICorDebugThread2_GetConnectionID(This,pdwConnectionId) \ ( (This)->lpVtbl -> GetConnectionID(This,pdwConnectionId) ) #define ICorDebugThread2_GetTaskID(This,pTaskId) \ ( (This)->lpVtbl -> GetTaskID(This,pTaskId) ) #define ICorDebugThread2_GetVolatileOSThreadID(This,pdwTid) \ ( (This)->lpVtbl -> GetVolatileOSThreadID(This,pdwTid) ) #define ICorDebugThread2_InterceptCurrentException(This,pFrame) \ ( (This)->lpVtbl -> InterceptCurrentException(This,pFrame) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugThread2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugThread3_INTERFACE_DEFINED__ #define __ICorDebugThread3_INTERFACE_DEFINED__ /* interface ICorDebugThread3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F8544EC3-5E4E-46c7-8D3E-A52B8405B1F5") ICorDebugThread3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( /* [out] */ ICorDebugStackWalk **ppStackWalk) = 0; virtual HRESULT STDMETHODCALLTYPE GetActiveInternalFrames( /* [in] */ ULONG32 cInternalFrames, /* [out] */ ULONG32 *pcInternalFrames, /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugThread3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread3 * This); HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( ICorDebugThread3 * This, /* [out] */ ICorDebugStackWalk **ppStackWalk); HRESULT ( STDMETHODCALLTYPE *GetActiveInternalFrames )( ICorDebugThread3 * This, /* [in] */ ULONG32 cInternalFrames, /* [out] */ ULONG32 *pcInternalFrames, /* [length_is][size_is][out][in] */ ICorDebugInternalFrame2 *ppInternalFrames[ ]); END_INTERFACE } ICorDebugThread3Vtbl; interface ICorDebugThread3 { CONST_VTBL struct ICorDebugThread3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugThread3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread3_CreateStackWalk(This,ppStackWalk) \ ( (This)->lpVtbl -> CreateStackWalk(This,ppStackWalk) ) #define ICorDebugThread3_GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) \ ( (This)->lpVtbl -> GetActiveInternalFrames(This,cInternalFrames,pcInternalFrames,ppInternalFrames) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugThread3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugThread4_INTERFACE_DEFINED__ #define __ICorDebugThread4_INTERFACE_DEFINED__ /* interface ICorDebugThread4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("1A1F204B-1C66-4637-823F-3EE6C744A69C") ICorDebugThread4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE HasUnhandledException( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetBlockingObjects( /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentCustomDebuggerNotification( /* [out] */ ICorDebugValue **ppNotificationObject) = 0; }; #else /* C style interface */ typedef struct ICorDebugThread4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread4 * This); HRESULT ( STDMETHODCALLTYPE *HasUnhandledException )( ICorDebugThread4 * This); HRESULT ( STDMETHODCALLTYPE *GetBlockingObjects )( ICorDebugThread4 * This, /* [out] */ ICorDebugBlockingObjectEnum **ppBlockingObjectEnum); HRESULT ( STDMETHODCALLTYPE *GetCurrentCustomDebuggerNotification )( ICorDebugThread4 * This, /* [out] */ ICorDebugValue **ppNotificationObject); END_INTERFACE } ICorDebugThread4Vtbl; interface ICorDebugThread4 { CONST_VTBL struct ICorDebugThread4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugThread4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread4_HasUnhandledException(This) \ ( (This)->lpVtbl -> HasUnhandledException(This) ) #define ICorDebugThread4_GetBlockingObjects(This,ppBlockingObjectEnum) \ ( (This)->lpVtbl -> GetBlockingObjects(This,ppBlockingObjectEnum) ) #define ICorDebugThread4_GetCurrentCustomDebuggerNotification(This,ppNotificationObject) \ ( (This)->lpVtbl -> GetCurrentCustomDebuggerNotification(This,ppNotificationObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugThread4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugThread5_INTERFACE_DEFINED__ #define __ICorDebugThread5_INTERFACE_DEFINED__ /* interface ICorDebugThread5 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThread5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F98421C4-E506-4D24-916F-0237EE853EC6") ICorDebugThread5 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetBytesAllocated( /* [out] */ ULONG64 *pSohAllocatedBytes, /* [out] */ ULONG64 *pUohAllocatedBytes) = 0; }; #else /* C style interface */ typedef struct ICorDebugThread5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThread5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThread5 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThread5 * This); HRESULT ( STDMETHODCALLTYPE *GetBytesAllocated )( ICorDebugThread5 * This, /* [out] */ ULONG64 *pSohAllocatedBytes, /* [out] */ ULONG64 *pUohAllocatedBytes); END_INTERFACE } ICorDebugThread5Vtbl; interface ICorDebugThread5 { CONST_VTBL struct ICorDebugThread5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugThread5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThread5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThread5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThread5_GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) \ ( (This)->lpVtbl -> GetBytesAllocated(This,pSohAllocatedBytes,pUohAllocatedBytes) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugThread5_INTERFACE_DEFINED__ */ #ifndef __ICorDebugStackWalk_INTERFACE_DEFINED__ #define __ICorDebugStackWalk_INTERFACE_DEFINED__ /* interface ICorDebugStackWalk */ /* [unique][uuid][local][object] */ typedef enum CorDebugSetContextFlag { SET_CONTEXT_FLAG_ACTIVE_FRAME = 0x1, SET_CONTEXT_FLAG_UNWIND_FRAME = 0x2 } CorDebugSetContextFlag; EXTERN_C const IID IID_ICorDebugStackWalk; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A0647DE9-55DE-4816-929C-385271C64CF7") ICorDebugStackWalk : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetContext( /* [in] */ CorDebugSetContextFlag flag, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetFrame( /* [out] */ ICorDebugFrame **pFrame) = 0; }; #else /* C style interface */ typedef struct ICorDebugStackWalkVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStackWalk * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStackWalk * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStackWalk * This); HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugStackWalk * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); HRESULT ( STDMETHODCALLTYPE *SetContext )( ICorDebugStackWalk * This, /* [in] */ CorDebugSetContextFlag flag, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugStackWalk * This); HRESULT ( STDMETHODCALLTYPE *GetFrame )( ICorDebugStackWalk * This, /* [out] */ ICorDebugFrame **pFrame); END_INTERFACE } ICorDebugStackWalkVtbl; interface ICorDebugStackWalk { CONST_VTBL struct ICorDebugStackWalkVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugStackWalk_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStackWalk_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStackWalk_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStackWalk_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) #define ICorDebugStackWalk_SetContext(This,flag,contextSize,context) \ ( (This)->lpVtbl -> SetContext(This,flag,contextSize,context) ) #define ICorDebugStackWalk_Next(This) \ ( (This)->lpVtbl -> Next(This) ) #define ICorDebugStackWalk_GetFrame(This,pFrame) \ ( (This)->lpVtbl -> GetFrame(This,pFrame) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugStackWalk_INTERFACE_DEFINED__ */ #ifndef __ICorDebugChain_INTERFACE_DEFINED__ #define __ICorDebugChain_INTERFACE_DEFINED__ /* interface ICorDebugChain */ /* [unique][uuid][local][object] */ typedef enum CorDebugChainReason { CHAIN_NONE = 0, CHAIN_CLASS_INIT = 0x1, CHAIN_EXCEPTION_FILTER = 0x2, CHAIN_SECURITY = 0x4, CHAIN_CONTEXT_POLICY = 0x8, CHAIN_INTERCEPTION = 0x10, CHAIN_PROCESS_START = 0x20, CHAIN_THREAD_START = 0x40, CHAIN_ENTER_MANAGED = 0x80, CHAIN_ENTER_UNMANAGED = 0x100, CHAIN_DEBUGGER_EVAL = 0x200, CHAIN_CONTEXT_SWITCH = 0x400, CHAIN_FUNC_EVAL = 0x800 } CorDebugChainReason; EXTERN_C const IID IID_ICorDebugChain; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAEE-8A68-11d2-983C-0000F808342D") ICorDebugChain : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackRange( /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd) = 0; virtual HRESULT STDMETHODCALLTYPE GetContext( /* [out] */ ICorDebugContext **ppContext) = 0; virtual HRESULT STDMETHODCALLTYPE GetCaller( /* [out] */ ICorDebugChain **ppChain) = 0; virtual HRESULT STDMETHODCALLTYPE GetCallee( /* [out] */ ICorDebugChain **ppChain) = 0; virtual HRESULT STDMETHODCALLTYPE GetPrevious( /* [out] */ ICorDebugChain **ppChain) = 0; virtual HRESULT STDMETHODCALLTYPE GetNext( /* [out] */ ICorDebugChain **ppChain) = 0; virtual HRESULT STDMETHODCALLTYPE IsManaged( /* [out] */ BOOL *pManaged) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateFrames( /* [out] */ ICorDebugFrameEnum **ppFrames) = 0; virtual HRESULT STDMETHODCALLTYPE GetActiveFrame( /* [out] */ ICorDebugFrame **ppFrame) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; virtual HRESULT STDMETHODCALLTYPE GetReason( /* [out] */ CorDebugChainReason *pReason) = 0; }; #else /* C style interface */ typedef struct ICorDebugChainVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugChain * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugChain * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugChain * This); HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugChain * This, /* [out] */ ICorDebugThread **ppThread); HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugChain * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugChain * This, /* [out] */ ICorDebugContext **ppContext); HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetPrevious )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetNext )( ICorDebugChain * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *IsManaged )( ICorDebugChain * This, /* [out] */ BOOL *pManaged); HRESULT ( STDMETHODCALLTYPE *EnumerateFrames )( ICorDebugChain * This, /* [out] */ ICorDebugFrameEnum **ppFrames); HRESULT ( STDMETHODCALLTYPE *GetActiveFrame )( ICorDebugChain * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugChain * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); HRESULT ( STDMETHODCALLTYPE *GetReason )( ICorDebugChain * This, /* [out] */ CorDebugChainReason *pReason); END_INTERFACE } ICorDebugChainVtbl; interface ICorDebugChain { CONST_VTBL struct ICorDebugChainVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugChain_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugChain_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugChain_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugChain_GetThread(This,ppThread) \ ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugChain_GetStackRange(This,pStart,pEnd) \ ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugChain_GetContext(This,ppContext) \ ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugChain_GetCaller(This,ppChain) \ ( (This)->lpVtbl -> GetCaller(This,ppChain) ) #define ICorDebugChain_GetCallee(This,ppChain) \ ( (This)->lpVtbl -> GetCallee(This,ppChain) ) #define ICorDebugChain_GetPrevious(This,ppChain) \ ( (This)->lpVtbl -> GetPrevious(This,ppChain) ) #define ICorDebugChain_GetNext(This,ppChain) \ ( (This)->lpVtbl -> GetNext(This,ppChain) ) #define ICorDebugChain_IsManaged(This,pManaged) \ ( (This)->lpVtbl -> IsManaged(This,pManaged) ) #define ICorDebugChain_EnumerateFrames(This,ppFrames) \ ( (This)->lpVtbl -> EnumerateFrames(This,ppFrames) ) #define ICorDebugChain_GetActiveFrame(This,ppFrame) \ ( (This)->lpVtbl -> GetActiveFrame(This,ppFrame) ) #define ICorDebugChain_GetRegisterSet(This,ppRegisters) \ ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugChain_GetReason(This,pReason) \ ( (This)->lpVtbl -> GetReason(This,pReason) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugChain_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFrame_INTERFACE_DEFINED__ #define __ICorDebugFrame_INTERFACE_DEFINED__ /* interface ICorDebugFrame */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFrame; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAEF-8A68-11d2-983C-0000F808342D") ICorDebugFrame : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetChain( /* [out] */ ICorDebugChain **ppChain) = 0; virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ICorDebugCode **ppCode) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionToken( /* [out] */ mdMethodDef *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackRange( /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd) = 0; virtual HRESULT STDMETHODCALLTYPE GetCaller( /* [out] */ ICorDebugFrame **ppFrame) = 0; virtual HRESULT STDMETHODCALLTYPE GetCallee( /* [out] */ ICorDebugFrame **ppFrame) = 0; virtual HRESULT STDMETHODCALLTYPE CreateStepper( /* [out] */ ICorDebugStepper **ppStepper) = 0; }; #else /* C style interface */ typedef struct ICorDebugFrameVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFrame * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFrame * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFrame * This); HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugFrame * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugFrame * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugFrame * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugFrame * This, /* [out] */ mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugFrame * This, /* [out] */ ICorDebugStepper **ppStepper); END_INTERFACE } ICorDebugFrameVtbl; interface ICorDebugFrame { CONST_VTBL struct ICorDebugFrameVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFrame_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFrame_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFrame_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFrame_GetChain(This,ppChain) \ ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugFrame_GetCode(This,ppCode) \ ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugFrame_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugFrame_GetFunctionToken(This,pToken) \ ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugFrame_GetStackRange(This,pStart,pEnd) \ ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugFrame_GetCaller(This,ppFrame) \ ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugFrame_GetCallee(This,ppFrame) \ ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugFrame_CreateStepper(This,ppStepper) \ ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFrame_INTERFACE_DEFINED__ */ #ifndef __ICorDebugInternalFrame_INTERFACE_DEFINED__ #define __ICorDebugInternalFrame_INTERFACE_DEFINED__ /* interface ICorDebugInternalFrame */ /* [unique][uuid][local][object] */ typedef enum CorDebugInternalFrameType { STUBFRAME_NONE = 0, STUBFRAME_M2U = 0x1, STUBFRAME_U2M = 0x2, STUBFRAME_APPDOMAIN_TRANSITION = 0x3, STUBFRAME_LIGHTWEIGHT_FUNCTION = 0x4, STUBFRAME_FUNC_EVAL = 0x5, STUBFRAME_INTERNALCALL = 0x6, STUBFRAME_CLASS_INIT = 0x7, STUBFRAME_EXCEPTION = 0x8, STUBFRAME_SECURITY = 0x9, STUBFRAME_JIT_COMPILATION = 0xa } CorDebugInternalFrameType; EXTERN_C const IID IID_ICorDebugInternalFrame; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B92CC7F7-9D2D-45c4-BC2B-621FCC9DFBF4") ICorDebugInternalFrame : public ICorDebugFrame { public: virtual HRESULT STDMETHODCALLTYPE GetFrameType( /* [out] */ CorDebugInternalFrameType *pType) = 0; }; #else /* C style interface */ typedef struct ICorDebugInternalFrameVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInternalFrame * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInternalFrame * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInternalFrame * This); HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugInternalFrame * This, /* [out] */ mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugInternalFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugInternalFrame * This, /* [out] */ ICorDebugStepper **ppStepper); HRESULT ( STDMETHODCALLTYPE *GetFrameType )( ICorDebugInternalFrame * This, /* [out] */ CorDebugInternalFrameType *pType); END_INTERFACE } ICorDebugInternalFrameVtbl; interface ICorDebugInternalFrame { CONST_VTBL struct ICorDebugInternalFrameVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugInternalFrame_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInternalFrame_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInternalFrame_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInternalFrame_GetChain(This,ppChain) \ ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugInternalFrame_GetCode(This,ppCode) \ ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugInternalFrame_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugInternalFrame_GetFunctionToken(This,pToken) \ ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugInternalFrame_GetStackRange(This,pStart,pEnd) \ ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugInternalFrame_GetCaller(This,ppFrame) \ ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugInternalFrame_GetCallee(This,ppFrame) \ ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugInternalFrame_CreateStepper(This,ppStepper) \ ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugInternalFrame_GetFrameType(This,pType) \ ( (This)->lpVtbl -> GetFrameType(This,pType) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugInternalFrame_INTERFACE_DEFINED__ */ #ifndef __ICorDebugInternalFrame2_INTERFACE_DEFINED__ #define __ICorDebugInternalFrame2_INTERFACE_DEFINED__ /* interface ICorDebugInternalFrame2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugInternalFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("C0815BDC-CFAB-447e-A779-C116B454EB5B") ICorDebugInternalFrame2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; virtual HRESULT STDMETHODCALLTYPE IsCloserToLeaf( /* [in] */ ICorDebugFrame *pFrameToCompare, /* [out] */ BOOL *pIsCloser) = 0; }; #else /* C style interface */ typedef struct ICorDebugInternalFrame2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugInternalFrame2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugInternalFrame2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugInternalFrame2 * This); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugInternalFrame2 * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *IsCloserToLeaf )( ICorDebugInternalFrame2 * This, /* [in] */ ICorDebugFrame *pFrameToCompare, /* [out] */ BOOL *pIsCloser); END_INTERFACE } ICorDebugInternalFrame2Vtbl; interface ICorDebugInternalFrame2 { CONST_VTBL struct ICorDebugInternalFrame2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugInternalFrame2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugInternalFrame2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugInternalFrame2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugInternalFrame2_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugInternalFrame2_IsCloserToLeaf(This,pFrameToCompare,pIsCloser) \ ( (This)->lpVtbl -> IsCloserToLeaf(This,pFrameToCompare,pIsCloser) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugInternalFrame2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugILFrame_INTERFACE_DEFINED__ #define __ICorDebugILFrame_INTERFACE_DEFINED__ /* interface ICorDebugILFrame */ /* [unique][uuid][local][object] */ typedef enum CorDebugMappingResult { MAPPING_PROLOG = 0x1, MAPPING_EPILOG = 0x2, MAPPING_NO_INFO = 0x4, MAPPING_UNMAPPED_ADDRESS = 0x8, MAPPING_EXACT = 0x10, MAPPING_APPROXIMATE = 0x20 } CorDebugMappingResult; EXTERN_C const IID IID_ICorDebugILFrame; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("03E26311-4F76-11d3-88C6-006097945418") ICorDebugILFrame : public ICorDebugFrame { public: virtual HRESULT STDMETHODCALLTYPE GetIP( /* [out] */ ULONG32 *pnOffset, /* [out] */ CorDebugMappingResult *pMappingResult) = 0; virtual HRESULT STDMETHODCALLTYPE SetIP( /* [in] */ ULONG32 nOffset) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariables( /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalVariable( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateArguments( /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetArgument( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackDepth( /* [out] */ ULONG32 *pDepth) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackValue( /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE CanSetIP( /* [in] */ ULONG32 nOffset) = 0; }; #else /* C style interface */ typedef struct ICorDebugILFrameVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame * This); HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugILFrame * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugILFrame * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugILFrame * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugILFrame * This, /* [out] */ mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugILFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugILFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugILFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugILFrame * This, /* [out] */ ICorDebugStepper **ppStepper); HRESULT ( STDMETHODCALLTYPE *GetIP )( ICorDebugILFrame * This, /* [out] */ ULONG32 *pnOffset, /* [out] */ CorDebugMappingResult *pMappingResult); HRESULT ( STDMETHODCALLTYPE *SetIP )( ICorDebugILFrame * This, /* [in] */ ULONG32 nOffset); HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariables )( ICorDebugILFrame * This, /* [out] */ ICorDebugValueEnum **ppValueEnum); HRESULT ( STDMETHODCALLTYPE *GetLocalVariable )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *EnumerateArguments )( ICorDebugILFrame * This, /* [out] */ ICorDebugValueEnum **ppValueEnum); HRESULT ( STDMETHODCALLTYPE *GetArgument )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetStackDepth )( ICorDebugILFrame * This, /* [out] */ ULONG32 *pDepth); HRESULT ( STDMETHODCALLTYPE *GetStackValue )( ICorDebugILFrame * This, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *CanSetIP )( ICorDebugILFrame * This, /* [in] */ ULONG32 nOffset); END_INTERFACE } ICorDebugILFrameVtbl; interface ICorDebugILFrame { CONST_VTBL struct ICorDebugILFrameVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugILFrame_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame_GetChain(This,ppChain) \ ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugILFrame_GetCode(This,ppCode) \ ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugILFrame_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugILFrame_GetFunctionToken(This,pToken) \ ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugILFrame_GetStackRange(This,pStart,pEnd) \ ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugILFrame_GetCaller(This,ppFrame) \ ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugILFrame_GetCallee(This,ppFrame) \ ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugILFrame_CreateStepper(This,ppStepper) \ ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugILFrame_GetIP(This,pnOffset,pMappingResult) \ ( (This)->lpVtbl -> GetIP(This,pnOffset,pMappingResult) ) #define ICorDebugILFrame_SetIP(This,nOffset) \ ( (This)->lpVtbl -> SetIP(This,nOffset) ) #define ICorDebugILFrame_EnumerateLocalVariables(This,ppValueEnum) \ ( (This)->lpVtbl -> EnumerateLocalVariables(This,ppValueEnum) ) #define ICorDebugILFrame_GetLocalVariable(This,dwIndex,ppValue) \ ( (This)->lpVtbl -> GetLocalVariable(This,dwIndex,ppValue) ) #define ICorDebugILFrame_EnumerateArguments(This,ppValueEnum) \ ( (This)->lpVtbl -> EnumerateArguments(This,ppValueEnum) ) #define ICorDebugILFrame_GetArgument(This,dwIndex,ppValue) \ ( (This)->lpVtbl -> GetArgument(This,dwIndex,ppValue) ) #define ICorDebugILFrame_GetStackDepth(This,pDepth) \ ( (This)->lpVtbl -> GetStackDepth(This,pDepth) ) #define ICorDebugILFrame_GetStackValue(This,dwIndex,ppValue) \ ( (This)->lpVtbl -> GetStackValue(This,dwIndex,ppValue) ) #define ICorDebugILFrame_CanSetIP(This,nOffset) \ ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugILFrame_INTERFACE_DEFINED__ */ #ifndef __ICorDebugILFrame2_INTERFACE_DEFINED__ #define __ICorDebugILFrame2_INTERFACE_DEFINED__ /* interface ICorDebugILFrame2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5D88A994-6C30-479b-890F-BCEF88B129A5") ICorDebugILFrame2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE RemapFunction( /* [in] */ ULONG32 newILOffset) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; }; #else /* C style interface */ typedef struct ICorDebugILFrame2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame2 * This); HRESULT ( STDMETHODCALLTYPE *RemapFunction )( ICorDebugILFrame2 * This, /* [in] */ ULONG32 newILOffset); HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( ICorDebugILFrame2 * This, /* [out] */ ICorDebugTypeEnum **ppTyParEnum); END_INTERFACE } ICorDebugILFrame2Vtbl; interface ICorDebugILFrame2 { CONST_VTBL struct ICorDebugILFrame2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugILFrame2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame2_RemapFunction(This,newILOffset) \ ( (This)->lpVtbl -> RemapFunction(This,newILOffset) ) #define ICorDebugILFrame2_EnumerateTypeParameters(This,ppTyParEnum) \ ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugILFrame2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugILFrame3_INTERFACE_DEFINED__ #define __ICorDebugILFrame3_INTERFACE_DEFINED__ /* interface ICorDebugILFrame3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("9A9E2ED6-04DF-4FE0-BB50-CAB64126AD24") ICorDebugILFrame3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetReturnValueForILOffset( ULONG32 ILoffset, /* [out] */ ICorDebugValue **ppReturnValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugILFrame3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame3 * This); HRESULT ( STDMETHODCALLTYPE *GetReturnValueForILOffset )( ICorDebugILFrame3 * This, ULONG32 ILoffset, /* [out] */ ICorDebugValue **ppReturnValue); END_INTERFACE } ICorDebugILFrame3Vtbl; interface ICorDebugILFrame3 { CONST_VTBL struct ICorDebugILFrame3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugILFrame3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame3_GetReturnValueForILOffset(This,ILoffset,ppReturnValue) \ ( (This)->lpVtbl -> GetReturnValueForILOffset(This,ILoffset,ppReturnValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugILFrame3_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0070 */ /* [local] */ typedef enum ILCodeKind { ILCODE_ORIGINAL_IL = 0x1, ILCODE_REJIT_IL = 0x2 } ILCodeKind; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0070_v0_0_s_ifspec; #ifndef __ICorDebugILFrame4_INTERFACE_DEFINED__ #define __ICorDebugILFrame4_INTERFACE_DEFINED__ /* interface ICorDebugILFrame4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILFrame4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AD914A30-C6D1-4AC5-9C5E-577F3BAA8A45") ICorDebugILFrame4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumerateLocalVariablesEx( /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugValueEnum **ppValueEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalVariableEx( /* [in] */ ILCodeKind flags, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeEx( /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugCode **ppCode) = 0; }; #else /* C style interface */ typedef struct ICorDebugILFrame4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILFrame4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILFrame4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILFrame4 * This); HRESULT ( STDMETHODCALLTYPE *EnumerateLocalVariablesEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugValueEnum **ppValueEnum); HRESULT ( STDMETHODCALLTYPE *GetLocalVariableEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [in] */ DWORD dwIndex, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetCodeEx )( ICorDebugILFrame4 * This, /* [in] */ ILCodeKind flags, /* [out] */ ICorDebugCode **ppCode); END_INTERFACE } ICorDebugILFrame4Vtbl; interface ICorDebugILFrame4 { CONST_VTBL struct ICorDebugILFrame4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugILFrame4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILFrame4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILFrame4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILFrame4_EnumerateLocalVariablesEx(This,flags,ppValueEnum) \ ( (This)->lpVtbl -> EnumerateLocalVariablesEx(This,flags,ppValueEnum) ) #define ICorDebugILFrame4_GetLocalVariableEx(This,flags,dwIndex,ppValue) \ ( (This)->lpVtbl -> GetLocalVariableEx(This,flags,dwIndex,ppValue) ) #define ICorDebugILFrame4_GetCodeEx(This,flags,ppCode) \ ( (This)->lpVtbl -> GetCodeEx(This,flags,ppCode) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugILFrame4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugNativeFrame_INTERFACE_DEFINED__ #define __ICorDebugNativeFrame_INTERFACE_DEFINED__ /* interface ICorDebugNativeFrame */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugNativeFrame; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("03E26314-4F76-11d3-88C6-006097945418") ICorDebugNativeFrame : public ICorDebugFrame { public: virtual HRESULT STDMETHODCALLTYPE GetIP( /* [out] */ ULONG32 *pnOffset) = 0; virtual HRESULT STDMETHODCALLTYPE SetIP( /* [in] */ ULONG32 nOffset) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegisterSet( /* [out] */ ICorDebugRegisterSet **ppRegisters) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterValue( /* [in] */ CorDebugRegister reg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalDoubleRegisterValue( /* [in] */ CorDebugRegister highWordReg, /* [in] */ CorDebugRegister lowWordReg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryValue( /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalRegisterMemoryValue( /* [in] */ CorDebugRegister highWordReg, /* [in] */ CORDB_ADDRESS lowWordAddress, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalMemoryRegisterValue( /* [in] */ CORDB_ADDRESS highWordAddress, /* [in] */ CorDebugRegister lowWordRegister, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE CanSetIP( /* [in] */ ULONG32 nOffset) = 0; }; #else /* C style interface */ typedef struct ICorDebugNativeFrameVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugNativeFrame * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugNativeFrame * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugNativeFrame * This); HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugNativeFrame * This, /* [out] */ mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugNativeFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugStepper **ppStepper); HRESULT ( STDMETHODCALLTYPE *GetIP )( ICorDebugNativeFrame * This, /* [out] */ ULONG32 *pnOffset); HRESULT ( STDMETHODCALLTYPE *SetIP )( ICorDebugNativeFrame * This, /* [in] */ ULONG32 nOffset); HRESULT ( STDMETHODCALLTYPE *GetRegisterSet )( ICorDebugNativeFrame * This, /* [out] */ ICorDebugRegisterSet **ppRegisters); HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister reg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetLocalDoubleRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister highWordReg, /* [in] */ CorDebugRegister lowWordReg, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryValue )( ICorDebugNativeFrame * This, /* [in] */ CORDB_ADDRESS address, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetLocalRegisterMemoryValue )( ICorDebugNativeFrame * This, /* [in] */ CorDebugRegister highWordReg, /* [in] */ CORDB_ADDRESS lowWordAddress, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetLocalMemoryRegisterValue )( ICorDebugNativeFrame * This, /* [in] */ CORDB_ADDRESS highWordAddress, /* [in] */ CorDebugRegister lowWordRegister, /* [in] */ ULONG cbSigBlob, /* [in] */ PCCOR_SIGNATURE pvSigBlob, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *CanSetIP )( ICorDebugNativeFrame * This, /* [in] */ ULONG32 nOffset); END_INTERFACE } ICorDebugNativeFrameVtbl; interface ICorDebugNativeFrame { CONST_VTBL struct ICorDebugNativeFrameVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugNativeFrame_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugNativeFrame_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugNativeFrame_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugNativeFrame_GetChain(This,ppChain) \ ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugNativeFrame_GetCode(This,ppCode) \ ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugNativeFrame_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugNativeFrame_GetFunctionToken(This,pToken) \ ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugNativeFrame_GetStackRange(This,pStart,pEnd) \ ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugNativeFrame_GetCaller(This,ppFrame) \ ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugNativeFrame_GetCallee(This,ppFrame) \ ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugNativeFrame_CreateStepper(This,ppStepper) \ ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #define ICorDebugNativeFrame_GetIP(This,pnOffset) \ ( (This)->lpVtbl -> GetIP(This,pnOffset) ) #define ICorDebugNativeFrame_SetIP(This,nOffset) \ ( (This)->lpVtbl -> SetIP(This,nOffset) ) #define ICorDebugNativeFrame_GetRegisterSet(This,ppRegisters) \ ( (This)->lpVtbl -> GetRegisterSet(This,ppRegisters) ) #define ICorDebugNativeFrame_GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) \ ( (This)->lpVtbl -> GetLocalRegisterValue(This,reg,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) \ ( (This)->lpVtbl -> GetLocalDoubleRegisterValue(This,highWordReg,lowWordReg,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) \ ( (This)->lpVtbl -> GetLocalMemoryValue(This,address,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) \ ( (This)->lpVtbl -> GetLocalRegisterMemoryValue(This,highWordReg,lowWordAddress,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) \ ( (This)->lpVtbl -> GetLocalMemoryRegisterValue(This,highWordAddress,lowWordRegister,cbSigBlob,pvSigBlob,ppValue) ) #define ICorDebugNativeFrame_CanSetIP(This,nOffset) \ ( (This)->lpVtbl -> CanSetIP(This,nOffset) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugNativeFrame_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0072 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0072_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0072_v0_0_s_ifspec; #ifndef __ICorDebugNativeFrame2_INTERFACE_DEFINED__ #define __ICorDebugNativeFrame2_INTERFACE_DEFINED__ /* interface ICorDebugNativeFrame2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugNativeFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("35389FF1-3684-4c55-A2EE-210F26C60E5E") ICorDebugNativeFrame2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsChild( /* [out] */ BOOL *pIsChild) = 0; virtual HRESULT STDMETHODCALLTYPE IsMatchingParentFrame( /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, /* [out] */ BOOL *pIsParent) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackParameterSize( /* [out] */ ULONG32 *pSize) = 0; }; #else /* C style interface */ typedef struct ICorDebugNativeFrame2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugNativeFrame2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugNativeFrame2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugNativeFrame2 * This); HRESULT ( STDMETHODCALLTYPE *IsChild )( ICorDebugNativeFrame2 * This, /* [out] */ BOOL *pIsChild); HRESULT ( STDMETHODCALLTYPE *IsMatchingParentFrame )( ICorDebugNativeFrame2 * This, /* [in] */ ICorDebugNativeFrame2 *pPotentialParentFrame, /* [out] */ BOOL *pIsParent); HRESULT ( STDMETHODCALLTYPE *GetStackParameterSize )( ICorDebugNativeFrame2 * This, /* [out] */ ULONG32 *pSize); END_INTERFACE } ICorDebugNativeFrame2Vtbl; interface ICorDebugNativeFrame2 { CONST_VTBL struct ICorDebugNativeFrame2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugNativeFrame2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugNativeFrame2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugNativeFrame2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugNativeFrame2_IsChild(This,pIsChild) \ ( (This)->lpVtbl -> IsChild(This,pIsChild) ) #define ICorDebugNativeFrame2_IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) \ ( (This)->lpVtbl -> IsMatchingParentFrame(This,pPotentialParentFrame,pIsParent) ) #define ICorDebugNativeFrame2_GetStackParameterSize(This,pSize) \ ( (This)->lpVtbl -> GetStackParameterSize(This,pSize) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugNativeFrame2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugModule3_INTERFACE_DEFINED__ #define __ICorDebugModule3_INTERFACE_DEFINED__ /* interface ICorDebugModule3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("86F012BF-FF15-4372-BD30-B6F11CAAE1DD") ICorDebugModule3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CreateReaderForInMemorySymbols( /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppObj) = 0; }; #else /* C style interface */ typedef struct ICorDebugModule3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule3 * This); HRESULT ( STDMETHODCALLTYPE *CreateReaderForInMemorySymbols )( ICorDebugModule3 * This, /* [in] */ REFIID riid, /* [iid_is][out] */ void **ppObj); END_INTERFACE } ICorDebugModule3Vtbl; interface ICorDebugModule3 { CONST_VTBL struct ICorDebugModule3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModule3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule3_CreateReaderForInMemorySymbols(This,riid,ppObj) \ ( (This)->lpVtbl -> CreateReaderForInMemorySymbols(This,riid,ppObj) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModule3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugModule4_INTERFACE_DEFINED__ #define __ICorDebugModule4_INTERFACE_DEFINED__ /* interface ICorDebugModule4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FF8B8EAF-25CD-4316-8859-84416DE4402E") ICorDebugModule4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsMappedLayout( /* [out] */ BOOL *pIsMapped) = 0; }; #else /* C style interface */ typedef struct ICorDebugModule4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule4 * This); HRESULT ( STDMETHODCALLTYPE *IsMappedLayout )( ICorDebugModule4 * This, /* [out] */ BOOL *pIsMapped); END_INTERFACE } ICorDebugModule4Vtbl; interface ICorDebugModule4 { CONST_VTBL struct ICorDebugModule4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModule4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule4_IsMappedLayout(This,pIsMapped) \ ( (This)->lpVtbl -> IsMappedLayout(This,pIsMapped) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModule4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ #define __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ /* interface ICorDebugRuntimeUnwindableFrame */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugRuntimeUnwindableFrame; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("879CAC0A-4A53-4668-B8E3-CB8473CB187F") ICorDebugRuntimeUnwindableFrame : public ICorDebugFrame { public: }; #else /* C style interface */ typedef struct ICorDebugRuntimeUnwindableFrameVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugRuntimeUnwindableFrame * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugRuntimeUnwindableFrame * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugRuntimeUnwindableFrame * This); HRESULT ( STDMETHODCALLTYPE *GetChain )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugChain **ppChain); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetFunctionToken )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetStackRange )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ CORDB_ADDRESS *pStart, /* [out] */ CORDB_ADDRESS *pEnd); HRESULT ( STDMETHODCALLTYPE *GetCaller )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *GetCallee )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugFrame **ppFrame); HRESULT ( STDMETHODCALLTYPE *CreateStepper )( ICorDebugRuntimeUnwindableFrame * This, /* [out] */ ICorDebugStepper **ppStepper); END_INTERFACE } ICorDebugRuntimeUnwindableFrameVtbl; interface ICorDebugRuntimeUnwindableFrame { CONST_VTBL struct ICorDebugRuntimeUnwindableFrameVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugRuntimeUnwindableFrame_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugRuntimeUnwindableFrame_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugRuntimeUnwindableFrame_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugRuntimeUnwindableFrame_GetChain(This,ppChain) \ ( (This)->lpVtbl -> GetChain(This,ppChain) ) #define ICorDebugRuntimeUnwindableFrame_GetCode(This,ppCode) \ ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugRuntimeUnwindableFrame_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugRuntimeUnwindableFrame_GetFunctionToken(This,pToken) \ ( (This)->lpVtbl -> GetFunctionToken(This,pToken) ) #define ICorDebugRuntimeUnwindableFrame_GetStackRange(This,pStart,pEnd) \ ( (This)->lpVtbl -> GetStackRange(This,pStart,pEnd) ) #define ICorDebugRuntimeUnwindableFrame_GetCaller(This,ppFrame) \ ( (This)->lpVtbl -> GetCaller(This,ppFrame) ) #define ICorDebugRuntimeUnwindableFrame_GetCallee(This,ppFrame) \ ( (This)->lpVtbl -> GetCallee(This,ppFrame) ) #define ICorDebugRuntimeUnwindableFrame_CreateStepper(This,ppStepper) \ ( (This)->lpVtbl -> CreateStepper(This,ppStepper) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugRuntimeUnwindableFrame_INTERFACE_DEFINED__ */ #ifndef __ICorDebugModule_INTERFACE_DEFINED__ #define __ICorDebugModule_INTERFACE_DEFINED__ /* interface ICorDebugModule */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("dba2d8c1-e5c5-4069-8c13-10a7c6abf43d") ICorDebugModule : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ ICorDebugProcess **ppProcess) = 0; virtual HRESULT STDMETHODCALLTYPE GetBaseAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssembly( /* [out] */ ICorDebugAssembly **ppAssembly) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE EnableJITDebugging( /* [in] */ BOOL bTrackJITInfo, /* [in] */ BOOL bAllowJitOpts) = 0; virtual HRESULT STDMETHODCALLTYPE EnableClassLoadCallbacks( /* [in] */ BOOL bClassLoadCallbacks) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( /* [in] */ mdMethodDef methodDef, /* [out] */ ICorDebugFunction **ppFunction) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromRVA( /* [in] */ CORDB_ADDRESS rva, /* [out] */ ICorDebugFunction **ppFunction) = 0; virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( /* [in] */ mdTypeDef typeDef, /* [out] */ ICorDebugClass **ppClass) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint) = 0; virtual HRESULT STDMETHODCALLTYPE GetEditAndContinueSnapshot( /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot) = 0; virtual HRESULT STDMETHODCALLTYPE GetMetaDataInterface( /* [in] */ REFIID riid, /* [out] */ IUnknown **ppObj) = 0; virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdModule *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE IsDynamic( /* [out] */ BOOL *pDynamic) = 0; virtual HRESULT STDMETHODCALLTYPE GetGlobalVariableValue( /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; virtual HRESULT STDMETHODCALLTYPE IsInMemory( /* [out] */ BOOL *pInMemory) = 0; }; #else /* C style interface */ typedef struct ICorDebugModuleVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule * This); HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorDebugModule * This, /* [out] */ ICorDebugProcess **ppProcess); HRESULT ( STDMETHODCALLTYPE *GetBaseAddress )( ICorDebugModule * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *GetAssembly )( ICorDebugModule * This, /* [out] */ ICorDebugAssembly **ppAssembly); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugModule * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *EnableJITDebugging )( ICorDebugModule * This, /* [in] */ BOOL bTrackJITInfo, /* [in] */ BOOL bAllowJitOpts); HRESULT ( STDMETHODCALLTYPE *EnableClassLoadCallbacks )( ICorDebugModule * This, /* [in] */ BOOL bClassLoadCallbacks); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorDebugModule * This, /* [in] */ mdMethodDef methodDef, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromRVA )( ICorDebugModule * This, /* [in] */ CORDB_ADDRESS rva, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorDebugModule * This, /* [in] */ mdTypeDef typeDef, /* [out] */ ICorDebugClass **ppClass); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugModule * This, /* [out] */ ICorDebugModuleBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetEditAndContinueSnapshot )( ICorDebugModule * This, /* [out] */ ICorDebugEditAndContinueSnapshot **ppEditAndContinueSnapshot); HRESULT ( STDMETHODCALLTYPE *GetMetaDataInterface )( ICorDebugModule * This, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppObj); HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugModule * This, /* [out] */ mdModule *pToken); HRESULT ( STDMETHODCALLTYPE *IsDynamic )( ICorDebugModule * This, /* [out] */ BOOL *pDynamic); HRESULT ( STDMETHODCALLTYPE *GetGlobalVariableValue )( ICorDebugModule * This, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugModule * This, /* [out] */ ULONG32 *pcBytes); HRESULT ( STDMETHODCALLTYPE *IsInMemory )( ICorDebugModule * This, /* [out] */ BOOL *pInMemory); END_INTERFACE } ICorDebugModuleVtbl; interface ICorDebugModule { CONST_VTBL struct ICorDebugModuleVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModule_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule_GetProcess(This,ppProcess) \ ( (This)->lpVtbl -> GetProcess(This,ppProcess) ) #define ICorDebugModule_GetBaseAddress(This,pAddress) \ ( (This)->lpVtbl -> GetBaseAddress(This,pAddress) ) #define ICorDebugModule_GetAssembly(This,ppAssembly) \ ( (This)->lpVtbl -> GetAssembly(This,ppAssembly) ) #define ICorDebugModule_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugModule_EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) \ ( (This)->lpVtbl -> EnableJITDebugging(This,bTrackJITInfo,bAllowJitOpts) ) #define ICorDebugModule_EnableClassLoadCallbacks(This,bClassLoadCallbacks) \ ( (This)->lpVtbl -> EnableClassLoadCallbacks(This,bClassLoadCallbacks) ) #define ICorDebugModule_GetFunctionFromToken(This,methodDef,ppFunction) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,methodDef,ppFunction) ) #define ICorDebugModule_GetFunctionFromRVA(This,rva,ppFunction) \ ( (This)->lpVtbl -> GetFunctionFromRVA(This,rva,ppFunction) ) #define ICorDebugModule_GetClassFromToken(This,typeDef,ppClass) \ ( (This)->lpVtbl -> GetClassFromToken(This,typeDef,ppClass) ) #define ICorDebugModule_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugModule_GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) \ ( (This)->lpVtbl -> GetEditAndContinueSnapshot(This,ppEditAndContinueSnapshot) ) #define ICorDebugModule_GetMetaDataInterface(This,riid,ppObj) \ ( (This)->lpVtbl -> GetMetaDataInterface(This,riid,ppObj) ) #define ICorDebugModule_GetToken(This,pToken) \ ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ICorDebugModule_IsDynamic(This,pDynamic) \ ( (This)->lpVtbl -> IsDynamic(This,pDynamic) ) #define ICorDebugModule_GetGlobalVariableValue(This,fieldDef,ppValue) \ ( (This)->lpVtbl -> GetGlobalVariableValue(This,fieldDef,ppValue) ) #define ICorDebugModule_GetSize(This,pcBytes) \ ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #define ICorDebugModule_IsInMemory(This,pInMemory) \ ( (This)->lpVtbl -> IsInMemory(This,pInMemory) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModule_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0077 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0077_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0077_v0_0_s_ifspec; #ifndef __ICorDebugModule2_INTERFACE_DEFINED__ #define __ICorDebugModule2_INTERFACE_DEFINED__ /* interface ICorDebugModule2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModule2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("7FCC5FB5-49C0-41de-9938-3B88B5B9ADD7") ICorDebugModule2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode, /* [in] */ ULONG32 cTokens, /* [size_is][in] */ mdToken pTokens[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE ApplyChanges( /* [in] */ ULONG cbMetadata, /* [size_is][in] */ BYTE pbMetadata[ ], /* [in] */ ULONG cbIL, /* [size_is][in] */ BYTE pbIL[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( /* [in] */ DWORD dwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetJITCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE ResolveAssembly( /* [in] */ mdToken tkAssemblyRef, /* [out] */ ICorDebugAssembly **ppAssembly) = 0; }; #else /* C style interface */ typedef struct ICorDebugModule2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModule2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModule2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModule2 * This); HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugModule2 * This, /* [in] */ BOOL bIsJustMyCode, /* [in] */ ULONG32 cTokens, /* [size_is][in] */ mdToken pTokens[ ]); HRESULT ( STDMETHODCALLTYPE *ApplyChanges )( ICorDebugModule2 * This, /* [in] */ ULONG cbMetadata, /* [size_is][in] */ BYTE pbMetadata[ ], /* [in] */ ULONG cbIL, /* [size_is][in] */ BYTE pbIL[ ]); HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( ICorDebugModule2 * This, /* [in] */ DWORD dwFlags); HRESULT ( STDMETHODCALLTYPE *GetJITCompilerFlags )( ICorDebugModule2 * This, /* [out] */ DWORD *pdwFlags); HRESULT ( STDMETHODCALLTYPE *ResolveAssembly )( ICorDebugModule2 * This, /* [in] */ mdToken tkAssemblyRef, /* [out] */ ICorDebugAssembly **ppAssembly); END_INTERFACE } ICorDebugModule2Vtbl; interface ICorDebugModule2 { CONST_VTBL struct ICorDebugModule2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModule2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModule2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModule2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModule2_SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) \ ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode,cTokens,pTokens) ) #define ICorDebugModule2_ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) \ ( (This)->lpVtbl -> ApplyChanges(This,cbMetadata,pbMetadata,cbIL,pbIL) ) #define ICorDebugModule2_SetJITCompilerFlags(This,dwFlags) \ ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) #define ICorDebugModule2_GetJITCompilerFlags(This,pdwFlags) \ ( (This)->lpVtbl -> GetJITCompilerFlags(This,pdwFlags) ) #define ICorDebugModule2_ResolveAssembly(This,tkAssemblyRef,ppAssembly) \ ( (This)->lpVtbl -> ResolveAssembly(This,tkAssemblyRef,ppAssembly) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModule2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFunction_INTERFACE_DEFINED__ #define __ICorDebugFunction_INTERFACE_DEFINED__ /* interface ICorDebugFunction */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF3-8A68-11d2-983C-0000F808342D") ICorDebugFunction : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdMethodDef *pMethodDef) = 0; virtual HRESULT STDMETHODCALLTYPE GetILCode( /* [out] */ ICorDebugCode **ppCode) = 0; virtual HRESULT STDMETHODCALLTYPE GetNativeCode( /* [out] */ ICorDebugCode **ppCode) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( /* [out] */ mdSignature *pmdSig) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentVersionNumber( /* [out] */ ULONG32 *pnCurrentVersion) = 0; }; #else /* C style interface */ typedef struct ICorDebugFunctionVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction * This); HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugFunction * This, /* [out] */ ICorDebugModule **ppModule); HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugFunction * This, /* [out] */ ICorDebugClass **ppClass); HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugFunction * This, /* [out] */ mdMethodDef *pMethodDef); HRESULT ( STDMETHODCALLTYPE *GetILCode )( ICorDebugFunction * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetNativeCode )( ICorDebugFunction * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugFunction * This, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( ICorDebugFunction * This, /* [out] */ mdSignature *pmdSig); HRESULT ( STDMETHODCALLTYPE *GetCurrentVersionNumber )( ICorDebugFunction * This, /* [out] */ ULONG32 *pnCurrentVersion); END_INTERFACE } ICorDebugFunctionVtbl; interface ICorDebugFunction { CONST_VTBL struct ICorDebugFunctionVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFunction_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction_GetModule(This,ppModule) \ ( (This)->lpVtbl -> GetModule(This,ppModule) ) #define ICorDebugFunction_GetClass(This,ppClass) \ ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugFunction_GetToken(This,pMethodDef) \ ( (This)->lpVtbl -> GetToken(This,pMethodDef) ) #define ICorDebugFunction_GetILCode(This,ppCode) \ ( (This)->lpVtbl -> GetILCode(This,ppCode) ) #define ICorDebugFunction_GetNativeCode(This,ppCode) \ ( (This)->lpVtbl -> GetNativeCode(This,ppCode) ) #define ICorDebugFunction_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugFunction_GetLocalVarSigToken(This,pmdSig) \ ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) #define ICorDebugFunction_GetCurrentVersionNumber(This,pnCurrentVersion) \ ( (This)->lpVtbl -> GetCurrentVersionNumber(This,pnCurrentVersion) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFunction_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFunction2_INTERFACE_DEFINED__ #define __ICorDebugFunction2_INTERFACE_DEFINED__ /* interface ICorDebugFunction2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("EF0C490B-94C3-4e4d-B629-DDC134C532D8") ICorDebugFunction2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode) = 0; virtual HRESULT STDMETHODCALLTYPE GetJMCStatus( /* [out] */ BOOL *pbIsJustMyCode) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateNativeCode( /* [out] */ ICorDebugCodeEnum **ppCodeEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( /* [out] */ ULONG32 *pnVersion) = 0; }; #else /* C style interface */ typedef struct ICorDebugFunction2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction2 * This); HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugFunction2 * This, /* [in] */ BOOL bIsJustMyCode); HRESULT ( STDMETHODCALLTYPE *GetJMCStatus )( ICorDebugFunction2 * This, /* [out] */ BOOL *pbIsJustMyCode); HRESULT ( STDMETHODCALLTYPE *EnumerateNativeCode )( ICorDebugFunction2 * This, /* [out] */ ICorDebugCodeEnum **ppCodeEnum); HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( ICorDebugFunction2 * This, /* [out] */ ULONG32 *pnVersion); END_INTERFACE } ICorDebugFunction2Vtbl; interface ICorDebugFunction2 { CONST_VTBL struct ICorDebugFunction2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFunction2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction2_SetJMCStatus(This,bIsJustMyCode) \ ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) #define ICorDebugFunction2_GetJMCStatus(This,pbIsJustMyCode) \ ( (This)->lpVtbl -> GetJMCStatus(This,pbIsJustMyCode) ) #define ICorDebugFunction2_EnumerateNativeCode(This,ppCodeEnum) \ ( (This)->lpVtbl -> EnumerateNativeCode(This,ppCodeEnum) ) #define ICorDebugFunction2_GetVersionNumber(This,pnVersion) \ ( (This)->lpVtbl -> GetVersionNumber(This,pnVersion) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFunction2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFunction3_INTERFACE_DEFINED__ #define __ICorDebugFunction3_INTERFACE_DEFINED__ /* interface ICorDebugFunction3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("09B70F28-E465-482D-99E0-81A165EB0532") ICorDebugFunction3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetActiveReJitRequestILCode( ICorDebugILCode **ppReJitedILCode) = 0; }; #else /* C style interface */ typedef struct ICorDebugFunction3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction3 * This); HRESULT ( STDMETHODCALLTYPE *GetActiveReJitRequestILCode )( ICorDebugFunction3 * This, ICorDebugILCode **ppReJitedILCode); END_INTERFACE } ICorDebugFunction3Vtbl; interface ICorDebugFunction3 { CONST_VTBL struct ICorDebugFunction3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFunction3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction3_GetActiveReJitRequestILCode(This,ppReJitedILCode) \ ( (This)->lpVtbl -> GetActiveReJitRequestILCode(This,ppReJitedILCode) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFunction3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFunction4_INTERFACE_DEFINED__ #define __ICorDebugFunction4_INTERFACE_DEFINED__ /* interface ICorDebugFunction4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFunction4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("72965963-34fd-46e9-9434-b817fe6e7f43") ICorDebugFunction4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CreateNativeBreakpoint( ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; }; #else /* C style interface */ typedef struct ICorDebugFunction4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFunction4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFunction4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFunction4 * This); HRESULT ( STDMETHODCALLTYPE *CreateNativeBreakpoint )( ICorDebugFunction4 * This, ICorDebugFunctionBreakpoint **ppBreakpoint); END_INTERFACE } ICorDebugFunction4Vtbl; interface ICorDebugFunction4 { CONST_VTBL struct ICorDebugFunction4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFunction4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFunction4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFunction4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFunction4_CreateNativeBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateNativeBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFunction4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugCode_INTERFACE_DEFINED__ #define __ICorDebugCode_INTERFACE_DEFINED__ /* interface ICorDebugCode */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF4-8A68-11d2-983C-0000F808342D") ICorDebugCode : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsIL( /* [out] */ BOOL *pbIL) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pStart) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pcBytes) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [in] */ ULONG32 offset, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint) = 0; virtual HRESULT STDMETHODCALLTYPE GetCode( /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset, /* [in] */ ULONG32 cBufferAlloc, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *pcBufferSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetVersionNumber( /* [out] */ ULONG32 *nVersion) = 0; virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetEnCRemapSequencePoints( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ ULONG32 offsets[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugCodeVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode * This); HRESULT ( STDMETHODCALLTYPE *IsIL )( ICorDebugCode * This, /* [out] */ BOOL *pbIL); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugCode * This, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugCode * This, /* [out] */ CORDB_ADDRESS *pStart); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugCode * This, /* [out] */ ULONG32 *pcBytes); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugCode * This, /* [in] */ ULONG32 offset, /* [out] */ ICorDebugFunctionBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugCode * This, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset, /* [in] */ ULONG32 cBufferAlloc, /* [length_is][size_is][out] */ BYTE buffer[ ], /* [out] */ ULONG32 *pcBufferSize); HRESULT ( STDMETHODCALLTYPE *GetVersionNumber )( ICorDebugCode * This, /* [out] */ ULONG32 *nVersion); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorDebugCode * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *GetEnCRemapSequencePoints )( ICorDebugCode * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ ULONG32 offsets[ ]); END_INTERFACE } ICorDebugCodeVtbl; interface ICorDebugCode { CONST_VTBL struct ICorDebugCodeVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugCode_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode_IsIL(This,pbIL) \ ( (This)->lpVtbl -> IsIL(This,pbIL) ) #define ICorDebugCode_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #define ICorDebugCode_GetAddress(This,pStart) \ ( (This)->lpVtbl -> GetAddress(This,pStart) ) #define ICorDebugCode_GetSize(This,pcBytes) \ ( (This)->lpVtbl -> GetSize(This,pcBytes) ) #define ICorDebugCode_CreateBreakpoint(This,offset,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,offset,ppBreakpoint) ) #define ICorDebugCode_GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) \ ( (This)->lpVtbl -> GetCode(This,startOffset,endOffset,cBufferAlloc,buffer,pcBufferSize) ) #define ICorDebugCode_GetVersionNumber(This,nVersion) \ ( (This)->lpVtbl -> GetVersionNumber(This,nVersion) ) #define ICorDebugCode_GetILToNativeMapping(This,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,cMap,pcMap,map) ) #define ICorDebugCode_GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) \ ( (This)->lpVtbl -> GetEnCRemapSequencePoints(This,cMap,pcMap,offsets) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugCode_INTERFACE_DEFINED__ */ #ifndef __ICorDebugCode2_INTERFACE_DEFINED__ #define __ICorDebugCode2_INTERFACE_DEFINED__ /* interface ICorDebugCode2 */ /* [unique][uuid][local][object] */ typedef struct _CodeChunkInfo { CORDB_ADDRESS startAddr; ULONG32 length; } CodeChunkInfo; EXTERN_C const IID IID_ICorDebugCode2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5F696509-452F-4436-A3FE-4D11FE7E2347") ICorDebugCode2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetCodeChunks( /* [in] */ ULONG32 cbufSize, /* [out] */ ULONG32 *pcnumChunks, /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCompilerFlags( /* [out] */ DWORD *pdwFlags) = 0; }; #else /* C style interface */ typedef struct ICorDebugCode2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode2 * This); HRESULT ( STDMETHODCALLTYPE *GetCodeChunks )( ICorDebugCode2 * This, /* [in] */ ULONG32 cbufSize, /* [out] */ ULONG32 *pcnumChunks, /* [length_is][size_is][out] */ CodeChunkInfo chunks[ ]); HRESULT ( STDMETHODCALLTYPE *GetCompilerFlags )( ICorDebugCode2 * This, /* [out] */ DWORD *pdwFlags); END_INTERFACE } ICorDebugCode2Vtbl; interface ICorDebugCode2 { CONST_VTBL struct ICorDebugCode2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugCode2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode2_GetCodeChunks(This,cbufSize,pcnumChunks,chunks) \ ( (This)->lpVtbl -> GetCodeChunks(This,cbufSize,pcnumChunks,chunks) ) #define ICorDebugCode2_GetCompilerFlags(This,pdwFlags) \ ( (This)->lpVtbl -> GetCompilerFlags(This,pdwFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugCode2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugCode3_INTERFACE_DEFINED__ #define __ICorDebugCode3_INTERFACE_DEFINED__ /* interface ICorDebugCode3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D13D3E88-E1F2-4020-AA1D-3D162DCBE966") ICorDebugCode3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetReturnValueLiveOffset( /* [in] */ ULONG32 ILoffset, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *pFetched, /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugCode3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode3 * This); HRESULT ( STDMETHODCALLTYPE *GetReturnValueLiveOffset )( ICorDebugCode3 * This, /* [in] */ ULONG32 ILoffset, /* [in] */ ULONG32 bufferSize, /* [out] */ ULONG32 *pFetched, /* [length_is][size_is][out] */ ULONG32 pOffsets[ ]); END_INTERFACE } ICorDebugCode3Vtbl; interface ICorDebugCode3 { CONST_VTBL struct ICorDebugCode3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugCode3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode3_GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) \ ( (This)->lpVtbl -> GetReturnValueLiveOffset(This,ILoffset,bufferSize,pFetched,pOffsets) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugCode3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugCode4_INTERFACE_DEFINED__ #define __ICorDebugCode4_INTERFACE_DEFINED__ /* interface ICorDebugCode4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCode4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("18221fa4-20cb-40fa-b19d-9f91c4fa8c14") ICorDebugCode4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumerateVariableHomes( /* [out] */ ICorDebugVariableHomeEnum **ppEnum) = 0; }; #else /* C style interface */ typedef struct ICorDebugCode4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCode4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCode4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCode4 * This); HRESULT ( STDMETHODCALLTYPE *EnumerateVariableHomes )( ICorDebugCode4 * This, /* [out] */ ICorDebugVariableHomeEnum **ppEnum); END_INTERFACE } ICorDebugCode4Vtbl; interface ICorDebugCode4 { CONST_VTBL struct ICorDebugCode4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugCode4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCode4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCode4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCode4_EnumerateVariableHomes(This,ppEnum) \ ( (This)->lpVtbl -> EnumerateVariableHomes(This,ppEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugCode4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugILCode_INTERFACE_DEFINED__ #define __ICorDebugILCode_INTERFACE_DEFINED__ /* interface ICorDebugILCode */ /* [unique][uuid][local][object] */ typedef struct _CorDebugEHClause { ULONG32 Flags; ULONG32 TryOffset; ULONG32 TryLength; ULONG32 HandlerOffset; ULONG32 HandlerLength; ULONG32 ClassToken; ULONG32 FilterOffset; } CorDebugEHClause; EXTERN_C const IID IID_ICorDebugILCode; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("598D46C2-C877-42A7-89D2-3D0C7F1C1264") ICorDebugILCode : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetEHClauses( /* [in] */ ULONG32 cClauses, /* [out] */ ULONG32 *pcClauses, /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugILCodeVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILCode * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILCode * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILCode * This); HRESULT ( STDMETHODCALLTYPE *GetEHClauses )( ICorDebugILCode * This, /* [in] */ ULONG32 cClauses, /* [out] */ ULONG32 *pcClauses, /* [length_is][size_is][out] */ CorDebugEHClause clauses[ ]); END_INTERFACE } ICorDebugILCodeVtbl; interface ICorDebugILCode { CONST_VTBL struct ICorDebugILCodeVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugILCode_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILCode_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILCode_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILCode_GetEHClauses(This,cClauses,pcClauses,clauses) \ ( (This)->lpVtbl -> GetEHClauses(This,cClauses,pcClauses,clauses) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugILCode_INTERFACE_DEFINED__ */ #ifndef __ICorDebugILCode2_INTERFACE_DEFINED__ #define __ICorDebugILCode2_INTERFACE_DEFINED__ /* interface ICorDebugILCode2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugILCode2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("46586093-D3F5-4DB6-ACDB-955BCE228C15") ICorDebugILCode2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetLocalVarSigToken( /* [out] */ mdSignature *pmdSig) = 0; virtual HRESULT STDMETHODCALLTYPE GetInstrumentedILMap( /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_IL_MAP map[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugILCode2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugILCode2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugILCode2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugILCode2 * This); HRESULT ( STDMETHODCALLTYPE *GetLocalVarSigToken )( ICorDebugILCode2 * This, /* [out] */ mdSignature *pmdSig); HRESULT ( STDMETHODCALLTYPE *GetInstrumentedILMap )( ICorDebugILCode2 * This, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_IL_MAP map[ ]); END_INTERFACE } ICorDebugILCode2Vtbl; interface ICorDebugILCode2 { CONST_VTBL struct ICorDebugILCode2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugILCode2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugILCode2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugILCode2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugILCode2_GetLocalVarSigToken(This,pmdSig) \ ( (This)->lpVtbl -> GetLocalVarSigToken(This,pmdSig) ) #define ICorDebugILCode2_GetInstrumentedILMap(This,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetInstrumentedILMap(This,cMap,pcMap,map) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugILCode2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugClass_INTERFACE_DEFINED__ #define __ICorDebugClass_INTERFACE_DEFINED__ /* interface ICorDebugClass */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugClass; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF5-8A68-11d2-983C-0000F808342D") ICorDebugClass : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **pModule) = 0; virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdTypeDef *pTypeDef) = 0; virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugClassVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugClass * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugClass * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugClass * This); HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugClass * This, /* [out] */ ICorDebugModule **pModule); HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugClass * This, /* [out] */ mdTypeDef *pTypeDef); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( ICorDebugClass * This, /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue); END_INTERFACE } ICorDebugClassVtbl; interface ICorDebugClass { CONST_VTBL struct ICorDebugClassVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugClass_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugClass_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugClass_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugClass_GetModule(This,pModule) \ ( (This)->lpVtbl -> GetModule(This,pModule) ) #define ICorDebugClass_GetToken(This,pTypeDef) \ ( (This)->lpVtbl -> GetToken(This,pTypeDef) ) #define ICorDebugClass_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugClass_INTERFACE_DEFINED__ */ #ifndef __ICorDebugClass2_INTERFACE_DEFINED__ #define __ICorDebugClass2_INTERFACE_DEFINED__ /* interface ICorDebugClass2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugClass2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B008EA8D-7AB1-43f7-BB20-FBB5A04038AE") ICorDebugClass2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetParameterizedType( /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType) = 0; virtual HRESULT STDMETHODCALLTYPE SetJMCStatus( /* [in] */ BOOL bIsJustMyCode) = 0; }; #else /* C style interface */ typedef struct ICorDebugClass2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugClass2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugClass2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugClass2 * This); HRESULT ( STDMETHODCALLTYPE *GetParameterizedType )( ICorDebugClass2 * This, /* [in] */ CorElementType elementType, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [out] */ ICorDebugType **ppType); HRESULT ( STDMETHODCALLTYPE *SetJMCStatus )( ICorDebugClass2 * This, /* [in] */ BOOL bIsJustMyCode); END_INTERFACE } ICorDebugClass2Vtbl; interface ICorDebugClass2 { CONST_VTBL struct ICorDebugClass2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugClass2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugClass2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugClass2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugClass2_GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) \ ( (This)->lpVtbl -> GetParameterizedType(This,elementType,nTypeArgs,ppTypeArgs,ppType) ) #define ICorDebugClass2_SetJMCStatus(This,bIsJustMyCode) \ ( (This)->lpVtbl -> SetJMCStatus(This,bIsJustMyCode) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugClass2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugEval_INTERFACE_DEFINED__ #define __ICorDebugEval_INTERFACE_DEFINED__ /* interface ICorDebugEval */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEval; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF6-8A68-11d2-983C-0000F808342D") ICorDebugEval : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CallFunction( /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE NewObject( /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE NewObjectNoConstructor( /* [in] */ ICorDebugClass *pClass) = 0; virtual HRESULT STDMETHODCALLTYPE NewString( /* [in] */ LPCWSTR string) = 0; virtual HRESULT STDMETHODCALLTYPE NewArray( /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE IsActive( /* [out] */ BOOL *pbActive) = 0; virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetResult( /* [out] */ ICorDebugValue **ppResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetThread( /* [out] */ ICorDebugThread **ppThread) = 0; virtual HRESULT STDMETHODCALLTYPE CreateValue( /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [out] */ ICorDebugValue **ppValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugEvalVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEval * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEval * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEval * This); HRESULT ( STDMETHODCALLTYPE *CallFunction )( ICorDebugEval * This, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); HRESULT ( STDMETHODCALLTYPE *NewObject )( ICorDebugEval * This, /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); HRESULT ( STDMETHODCALLTYPE *NewObjectNoConstructor )( ICorDebugEval * This, /* [in] */ ICorDebugClass *pClass); HRESULT ( STDMETHODCALLTYPE *NewString )( ICorDebugEval * This, /* [in] */ LPCWSTR string); HRESULT ( STDMETHODCALLTYPE *NewArray )( ICorDebugEval * This, /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]); HRESULT ( STDMETHODCALLTYPE *IsActive )( ICorDebugEval * This, /* [out] */ BOOL *pbActive); HRESULT ( STDMETHODCALLTYPE *Abort )( ICorDebugEval * This); HRESULT ( STDMETHODCALLTYPE *GetResult )( ICorDebugEval * This, /* [out] */ ICorDebugValue **ppResult); HRESULT ( STDMETHODCALLTYPE *GetThread )( ICorDebugEval * This, /* [out] */ ICorDebugThread **ppThread); HRESULT ( STDMETHODCALLTYPE *CreateValue )( ICorDebugEval * This, /* [in] */ CorElementType elementType, /* [in] */ ICorDebugClass *pElementClass, /* [out] */ ICorDebugValue **ppValue); END_INTERFACE } ICorDebugEvalVtbl; interface ICorDebugEval { CONST_VTBL struct ICorDebugEvalVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugEval_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEval_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEval_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEval_CallFunction(This,pFunction,nArgs,ppArgs) \ ( (This)->lpVtbl -> CallFunction(This,pFunction,nArgs,ppArgs) ) #define ICorDebugEval_NewObject(This,pConstructor,nArgs,ppArgs) \ ( (This)->lpVtbl -> NewObject(This,pConstructor,nArgs,ppArgs) ) #define ICorDebugEval_NewObjectNoConstructor(This,pClass) \ ( (This)->lpVtbl -> NewObjectNoConstructor(This,pClass) ) #define ICorDebugEval_NewString(This,string) \ ( (This)->lpVtbl -> NewString(This,string) ) #define ICorDebugEval_NewArray(This,elementType,pElementClass,rank,dims,lowBounds) \ ( (This)->lpVtbl -> NewArray(This,elementType,pElementClass,rank,dims,lowBounds) ) #define ICorDebugEval_IsActive(This,pbActive) \ ( (This)->lpVtbl -> IsActive(This,pbActive) ) #define ICorDebugEval_Abort(This) \ ( (This)->lpVtbl -> Abort(This) ) #define ICorDebugEval_GetResult(This,ppResult) \ ( (This)->lpVtbl -> GetResult(This,ppResult) ) #define ICorDebugEval_GetThread(This,ppThread) \ ( (This)->lpVtbl -> GetThread(This,ppThread) ) #define ICorDebugEval_CreateValue(This,elementType,pElementClass,ppValue) \ ( (This)->lpVtbl -> CreateValue(This,elementType,pElementClass,ppValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugEval_INTERFACE_DEFINED__ */ #ifndef __ICorDebugEval2_INTERFACE_DEFINED__ #define __ICorDebugEval2_INTERFACE_DEFINED__ /* interface ICorDebugEval2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEval2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FB0D9CE7-BE66-4683-9D32-A42A04E2FD91") ICorDebugEval2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CallParameterizedFunction( /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE CreateValueForType( /* [in] */ ICorDebugType *pType, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE NewParameterizedObject( /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE NewParameterizedObjectNoConstructor( /* [in] */ ICorDebugClass *pClass, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE NewParameterizedArray( /* [in] */ ICorDebugType *pElementType, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE NewStringWithLength( /* [in] */ LPCWSTR string, /* [in] */ UINT uiLength) = 0; virtual HRESULT STDMETHODCALLTYPE RudeAbort( void) = 0; }; #else /* C style interface */ typedef struct ICorDebugEval2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEval2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEval2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEval2 * This); HRESULT ( STDMETHODCALLTYPE *CallParameterizedFunction )( ICorDebugEval2 * This, /* [in] */ ICorDebugFunction *pFunction, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); HRESULT ( STDMETHODCALLTYPE *CreateValueForType )( ICorDebugEval2 * This, /* [in] */ ICorDebugType *pType, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *NewParameterizedObject )( ICorDebugEval2 * This, /* [in] */ ICorDebugFunction *pConstructor, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ], /* [in] */ ULONG32 nArgs, /* [size_is][in] */ ICorDebugValue *ppArgs[ ]); HRESULT ( STDMETHODCALLTYPE *NewParameterizedObjectNoConstructor )( ICorDebugEval2 * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ ULONG32 nTypeArgs, /* [size_is][in] */ ICorDebugType *ppTypeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *NewParameterizedArray )( ICorDebugEval2 * This, /* [in] */ ICorDebugType *pElementType, /* [in] */ ULONG32 rank, /* [size_is][in] */ ULONG32 dims[ ], /* [size_is][in] */ ULONG32 lowBounds[ ]); HRESULT ( STDMETHODCALLTYPE *NewStringWithLength )( ICorDebugEval2 * This, /* [in] */ LPCWSTR string, /* [in] */ UINT uiLength); HRESULT ( STDMETHODCALLTYPE *RudeAbort )( ICorDebugEval2 * This); END_INTERFACE } ICorDebugEval2Vtbl; interface ICorDebugEval2 { CONST_VTBL struct ICorDebugEval2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugEval2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEval2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEval2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEval2_CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ ( (This)->lpVtbl -> CallParameterizedFunction(This,pFunction,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) #define ICorDebugEval2_CreateValueForType(This,pType,ppValue) \ ( (This)->lpVtbl -> CreateValueForType(This,pType,ppValue) ) #define ICorDebugEval2_NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) \ ( (This)->lpVtbl -> NewParameterizedObject(This,pConstructor,nTypeArgs,ppTypeArgs,nArgs,ppArgs) ) #define ICorDebugEval2_NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) \ ( (This)->lpVtbl -> NewParameterizedObjectNoConstructor(This,pClass,nTypeArgs,ppTypeArgs) ) #define ICorDebugEval2_NewParameterizedArray(This,pElementType,rank,dims,lowBounds) \ ( (This)->lpVtbl -> NewParameterizedArray(This,pElementType,rank,dims,lowBounds) ) #define ICorDebugEval2_NewStringWithLength(This,string,uiLength) \ ( (This)->lpVtbl -> NewStringWithLength(This,string,uiLength) ) #define ICorDebugEval2_RudeAbort(This) \ ( (This)->lpVtbl -> RudeAbort(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugEval2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugValue_INTERFACE_DEFINED__ #define __ICorDebugValue_INTERFACE_DEFINED__ /* interface ICorDebugValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF7-8A68-11d2-983C-0000F808342D") ICorDebugValue : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ CorElementType *pType) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG32 *pSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CORDB_ADDRESS *pAddress) = 0; virtual HRESULT STDMETHODCALLTYPE CreateBreakpoint( /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; }; #else /* C style interface */ typedef struct ICorDebugValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); END_INTERFACE } ICorDebugValueVtbl; interface ICorDebugValue { CONST_VTBL struct ICorDebugValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugValue2_INTERFACE_DEFINED__ #define __ICorDebugValue2_INTERFACE_DEFINED__ /* interface ICorDebugValue2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5E0B54E7-D88A-4626-9420-A691E0A78B49") ICorDebugValue2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetExactType( /* [out] */ ICorDebugType **ppType) = 0; }; #else /* C style interface */ typedef struct ICorDebugValue2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue2 * This); HRESULT ( STDMETHODCALLTYPE *GetExactType )( ICorDebugValue2 * This, /* [out] */ ICorDebugType **ppType); END_INTERFACE } ICorDebugValue2Vtbl; interface ICorDebugValue2 { CONST_VTBL struct ICorDebugValue2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugValue2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue2_GetExactType(This,ppType) \ ( (This)->lpVtbl -> GetExactType(This,ppType) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugValue2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugValue3_INTERFACE_DEFINED__ #define __ICorDebugValue3_INTERFACE_DEFINED__ /* interface ICorDebugValue3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValue3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("565005FC-0F8A-4F3E-9EDB-83102B156595") ICorDebugValue3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetSize64( /* [out] */ ULONG64 *pSize) = 0; }; #else /* C style interface */ typedef struct ICorDebugValue3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValue3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValue3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValue3 * This); HRESULT ( STDMETHODCALLTYPE *GetSize64 )( ICorDebugValue3 * This, /* [out] */ ULONG64 *pSize); END_INTERFACE } ICorDebugValue3Vtbl; interface ICorDebugValue3 { CONST_VTBL struct ICorDebugValue3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugValue3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValue3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValue3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValue3_GetSize64(This,pSize) \ ( (This)->lpVtbl -> GetSize64(This,pSize) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugValue3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugGenericValue_INTERFACE_DEFINED__ #define __ICorDebugGenericValue_INTERFACE_DEFINED__ /* interface ICorDebugGenericValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugGenericValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF8-8A68-11d2-983C-0000F808342D") ICorDebugGenericValue : public ICorDebugValue { public: virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ void *pTo) = 0; virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ void *pFrom) = 0; }; #else /* C style interface */ typedef struct ICorDebugGenericValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugGenericValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugGenericValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugGenericValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugGenericValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugGenericValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugGenericValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugGenericValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugGenericValue * This, /* [out] */ void *pTo); HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugGenericValue * This, /* [in] */ void *pFrom); END_INTERFACE } ICorDebugGenericValueVtbl; interface ICorDebugGenericValue { CONST_VTBL struct ICorDebugGenericValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugGenericValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugGenericValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugGenericValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugGenericValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugGenericValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugGenericValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugGenericValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugGenericValue_GetValue(This,pTo) \ ( (This)->lpVtbl -> GetValue(This,pTo) ) #define ICorDebugGenericValue_SetValue(This,pFrom) \ ( (This)->lpVtbl -> SetValue(This,pFrom) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugGenericValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugReferenceValue_INTERFACE_DEFINED__ #define __ICorDebugReferenceValue_INTERFACE_DEFINED__ /* interface ICorDebugReferenceValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugReferenceValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAF9-8A68-11d2-983C-0000F808342D") ICorDebugReferenceValue : public ICorDebugValue { public: virtual HRESULT STDMETHODCALLTYPE IsNull( /* [out] */ BOOL *pbNull) = 0; virtual HRESULT STDMETHODCALLTYPE GetValue( /* [out] */ CORDB_ADDRESS *pValue) = 0; virtual HRESULT STDMETHODCALLTYPE SetValue( /* [in] */ CORDB_ADDRESS value) = 0; virtual HRESULT STDMETHODCALLTYPE Dereference( /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE DereferenceStrong( /* [out] */ ICorDebugValue **ppValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugReferenceValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugReferenceValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugReferenceValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugReferenceValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugReferenceValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugReferenceValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugReferenceValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *IsNull )( ICorDebugReferenceValue * This, /* [out] */ BOOL *pbNull); HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugReferenceValue * This, /* [out] */ CORDB_ADDRESS *pValue); HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugReferenceValue * This, /* [in] */ CORDB_ADDRESS value); HRESULT ( STDMETHODCALLTYPE *Dereference )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( ICorDebugReferenceValue * This, /* [out] */ ICorDebugValue **ppValue); END_INTERFACE } ICorDebugReferenceValueVtbl; interface ICorDebugReferenceValue { CONST_VTBL struct ICorDebugReferenceValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugReferenceValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugReferenceValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugReferenceValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugReferenceValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugReferenceValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugReferenceValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugReferenceValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugReferenceValue_IsNull(This,pbNull) \ ( (This)->lpVtbl -> IsNull(This,pbNull) ) #define ICorDebugReferenceValue_GetValue(This,pValue) \ ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ICorDebugReferenceValue_SetValue(This,value) \ ( (This)->lpVtbl -> SetValue(This,value) ) #define ICorDebugReferenceValue_Dereference(This,ppValue) \ ( (This)->lpVtbl -> Dereference(This,ppValue) ) #define ICorDebugReferenceValue_DereferenceStrong(This,ppValue) \ ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugReferenceValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugHeapValue_INTERFACE_DEFINED__ #define __ICorDebugHeapValue_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAFA-8A68-11d2-983C-0000F808342D") ICorDebugHeapValue : public ICorDebugValue { public: virtual HRESULT STDMETHODCALLTYPE IsValid( /* [out] */ BOOL *pbValid) = 0; virtual HRESULT STDMETHODCALLTYPE CreateRelocBreakpoint( /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint) = 0; }; #else /* C style interface */ typedef struct ICorDebugHeapValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugHeapValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugHeapValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugHeapValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugHeapValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugHeapValue * This, /* [out] */ BOOL *pbValid); HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugHeapValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); END_INTERFACE } ICorDebugHeapValueVtbl; interface ICorDebugHeapValue { CONST_VTBL struct ICorDebugHeapValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHeapValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugHeapValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugHeapValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugHeapValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugHeapValue_IsValid(This,pbValid) \ ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugHeapValue_CreateRelocBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHeapValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugHeapValue2_INTERFACE_DEFINED__ #define __ICorDebugHeapValue2_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E3AC4D6C-9CB7-43e6-96CC-B21540E5083C") ICorDebugHeapValue2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CreateHandle( /* [in] */ CorDebugHandleType type, /* [out] */ ICorDebugHandleValue **ppHandle) = 0; }; #else /* C style interface */ typedef struct ICorDebugHeapValue2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue2 * This); HRESULT ( STDMETHODCALLTYPE *CreateHandle )( ICorDebugHeapValue2 * This, /* [in] */ CorDebugHandleType type, /* [out] */ ICorDebugHandleValue **ppHandle); END_INTERFACE } ICorDebugHeapValue2Vtbl; interface ICorDebugHeapValue2 { CONST_VTBL struct ICorDebugHeapValue2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHeapValue2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue2_CreateHandle(This,type,ppHandle) \ ( (This)->lpVtbl -> CreateHandle(This,type,ppHandle) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHeapValue2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugHeapValue3_INTERFACE_DEFINED__ #define __ICorDebugHeapValue3_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A69ACAD8-2374-46e9-9FF8-B1F14120D296") ICorDebugHeapValue3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetThreadOwningMonitorLock( /* [out] */ ICorDebugThread **ppThread, /* [out] */ DWORD *pAcquisitionCount) = 0; virtual HRESULT STDMETHODCALLTYPE GetMonitorEventWaitList( /* [out] */ ICorDebugThreadEnum **ppThreadEnum) = 0; }; #else /* C style interface */ typedef struct ICorDebugHeapValue3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue3 * This); HRESULT ( STDMETHODCALLTYPE *GetThreadOwningMonitorLock )( ICorDebugHeapValue3 * This, /* [out] */ ICorDebugThread **ppThread, /* [out] */ DWORD *pAcquisitionCount); HRESULT ( STDMETHODCALLTYPE *GetMonitorEventWaitList )( ICorDebugHeapValue3 * This, /* [out] */ ICorDebugThreadEnum **ppThreadEnum); END_INTERFACE } ICorDebugHeapValue3Vtbl; interface ICorDebugHeapValue3 { CONST_VTBL struct ICorDebugHeapValue3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHeapValue3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue3_GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) \ ( (This)->lpVtbl -> GetThreadOwningMonitorLock(This,ppThread,pAcquisitionCount) ) #define ICorDebugHeapValue3_GetMonitorEventWaitList(This,ppThreadEnum) \ ( (This)->lpVtbl -> GetMonitorEventWaitList(This,ppThreadEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHeapValue3_INTERFACE_DEFINED__ */ #ifndef __ICorDebugHeapValue4_INTERFACE_DEFINED__ #define __ICorDebugHeapValue4_INTERFACE_DEFINED__ /* interface ICorDebugHeapValue4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHeapValue4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B35DD495-A555-463B-9BE9-C55338486BB8") ICorDebugHeapValue4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CreatePinnedHandle( /* [out] */ ICorDebugHandleValue **ppHandle) = 0; }; #else /* C style interface */ typedef struct ICorDebugHeapValue4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHeapValue4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHeapValue4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHeapValue4 * This); HRESULT ( STDMETHODCALLTYPE *CreatePinnedHandle )( ICorDebugHeapValue4 * This, /* [out] */ ICorDebugHandleValue **ppHandle); END_INTERFACE } ICorDebugHeapValue4Vtbl; interface ICorDebugHeapValue4 { CONST_VTBL struct ICorDebugHeapValue4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHeapValue4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHeapValue4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHeapValue4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHeapValue4_CreatePinnedHandle(This,ppHandle) \ ( (This)->lpVtbl -> CreatePinnedHandle(This,ppHandle) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHeapValue4_INTERFACE_DEFINED__ */ #ifndef __ICorDebugObjectValue_INTERFACE_DEFINED__ #define __ICorDebugObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugObjectValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("18AD3D6E-B7D2-11d2-BD04-0000F80849BD") ICorDebugObjectValue : public ICorDebugValue { public: virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldValue( /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetVirtualMethod( /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction) = 0; virtual HRESULT STDMETHODCALLTYPE GetContext( /* [out] */ ICorDebugContext **ppContext) = 0; virtual HRESULT STDMETHODCALLTYPE IsValueClass( /* [out] */ BOOL *pbIsValueClass) = 0; virtual HRESULT STDMETHODCALLTYPE GetManagedCopy( /* [out] */ IUnknown **ppObject) = 0; virtual HRESULT STDMETHODCALLTYPE SetFromManagedCopy( /* [in] */ IUnknown *pObject) = 0; }; #else /* C style interface */ typedef struct ICorDebugObjectValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugObjectValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugObjectValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugObjectValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugObjectValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugObjectValue * This, /* [out] */ ICorDebugClass **ppClass); HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( ICorDebugObjectValue * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( ICorDebugObjectValue * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugObjectValue * This, /* [out] */ ICorDebugContext **ppContext); HRESULT ( STDMETHODCALLTYPE *IsValueClass )( ICorDebugObjectValue * This, /* [out] */ BOOL *pbIsValueClass); HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( ICorDebugObjectValue * This, /* [out] */ IUnknown **ppObject); HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( ICorDebugObjectValue * This, /* [in] */ IUnknown *pObject); END_INTERFACE } ICorDebugObjectValueVtbl; interface ICorDebugObjectValue { CONST_VTBL struct ICorDebugObjectValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugObjectValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugObjectValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugObjectValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugObjectValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugObjectValue_GetClass(This,ppClass) \ ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugObjectValue_GetFieldValue(This,pClass,fieldDef,ppValue) \ ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) #define ICorDebugObjectValue_GetVirtualMethod(This,memberRef,ppFunction) \ ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) #define ICorDebugObjectValue_GetContext(This,ppContext) \ ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugObjectValue_IsValueClass(This,pbIsValueClass) \ ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) #define ICorDebugObjectValue_GetManagedCopy(This,ppObject) \ ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) #define ICorDebugObjectValue_SetFromManagedCopy(This,pObject) \ ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugObjectValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugObjectValue2_INTERFACE_DEFINED__ #define __ICorDebugObjectValue2_INTERFACE_DEFINED__ /* interface ICorDebugObjectValue2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectValue2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("49E4A320-4A9B-4eca-B105-229FB7D5009F") ICorDebugObjectValue2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetVirtualMethodAndType( /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction, /* [out] */ ICorDebugType **ppType) = 0; }; #else /* C style interface */ typedef struct ICorDebugObjectValue2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectValue2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectValue2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectValue2 * This); HRESULT ( STDMETHODCALLTYPE *GetVirtualMethodAndType )( ICorDebugObjectValue2 * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction, /* [out] */ ICorDebugType **ppType); END_INTERFACE } ICorDebugObjectValue2Vtbl; interface ICorDebugObjectValue2 { CONST_VTBL struct ICorDebugObjectValue2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugObjectValue2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectValue2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectValue2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectValue2_GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) \ ( (This)->lpVtbl -> GetVirtualMethodAndType(This,memberRef,ppFunction,ppType) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugObjectValue2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ #define __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugDelegateObjectValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugDelegateObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3AF70CC7-6047-47F6-A5C5-090A1A622638") ICorDebugDelegateObjectValue : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetTarget( /* [out] */ ICorDebugReferenceValue **ppObject) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunction( /* [out] */ ICorDebugFunction **ppFunction) = 0; }; #else /* C style interface */ typedef struct ICorDebugDelegateObjectValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugDelegateObjectValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugDelegateObjectValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugDelegateObjectValue * This); HRESULT ( STDMETHODCALLTYPE *GetTarget )( ICorDebugDelegateObjectValue * This, /* [out] */ ICorDebugReferenceValue **ppObject); HRESULT ( STDMETHODCALLTYPE *GetFunction )( ICorDebugDelegateObjectValue * This, /* [out] */ ICorDebugFunction **ppFunction); END_INTERFACE } ICorDebugDelegateObjectValueVtbl; interface ICorDebugDelegateObjectValue { CONST_VTBL struct ICorDebugDelegateObjectValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugDelegateObjectValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugDelegateObjectValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugDelegateObjectValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugDelegateObjectValue_GetTarget(This,ppObject) \ ( (This)->lpVtbl -> GetTarget(This,ppObject) ) #define ICorDebugDelegateObjectValue_GetFunction(This,ppFunction) \ ( (This)->lpVtbl -> GetFunction(This,ppFunction) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugDelegateObjectValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugBoxValue_INTERFACE_DEFINED__ #define __ICorDebugBoxValue_INTERFACE_DEFINED__ /* interface ICorDebugBoxValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBoxValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAFC-8A68-11d2-983C-0000F808342D") ICorDebugBoxValue : public ICorDebugHeapValue { public: virtual HRESULT STDMETHODCALLTYPE GetObject( /* [out] */ ICorDebugObjectValue **ppObject) = 0; }; #else /* C style interface */ typedef struct ICorDebugBoxValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBoxValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBoxValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBoxValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugBoxValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugBoxValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugBoxValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugBoxValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugBoxValue * This, /* [out] */ BOOL *pbValid); HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugBoxValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetObject )( ICorDebugBoxValue * This, /* [out] */ ICorDebugObjectValue **ppObject); END_INTERFACE } ICorDebugBoxValueVtbl; interface ICorDebugBoxValue { CONST_VTBL struct ICorDebugBoxValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugBoxValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBoxValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBoxValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBoxValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugBoxValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugBoxValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugBoxValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugBoxValue_IsValid(This,pbValid) \ ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugBoxValue_CreateRelocBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugBoxValue_GetObject(This,ppObject) \ ( (This)->lpVtbl -> GetObject(This,ppObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugBoxValue_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0105 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0105_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0105_v0_0_s_ifspec; #ifndef __ICorDebugStringValue_INTERFACE_DEFINED__ #define __ICorDebugStringValue_INTERFACE_DEFINED__ /* interface ICorDebugStringValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStringValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCAFD-8A68-11d2-983C-0000F808342D") ICorDebugStringValue : public ICorDebugHeapValue { public: virtual HRESULT STDMETHODCALLTYPE GetLength( /* [out] */ ULONG32 *pcchString) = 0; virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugStringValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStringValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStringValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStringValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugStringValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugStringValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugStringValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugStringValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugStringValue * This, /* [out] */ BOOL *pbValid); HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugStringValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetLength )( ICorDebugStringValue * This, /* [out] */ ULONG32 *pcchString); HRESULT ( STDMETHODCALLTYPE *GetString )( ICorDebugStringValue * This, /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]); END_INTERFACE } ICorDebugStringValueVtbl; interface ICorDebugStringValue { CONST_VTBL struct ICorDebugStringValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugStringValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStringValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStringValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStringValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugStringValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugStringValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugStringValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugStringValue_IsValid(This,pbValid) \ ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugStringValue_CreateRelocBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugStringValue_GetLength(This,pcchString) \ ( (This)->lpVtbl -> GetLength(This,pcchString) ) #define ICorDebugStringValue_GetString(This,cchString,pcchString,szString) \ ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugStringValue_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0106 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0106_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0106_v0_0_s_ifspec; #ifndef __ICorDebugArrayValue_INTERFACE_DEFINED__ #define __ICorDebugArrayValue_INTERFACE_DEFINED__ /* interface ICorDebugArrayValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugArrayValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("0405B0DF-A660-11d2-BD02-0000F80849BD") ICorDebugArrayValue : public ICorDebugHeapValue { public: virtual HRESULT STDMETHODCALLTYPE GetElementType( /* [out] */ CorElementType *pType) = 0; virtual HRESULT STDMETHODCALLTYPE GetRank( /* [out] */ ULONG32 *pnRank) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG32 *pnCount) = 0; virtual HRESULT STDMETHODCALLTYPE GetDimensions( /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 dims[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE HasBaseIndicies( /* [out] */ BOOL *pbHasBaseIndicies) = 0; virtual HRESULT STDMETHODCALLTYPE GetBaseIndicies( /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 indices[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetElement( /* [in] */ ULONG32 cdim, /* [length_is][size_is][in] */ ULONG32 indices[ ], /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetElementAtPosition( /* [in] */ ULONG32 nPosition, /* [out] */ ICorDebugValue **ppValue) = 0; }; #else /* C style interface */ typedef struct ICorDebugArrayValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugArrayValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugArrayValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugArrayValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugArrayValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugArrayValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugArrayValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *IsValid )( ICorDebugArrayValue * This, /* [out] */ BOOL *pbValid); HRESULT ( STDMETHODCALLTYPE *CreateRelocBreakpoint )( ICorDebugArrayValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetElementType )( ICorDebugArrayValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetRank )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pnRank); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugArrayValue * This, /* [out] */ ULONG32 *pnCount); HRESULT ( STDMETHODCALLTYPE *GetDimensions )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 dims[ ]); HRESULT ( STDMETHODCALLTYPE *HasBaseIndicies )( ICorDebugArrayValue * This, /* [out] */ BOOL *pbHasBaseIndicies); HRESULT ( STDMETHODCALLTYPE *GetBaseIndicies )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][out] */ ULONG32 indices[ ]); HRESULT ( STDMETHODCALLTYPE *GetElement )( ICorDebugArrayValue * This, /* [in] */ ULONG32 cdim, /* [length_is][size_is][in] */ ULONG32 indices[ ], /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetElementAtPosition )( ICorDebugArrayValue * This, /* [in] */ ULONG32 nPosition, /* [out] */ ICorDebugValue **ppValue); END_INTERFACE } ICorDebugArrayValueVtbl; interface ICorDebugArrayValue { CONST_VTBL struct ICorDebugArrayValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugArrayValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugArrayValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugArrayValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugArrayValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugArrayValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugArrayValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugArrayValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugArrayValue_IsValid(This,pbValid) \ ( (This)->lpVtbl -> IsValid(This,pbValid) ) #define ICorDebugArrayValue_CreateRelocBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateRelocBreakpoint(This,ppBreakpoint) ) #define ICorDebugArrayValue_GetElementType(This,pType) \ ( (This)->lpVtbl -> GetElementType(This,pType) ) #define ICorDebugArrayValue_GetRank(This,pnRank) \ ( (This)->lpVtbl -> GetRank(This,pnRank) ) #define ICorDebugArrayValue_GetCount(This,pnCount) \ ( (This)->lpVtbl -> GetCount(This,pnCount) ) #define ICorDebugArrayValue_GetDimensions(This,cdim,dims) \ ( (This)->lpVtbl -> GetDimensions(This,cdim,dims) ) #define ICorDebugArrayValue_HasBaseIndicies(This,pbHasBaseIndicies) \ ( (This)->lpVtbl -> HasBaseIndicies(This,pbHasBaseIndicies) ) #define ICorDebugArrayValue_GetBaseIndicies(This,cdim,indices) \ ( (This)->lpVtbl -> GetBaseIndicies(This,cdim,indices) ) #define ICorDebugArrayValue_GetElement(This,cdim,indices,ppValue) \ ( (This)->lpVtbl -> GetElement(This,cdim,indices,ppValue) ) #define ICorDebugArrayValue_GetElementAtPosition(This,nPosition,ppValue) \ ( (This)->lpVtbl -> GetElementAtPosition(This,nPosition,ppValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugArrayValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugVariableHome_INTERFACE_DEFINED__ #define __ICorDebugVariableHome_INTERFACE_DEFINED__ /* interface ICorDebugVariableHome */ /* [unique][uuid][local][object] */ typedef enum VariableLocationType { VLT_REGISTER = 0, VLT_REGISTER_RELATIVE = ( VLT_REGISTER + 1 ) , VLT_INVALID = ( VLT_REGISTER_RELATIVE + 1 ) } VariableLocationType; EXTERN_C const IID IID_ICorDebugVariableHome; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("50847b8d-f43f-41b0-924c-6383a5f2278b") ICorDebugVariableHome : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ICorDebugCode **ppCode) = 0; virtual HRESULT STDMETHODCALLTYPE GetSlotIndex( /* [out] */ ULONG32 *pSlotIndex) = 0; virtual HRESULT STDMETHODCALLTYPE GetArgumentIndex( /* [out] */ ULONG32 *pArgumentIndex) = 0; virtual HRESULT STDMETHODCALLTYPE GetLiveRange( /* [out] */ ULONG32 *pStartOffset, /* [out] */ ULONG32 *pEndOffset) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocationType( /* [out] */ VariableLocationType *pLocationType) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegister( /* [out] */ CorDebugRegister *pRegister) = 0; virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [out] */ LONG *pOffset) = 0; }; #else /* C style interface */ typedef struct ICorDebugVariableHomeVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableHome * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableHome * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableHome * This); HRESULT ( STDMETHODCALLTYPE *GetCode )( ICorDebugVariableHome * This, /* [out] */ ICorDebugCode **ppCode); HRESULT ( STDMETHODCALLTYPE *GetSlotIndex )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pSlotIndex); HRESULT ( STDMETHODCALLTYPE *GetArgumentIndex )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pArgumentIndex); HRESULT ( STDMETHODCALLTYPE *GetLiveRange )( ICorDebugVariableHome * This, /* [out] */ ULONG32 *pStartOffset, /* [out] */ ULONG32 *pEndOffset); HRESULT ( STDMETHODCALLTYPE *GetLocationType )( ICorDebugVariableHome * This, /* [out] */ VariableLocationType *pLocationType); HRESULT ( STDMETHODCALLTYPE *GetRegister )( ICorDebugVariableHome * This, /* [out] */ CorDebugRegister *pRegister); HRESULT ( STDMETHODCALLTYPE *GetOffset )( ICorDebugVariableHome * This, /* [out] */ LONG *pOffset); END_INTERFACE } ICorDebugVariableHomeVtbl; interface ICorDebugVariableHome { CONST_VTBL struct ICorDebugVariableHomeVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugVariableHome_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableHome_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableHome_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableHome_GetCode(This,ppCode) \ ( (This)->lpVtbl -> GetCode(This,ppCode) ) #define ICorDebugVariableHome_GetSlotIndex(This,pSlotIndex) \ ( (This)->lpVtbl -> GetSlotIndex(This,pSlotIndex) ) #define ICorDebugVariableHome_GetArgumentIndex(This,pArgumentIndex) \ ( (This)->lpVtbl -> GetArgumentIndex(This,pArgumentIndex) ) #define ICorDebugVariableHome_GetLiveRange(This,pStartOffset,pEndOffset) \ ( (This)->lpVtbl -> GetLiveRange(This,pStartOffset,pEndOffset) ) #define ICorDebugVariableHome_GetLocationType(This,pLocationType) \ ( (This)->lpVtbl -> GetLocationType(This,pLocationType) ) #define ICorDebugVariableHome_GetRegister(This,pRegister) \ ( (This)->lpVtbl -> GetRegister(This,pRegister) ) #define ICorDebugVariableHome_GetOffset(This,pOffset) \ ( (This)->lpVtbl -> GetOffset(This,pOffset) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugVariableHome_INTERFACE_DEFINED__ */ #ifndef __ICorDebugHandleValue_INTERFACE_DEFINED__ #define __ICorDebugHandleValue_INTERFACE_DEFINED__ /* interface ICorDebugHandleValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugHandleValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("029596E8-276B-46a1-9821-732E96BBB00B") ICorDebugHandleValue : public ICorDebugReferenceValue { public: virtual HRESULT STDMETHODCALLTYPE GetHandleType( /* [out] */ CorDebugHandleType *pType) = 0; virtual HRESULT STDMETHODCALLTYPE Dispose( void) = 0; }; #else /* C style interface */ typedef struct ICorDebugHandleValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugHandleValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugHandleValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugHandleValue * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugHandleValue * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugHandleValue * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugHandleValue * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *IsNull )( ICorDebugHandleValue * This, /* [out] */ BOOL *pbNull); HRESULT ( STDMETHODCALLTYPE *GetValue )( ICorDebugHandleValue * This, /* [out] */ CORDB_ADDRESS *pValue); HRESULT ( STDMETHODCALLTYPE *SetValue )( ICorDebugHandleValue * This, /* [in] */ CORDB_ADDRESS value); HRESULT ( STDMETHODCALLTYPE *Dereference )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *DereferenceStrong )( ICorDebugHandleValue * This, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetHandleType )( ICorDebugHandleValue * This, /* [out] */ CorDebugHandleType *pType); HRESULT ( STDMETHODCALLTYPE *Dispose )( ICorDebugHandleValue * This); END_INTERFACE } ICorDebugHandleValueVtbl; interface ICorDebugHandleValue { CONST_VTBL struct ICorDebugHandleValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugHandleValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugHandleValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugHandleValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugHandleValue_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugHandleValue_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugHandleValue_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugHandleValue_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugHandleValue_IsNull(This,pbNull) \ ( (This)->lpVtbl -> IsNull(This,pbNull) ) #define ICorDebugHandleValue_GetValue(This,pValue) \ ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ICorDebugHandleValue_SetValue(This,value) \ ( (This)->lpVtbl -> SetValue(This,value) ) #define ICorDebugHandleValue_Dereference(This,ppValue) \ ( (This)->lpVtbl -> Dereference(This,ppValue) ) #define ICorDebugHandleValue_DereferenceStrong(This,ppValue) \ ( (This)->lpVtbl -> DereferenceStrong(This,ppValue) ) #define ICorDebugHandleValue_GetHandleType(This,pType) \ ( (This)->lpVtbl -> GetHandleType(This,pType) ) #define ICorDebugHandleValue_Dispose(This) \ ( (This)->lpVtbl -> Dispose(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugHandleValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugContext_INTERFACE_DEFINED__ #define __ICorDebugContext_INTERFACE_DEFINED__ /* interface ICorDebugContext */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugContext; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB00-8A68-11d2-983C-0000F808342D") ICorDebugContext : public ICorDebugObjectValue { public: }; #else /* C style interface */ typedef struct ICorDebugContextVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugContext * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugContext * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugContext * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugContext * This, /* [out] */ CorElementType *pType); HRESULT ( STDMETHODCALLTYPE *GetSize )( ICorDebugContext * This, /* [out] */ ULONG32 *pSize); HRESULT ( STDMETHODCALLTYPE *GetAddress )( ICorDebugContext * This, /* [out] */ CORDB_ADDRESS *pAddress); HRESULT ( STDMETHODCALLTYPE *CreateBreakpoint )( ICorDebugContext * This, /* [out] */ ICorDebugValueBreakpoint **ppBreakpoint); HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugContext * This, /* [out] */ ICorDebugClass **ppClass); HRESULT ( STDMETHODCALLTYPE *GetFieldValue )( ICorDebugContext * This, /* [in] */ ICorDebugClass *pClass, /* [in] */ mdFieldDef fieldDef, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetVirtualMethod )( ICorDebugContext * This, /* [in] */ mdMemberRef memberRef, /* [out] */ ICorDebugFunction **ppFunction); HRESULT ( STDMETHODCALLTYPE *GetContext )( ICorDebugContext * This, /* [out] */ ICorDebugContext **ppContext); HRESULT ( STDMETHODCALLTYPE *IsValueClass )( ICorDebugContext * This, /* [out] */ BOOL *pbIsValueClass); HRESULT ( STDMETHODCALLTYPE *GetManagedCopy )( ICorDebugContext * This, /* [out] */ IUnknown **ppObject); HRESULT ( STDMETHODCALLTYPE *SetFromManagedCopy )( ICorDebugContext * This, /* [in] */ IUnknown *pObject); END_INTERFACE } ICorDebugContextVtbl; interface ICorDebugContext { CONST_VTBL struct ICorDebugContextVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugContext_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugContext_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugContext_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugContext_GetType(This,pType) \ ( (This)->lpVtbl -> GetType(This,pType) ) #define ICorDebugContext_GetSize(This,pSize) \ ( (This)->lpVtbl -> GetSize(This,pSize) ) #define ICorDebugContext_GetAddress(This,pAddress) \ ( (This)->lpVtbl -> GetAddress(This,pAddress) ) #define ICorDebugContext_CreateBreakpoint(This,ppBreakpoint) \ ( (This)->lpVtbl -> CreateBreakpoint(This,ppBreakpoint) ) #define ICorDebugContext_GetClass(This,ppClass) \ ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugContext_GetFieldValue(This,pClass,fieldDef,ppValue) \ ( (This)->lpVtbl -> GetFieldValue(This,pClass,fieldDef,ppValue) ) #define ICorDebugContext_GetVirtualMethod(This,memberRef,ppFunction) \ ( (This)->lpVtbl -> GetVirtualMethod(This,memberRef,ppFunction) ) #define ICorDebugContext_GetContext(This,ppContext) \ ( (This)->lpVtbl -> GetContext(This,ppContext) ) #define ICorDebugContext_IsValueClass(This,pbIsValueClass) \ ( (This)->lpVtbl -> IsValueClass(This,pbIsValueClass) ) #define ICorDebugContext_GetManagedCopy(This,ppObject) \ ( (This)->lpVtbl -> GetManagedCopy(This,ppObject) ) #define ICorDebugContext_SetFromManagedCopy(This,pObject) \ ( (This)->lpVtbl -> SetFromManagedCopy(This,pObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugContext_INTERFACE_DEFINED__ */ #ifndef __ICorDebugComObjectValue_INTERFACE_DEFINED__ #define __ICorDebugComObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugComObjectValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugComObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5F69C5E5-3E12-42DF-B371-F9D761D6EE24") ICorDebugComObjectValue : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetCachedInterfaceTypes( /* [in] */ BOOL bIInspectableOnly, /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCachedInterfacePointers( /* [in] */ BOOL bIInspectableOnly, /* [in] */ ULONG32 celt, /* [out] */ ULONG32 *pcEltFetched, /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs) = 0; }; #else /* C style interface */ typedef struct ICorDebugComObjectValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugComObjectValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugComObjectValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugComObjectValue * This); HRESULT ( STDMETHODCALLTYPE *GetCachedInterfaceTypes )( ICorDebugComObjectValue * This, /* [in] */ BOOL bIInspectableOnly, /* [out] */ ICorDebugTypeEnum **ppInterfacesEnum); HRESULT ( STDMETHODCALLTYPE *GetCachedInterfacePointers )( ICorDebugComObjectValue * This, /* [in] */ BOOL bIInspectableOnly, /* [in] */ ULONG32 celt, /* [out] */ ULONG32 *pcEltFetched, /* [length_is][size_is][out] */ CORDB_ADDRESS *ptrs); END_INTERFACE } ICorDebugComObjectValueVtbl; interface ICorDebugComObjectValue { CONST_VTBL struct ICorDebugComObjectValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugComObjectValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugComObjectValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugComObjectValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugComObjectValue_GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) \ ( (This)->lpVtbl -> GetCachedInterfaceTypes(This,bIInspectableOnly,ppInterfacesEnum) ) #define ICorDebugComObjectValue_GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) \ ( (This)->lpVtbl -> GetCachedInterfacePointers(This,bIInspectableOnly,celt,pcEltFetched,ptrs) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugComObjectValue_INTERFACE_DEFINED__ */ #ifndef __ICorDebugObjectEnum_INTERFACE_DEFINED__ #define __ICorDebugObjectEnum_INTERFACE_DEFINED__ /* interface ICorDebugObjectEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB02-8A68-11d2-983C-0000F808342D") ICorDebugObjectEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugObjectEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugObjectEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugObjectEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugObjectEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugObjectEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugObjectEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugObjectEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugObjectEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CORDB_ADDRESS objects[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugObjectEnumVtbl; interface ICorDebugObjectEnum { CONST_VTBL struct ICorDebugObjectEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugObjectEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugObjectEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugObjectEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugObjectEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugObjectEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugObjectEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugObjectEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugObjectEnum_Next(This,celt,objects,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugObjectEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ #define __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ /* interface ICorDebugBreakpointEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBreakpointEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB03-8A68-11d2-983C-0000F808342D") ICorDebugBreakpointEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugBreakpointEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBreakpointEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBreakpointEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBreakpointEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugBreakpointEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugBreakpointEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugBreakpointEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugBreakpointEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugBreakpointEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugBreakpoint *breakpoints[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugBreakpointEnumVtbl; interface ICorDebugBreakpointEnum { CONST_VTBL struct ICorDebugBreakpointEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugBreakpointEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBreakpointEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBreakpointEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBreakpointEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugBreakpointEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugBreakpointEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugBreakpointEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugBreakpointEnum_Next(This,celt,breakpoints,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,breakpoints,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugBreakpointEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugStepperEnum_INTERFACE_DEFINED__ #define __ICorDebugStepperEnum_INTERFACE_DEFINED__ /* interface ICorDebugStepperEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugStepperEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB04-8A68-11d2-983C-0000F808342D") ICorDebugStepperEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugStepperEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugStepperEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugStepperEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugStepperEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugStepperEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugStepperEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugStepperEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugStepperEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugStepperEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugStepper *steppers[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugStepperEnumVtbl; interface ICorDebugStepperEnum { CONST_VTBL struct ICorDebugStepperEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugStepperEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugStepperEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugStepperEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugStepperEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugStepperEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugStepperEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugStepperEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugStepperEnum_Next(This,celt,steppers,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,steppers,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugStepperEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugProcessEnum_INTERFACE_DEFINED__ #define __ICorDebugProcessEnum_INTERFACE_DEFINED__ /* interface ICorDebugProcessEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcessEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB05-8A68-11d2-983C-0000F808342D") ICorDebugProcessEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcessEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcessEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcessEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcessEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugProcessEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugProcessEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugProcessEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugProcessEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugProcessEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugProcess *processes[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugProcessEnumVtbl; interface ICorDebugProcessEnum { CONST_VTBL struct ICorDebugProcessEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcessEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcessEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcessEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcessEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugProcessEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugProcessEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugProcessEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugProcessEnum_Next(This,celt,processes,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,processes,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcessEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugThreadEnum_INTERFACE_DEFINED__ #define __ICorDebugThreadEnum_INTERFACE_DEFINED__ /* interface ICorDebugThreadEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugThreadEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB06-8A68-11d2-983C-0000F808342D") ICorDebugThreadEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugThreadEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugThreadEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugThreadEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugThreadEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugThreadEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugThreadEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugThreadEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugThreadEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugThreadEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugThread *threads[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugThreadEnumVtbl; interface ICorDebugThreadEnum { CONST_VTBL struct ICorDebugThreadEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugThreadEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugThreadEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugThreadEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugThreadEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugThreadEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugThreadEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugThreadEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugThreadEnum_Next(This,celt,threads,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,threads,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugThreadEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugFrameEnum_INTERFACE_DEFINED__ #define __ICorDebugFrameEnum_INTERFACE_DEFINED__ /* interface ICorDebugFrameEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugFrameEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB07-8A68-11d2-983C-0000F808342D") ICorDebugFrameEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugFrameEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugFrameEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugFrameEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugFrameEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugFrameEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugFrameEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugFrameEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugFrameEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugFrameEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugFrame *frames[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugFrameEnumVtbl; interface ICorDebugFrameEnum { CONST_VTBL struct ICorDebugFrameEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugFrameEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugFrameEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugFrameEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugFrameEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugFrameEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugFrameEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugFrameEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugFrameEnum_Next(This,celt,frames,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,frames,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugFrameEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugChainEnum_INTERFACE_DEFINED__ #define __ICorDebugChainEnum_INTERFACE_DEFINED__ /* interface ICorDebugChainEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugChainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB08-8A68-11d2-983C-0000F808342D") ICorDebugChainEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugChainEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugChainEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugChainEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugChainEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugChainEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugChainEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugChainEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugChainEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugChainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugChain *chains[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugChainEnumVtbl; interface ICorDebugChainEnum { CONST_VTBL struct ICorDebugChainEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugChainEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugChainEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugChainEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugChainEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugChainEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugChainEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugChainEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugChainEnum_Next(This,celt,chains,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,chains,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugChainEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugModuleEnum_INTERFACE_DEFINED__ #define __ICorDebugModuleEnum_INTERFACE_DEFINED__ /* interface ICorDebugModuleEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugModuleEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB09-8A68-11d2-983C-0000F808342D") ICorDebugModuleEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugModuleEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugModuleEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugModuleEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugModuleEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugModuleEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugModuleEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugModuleEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugModuleEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugModuleEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugModule *modules[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugModuleEnumVtbl; interface ICorDebugModuleEnum { CONST_VTBL struct ICorDebugModuleEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugModuleEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugModuleEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugModuleEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugModuleEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugModuleEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugModuleEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugModuleEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugModuleEnum_Next(This,celt,modules,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,modules,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugModuleEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugValueEnum_INTERFACE_DEFINED__ #define __ICorDebugValueEnum_INTERFACE_DEFINED__ /* interface ICorDebugValueEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugValueEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC7BCB0A-8A68-11d2-983C-0000F808342D") ICorDebugValueEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugValue *values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugValueEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugValueEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugValueEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugValueEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugValueEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugValueEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugValueEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugValueEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugValueEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugValue *values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugValueEnumVtbl; interface ICorDebugValueEnum { CONST_VTBL struct ICorDebugValueEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugValueEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugValueEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugValueEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugValueEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugValueEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugValueEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugValueEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugValueEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugValueEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ #define __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ /* interface ICorDebugVariableHomeEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugVariableHomeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("e76b7a57-4f7a-4309-85a7-5d918c3deaf7") ICorDebugVariableHomeEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugVariableHomeEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugVariableHomeEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugVariableHomeEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugVariableHomeEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugVariableHomeEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugVariableHomeEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugVariableHomeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugVariableHomeEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugVariableHomeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugVariableHome *homes[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugVariableHomeEnumVtbl; interface ICorDebugVariableHomeEnum { CONST_VTBL struct ICorDebugVariableHomeEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugVariableHomeEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugVariableHomeEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugVariableHomeEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugVariableHomeEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugVariableHomeEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugVariableHomeEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugVariableHomeEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugVariableHomeEnum_Next(This,celt,homes,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,homes,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugVariableHomeEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugCodeEnum_INTERFACE_DEFINED__ #define __ICorDebugCodeEnum_INTERFACE_DEFINED__ /* interface ICorDebugCodeEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugCodeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("55E96461-9645-45e4-A2FF-0367877ABCDE") ICorDebugCodeEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugCode *values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugCodeEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugCodeEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugCodeEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugCodeEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugCodeEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugCodeEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugCodeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugCodeEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugCodeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugCode *values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugCodeEnumVtbl; interface ICorDebugCodeEnum { CONST_VTBL struct ICorDebugCodeEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugCodeEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugCodeEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugCodeEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugCodeEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugCodeEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugCodeEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugCodeEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugCodeEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugCodeEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugTypeEnum_INTERFACE_DEFINED__ #define __ICorDebugTypeEnum_INTERFACE_DEFINED__ /* interface ICorDebugTypeEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugTypeEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("10F27499-9DF2-43ce-8333-A321D7C99CB4") ICorDebugTypeEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugType *values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugTypeEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugTypeEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugTypeEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugTypeEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugTypeEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugTypeEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugTypeEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugTypeEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugTypeEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugType *values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugTypeEnumVtbl; interface ICorDebugTypeEnum { CONST_VTBL struct ICorDebugTypeEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugTypeEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugTypeEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugTypeEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugTypeEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugTypeEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugTypeEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugTypeEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugTypeEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugTypeEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugType_INTERFACE_DEFINED__ #define __ICorDebugType_INTERFACE_DEFINED__ /* interface ICorDebugType */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugType; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D613F0BB-ACE1-4c19-BD72-E4C08D5DA7F5") ICorDebugType : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ CorElementType *ty) = 0; virtual HRESULT STDMETHODCALLTYPE GetClass( /* [out] */ ICorDebugClass **ppClass) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateTypeParameters( /* [out] */ ICorDebugTypeEnum **ppTyParEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetFirstTypeParameter( /* [out] */ ICorDebugType **value) = 0; virtual HRESULT STDMETHODCALLTYPE GetBase( /* [out] */ ICorDebugType **pBase) = 0; virtual HRESULT STDMETHODCALLTYPE GetStaticFieldValue( /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetRank( /* [out] */ ULONG32 *pnRank) = 0; }; #else /* C style interface */ typedef struct ICorDebugTypeVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugType * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugType * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugType * This); HRESULT ( STDMETHODCALLTYPE *GetType )( ICorDebugType * This, /* [out] */ CorElementType *ty); HRESULT ( STDMETHODCALLTYPE *GetClass )( ICorDebugType * This, /* [out] */ ICorDebugClass **ppClass); HRESULT ( STDMETHODCALLTYPE *EnumerateTypeParameters )( ICorDebugType * This, /* [out] */ ICorDebugTypeEnum **ppTyParEnum); HRESULT ( STDMETHODCALLTYPE *GetFirstTypeParameter )( ICorDebugType * This, /* [out] */ ICorDebugType **value); HRESULT ( STDMETHODCALLTYPE *GetBase )( ICorDebugType * This, /* [out] */ ICorDebugType **pBase); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldValue )( ICorDebugType * This, /* [in] */ mdFieldDef fieldDef, /* [in] */ ICorDebugFrame *pFrame, /* [out] */ ICorDebugValue **ppValue); HRESULT ( STDMETHODCALLTYPE *GetRank )( ICorDebugType * This, /* [out] */ ULONG32 *pnRank); END_INTERFACE } ICorDebugTypeVtbl; interface ICorDebugType { CONST_VTBL struct ICorDebugTypeVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugType_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugType_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugType_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugType_GetType(This,ty) \ ( (This)->lpVtbl -> GetType(This,ty) ) #define ICorDebugType_GetClass(This,ppClass) \ ( (This)->lpVtbl -> GetClass(This,ppClass) ) #define ICorDebugType_EnumerateTypeParameters(This,ppTyParEnum) \ ( (This)->lpVtbl -> EnumerateTypeParameters(This,ppTyParEnum) ) #define ICorDebugType_GetFirstTypeParameter(This,value) \ ( (This)->lpVtbl -> GetFirstTypeParameter(This,value) ) #define ICorDebugType_GetBase(This,pBase) \ ( (This)->lpVtbl -> GetBase(This,pBase) ) #define ICorDebugType_GetStaticFieldValue(This,fieldDef,pFrame,ppValue) \ ( (This)->lpVtbl -> GetStaticFieldValue(This,fieldDef,pFrame,ppValue) ) #define ICorDebugType_GetRank(This,pnRank) \ ( (This)->lpVtbl -> GetRank(This,pnRank) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugType_INTERFACE_DEFINED__ */ #ifndef __ICorDebugType2_INTERFACE_DEFINED__ #define __ICorDebugType2_INTERFACE_DEFINED__ /* interface ICorDebugType2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugType2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("e6e91d79-693d-48bc-b417-8284b4f10fb5") ICorDebugType2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetTypeID( /* [out] */ COR_TYPEID *id) = 0; }; #else /* C style interface */ typedef struct ICorDebugType2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugType2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugType2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugType2 * This); HRESULT ( STDMETHODCALLTYPE *GetTypeID )( ICorDebugType2 * This, /* [out] */ COR_TYPEID *id); END_INTERFACE } ICorDebugType2Vtbl; interface ICorDebugType2 { CONST_VTBL struct ICorDebugType2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugType2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugType2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugType2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugType2_GetTypeID(This,id) \ ( (This)->lpVtbl -> GetTypeID(This,id) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugType2_INTERFACE_DEFINED__ */ #ifndef __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ #define __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ /* interface ICorDebugErrorInfoEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugErrorInfoEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F0E18809-72B5-11d2-976F-00A0C9B4D50C") ICorDebugErrorInfoEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugErrorInfoEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugErrorInfoEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugErrorInfoEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugErrorInfoEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugErrorInfoEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugErrorInfoEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugErrorInfoEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugErrorInfoEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugErrorInfoEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugEditAndContinueErrorInfo *errors[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugErrorInfoEnumVtbl; interface ICorDebugErrorInfoEnum { CONST_VTBL struct ICorDebugErrorInfoEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugErrorInfoEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugErrorInfoEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugErrorInfoEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugErrorInfoEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugErrorInfoEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugErrorInfoEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugErrorInfoEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugErrorInfoEnum_Next(This,celt,errors,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,errors,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugErrorInfoEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ #define __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ /* interface ICorDebugAppDomainEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAppDomainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("63ca1b24-4359-4883-bd57-13f815f58744") ICorDebugAppDomainEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugAppDomainEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAppDomainEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAppDomainEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAppDomainEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugAppDomainEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugAppDomainEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugAppDomainEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugAppDomainEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugAppDomainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAppDomain *values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugAppDomainEnumVtbl; interface ICorDebugAppDomainEnum { CONST_VTBL struct ICorDebugAppDomainEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAppDomainEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAppDomainEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAppDomainEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAppDomainEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugAppDomainEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugAppDomainEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugAppDomainEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugAppDomainEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAppDomainEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ #define __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ /* interface ICorDebugAssemblyEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugAssemblyEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("4a2a1ec9-85ec-4bfb-9f15-a89fdfe0fe83") ICorDebugAssemblyEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugAssemblyEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugAssemblyEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugAssemblyEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugAssemblyEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugAssemblyEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugAssemblyEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugAssemblyEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugAssemblyEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugAssemblyEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorDebugAssembly *values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugAssemblyEnumVtbl; interface ICorDebugAssemblyEnum { CONST_VTBL struct ICorDebugAssemblyEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugAssemblyEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugAssemblyEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugAssemblyEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugAssemblyEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugAssemblyEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugAssemblyEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugAssemblyEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugAssemblyEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugAssemblyEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ #define __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ /* interface ICorDebugBlockingObjectEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugBlockingObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("976A6278-134A-4a81-81A3-8F277943F4C3") ICorDebugBlockingObjectEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugBlockingObjectEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugBlockingObjectEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugBlockingObjectEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugBlockingObjectEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugBlockingObjectEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugBlockingObjectEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugBlockingObjectEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugBlockingObjectEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugBlockingObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugBlockingObject values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugBlockingObjectEnumVtbl; interface ICorDebugBlockingObjectEnum { CONST_VTBL struct ICorDebugBlockingObjectEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugBlockingObjectEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugBlockingObjectEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugBlockingObjectEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugBlockingObjectEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugBlockingObjectEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugBlockingObjectEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugBlockingObjectEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugBlockingObjectEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugBlockingObjectEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0130 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0130_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0130_v0_0_s_ifspec; #ifndef __ICorDebugMDA_INTERFACE_DEFINED__ #define __ICorDebugMDA_INTERFACE_DEFINED__ /* interface ICorDebugMDA */ /* [unique][uuid][local][object] */ typedef enum CorDebugMDAFlags { MDA_FLAG_SLIP = 0x2 } CorDebugMDAFlags; EXTERN_C const IID IID_ICorDebugMDA; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC726F2F-1DB7-459b-B0EC-05F01D841B42") ICorDebugMDA : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetDescription( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetXML( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [in] */ CorDebugMDAFlags *pFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetOSThreadId( /* [out] */ DWORD *pOsTid) = 0; }; #else /* C style interface */ typedef struct ICorDebugMDAVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugMDA * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugMDA * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugMDA * This); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetDescription )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetXML )( ICorDebugMDA * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetFlags )( ICorDebugMDA * This, /* [in] */ CorDebugMDAFlags *pFlags); HRESULT ( STDMETHODCALLTYPE *GetOSThreadId )( ICorDebugMDA * This, /* [out] */ DWORD *pOsTid); END_INTERFACE } ICorDebugMDAVtbl; interface ICorDebugMDA { CONST_VTBL struct ICorDebugMDAVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugMDA_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugMDA_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugMDA_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugMDA_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetDescription(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetDescription(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetXML(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetXML(This,cchName,pcchName,szName) ) #define ICorDebugMDA_GetFlags(This,pFlags) \ ( (This)->lpVtbl -> GetFlags(This,pFlags) ) #define ICorDebugMDA_GetOSThreadId(This,pOsTid) \ ( (This)->lpVtbl -> GetOSThreadId(This,pOsTid) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugMDA_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0131 */ /* [local] */ #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0131_v0_0_s_ifspec; #ifndef __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ #define __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ /* interface ICorDebugEditAndContinueErrorInfo */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEditAndContinueErrorInfo; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("8D600D41-F4F6-4cb3-B7EC-7BD164944036") ICorDebugEditAndContinueErrorInfo : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ ICorDebugModule **ppModule) = 0; virtual HRESULT STDMETHODCALLTYPE GetToken( /* [out] */ mdToken *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE GetErrorCode( /* [out] */ HRESULT *pHr) = 0; virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]) = 0; }; #else /* C style interface */ typedef struct ICorDebugEditAndContinueErrorInfoVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEditAndContinueErrorInfo * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEditAndContinueErrorInfo * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEditAndContinueErrorInfo * This); HRESULT ( STDMETHODCALLTYPE *GetModule )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ ICorDebugModule **ppModule); HRESULT ( STDMETHODCALLTYPE *GetToken )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetErrorCode )( ICorDebugEditAndContinueErrorInfo * This, /* [out] */ HRESULT *pHr); HRESULT ( STDMETHODCALLTYPE *GetString )( ICorDebugEditAndContinueErrorInfo * This, /* [in] */ ULONG32 cchString, /* [out] */ ULONG32 *pcchString, /* [length_is][size_is][out] */ WCHAR szString[ ]); END_INTERFACE } ICorDebugEditAndContinueErrorInfoVtbl; interface ICorDebugEditAndContinueErrorInfo { CONST_VTBL struct ICorDebugEditAndContinueErrorInfoVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugEditAndContinueErrorInfo_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEditAndContinueErrorInfo_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEditAndContinueErrorInfo_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEditAndContinueErrorInfo_GetModule(This,ppModule) \ ( (This)->lpVtbl -> GetModule(This,ppModule) ) #define ICorDebugEditAndContinueErrorInfo_GetToken(This,pToken) \ ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ICorDebugEditAndContinueErrorInfo_GetErrorCode(This,pHr) \ ( (This)->lpVtbl -> GetErrorCode(This,pHr) ) #define ICorDebugEditAndContinueErrorInfo_GetString(This,cchString,pcchString,szString) \ ( (This)->lpVtbl -> GetString(This,cchString,pcchString,szString) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugEditAndContinueErrorInfo_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_cordebug_0000_0132 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0132_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_cordebug_0000_0132_v0_0_s_ifspec; #ifndef __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ #define __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ /* interface ICorDebugEditAndContinueSnapshot */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugEditAndContinueSnapshot; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("6DC3FA01-D7CB-11d2-8A95-0080C792E5D8") ICorDebugEditAndContinueSnapshot : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE CopyMetaData( /* [in] */ IStream *pIStream, /* [out] */ GUID *pMvid) = 0; virtual HRESULT STDMETHODCALLTYPE GetMvid( /* [out] */ GUID *pMvid) = 0; virtual HRESULT STDMETHODCALLTYPE GetRoDataRVA( /* [out] */ ULONG32 *pRoDataRVA) = 0; virtual HRESULT STDMETHODCALLTYPE GetRwDataRVA( /* [out] */ ULONG32 *pRwDataRVA) = 0; virtual HRESULT STDMETHODCALLTYPE SetPEBytes( /* [in] */ IStream *pIStream) = 0; virtual HRESULT STDMETHODCALLTYPE SetILMap( /* [in] */ mdToken mdFunction, /* [in] */ ULONG cMapSize, /* [size_is][in] */ COR_IL_MAP map[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetPESymbolBytes( /* [in] */ IStream *pIStream) = 0; }; #else /* C style interface */ typedef struct ICorDebugEditAndContinueSnapshotVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugEditAndContinueSnapshot * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugEditAndContinueSnapshot * This); HRESULT ( STDMETHODCALLTYPE *CopyMetaData )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream, /* [out] */ GUID *pMvid); HRESULT ( STDMETHODCALLTYPE *GetMvid )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ GUID *pMvid); HRESULT ( STDMETHODCALLTYPE *GetRoDataRVA )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ ULONG32 *pRoDataRVA); HRESULT ( STDMETHODCALLTYPE *GetRwDataRVA )( ICorDebugEditAndContinueSnapshot * This, /* [out] */ ULONG32 *pRwDataRVA); HRESULT ( STDMETHODCALLTYPE *SetPEBytes )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *SetILMap )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ mdToken mdFunction, /* [in] */ ULONG cMapSize, /* [size_is][in] */ COR_IL_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *SetPESymbolBytes )( ICorDebugEditAndContinueSnapshot * This, /* [in] */ IStream *pIStream); END_INTERFACE } ICorDebugEditAndContinueSnapshotVtbl; interface ICorDebugEditAndContinueSnapshot { CONST_VTBL struct ICorDebugEditAndContinueSnapshotVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugEditAndContinueSnapshot_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugEditAndContinueSnapshot_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugEditAndContinueSnapshot_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugEditAndContinueSnapshot_CopyMetaData(This,pIStream,pMvid) \ ( (This)->lpVtbl -> CopyMetaData(This,pIStream,pMvid) ) #define ICorDebugEditAndContinueSnapshot_GetMvid(This,pMvid) \ ( (This)->lpVtbl -> GetMvid(This,pMvid) ) #define ICorDebugEditAndContinueSnapshot_GetRoDataRVA(This,pRoDataRVA) \ ( (This)->lpVtbl -> GetRoDataRVA(This,pRoDataRVA) ) #define ICorDebugEditAndContinueSnapshot_GetRwDataRVA(This,pRwDataRVA) \ ( (This)->lpVtbl -> GetRwDataRVA(This,pRwDataRVA) ) #define ICorDebugEditAndContinueSnapshot_SetPEBytes(This,pIStream) \ ( (This)->lpVtbl -> SetPEBytes(This,pIStream) ) #define ICorDebugEditAndContinueSnapshot_SetILMap(This,mdFunction,cMapSize,map) \ ( (This)->lpVtbl -> SetILMap(This,mdFunction,cMapSize,map) ) #define ICorDebugEditAndContinueSnapshot_SetPESymbolBytes(This,pIStream) \ ( (This)->lpVtbl -> SetPESymbolBytes(This,pIStream) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugEditAndContinueSnapshot_INTERFACE_DEFINED__ */ #ifndef __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ #define __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ /* interface ICorDebugExceptionObjectCallStackEnum */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionObjectCallStackEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("ED775530-4DC4-41F7-86D0-9E2DEF7DFC66") ICorDebugExceptionObjectCallStackEnum : public ICorDebugEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorDebugExceptionObjectCallStackEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionObjectCallStackEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionObjectCallStackEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorDebugExceptionObjectCallStackEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorDebugExceptionObjectCallStackEnum * This, /* [out] */ ICorDebugEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorDebugExceptionObjectCallStackEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorDebugExceptionObjectCallStackEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ CorDebugExceptionObjectStackFrame values[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorDebugExceptionObjectCallStackEnumVtbl; interface ICorDebugExceptionObjectCallStackEnum { CONST_VTBL struct ICorDebugExceptionObjectCallStackEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugExceptionObjectCallStackEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionObjectCallStackEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionObjectCallStackEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionObjectCallStackEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorDebugExceptionObjectCallStackEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorDebugExceptionObjectCallStackEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorDebugExceptionObjectCallStackEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorDebugExceptionObjectCallStackEnum_Next(This,celt,values,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,values,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugExceptionObjectCallStackEnum_INTERFACE_DEFINED__ */ #ifndef __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ #define __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ /* interface ICorDebugExceptionObjectValue */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugExceptionObjectValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AE4CA65D-59DD-42A2-83A5-57E8A08D8719") ICorDebugExceptionObjectValue : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumerateExceptionCallStack( /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum) = 0; }; #else /* C style interface */ typedef struct ICorDebugExceptionObjectValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugExceptionObjectValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugExceptionObjectValue * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugExceptionObjectValue * This); HRESULT ( STDMETHODCALLTYPE *EnumerateExceptionCallStack )( ICorDebugExceptionObjectValue * This, /* [out] */ ICorDebugExceptionObjectCallStackEnum **ppCallStackEnum); END_INTERFACE } ICorDebugExceptionObjectValueVtbl; interface ICorDebugExceptionObjectValue { CONST_VTBL struct ICorDebugExceptionObjectValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugExceptionObjectValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugExceptionObjectValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugExceptionObjectValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugExceptionObjectValue_EnumerateExceptionCallStack(This,ppCallStackEnum) \ ( (This)->lpVtbl -> EnumerateExceptionCallStack(This,ppCallStackEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugExceptionObjectValue_INTERFACE_DEFINED__ */ #ifndef __CORDBLib_LIBRARY_DEFINED__ #define __CORDBLib_LIBRARY_DEFINED__ /* library CORDBLib */ /* [helpstring][version][uuid] */ EXTERN_C const IID LIBID_CORDBLib; EXTERN_C const CLSID CLSID_CorDebug; #ifdef __cplusplus class DECLSPEC_UUID("6fef44d0-39e7-4c77-be8e-c9f8cf988630") CorDebug; #endif EXTERN_C const CLSID CLSID_EmbeddedCLRCorDebug; #ifdef __cplusplus class DECLSPEC_UUID("211f1254-bc7e-4af5-b9aa-067308d83dd1") EmbeddedCLRCorDebug; #endif #endif /* __CORDBLib_LIBRARY_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/corerror.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifndef __COMMON_LANGUAGE_RUNTIME_HRESULTS__ #define __COMMON_LANGUAGE_RUNTIME_HRESULTS__ #include // //This file is AutoGenerated -- Do Not Edit by hand!!! // //Add new HRESULTS along with their corresponding error messages to //corerror.xml // #ifndef FACILITY_URT #define FACILITY_URT 0x13 #endif #ifndef EMAKEHR #define SMAKEHR(val) MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_URT, val) #define EMAKEHR(val) MAKE_HRESULT(SEVERITY_ERROR, FACILITY_URT, val) #endif #define CLDB_S_TRUNCATION SMAKEHR(0x1106) #define META_S_DUPLICATE SMAKEHR(0x1197) #define CORDBG_S_BAD_START_SEQUENCE_POINT SMAKEHR(0x130b) #define CORDBG_S_BAD_END_SEQUENCE_POINT SMAKEHR(0x130c) #define CORDBG_S_FUNC_EVAL_HAS_NO_RESULT SMAKEHR(0x1316) #define CORDBG_S_VALUE_POINTS_TO_VOID SMAKEHR(0x1317) #define CORDBG_S_FUNC_EVAL_ABORTED SMAKEHR(0x1319) #define CORDBG_S_AT_END_OF_STACK SMAKEHR(0x1324) #define CORDBG_S_NOT_ALL_BITS_SET SMAKEHR(0x1c13) #define COR_E_TYPEUNLOADED EMAKEHR(0x1013) #define COR_E_APPDOMAINUNLOADED EMAKEHR(0x1014) #define COR_E_CANNOTUNLOADAPPDOMAIN EMAKEHR(0x1015) #define MSEE_E_ASSEMBLYLOADINPROGRESS EMAKEHR(0x1016) #define COR_E_ASSEMBLYEXPECTED EMAKEHR(0x1018) #define COR_E_NEWER_RUNTIME EMAKEHR(0x101b) #define COR_E_MULTIMODULEASSEMBLIESDIALLOWED EMAKEHR(0x101e) #define HOST_E_INVALIDOPERATION EMAKEHR(0x1022) #define HOST_E_CLRNOTAVAILABLE EMAKEHR(0x1023) #define FUSION_E_REF_DEF_MISMATCH EMAKEHR(0x1040) #define FUSION_E_PRIVATE_ASM_DISALLOWED EMAKEHR(0x1044) #define FUSION_E_INVALID_NAME EMAKEHR(0x1047) #define FUSION_E_CACHEFILE_FAILED EMAKEHR(0x1052) #define FUSION_E_APP_DOMAIN_LOCKED EMAKEHR(0x1053) #define COR_E_LOADING_REFERENCE_ASSEMBLY EMAKEHR(0x1058) #define COR_E_AMBIGUOUSIMPLEMENTATION EMAKEHR(0x106a) #define CLDB_E_FILE_BADREAD EMAKEHR(0x1100) #define CLDB_E_FILE_BADWRITE EMAKEHR(0x1101) #define CLDB_E_FILE_OLDVER EMAKEHR(0x1107) #define CLDB_E_SMDUPLICATE EMAKEHR(0x110a) #define CLDB_E_NO_DATA EMAKEHR(0x110b) #define CLDB_E_INCOMPATIBLE EMAKEHR(0x110d) #define CLDB_E_FILE_CORRUPT EMAKEHR(0x110e) #define CLDB_E_BADUPDATEMODE EMAKEHR(0x1110) #define CLDB_E_INDEX_NOTFOUND EMAKEHR(0x1124) #define CLDB_E_RECORD_NOTFOUND EMAKEHR(0x1130) #define CLDB_E_RECORD_OUTOFORDER EMAKEHR(0x1135) #define CLDB_E_TOO_BIG EMAKEHR(0x1154) #define META_E_INVALID_TOKEN_TYPE EMAKEHR(0x115f) #define TLBX_E_LIBNOTREGISTERED EMAKEHR(0x1165) #define META_E_BADMETADATA EMAKEHR(0x118a) #define META_E_BAD_SIGNATURE EMAKEHR(0x1192) #define META_E_BAD_INPUT_PARAMETER EMAKEHR(0x1193) #define META_E_CANNOTRESOLVETYPEREF EMAKEHR(0x1196) #define META_E_STRINGSPACE_FULL EMAKEHR(0x1198) #define META_E_HAS_UNMARKALL EMAKEHR(0x119a) #define META_E_MUST_CALL_UNMARKALL EMAKEHR(0x119b) #define META_E_CA_INVALID_TARGET EMAKEHR(0x11c0) #define META_E_CA_INVALID_VALUE EMAKEHR(0x11c1) #define META_E_CA_INVALID_BLOB EMAKEHR(0x11c2) #define META_E_CA_REPEATED_ARG EMAKEHR(0x11c3) #define META_E_CA_UNKNOWN_ARGUMENT EMAKEHR(0x11c4) #define META_E_CA_UNEXPECTED_TYPE EMAKEHR(0x11c7) #define META_E_CA_INVALID_ARGTYPE EMAKEHR(0x11c8) #define META_E_CA_INVALID_ARG_FOR_TYPE EMAKEHR(0x11c9) #define META_E_CA_INVALID_UUID EMAKEHR(0x11ca) #define META_E_CA_INVALID_MARSHALAS_FIELDS EMAKEHR(0x11cb) #define META_E_CA_NT_FIELDONLY EMAKEHR(0x11cc) #define META_E_CA_NEGATIVE_PARAMINDEX EMAKEHR(0x11cd) #define META_E_CA_NEGATIVE_CONSTSIZE EMAKEHR(0x11cf) #define META_E_CA_FIXEDSTR_SIZE_REQUIRED EMAKEHR(0x11d0) #define META_E_CA_CUSTMARSH_TYPE_REQUIRED EMAKEHR(0x11d1) #define META_E_NOT_IN_ENC_MODE EMAKEHR(0x11d4) #define META_E_CA_BAD_FRIENDS_ARGS EMAKEHR(0x11e5) #define META_E_CA_FRIENDS_SN_REQUIRED EMAKEHR(0x11e6) #define VLDTR_E_RID_OUTOFRANGE EMAKEHR(0x1203) #define VLDTR_E_STRING_INVALID EMAKEHR(0x1206) #define VLDTR_E_GUID_INVALID EMAKEHR(0x1207) #define VLDTR_E_BLOB_INVALID EMAKEHR(0x1208) #define VLDTR_E_MR_BADCALLINGCONV EMAKEHR(0x1224) #define VLDTR_E_SIGNULL EMAKEHR(0x1237) #define VLDTR_E_MD_BADCALLINGCONV EMAKEHR(0x1239) #define VLDTR_E_MD_THISSTATIC EMAKEHR(0x123a) #define VLDTR_E_MD_NOTTHISNOTSTATIC EMAKEHR(0x123b) #define VLDTR_E_MD_NOARGCNT EMAKEHR(0x123c) #define VLDTR_E_SIG_MISSELTYPE EMAKEHR(0x123d) #define VLDTR_E_SIG_MISSTKN EMAKEHR(0x123e) #define VLDTR_E_SIG_TKNBAD EMAKEHR(0x123f) #define VLDTR_E_SIG_MISSFPTR EMAKEHR(0x1240) #define VLDTR_E_SIG_MISSFPTRARGCNT EMAKEHR(0x1241) #define VLDTR_E_SIG_MISSRANK EMAKEHR(0x1242) #define VLDTR_E_SIG_MISSNSIZE EMAKEHR(0x1243) #define VLDTR_E_SIG_MISSSIZE EMAKEHR(0x1244) #define VLDTR_E_SIG_MISSNLBND EMAKEHR(0x1245) #define VLDTR_E_SIG_MISSLBND EMAKEHR(0x1246) #define VLDTR_E_SIG_BADELTYPE EMAKEHR(0x1247) #define VLDTR_E_TD_ENCLNOTNESTED EMAKEHR(0x1256) #define VLDTR_E_FMD_PINVOKENOTSTATIC EMAKEHR(0x1277) #define VLDTR_E_SIG_SENTINMETHODDEF EMAKEHR(0x12df) #define VLDTR_E_SIG_SENTMUSTVARARG EMAKEHR(0x12e0) #define VLDTR_E_SIG_MULTSENTINELS EMAKEHR(0x12e1) #define VLDTR_E_SIG_MISSARG EMAKEHR(0x12e3) #define VLDTR_E_SIG_BYREFINFIELD EMAKEHR(0x12e4) #define CORDBG_E_UNRECOVERABLE_ERROR EMAKEHR(0x1300) #define CORDBG_E_PROCESS_TERMINATED EMAKEHR(0x1301) #define CORDBG_E_PROCESS_NOT_SYNCHRONIZED EMAKEHR(0x1302) #define CORDBG_E_CLASS_NOT_LOADED EMAKEHR(0x1303) #define CORDBG_E_IL_VAR_NOT_AVAILABLE EMAKEHR(0x1304) #define CORDBG_E_BAD_REFERENCE_VALUE EMAKEHR(0x1305) #define CORDBG_E_FIELD_NOT_AVAILABLE EMAKEHR(0x1306) #define CORDBG_E_NON_NATIVE_FRAME EMAKEHR(0x1307) #define CORDBG_E_CODE_NOT_AVAILABLE EMAKEHR(0x1309) #define CORDBG_E_FUNCTION_NOT_IL EMAKEHR(0x130a) #define CORDBG_E_CANT_SET_IP_INTO_FINALLY EMAKEHR(0x130e) #define CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY EMAKEHR(0x130f) #define CORDBG_E_CANT_SET_IP_INTO_CATCH EMAKEHR(0x1310) #define CORDBG_E_SET_IP_NOT_ALLOWED_ON_NONLEAF_FRAME EMAKEHR(0x1311) #define CORDBG_E_SET_IP_IMPOSSIBLE EMAKEHR(0x1312) #define CORDBG_E_FUNC_EVAL_BAD_START_POINT EMAKEHR(0x1313) #define CORDBG_E_INVALID_OBJECT EMAKEHR(0x1314) #define CORDBG_E_FUNC_EVAL_NOT_COMPLETE EMAKEHR(0x1315) #define CORDBG_E_STATIC_VAR_NOT_AVAILABLE EMAKEHR(0x131a) #define CORDBG_E_CANT_SETIP_INTO_OR_OUT_OF_FILTER EMAKEHR(0x131c) #define CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE EMAKEHR(0x131d) #define CORDBG_E_CANT_SET_IP_OUT_OF_FINALLY_ON_WIN64 EMAKEHR(0x131e) #define CORDBG_E_CANT_SET_IP_OUT_OF_CATCH_ON_WIN64 EMAKEHR(0x131f) #define CORDBG_E_CANT_SET_TO_JMC EMAKEHR(0x1323) #define CORDBG_E_NO_CONTEXT_FOR_INTERNAL_FRAME EMAKEHR(0x1325) #define CORDBG_E_NOT_CHILD_FRAME EMAKEHR(0x1326) #define CORDBG_E_NON_MATCHING_CONTEXT EMAKEHR(0x1327) #define CORDBG_E_PAST_END_OF_STACK EMAKEHR(0x1328) #define CORDBG_E_FUNC_EVAL_CANNOT_UPDATE_REGISTER_IN_NONLEAF_FRAME EMAKEHR(0x1329) #define CORDBG_E_BAD_THREAD_STATE EMAKEHR(0x132d) #define CORDBG_E_DEBUGGER_ALREADY_ATTACHED EMAKEHR(0x132e) #define CORDBG_E_SUPERFLOUS_CONTINUE EMAKEHR(0x132f) #define CORDBG_E_SET_VALUE_NOT_ALLOWED_ON_NONLEAF_FRAME EMAKEHR(0x1330) #define CORDBG_E_ENC_MODULE_NOT_ENC_ENABLED EMAKEHR(0x1332) #define CORDBG_E_SET_IP_NOT_ALLOWED_ON_EXCEPTION EMAKEHR(0x1333) #define CORDBG_E_VARIABLE_IS_ACTUALLY_LITERAL EMAKEHR(0x1334) #define CORDBG_E_PROCESS_DETACHED EMAKEHR(0x1335) #define CORDBG_E_ENC_CANT_ADD_FIELD_TO_VALUE_OR_LAYOUT_CLASS EMAKEHR(0x1338) #define CORDBG_E_FIELD_NOT_STATIC EMAKEHR(0x133b) #define CORDBG_E_FIELD_NOT_INSTANCE EMAKEHR(0x133c) #define CORDBG_E_ENC_JIT_CANT_UPDATE EMAKEHR(0x133f) #define CORDBG_E_ENC_INTERNAL_ERROR EMAKEHR(0x1341) #define CORDBG_E_ENC_HANGING_FIELD EMAKEHR(0x1342) #define CORDBG_E_MODULE_NOT_LOADED EMAKEHR(0x1343) #define CORDBG_E_UNABLE_TO_SET_BREAKPOINT EMAKEHR(0x1345) #define CORDBG_E_DEBUGGING_NOT_POSSIBLE EMAKEHR(0x1346) #define CORDBG_E_KERNEL_DEBUGGER_ENABLED EMAKEHR(0x1347) #define CORDBG_E_KERNEL_DEBUGGER_PRESENT EMAKEHR(0x1348) #define CORDBG_E_INCOMPATIBLE_PROTOCOL EMAKEHR(0x134b) #define CORDBG_E_TOO_MANY_PROCESSES EMAKEHR(0x134c) #define CORDBG_E_INTEROP_NOT_SUPPORTED EMAKEHR(0x134d) #define CORDBG_E_NO_REMAP_BREAKPIONT EMAKEHR(0x134e) #define CORDBG_E_OBJECT_NEUTERED EMAKEHR(0x134f) #define CORPROF_E_FUNCTION_NOT_COMPILED EMAKEHR(0x1350) #define CORPROF_E_DATAINCOMPLETE EMAKEHR(0x1351) #define CORPROF_E_FUNCTION_NOT_IL EMAKEHR(0x1354) #define CORPROF_E_NOT_MANAGED_THREAD EMAKEHR(0x1355) #define CORPROF_E_CALL_ONLY_FROM_INIT EMAKEHR(0x1356) #define CORPROF_E_NOT_YET_AVAILABLE EMAKEHR(0x135b) #define CORPROF_E_TYPE_IS_PARAMETERIZED EMAKEHR(0x135c) #define CORPROF_E_FUNCTION_IS_PARAMETERIZED EMAKEHR(0x135d) #define CORPROF_E_STACKSNAPSHOT_INVALID_TGT_THREAD EMAKEHR(0x135e) #define CORPROF_E_STACKSNAPSHOT_UNMANAGED_CTX EMAKEHR(0x135f) #define CORPROF_E_STACKSNAPSHOT_UNSAFE EMAKEHR(0x1360) #define CORPROF_E_STACKSNAPSHOT_ABORTED EMAKEHR(0x1361) #define CORPROF_E_LITERALS_HAVE_NO_ADDRESS EMAKEHR(0x1362) #define CORPROF_E_UNSUPPORTED_CALL_SEQUENCE EMAKEHR(0x1363) #define CORPROF_E_ASYNCHRONOUS_UNSAFE EMAKEHR(0x1364) #define CORPROF_E_CLASSID_IS_ARRAY EMAKEHR(0x1365) #define CORPROF_E_CLASSID_IS_COMPOSITE EMAKEHR(0x1366) #define CORPROF_E_PROFILER_DETACHING EMAKEHR(0x1367) #define CORPROF_E_PROFILER_NOT_ATTACHABLE EMAKEHR(0x1368) #define CORPROF_E_UNRECOGNIZED_PIPE_MSG_FORMAT EMAKEHR(0x1369) #define CORPROF_E_PROFILER_ALREADY_ACTIVE EMAKEHR(0x136a) #define CORPROF_E_PROFILEE_INCOMPATIBLE_WITH_TRIGGER EMAKEHR(0x136b) #define CORPROF_E_IPC_FAILED EMAKEHR(0x136c) #define CORPROF_E_PROFILEE_PROCESS_NOT_FOUND EMAKEHR(0x136d) #define CORPROF_E_CALLBACK3_REQUIRED EMAKEHR(0x136e) #define CORPROF_E_UNSUPPORTED_FOR_ATTACHING_PROFILER EMAKEHR(0x136f) #define CORPROF_E_IRREVERSIBLE_INSTRUMENTATION_PRESENT EMAKEHR(0x1370) #define CORPROF_E_RUNTIME_UNINITIALIZED EMAKEHR(0x1371) #define CORPROF_E_IMMUTABLE_FLAGS_SET EMAKEHR(0x1372) #define CORPROF_E_PROFILER_NOT_YET_INITIALIZED EMAKEHR(0x1373) #define CORPROF_E_INCONSISTENT_WITH_FLAGS EMAKEHR(0x1374) #define CORPROF_E_PROFILER_CANCEL_ACTIVATION EMAKEHR(0x1375) #define CORPROF_E_CONCURRENT_GC_NOT_PROFILABLE EMAKEHR(0x1376) #define CORPROF_E_DEBUGGING_DISABLED EMAKEHR(0x1378) #define CORPROF_E_TIMEOUT_WAITING_FOR_CONCURRENT_GC EMAKEHR(0x1379) #define CORPROF_E_MODULE_IS_DYNAMIC EMAKEHR(0x137a) #define CORPROF_E_CALLBACK4_REQUIRED EMAKEHR(0x137b) #define CORPROF_E_REJIT_NOT_ENABLED EMAKEHR(0x137c) #define CORPROF_E_FUNCTION_IS_COLLECTIBLE EMAKEHR(0x137e) #define CORPROF_E_CALLBACK6_REQUIRED EMAKEHR(0x1380) #define CORPROF_E_CALLBACK7_REQUIRED EMAKEHR(0x1382) #define CORPROF_E_REJIT_INLINING_DISABLED EMAKEHR(0x1383) #define CORDIAGIPC_E_BAD_ENCODING EMAKEHR(0x1384) #define CORDIAGIPC_E_UNKNOWN_COMMAND EMAKEHR(0x1385) #define CORDIAGIPC_E_UNKNOWN_MAGIC EMAKEHR(0x1386) #define CORDIAGIPC_E_UNKNOWN_ERROR EMAKEHR(0x1387) #define CORPROF_E_SUSPENSION_IN_PROGRESS EMAKEHR(0x1388) #define CORSEC_E_POLICY_EXCEPTION EMAKEHR(0x1416) #define CORSEC_E_MIN_GRANT_FAIL EMAKEHR(0x1417) #define CORSEC_E_NO_EXEC_PERM EMAKEHR(0x1418) #define CORSEC_E_XMLSYNTAX EMAKEHR(0x1419) #define CORSEC_E_INVALID_STRONGNAME EMAKEHR(0x141a) #define CORSEC_E_INVALID_IMAGE_FORMAT EMAKEHR(0x141d) #define CORSEC_E_INVALID_PUBLICKEY EMAKEHR(0x141e) #define CORSEC_E_SIGNATURE_MISMATCH EMAKEHR(0x1420) #define CORSEC_E_CRYPTO EMAKEHR(0x1430) #define CORSEC_E_CRYPTO_UNEX_OPER EMAKEHR(0x1431) #define COR_E_EXCEPTION EMAKEHR(0x1500) #define COR_E_SYSTEM EMAKEHR(0x1501) #define COR_E_ARGUMENTOUTOFRANGE EMAKEHR(0x1502) #define COR_E_ARRAYTYPEMISMATCH EMAKEHR(0x1503) #define COR_E_CONTEXTMARSHAL EMAKEHR(0x1504) #define COR_E_TIMEOUT EMAKEHR(0x1505) #define COR_E_EXECUTIONENGINE EMAKEHR(0x1506) #define COR_E_FIELDACCESS EMAKEHR(0x1507) #define COR_E_INDEXOUTOFRANGE EMAKEHR(0x1508) #define COR_E_INVALIDOPERATION EMAKEHR(0x1509) #define COR_E_SECURITY EMAKEHR(0x150a) #define COR_E_SERIALIZATION EMAKEHR(0x150c) #define COR_E_VERIFICATION EMAKEHR(0x150d) #define COR_E_METHODACCESS EMAKEHR(0x1510) #define COR_E_MISSINGFIELD EMAKEHR(0x1511) #define COR_E_MISSINGMEMBER EMAKEHR(0x1512) #define COR_E_MISSINGMETHOD EMAKEHR(0x1513) #define COR_E_MULTICASTNOTSUPPORTED EMAKEHR(0x1514) #define COR_E_NOTSUPPORTED EMAKEHR(0x1515) #define COR_E_OVERFLOW EMAKEHR(0x1516) #define COR_E_RANK EMAKEHR(0x1517) #define COR_E_SYNCHRONIZATIONLOCK EMAKEHR(0x1518) #define COR_E_THREADINTERRUPTED EMAKEHR(0x1519) #define COR_E_MEMBERACCESS EMAKEHR(0x151a) #define COR_E_THREADSTATE EMAKEHR(0x1520) #define COR_E_THREADSTOP EMAKEHR(0x1521) #define COR_E_TYPELOAD EMAKEHR(0x1522) #define COR_E_ENTRYPOINTNOTFOUND EMAKEHR(0x1523) #define COR_E_DLLNOTFOUND EMAKEHR(0x1524) #define COR_E_THREADSTART EMAKEHR(0x1525) #define COR_E_INVALIDCOMOBJECT EMAKEHR(0x1527) #define COR_E_NOTFINITENUMBER EMAKEHR(0x1528) #define COR_E_DUPLICATEWAITOBJECT EMAKEHR(0x1529) #define COR_E_SEMAPHOREFULL EMAKEHR(0x152b) #define COR_E_WAITHANDLECANNOTBEOPENED EMAKEHR(0x152c) #define COR_E_ABANDONEDMUTEX EMAKEHR(0x152d) #define COR_E_THREADABORTED EMAKEHR(0x1530) #define COR_E_INVALIDOLEVARIANTTYPE EMAKEHR(0x1531) #define COR_E_MISSINGMANIFESTRESOURCE EMAKEHR(0x1532) #define COR_E_SAFEARRAYTYPEMISMATCH EMAKEHR(0x1533) #define COR_E_TYPEINITIALIZATION EMAKEHR(0x1534) #define COR_E_MARSHALDIRECTIVE EMAKEHR(0x1535) #define COR_E_MISSINGSATELLITEASSEMBLY EMAKEHR(0x1536) #define COR_E_FORMAT EMAKEHR(0x1537) #define COR_E_SAFEARRAYRANKMISMATCH EMAKEHR(0x1538) #define COR_E_PLATFORMNOTSUPPORTED EMAKEHR(0x1539) #define COR_E_INVALIDPROGRAM EMAKEHR(0x153a) #define COR_E_OPERATIONCANCELED EMAKEHR(0x153b) #define COR_E_INSUFFICIENTMEMORY EMAKEHR(0x153d) #define COR_E_RUNTIMEWRAPPED EMAKEHR(0x153e) #define COR_E_DATAMISALIGNED EMAKEHR(0x1541) #define COR_E_CODECONTRACTFAILED EMAKEHR(0x1542) #define COR_E_TYPEACCESS EMAKEHR(0x1543) #define COR_E_ACCESSING_CCW EMAKEHR(0x1544) #define COR_E_KEYNOTFOUND EMAKEHR(0x1577) #define COR_E_INSUFFICIENTEXECUTIONSTACK EMAKEHR(0x1578) #define COR_E_APPLICATION EMAKEHR(0x1600) #define COR_E_INVALIDFILTERCRITERIA EMAKEHR(0x1601) #define COR_E_REFLECTIONTYPELOAD EMAKEHR(0x1602) #define COR_E_TARGET EMAKEHR(0x1603) #define COR_E_TARGETINVOCATION EMAKEHR(0x1604) #define COR_E_CUSTOMATTRIBUTEFORMAT EMAKEHR(0x1605) #define COR_E_IO EMAKEHR(0x1620) #define COR_E_FILELOAD EMAKEHR(0x1621) #define COR_E_OBJECTDISPOSED EMAKEHR(0x1622) #define COR_E_FAILFAST EMAKEHR(0x1623) #define COR_E_HOSTPROTECTION EMAKEHR(0x1640) #define COR_E_ILLEGAL_REENTRANCY EMAKEHR(0x1641) #define CLR_E_SHIM_RUNTIMELOAD EMAKEHR(0x1700) #define CLR_E_SHIM_LEGACYRUNTIMEALREADYBOUND EMAKEHR(0x1704) #define VER_E_FIELD_SIG EMAKEHR(0x1815) #define VER_E_CIRCULAR_VAR_CONSTRAINTS EMAKEHR(0x18ce) #define VER_E_CIRCULAR_MVAR_CONSTRAINTS EMAKEHR(0x18cf) #define COR_E_Data EMAKEHR(0x1920) #define VLDTR_E_SIG_BADVOID EMAKEHR(0x1b24) #define VLDTR_E_GP_ILLEGAL_VARIANT_MVAR EMAKEHR(0x1b2d) #define CORDBG_E_THREAD_NOT_SCHEDULED EMAKEHR(0x1c00) #define CORDBG_E_HANDLE_HAS_BEEN_DISPOSED EMAKEHR(0x1c01) #define CORDBG_E_NONINTERCEPTABLE_EXCEPTION EMAKEHR(0x1c02) #define CORDBG_E_INTERCEPT_FRAME_ALREADY_SET EMAKEHR(0x1c04) #define CORDBG_E_NO_NATIVE_PATCH_AT_ADDR EMAKEHR(0x1c05) #define CORDBG_E_MUST_BE_INTEROP_DEBUGGING EMAKEHR(0x1c06) #define CORDBG_E_NATIVE_PATCH_ALREADY_AT_ADDR EMAKEHR(0x1c07) #define CORDBG_E_TIMEOUT EMAKEHR(0x1c08) #define CORDBG_E_CANT_CALL_ON_THIS_THREAD EMAKEHR(0x1c09) #define CORDBG_E_ENC_INFOLESS_METHOD EMAKEHR(0x1c0a) #define CORDBG_E_ENC_IN_FUNCLET EMAKEHR(0x1c0c) #define CORDBG_E_ENC_EDIT_NOT_SUPPORTED EMAKEHR(0x1c0e) #define CORDBG_E_NOTREADY EMAKEHR(0x1c10) #define CORDBG_E_CANNOT_RESOLVE_ASSEMBLY EMAKEHR(0x1c11) #define CORDBG_E_MUST_BE_IN_LOAD_MODULE EMAKEHR(0x1c12) #define CORDBG_E_CANNOT_BE_ON_ATTACH EMAKEHR(0x1c13) #define CORDBG_E_NGEN_NOT_SUPPORTED EMAKEHR(0x1c14) #define CORDBG_E_ILLEGAL_SHUTDOWN_ORDER EMAKEHR(0x1c15) #define CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS EMAKEHR(0x1c16) #define CORDBG_E_MUST_BE_IN_CREATE_PROCESS EMAKEHR(0x1c17) #define CORDBG_E_DETACH_FAILED_OUTSTANDING_EVALS EMAKEHR(0x1c18) #define CORDBG_E_DETACH_FAILED_OUTSTANDING_STEPPERS EMAKEHR(0x1c19) #define CORDBG_E_CANT_INTEROP_STEP_OUT EMAKEHR(0x1c20) #define CORDBG_E_DETACH_FAILED_OUTSTANDING_BREAKPOINTS EMAKEHR(0x1c21) #define CORDBG_E_ILLEGAL_IN_STACK_OVERFLOW EMAKEHR(0x1c22) #define CORDBG_E_ILLEGAL_AT_GC_UNSAFE_POINT EMAKEHR(0x1c23) #define CORDBG_E_ILLEGAL_IN_PROLOG EMAKEHR(0x1c24) #define CORDBG_E_ILLEGAL_IN_NATIVE_CODE EMAKEHR(0x1c25) #define CORDBG_E_ILLEGAL_IN_OPTIMIZED_CODE EMAKEHR(0x1c26) #define CORDBG_E_APPDOMAIN_MISMATCH EMAKEHR(0x1c28) #define CORDBG_E_CONTEXT_UNVAILABLE EMAKEHR(0x1c29) #define CORDBG_E_INCOMPATIBLE_PLATFORMS EMAKEHR(0x1c30) #define CORDBG_E_DEBUGGING_DISABLED EMAKEHR(0x1c31) #define CORDBG_E_DETACH_FAILED_ON_ENC EMAKEHR(0x1c32) #define CORDBG_E_CURRENT_EXCEPTION_IS_OUTSIDE_CURRENT_EXECUTION_SCOPE EMAKEHR(0x1c33) #define CORDBG_E_HELPER_MAY_DEADLOCK EMAKEHR(0x1c34) #define CORDBG_E_MISSING_METADATA EMAKEHR(0x1c35) #define CORDBG_E_TARGET_INCONSISTENT EMAKEHR(0x1c36) #define CORDBG_E_DETACH_FAILED_OUTSTANDING_TARGET_RESOURCES EMAKEHR(0x1c37) #define CORDBG_E_TARGET_READONLY EMAKEHR(0x1c38) #define CORDBG_E_MISMATCHED_CORWKS_AND_DACWKS_DLLS EMAKEHR(0x1c39) #define CORDBG_E_MODULE_LOADED_FROM_DISK EMAKEHR(0x1c3a) #define CORDBG_E_SYMBOLS_NOT_AVAILABLE EMAKEHR(0x1c3b) #define CORDBG_E_DEBUG_COMPONENT_MISSING EMAKEHR(0x1c3c) #define CORDBG_E_LIBRARY_PROVIDER_ERROR EMAKEHR(0x1c43) #define CORDBG_E_NOT_CLR EMAKEHR(0x1c44) #define CORDBG_E_MISSING_DATA_TARGET_INTERFACE EMAKEHR(0x1c45) #define CORDBG_E_UNSUPPORTED_DEBUGGING_MODEL EMAKEHR(0x1c46) #define CORDBG_E_UNSUPPORTED_FORWARD_COMPAT EMAKEHR(0x1c47) #define CORDBG_E_UNSUPPORTED_VERSION_STRUCT EMAKEHR(0x1c48) #define CORDBG_E_READVIRTUAL_FAILURE EMAKEHR(0x1c49) #define CORDBG_E_VALUE_POINTS_TO_FUNCTION EMAKEHR(0x1c4a) #define CORDBG_E_CORRUPT_OBJECT EMAKEHR(0x1c4b) #define CORDBG_E_GC_STRUCTURES_INVALID EMAKEHR(0x1c4c) #define CORDBG_E_INVALID_OPCODE EMAKEHR(0x1c4d) #define CORDBG_E_UNSUPPORTED EMAKEHR(0x1c4e) #define CORDBG_E_MISSING_DEBUGGER_EXPORTS EMAKEHR(0x1c4f) #define CORDBG_E_DATA_TARGET_ERROR EMAKEHR(0x1c61) #define CORDBG_E_UNSUPPORTED_DELEGATE EMAKEHR(0x1c68) #define CORDBG_E_ASSEMBLY_UPDATES_APPLIED EMAKEHR(0x1c69) #define PEFMT_E_64BIT EMAKEHR(0x1d02) #define PEFMT_E_32BIT EMAKEHR(0x1d0b) #define CLDB_E_INTERNALERROR EMAKEHR(0x1fff) #define CLR_E_BIND_ASSEMBLY_VERSION_TOO_LOW EMAKEHR(0x2000) #define CLR_E_BIND_ASSEMBLY_PUBLIC_KEY_MISMATCH EMAKEHR(0x2001) #define CLR_E_BIND_IMAGE_UNAVAILABLE EMAKEHR(0x2002) #define CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT EMAKEHR(0x2003) #define CLR_E_BIND_ASSEMBLY_NOT_FOUND EMAKEHR(0x2004) #define CLR_E_BIND_TYPE_NOT_FOUND EMAKEHR(0x2005) #define CLR_E_GC_OOM EMAKEHR(0x2009) #define CLR_E_GC_BAD_AFFINITY_CONFIG EMAKEHR(0x200a) #define CLR_E_GC_BAD_AFFINITY_CONFIG_FORMAT EMAKEHR(0x200b) #define CLR_E_GC_BAD_HARD_LIMIT EMAKEHR(0x200d) #define CLR_E_GC_LARGE_PAGE_MISSING_HARD_LIMIT EMAKEHR(0x200e) #define COR_E_UNAUTHORIZEDACCESS E_ACCESSDENIED #define COR_E_ARGUMENT E_INVALIDARG #define COR_E_INVALIDCAST E_NOINTERFACE #define COR_E_OUTOFMEMORY E_OUTOFMEMORY #define COR_E_NULLREFERENCE E_POINTER #define COR_E_ARITHMETIC __HRESULT_FROM_WIN32(ERROR_ARITHMETIC_OVERFLOW) #define COR_E_PATHTOOLONG __HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE) #define COR_E_FILENOTFOUND __HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) #define COR_E_ENDOFSTREAM __HRESULT_FROM_WIN32(ERROR_HANDLE_EOF) #define COR_E_DIRECTORYNOTFOUND __HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) #define COR_E_STACKOVERFLOW __HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW) #define COR_E_AMBIGUOUSMATCH _HRESULT_TYPEDEF_(0x8000211DL) #define COR_E_TARGETPARAMCOUNT _HRESULT_TYPEDEF_(0x8002000EL) #define COR_E_DIVIDEBYZERO _HRESULT_TYPEDEF_(0x80020012L) #define COR_E_BADIMAGEFORMAT _HRESULT_TYPEDEF_(0x8007000BL) #endif // __COMMON_LANGUAGE_RUNTIME_HRESULTS__ ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/corprof.h ================================================ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0622 */ /* Compiler settings for corprof.idl: Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __corprof_h__ #define __corprof_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __ICorProfilerCallback_FWD_DEFINED__ #define __ICorProfilerCallback_FWD_DEFINED__ typedef interface ICorProfilerCallback ICorProfilerCallback; #endif /* __ICorProfilerCallback_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback2_FWD_DEFINED__ #define __ICorProfilerCallback2_FWD_DEFINED__ typedef interface ICorProfilerCallback2 ICorProfilerCallback2; #endif /* __ICorProfilerCallback2_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback3_FWD_DEFINED__ #define __ICorProfilerCallback3_FWD_DEFINED__ typedef interface ICorProfilerCallback3 ICorProfilerCallback3; #endif /* __ICorProfilerCallback3_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback4_FWD_DEFINED__ #define __ICorProfilerCallback4_FWD_DEFINED__ typedef interface ICorProfilerCallback4 ICorProfilerCallback4; #endif /* __ICorProfilerCallback4_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback5_FWD_DEFINED__ #define __ICorProfilerCallback5_FWD_DEFINED__ typedef interface ICorProfilerCallback5 ICorProfilerCallback5; #endif /* __ICorProfilerCallback5_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback6_FWD_DEFINED__ #define __ICorProfilerCallback6_FWD_DEFINED__ typedef interface ICorProfilerCallback6 ICorProfilerCallback6; #endif /* __ICorProfilerCallback6_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback7_FWD_DEFINED__ #define __ICorProfilerCallback7_FWD_DEFINED__ typedef interface ICorProfilerCallback7 ICorProfilerCallback7; #endif /* __ICorProfilerCallback7_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback8_FWD_DEFINED__ #define __ICorProfilerCallback8_FWD_DEFINED__ typedef interface ICorProfilerCallback8 ICorProfilerCallback8; #endif /* __ICorProfilerCallback8_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback9_FWD_DEFINED__ #define __ICorProfilerCallback9_FWD_DEFINED__ typedef interface ICorProfilerCallback9 ICorProfilerCallback9; #endif /* __ICorProfilerCallback9_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback10_FWD_DEFINED__ #define __ICorProfilerCallback10_FWD_DEFINED__ typedef interface ICorProfilerCallback10 ICorProfilerCallback10; #endif /* __ICorProfilerCallback10_FWD_DEFINED__ */ #ifndef __ICorProfilerCallback11_FWD_DEFINED__ #define __ICorProfilerCallback11_FWD_DEFINED__ typedef interface ICorProfilerCallback11 ICorProfilerCallback11; #endif /* __ICorProfilerCallback11_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo_FWD_DEFINED__ #define __ICorProfilerInfo_FWD_DEFINED__ typedef interface ICorProfilerInfo ICorProfilerInfo; #endif /* __ICorProfilerInfo_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo2_FWD_DEFINED__ #define __ICorProfilerInfo2_FWD_DEFINED__ typedef interface ICorProfilerInfo2 ICorProfilerInfo2; #endif /* __ICorProfilerInfo2_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo3_FWD_DEFINED__ #define __ICorProfilerInfo3_FWD_DEFINED__ typedef interface ICorProfilerInfo3 ICorProfilerInfo3; #endif /* __ICorProfilerInfo3_FWD_DEFINED__ */ #ifndef __ICorProfilerObjectEnum_FWD_DEFINED__ #define __ICorProfilerObjectEnum_FWD_DEFINED__ typedef interface ICorProfilerObjectEnum ICorProfilerObjectEnum; #endif /* __ICorProfilerObjectEnum_FWD_DEFINED__ */ #ifndef __ICorProfilerFunctionEnum_FWD_DEFINED__ #define __ICorProfilerFunctionEnum_FWD_DEFINED__ typedef interface ICorProfilerFunctionEnum ICorProfilerFunctionEnum; #endif /* __ICorProfilerFunctionEnum_FWD_DEFINED__ */ #ifndef __ICorProfilerModuleEnum_FWD_DEFINED__ #define __ICorProfilerModuleEnum_FWD_DEFINED__ typedef interface ICorProfilerModuleEnum ICorProfilerModuleEnum; #endif /* __ICorProfilerModuleEnum_FWD_DEFINED__ */ #ifndef __IMethodMalloc_FWD_DEFINED__ #define __IMethodMalloc_FWD_DEFINED__ typedef interface IMethodMalloc IMethodMalloc; #endif /* __IMethodMalloc_FWD_DEFINED__ */ #ifndef __ICorProfilerFunctionControl_FWD_DEFINED__ #define __ICorProfilerFunctionControl_FWD_DEFINED__ typedef interface ICorProfilerFunctionControl ICorProfilerFunctionControl; #endif /* __ICorProfilerFunctionControl_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo4_FWD_DEFINED__ #define __ICorProfilerInfo4_FWD_DEFINED__ typedef interface ICorProfilerInfo4 ICorProfilerInfo4; #endif /* __ICorProfilerInfo4_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo5_FWD_DEFINED__ #define __ICorProfilerInfo5_FWD_DEFINED__ typedef interface ICorProfilerInfo5 ICorProfilerInfo5; #endif /* __ICorProfilerInfo5_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo6_FWD_DEFINED__ #define __ICorProfilerInfo6_FWD_DEFINED__ typedef interface ICorProfilerInfo6 ICorProfilerInfo6; #endif /* __ICorProfilerInfo6_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo7_FWD_DEFINED__ #define __ICorProfilerInfo7_FWD_DEFINED__ typedef interface ICorProfilerInfo7 ICorProfilerInfo7; #endif /* __ICorProfilerInfo7_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo8_FWD_DEFINED__ #define __ICorProfilerInfo8_FWD_DEFINED__ typedef interface ICorProfilerInfo8 ICorProfilerInfo8; #endif /* __ICorProfilerInfo8_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo9_FWD_DEFINED__ #define __ICorProfilerInfo9_FWD_DEFINED__ typedef interface ICorProfilerInfo9 ICorProfilerInfo9; #endif /* __ICorProfilerInfo9_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo10_FWD_DEFINED__ #define __ICorProfilerInfo10_FWD_DEFINED__ typedef interface ICorProfilerInfo10 ICorProfilerInfo10; #endif /* __ICorProfilerInfo10_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo11_FWD_DEFINED__ #define __ICorProfilerInfo11_FWD_DEFINED__ typedef interface ICorProfilerInfo11 ICorProfilerInfo11; #endif /* __ICorProfilerInfo11_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo12_FWD_DEFINED__ #define __ICorProfilerInfo12_FWD_DEFINED__ typedef interface ICorProfilerInfo12 ICorProfilerInfo12; #endif /* __ICorProfilerInfo12_FWD_DEFINED__ */ #ifndef __ICorProfilerInfo13_FWD_DEFINED__ #define __ICorProfilerInfo13_FWD_DEFINED__ typedef interface ICorProfilerInfo13 ICorProfilerInfo13; #endif /* __ICorProfilerInfo13_FWD_DEFINED__ */ #ifndef __ICorProfilerMethodEnum_FWD_DEFINED__ #define __ICorProfilerMethodEnum_FWD_DEFINED__ typedef interface ICorProfilerMethodEnum ICorProfilerMethodEnum; #endif /* __ICorProfilerMethodEnum_FWD_DEFINED__ */ #ifndef __ICorProfilerThreadEnum_FWD_DEFINED__ #define __ICorProfilerThreadEnum_FWD_DEFINED__ typedef interface ICorProfilerThreadEnum ICorProfilerThreadEnum; #endif /* __ICorProfilerThreadEnum_FWD_DEFINED__ */ #ifndef __ICorProfilerAssemblyReferenceProvider_FWD_DEFINED__ #define __ICorProfilerAssemblyReferenceProvider_FWD_DEFINED__ typedef interface ICorProfilerAssemblyReferenceProvider ICorProfilerAssemblyReferenceProvider; #endif /* __ICorProfilerAssemblyReferenceProvider_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_corprof_0000_0000 */ /* [local] */ #if 0 typedef LONG32 mdToken; typedef mdToken mdModule; typedef mdToken mdTypeDef; typedef mdToken mdMethodDef; typedef mdToken mdFieldDef; typedef ULONG CorElementType; typedef /* [public][public][public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0001 { DWORD dwOSPlatformId; DWORD dwOSMajorVersion; DWORD dwOSMinorVersion; } OSINFO; typedef /* [public][public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0002 { USHORT usMajorVersion; USHORT usMinorVersion; USHORT usBuildNumber; USHORT usRevisionNumber; LPWSTR szLocale; ULONG cbLocale; DWORD *rProcessor; ULONG ulProcessor; OSINFO *rOS; ULONG ulOS; } ASSEMBLYMETADATA; #endif typedef const BYTE *LPCBYTE; typedef BYTE *LPBYTE; typedef BYTE COR_SIGNATURE; typedef COR_SIGNATURE *PCOR_SIGNATURE; typedef const COR_SIGNATURE *PCCOR_SIGNATURE; #ifndef _COR_IL_MAP #define _COR_IL_MAP typedef struct _COR_IL_MAP { ULONG32 oldOffset; ULONG32 newOffset; BOOL fAccurate; } COR_IL_MAP; #endif //_COR_IL_MAP #ifndef _COR_DEBUG_IL_TO_NATIVE_MAP_ #define _COR_DEBUG_IL_TO_NATIVE_MAP_ typedef enum CorDebugIlToNativeMappingTypes { NO_MAPPING = -1, PROLOG = -2, EPILOG = -3 } CorDebugIlToNativeMappingTypes; typedef struct COR_DEBUG_IL_TO_NATIVE_MAP { ULONG32 ilOffset; ULONG32 nativeStartOffset; ULONG32 nativeEndOffset; } COR_DEBUG_IL_TO_NATIVE_MAP; #endif // _COR_DEBUG_IL_TO_NATIVE_MAP_ #ifndef _COR_FIELD_OFFSET_ #define _COR_FIELD_OFFSET_ typedef struct _COR_FIELD_OFFSET { mdFieldDef ridOfField; ULONG ulOffset; } COR_FIELD_OFFSET; #endif // _COR_FIELD_OFFSET_ typedef UINT_PTR ProcessID; typedef UINT_PTR AssemblyID; typedef UINT_PTR AppDomainID; typedef UINT_PTR ModuleID; typedef UINT_PTR ClassID; typedef UINT_PTR ThreadID; typedef UINT_PTR ContextID; typedef UINT_PTR FunctionID; typedef UINT_PTR ObjectID; typedef UINT_PTR GCHandleID; typedef UINT_PTR COR_PRF_ELT_INFO; typedef UINT_PTR ReJITID; typedef /* [public][public][public][public][public][public][public][public][public][public][public][public][public] */ union __MIDL___MIDL_itf_corprof_0000_0000_0003 { FunctionID functionID; UINT_PTR clientID; } FunctionIDOrClientID; typedef UINT_PTR __stdcall __stdcall FunctionIDMapper( FunctionID funcId, BOOL *pbHookFunction); typedef UINT_PTR __stdcall __stdcall FunctionIDMapper2( FunctionID funcId, void *clientData, BOOL *pbHookFunction); typedef enum _COR_PRF_SNAPSHOT_INFO { COR_PRF_SNAPSHOT_DEFAULT = 0, COR_PRF_SNAPSHOT_REGISTER_CONTEXT = 0x1, COR_PRF_SNAPSHOT_X86_OPTIMIZED = 0x2 } COR_PRF_SNAPSHOT_INFO; typedef UINT_PTR COR_PRF_FRAME_INFO; typedef struct _COR_PRF_FUNCTION_ARGUMENT_RANGE { UINT_PTR startAddress; ULONG length; } COR_PRF_FUNCTION_ARGUMENT_RANGE; typedef struct _COR_PRF_FUNCTION_ARGUMENT_INFO { ULONG numRanges; ULONG totalArgumentSize; COR_PRF_FUNCTION_ARGUMENT_RANGE ranges[ 1 ]; } COR_PRF_FUNCTION_ARGUMENT_INFO; typedef struct _COR_PRF_CODE_INFO { UINT_PTR startAddress; SIZE_T size; } COR_PRF_CODE_INFO; typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0004 { COR_PRF_FIELD_NOT_A_STATIC = 0, COR_PRF_FIELD_APP_DOMAIN_STATIC = 0x1, COR_PRF_FIELD_THREAD_STATIC = 0x2, COR_PRF_FIELD_CONTEXT_STATIC = 0x4, COR_PRF_FIELD_RVA_STATIC = 0x8 } COR_PRF_STATIC_TYPE; typedef struct _COR_PRF_FUNCTION { FunctionID functionId; ReJITID reJitId; } COR_PRF_FUNCTION; typedef struct _COR_PRF_ASSEMBLY_REFERENCE_INFO { void *pbPublicKeyOrToken; ULONG cbPublicKeyOrToken; LPCWSTR szName; ASSEMBLYMETADATA *pMetaData; void *pbHashValue; ULONG cbHashValue; DWORD dwAssemblyRefFlags; } COR_PRF_ASSEMBLY_REFERENCE_INFO; typedef struct _COR_PRF_METHOD { ModuleID moduleId; mdMethodDef methodId; } COR_PRF_METHOD; typedef void FunctionEnter( FunctionID funcID); typedef void FunctionLeave( FunctionID funcID); typedef void FunctionTailcall( FunctionID funcID); typedef void FunctionEnter2( FunctionID funcId, UINT_PTR clientData, COR_PRF_FRAME_INFO func, COR_PRF_FUNCTION_ARGUMENT_INFO *argumentInfo); typedef void FunctionLeave2( FunctionID funcId, UINT_PTR clientData, COR_PRF_FRAME_INFO func, COR_PRF_FUNCTION_ARGUMENT_RANGE *retvalRange); typedef void FunctionTailcall2( FunctionID funcId, UINT_PTR clientData, COR_PRF_FRAME_INFO func); typedef void FunctionEnter3( FunctionIDOrClientID functionIDOrClientID); typedef void FunctionLeave3( FunctionIDOrClientID functionIDOrClientID); typedef void FunctionTailcall3( FunctionIDOrClientID functionIDOrClientID); typedef void FunctionEnter3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); typedef void FunctionLeave3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); typedef void FunctionTailcall3WithInfo( FunctionIDOrClientID functionIDOrClientID, COR_PRF_ELT_INFO eltInfo); typedef HRESULT __stdcall __stdcall StackSnapshotCallback( FunctionID funcId, UINT_PTR ip, COR_PRF_FRAME_INFO frameInfo, ULONG32 contextSize, BYTE context[ ], void *clientData); typedef BOOL ObjectReferenceCallback( ObjectID root, ObjectID *reference, void *clientData); typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0005 { COR_PRF_MONITOR_NONE = 0, COR_PRF_MONITOR_FUNCTION_UNLOADS = 0x1, COR_PRF_MONITOR_CLASS_LOADS = 0x2, COR_PRF_MONITOR_MODULE_LOADS = 0x4, COR_PRF_MONITOR_ASSEMBLY_LOADS = 0x8, COR_PRF_MONITOR_APPDOMAIN_LOADS = 0x10, COR_PRF_MONITOR_JIT_COMPILATION = 0x20, COR_PRF_MONITOR_EXCEPTIONS = 0x40, COR_PRF_MONITOR_GC = 0x80, COR_PRF_MONITOR_OBJECT_ALLOCATED = 0x100, COR_PRF_MONITOR_THREADS = 0x200, COR_PRF_MONITOR_REMOTING = 0x400, COR_PRF_MONITOR_CODE_TRANSITIONS = 0x800, COR_PRF_MONITOR_ENTERLEAVE = 0x1000, COR_PRF_MONITOR_CCW = 0x2000, COR_PRF_MONITOR_REMOTING_COOKIE = ( 0x4000 | COR_PRF_MONITOR_REMOTING ) , COR_PRF_MONITOR_REMOTING_ASYNC = ( 0x8000 | COR_PRF_MONITOR_REMOTING ) , COR_PRF_MONITOR_SUSPENDS = 0x10000, COR_PRF_MONITOR_CACHE_SEARCHES = 0x20000, COR_PRF_ENABLE_REJIT = 0x40000, COR_PRF_ENABLE_INPROC_DEBUGGING = 0x80000, COR_PRF_ENABLE_JIT_MAPS = 0x100000, COR_PRF_DISABLE_INLINING = 0x200000, COR_PRF_DISABLE_OPTIMIZATIONS = 0x400000, COR_PRF_ENABLE_OBJECT_ALLOCATED = 0x800000, COR_PRF_MONITOR_CLR_EXCEPTIONS = 0x1000000, COR_PRF_MONITOR_ALL = 0x107ffff, COR_PRF_ENABLE_FUNCTION_ARGS = 0x2000000, COR_PRF_ENABLE_FUNCTION_RETVAL = 0x4000000, COR_PRF_ENABLE_FRAME_INFO = 0x8000000, COR_PRF_ENABLE_STACK_SNAPSHOT = 0x10000000, COR_PRF_USE_PROFILE_IMAGES = 0x20000000, COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST = 0x40000000, COR_PRF_DISABLE_ALL_NGEN_IMAGES = 0x80000000, COR_PRF_ALL = 0x8fffffff, COR_PRF_REQUIRE_PROFILE_IMAGE = ( ( COR_PRF_USE_PROFILE_IMAGES | COR_PRF_MONITOR_CODE_TRANSITIONS ) | COR_PRF_MONITOR_ENTERLEAVE ) , COR_PRF_ALLOWABLE_AFTER_ATTACH = ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_THREADS | COR_PRF_MONITOR_MODULE_LOADS ) | COR_PRF_MONITOR_ASSEMBLY_LOADS ) | COR_PRF_MONITOR_APPDOMAIN_LOADS ) | COR_PRF_ENABLE_STACK_SNAPSHOT ) | COR_PRF_MONITOR_GC ) | COR_PRF_MONITOR_SUSPENDS ) | COR_PRF_MONITOR_CLASS_LOADS ) | COR_PRF_MONITOR_EXCEPTIONS ) | COR_PRF_MONITOR_JIT_COMPILATION ) | COR_PRF_ENABLE_REJIT ) , COR_PRF_ALLOWABLE_NOTIFICATION_PROFILER = ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_FUNCTION_UNLOADS | COR_PRF_MONITOR_CLASS_LOADS ) | COR_PRF_MONITOR_MODULE_LOADS ) | COR_PRF_MONITOR_ASSEMBLY_LOADS ) | COR_PRF_MONITOR_APPDOMAIN_LOADS ) | COR_PRF_MONITOR_JIT_COMPILATION ) | COR_PRF_MONITOR_EXCEPTIONS ) | COR_PRF_MONITOR_OBJECT_ALLOCATED ) | COR_PRF_MONITOR_THREADS ) | COR_PRF_MONITOR_CODE_TRANSITIONS ) | COR_PRF_MONITOR_CCW ) | COR_PRF_MONITOR_SUSPENDS ) | COR_PRF_MONITOR_CACHE_SEARCHES ) | COR_PRF_DISABLE_INLINING ) | COR_PRF_DISABLE_OPTIMIZATIONS ) | COR_PRF_ENABLE_OBJECT_ALLOCATED ) | COR_PRF_MONITOR_CLR_EXCEPTIONS ) | COR_PRF_ENABLE_STACK_SNAPSHOT ) | COR_PRF_USE_PROFILE_IMAGES ) | COR_PRF_DISABLE_ALL_NGEN_IMAGES ) , COR_PRF_MONITOR_IMMUTABLE = ( ( ( ( ( ( ( ( ( ( ( ( ( ( COR_PRF_MONITOR_CODE_TRANSITIONS | COR_PRF_MONITOR_REMOTING ) | COR_PRF_MONITOR_REMOTING_COOKIE ) | COR_PRF_MONITOR_REMOTING_ASYNC ) | COR_PRF_ENABLE_INPROC_DEBUGGING ) | COR_PRF_ENABLE_JIT_MAPS ) | COR_PRF_DISABLE_OPTIMIZATIONS ) | COR_PRF_DISABLE_INLINING ) | COR_PRF_ENABLE_OBJECT_ALLOCATED ) | COR_PRF_ENABLE_FUNCTION_ARGS ) | COR_PRF_ENABLE_FUNCTION_RETVAL ) | COR_PRF_ENABLE_FRAME_INFO ) | COR_PRF_USE_PROFILE_IMAGES ) | COR_PRF_DISABLE_TRANSPARENCY_CHECKS_UNDER_FULL_TRUST ) | COR_PRF_DISABLE_ALL_NGEN_IMAGES ) } COR_PRF_MONITOR; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0006 { COR_PRF_HIGH_MONITOR_NONE = 0, COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES = 0x1, COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x2, COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS = 0x4, COR_PRF_HIGH_DISABLE_TIERED_COMPILATION = 0x8, COR_PRF_HIGH_BASIC_GC = 0x10, COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS = 0x20, COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0, COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x40, COR_PRF_HIGH_MONITOR_EVENT_PIPE = 0x80, COR_PRF_HIGH_MONITOR_PINNEDOBJECT_ALLOCATED = 0x100, COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( ( ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS ) | COR_PRF_HIGH_BASIC_GC ) | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS ) | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED ) | COR_PRF_HIGH_MONITOR_EVENT_PIPE ) , COR_PRF_HIGH_ALLOWABLE_NOTIFICATION_PROFILER = ( ( ( ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS ) | COR_PRF_HIGH_DISABLE_TIERED_COMPILATION ) | COR_PRF_HIGH_BASIC_GC ) | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS ) | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED ) | COR_PRF_HIGH_MONITOR_EVENT_PIPE ) , COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION } COR_PRF_HIGH_MONITOR; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0007 { PROFILER_PARENT_UNKNOWN = 0xfffffffd, PROFILER_GLOBAL_CLASS = 0xfffffffe, PROFILER_GLOBAL_MODULE = 0xffffffff } COR_PRF_MISC; typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0008 { COR_PRF_CACHED_FUNCTION_FOUND = 0, COR_PRF_CACHED_FUNCTION_NOT_FOUND = ( COR_PRF_CACHED_FUNCTION_FOUND + 1 ) } COR_PRF_JIT_CACHE; typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0009 { COR_PRF_TRANSITION_CALL = 0, COR_PRF_TRANSITION_RETURN = ( COR_PRF_TRANSITION_CALL + 1 ) } COR_PRF_TRANSITION_REASON; typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0010 { COR_PRF_SUSPEND_OTHER = 0, COR_PRF_SUSPEND_FOR_GC = 1, COR_PRF_SUSPEND_FOR_APPDOMAIN_SHUTDOWN = 2, COR_PRF_SUSPEND_FOR_CODE_PITCHING = 3, COR_PRF_SUSPEND_FOR_SHUTDOWN = 4, COR_PRF_SUSPEND_FOR_INPROC_DEBUGGER = 6, COR_PRF_SUSPEND_FOR_GC_PREP = 7, COR_PRF_SUSPEND_FOR_REJIT = 8, COR_PRF_SUSPEND_FOR_PROFILER = 9 } COR_PRF_SUSPEND_REASON; typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0011 { COR_PRF_DESKTOP_CLR = 0x1, COR_PRF_CORE_CLR = 0x2 } COR_PRF_RUNTIME_TYPE; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0012 { COR_PRF_REJIT_BLOCK_INLINING = 0x1, COR_PRF_REJIT_INLINING_CALLBACKS = 0x2 } COR_PRF_REJIT_FLAGS; typedef UINT_PTR EVENTPIPE_PROVIDER; typedef UINT_PTR EVENTPIPE_EVENT; typedef UINT64 EVENTPIPE_SESSION; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0013 { COR_PRF_EVENTPIPE_OBJECT = 1, COR_PRF_EVENTPIPE_BOOLEAN = 3, COR_PRF_EVENTPIPE_CHAR = 4, COR_PRF_EVENTPIPE_SBYTE = 5, COR_PRF_EVENTPIPE_BYTE = 6, COR_PRF_EVENTPIPE_INT16 = 7, COR_PRF_EVENTPIPE_UINT16 = 8, COR_PRF_EVENTPIPE_INT32 = 9, COR_PRF_EVENTPIPE_UINT32 = 10, COR_PRF_EVENTPIPE_INT64 = 11, COR_PRF_EVENTPIPE_UINT64 = 12, COR_PRF_EVENTPIPE_SINGLE = 13, COR_PRF_EVENTPIPE_DOUBLE = 14, COR_PRF_EVENTPIPE_DECIMAL = 15, COR_PRF_EVENTPIPE_DATETIME = 16, COR_PRF_EVENTPIPE_GUID = 17, COR_PRF_EVENTPIPE_STRING = 18, COR_PRF_EVENTPIPE_ARRAY = 19 } COR_PRF_EVENTPIPE_PARAM_TYPE; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0000_0014 { COR_PRF_EVENTPIPE_LOGALWAYS = 0, COR_PRF_EVENTPIPE_CRITICAL = 1, COR_PRF_EVENTPIPE_ERROR = 2, COR_PRF_EVENTPIPE_WARNING = 3, COR_PRF_EVENTPIPE_INFORMATIONAL = 4, COR_PRF_EVENTPIPE_VERBOSE = 5 } COR_PRF_EVENTPIPE_LEVEL; typedef /* [public][public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0015 { const WCHAR *providerName; UINT64 keywords; UINT32 loggingLevel; const WCHAR *filterData; } COR_PRF_EVENTPIPE_PROVIDER_CONFIG; typedef /* [public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0016 { UINT32 type; UINT32 elementType; const WCHAR *name; } COR_PRF_EVENTPIPE_PARAM_DESC; typedef /* [public][public] */ struct __MIDL___MIDL_itf_corprof_0000_0000_0017 { UINT64 ptr; UINT32 size; UINT32 reserved; } COR_PRF_EVENT_DATA; typedef enum _COR_PRF_HANDLE_TYPE { COR_PRF_HANDLE_TYPE_WEAK = 0x1, COR_PRF_HANDLE_TYPE_STRONG = 0x2, COR_PRF_HANDLE_TYPE_PINNED = 0x3 } COR_PRF_HANDLE_TYPE; typedef void **ObjectHandleID; extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0000_v0_0_s_ifspec; #ifndef __ICorProfilerCallback_INTERFACE_DEFINED__ #define __ICorProfilerCallback_INTERFACE_DEFINED__ /* interface ICorProfilerCallback */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("176FBED1-A55C-4796-98CA-A9DA0EF883E7") ICorProfilerCallback : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Initialize( /* [in] */ IUnknown *pICorProfilerInfoUnk) = 0; virtual HRESULT STDMETHODCALLTYPE Shutdown( void) = 0; virtual HRESULT STDMETHODCALLTYPE AppDomainCreationStarted( /* [in] */ AppDomainID appDomainId) = 0; virtual HRESULT STDMETHODCALLTYPE AppDomainCreationFinished( /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownStarted( /* [in] */ AppDomainID appDomainId) = 0; virtual HRESULT STDMETHODCALLTYPE AppDomainShutdownFinished( /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE AssemblyLoadStarted( /* [in] */ AssemblyID assemblyId) = 0; virtual HRESULT STDMETHODCALLTYPE AssemblyLoadFinished( /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadStarted( /* [in] */ AssemblyID assemblyId) = 0; virtual HRESULT STDMETHODCALLTYPE AssemblyUnloadFinished( /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE ModuleLoadStarted( /* [in] */ ModuleID moduleId) = 0; virtual HRESULT STDMETHODCALLTYPE ModuleLoadFinished( /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE ModuleUnloadStarted( /* [in] */ ModuleID moduleId) = 0; virtual HRESULT STDMETHODCALLTYPE ModuleUnloadFinished( /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE ModuleAttachedToAssembly( /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId) = 0; virtual HRESULT STDMETHODCALLTYPE ClassLoadStarted( /* [in] */ ClassID classId) = 0; virtual HRESULT STDMETHODCALLTYPE ClassLoadFinished( /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE ClassUnloadStarted( /* [in] */ ClassID classId) = 0; virtual HRESULT STDMETHODCALLTYPE ClassUnloadFinished( /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE FunctionUnloadStarted( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE JITCompilationStarted( /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock) = 0; virtual HRESULT STDMETHODCALLTYPE JITCompilationFinished( /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock) = 0; virtual HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchStarted( /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction) = 0; virtual HRESULT STDMETHODCALLTYPE JITCachedFunctionSearchFinished( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result) = 0; virtual HRESULT STDMETHODCALLTYPE JITFunctionPitched( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE JITInlining( /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline) = 0; virtual HRESULT STDMETHODCALLTYPE ThreadCreated( /* [in] */ ThreadID threadId) = 0; virtual HRESULT STDMETHODCALLTYPE ThreadDestroyed( /* [in] */ ThreadID threadId) = 0; virtual HRESULT STDMETHODCALLTYPE ThreadAssignedToOSThread( /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationStarted( void) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingClientSendingMessage( /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingClientReceivingReply( /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingClientInvocationFinished( void) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingServerReceivingMessage( /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationStarted( void) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingServerInvocationReturned( void) = 0; virtual HRESULT STDMETHODCALLTYPE RemotingServerSendingReply( /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync) = 0; virtual HRESULT STDMETHODCALLTYPE UnmanagedToManagedTransition( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason) = 0; virtual HRESULT STDMETHODCALLTYPE ManagedToUnmanagedTransition( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendStarted( /* [in] */ COR_PRF_SUSPEND_REASON suspendReason) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendFinished( void) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeSuspendAborted( void) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeResumeStarted( void) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeResumeFinished( void) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeThreadSuspended( /* [in] */ ThreadID threadId) = 0; virtual HRESULT STDMETHODCALLTYPE RuntimeThreadResumed( /* [in] */ ThreadID threadId) = 0; virtual HRESULT STDMETHODCALLTYPE MovedReferences( /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE ObjectAllocated( /* [in] */ ObjectID objectId, /* [in] */ ClassID classId) = 0; virtual HRESULT STDMETHODCALLTYPE ObjectsAllocatedByClass( /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE ObjectReferences( /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE RootReferences( /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionThrown( /* [in] */ ObjectID thrownObjectId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionEnter( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFunctionLeave( void) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterEnter( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionSearchFilterLeave( void) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionSearchCatcherFound( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionOSHandlerEnter( /* [in] */ UINT_PTR __unused) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionOSHandlerLeave( /* [in] */ UINT_PTR __unused) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionEnter( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFunctionLeave( void) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyEnter( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionUnwindFinallyLeave( void) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter( /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherLeave( void) = 0; virtual HRESULT STDMETHODCALLTYPE COMClassicVTableCreated( /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots) = 0; virtual HRESULT STDMETHODCALLTYPE COMClassicVTableDestroyed( /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherFound( void) = 0; virtual HRESULT STDMETHODCALLTYPE ExceptionCLRCatcherExecute( void) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallbackVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback * This); END_INTERFACE } ICorProfilerCallbackVtbl; interface ICorProfilerCallback { CONST_VTBL struct ICorProfilerCallbackVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corprof_0000_0001 */ /* [local] */ typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0001 { COR_PRF_GC_ROOT_STACK = 1, COR_PRF_GC_ROOT_FINALIZER = 2, COR_PRF_GC_ROOT_HANDLE = 3, COR_PRF_GC_ROOT_OTHER = 0 } COR_PRF_GC_ROOT_KIND; typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0002 { COR_PRF_GC_ROOT_PINNING = 0x1, COR_PRF_GC_ROOT_WEAKREF = 0x2, COR_PRF_GC_ROOT_INTERIOR = 0x4, COR_PRF_GC_ROOT_REFCOUNTED = 0x8 } COR_PRF_GC_ROOT_FLAGS; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0003 { COR_PRF_FINALIZER_CRITICAL = 0x1 } COR_PRF_FINALIZER_FLAGS; typedef /* [public][public][public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0004 { COR_PRF_GC_GEN_0 = 0, COR_PRF_GC_GEN_1 = 1, COR_PRF_GC_GEN_2 = 2, COR_PRF_GC_LARGE_OBJECT_HEAP = 3, COR_PRF_GC_PINNED_OBJECT_HEAP = 4 } COR_PRF_GC_GENERATION; typedef struct COR_PRF_GC_GENERATION_RANGE { COR_PRF_GC_GENERATION generation; ObjectID rangeStart; UINT_PTR rangeLength; UINT_PTR rangeLengthReserved; } COR_PRF_GC_GENERATION_RANGE; typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0005 { COR_PRF_CLAUSE_NONE = 0, COR_PRF_CLAUSE_FILTER = 1, COR_PRF_CLAUSE_CATCH = 2, COR_PRF_CLAUSE_FINALLY = 3 } COR_PRF_CLAUSE_TYPE; typedef struct COR_PRF_EX_CLAUSE_INFO { COR_PRF_CLAUSE_TYPE clauseType; UINT_PTR programCounter; UINT_PTR framePointer; UINT_PTR shadowStackPointer; } COR_PRF_EX_CLAUSE_INFO; typedef /* [public][public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0006 { COR_PRF_GC_INDUCED = 1, COR_PRF_GC_OTHER = 0 } COR_PRF_GC_REASON; typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0001_0007 { COR_PRF_MODULE_DISK = 0x1, COR_PRF_MODULE_NGEN = 0x2, COR_PRF_MODULE_DYNAMIC = 0x4, COR_PRF_MODULE_COLLECTIBLE = 0x8, COR_PRF_MODULE_RESOURCE = 0x10, COR_PRF_MODULE_FLAT_LAYOUT = 0x20, COR_PRF_MODULE_WINDOWS_RUNTIME = 0x40 } COR_PRF_MODULE_FLAGS; extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0001_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0001_v0_0_s_ifspec; #ifndef __ICorProfilerCallback2_INTERFACE_DEFINED__ #define __ICorProfilerCallback2_INTERFACE_DEFINED__ /* interface ICorProfilerCallback2 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("8A8CC829-CCF2-49fe-BBAE-0F022228071A") ICorProfilerCallback2 : public ICorProfilerCallback { public: virtual HRESULT STDMETHODCALLTYPE ThreadNameChanged( /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GarbageCollectionStarted( /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason) = 0; virtual HRESULT STDMETHODCALLTYPE SurvivingReferences( /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GarbageCollectionFinished( void) = 0; virtual HRESULT STDMETHODCALLTYPE FinalizeableObjectQueued( /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID) = 0; virtual HRESULT STDMETHODCALLTYPE RootReferences2( /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE HandleCreated( /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId) = 0; virtual HRESULT STDMETHODCALLTYPE HandleDestroyed( /* [in] */ GCHandleID handleId) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback2 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback2 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback2 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback2 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback2 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback2 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback2 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback2 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback2 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback2 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback2 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback2 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback2 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback2 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback2 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback2 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback2 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback2 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback2 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback2 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback2 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback2 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback2 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback2 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback2 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback2 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback2 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback2 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback2 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback2 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback2 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback2 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback2 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback2 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback2 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback2 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback2 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback2 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback2 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback2 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback2 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback2 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback2 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback2 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback2 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback2 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback2 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback2 * This, /* [in] */ GCHandleID handleId); END_INTERFACE } ICorProfilerCallback2Vtbl; interface ICorProfilerCallback2 { CONST_VTBL struct ICorProfilerCallback2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback2_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback2_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback2_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback2_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback2_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback2_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback2_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback2_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback2_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback2_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback2_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback2_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback2_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback2_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback2_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback2_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback2_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback2_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback2_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback2_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback2_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback2_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback2_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback2_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback2_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback2_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback2_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback2_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback2_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback2_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback2_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback2_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback2_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback2_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback2_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback2_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback2_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback2_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback2_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback2_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback2_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback2_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback2_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback2_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback2_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback2_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback2_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback2_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback2_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback2_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback2_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback2_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback2_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback2_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback2_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback2_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback2_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback2_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback2_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback2_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback2_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback2_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback2_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback2_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback2_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback2_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback2_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback2_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback2_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback2_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback2_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback2_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback2_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback2_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback2_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback2_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback2_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback2_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback3_INTERFACE_DEFINED__ #define __ICorProfilerCallback3_INTERFACE_DEFINED__ /* interface ICorProfilerCallback3 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("4FD2ED52-7731-4b8d-9469-03D2CC3086C5") ICorProfilerCallback3 : public ICorProfilerCallback2 { public: virtual HRESULT STDMETHODCALLTYPE InitializeForAttach( /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData) = 0; virtual HRESULT STDMETHODCALLTYPE ProfilerAttachComplete( void) = 0; virtual HRESULT STDMETHODCALLTYPE ProfilerDetachSucceeded( void) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback3 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback3 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback3 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback3 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback3 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback3 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback3 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback3 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback3 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback3 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback3 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback3 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback3 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback3 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback3 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback3 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback3 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback3 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback3 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback3 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback3 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback3 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback3 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback3 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback3 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback3 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback3 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback3 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback3 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback3 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback3 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback3 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback3 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback3 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback3 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback3 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback3 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback3 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback3 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback3 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback3 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback3 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback3 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback3 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback3 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback3 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback3 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback3 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback3 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback3 * This); END_INTERFACE } ICorProfilerCallback3Vtbl; interface ICorProfilerCallback3 { CONST_VTBL struct ICorProfilerCallback3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback3_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback3_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback3_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback3_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback3_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback3_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback3_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback3_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback3_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback3_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback3_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback3_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback3_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback3_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback3_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback3_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback3_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback3_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback3_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback3_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback3_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback3_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback3_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback3_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback3_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback3_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback3_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback3_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback3_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback3_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback3_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback3_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback3_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback3_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback3_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback3_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback3_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback3_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback3_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback3_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback3_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback3_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback3_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback3_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback3_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback3_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback3_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback3_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback3_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback3_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback3_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback3_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback3_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback3_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback3_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback3_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback3_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback3_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback3_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback3_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback3_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback3_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback3_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback3_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback3_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback3_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback3_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback3_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback3_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback3_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback3_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback3_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback3_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback3_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback3_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback3_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback3_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback3_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback3_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback3_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback3_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback4_INTERFACE_DEFINED__ #define __ICorProfilerCallback4_INTERFACE_DEFINED__ /* interface ICorProfilerCallback4 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("7B63B2E3-107D-4d48-B2F6-F61E229470D2") ICorProfilerCallback4 : public ICorProfilerCallback3 { public: virtual HRESULT STDMETHODCALLTYPE ReJITCompilationStarted( /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock) = 0; virtual HRESULT STDMETHODCALLTYPE GetReJITParameters( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl) = 0; virtual HRESULT STDMETHODCALLTYPE ReJITCompilationFinished( /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock) = 0; virtual HRESULT STDMETHODCALLTYPE ReJITError( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus) = 0; virtual HRESULT STDMETHODCALLTYPE MovedReferences2( /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SurvivingReferences2( /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback4 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback4 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback4 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback4 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback4 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback4 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback4 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback4 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback4 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback4 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback4 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback4 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback4 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback4 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback4 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback4 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback4 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback4 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback4 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback4 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback4 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback4 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback4 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback4 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback4 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback4 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback4 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback4 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback4 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback4 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback4 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback4 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback4 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback4 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback4 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback4 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback4 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback4 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback4 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback4 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback4 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback4 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback4 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback4 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback4 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback4 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback4 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); END_INTERFACE } ICorProfilerCallback4Vtbl; interface ICorProfilerCallback4 { CONST_VTBL struct ICorProfilerCallback4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback4_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback4_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback4_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback4_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback4_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback4_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback4_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback4_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback4_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback4_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback4_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback4_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback4_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback4_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback4_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback4_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback4_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback4_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback4_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback4_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback4_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback4_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback4_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback4_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback4_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback4_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback4_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback4_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback4_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback4_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback4_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback4_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback4_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback4_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback4_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback4_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback4_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback4_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback4_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback4_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback4_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback4_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback4_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback4_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback4_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback4_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback4_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback4_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback4_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback4_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback4_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback4_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback4_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback4_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback4_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback4_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback4_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback4_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback4_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback4_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback4_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback4_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback4_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback4_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback4_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback4_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback4_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback4_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback4_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback4_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback4_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback4_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback4_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback4_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback4_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback4_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback4_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback4_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback4_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback4_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback4_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback4_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback4_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback4_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback4_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback4_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback4_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback5_INTERFACE_DEFINED__ #define __ICorProfilerCallback5_INTERFACE_DEFINED__ /* interface ICorProfilerCallback5 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("8DFBA405-8C9F-45F8-BFFA-83B14CEF78B5") ICorProfilerCallback5 : public ICorProfilerCallback4 { public: virtual HRESULT STDMETHODCALLTYPE ConditionalWeakTableElementReferences( /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback5 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback5 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback5 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback5 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback5 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback5 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback5 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback5 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback5 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback5 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback5 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback5 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback5 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback5 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback5 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback5 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback5 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback5 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback5 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback5 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback5 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback5 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback5 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback5 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback5 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback5 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback5 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback5 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback5 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback5 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback5 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback5 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback5 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback5 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback5 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback5 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback5 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback5 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback5 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback5 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback5 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback5 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback5 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback5 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback5 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback5 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback5 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback5 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); END_INTERFACE } ICorProfilerCallback5Vtbl; interface ICorProfilerCallback5 { CONST_VTBL struct ICorProfilerCallback5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback5_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback5_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback5_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback5_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback5_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback5_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback5_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback5_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback5_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback5_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback5_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback5_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback5_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback5_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback5_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback5_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback5_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback5_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback5_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback5_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback5_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback5_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback5_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback5_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback5_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback5_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback5_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback5_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback5_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback5_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback5_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback5_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback5_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback5_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback5_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback5_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback5_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback5_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback5_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback5_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback5_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback5_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback5_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback5_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback5_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback5_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback5_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback5_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback5_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback5_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback5_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback5_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback5_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback5_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback5_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback5_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback5_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback5_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback5_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback5_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback5_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback5_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback5_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback5_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback5_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback5_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback5_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback5_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback5_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback5_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback5_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback5_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback5_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback5_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback5_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback5_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback5_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback5_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback5_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback5_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback5_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback5_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback5_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback5_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback5_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback5_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback5_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback5_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback6_INTERFACE_DEFINED__ #define __ICorProfilerCallback6_INTERFACE_DEFINED__ /* interface ICorProfilerCallback6 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback6; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FC13DF4B-4448-4F4F-950C-BA8D19D00C36") ICorProfilerCallback6 : public ICorProfilerCallback5 { public: virtual HRESULT STDMETHODCALLTYPE GetAssemblyReferences( /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback6Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback6 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback6 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback6 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback6 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback6 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback6 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback6 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback6 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback6 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback6 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback6 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback6 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback6 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback6 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback6 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback6 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback6 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback6 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback6 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback6 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback6 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback6 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback6 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback6 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback6 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback6 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback6 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback6 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback6 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback6 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback6 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback6 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback6 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback6 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback6 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback6 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback6 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback6 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback6 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback6 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback6 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback6 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback6 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback6 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback6 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback6 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback6 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback6 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback6 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( ICorProfilerCallback6 * This, /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); END_INTERFACE } ICorProfilerCallback6Vtbl; interface ICorProfilerCallback6 { CONST_VTBL struct ICorProfilerCallback6Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback6_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback6_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback6_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback6_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback6_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback6_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback6_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback6_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback6_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback6_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback6_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback6_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback6_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback6_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback6_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback6_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback6_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback6_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback6_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback6_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback6_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback6_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback6_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback6_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback6_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback6_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback6_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback6_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback6_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback6_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback6_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback6_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback6_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback6_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback6_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback6_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback6_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback6_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback6_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback6_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback6_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback6_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback6_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback6_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback6_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback6_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback6_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback6_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback6_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback6_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback6_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback6_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback6_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback6_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback6_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback6_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback6_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback6_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback6_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback6_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback6_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback6_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback6_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback6_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback6_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback6_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback6_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback6_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback6_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback6_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback6_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback6_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback6_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback6_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback6_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback6_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback6_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback6_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback6_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback6_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback6_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback6_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback6_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback6_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback6_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback6_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback6_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback6_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback6_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback6_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #define ICorProfilerCallback6_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback6_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback7_INTERFACE_DEFINED__ #define __ICorProfilerCallback7_INTERFACE_DEFINED__ /* interface ICorProfilerCallback7 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback7; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F76A2DBA-1D52-4539-866C-2AA518F9EFC3") ICorProfilerCallback7 : public ICorProfilerCallback6 { public: virtual HRESULT STDMETHODCALLTYPE ModuleInMemorySymbolsUpdated( ModuleID moduleId) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback7Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback7 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback7 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback7 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback7 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback7 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback7 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback7 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback7 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback7 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback7 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback7 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback7 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback7 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback7 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback7 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback7 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback7 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback7 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback7 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback7 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback7 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback7 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback7 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback7 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback7 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback7 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback7 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback7 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback7 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback7 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback7 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback7 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback7 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback7 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback7 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback7 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback7 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback7 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback7 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback7 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback7 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback7 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback7 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback7 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback7 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback7 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback7 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback7 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback7 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( ICorProfilerCallback7 * This, /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( ICorProfilerCallback7 * This, ModuleID moduleId); END_INTERFACE } ICorProfilerCallback7Vtbl; interface ICorProfilerCallback7 { CONST_VTBL struct ICorProfilerCallback7Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback7_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback7_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback7_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback7_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback7_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback7_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback7_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback7_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback7_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback7_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback7_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback7_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback7_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback7_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback7_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback7_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback7_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback7_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback7_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback7_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback7_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback7_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback7_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback7_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback7_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback7_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback7_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback7_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback7_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback7_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback7_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback7_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback7_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback7_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback7_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback7_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback7_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback7_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback7_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback7_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback7_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback7_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback7_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback7_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback7_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback7_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback7_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback7_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback7_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback7_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback7_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback7_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback7_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback7_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback7_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback7_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback7_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback7_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback7_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback7_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback7_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback7_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback7_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback7_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback7_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback7_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback7_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback7_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback7_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback7_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback7_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback7_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback7_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback7_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback7_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback7_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback7_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback7_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback7_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback7_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback7_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback7_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback7_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback7_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback7_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback7_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback7_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback7_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback7_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback7_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #define ICorProfilerCallback7_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) #define ICorProfilerCallback7_ModuleInMemorySymbolsUpdated(This,moduleId) \ ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback7_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback8_INTERFACE_DEFINED__ #define __ICorProfilerCallback8_INTERFACE_DEFINED__ /* interface ICorProfilerCallback8 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback8; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5BED9B15-C079-4D47-BFE2-215A140C07E0") ICorProfilerCallback8 : public ICorProfilerCallback7 { public: virtual HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationStarted( /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock, /* [in] */ LPCBYTE pILHeader, /* [in] */ ULONG cbILHeader) = 0; virtual HRESULT STDMETHODCALLTYPE DynamicMethodJITCompilationFinished( /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback8Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback8 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback8 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback8 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback8 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback8 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback8 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback8 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback8 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback8 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback8 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback8 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback8 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback8 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback8 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback8 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback8 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback8 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback8 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback8 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback8 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback8 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback8 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback8 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback8 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback8 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback8 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback8 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback8 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback8 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback8 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback8 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback8 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback8 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback8 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback8 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback8 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback8 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback8 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback8 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback8 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback8 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback8 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback8 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback8 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback8 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback8 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback8 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback8 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( ICorProfilerCallback8 * This, /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( ICorProfilerCallback8 * This, ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock, /* [in] */ LPCBYTE pILHeader, /* [in] */ ULONG cbILHeader); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( ICorProfilerCallback8 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); END_INTERFACE } ICorProfilerCallback8Vtbl; interface ICorProfilerCallback8 { CONST_VTBL struct ICorProfilerCallback8Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback8_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback8_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback8_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback8_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback8_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback8_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback8_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback8_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback8_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback8_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback8_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback8_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback8_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback8_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback8_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback8_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback8_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback8_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback8_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback8_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback8_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback8_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback8_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback8_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback8_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback8_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback8_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback8_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback8_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback8_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback8_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback8_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback8_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback8_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback8_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback8_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback8_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback8_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback8_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback8_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback8_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback8_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback8_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback8_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback8_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback8_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback8_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback8_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback8_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback8_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback8_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback8_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback8_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback8_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback8_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback8_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback8_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback8_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback8_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback8_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback8_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback8_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback8_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback8_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback8_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback8_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback8_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback8_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback8_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback8_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback8_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback8_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback8_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback8_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback8_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback8_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback8_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback8_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback8_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback8_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback8_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback8_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback8_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback8_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback8_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback8_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback8_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback8_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback8_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback8_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #define ICorProfilerCallback8_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) #define ICorProfilerCallback8_ModuleInMemorySymbolsUpdated(This,moduleId) \ ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) #define ICorProfilerCallback8_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) #define ICorProfilerCallback8_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback8_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback9_INTERFACE_DEFINED__ #define __ICorProfilerCallback9_INTERFACE_DEFINED__ /* interface ICorProfilerCallback9 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback9; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("27583EC3-C8F5-482F-8052-194B8CE4705A") ICorProfilerCallback9 : public ICorProfilerCallback8 { public: virtual HRESULT STDMETHODCALLTYPE DynamicMethodUnloaded( /* [in] */ FunctionID functionId) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback9Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback9 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback9 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback9 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback9 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback9 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback9 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback9 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback9 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback9 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback9 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback9 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback9 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback9 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback9 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback9 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback9 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback9 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback9 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback9 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback9 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback9 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback9 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback9 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback9 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback9 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback9 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback9 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback9 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback9 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback9 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback9 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback9 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback9 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback9 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback9 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback9 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback9 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback9 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback9 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback9 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback9 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback9 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback9 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback9 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback9 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback9 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback9 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback9 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback9 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( ICorProfilerCallback9 * This, /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( ICorProfilerCallback9 * This, ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock, /* [in] */ LPCBYTE pILHeader, /* [in] */ ULONG cbILHeader); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *DynamicMethodUnloaded )( ICorProfilerCallback9 * This, /* [in] */ FunctionID functionId); END_INTERFACE } ICorProfilerCallback9Vtbl; interface ICorProfilerCallback9 { CONST_VTBL struct ICorProfilerCallback9Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback9_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback9_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback9_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback9_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback9_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback9_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback9_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback9_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback9_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback9_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback9_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback9_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback9_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback9_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback9_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback9_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback9_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback9_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback9_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback9_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback9_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback9_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback9_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback9_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback9_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback9_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback9_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback9_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback9_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback9_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback9_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback9_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback9_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback9_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback9_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback9_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback9_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback9_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback9_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback9_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback9_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback9_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback9_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback9_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback9_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback9_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback9_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback9_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback9_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback9_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback9_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback9_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback9_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback9_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback9_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback9_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback9_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback9_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback9_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback9_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback9_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback9_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback9_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback9_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback9_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback9_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback9_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback9_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback9_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback9_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback9_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback9_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback9_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback9_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback9_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback9_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback9_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback9_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback9_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback9_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback9_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback9_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback9_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback9_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback9_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback9_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback9_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback9_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback9_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback9_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #define ICorProfilerCallback9_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) #define ICorProfilerCallback9_ModuleInMemorySymbolsUpdated(This,moduleId) \ ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) #define ICorProfilerCallback9_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) #define ICorProfilerCallback9_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback9_DynamicMethodUnloaded(This,functionId) \ ( (This)->lpVtbl -> DynamicMethodUnloaded(This,functionId) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback9_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback10_INTERFACE_DEFINED__ #define __ICorProfilerCallback10_INTERFACE_DEFINED__ /* interface ICorProfilerCallback10 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback10; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CEC5B60E-C69C-495F-87F6-84D28EE16FFB") ICorProfilerCallback10 : public ICorProfilerCallback9 { public: virtual HRESULT STDMETHODCALLTYPE EventPipeEventDelivered( /* [in] */ EVENTPIPE_PROVIDER provider, /* [in] */ DWORD eventId, /* [in] */ DWORD eventVersion, /* [in] */ ULONG cbMetadataBlob, /* [size_is][in] */ LPCBYTE metadataBlob, /* [in] */ ULONG cbEventData, /* [size_is][in] */ LPCBYTE eventData, /* [in] */ LPCGUID pActivityId, /* [in] */ LPCGUID pRelatedActivityId, /* [in] */ ThreadID eventThread, /* [in] */ ULONG numStackFrames, /* [length_is][in] */ UINT_PTR stackFrames[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeProviderCreated( /* [in] */ EVENTPIPE_PROVIDER provider) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback10Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback10 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback10 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback10 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback10 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback10 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback10 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback10 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback10 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback10 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback10 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback10 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback10 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback10 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback10 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback10 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback10 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback10 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback10 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback10 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback10 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback10 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback10 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback10 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback10 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback10 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback10 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback10 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback10 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback10 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback10 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback10 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback10 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback10 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback10 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback10 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback10 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback10 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback10 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback10 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback10 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback10 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback10 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback10 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback10 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback10 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback10 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback10 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback10 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback10 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( ICorProfilerCallback10 * This, /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( ICorProfilerCallback10 * This, ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock, /* [in] */ LPCBYTE pILHeader, /* [in] */ ULONG cbILHeader); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *DynamicMethodUnloaded )( ICorProfilerCallback10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *EventPipeEventDelivered )( ICorProfilerCallback10 * This, /* [in] */ EVENTPIPE_PROVIDER provider, /* [in] */ DWORD eventId, /* [in] */ DWORD eventVersion, /* [in] */ ULONG cbMetadataBlob, /* [size_is][in] */ LPCBYTE metadataBlob, /* [in] */ ULONG cbEventData, /* [size_is][in] */ LPCBYTE eventData, /* [in] */ LPCGUID pActivityId, /* [in] */ LPCGUID pRelatedActivityId, /* [in] */ ThreadID eventThread, /* [in] */ ULONG numStackFrames, /* [length_is][in] */ UINT_PTR stackFrames[ ]); HRESULT ( STDMETHODCALLTYPE *EventPipeProviderCreated )( ICorProfilerCallback10 * This, /* [in] */ EVENTPIPE_PROVIDER provider); END_INTERFACE } ICorProfilerCallback10Vtbl; interface ICorProfilerCallback10 { CONST_VTBL struct ICorProfilerCallback10Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback10_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback10_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback10_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback10_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback10_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback10_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback10_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback10_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback10_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback10_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback10_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback10_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback10_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback10_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback10_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback10_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback10_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback10_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback10_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback10_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback10_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback10_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback10_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback10_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback10_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback10_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback10_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback10_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback10_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback10_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback10_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback10_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback10_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback10_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback10_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback10_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback10_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback10_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback10_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback10_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback10_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback10_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback10_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback10_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback10_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback10_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback10_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback10_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback10_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback10_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback10_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback10_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback10_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback10_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback10_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback10_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback10_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback10_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback10_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback10_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback10_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback10_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback10_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback10_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback10_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback10_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback10_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback10_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback10_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback10_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback10_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback10_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback10_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback10_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback10_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback10_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback10_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback10_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback10_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback10_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback10_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback10_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback10_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback10_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback10_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback10_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback10_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback10_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback10_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback10_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #define ICorProfilerCallback10_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) #define ICorProfilerCallback10_ModuleInMemorySymbolsUpdated(This,moduleId) \ ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) #define ICorProfilerCallback10_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) #define ICorProfilerCallback10_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback10_DynamicMethodUnloaded(This,functionId) \ ( (This)->lpVtbl -> DynamicMethodUnloaded(This,functionId) ) #define ICorProfilerCallback10_EventPipeEventDelivered(This,provider,eventId,eventVersion,cbMetadataBlob,metadataBlob,cbEventData,eventData,pActivityId,pRelatedActivityId,eventThread,numStackFrames,stackFrames) \ ( (This)->lpVtbl -> EventPipeEventDelivered(This,provider,eventId,eventVersion,cbMetadataBlob,metadataBlob,cbEventData,eventData,pActivityId,pRelatedActivityId,eventThread,numStackFrames,stackFrames) ) #define ICorProfilerCallback10_EventPipeProviderCreated(This,provider) \ ( (This)->lpVtbl -> EventPipeProviderCreated(This,provider) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback10_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerCallback11_INTERFACE_DEFINED__ #define __ICorProfilerCallback11_INTERFACE_DEFINED__ /* interface ICorProfilerCallback11 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerCallback11; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("42350846-AAED-47F7-B128-FD0C98881CDE") ICorProfilerCallback11 : public ICorProfilerCallback10 { public: virtual HRESULT STDMETHODCALLTYPE LoadAsNotificationOnly( BOOL *pbNotificationOnly) = 0; }; #else /* C style interface */ typedef struct ICorProfilerCallback11Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerCallback11 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerCallback11 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *Initialize )( ICorProfilerCallback11 * This, /* [in] */ IUnknown *pICorProfilerInfoUnk); HRESULT ( STDMETHODCALLTYPE *Shutdown )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationStarted )( ICorProfilerCallback11 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainCreationFinished )( ICorProfilerCallback11 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownStarted )( ICorProfilerCallback11 * This, /* [in] */ AppDomainID appDomainId); HRESULT ( STDMETHODCALLTYPE *AppDomainShutdownFinished )( ICorProfilerCallback11 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadStarted )( ICorProfilerCallback11 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyLoadFinished )( ICorProfilerCallback11 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadStarted )( ICorProfilerCallback11 * This, /* [in] */ AssemblyID assemblyId); HRESULT ( STDMETHODCALLTYPE *AssemblyUnloadFinished )( ICorProfilerCallback11 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleLoadStarted )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleLoadFinished )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadStarted )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *ModuleUnloadFinished )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ModuleAttachedToAssembly )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId, /* [in] */ AssemblyID AssemblyId); HRESULT ( STDMETHODCALLTYPE *ClassLoadStarted )( ICorProfilerCallback11 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassLoadFinished )( ICorProfilerCallback11 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *ClassUnloadStarted )( ICorProfilerCallback11 * This, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ClassUnloadFinished )( ICorProfilerCallback11 * This, /* [in] */ ClassID classId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *FunctionUnloadStarted )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITCompilationStarted )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCompilationFinished )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchStarted )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *pbUseCachedFunction); HRESULT ( STDMETHODCALLTYPE *JITCachedFunctionSearchFinished )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_JIT_CACHE result); HRESULT ( STDMETHODCALLTYPE *JITFunctionPitched )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *JITInlining )( ICorProfilerCallback11 * This, /* [in] */ FunctionID callerId, /* [in] */ FunctionID calleeId, /* [out] */ BOOL *pfShouldInline); HRESULT ( STDMETHODCALLTYPE *ThreadCreated )( ICorProfilerCallback11 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadDestroyed )( ICorProfilerCallback11 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *ThreadAssignedToOSThread )( ICorProfilerCallback11 * This, /* [in] */ ThreadID managedThreadId, /* [in] */ DWORD osThreadId); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationStarted )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RemotingClientSendingMessage )( ICorProfilerCallback11 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientReceivingReply )( ICorProfilerCallback11 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingClientInvocationFinished )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerReceivingMessage )( ICorProfilerCallback11 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationStarted )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerInvocationReturned )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RemotingServerSendingReply )( ICorProfilerCallback11 * This, /* [in] */ GUID *pCookie, /* [in] */ BOOL fIsAsync); HRESULT ( STDMETHODCALLTYPE *UnmanagedToManagedTransition )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *ManagedToUnmanagedTransition )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_TRANSITION_REASON reason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendStarted )( ICorProfilerCallback11 * This, /* [in] */ COR_PRF_SUSPEND_REASON suspendReason); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendFinished )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeSuspendAborted )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeStarted )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeResumeFinished )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadSuspended )( ICorProfilerCallback11 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *RuntimeThreadResumed )( ICorProfilerCallback11 * This, /* [in] */ ThreadID threadId); HRESULT ( STDMETHODCALLTYPE *MovedReferences )( ICorProfilerCallback11 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectAllocated )( ICorProfilerCallback11 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId); HRESULT ( STDMETHODCALLTYPE *ObjectsAllocatedByClass )( ICorProfilerCallback11 * This, /* [in] */ ULONG cClassCount, /* [size_is][in] */ ClassID classIds[ ], /* [size_is][in] */ ULONG cObjects[ ]); HRESULT ( STDMETHODCALLTYPE *ObjectReferences )( ICorProfilerCallback11 * This, /* [in] */ ObjectID objectId, /* [in] */ ClassID classId, /* [in] */ ULONG cObjectRefs, /* [size_is][in] */ ObjectID objectRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *RootReferences )( ICorProfilerCallback11 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ]); HRESULT ( STDMETHODCALLTYPE *ExceptionThrown )( ICorProfilerCallback11 * This, /* [in] */ ObjectID thrownObjectId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionEnter )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFunctionLeave )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterEnter )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchFilterLeave )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionSearchCatcherFound )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerEnter )( ICorProfilerCallback11 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionOSHandlerLeave )( ICorProfilerCallback11 * This, /* [in] */ UINT_PTR __unused); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionEnter )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFunctionLeave )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyEnter )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ExceptionUnwindFinallyLeave )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ ObjectID objectId); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherLeave )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableCreated )( ICorProfilerCallback11 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable, /* [in] */ ULONG cSlots); HRESULT ( STDMETHODCALLTYPE *COMClassicVTableDestroyed )( ICorProfilerCallback11 * This, /* [in] */ ClassID wrappedClassId, /* [in] */ REFGUID implementedIID, /* [in] */ void *pVTable); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherFound )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ExceptionCLRCatcherExecute )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ThreadNameChanged )( ICorProfilerCallback11 * This, /* [in] */ ThreadID threadId, /* [in] */ ULONG cchName, /* [annotation][in] */ _In_reads_opt_(cchName) WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionStarted )( ICorProfilerCallback11 * This, /* [in] */ int cGenerations, /* [size_is][in] */ BOOL generationCollected[ ], /* [in] */ COR_PRF_GC_REASON reason); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences )( ICorProfilerCallback11 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ ULONG cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *GarbageCollectionFinished )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *FinalizeableObjectQueued )( ICorProfilerCallback11 * This, /* [in] */ DWORD finalizerFlags, /* [in] */ ObjectID objectID); HRESULT ( STDMETHODCALLTYPE *RootReferences2 )( ICorProfilerCallback11 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID rootRefIds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_KIND rootKinds[ ], /* [size_is][in] */ COR_PRF_GC_ROOT_FLAGS rootFlags[ ], /* [size_is][in] */ UINT_PTR rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *HandleCreated )( ICorProfilerCallback11 * This, /* [in] */ GCHandleID handleId, /* [in] */ ObjectID initialObjectId); HRESULT ( STDMETHODCALLTYPE *HandleDestroyed )( ICorProfilerCallback11 * This, /* [in] */ GCHandleID handleId); HRESULT ( STDMETHODCALLTYPE *InitializeForAttach )( ICorProfilerCallback11 * This, /* [in] */ IUnknown *pCorProfilerInfoUnk, /* [in] */ void *pvClientData, /* [in] */ UINT cbClientData); HRESULT ( STDMETHODCALLTYPE *ProfilerAttachComplete )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ProfilerDetachSucceeded )( ICorProfilerCallback11 * This); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationStarted )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *GetReJITParameters )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ ICorProfilerFunctionControl *pFunctionControl); HRESULT ( STDMETHODCALLTYPE *ReJITCompilationFinished )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID rejitId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *ReJITError )( ICorProfilerCallback11 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus); HRESULT ( STDMETHODCALLTYPE *MovedReferences2 )( ICorProfilerCallback11 * This, /* [in] */ ULONG cMovedObjectIDRanges, /* [size_is][in] */ ObjectID oldObjectIDRangeStart[ ], /* [size_is][in] */ ObjectID newObjectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *SurvivingReferences2 )( ICorProfilerCallback11 * This, /* [in] */ ULONG cSurvivingObjectIDRanges, /* [size_is][in] */ ObjectID objectIDRangeStart[ ], /* [size_is][in] */ SIZE_T cObjectIDRangeLength[ ]); HRESULT ( STDMETHODCALLTYPE *ConditionalWeakTableElementReferences )( ICorProfilerCallback11 * This, /* [in] */ ULONG cRootRefs, /* [size_is][in] */ ObjectID keyRefIds[ ], /* [size_is][in] */ ObjectID valueRefIds[ ], /* [size_is][in] */ GCHandleID rootIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssemblyReferences )( ICorProfilerCallback11 * This, /* [string][in] */ const WCHAR *wszAssemblyPath, /* [in] */ ICorProfilerAssemblyReferenceProvider *pAsmRefProvider); HRESULT ( STDMETHODCALLTYPE *ModuleInMemorySymbolsUpdated )( ICorProfilerCallback11 * This, ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationStarted )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fIsSafeToBlock, /* [in] */ LPCBYTE pILHeader, /* [in] */ ULONG cbILHeader); HRESULT ( STDMETHODCALLTYPE *DynamicMethodJITCompilationFinished )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId, /* [in] */ HRESULT hrStatus, /* [in] */ BOOL fIsSafeToBlock); HRESULT ( STDMETHODCALLTYPE *DynamicMethodUnloaded )( ICorProfilerCallback11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *EventPipeEventDelivered )( ICorProfilerCallback11 * This, /* [in] */ EVENTPIPE_PROVIDER provider, /* [in] */ DWORD eventId, /* [in] */ DWORD eventVersion, /* [in] */ ULONG cbMetadataBlob, /* [size_is][in] */ LPCBYTE metadataBlob, /* [in] */ ULONG cbEventData, /* [size_is][in] */ LPCBYTE eventData, /* [in] */ LPCGUID pActivityId, /* [in] */ LPCGUID pRelatedActivityId, /* [in] */ ThreadID eventThread, /* [in] */ ULONG numStackFrames, /* [length_is][in] */ UINT_PTR stackFrames[ ]); HRESULT ( STDMETHODCALLTYPE *EventPipeProviderCreated )( ICorProfilerCallback11 * This, /* [in] */ EVENTPIPE_PROVIDER provider); HRESULT ( STDMETHODCALLTYPE *LoadAsNotificationOnly )( ICorProfilerCallback11 * This, BOOL *pbNotificationOnly); END_INTERFACE } ICorProfilerCallback11Vtbl; interface ICorProfilerCallback11 { CONST_VTBL struct ICorProfilerCallback11Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerCallback11_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerCallback11_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerCallback11_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerCallback11_Initialize(This,pICorProfilerInfoUnk) \ ( (This)->lpVtbl -> Initialize(This,pICorProfilerInfoUnk) ) #define ICorProfilerCallback11_Shutdown(This) \ ( (This)->lpVtbl -> Shutdown(This) ) #define ICorProfilerCallback11_AppDomainCreationStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainCreationStarted(This,appDomainId) ) #define ICorProfilerCallback11_AppDomainCreationFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainCreationFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback11_AppDomainShutdownStarted(This,appDomainId) \ ( (This)->lpVtbl -> AppDomainShutdownStarted(This,appDomainId) ) #define ICorProfilerCallback11_AppDomainShutdownFinished(This,appDomainId,hrStatus) \ ( (This)->lpVtbl -> AppDomainShutdownFinished(This,appDomainId,hrStatus) ) #define ICorProfilerCallback11_AssemblyLoadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyLoadStarted(This,assemblyId) ) #define ICorProfilerCallback11_AssemblyLoadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyLoadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback11_AssemblyUnloadStarted(This,assemblyId) \ ( (This)->lpVtbl -> AssemblyUnloadStarted(This,assemblyId) ) #define ICorProfilerCallback11_AssemblyUnloadFinished(This,assemblyId,hrStatus) \ ( (This)->lpVtbl -> AssemblyUnloadFinished(This,assemblyId,hrStatus) ) #define ICorProfilerCallback11_ModuleLoadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleLoadStarted(This,moduleId) ) #define ICorProfilerCallback11_ModuleLoadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleLoadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback11_ModuleUnloadStarted(This,moduleId) \ ( (This)->lpVtbl -> ModuleUnloadStarted(This,moduleId) ) #define ICorProfilerCallback11_ModuleUnloadFinished(This,moduleId,hrStatus) \ ( (This)->lpVtbl -> ModuleUnloadFinished(This,moduleId,hrStatus) ) #define ICorProfilerCallback11_ModuleAttachedToAssembly(This,moduleId,AssemblyId) \ ( (This)->lpVtbl -> ModuleAttachedToAssembly(This,moduleId,AssemblyId) ) #define ICorProfilerCallback11_ClassLoadStarted(This,classId) \ ( (This)->lpVtbl -> ClassLoadStarted(This,classId) ) #define ICorProfilerCallback11_ClassLoadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassLoadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback11_ClassUnloadStarted(This,classId) \ ( (This)->lpVtbl -> ClassUnloadStarted(This,classId) ) #define ICorProfilerCallback11_ClassUnloadFinished(This,classId,hrStatus) \ ( (This)->lpVtbl -> ClassUnloadFinished(This,classId,hrStatus) ) #define ICorProfilerCallback11_FunctionUnloadStarted(This,functionId) \ ( (This)->lpVtbl -> FunctionUnloadStarted(This,functionId) ) #define ICorProfilerCallback11_JITCompilationStarted(This,functionId,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationStarted(This,functionId,fIsSafeToBlock) ) #define ICorProfilerCallback11_JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> JITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback11_JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) \ ( (This)->lpVtbl -> JITCachedFunctionSearchStarted(This,functionId,pbUseCachedFunction) ) #define ICorProfilerCallback11_JITCachedFunctionSearchFinished(This,functionId,result) \ ( (This)->lpVtbl -> JITCachedFunctionSearchFinished(This,functionId,result) ) #define ICorProfilerCallback11_JITFunctionPitched(This,functionId) \ ( (This)->lpVtbl -> JITFunctionPitched(This,functionId) ) #define ICorProfilerCallback11_JITInlining(This,callerId,calleeId,pfShouldInline) \ ( (This)->lpVtbl -> JITInlining(This,callerId,calleeId,pfShouldInline) ) #define ICorProfilerCallback11_ThreadCreated(This,threadId) \ ( (This)->lpVtbl -> ThreadCreated(This,threadId) ) #define ICorProfilerCallback11_ThreadDestroyed(This,threadId) \ ( (This)->lpVtbl -> ThreadDestroyed(This,threadId) ) #define ICorProfilerCallback11_ThreadAssignedToOSThread(This,managedThreadId,osThreadId) \ ( (This)->lpVtbl -> ThreadAssignedToOSThread(This,managedThreadId,osThreadId) ) #define ICorProfilerCallback11_RemotingClientInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingClientInvocationStarted(This) ) #define ICorProfilerCallback11_RemotingClientSendingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientSendingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback11_RemotingClientReceivingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingClientReceivingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback11_RemotingClientInvocationFinished(This) \ ( (This)->lpVtbl -> RemotingClientInvocationFinished(This) ) #define ICorProfilerCallback11_RemotingServerReceivingMessage(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerReceivingMessage(This,pCookie,fIsAsync) ) #define ICorProfilerCallback11_RemotingServerInvocationStarted(This) \ ( (This)->lpVtbl -> RemotingServerInvocationStarted(This) ) #define ICorProfilerCallback11_RemotingServerInvocationReturned(This) \ ( (This)->lpVtbl -> RemotingServerInvocationReturned(This) ) #define ICorProfilerCallback11_RemotingServerSendingReply(This,pCookie,fIsAsync) \ ( (This)->lpVtbl -> RemotingServerSendingReply(This,pCookie,fIsAsync) ) #define ICorProfilerCallback11_UnmanagedToManagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> UnmanagedToManagedTransition(This,functionId,reason) ) #define ICorProfilerCallback11_ManagedToUnmanagedTransition(This,functionId,reason) \ ( (This)->lpVtbl -> ManagedToUnmanagedTransition(This,functionId,reason) ) #define ICorProfilerCallback11_RuntimeSuspendStarted(This,suspendReason) \ ( (This)->lpVtbl -> RuntimeSuspendStarted(This,suspendReason) ) #define ICorProfilerCallback11_RuntimeSuspendFinished(This) \ ( (This)->lpVtbl -> RuntimeSuspendFinished(This) ) #define ICorProfilerCallback11_RuntimeSuspendAborted(This) \ ( (This)->lpVtbl -> RuntimeSuspendAborted(This) ) #define ICorProfilerCallback11_RuntimeResumeStarted(This) \ ( (This)->lpVtbl -> RuntimeResumeStarted(This) ) #define ICorProfilerCallback11_RuntimeResumeFinished(This) \ ( (This)->lpVtbl -> RuntimeResumeFinished(This) ) #define ICorProfilerCallback11_RuntimeThreadSuspended(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadSuspended(This,threadId) ) #define ICorProfilerCallback11_RuntimeThreadResumed(This,threadId) \ ( (This)->lpVtbl -> RuntimeThreadResumed(This,threadId) ) #define ICorProfilerCallback11_MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback11_ObjectAllocated(This,objectId,classId) \ ( (This)->lpVtbl -> ObjectAllocated(This,objectId,classId) ) #define ICorProfilerCallback11_ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) \ ( (This)->lpVtbl -> ObjectsAllocatedByClass(This,cClassCount,classIds,cObjects) ) #define ICorProfilerCallback11_ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) \ ( (This)->lpVtbl -> ObjectReferences(This,objectId,classId,cObjectRefs,objectRefIds) ) #define ICorProfilerCallback11_RootReferences(This,cRootRefs,rootRefIds) \ ( (This)->lpVtbl -> RootReferences(This,cRootRefs,rootRefIds) ) #define ICorProfilerCallback11_ExceptionThrown(This,thrownObjectId) \ ( (This)->lpVtbl -> ExceptionThrown(This,thrownObjectId) ) #define ICorProfilerCallback11_ExceptionSearchFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFunctionEnter(This,functionId) ) #define ICorProfilerCallback11_ExceptionSearchFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFunctionLeave(This) ) #define ICorProfilerCallback11_ExceptionSearchFilterEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchFilterEnter(This,functionId) ) #define ICorProfilerCallback11_ExceptionSearchFilterLeave(This) \ ( (This)->lpVtbl -> ExceptionSearchFilterLeave(This) ) #define ICorProfilerCallback11_ExceptionSearchCatcherFound(This,functionId) \ ( (This)->lpVtbl -> ExceptionSearchCatcherFound(This,functionId) ) #define ICorProfilerCallback11_ExceptionOSHandlerEnter(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerEnter(This,__unused) ) #define ICorProfilerCallback11_ExceptionOSHandlerLeave(This,__unused) \ ( (This)->lpVtbl -> ExceptionOSHandlerLeave(This,__unused) ) #define ICorProfilerCallback11_ExceptionUnwindFunctionEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionEnter(This,functionId) ) #define ICorProfilerCallback11_ExceptionUnwindFunctionLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFunctionLeave(This) ) #define ICorProfilerCallback11_ExceptionUnwindFinallyEnter(This,functionId) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyEnter(This,functionId) ) #define ICorProfilerCallback11_ExceptionUnwindFinallyLeave(This) \ ( (This)->lpVtbl -> ExceptionUnwindFinallyLeave(This) ) #define ICorProfilerCallback11_ExceptionCatcherEnter(This,functionId,objectId) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,functionId,objectId) ) #define ICorProfilerCallback11_ExceptionCatcherLeave(This) \ ( (This)->lpVtbl -> ExceptionCatcherLeave(This) ) #define ICorProfilerCallback11_COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) \ ( (This)->lpVtbl -> COMClassicVTableCreated(This,wrappedClassId,implementedIID,pVTable,cSlots) ) #define ICorProfilerCallback11_COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) \ ( (This)->lpVtbl -> COMClassicVTableDestroyed(This,wrappedClassId,implementedIID,pVTable) ) #define ICorProfilerCallback11_ExceptionCLRCatcherFound(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherFound(This) ) #define ICorProfilerCallback11_ExceptionCLRCatcherExecute(This) \ ( (This)->lpVtbl -> ExceptionCLRCatcherExecute(This) ) #define ICorProfilerCallback11_ThreadNameChanged(This,threadId,cchName,name) \ ( (This)->lpVtbl -> ThreadNameChanged(This,threadId,cchName,name) ) #define ICorProfilerCallback11_GarbageCollectionStarted(This,cGenerations,generationCollected,reason) \ ( (This)->lpVtbl -> GarbageCollectionStarted(This,cGenerations,generationCollected,reason) ) #define ICorProfilerCallback11_SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback11_GarbageCollectionFinished(This) \ ( (This)->lpVtbl -> GarbageCollectionFinished(This) ) #define ICorProfilerCallback11_FinalizeableObjectQueued(This,finalizerFlags,objectID) \ ( (This)->lpVtbl -> FinalizeableObjectQueued(This,finalizerFlags,objectID) ) #define ICorProfilerCallback11_RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) \ ( (This)->lpVtbl -> RootReferences2(This,cRootRefs,rootRefIds,rootKinds,rootFlags,rootIds) ) #define ICorProfilerCallback11_HandleCreated(This,handleId,initialObjectId) \ ( (This)->lpVtbl -> HandleCreated(This,handleId,initialObjectId) ) #define ICorProfilerCallback11_HandleDestroyed(This,handleId) \ ( (This)->lpVtbl -> HandleDestroyed(This,handleId) ) #define ICorProfilerCallback11_InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) \ ( (This)->lpVtbl -> InitializeForAttach(This,pCorProfilerInfoUnk,pvClientData,cbClientData) ) #define ICorProfilerCallback11_ProfilerAttachComplete(This) \ ( (This)->lpVtbl -> ProfilerAttachComplete(This) ) #define ICorProfilerCallback11_ProfilerDetachSucceeded(This) \ ( (This)->lpVtbl -> ProfilerDetachSucceeded(This) ) #define ICorProfilerCallback11_ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationStarted(This,functionId,rejitId,fIsSafeToBlock) ) #define ICorProfilerCallback11_GetReJITParameters(This,moduleId,methodId,pFunctionControl) \ ( (This)->lpVtbl -> GetReJITParameters(This,moduleId,methodId,pFunctionControl) ) #define ICorProfilerCallback11_ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> ReJITCompilationFinished(This,functionId,rejitId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback11_ReJITError(This,moduleId,methodId,functionId,hrStatus) \ ( (This)->lpVtbl -> ReJITError(This,moduleId,methodId,functionId,hrStatus) ) #define ICorProfilerCallback11_MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> MovedReferences2(This,cMovedObjectIDRanges,oldObjectIDRangeStart,newObjectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback11_SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) \ ( (This)->lpVtbl -> SurvivingReferences2(This,cSurvivingObjectIDRanges,objectIDRangeStart,cObjectIDRangeLength) ) #define ICorProfilerCallback11_ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) \ ( (This)->lpVtbl -> ConditionalWeakTableElementReferences(This,cRootRefs,keyRefIds,valueRefIds,rootIds) ) #define ICorProfilerCallback11_GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) \ ( (This)->lpVtbl -> GetAssemblyReferences(This,wszAssemblyPath,pAsmRefProvider) ) #define ICorProfilerCallback11_ModuleInMemorySymbolsUpdated(This,moduleId) \ ( (This)->lpVtbl -> ModuleInMemorySymbolsUpdated(This,moduleId) ) #define ICorProfilerCallback11_DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationStarted(This,functionId,fIsSafeToBlock,pILHeader,cbILHeader) ) #define ICorProfilerCallback11_DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) \ ( (This)->lpVtbl -> DynamicMethodJITCompilationFinished(This,functionId,hrStatus,fIsSafeToBlock) ) #define ICorProfilerCallback11_DynamicMethodUnloaded(This,functionId) \ ( (This)->lpVtbl -> DynamicMethodUnloaded(This,functionId) ) #define ICorProfilerCallback11_EventPipeEventDelivered(This,provider,eventId,eventVersion,cbMetadataBlob,metadataBlob,cbEventData,eventData,pActivityId,pRelatedActivityId,eventThread,numStackFrames,stackFrames) \ ( (This)->lpVtbl -> EventPipeEventDelivered(This,provider,eventId,eventVersion,cbMetadataBlob,metadataBlob,cbEventData,eventData,pActivityId,pRelatedActivityId,eventThread,numStackFrames,stackFrames) ) #define ICorProfilerCallback11_EventPipeProviderCreated(This,provider) \ ( (This)->lpVtbl -> EventPipeProviderCreated(This,provider) ) #define ICorProfilerCallback11_LoadAsNotificationOnly(This,pbNotificationOnly) \ ( (This)->lpVtbl -> LoadAsNotificationOnly(This,pbNotificationOnly) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerCallback11_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corprof_0000_0011 */ /* [local] */ typedef /* [public] */ enum __MIDL___MIDL_itf_corprof_0000_0011_0001 { COR_PRF_CODEGEN_DISABLE_INLINING = 0x1, COR_PRF_CODEGEN_DISABLE_ALL_OPTIMIZATIONS = 0x2 } COR_PRF_CODEGEN_FLAGS; extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0011_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corprof_0000_0011_v0_0_s_ifspec; #ifndef __ICorProfilerInfo_INTERFACE_DEFINED__ #define __ICorProfilerInfo_INTERFACE_DEFINED__ /* interface ICorProfilerInfo */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("28B5557D-3F3F-48b4-90B2-5F9EEA2F6C48") ICorProfilerInfo : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetClassFromObject( /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId) = 0; virtual HRESULT STDMETHODCALLTYPE GetClassFromToken( /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeInfo( /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetEventMask( /* [out] */ DWORD *pdwEvents) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP( /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromToken( /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId) = 0; virtual HRESULT STDMETHODCALLTYPE GetHandleFromThread( /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectSize( /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize) = 0; virtual HRESULT STDMETHODCALLTYPE IsArrayClass( /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadInfo( /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentThreadID( /* [out] */ ThreadID *pThreadId) = 0; virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo( /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo( /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE SetEventMask( /* [in] */ DWORD dwEvents) = 0; virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks( /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall) = 0; virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper( /* [in] */ FunctionIDMapper *pFunc) = 0; virtual HRESULT STDMETHODCALLTYPE GetTokenAndMetaDataFromFunction( /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE GetModuleInfo( /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId) = 0; virtual HRESULT STDMETHODCALLTYPE GetModuleMetaData( /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut) = 0; virtual HRESULT STDMETHODCALLTYPE GetILFunctionBody( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetILFunctionBodyAllocator( /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc) = 0; virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainInfo( /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyInfo( /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId) = 0; virtual HRESULT STDMETHODCALLTYPE SetFunctionReJIT( /* [in] */ FunctionID functionId) = 0; virtual HRESULT STDMETHODCALLTYPE ForceGC( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionInterface( /* [out] */ IUnknown **ppicd) = 0; virtual HRESULT STDMETHODCALLTYPE GetInprocInspectionIThisThread( /* [out] */ IUnknown **ppicd) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadContext( /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId) = 0; virtual HRESULT STDMETHODCALLTYPE BeginInprocDebugging( /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext) = 0; virtual HRESULT STDMETHODCALLTYPE EndInprocDebugging( /* [in] */ DWORD dwProfilerContext) = 0; virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping( /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfoVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); END_INTERFACE } ICorProfilerInfoVtbl; interface ICorProfilerInfo { CONST_VTBL struct ICorProfilerInfoVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo2_INTERFACE_DEFINED__ #define __ICorProfilerInfo2_INTERFACE_DEFINED__ /* interface ICorProfilerInfo2 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("CC0935CD-A518-487d-B0BB-A93214E65478") ICorProfilerInfo2 : public ICorProfilerInfo { public: virtual HRESULT STDMETHODCALLTYPE DoStackSnapshot( /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize) = 0; virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks2( /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionInfo2( /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetStringLayout( /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset) = 0; virtual HRESULT STDMETHODCALLTYPE GetClassLayout( /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize) = 0; virtual HRESULT STDMETHODCALLTYPE GetClassIDInfo2( /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeInfo2( /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetClassFromTokenAndTypeArgs( /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromTokenAndTypeArgs( /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID) = 0; virtual HRESULT STDMETHODCALLTYPE EnumModuleFrozenObjects( /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetArrayObjectInfo( /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData) = 0; virtual HRESULT STDMETHODCALLTYPE GetBoxClassLayout( /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadAppDomain( /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId) = 0; virtual HRESULT STDMETHODCALLTYPE GetRVAStaticAddress( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainStaticAddress( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetContextStaticAddress( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetStaticFieldInfo( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo) = 0; virtual HRESULT STDMETHODCALLTYPE GetGenerationBounds( /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectGeneration( /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range) = 0; virtual HRESULT STDMETHODCALLTYPE GetNotifiedExceptionClauseInfo( /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo2 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo2 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo2 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo2 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo2 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo2 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo2 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo2 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo2 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo2 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo2 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo2 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo2 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo2 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo2 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo2 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo2 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo2 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo2 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo2 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo2 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo2 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo2 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo2 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo2 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo2 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); END_INTERFACE } ICorProfilerInfo2Vtbl; interface ICorProfilerInfo2 { CONST_VTBL struct ICorProfilerInfo2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo2_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo2_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo2_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo2_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo2_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo2_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo2_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo2_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo2_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo2_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo2_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo2_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo2_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo2_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo2_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo2_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo2_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo2_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo2_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo2_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo2_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo2_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo2_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo2_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo2_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo2_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo2_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo2_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo2_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo2_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo2_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo2_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo2_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo2_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo2_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo2_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo2_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo2_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo2_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo2_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo2_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo2_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo2_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo2_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo2_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo2_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo2_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo2_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo2_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo2_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo2_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo2_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo2_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo2_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo2_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo3_INTERFACE_DEFINED__ #define __ICorProfilerInfo3_INTERFACE_DEFINED__ /* interface ICorProfilerInfo3 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B555ED4F-452A-4E54-8B39-B5360BAD32A0") ICorProfilerInfo3 : public ICorProfilerInfo2 { public: virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions( /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE RequestProfilerDetach( /* [in] */ DWORD dwExpectedCompletionMilliseconds) = 0; virtual HRESULT STDMETHODCALLTYPE SetFunctionIDMapper2( /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData) = 0; virtual HRESULT STDMETHODCALLTYPE GetStringLayout2( /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset) = 0; virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3( /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3) = 0; virtual HRESULT STDMETHODCALLTYPE SetEnterLeaveFunctionHooks3WithInfo( /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionEnter3Info( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionLeave3Info( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionTailcall3Info( /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo) = 0; virtual HRESULT STDMETHODCALLTYPE EnumModules( /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetRuntimeInformation( /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadStaticAddress2( /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainsContainingModule( /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetModuleInfo2( /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo3 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo3 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo3 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo3 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo3 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo3 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo3 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo3 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo3 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo3 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo3 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo3 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo3 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo3 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo3 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo3 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo3 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo3 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo3 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo3 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo3 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo3 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo3 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo3 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo3 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo3 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo3 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo3 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo3 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo3 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo3 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo3 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo3 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo3 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo3 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo3 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo3 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo3 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo3 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo3 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); END_INTERFACE } ICorProfilerInfo3Vtbl; interface ICorProfilerInfo3 { CONST_VTBL struct ICorProfilerInfo3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo3_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo3_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo3_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo3_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo3_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo3_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo3_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo3_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo3_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo3_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo3_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo3_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo3_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo3_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo3_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo3_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo3_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo3_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo3_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo3_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo3_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo3_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo3_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo3_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo3_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo3_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo3_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo3_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo3_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo3_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo3_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo3_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo3_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo3_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo3_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo3_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo3_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo3_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo3_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo3_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo3_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo3_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo3_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo3_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo3_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo3_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo3_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo3_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo3_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo3_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo3_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo3_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo3_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo3_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo3_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo3_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo3_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo3_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo3_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo3_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo3_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo3_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo3_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo3_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo3_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo3_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo3_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo3_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerObjectEnum_INTERFACE_DEFINED__ #define __ICorProfilerObjectEnum_INTERFACE_DEFINED__ /* interface ICorProfilerObjectEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerObjectEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2C6269BD-2D13-4321-AE12-6686365FD6AF") ICorProfilerObjectEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorProfilerObjectEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ObjectID objects[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorProfilerObjectEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerObjectEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerObjectEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerObjectEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorProfilerObjectEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorProfilerObjectEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorProfilerObjectEnum * This, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorProfilerObjectEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorProfilerObjectEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ObjectID objects[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorProfilerObjectEnumVtbl; interface ICorProfilerObjectEnum { CONST_VTBL struct ICorProfilerObjectEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerObjectEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerObjectEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerObjectEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerObjectEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorProfilerObjectEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorProfilerObjectEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorProfilerObjectEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorProfilerObjectEnum_Next(This,celt,objects,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerObjectEnum_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ #define __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ /* interface ICorProfilerFunctionEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerFunctionEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FF71301A-B994-429D-A10B-B345A65280EF") ICorProfilerFunctionEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorProfilerFunctionEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerFunctionEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerFunctionEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerFunctionEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorProfilerFunctionEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorProfilerFunctionEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorProfilerFunctionEnum * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorProfilerFunctionEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorProfilerFunctionEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_PRF_FUNCTION ids[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorProfilerFunctionEnumVtbl; interface ICorProfilerFunctionEnum { CONST_VTBL struct ICorProfilerFunctionEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerFunctionEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerFunctionEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerFunctionEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerFunctionEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorProfilerFunctionEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorProfilerFunctionEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorProfilerFunctionEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorProfilerFunctionEnum_Next(This,celt,ids,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerFunctionEnum_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerModuleEnum_INTERFACE_DEFINED__ #define __ICorProfilerModuleEnum_INTERFACE_DEFINED__ /* interface ICorProfilerModuleEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerModuleEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("b0266d75-2081-4493-af7f-028ba34db891") ICorProfilerModuleEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorProfilerModuleEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ModuleID ids[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorProfilerModuleEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerModuleEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerModuleEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerModuleEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorProfilerModuleEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorProfilerModuleEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorProfilerModuleEnum * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorProfilerModuleEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorProfilerModuleEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ModuleID ids[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorProfilerModuleEnumVtbl; interface ICorProfilerModuleEnum { CONST_VTBL struct ICorProfilerModuleEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerModuleEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerModuleEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerModuleEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerModuleEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorProfilerModuleEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorProfilerModuleEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorProfilerModuleEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorProfilerModuleEnum_Next(This,celt,ids,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerModuleEnum_INTERFACE_DEFINED__ */ #ifndef __IMethodMalloc_INTERFACE_DEFINED__ #define __IMethodMalloc_INTERFACE_DEFINED__ /* interface IMethodMalloc */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_IMethodMalloc; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A0EFB28B-6EE2-4d7b-B983-A75EF7BEEDB8") IMethodMalloc : public IUnknown { public: virtual PVOID STDMETHODCALLTYPE Alloc( /* [in] */ ULONG cb) = 0; }; #else /* C style interface */ typedef struct IMethodMallocVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IMethodMalloc * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IMethodMalloc * This); ULONG ( STDMETHODCALLTYPE *Release )( IMethodMalloc * This); PVOID ( STDMETHODCALLTYPE *Alloc )( IMethodMalloc * This, /* [in] */ ULONG cb); END_INTERFACE } IMethodMallocVtbl; interface IMethodMalloc { CONST_VTBL struct IMethodMallocVtbl *lpVtbl; }; #ifdef COBJMACROS #define IMethodMalloc_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IMethodMalloc_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IMethodMalloc_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IMethodMalloc_Alloc(This,cb) \ ( (This)->lpVtbl -> Alloc(This,cb) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IMethodMalloc_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerFunctionControl_INTERFACE_DEFINED__ #define __ICorProfilerFunctionControl_INTERFACE_DEFINED__ /* interface ICorProfilerFunctionControl */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerFunctionControl; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F0963021-E1EA-4732-8581-E01B0BD3C0C6") ICorProfilerFunctionControl : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetCodegenFlags( /* [in] */ DWORD flags) = 0; virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody( /* [in] */ ULONG cbNewILMethodHeader, /* [size_is][in] */ LPCBYTE pbNewILMethodHeader) = 0; virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap( /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]) = 0; }; #else /* C style interface */ typedef struct ICorProfilerFunctionControlVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerFunctionControl * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerFunctionControl * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerFunctionControl * This); HRESULT ( STDMETHODCALLTYPE *SetCodegenFlags )( ICorProfilerFunctionControl * This, /* [in] */ DWORD flags); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerFunctionControl * This, /* [in] */ ULONG cbNewILMethodHeader, /* [size_is][in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerFunctionControl * This, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); END_INTERFACE } ICorProfilerFunctionControlVtbl; interface ICorProfilerFunctionControl { CONST_VTBL struct ICorProfilerFunctionControlVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerFunctionControl_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerFunctionControl_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerFunctionControl_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerFunctionControl_SetCodegenFlags(This,flags) \ ( (This)->lpVtbl -> SetCodegenFlags(This,flags) ) #define ICorProfilerFunctionControl_SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,cbNewILMethodHeader,pbNewILMethodHeader) ) #define ICorProfilerFunctionControl_SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,cILMapEntries,rgILMapEntries) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerFunctionControl_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo4_INTERFACE_DEFINED__ #define __ICorProfilerInfo4_INTERFACE_DEFINED__ /* interface ICorProfilerInfo4 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("0d8fdcaa-6257-47bf-b1bf-94dac88466ee") ICorProfilerInfo4 : public ICorProfilerInfo3 { public: virtual HRESULT STDMETHODCALLTYPE EnumThreads( /* [out] */ ICorProfilerThreadEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE InitializeCurrentThread( void) = 0; virtual HRESULT STDMETHODCALLTYPE RequestReJIT( /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE RequestRevert( /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeInfo3( /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP2( /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId) = 0; virtual HRESULT STDMETHODCALLTYPE GetReJITIDs( /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping2( /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE EnumJITedFunctions2( /* [out] */ ICorProfilerFunctionEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectSize2( /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo4 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo4 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo4 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo4 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo4 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo4 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo4 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo4 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo4 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo4 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo4 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo4 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo4 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo4 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo4 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo4 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo4 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo4 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo4 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo4 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo4 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo4 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo4 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo4 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo4 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo4 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo4 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo4 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo4 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo4 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo4 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo4 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo4 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo4 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo4 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo4 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo4 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo4 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo4 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo4 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo4 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo4 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo4 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo4 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo4 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo4 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo4 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); END_INTERFACE } ICorProfilerInfo4Vtbl; interface ICorProfilerInfo4 { CONST_VTBL struct ICorProfilerInfo4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo4_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo4_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo4_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo4_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo4_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo4_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo4_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo4_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo4_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo4_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo4_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo4_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo4_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo4_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo4_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo4_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo4_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo4_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo4_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo4_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo4_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo4_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo4_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo4_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo4_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo4_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo4_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo4_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo4_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo4_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo4_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo4_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo4_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo4_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo4_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo4_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo4_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo4_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo4_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo4_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo4_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo4_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo4_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo4_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo4_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo4_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo4_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo4_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo4_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo4_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo4_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo4_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo4_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo4_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo4_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo4_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo4_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo4_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo4_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo4_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo4_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo4_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo4_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo4_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo4_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo4_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo4_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo4_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo4_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo4_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo4_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo4_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo4_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo4_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo4_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo4_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo4_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo4_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo5_INTERFACE_DEFINED__ #define __ICorProfilerInfo5_INTERFACE_DEFINED__ /* interface ICorProfilerInfo5 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("07602928-CE38-4B83-81E7-74ADAF781214") ICorProfilerInfo5 : public ICorProfilerInfo4 { public: virtual HRESULT STDMETHODCALLTYPE GetEventMask2( /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh) = 0; virtual HRESULT STDMETHODCALLTYPE SetEventMask2( /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo5 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo5 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo5 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo5 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo5 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo5 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo5 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo5 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo5 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo5 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo5 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo5 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo5 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo5 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo5 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo5 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo5 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo5 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo5 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo5 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo5 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo5 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo5 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo5 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo5 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo5 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo5 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo5 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo5 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo5 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo5 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo5 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo5 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo5 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo5 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo5 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo5 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo5 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo5 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo5 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo5 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo5 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo5 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); END_INTERFACE } ICorProfilerInfo5Vtbl; interface ICorProfilerInfo5 { CONST_VTBL struct ICorProfilerInfo5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo5_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo5_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo5_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo5_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo5_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo5_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo5_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo5_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo5_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo5_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo5_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo5_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo5_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo5_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo5_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo5_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo5_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo5_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo5_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo5_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo5_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo5_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo5_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo5_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo5_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo5_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo5_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo5_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo5_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo5_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo5_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo5_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo5_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo5_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo5_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo5_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo5_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo5_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo5_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo5_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo5_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo5_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo5_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo5_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo5_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo5_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo5_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo5_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo5_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo5_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo5_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo5_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo5_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo5_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo5_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo5_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo5_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo5_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo5_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo5_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo5_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo5_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo5_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo5_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo5_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo5_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo5_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo5_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo5_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo5_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo5_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo5_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo5_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo5_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo5_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo5_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo5_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo5_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo5_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo5_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo6_INTERFACE_DEFINED__ #define __ICorProfilerInfo6_INTERFACE_DEFINED__ /* interface ICorProfilerInfo6 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo6; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F30A070D-BFFB-46A7-B1D8-8781EF7B698A") ICorProfilerInfo6 : public ICorProfilerInfo5 { public: virtual HRESULT STDMETHODCALLTYPE EnumNgenModuleMethodsInliningThisMethod( /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo6Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo6 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo6 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo6 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo6 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo6 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo6 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo6 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo6 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo6 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo6 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo6 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo6 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo6 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo6 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo6 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo6 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo6 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo6 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo6 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo6 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo6 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo6 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo6 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo6 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo6 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo6 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo6 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo6 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo6 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo6 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo6 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo6 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo6 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo6 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo6 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo6 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo6 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo6 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo6 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo6 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo6 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo6 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo6 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo6 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo6 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); END_INTERFACE } ICorProfilerInfo6Vtbl; interface ICorProfilerInfo6 { CONST_VTBL struct ICorProfilerInfo6Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo6_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo6_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo6_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo6_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo6_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo6_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo6_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo6_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo6_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo6_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo6_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo6_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo6_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo6_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo6_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo6_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo6_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo6_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo6_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo6_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo6_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo6_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo6_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo6_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo6_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo6_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo6_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo6_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo6_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo6_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo6_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo6_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo6_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo6_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo6_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo6_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo6_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo6_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo6_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo6_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo6_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo6_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo6_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo6_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo6_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo6_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo6_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo6_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo6_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo6_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo6_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo6_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo6_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo6_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo6_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo6_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo6_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo6_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo6_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo6_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo6_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo6_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo6_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo6_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo6_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo6_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo6_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo6_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo6_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo6_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo6_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo6_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo6_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo6_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo6_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo6_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo6_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo6_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo6_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo6_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo6_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo6_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo6_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo6_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo7_INTERFACE_DEFINED__ #define __ICorProfilerInfo7_INTERFACE_DEFINED__ /* interface ICorProfilerInfo7 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo7; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("9AEECC0D-63E0-4187-8C00-E312F503F663") ICorProfilerInfo7 : public ICorProfilerInfo6 { public: virtual HRESULT STDMETHODCALLTYPE ApplyMetaData( /* [in] */ ModuleID moduleId) = 0; virtual HRESULT STDMETHODCALLTYPE GetInMemorySymbolsLength( /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes) = 0; virtual HRESULT STDMETHODCALLTYPE ReadInMemorySymbols( /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo7Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo7 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo7 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo7 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo7 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo7 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo7 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo7 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo7 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo7 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo7 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo7 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo7 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo7 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo7 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo7 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo7 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo7 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo7 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo7 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo7 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo7 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo7 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo7 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo7 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo7 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo7 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo7 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo7 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo7 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo7 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo7 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo7 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo7 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo7 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo7 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo7 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo7 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo7 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo7 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo7 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo7 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo7 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo7 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo7 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo7 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); END_INTERFACE } ICorProfilerInfo7Vtbl; interface ICorProfilerInfo7 { CONST_VTBL struct ICorProfilerInfo7Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo7_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo7_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo7_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo7_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo7_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo7_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo7_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo7_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo7_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo7_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo7_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo7_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo7_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo7_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo7_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo7_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo7_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo7_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo7_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo7_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo7_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo7_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo7_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo7_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo7_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo7_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo7_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo7_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo7_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo7_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo7_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo7_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo7_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo7_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo7_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo7_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo7_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo7_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo7_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo7_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo7_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo7_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo7_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo7_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo7_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo7_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo7_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo7_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo7_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo7_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo7_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo7_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo7_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo7_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo7_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo7_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo7_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo7_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo7_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo7_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo7_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo7_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo7_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo7_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo7_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo7_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo7_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo7_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo7_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo7_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo7_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo7_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo7_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo7_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo7_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo7_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo7_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo7_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo7_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo7_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo7_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo7_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo7_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo7_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo7_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo7_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo7_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo8_INTERFACE_DEFINED__ #define __ICorProfilerInfo8_INTERFACE_DEFINED__ /* interface ICorProfilerInfo8 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo8; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("C5AC80A6-782E-4716-8044-39598C60CFBF") ICorProfilerInfo8 : public ICorProfilerInfo7 { public: virtual HRESULT STDMETHODCALLTYPE IsFunctionDynamic( /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic) = 0; virtual HRESULT STDMETHODCALLTYPE GetFunctionFromIP3( /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId) = 0; virtual HRESULT STDMETHODCALLTYPE GetDynamicFunctionInfo( /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo8Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo8 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo8 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo8 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo8 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo8 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo8 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo8 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo8 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo8 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo8 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo8 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo8 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo8 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo8 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo8 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo8 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo8 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo8 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo8 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo8 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo8 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo8 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo8 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo8 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo8 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo8 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo8 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo8 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo8 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo8 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo8 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo8 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo8 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo8 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo8 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo8 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo8 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo8 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo8 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo8 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo8 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo8 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo8 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo8 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( ICorProfilerInfo8 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( ICorProfilerInfo8 * This, /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]); END_INTERFACE } ICorProfilerInfo8Vtbl; interface ICorProfilerInfo8 { CONST_VTBL struct ICorProfilerInfo8Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo8_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo8_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo8_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo8_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo8_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo8_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo8_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo8_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo8_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo8_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo8_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo8_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo8_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo8_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo8_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo8_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo8_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo8_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo8_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo8_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo8_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo8_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo8_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo8_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo8_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo8_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo8_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo8_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo8_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo8_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo8_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo8_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo8_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo8_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo8_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo8_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo8_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo8_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo8_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo8_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo8_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo8_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo8_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo8_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo8_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo8_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo8_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo8_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo8_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo8_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo8_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo8_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo8_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo8_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo8_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo8_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo8_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo8_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo8_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo8_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo8_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo8_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo8_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo8_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo8_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo8_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo8_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo8_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo8_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo8_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo8_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo8_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo8_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo8_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo8_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo8_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo8_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo8_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo8_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo8_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo8_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo8_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo8_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo8_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo8_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo8_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo8_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #define ICorProfilerInfo8_IsFunctionDynamic(This,functionId,isDynamic) \ ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) #define ICorProfilerInfo8_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) #define ICorProfilerInfo8_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo8_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo9_INTERFACE_DEFINED__ #define __ICorProfilerInfo9_INTERFACE_DEFINED__ /* interface ICorProfilerInfo9 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo9; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("008170DB-F8CC-4796-9A51-DC8AA0B47012") ICorProfilerInfo9 : public ICorProfilerInfo8 { public: virtual HRESULT STDMETHODCALLTYPE GetNativeCodeStartAddresses( FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetILToNativeMapping3( UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeInfo4( UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32 *pcCodeInfos, COR_PRF_CODE_INFO codeInfos[ ]) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo9Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo9 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo9 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo9 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo9 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo9 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo9 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo9 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo9 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo9 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo9 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo9 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo9 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo9 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo9 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo9 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo9 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo9 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo9 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo9 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo9 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo9 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo9 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo9 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo9 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo9 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo9 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo9 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo9 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo9 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo9 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo9 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo9 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo9 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo9 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo9 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo9 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo9 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo9 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo9 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo9 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo9 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo9 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo9 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo9 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo9 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo9 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo9 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo9 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo9 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo9 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo9 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( ICorProfilerInfo9 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( ICorProfilerInfo9 * This, /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]); HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( ICorProfilerInfo9 * This, FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( ICorProfilerInfo9 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( ICorProfilerInfo9 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32 *pcCodeInfos, COR_PRF_CODE_INFO codeInfos[ ]); END_INTERFACE } ICorProfilerInfo9Vtbl; interface ICorProfilerInfo9 { CONST_VTBL struct ICorProfilerInfo9Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo9_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo9_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo9_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo9_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo9_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo9_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo9_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo9_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo9_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo9_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo9_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo9_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo9_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo9_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo9_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo9_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo9_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo9_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo9_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo9_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo9_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo9_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo9_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo9_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo9_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo9_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo9_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo9_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo9_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo9_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo9_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo9_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo9_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo9_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo9_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo9_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo9_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo9_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo9_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo9_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo9_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo9_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo9_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo9_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo9_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo9_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo9_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo9_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo9_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo9_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo9_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo9_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo9_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo9_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo9_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo9_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo9_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo9_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo9_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo9_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo9_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo9_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo9_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo9_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo9_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo9_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo9_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo9_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo9_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo9_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo9_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo9_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo9_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo9_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo9_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo9_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo9_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo9_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo9_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo9_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo9_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo9_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo9_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo9_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo9_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo9_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo9_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #define ICorProfilerInfo9_IsFunctionDynamic(This,functionId,isDynamic) \ ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) #define ICorProfilerInfo9_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) #define ICorProfilerInfo9_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) #define ICorProfilerInfo9_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) #define ICorProfilerInfo9_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) #define ICorProfilerInfo9_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo9_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo10_INTERFACE_DEFINED__ #define __ICorProfilerInfo10_INTERFACE_DEFINED__ /* interface ICorProfilerInfo10 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo10; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2F1B5152-C869-40C9-AA5F-3ABE026BD720") ICorProfilerInfo10 : public ICorProfilerInfo9 { public: virtual HRESULT STDMETHODCALLTYPE EnumerateObjectReferences( ObjectID objectId, ObjectReferenceCallback callback, void *clientData) = 0; virtual HRESULT STDMETHODCALLTYPE IsFrozenObject( ObjectID objectId, BOOL *pbFrozen) = 0; virtual HRESULT STDMETHODCALLTYPE GetLOHObjectSizeThreshold( DWORD *pThreshold) = 0; virtual HRESULT STDMETHODCALLTYPE RequestReJITWithInliners( /* [in] */ DWORD dwRejitFlags, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SuspendRuntime( void) = 0; virtual HRESULT STDMETHODCALLTYPE ResumeRuntime( void) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo10Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo10 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo10 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo10 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo10 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo10 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo10 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo10 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo10 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo10 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo10 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo10 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo10 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo10 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo10 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo10 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo10 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo10 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo10 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo10 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo10 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo10 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo10 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo10 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo10 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo10 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo10 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo10 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo10 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo10 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo10 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo10 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo10 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo10 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo10 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo10 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo10 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo10 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo10 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo10 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo10 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo10 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo10 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo10 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo10 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo10 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo10 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo10 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo10 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo10 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo10 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo10 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( ICorProfilerInfo10 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( ICorProfilerInfo10 * This, /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]); HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( ICorProfilerInfo10 * This, FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( ICorProfilerInfo10 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( ICorProfilerInfo10 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32 *pcCodeInfos, COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( ICorProfilerInfo10 * This, ObjectID objectId, ObjectReferenceCallback callback, void *clientData); HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( ICorProfilerInfo10 * This, ObjectID objectId, BOOL *pbFrozen); HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( ICorProfilerInfo10 * This, DWORD *pThreshold); HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( ICorProfilerInfo10 * This, /* [in] */ DWORD dwRejitFlags, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( ICorProfilerInfo10 * This); HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( ICorProfilerInfo10 * This); END_INTERFACE } ICorProfilerInfo10Vtbl; interface ICorProfilerInfo10 { CONST_VTBL struct ICorProfilerInfo10Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo10_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo10_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo10_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo10_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo10_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo10_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo10_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo10_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo10_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo10_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo10_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo10_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo10_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo10_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo10_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo10_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo10_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo10_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo10_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo10_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo10_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo10_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo10_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo10_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo10_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo10_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo10_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo10_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo10_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo10_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo10_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo10_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo10_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo10_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo10_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo10_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo10_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo10_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo10_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo10_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo10_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo10_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo10_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo10_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo10_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo10_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo10_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo10_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo10_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo10_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo10_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo10_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo10_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo10_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo10_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo10_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo10_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo10_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo10_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo10_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo10_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo10_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo10_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo10_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo10_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo10_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo10_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo10_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo10_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo10_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo10_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo10_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo10_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo10_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo10_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo10_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo10_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo10_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo10_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo10_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo10_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo10_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo10_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo10_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo10_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo10_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo10_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #define ICorProfilerInfo10_IsFunctionDynamic(This,functionId,isDynamic) \ ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) #define ICorProfilerInfo10_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) #define ICorProfilerInfo10_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) #define ICorProfilerInfo10_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) #define ICorProfilerInfo10_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) #define ICorProfilerInfo10_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo10_EnumerateObjectReferences(This,objectId,callback,clientData) \ ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) #define ICorProfilerInfo10_IsFrozenObject(This,objectId,pbFrozen) \ ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) #define ICorProfilerInfo10_GetLOHObjectSizeThreshold(This,pThreshold) \ ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) #define ICorProfilerInfo10_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo10_SuspendRuntime(This) \ ( (This)->lpVtbl -> SuspendRuntime(This) ) #define ICorProfilerInfo10_ResumeRuntime(This) \ ( (This)->lpVtbl -> ResumeRuntime(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo10_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo11_INTERFACE_DEFINED__ #define __ICorProfilerInfo11_INTERFACE_DEFINED__ /* interface ICorProfilerInfo11 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo11; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("06398876-8987-4154-B621-40A00D6E4D04") ICorProfilerInfo11 : public ICorProfilerInfo10 { public: virtual HRESULT STDMETHODCALLTYPE GetEnvironmentVariable( /* [string][in] */ const WCHAR *szName, /* [in] */ ULONG cchValue, /* [out] */ ULONG *pcchValue, /* [annotation][out] */ _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetEnvironmentVariable( /* [string][in] */ const WCHAR *szName, /* [string][in] */ const WCHAR *szValue) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo11Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo11 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo11 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo11 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo11 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo11 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo11 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo11 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo11 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo11 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo11 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo11 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo11 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo11 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo11 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo11 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo11 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo11 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo11 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo11 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo11 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo11 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo11 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo11 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo11 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo11 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo11 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo11 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo11 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo11 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo11 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo11 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo11 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo11 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo11 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo11 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo11 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo11 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo11 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo11 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo11 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo11 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo11 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo11 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo11 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo11 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo11 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo11 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo11 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo11 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo11 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo11 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( ICorProfilerInfo11 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( ICorProfilerInfo11 * This, /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]); HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( ICorProfilerInfo11 * This, FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( ICorProfilerInfo11 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( ICorProfilerInfo11 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32 *pcCodeInfos, COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( ICorProfilerInfo11 * This, ObjectID objectId, ObjectReferenceCallback callback, void *clientData); HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( ICorProfilerInfo11 * This, ObjectID objectId, BOOL *pbFrozen); HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( ICorProfilerInfo11 * This, DWORD *pThreshold); HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( ICorProfilerInfo11 * This, /* [in] */ DWORD dwRejitFlags, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( ICorProfilerInfo11 * This); HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( ICorProfilerInfo11 * This); HRESULT ( STDMETHODCALLTYPE *GetEnvironmentVariable )( ICorProfilerInfo11 * This, /* [string][in] */ const WCHAR *szName, /* [in] */ ULONG cchValue, /* [out] */ ULONG *pcchValue, /* [annotation][out] */ _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]); HRESULT ( STDMETHODCALLTYPE *SetEnvironmentVariable )( ICorProfilerInfo11 * This, /* [string][in] */ const WCHAR *szName, /* [string][in] */ const WCHAR *szValue); END_INTERFACE } ICorProfilerInfo11Vtbl; interface ICorProfilerInfo11 { CONST_VTBL struct ICorProfilerInfo11Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo11_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo11_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo11_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo11_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo11_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo11_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo11_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo11_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo11_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo11_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo11_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo11_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo11_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo11_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo11_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo11_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo11_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo11_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo11_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo11_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo11_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo11_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo11_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo11_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo11_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo11_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo11_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo11_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo11_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo11_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo11_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo11_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo11_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo11_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo11_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo11_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo11_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo11_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo11_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo11_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo11_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo11_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo11_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo11_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo11_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo11_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo11_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo11_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo11_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo11_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo11_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo11_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo11_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo11_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo11_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo11_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo11_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo11_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo11_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo11_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo11_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo11_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo11_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo11_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo11_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo11_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo11_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo11_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo11_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo11_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo11_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo11_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo11_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo11_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo11_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo11_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo11_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo11_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo11_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo11_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo11_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo11_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo11_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo11_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo11_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo11_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo11_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #define ICorProfilerInfo11_IsFunctionDynamic(This,functionId,isDynamic) \ ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) #define ICorProfilerInfo11_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) #define ICorProfilerInfo11_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) #define ICorProfilerInfo11_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) #define ICorProfilerInfo11_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) #define ICorProfilerInfo11_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo11_EnumerateObjectReferences(This,objectId,callback,clientData) \ ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) #define ICorProfilerInfo11_IsFrozenObject(This,objectId,pbFrozen) \ ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) #define ICorProfilerInfo11_GetLOHObjectSizeThreshold(This,pThreshold) \ ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) #define ICorProfilerInfo11_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo11_SuspendRuntime(This) \ ( (This)->lpVtbl -> SuspendRuntime(This) ) #define ICorProfilerInfo11_ResumeRuntime(This) \ ( (This)->lpVtbl -> ResumeRuntime(This) ) #define ICorProfilerInfo11_GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) \ ( (This)->lpVtbl -> GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) ) #define ICorProfilerInfo11_SetEnvironmentVariable(This,szName,szValue) \ ( (This)->lpVtbl -> SetEnvironmentVariable(This,szName,szValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo11_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo12_INTERFACE_DEFINED__ #define __ICorProfilerInfo12_INTERFACE_DEFINED__ /* interface ICorProfilerInfo12 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo12; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("27b24ccd-1cb1-47c5-96ee-98190dc30959") ICorProfilerInfo12 : public ICorProfilerInfo11 { public: virtual HRESULT STDMETHODCALLTYPE EventPipeStartSession( /* [in] */ UINT32 cProviderConfigs, /* [size_is][in] */ COR_PRF_EVENTPIPE_PROVIDER_CONFIG pProviderConfigs[ ], /* [in] */ BOOL requestRundown, /* [out] */ EVENTPIPE_SESSION *pSession) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeAddProviderToSession( /* [in] */ EVENTPIPE_SESSION session, /* [in] */ COR_PRF_EVENTPIPE_PROVIDER_CONFIG providerConfig) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeStopSession( /* [in] */ EVENTPIPE_SESSION session) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeCreateProvider( /* [string][in] */ const WCHAR *providerName, /* [out] */ EVENTPIPE_PROVIDER *pProvider) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeGetProviderInfo( /* [in] */ EVENTPIPE_PROVIDER provider, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR providerName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeDefineEvent( /* [in] */ EVENTPIPE_PROVIDER provider, /* [string][in] */ const WCHAR *eventName, /* [in] */ UINT32 eventID, /* [in] */ UINT64 keywords, /* [in] */ UINT32 eventVersion, /* [in] */ UINT32 level, /* [in] */ UINT8 opcode, /* [in] */ BOOL needStack, /* [in] */ UINT32 cParamDescs, /* [size_is][in] */ COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[ ], /* [out] */ EVENTPIPE_EVENT *pEvent) = 0; virtual HRESULT STDMETHODCALLTYPE EventPipeWriteEvent( /* [in] */ EVENTPIPE_EVENT event, /* [in] */ UINT32 cData, /* [size_is][in] */ COR_PRF_EVENT_DATA data[ ], /* [in] */ LPCGUID pActivityId, /* [in] */ LPCGUID pRelatedActivityId) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo12Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo12 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo12 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo12 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo12 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo12 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo12 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo12 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo12 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo12 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo12 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo12 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo12 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo12 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo12 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo12 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo12 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo12 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo12 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo12 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo12 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo12 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo12 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo12 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo12 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo12 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo12 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo12 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo12 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo12 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo12 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo12 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo12 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo12 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo12 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo12 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo12 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo12 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo12 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo12 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo12 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo12 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo12 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo12 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo12 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo12 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo12 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo12 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo12 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo12 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo12 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo12 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( ICorProfilerInfo12 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( ICorProfilerInfo12 * This, /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]); HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( ICorProfilerInfo12 * This, FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( ICorProfilerInfo12 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( ICorProfilerInfo12 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32 *pcCodeInfos, COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( ICorProfilerInfo12 * This, ObjectID objectId, ObjectReferenceCallback callback, void *clientData); HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( ICorProfilerInfo12 * This, ObjectID objectId, BOOL *pbFrozen); HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( ICorProfilerInfo12 * This, DWORD *pThreshold); HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( ICorProfilerInfo12 * This, /* [in] */ DWORD dwRejitFlags, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( ICorProfilerInfo12 * This); HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( ICorProfilerInfo12 * This); HRESULT ( STDMETHODCALLTYPE *GetEnvironmentVariable )( ICorProfilerInfo12 * This, /* [string][in] */ const WCHAR *szName, /* [in] */ ULONG cchValue, /* [out] */ ULONG *pcchValue, /* [annotation][out] */ _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]); HRESULT ( STDMETHODCALLTYPE *SetEnvironmentVariable )( ICorProfilerInfo12 * This, /* [string][in] */ const WCHAR *szName, /* [string][in] */ const WCHAR *szValue); HRESULT ( STDMETHODCALLTYPE *EventPipeStartSession )( ICorProfilerInfo12 * This, /* [in] */ UINT32 cProviderConfigs, /* [size_is][in] */ COR_PRF_EVENTPIPE_PROVIDER_CONFIG pProviderConfigs[ ], /* [in] */ BOOL requestRundown, /* [out] */ EVENTPIPE_SESSION *pSession); HRESULT ( STDMETHODCALLTYPE *EventPipeAddProviderToSession )( ICorProfilerInfo12 * This, /* [in] */ EVENTPIPE_SESSION session, /* [in] */ COR_PRF_EVENTPIPE_PROVIDER_CONFIG providerConfig); HRESULT ( STDMETHODCALLTYPE *EventPipeStopSession )( ICorProfilerInfo12 * This, /* [in] */ EVENTPIPE_SESSION session); HRESULT ( STDMETHODCALLTYPE *EventPipeCreateProvider )( ICorProfilerInfo12 * This, /* [string][in] */ const WCHAR *providerName, /* [out] */ EVENTPIPE_PROVIDER *pProvider); HRESULT ( STDMETHODCALLTYPE *EventPipeGetProviderInfo )( ICorProfilerInfo12 * This, /* [in] */ EVENTPIPE_PROVIDER provider, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR providerName[ ]); HRESULT ( STDMETHODCALLTYPE *EventPipeDefineEvent )( ICorProfilerInfo12 * This, /* [in] */ EVENTPIPE_PROVIDER provider, /* [string][in] */ const WCHAR *eventName, /* [in] */ UINT32 eventID, /* [in] */ UINT64 keywords, /* [in] */ UINT32 eventVersion, /* [in] */ UINT32 level, /* [in] */ UINT8 opcode, /* [in] */ BOOL needStack, /* [in] */ UINT32 cParamDescs, /* [size_is][in] */ COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[ ], /* [out] */ EVENTPIPE_EVENT *pEvent); HRESULT ( STDMETHODCALLTYPE *EventPipeWriteEvent )( ICorProfilerInfo12 * This, /* [in] */ EVENTPIPE_EVENT event, /* [in] */ UINT32 cData, /* [size_is][in] */ COR_PRF_EVENT_DATA data[ ], /* [in] */ LPCGUID pActivityId, /* [in] */ LPCGUID pRelatedActivityId); END_INTERFACE } ICorProfilerInfo12Vtbl; interface ICorProfilerInfo12 { CONST_VTBL struct ICorProfilerInfo12Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo12_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo12_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo12_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo12_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo12_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo12_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo12_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo12_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo12_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo12_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo12_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo12_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo12_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo12_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo12_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo12_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo12_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo12_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo12_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo12_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo12_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo12_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo12_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo12_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo12_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo12_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo12_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo12_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo12_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo12_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo12_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo12_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo12_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo12_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo12_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo12_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo12_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo12_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo12_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo12_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo12_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo12_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo12_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo12_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo12_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo12_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo12_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo12_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo12_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo12_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo12_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo12_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo12_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo12_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo12_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo12_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo12_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo12_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo12_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo12_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo12_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo12_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo12_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo12_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo12_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo12_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo12_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo12_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo12_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo12_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo12_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo12_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo12_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo12_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo12_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo12_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo12_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo12_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo12_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo12_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo12_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo12_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo12_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo12_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo12_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo12_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo12_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #define ICorProfilerInfo12_IsFunctionDynamic(This,functionId,isDynamic) \ ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) #define ICorProfilerInfo12_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) #define ICorProfilerInfo12_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) #define ICorProfilerInfo12_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) #define ICorProfilerInfo12_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) #define ICorProfilerInfo12_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo12_EnumerateObjectReferences(This,objectId,callback,clientData) \ ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) #define ICorProfilerInfo12_IsFrozenObject(This,objectId,pbFrozen) \ ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) #define ICorProfilerInfo12_GetLOHObjectSizeThreshold(This,pThreshold) \ ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) #define ICorProfilerInfo12_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo12_SuspendRuntime(This) \ ( (This)->lpVtbl -> SuspendRuntime(This) ) #define ICorProfilerInfo12_ResumeRuntime(This) \ ( (This)->lpVtbl -> ResumeRuntime(This) ) #define ICorProfilerInfo12_GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) \ ( (This)->lpVtbl -> GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) ) #define ICorProfilerInfo12_SetEnvironmentVariable(This,szName,szValue) \ ( (This)->lpVtbl -> SetEnvironmentVariable(This,szName,szValue) ) #define ICorProfilerInfo12_EventPipeStartSession(This,cProviderConfigs,pProviderConfigs,requestRundown,pSession) \ ( (This)->lpVtbl -> EventPipeStartSession(This,cProviderConfigs,pProviderConfigs,requestRundown,pSession) ) #define ICorProfilerInfo12_EventPipeAddProviderToSession(This,session,providerConfig) \ ( (This)->lpVtbl -> EventPipeAddProviderToSession(This,session,providerConfig) ) #define ICorProfilerInfo12_EventPipeStopSession(This,session) \ ( (This)->lpVtbl -> EventPipeStopSession(This,session) ) #define ICorProfilerInfo12_EventPipeCreateProvider(This,providerName,pProvider) \ ( (This)->lpVtbl -> EventPipeCreateProvider(This,providerName,pProvider) ) #define ICorProfilerInfo12_EventPipeGetProviderInfo(This,provider,cchName,pcchName,providerName) \ ( (This)->lpVtbl -> EventPipeGetProviderInfo(This,provider,cchName,pcchName,providerName) ) #define ICorProfilerInfo12_EventPipeDefineEvent(This,provider,eventName,eventID,keywords,eventVersion,level,opcode,needStack,cParamDescs,pParamDescs,pEvent) \ ( (This)->lpVtbl -> EventPipeDefineEvent(This,provider,eventName,eventID,keywords,eventVersion,level,opcode,needStack,cParamDescs,pParamDescs,pEvent) ) #define ICorProfilerInfo12_EventPipeWriteEvent(This,event,cData,data,pActivityId,pRelatedActivityId) \ ( (This)->lpVtbl -> EventPipeWriteEvent(This,event,cData,data,pActivityId,pRelatedActivityId) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo12_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerInfo13_INTERFACE_DEFINED__ #define __ICorProfilerInfo13_INTERFACE_DEFINED__ /* interface ICorProfilerInfo13 */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerInfo13; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("6e6c7ee2-0701-4ec2-9d29-2e8733b66934") ICorProfilerInfo13 : public ICorProfilerInfo12 { public: virtual HRESULT STDMETHODCALLTYPE CreateHandle( /* [in] */ ObjectID object, /* [in] */ COR_PRF_HANDLE_TYPE type, /* [out] */ ObjectHandleID* pHandle) = 0; virtual HRESULT STDMETHODCALLTYPE DestroyHandle( /* [in] */ ObjectHandleID handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectIDFromHandle( /* [in] */ ObjectHandleID handle, /* [out] */ ObjectID* pObject) = 0; }; #else /* C style interface */ typedef struct ICorProfilerInfo13Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerInfo13 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerInfo13 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerInfo13 * This); HRESULT ( STDMETHODCALLTYPE *GetClassFromObject )( ICorProfilerInfo13 * This, /* [in] */ ObjectID objectId, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetClassFromToken )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdTypeDef typeDef, /* [out] */ ClassID *pClassId); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [out] */ LPCBYTE *pStart, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask )( ICorProfilerInfo13 * This, /* [out] */ DWORD *pdwEvents); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP )( ICorProfilerInfo13 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromToken )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdToken token, /* [out] */ FunctionID *pFunctionId); HRESULT ( STDMETHODCALLTYPE *GetHandleFromThread )( ICorProfilerInfo13 * This, /* [in] */ ThreadID threadId, /* [out] */ HANDLE *phThread); HRESULT ( STDMETHODCALLTYPE *GetObjectSize )( ICorProfilerInfo13 * This, /* [in] */ ObjectID objectId, /* [out] */ ULONG *pcSize); HRESULT ( STDMETHODCALLTYPE *IsArrayClass )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [out] */ CorElementType *pBaseElemType, /* [out] */ ClassID *pBaseClassId, /* [out] */ ULONG *pcRank); HRESULT ( STDMETHODCALLTYPE *GetThreadInfo )( ICorProfilerInfo13 * This, /* [in] */ ThreadID threadId, /* [out] */ DWORD *pdwWin32ThreadId); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( ICorProfilerInfo13 * This, /* [out] */ ThreadID *pThreadId); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *SetEventMask )( ICorProfilerInfo13 * This, /* [in] */ DWORD dwEvents); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks )( ICorProfilerInfo13 * This, /* [in] */ FunctionEnter *pFuncEnter, /* [in] */ FunctionLeave *pFuncLeave, /* [in] */ FunctionTailcall *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper )( ICorProfilerInfo13 * This, /* [in] */ FunctionIDMapper *pFunc); HRESULT ( STDMETHODCALLTYPE *GetTokenAndMetaDataFromFunction )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppImport, /* [out] */ mdToken *pToken); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId); HRESULT ( STDMETHODCALLTYPE *GetModuleMetaData )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD dwOpenFlags, /* [in] */ REFIID riid, /* [out] */ IUnknown **ppOut); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBody )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodId, /* [out] */ LPCBYTE *ppMethodHeader, /* [out] */ ULONG *pcbMethodSize); HRESULT ( STDMETHODCALLTYPE *GetILFunctionBodyAllocator )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [out] */ IMethodMalloc **ppMalloc); HRESULT ( STDMETHODCALLTYPE *SetILFunctionBody )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ mdMethodDef methodid, /* [in] */ LPCBYTE pbNewILMethodHeader); HRESULT ( STDMETHODCALLTYPE *GetAppDomainInfo )( ICorProfilerInfo13 * This, /* [in] */ AppDomainID appDomainId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ ProcessID *pProcessId); HRESULT ( STDMETHODCALLTYPE *GetAssemblyInfo )( ICorProfilerInfo13 * This, /* [in] */ AssemblyID assemblyId, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AppDomainID *pAppDomainId, /* [out] */ ModuleID *pModuleId); HRESULT ( STDMETHODCALLTYPE *SetFunctionReJIT )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId); HRESULT ( STDMETHODCALLTYPE *ForceGC )( ICorProfilerInfo13 * This); HRESULT ( STDMETHODCALLTYPE *SetILInstrumentedCodeMap )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ BOOL fStartJit, /* [in] */ ULONG cILMapEntries, /* [size_is][in] */ COR_IL_MAP rgILMapEntries[ ]); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionInterface )( ICorProfilerInfo13 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetInprocInspectionIThisThread )( ICorProfilerInfo13 * This, /* [out] */ IUnknown **ppicd); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( ICorProfilerInfo13 * This, /* [in] */ ThreadID threadId, /* [out] */ ContextID *pContextId); HRESULT ( STDMETHODCALLTYPE *BeginInprocDebugging )( ICorProfilerInfo13 * This, /* [in] */ BOOL fThisThreadOnly, /* [out] */ DWORD *pdwProfilerContext); HRESULT ( STDMETHODCALLTYPE *EndInprocDebugging )( ICorProfilerInfo13 * This, /* [in] */ DWORD dwProfilerContext); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *DoStackSnapshot )( ICorProfilerInfo13 * This, /* [in] */ ThreadID thread, /* [in] */ StackSnapshotCallback *callback, /* [in] */ ULONG32 infoFlags, /* [in] */ void *clientData, /* [size_is][in] */ BYTE context[ ], /* [in] */ ULONG32 contextSize); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks2 )( ICorProfilerInfo13 * This, /* [in] */ FunctionEnter2 *pFuncEnter, /* [in] */ FunctionLeave2 *pFuncLeave, /* [in] */ FunctionTailcall2 *pFuncTailcall); HRESULT ( STDMETHODCALLTYPE *GetFunctionInfo2 )( ICorProfilerInfo13 * This, /* [in] */ FunctionID funcId, /* [in] */ COR_PRF_FRAME_INFO frameInfo, /* [out] */ ClassID *pClassId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdToken *pToken, /* [in] */ ULONG32 cTypeArgs, /* [out] */ ULONG32 *pcTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetStringLayout )( ICorProfilerInfo13 * This, /* [out] */ ULONG *pBufferLengthOffset, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetClassLayout )( ICorProfilerInfo13 * This, /* [in] */ ClassID classID, /* [out][in] */ COR_FIELD_OFFSET rFieldOffset[ ], /* [in] */ ULONG cFieldOffset, /* [out] */ ULONG *pcFieldOffset, /* [out] */ ULONG *pulClassSize); HRESULT ( STDMETHODCALLTYPE *GetClassIDInfo2 )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [out] */ ModuleID *pModuleId, /* [out] */ mdTypeDef *pTypeDefToken, /* [out] */ ClassID *pParentClassId, /* [in] */ ULONG32 cNumTypeArgs, /* [out] */ ULONG32 *pcNumTypeArgs, /* [out] */ ClassID typeArgs[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo2 )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionID, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetClassFromTokenAndTypeArgs )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdTypeDef typeDef, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ ClassID *pClassID); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromTokenAndTypeArgs )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleID, /* [in] */ mdMethodDef funcDef, /* [in] */ ClassID classId, /* [in] */ ULONG32 cTypeArgs, /* [size_is][in] */ ClassID typeArgs[ ], /* [out] */ FunctionID *pFunctionID); HRESULT ( STDMETHODCALLTYPE *EnumModuleFrozenObjects )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleID, /* [out] */ ICorProfilerObjectEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetArrayObjectInfo )( ICorProfilerInfo13 * This, /* [in] */ ObjectID objectId, /* [in] */ ULONG32 cDimensions, /* [size_is][out] */ ULONG32 pDimensionSizes[ ], /* [size_is][out] */ int pDimensionLowerBounds[ ], /* [out] */ BYTE **ppData); HRESULT ( STDMETHODCALLTYPE *GetBoxClassLayout )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [out] */ ULONG32 *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *GetThreadAppDomain )( ICorProfilerInfo13 * This, /* [in] */ ThreadID threadId, /* [out] */ AppDomainID *pAppDomainId); HRESULT ( STDMETHODCALLTYPE *GetRVAStaticAddress )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStaticAddress )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetContextStaticAddress )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ ContextID contextId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldInfo )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [out] */ COR_PRF_STATIC_TYPE *pFieldInfo); HRESULT ( STDMETHODCALLTYPE *GetGenerationBounds )( ICorProfilerInfo13 * This, /* [in] */ ULONG cObjectRanges, /* [out] */ ULONG *pcObjectRanges, /* [length_is][size_is][out] */ COR_PRF_GC_GENERATION_RANGE ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetObjectGeneration )( ICorProfilerInfo13 * This, /* [in] */ ObjectID objectId, /* [out] */ COR_PRF_GC_GENERATION_RANGE *range); HRESULT ( STDMETHODCALLTYPE *GetNotifiedExceptionClauseInfo )( ICorProfilerInfo13 * This, /* [out] */ COR_PRF_EX_CLAUSE_INFO *pinfo); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions )( ICorProfilerInfo13 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *RequestProfilerDetach )( ICorProfilerInfo13 * This, /* [in] */ DWORD dwExpectedCompletionMilliseconds); HRESULT ( STDMETHODCALLTYPE *SetFunctionIDMapper2 )( ICorProfilerInfo13 * This, /* [in] */ FunctionIDMapper2 *pFunc, /* [in] */ void *clientData); HRESULT ( STDMETHODCALLTYPE *GetStringLayout2 )( ICorProfilerInfo13 * This, /* [out] */ ULONG *pStringLengthOffset, /* [out] */ ULONG *pBufferOffset); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3 )( ICorProfilerInfo13 * This, /* [in] */ FunctionEnter3 *pFuncEnter3, /* [in] */ FunctionLeave3 *pFuncLeave3, /* [in] */ FunctionTailcall3 *pFuncTailcall3); HRESULT ( STDMETHODCALLTYPE *SetEnterLeaveFunctionHooks3WithInfo )( ICorProfilerInfo13 * This, /* [in] */ FunctionEnter3WithInfo *pFuncEnter3WithInfo, /* [in] */ FunctionLeave3WithInfo *pFuncLeave3WithInfo, /* [in] */ FunctionTailcall3WithInfo *pFuncTailcall3WithInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionEnter3Info )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out][in] */ ULONG *pcbArgumentInfo, /* [size_is][out] */ COR_PRF_FUNCTION_ARGUMENT_INFO *pArgumentInfo); HRESULT ( STDMETHODCALLTYPE *GetFunctionLeave3Info )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo, /* [out] */ COR_PRF_FUNCTION_ARGUMENT_RANGE *pRetvalRange); HRESULT ( STDMETHODCALLTYPE *GetFunctionTailcall3Info )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ COR_PRF_ELT_INFO eltInfo, /* [out] */ COR_PRF_FRAME_INFO *pFrameInfo); HRESULT ( STDMETHODCALLTYPE *EnumModules )( ICorProfilerInfo13 * This, /* [out] */ ICorProfilerModuleEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRuntimeInformation )( ICorProfilerInfo13 * This, /* [out] */ USHORT *pClrInstanceId, /* [out] */ COR_PRF_RUNTIME_TYPE *pRuntimeType, /* [out] */ USHORT *pMajorVersion, /* [out] */ USHORT *pMinorVersion, /* [out] */ USHORT *pBuildNumber, /* [out] */ USHORT *pQFEVersion, /* [in] */ ULONG cchVersionString, /* [out] */ ULONG *pcchVersionString, /* [annotation][out] */ _Out_writes_to_(cchVersionString, *pcchVersionString) WCHAR szVersionString[ ]); HRESULT ( STDMETHODCALLTYPE *GetThreadStaticAddress2 )( ICorProfilerInfo13 * This, /* [in] */ ClassID classId, /* [in] */ mdFieldDef fieldToken, /* [in] */ AppDomainID appDomainId, /* [in] */ ThreadID threadId, /* [out] */ void **ppAddress); HRESULT ( STDMETHODCALLTYPE *GetAppDomainsContainingModule )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ ULONG32 cAppDomainIds, /* [out] */ ULONG32 *pcAppDomainIds, /* [length_is][size_is][out] */ AppDomainID appDomainIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetModuleInfo2 )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [out] */ LPCBYTE *ppBaseLoadAddress, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR szName[ ], /* [out] */ AssemblyID *pAssemblyId, /* [out] */ DWORD *pdwModuleFlags); HRESULT ( STDMETHODCALLTYPE *EnumThreads )( ICorProfilerInfo13 * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *InitializeCurrentThread )( ICorProfilerInfo13 * This); HRESULT ( STDMETHODCALLTYPE *RequestReJIT )( ICorProfilerInfo13 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *RequestRevert )( ICorProfilerInfo13 * This, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ], /* [size_is][out] */ HRESULT status[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo3 )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionID, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cCodeInfos, /* [out] */ ULONG32 *pcCodeInfos, /* [length_is][size_is][out] */ COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP2 )( ICorProfilerInfo13 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *pFunctionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetReJITIDs )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ ULONG cReJitIds, /* [out] */ ULONG *pcReJitIds, /* [length_is][size_is][out] */ ReJITID reJitIds[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping2 )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [in] */ ReJITID reJitId, /* [in] */ ULONG32 cMap, /* [out] */ ULONG32 *pcMap, /* [length_is][size_is][out] */ COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *EnumJITedFunctions2 )( ICorProfilerInfo13 * This, /* [out] */ ICorProfilerFunctionEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetObjectSize2 )( ICorProfilerInfo13 * This, /* [in] */ ObjectID objectId, /* [out] */ SIZE_T *pcSize); HRESULT ( STDMETHODCALLTYPE *GetEventMask2 )( ICorProfilerInfo13 * This, /* [out] */ DWORD *pdwEventsLow, /* [out] */ DWORD *pdwEventsHigh); HRESULT ( STDMETHODCALLTYPE *SetEventMask2 )( ICorProfilerInfo13 * This, /* [in] */ DWORD dwEventsLow, /* [in] */ DWORD dwEventsHigh); HRESULT ( STDMETHODCALLTYPE *EnumNgenModuleMethodsInliningThisMethod )( ICorProfilerInfo13 * This, /* [in] */ ModuleID inlinersModuleId, /* [in] */ ModuleID inlineeModuleId, /* [in] */ mdMethodDef inlineeMethodId, /* [out] */ BOOL *incompleteData, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *ApplyMetaData )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId); HRESULT ( STDMETHODCALLTYPE *GetInMemorySymbolsLength )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [out] */ DWORD *pCountSymbolBytes); HRESULT ( STDMETHODCALLTYPE *ReadInMemorySymbols )( ICorProfilerInfo13 * This, /* [in] */ ModuleID moduleId, /* [in] */ DWORD symbolsReadOffset, /* [out] */ BYTE *pSymbolBytes, /* [in] */ DWORD countSymbolBytes, /* [out] */ DWORD *pCountSymbolBytesRead); HRESULT ( STDMETHODCALLTYPE *IsFunctionDynamic )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [out] */ BOOL *isDynamic); HRESULT ( STDMETHODCALLTYPE *GetFunctionFromIP3 )( ICorProfilerInfo13 * This, /* [in] */ LPCBYTE ip, /* [out] */ FunctionID *functionId, /* [out] */ ReJITID *pReJitId); HRESULT ( STDMETHODCALLTYPE *GetDynamicFunctionInfo )( ICorProfilerInfo13 * This, /* [in] */ FunctionID functionId, /* [out] */ ModuleID *moduleId, /* [out] */ PCCOR_SIGNATURE *ppvSig, /* [out] */ ULONG *pbSig, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [out] */ WCHAR wszName[ ]); HRESULT ( STDMETHODCALLTYPE *GetNativeCodeStartAddresses )( ICorProfilerInfo13 * This, FunctionID functionID, ReJITID reJitId, ULONG32 cCodeStartAddresses, ULONG32 *pcCodeStartAddresses, UINT_PTR codeStartAddresses[ ]); HRESULT ( STDMETHODCALLTYPE *GetILToNativeMapping3 )( ICorProfilerInfo13 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cMap, ULONG32 *pcMap, COR_DEBUG_IL_TO_NATIVE_MAP map[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeInfo4 )( ICorProfilerInfo13 * This, UINT_PTR pNativeCodeStartAddress, ULONG32 cCodeInfos, ULONG32 *pcCodeInfos, COR_PRF_CODE_INFO codeInfos[ ]); HRESULT ( STDMETHODCALLTYPE *EnumerateObjectReferences )( ICorProfilerInfo13 * This, ObjectID objectId, ObjectReferenceCallback callback, void *clientData); HRESULT ( STDMETHODCALLTYPE *IsFrozenObject )( ICorProfilerInfo13 * This, ObjectID objectId, BOOL *pbFrozen); HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )( ICorProfilerInfo13 * This, DWORD *pThreshold); HRESULT ( STDMETHODCALLTYPE *RequestReJITWithInliners )( ICorProfilerInfo13 * This, /* [in] */ DWORD dwRejitFlags, /* [in] */ ULONG cFunctions, /* [size_is][in] */ ModuleID moduleIds[ ], /* [size_is][in] */ mdMethodDef methodIds[ ]); HRESULT ( STDMETHODCALLTYPE *SuspendRuntime )( ICorProfilerInfo13 * This); HRESULT ( STDMETHODCALLTYPE *ResumeRuntime )( ICorProfilerInfo13 * This); HRESULT ( STDMETHODCALLTYPE *GetEnvironmentVariable )( ICorProfilerInfo13 * This, /* [string][in] */ const WCHAR *szName, /* [in] */ ULONG cchValue, /* [out] */ ULONG *pcchValue, /* [annotation][out] */ _Out_writes_to_(cchValue, *pcchValue) WCHAR szValue[ ]); HRESULT ( STDMETHODCALLTYPE *SetEnvironmentVariable )( ICorProfilerInfo13 * This, /* [string][in] */ const WCHAR *szName, /* [string][in] */ const WCHAR *szValue); HRESULT ( STDMETHODCALLTYPE *EventPipeStartSession )( ICorProfilerInfo13 * This, /* [in] */ UINT32 cProviderConfigs, /* [size_is][in] */ COR_PRF_EVENTPIPE_PROVIDER_CONFIG pProviderConfigs[ ], /* [in] */ BOOL requestRundown, /* [out] */ EVENTPIPE_SESSION *pSession); HRESULT ( STDMETHODCALLTYPE *EventPipeAddProviderToSession )( ICorProfilerInfo13 * This, /* [in] */ EVENTPIPE_SESSION session, /* [in] */ COR_PRF_EVENTPIPE_PROVIDER_CONFIG providerConfig); HRESULT ( STDMETHODCALLTYPE *EventPipeStopSession )( ICorProfilerInfo13 * This, /* [in] */ EVENTPIPE_SESSION session); HRESULT ( STDMETHODCALLTYPE *EventPipeCreateProvider )( ICorProfilerInfo13 * This, /* [string][in] */ const WCHAR *providerName, /* [out] */ EVENTPIPE_PROVIDER *pProvider); HRESULT ( STDMETHODCALLTYPE *EventPipeGetProviderInfo )( ICorProfilerInfo13 * This, /* [in] */ EVENTPIPE_PROVIDER provider, /* [in] */ ULONG cchName, /* [out] */ ULONG *pcchName, /* [annotation][out] */ _Out_writes_to_(cchName, *pcchName) WCHAR providerName[ ]); HRESULT ( STDMETHODCALLTYPE *EventPipeDefineEvent )( ICorProfilerInfo13 * This, /* [in] */ EVENTPIPE_PROVIDER provider, /* [string][in] */ const WCHAR *eventName, /* [in] */ UINT32 eventID, /* [in] */ UINT64 keywords, /* [in] */ UINT32 eventVersion, /* [in] */ UINT32 level, /* [in] */ UINT8 opcode, /* [in] */ BOOL needStack, /* [in] */ UINT32 cParamDescs, /* [size_is][in] */ COR_PRF_EVENTPIPE_PARAM_DESC pParamDescs[ ], /* [out] */ EVENTPIPE_EVENT *pEvent); HRESULT ( STDMETHODCALLTYPE *EventPipeWriteEvent )( ICorProfilerInfo13 * This, /* [in] */ EVENTPIPE_EVENT event, /* [in] */ UINT32 cData, /* [size_is][in] */ COR_PRF_EVENT_DATA data[ ], /* [in] */ LPCGUID pActivityId, /* [in] */ LPCGUID pRelatedActivityId); HRESULT ( STDMETHODCALLTYPE CreateHandle )( ICorProfilerInfo13 * This, /* [in] */ ObjectID object, /* [in] */ COR_PRF_HANDLE_TYPE type, /* [out] */ ObjectHandleID* pHandle); HRESULT ( STDMETHODCALLTYPE DestroyHandle )( ICorProfilerInfo13 * This, /* [in] */ ObjectHandleID handle); HRESULT ( STDMETHODCALLTYPE GetObjectIDFromHandle )( ICorProfilerInfo13 * This, /* [in] */ ObjectHandleID handle, /* [out] */ ObjectID* pObject); END_INTERFACE } ICorProfilerInfo13Vtbl; interface ICorProfilerInfo13 { CONST_VTBL struct ICorProfilerInfo13Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerInfo13_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerInfo13_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerInfo13_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerInfo13_GetClassFromObject(This,objectId,pClassId) \ ( (This)->lpVtbl -> GetClassFromObject(This,objectId,pClassId) ) #define ICorProfilerInfo13_GetClassFromToken(This,moduleId,typeDef,pClassId) \ ( (This)->lpVtbl -> GetClassFromToken(This,moduleId,typeDef,pClassId) ) #define ICorProfilerInfo13_GetCodeInfo(This,functionId,pStart,pcSize) \ ( (This)->lpVtbl -> GetCodeInfo(This,functionId,pStart,pcSize) ) #define ICorProfilerInfo13_GetEventMask(This,pdwEvents) \ ( (This)->lpVtbl -> GetEventMask(This,pdwEvents) ) #define ICorProfilerInfo13_GetFunctionFromIP(This,ip,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromIP(This,ip,pFunctionId) ) #define ICorProfilerInfo13_GetFunctionFromToken(This,moduleId,token,pFunctionId) \ ( (This)->lpVtbl -> GetFunctionFromToken(This,moduleId,token,pFunctionId) ) #define ICorProfilerInfo13_GetHandleFromThread(This,threadId,phThread) \ ( (This)->lpVtbl -> GetHandleFromThread(This,threadId,phThread) ) #define ICorProfilerInfo13_GetObjectSize(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize(This,objectId,pcSize) ) #define ICorProfilerInfo13_IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) \ ( (This)->lpVtbl -> IsArrayClass(This,classId,pBaseElemType,pBaseClassId,pcRank) ) #define ICorProfilerInfo13_GetThreadInfo(This,threadId,pdwWin32ThreadId) \ ( (This)->lpVtbl -> GetThreadInfo(This,threadId,pdwWin32ThreadId) ) #define ICorProfilerInfo13_GetCurrentThreadID(This,pThreadId) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,pThreadId) ) #define ICorProfilerInfo13_GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) \ ( (This)->lpVtbl -> GetClassIDInfo(This,classId,pModuleId,pTypeDefToken) ) #define ICorProfilerInfo13_GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) \ ( (This)->lpVtbl -> GetFunctionInfo(This,functionId,pClassId,pModuleId,pToken) ) #define ICorProfilerInfo13_SetEventMask(This,dwEvents) \ ( (This)->lpVtbl -> SetEventMask(This,dwEvents) ) #define ICorProfilerInfo13_SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo13_SetFunctionIDMapper(This,pFunc) \ ( (This)->lpVtbl -> SetFunctionIDMapper(This,pFunc) ) #define ICorProfilerInfo13_GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) \ ( (This)->lpVtbl -> GetTokenAndMetaDataFromFunction(This,functionId,riid,ppImport,pToken) ) #define ICorProfilerInfo13_GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) \ ( (This)->lpVtbl -> GetModuleInfo(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId) ) #define ICorProfilerInfo13_GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) \ ( (This)->lpVtbl -> GetModuleMetaData(This,moduleId,dwOpenFlags,riid,ppOut) ) #define ICorProfilerInfo13_GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) \ ( (This)->lpVtbl -> GetILFunctionBody(This,moduleId,methodId,ppMethodHeader,pcbMethodSize) ) #define ICorProfilerInfo13_GetILFunctionBodyAllocator(This,moduleId,ppMalloc) \ ( (This)->lpVtbl -> GetILFunctionBodyAllocator(This,moduleId,ppMalloc) ) #define ICorProfilerInfo13_SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) \ ( (This)->lpVtbl -> SetILFunctionBody(This,moduleId,methodid,pbNewILMethodHeader) ) #define ICorProfilerInfo13_GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) \ ( (This)->lpVtbl -> GetAppDomainInfo(This,appDomainId,cchName,pcchName,szName,pProcessId) ) #define ICorProfilerInfo13_GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) \ ( (This)->lpVtbl -> GetAssemblyInfo(This,assemblyId,cchName,pcchName,szName,pAppDomainId,pModuleId) ) #define ICorProfilerInfo13_SetFunctionReJIT(This,functionId) \ ( (This)->lpVtbl -> SetFunctionReJIT(This,functionId) ) #define ICorProfilerInfo13_ForceGC(This) \ ( (This)->lpVtbl -> ForceGC(This) ) #define ICorProfilerInfo13_SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) \ ( (This)->lpVtbl -> SetILInstrumentedCodeMap(This,functionId,fStartJit,cILMapEntries,rgILMapEntries) ) #define ICorProfilerInfo13_GetInprocInspectionInterface(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionInterface(This,ppicd) ) #define ICorProfilerInfo13_GetInprocInspectionIThisThread(This,ppicd) \ ( (This)->lpVtbl -> GetInprocInspectionIThisThread(This,ppicd) ) #define ICorProfilerInfo13_GetThreadContext(This,threadId,pContextId) \ ( (This)->lpVtbl -> GetThreadContext(This,threadId,pContextId) ) #define ICorProfilerInfo13_BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) \ ( (This)->lpVtbl -> BeginInprocDebugging(This,fThisThreadOnly,pdwProfilerContext) ) #define ICorProfilerInfo13_EndInprocDebugging(This,dwProfilerContext) \ ( (This)->lpVtbl -> EndInprocDebugging(This,dwProfilerContext) ) #define ICorProfilerInfo13_GetILToNativeMapping(This,functionId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping(This,functionId,cMap,pcMap,map) ) #define ICorProfilerInfo13_DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) \ ( (This)->lpVtbl -> DoStackSnapshot(This,thread,callback,infoFlags,clientData,context,contextSize) ) #define ICorProfilerInfo13_SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks2(This,pFuncEnter,pFuncLeave,pFuncTailcall) ) #define ICorProfilerInfo13_GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetFunctionInfo2(This,funcId,frameInfo,pClassId,pModuleId,pToken,cTypeArgs,pcTypeArgs,typeArgs) ) #define ICorProfilerInfo13_GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout(This,pBufferLengthOffset,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo13_GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) \ ( (This)->lpVtbl -> GetClassLayout(This,classID,rFieldOffset,cFieldOffset,pcFieldOffset,pulClassSize) ) #define ICorProfilerInfo13_GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) \ ( (This)->lpVtbl -> GetClassIDInfo2(This,classId,pModuleId,pTypeDefToken,pParentClassId,cNumTypeArgs,pcNumTypeArgs,typeArgs) ) #define ICorProfilerInfo13_GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo2(This,functionID,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo13_GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) \ ( (This)->lpVtbl -> GetClassFromTokenAndTypeArgs(This,moduleID,typeDef,cTypeArgs,typeArgs,pClassID) ) #define ICorProfilerInfo13_GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) \ ( (This)->lpVtbl -> GetFunctionFromTokenAndTypeArgs(This,moduleID,funcDef,classId,cTypeArgs,typeArgs,pFunctionID) ) #define ICorProfilerInfo13_EnumModuleFrozenObjects(This,moduleID,ppEnum) \ ( (This)->lpVtbl -> EnumModuleFrozenObjects(This,moduleID,ppEnum) ) #define ICorProfilerInfo13_GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) \ ( (This)->lpVtbl -> GetArrayObjectInfo(This,objectId,cDimensions,pDimensionSizes,pDimensionLowerBounds,ppData) ) #define ICorProfilerInfo13_GetBoxClassLayout(This,classId,pBufferOffset) \ ( (This)->lpVtbl -> GetBoxClassLayout(This,classId,pBufferOffset) ) #define ICorProfilerInfo13_GetThreadAppDomain(This,threadId,pAppDomainId) \ ( (This)->lpVtbl -> GetThreadAppDomain(This,threadId,pAppDomainId) ) #define ICorProfilerInfo13_GetRVAStaticAddress(This,classId,fieldToken,ppAddress) \ ( (This)->lpVtbl -> GetRVAStaticAddress(This,classId,fieldToken,ppAddress) ) #define ICorProfilerInfo13_GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) \ ( (This)->lpVtbl -> GetAppDomainStaticAddress(This,classId,fieldToken,appDomainId,ppAddress) ) #define ICorProfilerInfo13_GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress(This,classId,fieldToken,threadId,ppAddress) ) #define ICorProfilerInfo13_GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) \ ( (This)->lpVtbl -> GetContextStaticAddress(This,classId,fieldToken,contextId,ppAddress) ) #define ICorProfilerInfo13_GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) \ ( (This)->lpVtbl -> GetStaticFieldInfo(This,classId,fieldToken,pFieldInfo) ) #define ICorProfilerInfo13_GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) \ ( (This)->lpVtbl -> GetGenerationBounds(This,cObjectRanges,pcObjectRanges,ranges) ) #define ICorProfilerInfo13_GetObjectGeneration(This,objectId,range) \ ( (This)->lpVtbl -> GetObjectGeneration(This,objectId,range) ) #define ICorProfilerInfo13_GetNotifiedExceptionClauseInfo(This,pinfo) \ ( (This)->lpVtbl -> GetNotifiedExceptionClauseInfo(This,pinfo) ) #define ICorProfilerInfo13_EnumJITedFunctions(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions(This,ppEnum) ) #define ICorProfilerInfo13_RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) \ ( (This)->lpVtbl -> RequestProfilerDetach(This,dwExpectedCompletionMilliseconds) ) #define ICorProfilerInfo13_SetFunctionIDMapper2(This,pFunc,clientData) \ ( (This)->lpVtbl -> SetFunctionIDMapper2(This,pFunc,clientData) ) #define ICorProfilerInfo13_GetStringLayout2(This,pStringLengthOffset,pBufferOffset) \ ( (This)->lpVtbl -> GetStringLayout2(This,pStringLengthOffset,pBufferOffset) ) #define ICorProfilerInfo13_SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3(This,pFuncEnter3,pFuncLeave3,pFuncTailcall3) ) #define ICorProfilerInfo13_SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) \ ( (This)->lpVtbl -> SetEnterLeaveFunctionHooks3WithInfo(This,pFuncEnter3WithInfo,pFuncLeave3WithInfo,pFuncTailcall3WithInfo) ) #define ICorProfilerInfo13_GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) \ ( (This)->lpVtbl -> GetFunctionEnter3Info(This,functionId,eltInfo,pFrameInfo,pcbArgumentInfo,pArgumentInfo) ) #define ICorProfilerInfo13_GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) \ ( (This)->lpVtbl -> GetFunctionLeave3Info(This,functionId,eltInfo,pFrameInfo,pRetvalRange) ) #define ICorProfilerInfo13_GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) \ ( (This)->lpVtbl -> GetFunctionTailcall3Info(This,functionId,eltInfo,pFrameInfo) ) #define ICorProfilerInfo13_EnumModules(This,ppEnum) \ ( (This)->lpVtbl -> EnumModules(This,ppEnum) ) #define ICorProfilerInfo13_GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) \ ( (This)->lpVtbl -> GetRuntimeInformation(This,pClrInstanceId,pRuntimeType,pMajorVersion,pMinorVersion,pBuildNumber,pQFEVersion,cchVersionString,pcchVersionString,szVersionString) ) #define ICorProfilerInfo13_GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) \ ( (This)->lpVtbl -> GetThreadStaticAddress2(This,classId,fieldToken,appDomainId,threadId,ppAddress) ) #define ICorProfilerInfo13_GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) \ ( (This)->lpVtbl -> GetAppDomainsContainingModule(This,moduleId,cAppDomainIds,pcAppDomainIds,appDomainIds) ) #define ICorProfilerInfo13_GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) \ ( (This)->lpVtbl -> GetModuleInfo2(This,moduleId,ppBaseLoadAddress,cchName,pcchName,szName,pAssemblyId,pdwModuleFlags) ) #define ICorProfilerInfo13_EnumThreads(This,ppEnum) \ ( (This)->lpVtbl -> EnumThreads(This,ppEnum) ) #define ICorProfilerInfo13_InitializeCurrentThread(This) \ ( (This)->lpVtbl -> InitializeCurrentThread(This) ) #define ICorProfilerInfo13_RequestReJIT(This,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJIT(This,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo13_RequestRevert(This,cFunctions,moduleIds,methodIds,status) \ ( (This)->lpVtbl -> RequestRevert(This,cFunctions,moduleIds,methodIds,status) ) #define ICorProfilerInfo13_GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo3(This,functionID,reJitId,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo13_GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP2(This,ip,pFunctionId,pReJitId) ) #define ICorProfilerInfo13_GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) \ ( (This)->lpVtbl -> GetReJITIDs(This,functionId,cReJitIds,pcReJitIds,reJitIds) ) #define ICorProfilerInfo13_GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping2(This,functionId,reJitId,cMap,pcMap,map) ) #define ICorProfilerInfo13_EnumJITedFunctions2(This,ppEnum) \ ( (This)->lpVtbl -> EnumJITedFunctions2(This,ppEnum) ) #define ICorProfilerInfo13_GetObjectSize2(This,objectId,pcSize) \ ( (This)->lpVtbl -> GetObjectSize2(This,objectId,pcSize) ) #define ICorProfilerInfo13_GetEventMask2(This,pdwEventsLow,pdwEventsHigh) \ ( (This)->lpVtbl -> GetEventMask2(This,pdwEventsLow,pdwEventsHigh) ) #define ICorProfilerInfo13_SetEventMask2(This,dwEventsLow,dwEventsHigh) \ ( (This)->lpVtbl -> SetEventMask2(This,dwEventsLow,dwEventsHigh) ) #define ICorProfilerInfo13_EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) \ ( (This)->lpVtbl -> EnumNgenModuleMethodsInliningThisMethod(This,inlinersModuleId,inlineeModuleId,inlineeMethodId,incompleteData,ppEnum) ) #define ICorProfilerInfo13_ApplyMetaData(This,moduleId) \ ( (This)->lpVtbl -> ApplyMetaData(This,moduleId) ) #define ICorProfilerInfo13_GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) \ ( (This)->lpVtbl -> GetInMemorySymbolsLength(This,moduleId,pCountSymbolBytes) ) #define ICorProfilerInfo13_ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) \ ( (This)->lpVtbl -> ReadInMemorySymbols(This,moduleId,symbolsReadOffset,pSymbolBytes,countSymbolBytes,pCountSymbolBytesRead) ) #define ICorProfilerInfo13_IsFunctionDynamic(This,functionId,isDynamic) \ ( (This)->lpVtbl -> IsFunctionDynamic(This,functionId,isDynamic) ) #define ICorProfilerInfo13_GetFunctionFromIP3(This,ip,functionId,pReJitId) \ ( (This)->lpVtbl -> GetFunctionFromIP3(This,ip,functionId,pReJitId) ) #define ICorProfilerInfo13_GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) \ ( (This)->lpVtbl -> GetDynamicFunctionInfo(This,functionId,moduleId,ppvSig,pbSig,cchName,pcchName,wszName) ) #define ICorProfilerInfo13_GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) \ ( (This)->lpVtbl -> GetNativeCodeStartAddresses(This,functionID,reJitId,cCodeStartAddresses,pcCodeStartAddresses,codeStartAddresses) ) #define ICorProfilerInfo13_GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) \ ( (This)->lpVtbl -> GetILToNativeMapping3(This,pNativeCodeStartAddress,cMap,pcMap,map) ) #define ICorProfilerInfo13_GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) \ ( (This)->lpVtbl -> GetCodeInfo4(This,pNativeCodeStartAddress,cCodeInfos,pcCodeInfos,codeInfos) ) #define ICorProfilerInfo13_EnumerateObjectReferences(This,objectId,callback,clientData) \ ( (This)->lpVtbl -> EnumerateObjectReferences(This,objectId,callback,clientData) ) #define ICorProfilerInfo13_IsFrozenObject(This,objectId,pbFrozen) \ ( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) ) #define ICorProfilerInfo13_GetLOHObjectSizeThreshold(This,pThreshold) \ ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) ) #define ICorProfilerInfo13_RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) \ ( (This)->lpVtbl -> RequestReJITWithInliners(This,dwRejitFlags,cFunctions,moduleIds,methodIds) ) #define ICorProfilerInfo13_SuspendRuntime(This) \ ( (This)->lpVtbl -> SuspendRuntime(This) ) #define ICorProfilerInfo13_ResumeRuntime(This) \ ( (This)->lpVtbl -> ResumeRuntime(This) ) #define ICorProfilerInfo13_GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) \ ( (This)->lpVtbl -> GetEnvironmentVariable(This,szName,cchValue,pcchValue,szValue) ) #define ICorProfilerInfo13_SetEnvironmentVariable(This,szName,szValue) \ ( (This)->lpVtbl -> SetEnvironmentVariable(This,szName,szValue) ) #define ICorProfilerInfo13_EventPipeStartSession(This,cProviderConfigs,pProviderConfigs,requestRundown,pSession) \ ( (This)->lpVtbl -> EventPipeStartSession(This,cProviderConfigs,pProviderConfigs,requestRundown,pSession) ) #define ICorProfilerInfo13_EventPipeAddProviderToSession(This,session,providerConfig) \ ( (This)->lpVtbl -> EventPipeAddProviderToSession(This,session,providerConfig) ) #define ICorProfilerInfo13_EventPipeStopSession(This,session) \ ( (This)->lpVtbl -> EventPipeStopSession(This,session) ) #define ICorProfilerInfo13_EventPipeCreateProvider(This,providerName,pProvider) \ ( (This)->lpVtbl -> EventPipeCreateProvider(This,providerName,pProvider) ) #define ICorProfilerInfo13_EventPipeGetProviderInfo(This,provider,cchName,pcchName,providerName) \ ( (This)->lpVtbl -> EventPipeGetProviderInfo(This,provider,cchName,pcchName,providerName) ) #define ICorProfilerInfo13_EventPipeDefineEvent(This,provider,eventName,eventID,keywords,eventVersion,level,opcode,needStack,cParamDescs,pParamDescs,pEvent) \ ( (This)->lpVtbl -> EventPipeDefineEvent(This,provider,eventName,eventID,keywords,eventVersion,level,opcode,needStack,cParamDescs,pParamDescs,pEvent) ) #define ICorProfilerInfo13_EventPipeWriteEvent(This,event,cData,data,pActivityId,pRelatedActivityId) \ ( (This)->lpVtbl -> EventPipeWriteEvent(This,event,cData,data,pActivityId,pRelatedActivityId) ) #define ICorProfilerInfo13_CreateHandle(This,object,type,pHandle) \ ( (This)->lpVtbl -> CreateHandle(This,object,type,pHandle) ) #define ICorProfilerInfo13_DestroyHandle(This,handle) \ ( (This)->lpVtbl -> DestroyHandle(This,handle) ) #define ICorProfilerInfo13_GetObjectIDFromHandle(This,handle,pObject) \ ( (This)->lpVtbl -> GetObjectIDFromHandle(This,handle,pObject) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerInfo13_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerMethodEnum_INTERFACE_DEFINED__ #define __ICorProfilerMethodEnum_INTERFACE_DEFINED__ /* interface ICorProfilerMethodEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerMethodEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FCCEE788-0088-454B-A811-C99F298D1942") ICorProfilerMethodEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorProfilerMethodEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_PRF_METHOD elements[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorProfilerMethodEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerMethodEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerMethodEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerMethodEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorProfilerMethodEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorProfilerMethodEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorProfilerMethodEnum * This, /* [out] */ ICorProfilerMethodEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorProfilerMethodEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorProfilerMethodEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ COR_PRF_METHOD elements[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorProfilerMethodEnumVtbl; interface ICorProfilerMethodEnum { CONST_VTBL struct ICorProfilerMethodEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerMethodEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerMethodEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerMethodEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerMethodEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorProfilerMethodEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorProfilerMethodEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorProfilerMethodEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorProfilerMethodEnum_Next(This,celt,elements,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,elements,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerMethodEnum_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerThreadEnum_INTERFACE_DEFINED__ #define __ICorProfilerThreadEnum_INTERFACE_DEFINED__ /* interface ICorProfilerThreadEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerThreadEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("571194f7-25ed-419f-aa8b-7016b3159701") ICorProfilerThreadEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorProfilerThreadEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ThreadID ids[ ], /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorProfilerThreadEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerThreadEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerThreadEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerThreadEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorProfilerThreadEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorProfilerThreadEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorProfilerThreadEnum * This, /* [out] */ ICorProfilerThreadEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorProfilerThreadEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorProfilerThreadEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ThreadID ids[ ], /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorProfilerThreadEnumVtbl; interface ICorProfilerThreadEnum { CONST_VTBL struct ICorProfilerThreadEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerThreadEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerThreadEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerThreadEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerThreadEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorProfilerThreadEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorProfilerThreadEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorProfilerThreadEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorProfilerThreadEnum_Next(This,celt,ids,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,ids,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerThreadEnum_INTERFACE_DEFINED__ */ #ifndef __ICorProfilerAssemblyReferenceProvider_INTERFACE_DEFINED__ #define __ICorProfilerAssemblyReferenceProvider_INTERFACE_DEFINED__ /* interface ICorProfilerAssemblyReferenceProvider */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorProfilerAssemblyReferenceProvider; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("66A78C24-2EEF-4F65-B45F-DD1D8038BF3C") ICorProfilerAssemblyReferenceProvider : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE AddAssemblyReference( const COR_PRF_ASSEMBLY_REFERENCE_INFO *pAssemblyRefInfo) = 0; }; #else /* C style interface */ typedef struct ICorProfilerAssemblyReferenceProviderVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorProfilerAssemblyReferenceProvider * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorProfilerAssemblyReferenceProvider * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorProfilerAssemblyReferenceProvider * This); HRESULT ( STDMETHODCALLTYPE *AddAssemblyReference )( ICorProfilerAssemblyReferenceProvider * This, const COR_PRF_ASSEMBLY_REFERENCE_INFO *pAssemblyRefInfo); END_INTERFACE } ICorProfilerAssemblyReferenceProviderVtbl; interface ICorProfilerAssemblyReferenceProvider { CONST_VTBL struct ICorProfilerAssemblyReferenceProviderVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorProfilerAssemblyReferenceProvider_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorProfilerAssemblyReferenceProvider_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorProfilerAssemblyReferenceProvider_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorProfilerAssemblyReferenceProvider_AddAssemblyReference(This,pAssemblyRefInfo) \ ( (This)->lpVtbl -> AddAssemblyReference(This,pAssemblyRefInfo) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorProfilerAssemblyReferenceProvider_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/corpub.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.00.0603 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif // __RPCNDR_H_VERSION__ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __corpub_h__ #define __corpub_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __CorpubPublish_FWD_DEFINED__ #define __CorpubPublish_FWD_DEFINED__ #ifdef __cplusplus typedef class CorpubPublish CorpubPublish; #else typedef struct CorpubPublish CorpubPublish; #endif /* __cplusplus */ #endif /* __CorpubPublish_FWD_DEFINED__ */ #ifndef __ICorPublish_FWD_DEFINED__ #define __ICorPublish_FWD_DEFINED__ typedef interface ICorPublish ICorPublish; #endif /* __ICorPublish_FWD_DEFINED__ */ #ifndef __ICorPublishEnum_FWD_DEFINED__ #define __ICorPublishEnum_FWD_DEFINED__ typedef interface ICorPublishEnum ICorPublishEnum; #endif /* __ICorPublishEnum_FWD_DEFINED__ */ #ifndef __ICorPublishProcess_FWD_DEFINED__ #define __ICorPublishProcess_FWD_DEFINED__ typedef interface ICorPublishProcess ICorPublishProcess; #endif /* __ICorPublishProcess_FWD_DEFINED__ */ #ifndef __ICorPublishAppDomain_FWD_DEFINED__ #define __ICorPublishAppDomain_FWD_DEFINED__ typedef interface ICorPublishAppDomain ICorPublishAppDomain; #endif /* __ICorPublishAppDomain_FWD_DEFINED__ */ #ifndef __ICorPublishProcessEnum_FWD_DEFINED__ #define __ICorPublishProcessEnum_FWD_DEFINED__ typedef interface ICorPublishProcessEnum ICorPublishProcessEnum; #endif /* __ICorPublishProcessEnum_FWD_DEFINED__ */ #ifndef __ICorPublishAppDomainEnum_FWD_DEFINED__ #define __ICorPublishAppDomainEnum_FWD_DEFINED__ typedef interface ICorPublishAppDomainEnum ICorPublishAppDomainEnum; #endif /* __ICorPublishAppDomainEnum_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_corpub_0000_0000 */ /* [local] */ #if 0 #endif typedef /* [public][public] */ enum __MIDL___MIDL_itf_corpub_0000_0000_0001 { COR_PUB_MANAGEDONLY = 0x1 } COR_PUB_ENUMPROCESS; #pragma warning(push) #pragma warning(disable:28718) #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0000_v0_0_s_ifspec; #ifndef __CorpubProcessLib_LIBRARY_DEFINED__ #define __CorpubProcessLib_LIBRARY_DEFINED__ /* library CorpubProcessLib */ /* [helpstring][version][uuid] */ EXTERN_C const IID LIBID_CorpubProcessLib; EXTERN_C const CLSID CLSID_CorpubPublish; #ifdef __cplusplus class DECLSPEC_UUID("047a9a40-657e-11d3-8d5b-00104b35e7ef") CorpubPublish; #endif #endif /* __CorpubProcessLib_LIBRARY_DEFINED__ */ #ifndef __ICorPublish_INTERFACE_DEFINED__ #define __ICorPublish_INTERFACE_DEFINED__ /* interface ICorPublish */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorPublish; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("9613A0E7-5A68-11d3-8F84-00A0C9B4D50C") ICorPublish : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE EnumProcesses( /* [in] */ COR_PUB_ENUMPROCESS Type, /* [out] */ ICorPublishProcessEnum **ppIEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [in] */ unsigned int pid, /* [out] */ ICorPublishProcess **ppProcess) = 0; }; #else /* C style interface */ typedef struct ICorPublishVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorPublish * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorPublish * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorPublish * This); HRESULT ( STDMETHODCALLTYPE *EnumProcesses )( ICorPublish * This, /* [in] */ COR_PUB_ENUMPROCESS Type, /* [out] */ ICorPublishProcessEnum **ppIEnum); HRESULT ( STDMETHODCALLTYPE *GetProcess )( ICorPublish * This, /* [in] */ unsigned int pid, /* [out] */ ICorPublishProcess **ppProcess); END_INTERFACE } ICorPublishVtbl; interface ICorPublish { CONST_VTBL struct ICorPublishVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorPublish_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorPublish_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorPublish_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorPublish_EnumProcesses(This,Type,ppIEnum) \ ( (This)->lpVtbl -> EnumProcesses(This,Type,ppIEnum) ) #define ICorPublish_GetProcess(This,pid,ppProcess) \ ( (This)->lpVtbl -> GetProcess(This,pid,ppProcess) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorPublish_INTERFACE_DEFINED__ */ #ifndef __ICorPublishEnum_INTERFACE_DEFINED__ #define __ICorPublishEnum_INTERFACE_DEFINED__ /* interface ICorPublishEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorPublishEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("C0B22967-5A69-11d3-8F84-00A0C9B4D50C") ICorPublishEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ ULONG celt) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE Clone( /* [out] */ ICorPublishEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ ULONG *pcelt) = 0; }; #else /* C style interface */ typedef struct ICorPublishEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorPublishEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorPublishEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorPublishEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorPublishEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorPublishEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorPublishEnum * This, /* [out] */ ICorPublishEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorPublishEnum * This, /* [out] */ ULONG *pcelt); END_INTERFACE } ICorPublishEnumVtbl; interface ICorPublishEnum { CONST_VTBL struct ICorPublishEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorPublishEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorPublishEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorPublishEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorPublishEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorPublishEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorPublishEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorPublishEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorPublishEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corpub_0000_0003 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0003_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0003_v0_0_s_ifspec; #ifndef __ICorPublishProcess_INTERFACE_DEFINED__ #define __ICorPublishProcess_INTERFACE_DEFINED__ /* interface ICorPublishProcess */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorPublishProcess; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("18D87AF1-5A6A-11d3-8F84-00A0C9B4D50C") ICorPublishProcess : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsManaged( /* [out] */ BOOL *pbManaged) = 0; virtual HRESULT STDMETHODCALLTYPE EnumAppDomains( /* [out] */ ICorPublishAppDomainEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetProcessID( /* [out] */ unsigned int *pid) = 0; virtual HRESULT STDMETHODCALLTYPE GetDisplayName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR *szName) = 0; }; #else /* C style interface */ typedef struct ICorPublishProcessVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorPublishProcess * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorPublishProcess * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorPublishProcess * This); HRESULT ( STDMETHODCALLTYPE *IsManaged )( ICorPublishProcess * This, /* [out] */ BOOL *pbManaged); HRESULT ( STDMETHODCALLTYPE *EnumAppDomains )( ICorPublishProcess * This, /* [out] */ ICorPublishAppDomainEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetProcessID )( ICorPublishProcess * This, /* [out] */ unsigned int *pid); HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( ICorPublishProcess * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR *szName); END_INTERFACE } ICorPublishProcessVtbl; interface ICorPublishProcess { CONST_VTBL struct ICorPublishProcessVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorPublishProcess_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorPublishProcess_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorPublishProcess_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorPublishProcess_IsManaged(This,pbManaged) \ ( (This)->lpVtbl -> IsManaged(This,pbManaged) ) #define ICorPublishProcess_EnumAppDomains(This,ppEnum) \ ( (This)->lpVtbl -> EnumAppDomains(This,ppEnum) ) #define ICorPublishProcess_GetProcessID(This,pid) \ ( (This)->lpVtbl -> GetProcessID(This,pid) ) #define ICorPublishProcess_GetDisplayName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetDisplayName(This,cchName,pcchName,szName) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorPublishProcess_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corpub_0000_0004 */ /* [local] */ #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0004_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0004_v0_0_s_ifspec; #ifndef __ICorPublishAppDomain_INTERFACE_DEFINED__ #define __ICorPublishAppDomain_INTERFACE_DEFINED__ /* interface ICorPublishAppDomain */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorPublishAppDomain; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D6315C8F-5A6A-11d3-8F84-00A0C9B4D50C") ICorPublishAppDomain : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetID( /* [out] */ ULONG32 *puId) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR *szName) = 0; }; #else /* C style interface */ typedef struct ICorPublishAppDomainVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorPublishAppDomain * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorPublishAppDomain * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorPublishAppDomain * This); HRESULT ( STDMETHODCALLTYPE *GetID )( ICorPublishAppDomain * This, /* [out] */ ULONG32 *puId); HRESULT ( STDMETHODCALLTYPE *GetName )( ICorPublishAppDomain * This, /* [in] */ ULONG32 cchName, /* [out] */ ULONG32 *pcchName, /* [length_is][size_is][out] */ WCHAR *szName); END_INTERFACE } ICorPublishAppDomainVtbl; interface ICorPublishAppDomain { CONST_VTBL struct ICorPublishAppDomainVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorPublishAppDomain_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorPublishAppDomain_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorPublishAppDomain_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorPublishAppDomain_GetID(This,puId) \ ( (This)->lpVtbl -> GetID(This,puId) ) #define ICorPublishAppDomain_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorPublishAppDomain_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corpub_0000_0005 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0005_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corpub_0000_0005_v0_0_s_ifspec; #ifndef __ICorPublishProcessEnum_INTERFACE_DEFINED__ #define __ICorPublishProcessEnum_INTERFACE_DEFINED__ /* interface ICorPublishProcessEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorPublishProcessEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A37FBD41-5A69-11d3-8F84-00A0C9B4D50C") ICorPublishProcessEnum : public ICorPublishEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorPublishProcess **objects, /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorPublishProcessEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorPublishProcessEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorPublishProcessEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorPublishProcessEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorPublishProcessEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorPublishProcessEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorPublishProcessEnum * This, /* [out] */ ICorPublishEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorPublishProcessEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorPublishProcessEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorPublishProcess **objects, /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorPublishProcessEnumVtbl; interface ICorPublishProcessEnum { CONST_VTBL struct ICorPublishProcessEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorPublishProcessEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorPublishProcessEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorPublishProcessEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorPublishProcessEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorPublishProcessEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorPublishProcessEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorPublishProcessEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorPublishProcessEnum_Next(This,celt,objects,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorPublishProcessEnum_INTERFACE_DEFINED__ */ #ifndef __ICorPublishAppDomainEnum_INTERFACE_DEFINED__ #define __ICorPublishAppDomainEnum_INTERFACE_DEFINED__ /* interface ICorPublishAppDomainEnum */ /* [local][unique][uuid][object] */ EXTERN_C const IID IID_ICorPublishAppDomainEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("9F0C98F5-5A6A-11d3-8F84-00A0C9B4D50C") ICorPublishAppDomainEnum : public ICorPublishEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorPublishAppDomain **objects, /* [out] */ ULONG *pceltFetched) = 0; }; #else /* C style interface */ typedef struct ICorPublishAppDomainEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorPublishAppDomainEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorPublishAppDomainEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorPublishAppDomainEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ICorPublishAppDomainEnum * This, /* [in] */ ULONG celt); HRESULT ( STDMETHODCALLTYPE *Reset )( ICorPublishAppDomainEnum * This); HRESULT ( STDMETHODCALLTYPE *Clone )( ICorPublishAppDomainEnum * This, /* [out] */ ICorPublishEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetCount )( ICorPublishAppDomainEnum * This, /* [out] */ ULONG *pcelt); HRESULT ( STDMETHODCALLTYPE *Next )( ICorPublishAppDomainEnum * This, /* [in] */ ULONG celt, /* [length_is][size_is][out] */ ICorPublishAppDomain **objects, /* [out] */ ULONG *pceltFetched); END_INTERFACE } ICorPublishAppDomainEnumVtbl; interface ICorPublishAppDomainEnum { CONST_VTBL struct ICorPublishAppDomainEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorPublishAppDomainEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorPublishAppDomainEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorPublishAppDomainEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorPublishAppDomainEnum_Skip(This,celt) \ ( (This)->lpVtbl -> Skip(This,celt) ) #define ICorPublishAppDomainEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ICorPublishAppDomainEnum_Clone(This,ppEnum) \ ( (This)->lpVtbl -> Clone(This,ppEnum) ) #define ICorPublishAppDomainEnum_GetCount(This,pcelt) \ ( (This)->lpVtbl -> GetCount(This,pcelt) ) #define ICorPublishAppDomainEnum_Next(This,celt,objects,pceltFetched) \ ( (This)->lpVtbl -> Next(This,celt,objects,pceltFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorPublishAppDomainEnum_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/corsym.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.00.0601 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCSAL_H_VERSION__ #define __REQUIRED_RPCSAL_H_VERSION__ 100 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif // __RPCNDR_H_VERSION__ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __corsym_h__ #define __corsym_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __CorSymWriter_deprecated_FWD_DEFINED__ #define __CorSymWriter_deprecated_FWD_DEFINED__ #ifdef __cplusplus typedef class CorSymWriter_deprecated CorSymWriter_deprecated; #else typedef struct CorSymWriter_deprecated CorSymWriter_deprecated; #endif /* __cplusplus */ #endif /* __CorSymWriter_deprecated_FWD_DEFINED__ */ #ifndef __CorSymReader_deprecated_FWD_DEFINED__ #define __CorSymReader_deprecated_FWD_DEFINED__ #ifdef __cplusplus typedef class CorSymReader_deprecated CorSymReader_deprecated; #else typedef struct CorSymReader_deprecated CorSymReader_deprecated; #endif /* __cplusplus */ #endif /* __CorSymReader_deprecated_FWD_DEFINED__ */ #ifndef __CorSymBinder_deprecated_FWD_DEFINED__ #define __CorSymBinder_deprecated_FWD_DEFINED__ #ifdef __cplusplus typedef class CorSymBinder_deprecated CorSymBinder_deprecated; #else typedef struct CorSymBinder_deprecated CorSymBinder_deprecated; #endif /* __cplusplus */ #endif /* __CorSymBinder_deprecated_FWD_DEFINED__ */ #ifndef __CorSymWriter_SxS_FWD_DEFINED__ #define __CorSymWriter_SxS_FWD_DEFINED__ #ifdef __cplusplus typedef class CorSymWriter_SxS CorSymWriter_SxS; #else typedef struct CorSymWriter_SxS CorSymWriter_SxS; #endif /* __cplusplus */ #endif /* __CorSymWriter_SxS_FWD_DEFINED__ */ #ifndef __CorSymReader_SxS_FWD_DEFINED__ #define __CorSymReader_SxS_FWD_DEFINED__ #ifdef __cplusplus typedef class CorSymReader_SxS CorSymReader_SxS; #else typedef struct CorSymReader_SxS CorSymReader_SxS; #endif /* __cplusplus */ #endif /* __CorSymReader_SxS_FWD_DEFINED__ */ #ifndef __CorSymBinder_SxS_FWD_DEFINED__ #define __CorSymBinder_SxS_FWD_DEFINED__ #ifdef __cplusplus typedef class CorSymBinder_SxS CorSymBinder_SxS; #else typedef struct CorSymBinder_SxS CorSymBinder_SxS; #endif /* __cplusplus */ #endif /* __CorSymBinder_SxS_FWD_DEFINED__ */ #ifndef __ISymUnmanagedBinder_FWD_DEFINED__ #define __ISymUnmanagedBinder_FWD_DEFINED__ typedef interface ISymUnmanagedBinder ISymUnmanagedBinder; #endif /* __ISymUnmanagedBinder_FWD_DEFINED__ */ #ifndef __ISymUnmanagedBinder2_FWD_DEFINED__ #define __ISymUnmanagedBinder2_FWD_DEFINED__ typedef interface ISymUnmanagedBinder2 ISymUnmanagedBinder2; #endif /* __ISymUnmanagedBinder2_FWD_DEFINED__ */ #ifndef __ISymUnmanagedBinder3_FWD_DEFINED__ #define __ISymUnmanagedBinder3_FWD_DEFINED__ typedef interface ISymUnmanagedBinder3 ISymUnmanagedBinder3; #endif /* __ISymUnmanagedBinder3_FWD_DEFINED__ */ #ifndef __ISymUnmanagedDispose_FWD_DEFINED__ #define __ISymUnmanagedDispose_FWD_DEFINED__ typedef interface ISymUnmanagedDispose ISymUnmanagedDispose; #endif /* __ISymUnmanagedDispose_FWD_DEFINED__ */ #ifndef __ISymUnmanagedDocument_FWD_DEFINED__ #define __ISymUnmanagedDocument_FWD_DEFINED__ typedef interface ISymUnmanagedDocument ISymUnmanagedDocument; #endif /* __ISymUnmanagedDocument_FWD_DEFINED__ */ #ifndef __ISymUnmanagedDocumentWriter_FWD_DEFINED__ #define __ISymUnmanagedDocumentWriter_FWD_DEFINED__ typedef interface ISymUnmanagedDocumentWriter ISymUnmanagedDocumentWriter; #endif /* __ISymUnmanagedDocumentWriter_FWD_DEFINED__ */ #ifndef __ISymUnmanagedMethod_FWD_DEFINED__ #define __ISymUnmanagedMethod_FWD_DEFINED__ typedef interface ISymUnmanagedMethod ISymUnmanagedMethod; #endif /* __ISymUnmanagedMethod_FWD_DEFINED__ */ #ifndef __ISymENCUnmanagedMethod_FWD_DEFINED__ #define __ISymENCUnmanagedMethod_FWD_DEFINED__ typedef interface ISymENCUnmanagedMethod ISymENCUnmanagedMethod; #endif /* __ISymENCUnmanagedMethod_FWD_DEFINED__ */ #ifndef __ISymUnmanagedNamespace_FWD_DEFINED__ #define __ISymUnmanagedNamespace_FWD_DEFINED__ typedef interface ISymUnmanagedNamespace ISymUnmanagedNamespace; #endif /* __ISymUnmanagedNamespace_FWD_DEFINED__ */ #ifndef __ISymUnmanagedReader_FWD_DEFINED__ #define __ISymUnmanagedReader_FWD_DEFINED__ typedef interface ISymUnmanagedReader ISymUnmanagedReader; #endif /* __ISymUnmanagedReader_FWD_DEFINED__ */ #ifndef __ISymUnmanagedSourceServerModule_FWD_DEFINED__ #define __ISymUnmanagedSourceServerModule_FWD_DEFINED__ typedef interface ISymUnmanagedSourceServerModule ISymUnmanagedSourceServerModule; #endif /* __ISymUnmanagedSourceServerModule_FWD_DEFINED__ */ #ifndef __ISymUnmanagedENCUpdate_FWD_DEFINED__ #define __ISymUnmanagedENCUpdate_FWD_DEFINED__ typedef interface ISymUnmanagedENCUpdate ISymUnmanagedENCUpdate; #endif /* __ISymUnmanagedENCUpdate_FWD_DEFINED__ */ #ifndef __ISymUnmanagedReaderSymbolSearchInfo_FWD_DEFINED__ #define __ISymUnmanagedReaderSymbolSearchInfo_FWD_DEFINED__ typedef interface ISymUnmanagedReaderSymbolSearchInfo ISymUnmanagedReaderSymbolSearchInfo; #endif /* __ISymUnmanagedReaderSymbolSearchInfo_FWD_DEFINED__ */ #ifndef __ISymUnmanagedScope_FWD_DEFINED__ #define __ISymUnmanagedScope_FWD_DEFINED__ typedef interface ISymUnmanagedScope ISymUnmanagedScope; #endif /* __ISymUnmanagedScope_FWD_DEFINED__ */ #ifndef __ISymUnmanagedConstant_FWD_DEFINED__ #define __ISymUnmanagedConstant_FWD_DEFINED__ typedef interface ISymUnmanagedConstant ISymUnmanagedConstant; #endif /* __ISymUnmanagedConstant_FWD_DEFINED__ */ #ifndef __ISymUnmanagedScope2_FWD_DEFINED__ #define __ISymUnmanagedScope2_FWD_DEFINED__ typedef interface ISymUnmanagedScope2 ISymUnmanagedScope2; #endif /* __ISymUnmanagedScope2_FWD_DEFINED__ */ #ifndef __ISymUnmanagedVariable_FWD_DEFINED__ #define __ISymUnmanagedVariable_FWD_DEFINED__ typedef interface ISymUnmanagedVariable ISymUnmanagedVariable; #endif /* __ISymUnmanagedVariable_FWD_DEFINED__ */ #ifndef __ISymUnmanagedSymbolSearchInfo_FWD_DEFINED__ #define __ISymUnmanagedSymbolSearchInfo_FWD_DEFINED__ typedef interface ISymUnmanagedSymbolSearchInfo ISymUnmanagedSymbolSearchInfo; #endif /* __ISymUnmanagedSymbolSearchInfo_FWD_DEFINED__ */ #ifndef __ISymUnmanagedWriter_FWD_DEFINED__ #define __ISymUnmanagedWriter_FWD_DEFINED__ typedef interface ISymUnmanagedWriter ISymUnmanagedWriter; #endif /* __ISymUnmanagedWriter_FWD_DEFINED__ */ #ifndef __ISymUnmanagedWriter2_FWD_DEFINED__ #define __ISymUnmanagedWriter2_FWD_DEFINED__ typedef interface ISymUnmanagedWriter2 ISymUnmanagedWriter2; #endif /* __ISymUnmanagedWriter2_FWD_DEFINED__ */ #ifndef __ISymUnmanagedWriter3_FWD_DEFINED__ #define __ISymUnmanagedWriter3_FWD_DEFINED__ typedef interface ISymUnmanagedWriter3 ISymUnmanagedWriter3; #endif /* __ISymUnmanagedWriter3_FWD_DEFINED__ */ #ifndef __ISymUnmanagedWriter4_FWD_DEFINED__ #define __ISymUnmanagedWriter4_FWD_DEFINED__ typedef interface ISymUnmanagedWriter4 ISymUnmanagedWriter4; #endif /* __ISymUnmanagedWriter4_FWD_DEFINED__ */ #ifndef __ISymUnmanagedWriter5_FWD_DEFINED__ #define __ISymUnmanagedWriter5_FWD_DEFINED__ typedef interface ISymUnmanagedWriter5 ISymUnmanagedWriter5; #endif /* __ISymUnmanagedWriter5_FWD_DEFINED__ */ #ifndef __ISymUnmanagedReader2_FWD_DEFINED__ #define __ISymUnmanagedReader2_FWD_DEFINED__ typedef interface ISymUnmanagedReader2 ISymUnmanagedReader2; #endif /* __ISymUnmanagedReader2_FWD_DEFINED__ */ #ifndef __ISymNGenWriter_FWD_DEFINED__ #define __ISymNGenWriter_FWD_DEFINED__ typedef interface ISymNGenWriter ISymNGenWriter; #endif /* __ISymNGenWriter_FWD_DEFINED__ */ #ifndef __ISymNGenWriter2_FWD_DEFINED__ #define __ISymNGenWriter2_FWD_DEFINED__ typedef interface ISymNGenWriter2 ISymNGenWriter2; #endif /* __ISymNGenWriter2_FWD_DEFINED__ */ #ifndef __ISymUnmanagedAsyncMethodPropertiesWriter_FWD_DEFINED__ #define __ISymUnmanagedAsyncMethodPropertiesWriter_FWD_DEFINED__ typedef interface ISymUnmanagedAsyncMethodPropertiesWriter ISymUnmanagedAsyncMethodPropertiesWriter; #endif /* __ISymUnmanagedAsyncMethodPropertiesWriter_FWD_DEFINED__ */ #ifndef __ISymUnmanagedAsyncMethod_FWD_DEFINED__ #define __ISymUnmanagedAsyncMethod_FWD_DEFINED__ typedef interface ISymUnmanagedAsyncMethod ISymUnmanagedAsyncMethod; #endif /* __ISymUnmanagedAsyncMethod_FWD_DEFINED__ */ #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_corsym_0000_0000 */ /* [local] */ #if 0 typedef typedef unsigned int UINT32; ; typedef mdToken mdTypeDef; typedef mdToken mdMethodDef; typedef typedef ULONG_PTR SIZE_T; ; #endif #ifndef __CORHDR_H__ typedef mdToken mdSignature; #endif #pragma once #pragma once #pragma region Input Buffer SAL 1 compatibility macros #pragma endregion Input Buffer SAL 1 compatibility macros #pragma once #pragma once EXTERN_GUID(CorSym_LanguageType_C, 0x63a08714, 0xfc37, 0x11d2, 0x90, 0x4c, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); EXTERN_GUID(CorSym_LanguageType_CPlusPlus, 0x3a12d0b7, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); EXTERN_GUID(CorSym_LanguageType_CSharp, 0x3f5162f8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); EXTERN_GUID(CorSym_LanguageType_Basic, 0x3a12d0b8, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); EXTERN_GUID(CorSym_LanguageType_Java, 0x3a12d0b4, 0xc26c, 0x11d0, 0xb4, 0x42, 0x0, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); EXTERN_GUID(CorSym_LanguageType_Cobol, 0xaf046cd1, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); EXTERN_GUID(CorSym_LanguageType_Pascal, 0xaf046cd2, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); EXTERN_GUID(CorSym_LanguageType_ILAssembly, 0xaf046cd3, 0xd0e1, 0x11d2, 0x97, 0x7c, 0x0, 0xa0, 0xc9, 0xb4, 0xd5, 0xc); EXTERN_GUID(CorSym_LanguageType_JScript, 0x3a12d0b6, 0xc26c, 0x11d0, 0xb4, 0x42, 0x00, 0xa0, 0x24, 0x4a, 0x1d, 0xd2); EXTERN_GUID(CorSym_LanguageType_SMC, 0xd9b9f7b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd); EXTERN_GUID(CorSym_LanguageType_MCPlusPlus, 0x4b35fde8, 0x07c6, 0x11d3, 0x90, 0x53, 0x0, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); EXTERN_GUID(CorSym_LanguageVendor_Microsoft, 0x994b45c4, 0xe6e9, 0x11d2, 0x90, 0x3f, 0x00, 0xc0, 0x4f, 0xa3, 0x02, 0xa1); EXTERN_GUID(CorSym_DocumentType_Text, 0x5a869d0b, 0x6611, 0x11d3, 0xbd, 0x2a, 0x0, 0x0, 0xf8, 0x8, 0x49, 0xbd); EXTERN_GUID(CorSym_DocumentType_MC, 0xeb40cb65, 0x3c1f, 0x4352, 0x9d, 0x7b, 0xba, 0xf, 0xc4, 0x7a, 0x9d, 0x77); EXTERN_GUID(CorSym_SourceHash_MD5, 0x406ea660, 0x64cf, 0x4c82, 0xb6, 0xf0, 0x42, 0xd4, 0x81, 0x72, 0xa7, 0x99); EXTERN_GUID(CorSym_SourceHash_SHA1, 0xff1816ec, 0xaa5e, 0x4d10, 0x87, 0xf7, 0x6f, 0x49, 0x63, 0x83, 0x34, 0x60); typedef enum CorSymAddrKind { ADDR_IL_OFFSET = 1, ADDR_NATIVE_RVA = 2, ADDR_NATIVE_REGISTER = 3, ADDR_NATIVE_REGREL = 4, ADDR_NATIVE_OFFSET = 5, ADDR_NATIVE_REGREG = 6, ADDR_NATIVE_REGSTK = 7, ADDR_NATIVE_STKREG = 8, ADDR_BITFIELD = 9, ADDR_NATIVE_ISECTOFFSET = 10 } CorSymAddrKind; typedef enum CorSymVarFlag { VAR_IS_COMP_GEN = 1 } CorSymVarFlag; extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0000_v0_0_s_ifspec; #ifndef __CorSymLib_LIBRARY_DEFINED__ #define __CorSymLib_LIBRARY_DEFINED__ /* library CorSymLib */ /* [helpstring][version][uuid] */ EXTERN_C const IID LIBID_CorSymLib; EXTERN_C const CLSID CLSID_CorSymWriter_deprecated; #ifdef __cplusplus class DECLSPEC_UUID("108296C1-281E-11d3-BD22-0000F80849BD") CorSymWriter_deprecated; #endif EXTERN_C const CLSID CLSID_CorSymReader_deprecated; #ifdef __cplusplus class DECLSPEC_UUID("108296C2-281E-11d3-BD22-0000F80849BD") CorSymReader_deprecated; #endif EXTERN_C const CLSID CLSID_CorSymBinder_deprecated; #ifdef __cplusplus class DECLSPEC_UUID("AA544D41-28CB-11d3-BD22-0000F80849BD") CorSymBinder_deprecated; #endif EXTERN_C const CLSID CLSID_CorSymWriter_SxS; #ifdef __cplusplus class DECLSPEC_UUID("0AE2DEB0-F901-478b-BB9F-881EE8066788") CorSymWriter_SxS; #endif EXTERN_C const CLSID CLSID_CorSymReader_SxS; #ifdef __cplusplus class DECLSPEC_UUID("0A3976C5-4529-4ef8-B0B0-42EED37082CD") CorSymReader_SxS; #endif EXTERN_C const CLSID CLSID_CorSymBinder_SxS; #ifdef __cplusplus class DECLSPEC_UUID("0A29FF9E-7F9C-4437-8B11-F424491E3931") CorSymBinder_SxS; #endif #endif /* __CorSymLib_LIBRARY_DEFINED__ */ #ifndef __ISymUnmanagedBinder_INTERFACE_DEFINED__ #define __ISymUnmanagedBinder_INTERFACE_DEFINED__ /* interface ISymUnmanagedBinder */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedBinder; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AA544D42-28CB-11d3-BD22-0000F80849BD") ISymUnmanagedBinder : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetReaderForFile( /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetReaderFromStream( /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in_opt IStream *pstream, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedBinderVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedBinder * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedBinder * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedBinder * This); HRESULT ( STDMETHODCALLTYPE *GetReaderForFile )( __RPC__in ISymUnmanagedBinder * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetReaderFromStream )( __RPC__in ISymUnmanagedBinder * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in_opt IStream *pstream, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); END_INTERFACE } ISymUnmanagedBinderVtbl; interface ISymUnmanagedBinder { CONST_VTBL struct ISymUnmanagedBinderVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedBinder_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedBinder_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedBinder_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedBinder_GetReaderForFile(This,importer,fileName,searchPath,pRetVal) \ ( (This)->lpVtbl -> GetReaderForFile(This,importer,fileName,searchPath,pRetVal) ) #define ISymUnmanagedBinder_GetReaderFromStream(This,importer,pstream,pRetVal) \ ( (This)->lpVtbl -> GetReaderFromStream(This,importer,pstream,pRetVal) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedBinder_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corsym_0000_0002 */ /* [local] */ typedef enum CorSymSearchPolicyAttributes { AllowRegistryAccess = 0x1, AllowSymbolServerAccess = 0x2, AllowOriginalPathAccess = 0x4, AllowReferencePathAccess = 0x8 } CorSymSearchPolicyAttributes; extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0002_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0002_v0_0_s_ifspec; #ifndef __ISymUnmanagedBinder2_INTERFACE_DEFINED__ #define __ISymUnmanagedBinder2_INTERFACE_DEFINED__ /* interface ISymUnmanagedBinder2 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedBinder2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("ACCEE350-89AF-4ccb-8B40-1C2C4C6F9434") ISymUnmanagedBinder2 : public ISymUnmanagedBinder { public: virtual HRESULT STDMETHODCALLTYPE GetReaderForFile2( /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ ULONG32 searchPolicy, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedBinder2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedBinder2 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedBinder2 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedBinder2 * This); HRESULT ( STDMETHODCALLTYPE *GetReaderForFile )( __RPC__in ISymUnmanagedBinder2 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetReaderFromStream )( __RPC__in ISymUnmanagedBinder2 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in_opt IStream *pstream, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetReaderForFile2 )( __RPC__in ISymUnmanagedBinder2 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ ULONG32 searchPolicy, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); END_INTERFACE } ISymUnmanagedBinder2Vtbl; interface ISymUnmanagedBinder2 { CONST_VTBL struct ISymUnmanagedBinder2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedBinder2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedBinder2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedBinder2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedBinder2_GetReaderForFile(This,importer,fileName,searchPath,pRetVal) \ ( (This)->lpVtbl -> GetReaderForFile(This,importer,fileName,searchPath,pRetVal) ) #define ISymUnmanagedBinder2_GetReaderFromStream(This,importer,pstream,pRetVal) \ ( (This)->lpVtbl -> GetReaderFromStream(This,importer,pstream,pRetVal) ) #define ISymUnmanagedBinder2_GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) \ ( (This)->lpVtbl -> GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedBinder2_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedBinder3_INTERFACE_DEFINED__ #define __ISymUnmanagedBinder3_INTERFACE_DEFINED__ /* interface ISymUnmanagedBinder3 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedBinder3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("28AD3D43-B601-4d26-8A1B-25F9165AF9D7") ISymUnmanagedBinder3 : public ISymUnmanagedBinder2 { public: virtual HRESULT STDMETHODCALLTYPE GetReaderFromCallback( /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ ULONG32 searchPolicy, /* [in] */ __RPC__in_opt IUnknown *callback, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedBinder3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedBinder3 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedBinder3 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedBinder3 * This); HRESULT ( STDMETHODCALLTYPE *GetReaderForFile )( __RPC__in ISymUnmanagedBinder3 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetReaderFromStream )( __RPC__in ISymUnmanagedBinder3 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in_opt IStream *pstream, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetReaderForFile2 )( __RPC__in ISymUnmanagedBinder3 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ ULONG32 searchPolicy, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetReaderFromCallback )( __RPC__in ISymUnmanagedBinder3 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *fileName, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ ULONG32 searchPolicy, /* [in] */ __RPC__in_opt IUnknown *callback, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedReader **pRetVal); END_INTERFACE } ISymUnmanagedBinder3Vtbl; interface ISymUnmanagedBinder3 { CONST_VTBL struct ISymUnmanagedBinder3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedBinder3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedBinder3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedBinder3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedBinder3_GetReaderForFile(This,importer,fileName,searchPath,pRetVal) \ ( (This)->lpVtbl -> GetReaderForFile(This,importer,fileName,searchPath,pRetVal) ) #define ISymUnmanagedBinder3_GetReaderFromStream(This,importer,pstream,pRetVal) \ ( (This)->lpVtbl -> GetReaderFromStream(This,importer,pstream,pRetVal) ) #define ISymUnmanagedBinder3_GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) \ ( (This)->lpVtbl -> GetReaderForFile2(This,importer,fileName,searchPath,searchPolicy,pRetVal) ) #define ISymUnmanagedBinder3_GetReaderFromCallback(This,importer,fileName,searchPath,searchPolicy,callback,pRetVal) \ ( (This)->lpVtbl -> GetReaderFromCallback(This,importer,fileName,searchPath,searchPolicy,callback,pRetVal) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedBinder3_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_corsym_0000_0004 */ /* [local] */ static const int E_SYM_DESTROYED = MAKE_HRESULT(1, FACILITY_ITF, 0xdead); extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0004_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_corsym_0000_0004_v0_0_s_ifspec; #ifndef __ISymUnmanagedDispose_INTERFACE_DEFINED__ #define __ISymUnmanagedDispose_INTERFACE_DEFINED__ /* interface ISymUnmanagedDispose */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedDispose; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("969708D2-05E5-4861-A3B0-96E473CDF63F") ISymUnmanagedDispose : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Destroy( void) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedDisposeVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedDispose * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedDispose * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedDispose * This); HRESULT ( STDMETHODCALLTYPE *Destroy )( __RPC__in ISymUnmanagedDispose * This); END_INTERFACE } ISymUnmanagedDisposeVtbl; interface ISymUnmanagedDispose { CONST_VTBL struct ISymUnmanagedDisposeVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedDispose_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedDispose_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedDispose_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedDispose_Destroy(This) \ ( (This)->lpVtbl -> Destroy(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedDispose_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedDocument_INTERFACE_DEFINED__ #define __ISymUnmanagedDocument_INTERFACE_DEFINED__ /* interface ISymUnmanagedDocument */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedDocument; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("40DE4037-7C81-3E1E-B022-AE1ABFF2CA08") ISymUnmanagedDocument : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetURL( /* [in] */ ULONG32 cchUrl, /* [out] */ __RPC__out ULONG32 *pcchUrl, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchUrl, *pcchUrl) WCHAR szUrl[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetDocumentType( /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetLanguage( /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetLanguageVendor( /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetCheckSumAlgorithmId( /* [retval][out] */ __RPC__out GUID *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetCheckSum( /* [in] */ ULONG32 cData, /* [out] */ __RPC__out ULONG32 *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE FindClosestLine( /* [in] */ ULONG32 line, /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE HasEmbeddedSource( /* [retval][out] */ __RPC__out BOOL *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSourceLength( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSourceRange( /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn, /* [in] */ ULONG32 cSourceBytes, /* [out] */ __RPC__out ULONG32 *pcSourceBytes, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSourceBytes, *pcSourceBytes) BYTE source[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedDocumentVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedDocument * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedDocument * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedDocument * This); HRESULT ( STDMETHODCALLTYPE *GetURL )( __RPC__in ISymUnmanagedDocument * This, /* [in] */ ULONG32 cchUrl, /* [out] */ __RPC__out ULONG32 *pcchUrl, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchUrl, *pcchUrl) WCHAR szUrl[ ]); HRESULT ( STDMETHODCALLTYPE *GetDocumentType )( __RPC__in ISymUnmanagedDocument * This, /* [retval][out] */ __RPC__out GUID *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetLanguage )( __RPC__in ISymUnmanagedDocument * This, /* [retval][out] */ __RPC__out GUID *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetLanguageVendor )( __RPC__in ISymUnmanagedDocument * This, /* [retval][out] */ __RPC__out GUID *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetCheckSumAlgorithmId )( __RPC__in ISymUnmanagedDocument * This, /* [retval][out] */ __RPC__out GUID *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetCheckSum )( __RPC__in ISymUnmanagedDocument * This, /* [in] */ ULONG32 cData, /* [out] */ __RPC__out ULONG32 *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *FindClosestLine )( __RPC__in ISymUnmanagedDocument * This, /* [in] */ ULONG32 line, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *HasEmbeddedSource )( __RPC__in ISymUnmanagedDocument * This, /* [retval][out] */ __RPC__out BOOL *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSourceLength )( __RPC__in ISymUnmanagedDocument * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSourceRange )( __RPC__in ISymUnmanagedDocument * This, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn, /* [in] */ ULONG32 cSourceBytes, /* [out] */ __RPC__out ULONG32 *pcSourceBytes, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSourceBytes, *pcSourceBytes) BYTE source[ ]); END_INTERFACE } ISymUnmanagedDocumentVtbl; interface ISymUnmanagedDocument { CONST_VTBL struct ISymUnmanagedDocumentVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedDocument_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedDocument_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedDocument_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedDocument_GetURL(This,cchUrl,pcchUrl,szUrl) \ ( (This)->lpVtbl -> GetURL(This,cchUrl,pcchUrl,szUrl) ) #define ISymUnmanagedDocument_GetDocumentType(This,pRetVal) \ ( (This)->lpVtbl -> GetDocumentType(This,pRetVal) ) #define ISymUnmanagedDocument_GetLanguage(This,pRetVal) \ ( (This)->lpVtbl -> GetLanguage(This,pRetVal) ) #define ISymUnmanagedDocument_GetLanguageVendor(This,pRetVal) \ ( (This)->lpVtbl -> GetLanguageVendor(This,pRetVal) ) #define ISymUnmanagedDocument_GetCheckSumAlgorithmId(This,pRetVal) \ ( (This)->lpVtbl -> GetCheckSumAlgorithmId(This,pRetVal) ) #define ISymUnmanagedDocument_GetCheckSum(This,cData,pcData,data) \ ( (This)->lpVtbl -> GetCheckSum(This,cData,pcData,data) ) #define ISymUnmanagedDocument_FindClosestLine(This,line,pRetVal) \ ( (This)->lpVtbl -> FindClosestLine(This,line,pRetVal) ) #define ISymUnmanagedDocument_HasEmbeddedSource(This,pRetVal) \ ( (This)->lpVtbl -> HasEmbeddedSource(This,pRetVal) ) #define ISymUnmanagedDocument_GetSourceLength(This,pRetVal) \ ( (This)->lpVtbl -> GetSourceLength(This,pRetVal) ) #define ISymUnmanagedDocument_GetSourceRange(This,startLine,startColumn,endLine,endColumn,cSourceBytes,pcSourceBytes,source) \ ( (This)->lpVtbl -> GetSourceRange(This,startLine,startColumn,endLine,endColumn,cSourceBytes,pcSourceBytes,source) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedDocument_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedDocumentWriter_INTERFACE_DEFINED__ #define __ISymUnmanagedDocumentWriter_INTERFACE_DEFINED__ /* interface ISymUnmanagedDocumentWriter */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedDocumentWriter; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B01FAFEB-C450-3A4D-BEEC-B4CEEC01E006") ISymUnmanagedDocumentWriter : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetSource( /* [in] */ ULONG32 sourceSize, /* [size_is][in] */ __RPC__in_ecount_full(sourceSize) BYTE source[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetCheckSum( /* [in] */ GUID algorithmId, /* [in] */ ULONG32 checkSumSize, /* [size_is][in] */ __RPC__in_ecount_full(checkSumSize) BYTE checkSum[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedDocumentWriterVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedDocumentWriter * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedDocumentWriter * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedDocumentWriter * This); HRESULT ( STDMETHODCALLTYPE *SetSource )( __RPC__in ISymUnmanagedDocumentWriter * This, /* [in] */ ULONG32 sourceSize, /* [size_is][in] */ __RPC__in_ecount_full(sourceSize) BYTE source[ ]); HRESULT ( STDMETHODCALLTYPE *SetCheckSum )( __RPC__in ISymUnmanagedDocumentWriter * This, /* [in] */ GUID algorithmId, /* [in] */ ULONG32 checkSumSize, /* [size_is][in] */ __RPC__in_ecount_full(checkSumSize) BYTE checkSum[ ]); END_INTERFACE } ISymUnmanagedDocumentWriterVtbl; interface ISymUnmanagedDocumentWriter { CONST_VTBL struct ISymUnmanagedDocumentWriterVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedDocumentWriter_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedDocumentWriter_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedDocumentWriter_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedDocumentWriter_SetSource(This,sourceSize,source) \ ( (This)->lpVtbl -> SetSource(This,sourceSize,source) ) #define ISymUnmanagedDocumentWriter_SetCheckSum(This,algorithmId,checkSumSize,checkSum) \ ( (This)->lpVtbl -> SetCheckSum(This,algorithmId,checkSumSize,checkSum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedDocumentWriter_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedMethod_INTERFACE_DEFINED__ #define __ISymUnmanagedMethod_INTERFACE_DEFINED__ /* interface ISymUnmanagedMethod */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedMethod; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B62B923C-B500-3158-A543-24F307A8B7E1") ISymUnmanagedMethod : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetToken( /* [retval][out] */ __RPC__out mdMethodDef *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE GetSequencePointCount( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetRootScope( /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetScopeFromOffset( /* [in] */ ULONG32 offset, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetOffset( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetRanges( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 cRanges, /* [out] */ __RPC__out ULONG32 *pcRanges, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cRanges, *pcRanges) ULONG32 ranges[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetParameters( /* [in] */ ULONG32 cParams, /* [out] */ __RPC__out ULONG32 *pcParams, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cParams, *pcParams) ISymUnmanagedVariable *params[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetNamespace( /* [out] */ __RPC__deref_out_opt ISymUnmanagedNamespace **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSourceStartEnd( /* [in] */ __RPC__in_ecount_full(2) ISymUnmanagedDocument *docs[ 2 ], /* [in] */ __RPC__in_ecount_full(2) ULONG32 lines[ 2 ], /* [in] */ __RPC__in_ecount_full(2) ULONG32 columns[ 2 ], /* [out] */ __RPC__out BOOL *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSequencePoints( /* [in] */ ULONG32 cPoints, /* [out] */ __RPC__out ULONG32 *pcPoints, /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ISymUnmanagedDocument *documents[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endColumns[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedMethodVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedMethod * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedMethod * This); HRESULT ( STDMETHODCALLTYPE *GetToken )( __RPC__in ISymUnmanagedMethod * This, /* [retval][out] */ __RPC__out mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetSequencePointCount )( __RPC__in ISymUnmanagedMethod * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetRootScope )( __RPC__in ISymUnmanagedMethod * This, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetScopeFromOffset )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ ULONG32 offset, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetOffset )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetRanges )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 cRanges, /* [out] */ __RPC__out ULONG32 *pcRanges, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cRanges, *pcRanges) ULONG32 ranges[ ]); HRESULT ( STDMETHODCALLTYPE *GetParameters )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ ULONG32 cParams, /* [out] */ __RPC__out ULONG32 *pcParams, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cParams, *pcParams) ISymUnmanagedVariable *params[ ]); HRESULT ( STDMETHODCALLTYPE *GetNamespace )( __RPC__in ISymUnmanagedMethod * This, /* [out] */ __RPC__deref_out_opt ISymUnmanagedNamespace **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSourceStartEnd )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ __RPC__in_ecount_full(2) ISymUnmanagedDocument *docs[ 2 ], /* [in] */ __RPC__in_ecount_full(2) ULONG32 lines[ 2 ], /* [in] */ __RPC__in_ecount_full(2) ULONG32 columns[ 2 ], /* [out] */ __RPC__out BOOL *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSequencePoints )( __RPC__in ISymUnmanagedMethod * This, /* [in] */ ULONG32 cPoints, /* [out] */ __RPC__out ULONG32 *pcPoints, /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ISymUnmanagedDocument *documents[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(cPoints) ULONG32 endColumns[ ]); END_INTERFACE } ISymUnmanagedMethodVtbl; interface ISymUnmanagedMethod { CONST_VTBL struct ISymUnmanagedMethodVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedMethod_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedMethod_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedMethod_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedMethod_GetToken(This,pToken) \ ( (This)->lpVtbl -> GetToken(This,pToken) ) #define ISymUnmanagedMethod_GetSequencePointCount(This,pRetVal) \ ( (This)->lpVtbl -> GetSequencePointCount(This,pRetVal) ) #define ISymUnmanagedMethod_GetRootScope(This,pRetVal) \ ( (This)->lpVtbl -> GetRootScope(This,pRetVal) ) #define ISymUnmanagedMethod_GetScopeFromOffset(This,offset,pRetVal) \ ( (This)->lpVtbl -> GetScopeFromOffset(This,offset,pRetVal) ) #define ISymUnmanagedMethod_GetOffset(This,document,line,column,pRetVal) \ ( (This)->lpVtbl -> GetOffset(This,document,line,column,pRetVal) ) #define ISymUnmanagedMethod_GetRanges(This,document,line,column,cRanges,pcRanges,ranges) \ ( (This)->lpVtbl -> GetRanges(This,document,line,column,cRanges,pcRanges,ranges) ) #define ISymUnmanagedMethod_GetParameters(This,cParams,pcParams,params) \ ( (This)->lpVtbl -> GetParameters(This,cParams,pcParams,params) ) #define ISymUnmanagedMethod_GetNamespace(This,pRetVal) \ ( (This)->lpVtbl -> GetNamespace(This,pRetVal) ) #define ISymUnmanagedMethod_GetSourceStartEnd(This,docs,lines,columns,pRetVal) \ ( (This)->lpVtbl -> GetSourceStartEnd(This,docs,lines,columns,pRetVal) ) #define ISymUnmanagedMethod_GetSequencePoints(This,cPoints,pcPoints,offsets,documents,lines,columns,endLines,endColumns) \ ( (This)->lpVtbl -> GetSequencePoints(This,cPoints,pcPoints,offsets,documents,lines,columns,endLines,endColumns) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedMethod_INTERFACE_DEFINED__ */ #ifndef __ISymENCUnmanagedMethod_INTERFACE_DEFINED__ #define __ISymENCUnmanagedMethod_INTERFACE_DEFINED__ /* interface ISymENCUnmanagedMethod */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymENCUnmanagedMethod; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("85E891DA-A631-4c76-ACA2-A44A39C46B8C") ISymENCUnmanagedMethod : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetFileNameFromOffset( /* [in] */ ULONG32 dwOffset, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetLineFromOffset( /* [in] */ ULONG32 dwOffset, /* [out] */ __RPC__out ULONG32 *pline, /* [out] */ __RPC__out ULONG32 *pcolumn, /* [out] */ __RPC__out ULONG32 *pendLine, /* [out] */ __RPC__out ULONG32 *pendColumn, /* [out] */ __RPC__out ULONG32 *pdwStartOffset) = 0; virtual HRESULT STDMETHODCALLTYPE GetDocumentsForMethodCount( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetDocumentsForMethod( /* [in] */ ULONG32 cDocs, /* [out] */ __RPC__out ULONG32 *pcDocs, /* [size_is][in] */ __RPC__in_ecount_full(cDocs) ISymUnmanagedDocument *documents[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetSourceExtentInDocument( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [out] */ __RPC__out ULONG32 *pstartLine, /* [out] */ __RPC__out ULONG32 *pendLine) = 0; }; #else /* C style interface */ typedef struct ISymENCUnmanagedMethodVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymENCUnmanagedMethod * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymENCUnmanagedMethod * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymENCUnmanagedMethod * This); HRESULT ( STDMETHODCALLTYPE *GetFileNameFromOffset )( __RPC__in ISymENCUnmanagedMethod * This, /* [in] */ ULONG32 dwOffset, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetLineFromOffset )( __RPC__in ISymENCUnmanagedMethod * This, /* [in] */ ULONG32 dwOffset, /* [out] */ __RPC__out ULONG32 *pline, /* [out] */ __RPC__out ULONG32 *pcolumn, /* [out] */ __RPC__out ULONG32 *pendLine, /* [out] */ __RPC__out ULONG32 *pendColumn, /* [out] */ __RPC__out ULONG32 *pdwStartOffset); HRESULT ( STDMETHODCALLTYPE *GetDocumentsForMethodCount )( __RPC__in ISymENCUnmanagedMethod * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetDocumentsForMethod )( __RPC__in ISymENCUnmanagedMethod * This, /* [in] */ ULONG32 cDocs, /* [out] */ __RPC__out ULONG32 *pcDocs, /* [size_is][in] */ __RPC__in_ecount_full(cDocs) ISymUnmanagedDocument *documents[ ]); HRESULT ( STDMETHODCALLTYPE *GetSourceExtentInDocument )( __RPC__in ISymENCUnmanagedMethod * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [out] */ __RPC__out ULONG32 *pstartLine, /* [out] */ __RPC__out ULONG32 *pendLine); END_INTERFACE } ISymENCUnmanagedMethodVtbl; interface ISymENCUnmanagedMethod { CONST_VTBL struct ISymENCUnmanagedMethodVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymENCUnmanagedMethod_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymENCUnmanagedMethod_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymENCUnmanagedMethod_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymENCUnmanagedMethod_GetFileNameFromOffset(This,dwOffset,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetFileNameFromOffset(This,dwOffset,cchName,pcchName,szName) ) #define ISymENCUnmanagedMethod_GetLineFromOffset(This,dwOffset,pline,pcolumn,pendLine,pendColumn,pdwStartOffset) \ ( (This)->lpVtbl -> GetLineFromOffset(This,dwOffset,pline,pcolumn,pendLine,pendColumn,pdwStartOffset) ) #define ISymENCUnmanagedMethod_GetDocumentsForMethodCount(This,pRetVal) \ ( (This)->lpVtbl -> GetDocumentsForMethodCount(This,pRetVal) ) #define ISymENCUnmanagedMethod_GetDocumentsForMethod(This,cDocs,pcDocs,documents) \ ( (This)->lpVtbl -> GetDocumentsForMethod(This,cDocs,pcDocs,documents) ) #define ISymENCUnmanagedMethod_GetSourceExtentInDocument(This,document,pstartLine,pendLine) \ ( (This)->lpVtbl -> GetSourceExtentInDocument(This,document,pstartLine,pendLine) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymENCUnmanagedMethod_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedNamespace_INTERFACE_DEFINED__ #define __ISymUnmanagedNamespace_INTERFACE_DEFINED__ /* interface ISymUnmanagedNamespace */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedNamespace; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("0DFF7289-54F8-11d3-BD28-0000F80849BD") ISymUnmanagedNamespace : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetNamespaces( /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetVariables( /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedNamespaceVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedNamespace * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedNamespace * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedNamespace * This); HRESULT ( STDMETHODCALLTYPE *GetName )( __RPC__in ISymUnmanagedNamespace * This, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( __RPC__in ISymUnmanagedNamespace * This, /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); HRESULT ( STDMETHODCALLTYPE *GetVariables )( __RPC__in ISymUnmanagedNamespace * This, /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); END_INTERFACE } ISymUnmanagedNamespaceVtbl; interface ISymUnmanagedNamespace { CONST_VTBL struct ISymUnmanagedNamespaceVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedNamespace_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedNamespace_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedNamespace_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedNamespace_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ISymUnmanagedNamespace_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) #define ISymUnmanagedNamespace_GetVariables(This,cVars,pcVars,pVars) \ ( (This)->lpVtbl -> GetVariables(This,cVars,pcVars,pVars) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedNamespace_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedReader_INTERFACE_DEFINED__ #define __ISymUnmanagedReader_INTERFACE_DEFINED__ /* interface ISymUnmanagedReader */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedReader; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B4CE6286-2A6B-3712-A3B7-1EE1DAD467B5") ISymUnmanagedReader : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetDocument( /* [in] */ __RPC__in WCHAR *url, /* [in] */ GUID language, /* [in] */ GUID languageVendor, /* [in] */ GUID documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocument **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetDocuments( /* [in] */ ULONG32 cDocs, /* [out] */ __RPC__out ULONG32 *pcDocs, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cDocs, *pcDocs) ISymUnmanagedDocument *pDocs[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetUserEntryPoint( /* [retval][out] */ __RPC__out mdMethodDef *pToken) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethod( /* [in] */ mdMethodDef token, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodByVersion( /* [in] */ mdMethodDef token, /* [in] */ int version, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetVariables( /* [in] */ mdToken parent, /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetGlobalVariables( /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodFromDocumentPosition( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSymAttribute( /* [in] */ mdToken parent, /* [in] */ __RPC__in WCHAR *name, /* [in] */ ULONG32 cBuffer, /* [out] */ __RPC__out ULONG32 *pcBuffer, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetNamespaces( /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE Initialize( /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ __RPC__in_opt IStream *pIStream) = 0; virtual HRESULT STDMETHODCALLTYPE UpdateSymbolStore( /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream) = 0; virtual HRESULT STDMETHODCALLTYPE ReplaceSymbolStore( /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream) = 0; virtual HRESULT STDMETHODCALLTYPE GetSymbolStoreFileName( /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodsFromDocumentPosition( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 cMethod, /* [out] */ __RPC__out ULONG32 *pcMethod, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetDocumentVersion( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *pDoc, /* [out] */ __RPC__out int *version, /* [out] */ __RPC__out BOOL *pbCurrent) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodVersion( /* [in] */ __RPC__in_opt ISymUnmanagedMethod *pMethod, /* [out] */ __RPC__out int *version) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedReaderVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedReader * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedReader * This); HRESULT ( STDMETHODCALLTYPE *GetDocument )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in WCHAR *url, /* [in] */ GUID language, /* [in] */ GUID languageVendor, /* [in] */ GUID documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocument **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetDocuments )( __RPC__in ISymUnmanagedReader * This, /* [in] */ ULONG32 cDocs, /* [out] */ __RPC__out ULONG32 *pcDocs, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cDocs, *pcDocs) ISymUnmanagedDocument *pDocs[ ]); HRESULT ( STDMETHODCALLTYPE *GetUserEntryPoint )( __RPC__in ISymUnmanagedReader * This, /* [retval][out] */ __RPC__out mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetMethod )( __RPC__in ISymUnmanagedReader * This, /* [in] */ mdMethodDef token, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetMethodByVersion )( __RPC__in ISymUnmanagedReader * This, /* [in] */ mdMethodDef token, /* [in] */ int version, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetVariables )( __RPC__in ISymUnmanagedReader * This, /* [in] */ mdToken parent, /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); HRESULT ( STDMETHODCALLTYPE *GetGlobalVariables )( __RPC__in ISymUnmanagedReader * This, /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodFromDocumentPosition )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSymAttribute )( __RPC__in ISymUnmanagedReader * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in WCHAR *name, /* [in] */ ULONG32 cBuffer, /* [out] */ __RPC__out ULONG32 *pcBuffer, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]); HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( __RPC__in ISymUnmanagedReader * This, /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ __RPC__in_opt IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *UpdateSymbolStore )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *ReplaceSymbolStore )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *GetSymbolStoreFileName )( __RPC__in ISymUnmanagedReader * This, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodsFromDocumentPosition )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 cMethod, /* [out] */ __RPC__out ULONG32 *pcMethod, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]); HRESULT ( STDMETHODCALLTYPE *GetDocumentVersion )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *pDoc, /* [out] */ __RPC__out int *version, /* [out] */ __RPC__out BOOL *pbCurrent); HRESULT ( STDMETHODCALLTYPE *GetMethodVersion )( __RPC__in ISymUnmanagedReader * This, /* [in] */ __RPC__in_opt ISymUnmanagedMethod *pMethod, /* [out] */ __RPC__out int *version); END_INTERFACE } ISymUnmanagedReaderVtbl; interface ISymUnmanagedReader { CONST_VTBL struct ISymUnmanagedReaderVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedReader_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedReader_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedReader_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedReader_GetDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> GetDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedReader_GetDocuments(This,cDocs,pcDocs,pDocs) \ ( (This)->lpVtbl -> GetDocuments(This,cDocs,pcDocs,pDocs) ) #define ISymUnmanagedReader_GetUserEntryPoint(This,pToken) \ ( (This)->lpVtbl -> GetUserEntryPoint(This,pToken) ) #define ISymUnmanagedReader_GetMethod(This,token,pRetVal) \ ( (This)->lpVtbl -> GetMethod(This,token,pRetVal) ) #define ISymUnmanagedReader_GetMethodByVersion(This,token,version,pRetVal) \ ( (This)->lpVtbl -> GetMethodByVersion(This,token,version,pRetVal) ) #define ISymUnmanagedReader_GetVariables(This,parent,cVars,pcVars,pVars) \ ( (This)->lpVtbl -> GetVariables(This,parent,cVars,pcVars,pVars) ) #define ISymUnmanagedReader_GetGlobalVariables(This,cVars,pcVars,pVars) \ ( (This)->lpVtbl -> GetGlobalVariables(This,cVars,pcVars,pVars) ) #define ISymUnmanagedReader_GetMethodFromDocumentPosition(This,document,line,column,pRetVal) \ ( (This)->lpVtbl -> GetMethodFromDocumentPosition(This,document,line,column,pRetVal) ) #define ISymUnmanagedReader_GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) \ ( (This)->lpVtbl -> GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) ) #define ISymUnmanagedReader_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) #define ISymUnmanagedReader_Initialize(This,importer,filename,searchPath,pIStream) \ ( (This)->lpVtbl -> Initialize(This,importer,filename,searchPath,pIStream) ) #define ISymUnmanagedReader_UpdateSymbolStore(This,filename,pIStream) \ ( (This)->lpVtbl -> UpdateSymbolStore(This,filename,pIStream) ) #define ISymUnmanagedReader_ReplaceSymbolStore(This,filename,pIStream) \ ( (This)->lpVtbl -> ReplaceSymbolStore(This,filename,pIStream) ) #define ISymUnmanagedReader_GetSymbolStoreFileName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetSymbolStoreFileName(This,cchName,pcchName,szName) ) #define ISymUnmanagedReader_GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) \ ( (This)->lpVtbl -> GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) ) #define ISymUnmanagedReader_GetDocumentVersion(This,pDoc,version,pbCurrent) \ ( (This)->lpVtbl -> GetDocumentVersion(This,pDoc,version,pbCurrent) ) #define ISymUnmanagedReader_GetMethodVersion(This,pMethod,version) \ ( (This)->lpVtbl -> GetMethodVersion(This,pMethod,version) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedReader_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedSourceServerModule_INTERFACE_DEFINED__ #define __ISymUnmanagedSourceServerModule_INTERFACE_DEFINED__ /* interface ISymUnmanagedSourceServerModule */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedSourceServerModule; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("997DD0CC-A76F-4c82-8D79-EA87559D27AD") ISymUnmanagedSourceServerModule : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetSourceServerData( /* [out] */ __RPC__out ULONG *pDataByteCount, /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*pDataByteCount) BYTE **ppData) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedSourceServerModuleVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedSourceServerModule * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedSourceServerModule * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedSourceServerModule * This); HRESULT ( STDMETHODCALLTYPE *GetSourceServerData )( __RPC__in ISymUnmanagedSourceServerModule * This, /* [out] */ __RPC__out ULONG *pDataByteCount, /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*pDataByteCount) BYTE **ppData); END_INTERFACE } ISymUnmanagedSourceServerModuleVtbl; interface ISymUnmanagedSourceServerModule { CONST_VTBL struct ISymUnmanagedSourceServerModuleVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedSourceServerModule_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedSourceServerModule_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedSourceServerModule_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedSourceServerModule_GetSourceServerData(This,pDataByteCount,ppData) \ ( (This)->lpVtbl -> GetSourceServerData(This,pDataByteCount,ppData) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedSourceServerModule_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedENCUpdate_INTERFACE_DEFINED__ #define __ISymUnmanagedENCUpdate_INTERFACE_DEFINED__ /* interface ISymUnmanagedENCUpdate */ /* [unique][uuid][object] */ typedef struct _SYMLINEDELTA { mdMethodDef mdMethod; INT32 delta; } SYMLINEDELTA; EXTERN_C const IID IID_ISymUnmanagedENCUpdate; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E502D2DD-8671-4338-8F2A-FC08229628C4") ISymUnmanagedENCUpdate : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE UpdateSymbolStore2( /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ __RPC__in SYMLINEDELTA *pDeltaLines, /* [in] */ ULONG cDeltaLines) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalVariableCount( /* [in] */ mdMethodDef mdMethodToken, /* [out] */ __RPC__out ULONG *pcLocals) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalVariables( /* [in] */ mdMethodDef mdMethodToken, /* [in] */ ULONG cLocals, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pceltFetched) ISymUnmanagedVariable *rgLocals[ ], /* [out] */ __RPC__out ULONG *pceltFetched) = 0; virtual HRESULT STDMETHODCALLTYPE InitializeForEnc( void) = 0; virtual HRESULT STDMETHODCALLTYPE UpdateMethodLines( /* [in] */ mdMethodDef mdMethodToken, /* [size_is][in] */ __RPC__in_ecount_full(cDeltas) INT32 *pDeltas, /* [in] */ ULONG cDeltas) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedENCUpdateVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedENCUpdate * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedENCUpdate * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedENCUpdate * This); HRESULT ( STDMETHODCALLTYPE *UpdateSymbolStore2 )( __RPC__in ISymUnmanagedENCUpdate * This, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ __RPC__in SYMLINEDELTA *pDeltaLines, /* [in] */ ULONG cDeltaLines); HRESULT ( STDMETHODCALLTYPE *GetLocalVariableCount )( __RPC__in ISymUnmanagedENCUpdate * This, /* [in] */ mdMethodDef mdMethodToken, /* [out] */ __RPC__out ULONG *pcLocals); HRESULT ( STDMETHODCALLTYPE *GetLocalVariables )( __RPC__in ISymUnmanagedENCUpdate * This, /* [in] */ mdMethodDef mdMethodToken, /* [in] */ ULONG cLocals, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pceltFetched) ISymUnmanagedVariable *rgLocals[ ], /* [out] */ __RPC__out ULONG *pceltFetched); HRESULT ( STDMETHODCALLTYPE *InitializeForEnc )( __RPC__in ISymUnmanagedENCUpdate * This); HRESULT ( STDMETHODCALLTYPE *UpdateMethodLines )( __RPC__in ISymUnmanagedENCUpdate * This, /* [in] */ mdMethodDef mdMethodToken, /* [size_is][in] */ __RPC__in_ecount_full(cDeltas) INT32 *pDeltas, /* [in] */ ULONG cDeltas); END_INTERFACE } ISymUnmanagedENCUpdateVtbl; interface ISymUnmanagedENCUpdate { CONST_VTBL struct ISymUnmanagedENCUpdateVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedENCUpdate_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedENCUpdate_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedENCUpdate_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedENCUpdate_UpdateSymbolStore2(This,pIStream,pDeltaLines,cDeltaLines) \ ( (This)->lpVtbl -> UpdateSymbolStore2(This,pIStream,pDeltaLines,cDeltaLines) ) #define ISymUnmanagedENCUpdate_GetLocalVariableCount(This,mdMethodToken,pcLocals) \ ( (This)->lpVtbl -> GetLocalVariableCount(This,mdMethodToken,pcLocals) ) #define ISymUnmanagedENCUpdate_GetLocalVariables(This,mdMethodToken,cLocals,rgLocals,pceltFetched) \ ( (This)->lpVtbl -> GetLocalVariables(This,mdMethodToken,cLocals,rgLocals,pceltFetched) ) #define ISymUnmanagedENCUpdate_InitializeForEnc(This) \ ( (This)->lpVtbl -> InitializeForEnc(This) ) #define ISymUnmanagedENCUpdate_UpdateMethodLines(This,mdMethodToken,pDeltas,cDeltas) \ ( (This)->lpVtbl -> UpdateMethodLines(This,mdMethodToken,pDeltas,cDeltas) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedENCUpdate_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedReaderSymbolSearchInfo_INTERFACE_DEFINED__ #define __ISymUnmanagedReaderSymbolSearchInfo_INTERFACE_DEFINED__ /* interface ISymUnmanagedReaderSymbolSearchInfo */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedReaderSymbolSearchInfo; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("20D9645D-03CD-4e34-9C11-9848A5B084F1") ISymUnmanagedReaderSymbolSearchInfo : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetSymbolSearchInfoCount( /* [out] */ __RPC__out ULONG32 *pcSearchInfo) = 0; virtual HRESULT STDMETHODCALLTYPE GetSymbolSearchInfo( /* [in] */ ULONG32 cSearchInfo, /* [out] */ __RPC__out ULONG32 *pcSearchInfo, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSearchInfo, *pcSearchInfo) ISymUnmanagedSymbolSearchInfo **rgpSearchInfo) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedReaderSymbolSearchInfoVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This); HRESULT ( STDMETHODCALLTYPE *GetSymbolSearchInfoCount )( __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This, /* [out] */ __RPC__out ULONG32 *pcSearchInfo); HRESULT ( STDMETHODCALLTYPE *GetSymbolSearchInfo )( __RPC__in ISymUnmanagedReaderSymbolSearchInfo * This, /* [in] */ ULONG32 cSearchInfo, /* [out] */ __RPC__out ULONG32 *pcSearchInfo, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSearchInfo, *pcSearchInfo) ISymUnmanagedSymbolSearchInfo **rgpSearchInfo); END_INTERFACE } ISymUnmanagedReaderSymbolSearchInfoVtbl; interface ISymUnmanagedReaderSymbolSearchInfo { CONST_VTBL struct ISymUnmanagedReaderSymbolSearchInfoVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedReaderSymbolSearchInfo_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedReaderSymbolSearchInfo_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedReaderSymbolSearchInfo_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedReaderSymbolSearchInfo_GetSymbolSearchInfoCount(This,pcSearchInfo) \ ( (This)->lpVtbl -> GetSymbolSearchInfoCount(This,pcSearchInfo) ) #define ISymUnmanagedReaderSymbolSearchInfo_GetSymbolSearchInfo(This,cSearchInfo,pcSearchInfo,rgpSearchInfo) \ ( (This)->lpVtbl -> GetSymbolSearchInfo(This,cSearchInfo,pcSearchInfo,rgpSearchInfo) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedReaderSymbolSearchInfo_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedScope_INTERFACE_DEFINED__ #define __ISymUnmanagedScope_INTERFACE_DEFINED__ /* interface ISymUnmanagedScope */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedScope; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("68005D0F-B8E0-3B01-84D5-A11A94154942") ISymUnmanagedScope : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetMethod( /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetParent( /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetChildren( /* [in] */ ULONG32 cChildren, /* [out] */ __RPC__out ULONG32 *pcChildren, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cChildren, *pcChildren) ISymUnmanagedScope *children[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetStartOffset( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetEndOffset( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalCount( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocals( /* [in] */ ULONG32 cLocals, /* [out] */ __RPC__out ULONG32 *pcLocals, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pcLocals) ISymUnmanagedVariable *locals[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetNamespaces( /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedScopeVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedScope * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedScope * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedScope * This); HRESULT ( STDMETHODCALLTYPE *GetMethod )( __RPC__in ISymUnmanagedScope * This, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetParent )( __RPC__in ISymUnmanagedScope * This, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetChildren )( __RPC__in ISymUnmanagedScope * This, /* [in] */ ULONG32 cChildren, /* [out] */ __RPC__out ULONG32 *pcChildren, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cChildren, *pcChildren) ISymUnmanagedScope *children[ ]); HRESULT ( STDMETHODCALLTYPE *GetStartOffset )( __RPC__in ISymUnmanagedScope * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetEndOffset )( __RPC__in ISymUnmanagedScope * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetLocalCount )( __RPC__in ISymUnmanagedScope * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetLocals )( __RPC__in ISymUnmanagedScope * This, /* [in] */ ULONG32 cLocals, /* [out] */ __RPC__out ULONG32 *pcLocals, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pcLocals) ISymUnmanagedVariable *locals[ ]); HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( __RPC__in ISymUnmanagedScope * This, /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); END_INTERFACE } ISymUnmanagedScopeVtbl; interface ISymUnmanagedScope { CONST_VTBL struct ISymUnmanagedScopeVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedScope_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedScope_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedScope_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedScope_GetMethod(This,pRetVal) \ ( (This)->lpVtbl -> GetMethod(This,pRetVal) ) #define ISymUnmanagedScope_GetParent(This,pRetVal) \ ( (This)->lpVtbl -> GetParent(This,pRetVal) ) #define ISymUnmanagedScope_GetChildren(This,cChildren,pcChildren,children) \ ( (This)->lpVtbl -> GetChildren(This,cChildren,pcChildren,children) ) #define ISymUnmanagedScope_GetStartOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetStartOffset(This,pRetVal) ) #define ISymUnmanagedScope_GetEndOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetEndOffset(This,pRetVal) ) #define ISymUnmanagedScope_GetLocalCount(This,pRetVal) \ ( (This)->lpVtbl -> GetLocalCount(This,pRetVal) ) #define ISymUnmanagedScope_GetLocals(This,cLocals,pcLocals,locals) \ ( (This)->lpVtbl -> GetLocals(This,cLocals,pcLocals,locals) ) #define ISymUnmanagedScope_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedScope_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedConstant_INTERFACE_DEFINED__ #define __ISymUnmanagedConstant_INTERFACE_DEFINED__ /* interface ISymUnmanagedConstant */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedConstant; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("48B25ED8-5BAD-41bc-9CEE-CD62FABC74E9") ISymUnmanagedConstant : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetValue( __RPC__in VARIANT *pValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetSignature( /* [in] */ ULONG32 cSig, /* [out] */ __RPC__out ULONG32 *pcSig, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedConstantVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedConstant * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedConstant * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedConstant * This); HRESULT ( STDMETHODCALLTYPE *GetName )( __RPC__in ISymUnmanagedConstant * This, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetValue )( __RPC__in ISymUnmanagedConstant * This, __RPC__in VARIANT *pValue); HRESULT ( STDMETHODCALLTYPE *GetSignature )( __RPC__in ISymUnmanagedConstant * This, /* [in] */ ULONG32 cSig, /* [out] */ __RPC__out ULONG32 *pcSig, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]); END_INTERFACE } ISymUnmanagedConstantVtbl; interface ISymUnmanagedConstant { CONST_VTBL struct ISymUnmanagedConstantVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedConstant_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedConstant_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedConstant_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedConstant_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ISymUnmanagedConstant_GetValue(This,pValue) \ ( (This)->lpVtbl -> GetValue(This,pValue) ) #define ISymUnmanagedConstant_GetSignature(This,cSig,pcSig,sig) \ ( (This)->lpVtbl -> GetSignature(This,cSig,pcSig,sig) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedConstant_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedScope2_INTERFACE_DEFINED__ #define __ISymUnmanagedScope2_INTERFACE_DEFINED__ /* interface ISymUnmanagedScope2 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedScope2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AE932FBA-3FD8-4dba-8232-30A2309B02DB") ISymUnmanagedScope2 : public ISymUnmanagedScope { public: virtual HRESULT STDMETHODCALLTYPE GetConstantCount( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetConstants( /* [in] */ ULONG32 cConstants, /* [out] */ __RPC__out ULONG32 *pcConstants, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cConstants, *pcConstants) ISymUnmanagedConstant *constants[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedScope2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedScope2 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedScope2 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedScope2 * This); HRESULT ( STDMETHODCALLTYPE *GetMethod )( __RPC__in ISymUnmanagedScope2 * This, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetParent )( __RPC__in ISymUnmanagedScope2 * This, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedScope **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetChildren )( __RPC__in ISymUnmanagedScope2 * This, /* [in] */ ULONG32 cChildren, /* [out] */ __RPC__out ULONG32 *pcChildren, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cChildren, *pcChildren) ISymUnmanagedScope *children[ ]); HRESULT ( STDMETHODCALLTYPE *GetStartOffset )( __RPC__in ISymUnmanagedScope2 * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetEndOffset )( __RPC__in ISymUnmanagedScope2 * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetLocalCount )( __RPC__in ISymUnmanagedScope2 * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetLocals )( __RPC__in ISymUnmanagedScope2 * This, /* [in] */ ULONG32 cLocals, /* [out] */ __RPC__out ULONG32 *pcLocals, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cLocals, *pcLocals) ISymUnmanagedVariable *locals[ ]); HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( __RPC__in ISymUnmanagedScope2 * This, /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); HRESULT ( STDMETHODCALLTYPE *GetConstantCount )( __RPC__in ISymUnmanagedScope2 * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetConstants )( __RPC__in ISymUnmanagedScope2 * This, /* [in] */ ULONG32 cConstants, /* [out] */ __RPC__out ULONG32 *pcConstants, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cConstants, *pcConstants) ISymUnmanagedConstant *constants[ ]); END_INTERFACE } ISymUnmanagedScope2Vtbl; interface ISymUnmanagedScope2 { CONST_VTBL struct ISymUnmanagedScope2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedScope2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedScope2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedScope2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedScope2_GetMethod(This,pRetVal) \ ( (This)->lpVtbl -> GetMethod(This,pRetVal) ) #define ISymUnmanagedScope2_GetParent(This,pRetVal) \ ( (This)->lpVtbl -> GetParent(This,pRetVal) ) #define ISymUnmanagedScope2_GetChildren(This,cChildren,pcChildren,children) \ ( (This)->lpVtbl -> GetChildren(This,cChildren,pcChildren,children) ) #define ISymUnmanagedScope2_GetStartOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetStartOffset(This,pRetVal) ) #define ISymUnmanagedScope2_GetEndOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetEndOffset(This,pRetVal) ) #define ISymUnmanagedScope2_GetLocalCount(This,pRetVal) \ ( (This)->lpVtbl -> GetLocalCount(This,pRetVal) ) #define ISymUnmanagedScope2_GetLocals(This,cLocals,pcLocals,locals) \ ( (This)->lpVtbl -> GetLocals(This,cLocals,pcLocals,locals) ) #define ISymUnmanagedScope2_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) #define ISymUnmanagedScope2_GetConstantCount(This,pRetVal) \ ( (This)->lpVtbl -> GetConstantCount(This,pRetVal) ) #define ISymUnmanagedScope2_GetConstants(This,cConstants,pcConstants,constants) \ ( (This)->lpVtbl -> GetConstants(This,cConstants,pcConstants,constants) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedScope2_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedVariable_INTERFACE_DEFINED__ #define __ISymUnmanagedVariable_INTERFACE_DEFINED__ /* interface ISymUnmanagedVariable */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedVariable; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("9F60EEBE-2D9A-3F7C-BF58-80BC991C60BB") ISymUnmanagedVariable : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetAttributes( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSignature( /* [in] */ ULONG32 cSig, /* [out] */ __RPC__out ULONG32 *pcSig, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddressKind( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddressField1( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddressField2( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddressField3( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetStartOffset( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetEndOffset( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedVariableVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedVariable * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedVariable * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedVariable * This); HRESULT ( STDMETHODCALLTYPE *GetName )( __RPC__in ISymUnmanagedVariable * This, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetAttributes )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSignature )( __RPC__in ISymUnmanagedVariable * This, /* [in] */ ULONG32 cSig, /* [out] */ __RPC__out ULONG32 *pcSig, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cSig, *pcSig) BYTE sig[ ]); HRESULT ( STDMETHODCALLTYPE *GetAddressKind )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetAddressField1 )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetAddressField2 )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetAddressField3 )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetStartOffset )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetEndOffset )( __RPC__in ISymUnmanagedVariable * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); END_INTERFACE } ISymUnmanagedVariableVtbl; interface ISymUnmanagedVariable { CONST_VTBL struct ISymUnmanagedVariableVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedVariable_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedVariable_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedVariable_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedVariable_GetName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetName(This,cchName,pcchName,szName) ) #define ISymUnmanagedVariable_GetAttributes(This,pRetVal) \ ( (This)->lpVtbl -> GetAttributes(This,pRetVal) ) #define ISymUnmanagedVariable_GetSignature(This,cSig,pcSig,sig) \ ( (This)->lpVtbl -> GetSignature(This,cSig,pcSig,sig) ) #define ISymUnmanagedVariable_GetAddressKind(This,pRetVal) \ ( (This)->lpVtbl -> GetAddressKind(This,pRetVal) ) #define ISymUnmanagedVariable_GetAddressField1(This,pRetVal) \ ( (This)->lpVtbl -> GetAddressField1(This,pRetVal) ) #define ISymUnmanagedVariable_GetAddressField2(This,pRetVal) \ ( (This)->lpVtbl -> GetAddressField2(This,pRetVal) ) #define ISymUnmanagedVariable_GetAddressField3(This,pRetVal) \ ( (This)->lpVtbl -> GetAddressField3(This,pRetVal) ) #define ISymUnmanagedVariable_GetStartOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetStartOffset(This,pRetVal) ) #define ISymUnmanagedVariable_GetEndOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetEndOffset(This,pRetVal) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedVariable_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedSymbolSearchInfo_INTERFACE_DEFINED__ #define __ISymUnmanagedSymbolSearchInfo_INTERFACE_DEFINED__ /* interface ISymUnmanagedSymbolSearchInfo */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedSymbolSearchInfo; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F8B3534A-A46B-4980-B520-BEC4ACEABA8F") ISymUnmanagedSymbolSearchInfo : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetSearchPathLength( /* [out] */ __RPC__out ULONG32 *pcchPath) = 0; virtual HRESULT STDMETHODCALLTYPE GetSearchPath( /* [in] */ ULONG32 cchPath, /* [out] */ __RPC__out ULONG32 *pcchPath, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchPath, *pcchPath) WCHAR szPath[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetHRESULT( /* [out] */ __RPC__out HRESULT *phr) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedSymbolSearchInfoVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedSymbolSearchInfo * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedSymbolSearchInfo * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedSymbolSearchInfo * This); HRESULT ( STDMETHODCALLTYPE *GetSearchPathLength )( __RPC__in ISymUnmanagedSymbolSearchInfo * This, /* [out] */ __RPC__out ULONG32 *pcchPath); HRESULT ( STDMETHODCALLTYPE *GetSearchPath )( __RPC__in ISymUnmanagedSymbolSearchInfo * This, /* [in] */ ULONG32 cchPath, /* [out] */ __RPC__out ULONG32 *pcchPath, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchPath, *pcchPath) WCHAR szPath[ ]); HRESULT ( STDMETHODCALLTYPE *GetHRESULT )( __RPC__in ISymUnmanagedSymbolSearchInfo * This, /* [out] */ __RPC__out HRESULT *phr); END_INTERFACE } ISymUnmanagedSymbolSearchInfoVtbl; interface ISymUnmanagedSymbolSearchInfo { CONST_VTBL struct ISymUnmanagedSymbolSearchInfoVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedSymbolSearchInfo_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedSymbolSearchInfo_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedSymbolSearchInfo_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedSymbolSearchInfo_GetSearchPathLength(This,pcchPath) \ ( (This)->lpVtbl -> GetSearchPathLength(This,pcchPath) ) #define ISymUnmanagedSymbolSearchInfo_GetSearchPath(This,cchPath,pcchPath,szPath) \ ( (This)->lpVtbl -> GetSearchPath(This,cchPath,pcchPath,szPath) ) #define ISymUnmanagedSymbolSearchInfo_GetHRESULT(This,phr) \ ( (This)->lpVtbl -> GetHRESULT(This,phr) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedSymbolSearchInfo_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedWriter_INTERFACE_DEFINED__ #define __ISymUnmanagedWriter_INTERFACE_DEFINED__ /* interface ISymUnmanagedWriter */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedWriter; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("ED14AA72-78E2-4884-84E2-334293AE5214") ISymUnmanagedWriter : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE DefineDocument( /* [in] */ __RPC__in const WCHAR *url, /* [in] */ __RPC__in const GUID *language, /* [in] */ __RPC__in const GUID *languageVendor, /* [in] */ __RPC__in const GUID *documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE SetUserEntryPoint( /* [in] */ mdMethodDef entryMethod) = 0; virtual HRESULT STDMETHODCALLTYPE OpenMethod( /* [in] */ mdMethodDef method) = 0; virtual HRESULT STDMETHODCALLTYPE CloseMethod( void) = 0; virtual HRESULT STDMETHODCALLTYPE OpenScope( /* [in] */ ULONG32 startOffset, /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE CloseScope( /* [in] */ ULONG32 endOffset) = 0; virtual HRESULT STDMETHODCALLTYPE SetScopeRange( /* [in] */ ULONG32 scopeID, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset) = 0; virtual HRESULT STDMETHODCALLTYPE DefineLocalVariable( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset) = 0; virtual HRESULT STDMETHODCALLTYPE DefineParameter( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 sequence, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3) = 0; virtual HRESULT STDMETHODCALLTYPE DefineField( /* [in] */ mdTypeDef parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3) = 0; virtual HRESULT STDMETHODCALLTYPE DefineGlobalVariable( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3) = 0; virtual HRESULT STDMETHODCALLTYPE Close( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetSymAttribute( /* [in] */ mdToken parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 cData, /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE OpenNamespace( /* [in] */ __RPC__in const WCHAR *name) = 0; virtual HRESULT STDMETHODCALLTYPE CloseNamespace( void) = 0; virtual HRESULT STDMETHODCALLTYPE UsingNamespace( /* [in] */ __RPC__in const WCHAR *fullName) = 0; virtual HRESULT STDMETHODCALLTYPE SetMethodSourceRange( /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn) = 0; virtual HRESULT STDMETHODCALLTYPE Initialize( /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild) = 0; virtual HRESULT STDMETHODCALLTYPE GetDebugInfo( /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE DefineSequencePoints( /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 spCount, /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE RemapToken( /* [in] */ mdToken oldToken, /* [in] */ mdToken newToken) = 0; virtual HRESULT STDMETHODCALLTYPE Initialize2( /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *tempfilename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild, /* [in] */ __RPC__in const WCHAR *finalfilename) = 0; virtual HRESULT STDMETHODCALLTYPE DefineConstant( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedWriterVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedWriter * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedWriter * This); HRESULT ( STDMETHODCALLTYPE *DefineDocument )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *url, /* [in] */ __RPC__in const GUID *language, /* [in] */ __RPC__in const GUID *languageVendor, /* [in] */ __RPC__in const GUID *documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ mdMethodDef entryMethod); HRESULT ( STDMETHODCALLTYPE *OpenMethod )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ mdMethodDef method); HRESULT ( STDMETHODCALLTYPE *CloseMethod )( __RPC__in ISymUnmanagedWriter * This); HRESULT ( STDMETHODCALLTYPE *OpenScope )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ ULONG32 startOffset, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *CloseScope )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ ULONG32 scopeID, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineParameter )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 sequence, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineField )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ mdTypeDef parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *Close )( __RPC__in ISymUnmanagedWriter * This); HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 cData, /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *name); HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( __RPC__in ISymUnmanagedWriter * This); HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *fullName); HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild); HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( __RPC__in ISymUnmanagedWriter * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 spCount, /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); HRESULT ( STDMETHODCALLTYPE *RemapToken )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ mdToken oldToken, /* [in] */ mdToken newToken); HRESULT ( STDMETHODCALLTYPE *Initialize2 )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *tempfilename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild, /* [in] */ __RPC__in const WCHAR *finalfilename); HRESULT ( STDMETHODCALLTYPE *DefineConstant )( __RPC__in ISymUnmanagedWriter * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); HRESULT ( STDMETHODCALLTYPE *Abort )( __RPC__in ISymUnmanagedWriter * This); END_INTERFACE } ISymUnmanagedWriterVtbl; interface ISymUnmanagedWriter { CONST_VTBL struct ISymUnmanagedWriterVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedWriter_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedWriter_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedWriter_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedWriter_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedWriter_SetUserEntryPoint(This,entryMethod) \ ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) #define ISymUnmanagedWriter_OpenMethod(This,method) \ ( (This)->lpVtbl -> OpenMethod(This,method) ) #define ISymUnmanagedWriter_CloseMethod(This) \ ( (This)->lpVtbl -> CloseMethod(This) ) #define ISymUnmanagedWriter_OpenScope(This,startOffset,pRetVal) \ ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) #define ISymUnmanagedWriter_CloseScope(This,endOffset) \ ( (This)->lpVtbl -> CloseScope(This,endOffset) ) #define ISymUnmanagedWriter_SetScopeRange(This,scopeID,startOffset,endOffset) \ ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) #define ISymUnmanagedWriter_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter_Close(This) \ ( (This)->lpVtbl -> Close(This) ) #define ISymUnmanagedWriter_SetSymAttribute(This,parent,name,cData,data) \ ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) #define ISymUnmanagedWriter_OpenNamespace(This,name) \ ( (This)->lpVtbl -> OpenNamespace(This,name) ) #define ISymUnmanagedWriter_CloseNamespace(This) \ ( (This)->lpVtbl -> CloseNamespace(This) ) #define ISymUnmanagedWriter_UsingNamespace(This,fullName) \ ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) #define ISymUnmanagedWriter_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) #define ISymUnmanagedWriter_Initialize(This,emitter,filename,pIStream,fFullBuild) \ ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) #define ISymUnmanagedWriter_GetDebugInfo(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) #define ISymUnmanagedWriter_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) #define ISymUnmanagedWriter_RemapToken(This,oldToken,newToken) \ ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) #define ISymUnmanagedWriter_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) #define ISymUnmanagedWriter_DefineConstant(This,name,value,cSig,signature) \ ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) #define ISymUnmanagedWriter_Abort(This) \ ( (This)->lpVtbl -> Abort(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedWriter_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedWriter2_INTERFACE_DEFINED__ #define __ISymUnmanagedWriter2_INTERFACE_DEFINED__ /* interface ISymUnmanagedWriter2 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedWriter2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("0B97726E-9E6D-4f05-9A26-424022093CAA") ISymUnmanagedWriter2 : public ISymUnmanagedWriter { public: virtual HRESULT STDMETHODCALLTYPE DefineLocalVariable2( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset) = 0; virtual HRESULT STDMETHODCALLTYPE DefineGlobalVariable2( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3) = 0; virtual HRESULT STDMETHODCALLTYPE DefineConstant2( /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ mdSignature sigToken) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedWriter2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedWriter2 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedWriter2 * This); HRESULT ( STDMETHODCALLTYPE *DefineDocument )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *url, /* [in] */ __RPC__in const GUID *language, /* [in] */ __RPC__in const GUID *languageVendor, /* [in] */ __RPC__in const GUID *documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ mdMethodDef entryMethod); HRESULT ( STDMETHODCALLTYPE *OpenMethod )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ mdMethodDef method); HRESULT ( STDMETHODCALLTYPE *CloseMethod )( __RPC__in ISymUnmanagedWriter2 * This); HRESULT ( STDMETHODCALLTYPE *OpenScope )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ ULONG32 startOffset, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *CloseScope )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ ULONG32 scopeID, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineParameter )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 sequence, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineField )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ mdTypeDef parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *Close )( __RPC__in ISymUnmanagedWriter2 * This); HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 cData, /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name); HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( __RPC__in ISymUnmanagedWriter2 * This); HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *fullName); HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild); HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( __RPC__in ISymUnmanagedWriter2 * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 spCount, /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); HRESULT ( STDMETHODCALLTYPE *RemapToken )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ mdToken oldToken, /* [in] */ mdToken newToken); HRESULT ( STDMETHODCALLTYPE *Initialize2 )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *tempfilename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild, /* [in] */ __RPC__in const WCHAR *finalfilename); HRESULT ( STDMETHODCALLTYPE *DefineConstant )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); HRESULT ( STDMETHODCALLTYPE *Abort )( __RPC__in ISymUnmanagedWriter2 * This); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( __RPC__in ISymUnmanagedWriter2 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ mdSignature sigToken); END_INTERFACE } ISymUnmanagedWriter2Vtbl; interface ISymUnmanagedWriter2 { CONST_VTBL struct ISymUnmanagedWriter2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedWriter2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedWriter2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedWriter2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedWriter2_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedWriter2_SetUserEntryPoint(This,entryMethod) \ ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) #define ISymUnmanagedWriter2_OpenMethod(This,method) \ ( (This)->lpVtbl -> OpenMethod(This,method) ) #define ISymUnmanagedWriter2_CloseMethod(This) \ ( (This)->lpVtbl -> CloseMethod(This) ) #define ISymUnmanagedWriter2_OpenScope(This,startOffset,pRetVal) \ ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) #define ISymUnmanagedWriter2_CloseScope(This,endOffset) \ ( (This)->lpVtbl -> CloseScope(This,endOffset) ) #define ISymUnmanagedWriter2_SetScopeRange(This,scopeID,startOffset,endOffset) \ ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) #define ISymUnmanagedWriter2_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter2_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter2_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter2_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter2_Close(This) \ ( (This)->lpVtbl -> Close(This) ) #define ISymUnmanagedWriter2_SetSymAttribute(This,parent,name,cData,data) \ ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) #define ISymUnmanagedWriter2_OpenNamespace(This,name) \ ( (This)->lpVtbl -> OpenNamespace(This,name) ) #define ISymUnmanagedWriter2_CloseNamespace(This) \ ( (This)->lpVtbl -> CloseNamespace(This) ) #define ISymUnmanagedWriter2_UsingNamespace(This,fullName) \ ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) #define ISymUnmanagedWriter2_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) #define ISymUnmanagedWriter2_Initialize(This,emitter,filename,pIStream,fFullBuild) \ ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) #define ISymUnmanagedWriter2_GetDebugInfo(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) #define ISymUnmanagedWriter2_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) #define ISymUnmanagedWriter2_RemapToken(This,oldToken,newToken) \ ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) #define ISymUnmanagedWriter2_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) #define ISymUnmanagedWriter2_DefineConstant(This,name,value,cSig,signature) \ ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) #define ISymUnmanagedWriter2_Abort(This) \ ( (This)->lpVtbl -> Abort(This) ) #define ISymUnmanagedWriter2_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter2_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter2_DefineConstant2(This,name,value,sigToken) \ ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedWriter2_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedWriter3_INTERFACE_DEFINED__ #define __ISymUnmanagedWriter3_INTERFACE_DEFINED__ /* interface ISymUnmanagedWriter3 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedWriter3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("12F1E02C-1E05-4B0E-9468-EBC9D1BB040F") ISymUnmanagedWriter3 : public ISymUnmanagedWriter2 { public: virtual HRESULT STDMETHODCALLTYPE OpenMethod2( /* [in] */ mdMethodDef method, /* [in] */ ULONG32 isect, /* [in] */ ULONG32 offset) = 0; virtual HRESULT STDMETHODCALLTYPE Commit( void) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedWriter3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedWriter3 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedWriter3 * This); HRESULT ( STDMETHODCALLTYPE *DefineDocument )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *url, /* [in] */ __RPC__in const GUID *language, /* [in] */ __RPC__in const GUID *languageVendor, /* [in] */ __RPC__in const GUID *documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ mdMethodDef entryMethod); HRESULT ( STDMETHODCALLTYPE *OpenMethod )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ mdMethodDef method); HRESULT ( STDMETHODCALLTYPE *CloseMethod )( __RPC__in ISymUnmanagedWriter3 * This); HRESULT ( STDMETHODCALLTYPE *OpenScope )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ ULONG32 startOffset, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *CloseScope )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ ULONG32 scopeID, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineParameter )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 sequence, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineField )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ mdTypeDef parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *Close )( __RPC__in ISymUnmanagedWriter3 * This); HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 cData, /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name); HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( __RPC__in ISymUnmanagedWriter3 * This); HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *fullName); HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild); HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( __RPC__in ISymUnmanagedWriter3 * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 spCount, /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); HRESULT ( STDMETHODCALLTYPE *RemapToken )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ mdToken oldToken, /* [in] */ mdToken newToken); HRESULT ( STDMETHODCALLTYPE *Initialize2 )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *tempfilename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild, /* [in] */ __RPC__in const WCHAR *finalfilename); HRESULT ( STDMETHODCALLTYPE *DefineConstant )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); HRESULT ( STDMETHODCALLTYPE *Abort )( __RPC__in ISymUnmanagedWriter3 * This); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ mdSignature sigToken); HRESULT ( STDMETHODCALLTYPE *OpenMethod2 )( __RPC__in ISymUnmanagedWriter3 * This, /* [in] */ mdMethodDef method, /* [in] */ ULONG32 isect, /* [in] */ ULONG32 offset); HRESULT ( STDMETHODCALLTYPE *Commit )( __RPC__in ISymUnmanagedWriter3 * This); END_INTERFACE } ISymUnmanagedWriter3Vtbl; interface ISymUnmanagedWriter3 { CONST_VTBL struct ISymUnmanagedWriter3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedWriter3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedWriter3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedWriter3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedWriter3_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedWriter3_SetUserEntryPoint(This,entryMethod) \ ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) #define ISymUnmanagedWriter3_OpenMethod(This,method) \ ( (This)->lpVtbl -> OpenMethod(This,method) ) #define ISymUnmanagedWriter3_CloseMethod(This) \ ( (This)->lpVtbl -> CloseMethod(This) ) #define ISymUnmanagedWriter3_OpenScope(This,startOffset,pRetVal) \ ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) #define ISymUnmanagedWriter3_CloseScope(This,endOffset) \ ( (This)->lpVtbl -> CloseScope(This,endOffset) ) #define ISymUnmanagedWriter3_SetScopeRange(This,scopeID,startOffset,endOffset) \ ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) #define ISymUnmanagedWriter3_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter3_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter3_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter3_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter3_Close(This) \ ( (This)->lpVtbl -> Close(This) ) #define ISymUnmanagedWriter3_SetSymAttribute(This,parent,name,cData,data) \ ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) #define ISymUnmanagedWriter3_OpenNamespace(This,name) \ ( (This)->lpVtbl -> OpenNamespace(This,name) ) #define ISymUnmanagedWriter3_CloseNamespace(This) \ ( (This)->lpVtbl -> CloseNamespace(This) ) #define ISymUnmanagedWriter3_UsingNamespace(This,fullName) \ ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) #define ISymUnmanagedWriter3_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) #define ISymUnmanagedWriter3_Initialize(This,emitter,filename,pIStream,fFullBuild) \ ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) #define ISymUnmanagedWriter3_GetDebugInfo(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) #define ISymUnmanagedWriter3_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) #define ISymUnmanagedWriter3_RemapToken(This,oldToken,newToken) \ ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) #define ISymUnmanagedWriter3_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) #define ISymUnmanagedWriter3_DefineConstant(This,name,value,cSig,signature) \ ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) #define ISymUnmanagedWriter3_Abort(This) \ ( (This)->lpVtbl -> Abort(This) ) #define ISymUnmanagedWriter3_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter3_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter3_DefineConstant2(This,name,value,sigToken) \ ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) #define ISymUnmanagedWriter3_OpenMethod2(This,method,isect,offset) \ ( (This)->lpVtbl -> OpenMethod2(This,method,isect,offset) ) #define ISymUnmanagedWriter3_Commit(This) \ ( (This)->lpVtbl -> Commit(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedWriter3_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedWriter4_INTERFACE_DEFINED__ #define __ISymUnmanagedWriter4_INTERFACE_DEFINED__ /* interface ISymUnmanagedWriter4 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedWriter4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("BC7E3F53-F458-4C23-9DBD-A189E6E96594") ISymUnmanagedWriter4 : public ISymUnmanagedWriter3 { public: virtual HRESULT STDMETHODCALLTYPE GetDebugInfoWithPadding( /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedWriter4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedWriter4 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedWriter4 * This); HRESULT ( STDMETHODCALLTYPE *DefineDocument )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *url, /* [in] */ __RPC__in const GUID *language, /* [in] */ __RPC__in const GUID *languageVendor, /* [in] */ __RPC__in const GUID *documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ mdMethodDef entryMethod); HRESULT ( STDMETHODCALLTYPE *OpenMethod )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ mdMethodDef method); HRESULT ( STDMETHODCALLTYPE *CloseMethod )( __RPC__in ISymUnmanagedWriter4 * This); HRESULT ( STDMETHODCALLTYPE *OpenScope )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ ULONG32 startOffset, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *CloseScope )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ ULONG32 scopeID, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineParameter )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 sequence, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineField )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ mdTypeDef parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *Close )( __RPC__in ISymUnmanagedWriter4 * This); HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 cData, /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name); HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( __RPC__in ISymUnmanagedWriter4 * This); HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *fullName); HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild); HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( __RPC__in ISymUnmanagedWriter4 * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 spCount, /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); HRESULT ( STDMETHODCALLTYPE *RemapToken )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ mdToken oldToken, /* [in] */ mdToken newToken); HRESULT ( STDMETHODCALLTYPE *Initialize2 )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *tempfilename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild, /* [in] */ __RPC__in const WCHAR *finalfilename); HRESULT ( STDMETHODCALLTYPE *DefineConstant )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); HRESULT ( STDMETHODCALLTYPE *Abort )( __RPC__in ISymUnmanagedWriter4 * This); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ mdSignature sigToken); HRESULT ( STDMETHODCALLTYPE *OpenMethod2 )( __RPC__in ISymUnmanagedWriter4 * This, /* [in] */ mdMethodDef method, /* [in] */ ULONG32 isect, /* [in] */ ULONG32 offset); HRESULT ( STDMETHODCALLTYPE *Commit )( __RPC__in ISymUnmanagedWriter4 * This); HRESULT ( STDMETHODCALLTYPE *GetDebugInfoWithPadding )( __RPC__in ISymUnmanagedWriter4 * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); END_INTERFACE } ISymUnmanagedWriter4Vtbl; interface ISymUnmanagedWriter4 { CONST_VTBL struct ISymUnmanagedWriter4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedWriter4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedWriter4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedWriter4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedWriter4_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedWriter4_SetUserEntryPoint(This,entryMethod) \ ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) #define ISymUnmanagedWriter4_OpenMethod(This,method) \ ( (This)->lpVtbl -> OpenMethod(This,method) ) #define ISymUnmanagedWriter4_CloseMethod(This) \ ( (This)->lpVtbl -> CloseMethod(This) ) #define ISymUnmanagedWriter4_OpenScope(This,startOffset,pRetVal) \ ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) #define ISymUnmanagedWriter4_CloseScope(This,endOffset) \ ( (This)->lpVtbl -> CloseScope(This,endOffset) ) #define ISymUnmanagedWriter4_SetScopeRange(This,scopeID,startOffset,endOffset) \ ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) #define ISymUnmanagedWriter4_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter4_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter4_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter4_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter4_Close(This) \ ( (This)->lpVtbl -> Close(This) ) #define ISymUnmanagedWriter4_SetSymAttribute(This,parent,name,cData,data) \ ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) #define ISymUnmanagedWriter4_OpenNamespace(This,name) \ ( (This)->lpVtbl -> OpenNamespace(This,name) ) #define ISymUnmanagedWriter4_CloseNamespace(This) \ ( (This)->lpVtbl -> CloseNamespace(This) ) #define ISymUnmanagedWriter4_UsingNamespace(This,fullName) \ ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) #define ISymUnmanagedWriter4_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) #define ISymUnmanagedWriter4_Initialize(This,emitter,filename,pIStream,fFullBuild) \ ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) #define ISymUnmanagedWriter4_GetDebugInfo(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) #define ISymUnmanagedWriter4_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) #define ISymUnmanagedWriter4_RemapToken(This,oldToken,newToken) \ ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) #define ISymUnmanagedWriter4_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) #define ISymUnmanagedWriter4_DefineConstant(This,name,value,cSig,signature) \ ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) #define ISymUnmanagedWriter4_Abort(This) \ ( (This)->lpVtbl -> Abort(This) ) #define ISymUnmanagedWriter4_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter4_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter4_DefineConstant2(This,name,value,sigToken) \ ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) #define ISymUnmanagedWriter4_OpenMethod2(This,method,isect,offset) \ ( (This)->lpVtbl -> OpenMethod2(This,method,isect,offset) ) #define ISymUnmanagedWriter4_Commit(This) \ ( (This)->lpVtbl -> Commit(This) ) #define ISymUnmanagedWriter4_GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedWriter4_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedWriter5_INTERFACE_DEFINED__ #define __ISymUnmanagedWriter5_INTERFACE_DEFINED__ /* interface ISymUnmanagedWriter5 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedWriter5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("DCF7780D-BDE9-45DF-ACFE-21731A32000C") ISymUnmanagedWriter5 : public ISymUnmanagedWriter4 { public: virtual HRESULT STDMETHODCALLTYPE OpenMapTokensToSourceSpans( void) = 0; virtual HRESULT STDMETHODCALLTYPE CloseMapTokensToSourceSpans( void) = 0; virtual HRESULT STDMETHODCALLTYPE MapTokenToSourceSpan( /* [in] */ mdToken token, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedWriter5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedWriter5 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *DefineDocument )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *url, /* [in] */ __RPC__in const GUID *language, /* [in] */ __RPC__in const GUID *languageVendor, /* [in] */ __RPC__in const GUID *documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocumentWriter **pRetVal); HRESULT ( STDMETHODCALLTYPE *SetUserEntryPoint )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdMethodDef entryMethod); HRESULT ( STDMETHODCALLTYPE *OpenMethod )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdMethodDef method); HRESULT ( STDMETHODCALLTYPE *CloseMethod )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *OpenScope )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ ULONG32 startOffset, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *CloseScope )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *SetScopeRange )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ ULONG32 scopeID, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineParameter )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 sequence, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineField )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdTypeDef parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ], /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *Close )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *SetSymAttribute )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 cData, /* [size_is][in] */ __RPC__in_ecount_full(cData) unsigned char data[ ]); HRESULT ( STDMETHODCALLTYPE *OpenNamespace )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name); HRESULT ( STDMETHODCALLTYPE *CloseNamespace )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *UsingNamespace )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *fullName); HRESULT ( STDMETHODCALLTYPE *SetMethodSourceRange )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *startDoc, /* [in] */ ULONG32 startLine, /* [in] */ ULONG32 startColumn, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *endDoc, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild); HRESULT ( STDMETHODCALLTYPE *GetDebugInfo )( __RPC__in ISymUnmanagedWriter5 * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *DefineSequencePoints )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 spCount, /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 offsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 lines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 columns[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endLines[ ], /* [size_is][in] */ __RPC__in_ecount_full(spCount) ULONG32 endColumns[ ]); HRESULT ( STDMETHODCALLTYPE *RemapToken )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdToken oldToken, /* [in] */ mdToken newToken); HRESULT ( STDMETHODCALLTYPE *Initialize2 )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in_opt IUnknown *emitter, /* [in] */ __RPC__in const WCHAR *tempfilename, /* [in] */ __RPC__in_opt IStream *pIStream, /* [in] */ BOOL fFullBuild, /* [in] */ __RPC__in const WCHAR *finalfilename); HRESULT ( STDMETHODCALLTYPE *DefineConstant )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ ULONG32 cSig, /* [size_is][in] */ __RPC__in_ecount_full(cSig) unsigned char signature[ ]); HRESULT ( STDMETHODCALLTYPE *Abort )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *DefineLocalVariable2 )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3, /* [in] */ ULONG32 startOffset, /* [in] */ ULONG32 endOffset); HRESULT ( STDMETHODCALLTYPE *DefineGlobalVariable2 )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ ULONG32 attributes, /* [in] */ mdSignature sigToken, /* [in] */ ULONG32 addrKind, /* [in] */ ULONG32 addr1, /* [in] */ ULONG32 addr2, /* [in] */ ULONG32 addr3); HRESULT ( STDMETHODCALLTYPE *DefineConstant2 )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ __RPC__in const WCHAR *name, /* [in] */ VARIANT value, /* [in] */ mdSignature sigToken); HRESULT ( STDMETHODCALLTYPE *OpenMethod2 )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdMethodDef method, /* [in] */ ULONG32 isect, /* [in] */ ULONG32 offset); HRESULT ( STDMETHODCALLTYPE *Commit )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *GetDebugInfoWithPadding )( __RPC__in ISymUnmanagedWriter5 * This, /* [out][in] */ __RPC__inout IMAGE_DEBUG_DIRECTORY *pIDD, /* [in] */ DWORD cData, /* [out] */ __RPC__out DWORD *pcData, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cData, *pcData) BYTE data[ ]); HRESULT ( STDMETHODCALLTYPE *OpenMapTokensToSourceSpans )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *CloseMapTokensToSourceSpans )( __RPC__in ISymUnmanagedWriter5 * This); HRESULT ( STDMETHODCALLTYPE *MapTokenToSourceSpan )( __RPC__in ISymUnmanagedWriter5 * This, /* [in] */ mdToken token, /* [in] */ __RPC__in_opt ISymUnmanagedDocumentWriter *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 endLine, /* [in] */ ULONG32 endColumn); END_INTERFACE } ISymUnmanagedWriter5Vtbl; interface ISymUnmanagedWriter5 { CONST_VTBL struct ISymUnmanagedWriter5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedWriter5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedWriter5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedWriter5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedWriter5_DefineDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> DefineDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedWriter5_SetUserEntryPoint(This,entryMethod) \ ( (This)->lpVtbl -> SetUserEntryPoint(This,entryMethod) ) #define ISymUnmanagedWriter5_OpenMethod(This,method) \ ( (This)->lpVtbl -> OpenMethod(This,method) ) #define ISymUnmanagedWriter5_CloseMethod(This) \ ( (This)->lpVtbl -> CloseMethod(This) ) #define ISymUnmanagedWriter5_OpenScope(This,startOffset,pRetVal) \ ( (This)->lpVtbl -> OpenScope(This,startOffset,pRetVal) ) #define ISymUnmanagedWriter5_CloseScope(This,endOffset) \ ( (This)->lpVtbl -> CloseScope(This,endOffset) ) #define ISymUnmanagedWriter5_SetScopeRange(This,scopeID,startOffset,endOffset) \ ( (This)->lpVtbl -> SetScopeRange(This,scopeID,startOffset,endOffset) ) #define ISymUnmanagedWriter5_DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter5_DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineParameter(This,name,attributes,sequence,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter5_DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineField(This,parent,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter5_DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable(This,name,attributes,cSig,signature,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter5_Close(This) \ ( (This)->lpVtbl -> Close(This) ) #define ISymUnmanagedWriter5_SetSymAttribute(This,parent,name,cData,data) \ ( (This)->lpVtbl -> SetSymAttribute(This,parent,name,cData,data) ) #define ISymUnmanagedWriter5_OpenNamespace(This,name) \ ( (This)->lpVtbl -> OpenNamespace(This,name) ) #define ISymUnmanagedWriter5_CloseNamespace(This) \ ( (This)->lpVtbl -> CloseNamespace(This) ) #define ISymUnmanagedWriter5_UsingNamespace(This,fullName) \ ( (This)->lpVtbl -> UsingNamespace(This,fullName) ) #define ISymUnmanagedWriter5_SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) \ ( (This)->lpVtbl -> SetMethodSourceRange(This,startDoc,startLine,startColumn,endDoc,endLine,endColumn) ) #define ISymUnmanagedWriter5_Initialize(This,emitter,filename,pIStream,fFullBuild) \ ( (This)->lpVtbl -> Initialize(This,emitter,filename,pIStream,fFullBuild) ) #define ISymUnmanagedWriter5_GetDebugInfo(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfo(This,pIDD,cData,pcData,data) ) #define ISymUnmanagedWriter5_DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) \ ( (This)->lpVtbl -> DefineSequencePoints(This,document,spCount,offsets,lines,columns,endLines,endColumns) ) #define ISymUnmanagedWriter5_RemapToken(This,oldToken,newToken) \ ( (This)->lpVtbl -> RemapToken(This,oldToken,newToken) ) #define ISymUnmanagedWriter5_Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) \ ( (This)->lpVtbl -> Initialize2(This,emitter,tempfilename,pIStream,fFullBuild,finalfilename) ) #define ISymUnmanagedWriter5_DefineConstant(This,name,value,cSig,signature) \ ( (This)->lpVtbl -> DefineConstant(This,name,value,cSig,signature) ) #define ISymUnmanagedWriter5_Abort(This) \ ( (This)->lpVtbl -> Abort(This) ) #define ISymUnmanagedWriter5_DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) \ ( (This)->lpVtbl -> DefineLocalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3,startOffset,endOffset) ) #define ISymUnmanagedWriter5_DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) \ ( (This)->lpVtbl -> DefineGlobalVariable2(This,name,attributes,sigToken,addrKind,addr1,addr2,addr3) ) #define ISymUnmanagedWriter5_DefineConstant2(This,name,value,sigToken) \ ( (This)->lpVtbl -> DefineConstant2(This,name,value,sigToken) ) #define ISymUnmanagedWriter5_OpenMethod2(This,method,isect,offset) \ ( (This)->lpVtbl -> OpenMethod2(This,method,isect,offset) ) #define ISymUnmanagedWriter5_Commit(This) \ ( (This)->lpVtbl -> Commit(This) ) #define ISymUnmanagedWriter5_GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) \ ( (This)->lpVtbl -> GetDebugInfoWithPadding(This,pIDD,cData,pcData,data) ) #define ISymUnmanagedWriter5_OpenMapTokensToSourceSpans(This) \ ( (This)->lpVtbl -> OpenMapTokensToSourceSpans(This) ) #define ISymUnmanagedWriter5_CloseMapTokensToSourceSpans(This) \ ( (This)->lpVtbl -> CloseMapTokensToSourceSpans(This) ) #define ISymUnmanagedWriter5_MapTokenToSourceSpan(This,token,document,line,column,endLine,endColumn) \ ( (This)->lpVtbl -> MapTokenToSourceSpan(This,token,document,line,column,endLine,endColumn) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedWriter5_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedReader2_INTERFACE_DEFINED__ #define __ISymUnmanagedReader2_INTERFACE_DEFINED__ /* interface ISymUnmanagedReader2 */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedReader2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A09E53B2-2A57-4cca-8F63-B84F7C35D4AA") ISymUnmanagedReader2 : public ISymUnmanagedReader { public: virtual HRESULT STDMETHODCALLTYPE GetMethodByVersionPreRemap( /* [in] */ mdMethodDef token, /* [in] */ int version, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetSymAttributePreRemap( /* [in] */ mdToken parent, /* [in] */ __RPC__in WCHAR *name, /* [in] */ ULONG32 cBuffer, /* [out] */ __RPC__out ULONG32 *pcBuffer, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodsInDocument( /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 cMethod, /* [out] */ __RPC__out ULONG32 *pcMethod, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedReader2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedReader2 * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedReader2 * This); HRESULT ( STDMETHODCALLTYPE *GetDocument )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in WCHAR *url, /* [in] */ GUID language, /* [in] */ GUID languageVendor, /* [in] */ GUID documentType, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedDocument **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetDocuments )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ ULONG32 cDocs, /* [out] */ __RPC__out ULONG32 *pcDocs, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cDocs, *pcDocs) ISymUnmanagedDocument *pDocs[ ]); HRESULT ( STDMETHODCALLTYPE *GetUserEntryPoint )( __RPC__in ISymUnmanagedReader2 * This, /* [retval][out] */ __RPC__out mdMethodDef *pToken); HRESULT ( STDMETHODCALLTYPE *GetMethod )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ mdMethodDef token, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetMethodByVersion )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ mdMethodDef token, /* [in] */ int version, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetVariables )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ mdToken parent, /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); HRESULT ( STDMETHODCALLTYPE *GetGlobalVariables )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ ULONG32 cVars, /* [out] */ __RPC__out ULONG32 *pcVars, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cVars, *pcVars) ISymUnmanagedVariable *pVars[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodFromDocumentPosition )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSymAttribute )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in WCHAR *name, /* [in] */ ULONG32 cBuffer, /* [out] */ __RPC__out ULONG32 *pcBuffer, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]); HRESULT ( STDMETHODCALLTYPE *GetNamespaces )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ ULONG32 cNameSpaces, /* [out] */ __RPC__out ULONG32 *pcNameSpaces, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cNameSpaces, *pcNameSpaces) ISymUnmanagedNamespace *namespaces[ ]); HRESULT ( STDMETHODCALLTYPE *Initialize )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in_opt IUnknown *importer, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in const WCHAR *searchPath, /* [in] */ __RPC__in_opt IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *UpdateSymbolStore )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *ReplaceSymbolStore )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in const WCHAR *filename, /* [in] */ __RPC__in_opt IStream *pIStream); HRESULT ( STDMETHODCALLTYPE *GetSymbolStoreFileName )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ ULONG32 cchName, /* [out] */ __RPC__out ULONG32 *pcchName, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cchName, *pcchName) WCHAR szName[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodsFromDocumentPosition )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 line, /* [in] */ ULONG32 column, /* [in] */ ULONG32 cMethod, /* [out] */ __RPC__out ULONG32 *pcMethod, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]); HRESULT ( STDMETHODCALLTYPE *GetDocumentVersion )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *pDoc, /* [out] */ __RPC__out int *version, /* [out] */ __RPC__out BOOL *pbCurrent); HRESULT ( STDMETHODCALLTYPE *GetMethodVersion )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedMethod *pMethod, /* [out] */ __RPC__out int *version); HRESULT ( STDMETHODCALLTYPE *GetMethodByVersionPreRemap )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ mdMethodDef token, /* [in] */ int version, /* [retval][out] */ __RPC__deref_out_opt ISymUnmanagedMethod **pRetVal); HRESULT ( STDMETHODCALLTYPE *GetSymAttributePreRemap )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ mdToken parent, /* [in] */ __RPC__in WCHAR *name, /* [in] */ ULONG32 cBuffer, /* [out] */ __RPC__out ULONG32 *pcBuffer, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cBuffer, *pcBuffer) BYTE buffer[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodsInDocument )( __RPC__in ISymUnmanagedReader2 * This, /* [in] */ __RPC__in_opt ISymUnmanagedDocument *document, /* [in] */ ULONG32 cMethod, /* [out] */ __RPC__out ULONG32 *pcMethod, /* [length_is][size_is][out] */ __RPC__out_ecount_part(cMethod, *pcMethod) ISymUnmanagedMethod *pRetVal[ ]); END_INTERFACE } ISymUnmanagedReader2Vtbl; interface ISymUnmanagedReader2 { CONST_VTBL struct ISymUnmanagedReader2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedReader2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedReader2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedReader2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedReader2_GetDocument(This,url,language,languageVendor,documentType,pRetVal) \ ( (This)->lpVtbl -> GetDocument(This,url,language,languageVendor,documentType,pRetVal) ) #define ISymUnmanagedReader2_GetDocuments(This,cDocs,pcDocs,pDocs) \ ( (This)->lpVtbl -> GetDocuments(This,cDocs,pcDocs,pDocs) ) #define ISymUnmanagedReader2_GetUserEntryPoint(This,pToken) \ ( (This)->lpVtbl -> GetUserEntryPoint(This,pToken) ) #define ISymUnmanagedReader2_GetMethod(This,token,pRetVal) \ ( (This)->lpVtbl -> GetMethod(This,token,pRetVal) ) #define ISymUnmanagedReader2_GetMethodByVersion(This,token,version,pRetVal) \ ( (This)->lpVtbl -> GetMethodByVersion(This,token,version,pRetVal) ) #define ISymUnmanagedReader2_GetVariables(This,parent,cVars,pcVars,pVars) \ ( (This)->lpVtbl -> GetVariables(This,parent,cVars,pcVars,pVars) ) #define ISymUnmanagedReader2_GetGlobalVariables(This,cVars,pcVars,pVars) \ ( (This)->lpVtbl -> GetGlobalVariables(This,cVars,pcVars,pVars) ) #define ISymUnmanagedReader2_GetMethodFromDocumentPosition(This,document,line,column,pRetVal) \ ( (This)->lpVtbl -> GetMethodFromDocumentPosition(This,document,line,column,pRetVal) ) #define ISymUnmanagedReader2_GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) \ ( (This)->lpVtbl -> GetSymAttribute(This,parent,name,cBuffer,pcBuffer,buffer) ) #define ISymUnmanagedReader2_GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) \ ( (This)->lpVtbl -> GetNamespaces(This,cNameSpaces,pcNameSpaces,namespaces) ) #define ISymUnmanagedReader2_Initialize(This,importer,filename,searchPath,pIStream) \ ( (This)->lpVtbl -> Initialize(This,importer,filename,searchPath,pIStream) ) #define ISymUnmanagedReader2_UpdateSymbolStore(This,filename,pIStream) \ ( (This)->lpVtbl -> UpdateSymbolStore(This,filename,pIStream) ) #define ISymUnmanagedReader2_ReplaceSymbolStore(This,filename,pIStream) \ ( (This)->lpVtbl -> ReplaceSymbolStore(This,filename,pIStream) ) #define ISymUnmanagedReader2_GetSymbolStoreFileName(This,cchName,pcchName,szName) \ ( (This)->lpVtbl -> GetSymbolStoreFileName(This,cchName,pcchName,szName) ) #define ISymUnmanagedReader2_GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) \ ( (This)->lpVtbl -> GetMethodsFromDocumentPosition(This,document,line,column,cMethod,pcMethod,pRetVal) ) #define ISymUnmanagedReader2_GetDocumentVersion(This,pDoc,version,pbCurrent) \ ( (This)->lpVtbl -> GetDocumentVersion(This,pDoc,version,pbCurrent) ) #define ISymUnmanagedReader2_GetMethodVersion(This,pMethod,version) \ ( (This)->lpVtbl -> GetMethodVersion(This,pMethod,version) ) #define ISymUnmanagedReader2_GetMethodByVersionPreRemap(This,token,version,pRetVal) \ ( (This)->lpVtbl -> GetMethodByVersionPreRemap(This,token,version,pRetVal) ) #define ISymUnmanagedReader2_GetSymAttributePreRemap(This,parent,name,cBuffer,pcBuffer,buffer) \ ( (This)->lpVtbl -> GetSymAttributePreRemap(This,parent,name,cBuffer,pcBuffer,buffer) ) #define ISymUnmanagedReader2_GetMethodsInDocument(This,document,cMethod,pcMethod,pRetVal) \ ( (This)->lpVtbl -> GetMethodsInDocument(This,document,cMethod,pcMethod,pRetVal) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedReader2_INTERFACE_DEFINED__ */ #ifndef __ISymNGenWriter_INTERFACE_DEFINED__ #define __ISymNGenWriter_INTERFACE_DEFINED__ /* interface ISymNGenWriter */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymNGenWriter; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("d682fd12-43de-411c-811b-be8404cea126") ISymNGenWriter : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE AddSymbol( /* [in] */ __RPC__in BSTR pSymbol, /* [in] */ USHORT iSection, /* [in] */ ULONGLONG rva) = 0; virtual HRESULT STDMETHODCALLTYPE AddSection( /* [in] */ USHORT iSection, /* [in] */ USHORT flags, /* [in] */ long offset, /* [in] */ long cb) = 0; }; #else /* C style interface */ typedef struct ISymNGenWriterVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymNGenWriter * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymNGenWriter * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymNGenWriter * This); HRESULT ( STDMETHODCALLTYPE *AddSymbol )( __RPC__in ISymNGenWriter * This, /* [in] */ __RPC__in BSTR pSymbol, /* [in] */ USHORT iSection, /* [in] */ ULONGLONG rva); HRESULT ( STDMETHODCALLTYPE *AddSection )( __RPC__in ISymNGenWriter * This, /* [in] */ USHORT iSection, /* [in] */ USHORT flags, /* [in] */ long offset, /* [in] */ long cb); END_INTERFACE } ISymNGenWriterVtbl; interface ISymNGenWriter { CONST_VTBL struct ISymNGenWriterVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymNGenWriter_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymNGenWriter_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymNGenWriter_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymNGenWriter_AddSymbol(This,pSymbol,iSection,rva) \ ( (This)->lpVtbl -> AddSymbol(This,pSymbol,iSection,rva) ) #define ISymNGenWriter_AddSection(This,iSection,flags,offset,cb) \ ( (This)->lpVtbl -> AddSection(This,iSection,flags,offset,cb) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymNGenWriter_INTERFACE_DEFINED__ */ #ifndef __ISymNGenWriter2_INTERFACE_DEFINED__ #define __ISymNGenWriter2_INTERFACE_DEFINED__ /* interface ISymNGenWriter2 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ISymNGenWriter2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4") ISymNGenWriter2 : public ISymNGenWriter { public: virtual HRESULT STDMETHODCALLTYPE OpenModW( /* [in] */ LPCWSTR wszModule, /* [in] */ LPCWSTR wszObjFile, /* [out] */ BYTE **ppmod) = 0; virtual HRESULT STDMETHODCALLTYPE CloseMod( /* [in] */ BYTE *pmod) = 0; virtual HRESULT STDMETHODCALLTYPE ModAddSymbols( /* [in] */ BYTE *pmod, /* [in] */ BYTE *pbSym, /* [in] */ long cb) = 0; virtual HRESULT STDMETHODCALLTYPE ModAddSecContribEx( /* [in] */ BYTE *pmod, /* [in] */ USHORT isect, /* [in] */ long off, /* [in] */ long cb, /* [in] */ ULONG dwCharacteristics, /* [in] */ DWORD dwDataCrc, /* [in] */ DWORD dwRelocCrc) = 0; virtual HRESULT STDMETHODCALLTYPE QueryPDBNameExW( /* [size_is][out] */ WCHAR wszPDB[ ], /* [in] */ SIZE_T cchMax) = 0; }; #else /* C style interface */ typedef struct ISymNGenWriter2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISymNGenWriter2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISymNGenWriter2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISymNGenWriter2 * This); HRESULT ( STDMETHODCALLTYPE *AddSymbol )( ISymNGenWriter2 * This, /* [in] */ BSTR pSymbol, /* [in] */ USHORT iSection, /* [in] */ ULONGLONG rva); HRESULT ( STDMETHODCALLTYPE *AddSection )( ISymNGenWriter2 * This, /* [in] */ USHORT iSection, /* [in] */ USHORT flags, /* [in] */ long offset, /* [in] */ long cb); HRESULT ( STDMETHODCALLTYPE *OpenModW )( ISymNGenWriter2 * This, /* [in] */ const WCHAR *wszModule, /* [in] */ const WCHAR *wszObjFile, /* [out] */ BYTE **ppmod); HRESULT ( STDMETHODCALLTYPE *CloseMod )( ISymNGenWriter2 * This, /* [in] */ BYTE *pmod); HRESULT ( STDMETHODCALLTYPE *ModAddSymbols )( ISymNGenWriter2 * This, /* [in] */ BYTE *pmod, /* [in] */ BYTE *pbSym, /* [in] */ long cb); HRESULT ( STDMETHODCALLTYPE *ModAddSecContribEx )( ISymNGenWriter2 * This, /* [in] */ BYTE *pmod, /* [in] */ USHORT isect, /* [in] */ long off, /* [in] */ long cb, /* [in] */ ULONG dwCharacteristics, /* [in] */ DWORD dwDataCrc, /* [in] */ DWORD dwRelocCrc); HRESULT ( STDMETHODCALLTYPE *QueryPDBNameExW )( ISymNGenWriter2 * This, /* [size_is][out] */ WCHAR wszPDB[ ], /* [in] */ SIZE_T cchMax); END_INTERFACE } ISymNGenWriter2Vtbl; interface ISymNGenWriter2 { CONST_VTBL struct ISymNGenWriter2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymNGenWriter2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymNGenWriter2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymNGenWriter2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymNGenWriter2_AddSymbol(This,pSymbol,iSection,rva) \ ( (This)->lpVtbl -> AddSymbol(This,pSymbol,iSection,rva) ) #define ISymNGenWriter2_AddSection(This,iSection,flags,offset,cb) \ ( (This)->lpVtbl -> AddSection(This,iSection,flags,offset,cb) ) #define ISymNGenWriter2_OpenModW(This,wszModule,wszObjFile,ppmod) \ ( (This)->lpVtbl -> OpenModW(This,wszModule,wszObjFile,ppmod) ) #define ISymNGenWriter2_CloseMod(This,pmod) \ ( (This)->lpVtbl -> CloseMod(This,pmod) ) #define ISymNGenWriter2_ModAddSymbols(This,pmod,pbSym,cb) \ ( (This)->lpVtbl -> ModAddSymbols(This,pmod,pbSym,cb) ) #define ISymNGenWriter2_ModAddSecContribEx(This,pmod,isect,off,cb,dwCharacteristics,dwDataCrc,dwRelocCrc) \ ( (This)->lpVtbl -> ModAddSecContribEx(This,pmod,isect,off,cb,dwCharacteristics,dwDataCrc,dwRelocCrc) ) #define ISymNGenWriter2_QueryPDBNameExW(This,wszPDB,cchMax) \ ( (This)->lpVtbl -> QueryPDBNameExW(This,wszPDB,cchMax) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymNGenWriter2_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedAsyncMethodPropertiesWriter_INTERFACE_DEFINED__ #define __ISymUnmanagedAsyncMethodPropertiesWriter_INTERFACE_DEFINED__ /* interface ISymUnmanagedAsyncMethodPropertiesWriter */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedAsyncMethodPropertiesWriter; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("FC073774-1739-4232-BD56-A027294BEC15") ISymUnmanagedAsyncMethodPropertiesWriter : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE DefineKickoffMethod( /* [in] */ mdToken kickoffMethod) = 0; virtual HRESULT STDMETHODCALLTYPE DefineCatchHandlerILOffset( /* [in] */ ULONG32 catchHandlerOffset) = 0; virtual HRESULT STDMETHODCALLTYPE DefineAsyncStepInfo( /* [in] */ ULONG32 count, /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 yieldOffsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 breakpointOffset[ ], /* [size_is][in] */ __RPC__in_ecount_full(count) mdToken breakpointMethod[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedAsyncMethodPropertiesWriterVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This); HRESULT ( STDMETHODCALLTYPE *DefineKickoffMethod )( __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, /* [in] */ mdToken kickoffMethod); HRESULT ( STDMETHODCALLTYPE *DefineCatchHandlerILOffset )( __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, /* [in] */ ULONG32 catchHandlerOffset); HRESULT ( STDMETHODCALLTYPE *DefineAsyncStepInfo )( __RPC__in ISymUnmanagedAsyncMethodPropertiesWriter * This, /* [in] */ ULONG32 count, /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 yieldOffsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(count) ULONG32 breakpointOffset[ ], /* [size_is][in] */ __RPC__in_ecount_full(count) mdToken breakpointMethod[ ]); END_INTERFACE } ISymUnmanagedAsyncMethodPropertiesWriterVtbl; interface ISymUnmanagedAsyncMethodPropertiesWriter { CONST_VTBL struct ISymUnmanagedAsyncMethodPropertiesWriterVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedAsyncMethodPropertiesWriter_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedAsyncMethodPropertiesWriter_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedAsyncMethodPropertiesWriter_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedAsyncMethodPropertiesWriter_DefineKickoffMethod(This,kickoffMethod) \ ( (This)->lpVtbl -> DefineKickoffMethod(This,kickoffMethod) ) #define ISymUnmanagedAsyncMethodPropertiesWriter_DefineCatchHandlerILOffset(This,catchHandlerOffset) \ ( (This)->lpVtbl -> DefineCatchHandlerILOffset(This,catchHandlerOffset) ) #define ISymUnmanagedAsyncMethodPropertiesWriter_DefineAsyncStepInfo(This,count,yieldOffsets,breakpointOffset,breakpointMethod) \ ( (This)->lpVtbl -> DefineAsyncStepInfo(This,count,yieldOffsets,breakpointOffset,breakpointMethod) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedAsyncMethodPropertiesWriter_INTERFACE_DEFINED__ */ #ifndef __ISymUnmanagedAsyncMethod_INTERFACE_DEFINED__ #define __ISymUnmanagedAsyncMethod_INTERFACE_DEFINED__ /* interface ISymUnmanagedAsyncMethod */ /* [unique][uuid][object] */ EXTERN_C const IID IID_ISymUnmanagedAsyncMethod; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B20D55B3-532E-4906-87E7-25BD5734ABD2") ISymUnmanagedAsyncMethod : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsAsyncMethod( /* [retval][out] */ __RPC__out BOOL *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetKickoffMethod( /* [retval][out] */ __RPC__out mdToken *kickoffMethod) = 0; virtual HRESULT STDMETHODCALLTYPE HasCatchHandlerILOffset( /* [retval][out] */ __RPC__out BOOL *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetCatchHandlerILOffset( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetAsyncStepInfoCount( /* [retval][out] */ __RPC__out ULONG32 *pRetVal) = 0; virtual HRESULT STDMETHODCALLTYPE GetAsyncStepInfo( /* [in] */ ULONG32 cStepInfo, /* [out] */ __RPC__out ULONG32 *pcStepInfo, /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 yieldOffsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 breakpointOffset[ ], /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) mdToken breakpointMethod[ ]) = 0; }; #else /* C style interface */ typedef struct ISymUnmanagedAsyncMethodVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [in] */ __RPC__in REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( __RPC__in ISymUnmanagedAsyncMethod * This); ULONG ( STDMETHODCALLTYPE *Release )( __RPC__in ISymUnmanagedAsyncMethod * This); HRESULT ( STDMETHODCALLTYPE *IsAsyncMethod )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [retval][out] */ __RPC__out BOOL *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetKickoffMethod )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [retval][out] */ __RPC__out mdToken *kickoffMethod); HRESULT ( STDMETHODCALLTYPE *HasCatchHandlerILOffset )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [retval][out] */ __RPC__out BOOL *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetCatchHandlerILOffset )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetAsyncStepInfoCount )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [retval][out] */ __RPC__out ULONG32 *pRetVal); HRESULT ( STDMETHODCALLTYPE *GetAsyncStepInfo )( __RPC__in ISymUnmanagedAsyncMethod * This, /* [in] */ ULONG32 cStepInfo, /* [out] */ __RPC__out ULONG32 *pcStepInfo, /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 yieldOffsets[ ], /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) ULONG32 breakpointOffset[ ], /* [size_is][in] */ __RPC__in_ecount_full(cStepInfo) mdToken breakpointMethod[ ]); END_INTERFACE } ISymUnmanagedAsyncMethodVtbl; interface ISymUnmanagedAsyncMethod { CONST_VTBL struct ISymUnmanagedAsyncMethodVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISymUnmanagedAsyncMethod_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISymUnmanagedAsyncMethod_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISymUnmanagedAsyncMethod_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISymUnmanagedAsyncMethod_IsAsyncMethod(This,pRetVal) \ ( (This)->lpVtbl -> IsAsyncMethod(This,pRetVal) ) #define ISymUnmanagedAsyncMethod_GetKickoffMethod(This,kickoffMethod) \ ( (This)->lpVtbl -> GetKickoffMethod(This,kickoffMethod) ) #define ISymUnmanagedAsyncMethod_HasCatchHandlerILOffset(This,pRetVal) \ ( (This)->lpVtbl -> HasCatchHandlerILOffset(This,pRetVal) ) #define ISymUnmanagedAsyncMethod_GetCatchHandlerILOffset(This,pRetVal) \ ( (This)->lpVtbl -> GetCatchHandlerILOffset(This,pRetVal) ) #define ISymUnmanagedAsyncMethod_GetAsyncStepInfoCount(This,pRetVal) \ ( (This)->lpVtbl -> GetAsyncStepInfoCount(This,pRetVal) ) #define ISymUnmanagedAsyncMethod_GetAsyncStepInfo(This,cStepInfo,pcStepInfo,yieldOffsets,breakpointOffset,breakpointMethod) \ ( (This)->lpVtbl -> GetAsyncStepInfo(This,cStepInfo,pcStepInfo,yieldOffsets,breakpointOffset,breakpointMethod) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISymUnmanagedAsyncMethod_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ unsigned long __RPC_USER BSTR_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in BSTR * ); unsigned char * __RPC_USER BSTR_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in BSTR * ); unsigned char * __RPC_USER BSTR_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out BSTR * ); void __RPC_USER BSTR_UserFree( __RPC__in unsigned long *, __RPC__in BSTR * ); unsigned long __RPC_USER VARIANT_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in VARIANT * ); unsigned char * __RPC_USER VARIANT_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in VARIANT * ); unsigned char * __RPC_USER VARIANT_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out VARIANT * ); void __RPC_USER VARIANT_UserFree( __RPC__in unsigned long *, __RPC__in VARIANT * ); /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/fxver.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #include #define QUOTE_MACRO_HELPER(x) #x #define QUOTE_MACRO(x) QUOTE_MACRO_HELPER(x) #define VER_PRODUCTNAME_STR L"Microsoft\256 .NET" #define VER_INTERNALNAME_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) #define VER_ORIGINALFILENAME_STR QUOTE_MACRO(FX_VER_INTERNALNAME_STR) #define VER_FILEDESCRIPTION_STR FX_VER_FILEDESCRIPTION_STR #define VER_COMMENTS_STR "Flavor=" QUOTE_MACRO(URTBLDENV_FRIENDLY) #define VER_FILEFLAGSMASK VS_FFI_FILEFLAGSMASK #define VER_FILEFLAGS VER_DEBUG #define VER_FILEOS VOS__WINDOWS32 #define VER_FILETYPE VFT_UNKNOWN #define VER_FILESUBTYPE VFT2_UNKNOWN #define VER_VERSION_UNICODE_LANG "040904B0" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */ #define VER_VERSION_ANSI_LANG "040904E4" /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Ansi CP */ #define VER_VERSION_TRANSLATION 0x0409, 0x04B0 ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/fxver.rc ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #ifdef _WIN32 #include <_version.h> #endif //_WIN32 #ifdef RC_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_PRODUCTVERSION FILEFLAGSMASK VER_FILEFLAGSMASK FILEFLAGS VER_FILEFLAGS FILEOS VER_FILEOS FILETYPE VER_FILETYPE FILESUBTYPE VER_FILESUBTYPE BEGIN BLOCK "StringFileInfo" BEGIN BLOCK VER_VERSION_UNICODE_LANG BEGIN VALUE "CompanyName", VER_COMPANYNAME_STR VALUE "FileDescription", VER_FILEDESCRIPTION_STR VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", VER_INTERNALNAME_STR VALUE "LegalCopyright", VER_LEGALCOPYRIGHT_STR VALUE "OriginalFilename",VER_ORIGINALFILENAME_STR VALUE "ProductName", VER_PRODUCTNAME_STR VALUE "ProductVersion", VER_FILEVERSION_STR VALUE "Comments", VER_COMMENTS_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", VER_VERSION_TRANSLATION END END #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/metahost.h ================================================ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0622 */ /* at Mon Jan 18 19:14:07 2038 */ /* Compiler settings for metahost.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __metahost_h__ #define __metahost_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __ICLRMetaHost_FWD_DEFINED__ #define __ICLRMetaHost_FWD_DEFINED__ typedef interface ICLRMetaHost ICLRMetaHost; #endif /* __ICLRMetaHost_FWD_DEFINED__ */ #ifndef __ICLRDebuggingLibraryProvider_FWD_DEFINED__ #define __ICLRDebuggingLibraryProvider_FWD_DEFINED__ typedef interface ICLRDebuggingLibraryProvider ICLRDebuggingLibraryProvider; #endif /* __ICLRDebuggingLibraryProvider_FWD_DEFINED__ */ #ifndef __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ #define __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ typedef interface ICLRDebuggingLibraryProvider2 ICLRDebuggingLibraryProvider2; #endif /* __ICLRDebuggingLibraryProvider2_FWD_DEFINED__ */ #ifndef __ICLRDebugging_FWD_DEFINED__ #define __ICLRDebugging_FWD_DEFINED__ typedef interface ICLRDebugging ICLRDebugging; #endif /* __ICLRDebugging_FWD_DEFINED__ */ #ifndef __ICLRRuntimeInfo_FWD_DEFINED__ #define __ICLRRuntimeInfo_FWD_DEFINED__ typedef interface ICLRRuntimeInfo ICLRRuntimeInfo; #endif /* __ICLRRuntimeInfo_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #include "oaidl.h" #include "ocidl.h" #include "mscoree.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_metahost_0000_0000 */ /* [local] */ STDAPI CLRCreateInstance(REFCLSID clsid, REFIID riid, /*iid_is(riid)*/ LPVOID *ppInterface); EXTERN_GUID(IID_ICLRMetaHost, 0xD332DB9E, 0xB9B3, 0x4125, 0x82, 0x07, 0xA1, 0x48, 0x84, 0xF5, 0x32, 0x16); EXTERN_GUID(CLSID_CLRMetaHost, 0x9280188d, 0xe8e, 0x4867, 0xb3, 0xc, 0x7f, 0xa8, 0x38, 0x84, 0xe8, 0xde); EXTERN_GUID(IID_ICLRDebugging, 0xd28f3c5a, 0x9634, 0x4206, 0xa5, 0x9, 0x47, 0x75, 0x52, 0xee, 0xfb, 0x10); EXTERN_GUID(CLSID_CLRDebugging, 0xbacc578d, 0xfbdd, 0x48a4, 0x96, 0x9f, 0x2, 0xd9, 0x32, 0xb7, 0x46, 0x34); EXTERN_GUID(IID_ICLRRuntimeInfo, 0xBD39D1D2, 0xBA2F, 0x486a, 0x89, 0xB0, 0xB4, 0xB0, 0xCB, 0x46, 0x68, 0x91); EXTERN_GUID(IID_ICLRDebuggingLibraryProvider, 0x3151c08d, 0x4d09, 0x4f9b, 0x88, 0x38, 0x28, 0x80, 0xbf, 0x18, 0xfe, 0x51); EXTERN_GUID(IID_ICLRDebuggingLibraryProvider2, 0xE04E2FF1, 0xDCFD, 0x45D5, 0xBC, 0xD1, 0x16, 0xFF, 0xF2, 0xFA, 0xF7, 0xBA); typedef HRESULT ( __stdcall *CallbackThreadSetFnPtr )( void); typedef HRESULT ( __stdcall *CallbackThreadUnsetFnPtr )( void); typedef void ( __stdcall *RuntimeLoadedCallbackFnPtr )( ICLRRuntimeInfo *pRuntimeInfo, CallbackThreadSetFnPtr pfnCallbackThreadSet, CallbackThreadUnsetFnPtr pfnCallbackThreadUnset); extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0000_v0_0_s_ifspec; #ifndef __ICLRMetaHost_INTERFACE_DEFINED__ #define __ICLRMetaHost_INTERFACE_DEFINED__ /* interface ICLRMetaHost */ /* [object][local][helpstring][version][uuid] */ EXTERN_C const IID IID_ICLRMetaHost; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D332DB9E-B9B3-4125-8207-A14884F53216") ICLRMetaHost : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetRuntime( /* [in] */ LPCWSTR pwzVersion, /* [in] */ REFIID riid, /* [retval][iid_is][out] */ LPVOID *ppRuntime) = 0; virtual HRESULT STDMETHODCALLTYPE GetVersionFromFile( /* [in] */ LPCWSTR pwzFilePath, /* [annotation][size_is][out] */ _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateInstalledRuntimes( /* [retval][out] */ IEnumUnknown **ppEnumerator) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateLoadedRuntimes( /* [in] */ HANDLE hndProcess, /* [retval][out] */ IEnumUnknown **ppEnumerator) = 0; virtual HRESULT STDMETHODCALLTYPE RequestRuntimeLoadedNotification( /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction) = 0; virtual HRESULT STDMETHODCALLTYPE QueryLegacyV2RuntimeBinding( /* [in] */ REFIID riid, /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; virtual HRESULT STDMETHODCALLTYPE ExitProcess( /* [in] */ INT32 iExitCode) = 0; }; #else /* C style interface */ typedef struct ICLRMetaHostVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRMetaHost * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRMetaHost * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRMetaHost * This); HRESULT ( STDMETHODCALLTYPE *GetRuntime )( ICLRMetaHost * This, /* [in] */ LPCWSTR pwzVersion, /* [in] */ REFIID riid, /* [retval][iid_is][out] */ LPVOID *ppRuntime); HRESULT ( STDMETHODCALLTYPE *GetVersionFromFile )( ICLRMetaHost * This, /* [in] */ LPCWSTR pwzFilePath, /* [annotation][size_is][out] */ _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer); HRESULT ( STDMETHODCALLTYPE *EnumerateInstalledRuntimes )( ICLRMetaHost * This, /* [retval][out] */ IEnumUnknown **ppEnumerator); HRESULT ( STDMETHODCALLTYPE *EnumerateLoadedRuntimes )( ICLRMetaHost * This, /* [in] */ HANDLE hndProcess, /* [retval][out] */ IEnumUnknown **ppEnumerator); HRESULT ( STDMETHODCALLTYPE *RequestRuntimeLoadedNotification )( ICLRMetaHost * This, /* [in] */ RuntimeLoadedCallbackFnPtr pCallbackFunction); HRESULT ( STDMETHODCALLTYPE *QueryLegacyV2RuntimeBinding )( ICLRMetaHost * This, /* [in] */ REFIID riid, /* [retval][iid_is][out] */ LPVOID *ppUnk); HRESULT ( STDMETHODCALLTYPE *ExitProcess )( ICLRMetaHost * This, /* [in] */ INT32 iExitCode); END_INTERFACE } ICLRMetaHostVtbl; interface ICLRMetaHost { CONST_VTBL struct ICLRMetaHostVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRMetaHost_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRMetaHost_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRMetaHost_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRMetaHost_GetRuntime(This,pwzVersion,riid,ppRuntime) \ ( (This)->lpVtbl -> GetRuntime(This,pwzVersion,riid,ppRuntime) ) #define ICLRMetaHost_GetVersionFromFile(This,pwzFilePath,pwzBuffer,pcchBuffer) \ ( (This)->lpVtbl -> GetVersionFromFile(This,pwzFilePath,pwzBuffer,pcchBuffer) ) #define ICLRMetaHost_EnumerateInstalledRuntimes(This,ppEnumerator) \ ( (This)->lpVtbl -> EnumerateInstalledRuntimes(This,ppEnumerator) ) #define ICLRMetaHost_EnumerateLoadedRuntimes(This,hndProcess,ppEnumerator) \ ( (This)->lpVtbl -> EnumerateLoadedRuntimes(This,hndProcess,ppEnumerator) ) #define ICLRMetaHost_RequestRuntimeLoadedNotification(This,pCallbackFunction) \ ( (This)->lpVtbl -> RequestRuntimeLoadedNotification(This,pCallbackFunction) ) #define ICLRMetaHost_QueryLegacyV2RuntimeBinding(This,riid,ppUnk) \ ( (This)->lpVtbl -> QueryLegacyV2RuntimeBinding(This,riid,ppUnk) ) #define ICLRMetaHost_ExitProcess(This,iExitCode) \ ( (This)->lpVtbl -> ExitProcess(This,iExitCode) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRMetaHost_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_metahost_0000_0001 */ /* [local] */ typedef struct _CLR_DEBUGGING_VERSION { WORD wStructVersion; WORD wMajor; WORD wMinor; WORD wBuild; WORD wRevision; } CLR_DEBUGGING_VERSION; typedef /* [public][public] */ enum __MIDL___MIDL_itf_metahost_0000_0001_0001 { CLR_DEBUGGING_MANAGED_EVENT_PENDING = 1, CLR_DEBUGGING_MANAGED_EVENT_DEBUGGER_LAUNCH = 2 } CLR_DEBUGGING_PROCESS_FLAGS; extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0001_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_metahost_0000_0001_v0_0_s_ifspec; #ifndef __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ #define __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ /* interface ICLRDebuggingLibraryProvider */ /* [object][local][helpstring][version][uuid] */ EXTERN_C const IID IID_ICLRDebuggingLibraryProvider; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3151C08D-4D09-4f9b-8838-2880BF18FE51") ICLRDebuggingLibraryProvider : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE ProvideLibrary( /* [in] */ const WCHAR *pwszFileName, /* [in] */ DWORD dwTimestamp, /* [in] */ DWORD dwSizeOfImage, /* [out] */ HMODULE *phModule) = 0; }; #else /* C style interface */ typedef struct ICLRDebuggingLibraryProviderVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDebuggingLibraryProvider * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDebuggingLibraryProvider * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRDebuggingLibraryProvider * This); HRESULT ( STDMETHODCALLTYPE *ProvideLibrary )( ICLRDebuggingLibraryProvider * This, /* [in] */ const WCHAR *pwszFileName, /* [in] */ DWORD dwTimestamp, /* [in] */ DWORD dwSizeOfImage, /* [out] */ HMODULE *phModule); END_INTERFACE } ICLRDebuggingLibraryProviderVtbl; interface ICLRDebuggingLibraryProvider { CONST_VTBL struct ICLRDebuggingLibraryProviderVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDebuggingLibraryProvider_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDebuggingLibraryProvider_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDebuggingLibraryProvider_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDebuggingLibraryProvider_ProvideLibrary(This,pwszFileName,dwTimestamp,dwSizeOfImage,phModule) \ ( (This)->lpVtbl -> ProvideLibrary(This,pwszFileName,dwTimestamp,dwSizeOfImage,phModule) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDebuggingLibraryProvider_INTERFACE_DEFINED__ */ #ifndef __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ #define __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ /* interface ICLRDebuggingLibraryProvider2 */ /* [object][local][helpstring][version][uuid] */ EXTERN_C const IID IID_ICLRDebuggingLibraryProvider2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E04E2FF1-DCFD-45D5-BCD1-16FFF2FAF7BA") ICLRDebuggingLibraryProvider2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE ProvideLibrary2( /* [in] */ const WCHAR *pwszFileName, /* [in] */ DWORD dwTimestamp, /* [in] */ DWORD dwSizeOfImage, /* [out] */ LPWSTR *ppResolvedModulePath) = 0; }; #else /* C style interface */ typedef struct ICLRDebuggingLibraryProvider2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDebuggingLibraryProvider2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDebuggingLibraryProvider2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRDebuggingLibraryProvider2 * This); HRESULT ( STDMETHODCALLTYPE *ProvideLibrary2 )( ICLRDebuggingLibraryProvider2 * This, /* [in] */ const WCHAR *pwszFileName, /* [in] */ DWORD dwTimestamp, /* [in] */ DWORD dwSizeOfImage, /* [out] */ LPWSTR *ppResolvedModulePath); END_INTERFACE } ICLRDebuggingLibraryProvider2Vtbl; interface ICLRDebuggingLibraryProvider2 { CONST_VTBL struct ICLRDebuggingLibraryProvider2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDebuggingLibraryProvider2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDebuggingLibraryProvider2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDebuggingLibraryProvider2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDebuggingLibraryProvider2_ProvideLibrary2(This,pwszFileName,dwTimestamp,dwSizeOfImage,ppResolvedModulePath) \ ( (This)->lpVtbl -> ProvideLibrary2(This,pwszFileName,dwTimestamp,dwSizeOfImage,ppResolvedModulePath) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDebuggingLibraryProvider2_INTERFACE_DEFINED__ */ #ifndef __ICLRDebugging_INTERFACE_DEFINED__ #define __ICLRDebugging_INTERFACE_DEFINED__ /* interface ICLRDebugging */ /* [object][local][helpstring][version][uuid] */ EXTERN_C const IID IID_ICLRDebugging; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("D28F3C5A-9634-4206-A509-477552EEFB10") ICLRDebugging : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE OpenVirtualProcess( /* [in] */ ULONG64 moduleBaseAddress, /* [in] */ IUnknown *pDataTarget, /* [in] */ ICLRDebuggingLibraryProvider *pLibraryProvider, /* [in] */ CLR_DEBUGGING_VERSION *pMaxDebuggerSupportedVersion, /* [in] */ REFIID riidProcess, /* [iid_is][out] */ IUnknown **ppProcess, /* [out][in] */ CLR_DEBUGGING_VERSION *pVersion, /* [out] */ CLR_DEBUGGING_PROCESS_FLAGS *pdwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE CanUnloadNow( HMODULE hModule) = 0; }; #else /* C style interface */ typedef struct ICLRDebuggingVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRDebugging * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRDebugging * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRDebugging * This); HRESULT ( STDMETHODCALLTYPE *OpenVirtualProcess )( ICLRDebugging * This, /* [in] */ ULONG64 moduleBaseAddress, /* [in] */ IUnknown *pDataTarget, /* [in] */ ICLRDebuggingLibraryProvider *pLibraryProvider, /* [in] */ CLR_DEBUGGING_VERSION *pMaxDebuggerSupportedVersion, /* [in] */ REFIID riidProcess, /* [iid_is][out] */ IUnknown **ppProcess, /* [out][in] */ CLR_DEBUGGING_VERSION *pVersion, /* [out] */ CLR_DEBUGGING_PROCESS_FLAGS *pdwFlags); HRESULT ( STDMETHODCALLTYPE *CanUnloadNow )( ICLRDebugging * This, HMODULE hModule); END_INTERFACE } ICLRDebuggingVtbl; interface ICLRDebugging { CONST_VTBL struct ICLRDebuggingVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRDebugging_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRDebugging_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRDebugging_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRDebugging_OpenVirtualProcess(This,moduleBaseAddress,pDataTarget,pLibraryProvider,pMaxDebuggerSupportedVersion,riidProcess,ppProcess,pVersion,pdwFlags) \ ( (This)->lpVtbl -> OpenVirtualProcess(This,moduleBaseAddress,pDataTarget,pLibraryProvider,pMaxDebuggerSupportedVersion,riidProcess,ppProcess,pVersion,pdwFlags) ) #define ICLRDebugging_CanUnloadNow(This,hModule) \ ( (This)->lpVtbl -> CanUnloadNow(This,hModule) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRDebugging_INTERFACE_DEFINED__ */ #ifndef __ICLRRuntimeInfo_INTERFACE_DEFINED__ #define __ICLRRuntimeInfo_INTERFACE_DEFINED__ /* interface ICLRRuntimeInfo */ /* [object][local][helpstring][version][uuid] */ EXTERN_C const IID IID_ICLRRuntimeInfo; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("BD39D1D2-BA2F-486a-89B0-B4B0CB466891") ICLRRuntimeInfo : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetVersionString( /* [annotation][size_is][out] */ _Out_writes_all_opt_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetRuntimeDirectory( /* [annotation][size_is][out] */ _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE IsLoaded( /* [in] */ HANDLE hndProcess, /* [retval][out] */ BOOL *pbLoaded) = 0; virtual HRESULT STDMETHODCALLTYPE LoadErrorString( /* [in] */ UINT iResourceID, /* [annotation][size_is][out] */ _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer, /* [lcid][in] */ LONG iLocaleID) = 0; virtual HRESULT STDMETHODCALLTYPE LoadLibrary( /* [in] */ LPCWSTR pwzDllName, /* [retval][out] */ HMODULE *phndModule) = 0; virtual HRESULT STDMETHODCALLTYPE GetProcAddress( /* [in] */ LPCSTR pszProcName, /* [retval][out] */ LPVOID *ppProc) = 0; virtual HRESULT STDMETHODCALLTYPE GetInterface( /* [in] */ REFCLSID rclsid, /* [in] */ REFIID riid, /* [retval][iid_is][out] */ LPVOID *ppUnk) = 0; virtual HRESULT STDMETHODCALLTYPE IsLoadable( /* [retval][out] */ BOOL *pbLoadable) = 0; virtual HRESULT STDMETHODCALLTYPE SetDefaultStartupFlags( /* [in] */ DWORD dwStartupFlags, /* [in] */ LPCWSTR pwzHostConfigFile) = 0; virtual HRESULT STDMETHODCALLTYPE GetDefaultStartupFlags( /* [out] */ DWORD *pdwStartupFlags, /* [annotation][size_is][out] */ _Out_writes_all_opt_(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, /* [out][in] */ DWORD *pcchHostConfigFile) = 0; virtual HRESULT STDMETHODCALLTYPE BindAsLegacyV2Runtime( void) = 0; virtual HRESULT STDMETHODCALLTYPE IsStarted( /* [out] */ BOOL *pbStarted, /* [out] */ DWORD *pdwStartupFlags) = 0; }; #else /* C style interface */ typedef struct ICLRRuntimeInfoVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRRuntimeInfo * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRRuntimeInfo * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRRuntimeInfo * This); HRESULT ( STDMETHODCALLTYPE *GetVersionString )( ICLRRuntimeInfo * This, /* [annotation][size_is][out] */ _Out_writes_all_opt_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer); HRESULT ( STDMETHODCALLTYPE *GetRuntimeDirectory )( ICLRRuntimeInfo * This, /* [annotation][size_is][out] */ _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer); HRESULT ( STDMETHODCALLTYPE *IsLoaded )( ICLRRuntimeInfo * This, /* [in] */ HANDLE hndProcess, /* [retval][out] */ BOOL *pbLoaded); HRESULT ( STDMETHODCALLTYPE *LoadErrorString )( ICLRRuntimeInfo * This, /* [in] */ UINT iResourceID, /* [annotation][size_is][out] */ _Out_writes_all_(*pcchBuffer) LPWSTR pwzBuffer, /* [out][in] */ DWORD *pcchBuffer, /* [lcid][in] */ LONG iLocaleID); HRESULT ( STDMETHODCALLTYPE *LoadLibrary )( ICLRRuntimeInfo * This, /* [in] */ LPCWSTR pwzDllName, /* [retval][out] */ HMODULE *phndModule); HRESULT ( STDMETHODCALLTYPE *GetProcAddress )( ICLRRuntimeInfo * This, /* [in] */ LPCSTR pszProcName, /* [retval][out] */ LPVOID *ppProc); HRESULT ( STDMETHODCALLTYPE *GetInterface )( ICLRRuntimeInfo * This, /* [in] */ REFCLSID rclsid, /* [in] */ REFIID riid, /* [retval][iid_is][out] */ LPVOID *ppUnk); HRESULT ( STDMETHODCALLTYPE *IsLoadable )( ICLRRuntimeInfo * This, /* [retval][out] */ BOOL *pbLoadable); HRESULT ( STDMETHODCALLTYPE *SetDefaultStartupFlags )( ICLRRuntimeInfo * This, /* [in] */ DWORD dwStartupFlags, /* [in] */ LPCWSTR pwzHostConfigFile); HRESULT ( STDMETHODCALLTYPE *GetDefaultStartupFlags )( ICLRRuntimeInfo * This, /* [out] */ DWORD *pdwStartupFlags, /* [annotation][size_is][out] */ _Out_writes_all_opt_(*pcchHostConfigFile) LPWSTR pwzHostConfigFile, /* [out][in] */ DWORD *pcchHostConfigFile); HRESULT ( STDMETHODCALLTYPE *BindAsLegacyV2Runtime )( ICLRRuntimeInfo * This); HRESULT ( STDMETHODCALLTYPE *IsStarted )( ICLRRuntimeInfo * This, /* [out] */ BOOL *pbStarted, /* [out] */ DWORD *pdwStartupFlags); END_INTERFACE } ICLRRuntimeInfoVtbl; interface ICLRRuntimeInfo { CONST_VTBL struct ICLRRuntimeInfoVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRRuntimeInfo_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRRuntimeInfo_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRRuntimeInfo_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRRuntimeInfo_GetVersionString(This,pwzBuffer,pcchBuffer) \ ( (This)->lpVtbl -> GetVersionString(This,pwzBuffer,pcchBuffer) ) #define ICLRRuntimeInfo_GetRuntimeDirectory(This,pwzBuffer,pcchBuffer) \ ( (This)->lpVtbl -> GetRuntimeDirectory(This,pwzBuffer,pcchBuffer) ) #define ICLRRuntimeInfo_IsLoaded(This,hndProcess,pbLoaded) \ ( (This)->lpVtbl -> IsLoaded(This,hndProcess,pbLoaded) ) #define ICLRRuntimeInfo_LoadErrorString(This,iResourceID,pwzBuffer,pcchBuffer,iLocaleID) \ ( (This)->lpVtbl -> LoadErrorString(This,iResourceID,pwzBuffer,pcchBuffer,iLocaleID) ) #define ICLRRuntimeInfo_LoadLibrary(This,pwzDllName,phndModule) \ ( (This)->lpVtbl -> LoadLibrary(This,pwzDllName,phndModule) ) #define ICLRRuntimeInfo_GetProcAddress(This,pszProcName,ppProc) \ ( (This)->lpVtbl -> GetProcAddress(This,pszProcName,ppProc) ) #define ICLRRuntimeInfo_GetInterface(This,rclsid,riid,ppUnk) \ ( (This)->lpVtbl -> GetInterface(This,rclsid,riid,ppUnk) ) #define ICLRRuntimeInfo_IsLoadable(This,pbLoadable) \ ( (This)->lpVtbl -> IsLoadable(This,pbLoadable) ) #define ICLRRuntimeInfo_SetDefaultStartupFlags(This,dwStartupFlags,pwzHostConfigFile) \ ( (This)->lpVtbl -> SetDefaultStartupFlags(This,dwStartupFlags,pwzHostConfigFile) ) #define ICLRRuntimeInfo_GetDefaultStartupFlags(This,pdwStartupFlags,pwzHostConfigFile,pcchHostConfigFile) \ ( (This)->lpVtbl -> GetDefaultStartupFlags(This,pdwStartupFlags,pwzHostConfigFile,pcchHostConfigFile) ) #define ICLRRuntimeInfo_BindAsLegacyV2Runtime(This) \ ( (This)->lpVtbl -> BindAsLegacyV2Runtime(This) ) #define ICLRRuntimeInfo_IsStarted(This,pbStarted,pdwStartupFlags) \ ( (This)->lpVtbl -> IsStarted(This,pbStarted,pdwStartupFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRRuntimeInfo_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/mscoree.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.00.0603 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __mscoree_h__ #define __mscoree_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __ICLRRuntimeHost_FWD_DEFINED__ #define __ICLRRuntimeHost_FWD_DEFINED__ typedef interface ICLRRuntimeHost ICLRRuntimeHost; #endif /* __ICLRRuntimeHost_FWD_DEFINED__ */ #ifndef __ICLRRuntimeHost2_FWD_DEFINED__ #define __ICLRRuntimeHost2_FWD_DEFINED__ typedef interface ICLRRuntimeHost2 ICLRRuntimeHost2; #endif /* __ICLRRuntimeHost2_FWD_DEFINED__ */ #ifndef __ICLRRuntimeHost4_FWD_DEFINED__ #define __ICLRRuntimeHost4_FWD_DEFINED__ typedef interface ICLRRuntimeHost4 ICLRRuntimeHost4; #endif /* __ICLRRuntimeHost4_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_mscoree_0000_0000 */ /* [local] */ struct IActivationFactory; struct IHostControl; struct ICLRControl; EXTERN_GUID(IID_ICLRRuntimeHost, 0x90F1A06C, 0x7712, 0x4762, 0x86, 0xB5, 0x7A, 0x5E, 0xBA, 0x6B, 0xDB, 0x02); EXTERN_GUID(IID_ICLRRuntimeHost2, 0x712AB73F, 0x2C22, 0x4807, 0xAD, 0x7E, 0xF5, 0x01, 0xD7, 0xb7, 0x2C, 0x2D); EXTERN_GUID(IID_ICLRRuntimeHost4, 0x64F6D366, 0xD7C2, 0x4F1F, 0xB4, 0xB2, 0xE8, 0x16, 0x0C, 0xAC, 0x43, 0xAF); typedef HRESULT (STDAPICALLTYPE *FnGetCLRRuntimeHost)(REFIID riid, IUnknown **pUnk); typedef HRESULT ( __stdcall *FExecuteInAppDomainCallback )( void *cookie); typedef /* [public][public] */ enum __MIDL___MIDL_itf_mscoree_0000_0000_0001 { STARTUP_CONCURRENT_GC = 0x1, STARTUP_LOADER_OPTIMIZATION_MASK = ( 0x3 << 1 ) , STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN = ( 0x1 << 1 ) , STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN = ( 0x2 << 1 ) , STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST = ( 0x3 << 1 ) , STARTUP_LOADER_SAFEMODE = 0x10, STARTUP_LOADER_SETPREFERENCE = 0x100, STARTUP_SERVER_GC = 0x1000, STARTUP_HOARD_GC_VM = 0x2000, STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = 0x4000, STARTUP_LEGACY_IMPERSONATION = 0x10000, STARTUP_DISABLE_COMMITTHREADSTACK = 0x20000, STARTUP_ALWAYSFLOW_IMPERSONATION = 0x40000, STARTUP_TRIM_GC_COMMIT = 0x80000, STARTUP_ETW = 0x100000, STARTUP_ARM = 0x400000, STARTUP_SINGLE_APPDOMAIN = 0x800000, STARTUP_APPX_APP_MODEL = 0x1000000, STARTUP_DISABLE_RANDOMIZED_STRING_HASHING = 0x2000000 } STARTUP_FLAGS; typedef /* [public] */ enum __MIDL___MIDL_itf_mscoree_0000_0000_0002 { APPDOMAIN_SECURITY_DEFAULT = 0, APPDOMAIN_SECURITY_SANDBOXED = 0x1, APPDOMAIN_SECURITY_FORBID_CROSSAD_REVERSE_PINVOKE = 0x2, APPDOMAIN_IGNORE_UNHANDLED_EXCEPTIONS = 0x4, APPDOMAIN_FORCE_TRIVIAL_WAIT_OPERATIONS = 0x8, APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP = 0x10, APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS = 0x40, APPDOMAIN_ENABLE_ASSEMBLY_LOADFILE = 0x80, APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT = 0x100 } APPDOMAIN_SECURITY_FLAGS; typedef /* [public] */ enum __MIDL___MIDL_itf_mscoree_0000_0000_0003 { WAIT_MSGPUMP = 0x1, WAIT_ALERTABLE = 0x2, WAIT_NOTINDEADLOCK = 0x4 } WAIT_OPTION; typedef /* [public] */ enum __MIDL___MIDL_itf_mscoree_0000_0000_0004 { DUMP_FLAVOR_Mini = 0, DUMP_FLAVOR_CriticalCLRState = 1, DUMP_FLAVOR_NonHeapCLRState = 2, DUMP_FLAVOR_Default = DUMP_FLAVOR_Mini } ECustomDumpFlavor; #define BucketParamsCount ( 10 ) #define BucketParamLength ( 255 ) typedef /* [public] */ enum __MIDL___MIDL_itf_mscoree_0000_0000_0005 { Parameter1 = 0, Parameter2 = ( Parameter1 + 1 ) , Parameter3 = ( Parameter2 + 1 ) , Parameter4 = ( Parameter3 + 1 ) , Parameter5 = ( Parameter4 + 1 ) , Parameter6 = ( Parameter5 + 1 ) , Parameter7 = ( Parameter6 + 1 ) , Parameter8 = ( Parameter7 + 1 ) , Parameter9 = ( Parameter8 + 1 ) , InvalidBucketParamIndex = ( Parameter9 + 1 ) } BucketParameterIndex; typedef struct _BucketParameters { BOOL fInited; WCHAR pszEventTypeName[ 255 ]; WCHAR pszParams[ 10 ][ 255 ]; } BucketParameters; extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0000_v0_0_s_ifspec; #ifndef __ICLRRuntimeHost_INTERFACE_DEFINED__ #define __ICLRRuntimeHost_INTERFACE_DEFINED__ /* interface ICLRRuntimeHost */ /* [object][local][unique][helpstring][version][uuid] */ EXTERN_C const IID IID_ICLRRuntimeHost; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("90F1A06C-7712-4762-86B5-7A5EBA6BDB02") ICLRRuntimeHost : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Start( void) = 0; virtual HRESULT STDMETHODCALLTYPE Stop( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetHostControl( /* [in] */ IHostControl *pHostControl) = 0; virtual HRESULT STDMETHODCALLTYPE GetCLRControl( /* [out] */ ICLRControl **pCLRControl) = 0; virtual HRESULT STDMETHODCALLTYPE UnloadAppDomain( /* [in] */ DWORD dwAppDomainId, /* [in] */ BOOL fWaitUntilDone) = 0; virtual HRESULT STDMETHODCALLTYPE ExecuteInAppDomain( /* [in] */ DWORD dwAppDomainId, /* [in] */ FExecuteInAppDomainCallback pCallback, /* [in] */ void *cookie) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomainId( /* [out] */ DWORD *pdwAppDomainId) = 0; virtual HRESULT STDMETHODCALLTYPE ExecuteApplication( /* [in] */ LPCWSTR pwzAppFullName, /* [in] */ DWORD dwManifestPaths, /* [in] */ LPCWSTR *ppwzManifestPaths, /* [in] */ DWORD dwActivationData, /* [in] */ LPCWSTR *ppwzActivationData, /* [out] */ int *pReturnValue) = 0; virtual HRESULT STDMETHODCALLTYPE ExecuteInDefaultAppDomain( /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ LPCWSTR pwzTypeName, /* [in] */ LPCWSTR pwzMethodName, /* [in] */ LPCWSTR pwzArgument, /* [out] */ DWORD *pReturnValue) = 0; }; #else /* C style interface */ typedef struct ICLRRuntimeHostVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRRuntimeHost * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRRuntimeHost * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRRuntimeHost * This); HRESULT ( STDMETHODCALLTYPE *Start )( ICLRRuntimeHost * This); HRESULT ( STDMETHODCALLTYPE *Stop )( ICLRRuntimeHost * This); HRESULT ( STDMETHODCALLTYPE *SetHostControl )( ICLRRuntimeHost * This, /* [in] */ IHostControl *pHostControl); HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( ICLRRuntimeHost * This, /* [out] */ ICLRControl **pCLRControl); HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( ICLRRuntimeHost * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ BOOL fWaitUntilDone); HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( ICLRRuntimeHost * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ FExecuteInAppDomainCallback pCallback, /* [in] */ void *cookie); HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( ICLRRuntimeHost * This, /* [out] */ DWORD *pdwAppDomainId); HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( ICLRRuntimeHost * This, /* [in] */ LPCWSTR pwzAppFullName, /* [in] */ DWORD dwManifestPaths, /* [in] */ LPCWSTR *ppwzManifestPaths, /* [in] */ DWORD dwActivationData, /* [in] */ LPCWSTR *ppwzActivationData, /* [out] */ int *pReturnValue); HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( ICLRRuntimeHost * This, /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ LPCWSTR pwzTypeName, /* [in] */ LPCWSTR pwzMethodName, /* [in] */ LPCWSTR pwzArgument, /* [out] */ DWORD *pReturnValue); END_INTERFACE } ICLRRuntimeHostVtbl; interface ICLRRuntimeHost { CONST_VTBL struct ICLRRuntimeHostVtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRRuntimeHost_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRRuntimeHost_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRRuntimeHost_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRRuntimeHost_Start(This) \ ( (This)->lpVtbl -> Start(This) ) #define ICLRRuntimeHost_Stop(This) \ ( (This)->lpVtbl -> Stop(This) ) #define ICLRRuntimeHost_SetHostControl(This,pHostControl) \ ( (This)->lpVtbl -> SetHostControl(This,pHostControl) ) #define ICLRRuntimeHost_GetCLRControl(This,pCLRControl) \ ( (This)->lpVtbl -> GetCLRControl(This,pCLRControl) ) #define ICLRRuntimeHost_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ ( (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) ) #define ICLRRuntimeHost_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ ( (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) ) #define ICLRRuntimeHost_GetCurrentAppDomainId(This,pdwAppDomainId) \ ( (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) ) #define ICLRRuntimeHost_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ ( (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) ) #define ICLRRuntimeHost_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ ( (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRRuntimeHost_INTERFACE_DEFINED__ */ #ifndef __ICLRRuntimeHost2_INTERFACE_DEFINED__ #define __ICLRRuntimeHost2_INTERFACE_DEFINED__ /* interface ICLRRuntimeHost2 */ /* [local][unique][helpstring][version][uuid][object] */ EXTERN_C const IID IID_ICLRRuntimeHost2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("712AB73F-2C22-4807-AD7E-F501D7B72C2D") ICLRRuntimeHost2 : public ICLRRuntimeHost { public: virtual HRESULT STDMETHODCALLTYPE CreateAppDomainWithManager( /* [in] */ LPCWSTR wszFriendlyName, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR wszAppDomainManagerAssemblyName, /* [in] */ LPCWSTR wszAppDomainManagerTypeName, /* [in] */ int nProperties, /* [in] */ LPCWSTR *pPropertyNames, /* [in] */ LPCWSTR *pPropertyValues, /* [out] */ DWORD *pAppDomainID) = 0; virtual HRESULT STDMETHODCALLTYPE CreateDelegate( /* [in] */ DWORD appDomainID, /* [in] */ LPCWSTR wszAssemblyName, /* [in] */ LPCWSTR wszClassName, /* [in] */ LPCWSTR wszMethodName, /* [out] */ INT_PTR *fnPtr) = 0; virtual HRESULT STDMETHODCALLTYPE Authenticate( /* [in] */ ULONGLONG authKey) = 0; virtual HRESULT STDMETHODCALLTYPE RegisterMacEHPort( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetStartupFlags( /* [in] */ STARTUP_FLAGS dwFlags) = 0; virtual HRESULT STDMETHODCALLTYPE DllGetActivationFactory( /* [in] */ DWORD appDomainID, /* [in] */ LPCWSTR wszTypeName, /* [out] */ IActivationFactory **factory) = 0; virtual HRESULT STDMETHODCALLTYPE ExecuteAssembly( /* [in] */ DWORD dwAppDomainId, /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ int argc, /* [in] */ LPCWSTR *argv, /* [out] */ DWORD *pReturnValue) = 0; }; #else /* C style interface */ typedef struct ICLRRuntimeHost2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRRuntimeHost2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRRuntimeHost2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRRuntimeHost2 * This); HRESULT ( STDMETHODCALLTYPE *Start )( ICLRRuntimeHost2 * This); HRESULT ( STDMETHODCALLTYPE *Stop )( ICLRRuntimeHost2 * This); HRESULT ( STDMETHODCALLTYPE *SetHostControl )( ICLRRuntimeHost2 * This, /* [in] */ IHostControl *pHostControl); HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( ICLRRuntimeHost2 * This, /* [out] */ ICLRControl **pCLRControl); HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( ICLRRuntimeHost2 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ BOOL fWaitUntilDone); HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( ICLRRuntimeHost2 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ FExecuteInAppDomainCallback pCallback, /* [in] */ void *cookie); HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( ICLRRuntimeHost2 * This, /* [out] */ DWORD *pdwAppDomainId); HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( ICLRRuntimeHost2 * This, /* [in] */ LPCWSTR pwzAppFullName, /* [in] */ DWORD dwManifestPaths, /* [in] */ LPCWSTR *ppwzManifestPaths, /* [in] */ DWORD dwActivationData, /* [in] */ LPCWSTR *ppwzActivationData, /* [out] */ int *pReturnValue); HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( ICLRRuntimeHost2 * This, /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ LPCWSTR pwzTypeName, /* [in] */ LPCWSTR pwzMethodName, /* [in] */ LPCWSTR pwzArgument, /* [out] */ DWORD *pReturnValue); HRESULT ( STDMETHODCALLTYPE *CreateAppDomainWithManager )( ICLRRuntimeHost2 * This, /* [in] */ LPCWSTR wszFriendlyName, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR wszAppDomainManagerAssemblyName, /* [in] */ LPCWSTR wszAppDomainManagerTypeName, /* [in] */ int nProperties, /* [in] */ LPCWSTR *pPropertyNames, /* [in] */ LPCWSTR *pPropertyValues, /* [out] */ DWORD *pAppDomainID); HRESULT ( STDMETHODCALLTYPE *CreateDelegate )( ICLRRuntimeHost2 * This, /* [in] */ DWORD appDomainID, /* [in] */ LPCWSTR wszAssemblyName, /* [in] */ LPCWSTR wszClassName, /* [in] */ LPCWSTR wszMethodName, /* [out] */ INT_PTR *fnPtr); HRESULT ( STDMETHODCALLTYPE *Authenticate )( ICLRRuntimeHost2 * This, /* [in] */ ULONGLONG authKey); HRESULT ( STDMETHODCALLTYPE *RegisterMacEHPort )( ICLRRuntimeHost2 * This); HRESULT ( STDMETHODCALLTYPE *SetStartupFlags )( ICLRRuntimeHost2 * This, /* [in] */ STARTUP_FLAGS dwFlags); HRESULT ( STDMETHODCALLTYPE *DllGetActivationFactory )( ICLRRuntimeHost2 * This, /* [in] */ DWORD appDomainID, /* [in] */ LPCWSTR wszTypeName, /* [out] */ IActivationFactory **factory); HRESULT ( STDMETHODCALLTYPE *ExecuteAssembly )( ICLRRuntimeHost2 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ int argc, /* [in] */ LPCWSTR *argv, /* [out] */ DWORD *pReturnValue); END_INTERFACE } ICLRRuntimeHost2Vtbl; interface ICLRRuntimeHost2 { CONST_VTBL struct ICLRRuntimeHost2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRRuntimeHost2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRRuntimeHost2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRRuntimeHost2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRRuntimeHost2_Start(This) \ ( (This)->lpVtbl -> Start(This) ) #define ICLRRuntimeHost2_Stop(This) \ ( (This)->lpVtbl -> Stop(This) ) #define ICLRRuntimeHost2_SetHostControl(This,pHostControl) \ ( (This)->lpVtbl -> SetHostControl(This,pHostControl) ) #define ICLRRuntimeHost2_GetCLRControl(This,pCLRControl) \ ( (This)->lpVtbl -> GetCLRControl(This,pCLRControl) ) #define ICLRRuntimeHost2_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ ( (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) ) #define ICLRRuntimeHost2_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ ( (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) ) #define ICLRRuntimeHost2_GetCurrentAppDomainId(This,pdwAppDomainId) \ ( (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) ) #define ICLRRuntimeHost2_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ ( (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) ) #define ICLRRuntimeHost2_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ ( (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) ) #define ICLRRuntimeHost2_CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) \ ( (This)->lpVtbl -> CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) ) #define ICLRRuntimeHost2_CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) \ ( (This)->lpVtbl -> CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) ) #define ICLRRuntimeHost2_Authenticate(This,authKey) \ ( (This)->lpVtbl -> Authenticate(This,authKey) ) #define ICLRRuntimeHost2_RegisterMacEHPort(This) \ ( (This)->lpVtbl -> RegisterMacEHPort(This) ) #define ICLRRuntimeHost2_SetStartupFlags(This,dwFlags) \ ( (This)->lpVtbl -> SetStartupFlags(This,dwFlags) ) #define ICLRRuntimeHost2_DllGetActivationFactory(This,appDomainID,wszTypeName,factory) \ ( (This)->lpVtbl -> DllGetActivationFactory(This,appDomainID,wszTypeName,factory) ) #define ICLRRuntimeHost2_ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) \ ( (This)->lpVtbl -> ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRRuntimeHost2_INTERFACE_DEFINED__ */ #ifndef __ICLRRuntimeHost4_INTERFACE_DEFINED__ #define __ICLRRuntimeHost4_INTERFACE_DEFINED__ /* interface ICLRRuntimeHost4 */ /* [local][unique][helpstring][version][uuid][object] */ EXTERN_C const IID IID_ICLRRuntimeHost4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("64F6D366-D7C2-4F1F-B4B2-E8160CAC43AF") ICLRRuntimeHost4 : public ICLRRuntimeHost2 { public: virtual HRESULT STDMETHODCALLTYPE UnloadAppDomain2( /* [in] */ DWORD dwAppDomainId, /* [in] */ BOOL fWaitUntilDone, /* [out] */ int *pLatchedExitCode) = 0; }; #else /* C style interface */ typedef struct ICLRRuntimeHost4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICLRRuntimeHost4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICLRRuntimeHost4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICLRRuntimeHost4 * This); HRESULT ( STDMETHODCALLTYPE *Start )( ICLRRuntimeHost4 * This); HRESULT ( STDMETHODCALLTYPE *Stop )( ICLRRuntimeHost4 * This); HRESULT ( STDMETHODCALLTYPE *SetHostControl )( ICLRRuntimeHost4 * This, /* [in] */ IHostControl *pHostControl); HRESULT ( STDMETHODCALLTYPE *GetCLRControl )( ICLRRuntimeHost4 * This, /* [out] */ ICLRControl **pCLRControl); HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain )( ICLRRuntimeHost4 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ BOOL fWaitUntilDone); HRESULT ( STDMETHODCALLTYPE *ExecuteInAppDomain )( ICLRRuntimeHost4 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ FExecuteInAppDomainCallback pCallback, /* [in] */ void *cookie); HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomainId )( ICLRRuntimeHost4 * This, /* [out] */ DWORD *pdwAppDomainId); HRESULT ( STDMETHODCALLTYPE *ExecuteApplication )( ICLRRuntimeHost4 * This, /* [in] */ LPCWSTR pwzAppFullName, /* [in] */ DWORD dwManifestPaths, /* [in] */ LPCWSTR *ppwzManifestPaths, /* [in] */ DWORD dwActivationData, /* [in] */ LPCWSTR *ppwzActivationData, /* [out] */ int *pReturnValue); HRESULT ( STDMETHODCALLTYPE *ExecuteInDefaultAppDomain )( ICLRRuntimeHost4 * This, /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ LPCWSTR pwzTypeName, /* [in] */ LPCWSTR pwzMethodName, /* [in] */ LPCWSTR pwzArgument, /* [out] */ DWORD *pReturnValue); HRESULT ( STDMETHODCALLTYPE *CreateAppDomainWithManager )( ICLRRuntimeHost4 * This, /* [in] */ LPCWSTR wszFriendlyName, /* [in] */ DWORD dwFlags, /* [in] */ LPCWSTR wszAppDomainManagerAssemblyName, /* [in] */ LPCWSTR wszAppDomainManagerTypeName, /* [in] */ int nProperties, /* [in] */ LPCWSTR *pPropertyNames, /* [in] */ LPCWSTR *pPropertyValues, /* [out] */ DWORD *pAppDomainID); HRESULT ( STDMETHODCALLTYPE *CreateDelegate )( ICLRRuntimeHost4 * This, /* [in] */ DWORD appDomainID, /* [in] */ LPCWSTR wszAssemblyName, /* [in] */ LPCWSTR wszClassName, /* [in] */ LPCWSTR wszMethodName, /* [out] */ INT_PTR *fnPtr); HRESULT ( STDMETHODCALLTYPE *Authenticate )( ICLRRuntimeHost4 * This, /* [in] */ ULONGLONG authKey); HRESULT ( STDMETHODCALLTYPE *RegisterMacEHPort )( ICLRRuntimeHost4 * This); HRESULT ( STDMETHODCALLTYPE *SetStartupFlags )( ICLRRuntimeHost4 * This, /* [in] */ STARTUP_FLAGS dwFlags); HRESULT ( STDMETHODCALLTYPE *DllGetActivationFactory )( ICLRRuntimeHost4 * This, /* [in] */ DWORD appDomainID, /* [in] */ LPCWSTR wszTypeName, /* [out] */ IActivationFactory **factory); HRESULT ( STDMETHODCALLTYPE *ExecuteAssembly )( ICLRRuntimeHost4 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ LPCWSTR pwzAssemblyPath, /* [in] */ int argc, /* [in] */ LPCWSTR *argv, /* [out] */ DWORD *pReturnValue); HRESULT ( STDMETHODCALLTYPE *UnloadAppDomain2 )( ICLRRuntimeHost4 * This, /* [in] */ DWORD dwAppDomainId, /* [in] */ BOOL fWaitUntilDone, /* [out] */ int *pLatchedExitCode); END_INTERFACE } ICLRRuntimeHost4Vtbl; interface ICLRRuntimeHost4 { CONST_VTBL struct ICLRRuntimeHost4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICLRRuntimeHost4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICLRRuntimeHost4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICLRRuntimeHost4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICLRRuntimeHost4_Start(This) \ ( (This)->lpVtbl -> Start(This) ) #define ICLRRuntimeHost4_Stop(This) \ ( (This)->lpVtbl -> Stop(This) ) #define ICLRRuntimeHost4_SetHostControl(This,pHostControl) \ ( (This)->lpVtbl -> SetHostControl(This,pHostControl) ) #define ICLRRuntimeHost4_GetCLRControl(This,pCLRControl) \ ( (This)->lpVtbl -> GetCLRControl(This,pCLRControl) ) #define ICLRRuntimeHost4_UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) \ ( (This)->lpVtbl -> UnloadAppDomain(This,dwAppDomainId,fWaitUntilDone) ) #define ICLRRuntimeHost4_ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) \ ( (This)->lpVtbl -> ExecuteInAppDomain(This,dwAppDomainId,pCallback,cookie) ) #define ICLRRuntimeHost4_GetCurrentAppDomainId(This,pdwAppDomainId) \ ( (This)->lpVtbl -> GetCurrentAppDomainId(This,pdwAppDomainId) ) #define ICLRRuntimeHost4_ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) \ ( (This)->lpVtbl -> ExecuteApplication(This,pwzAppFullName,dwManifestPaths,ppwzManifestPaths,dwActivationData,ppwzActivationData,pReturnValue) ) #define ICLRRuntimeHost4_ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) \ ( (This)->lpVtbl -> ExecuteInDefaultAppDomain(This,pwzAssemblyPath,pwzTypeName,pwzMethodName,pwzArgument,pReturnValue) ) #define ICLRRuntimeHost4_CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) \ ( (This)->lpVtbl -> CreateAppDomainWithManager(This,wszFriendlyName,dwFlags,wszAppDomainManagerAssemblyName,wszAppDomainManagerTypeName,nProperties,pPropertyNames,pPropertyValues,pAppDomainID) ) #define ICLRRuntimeHost4_CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) \ ( (This)->lpVtbl -> CreateDelegate(This,appDomainID,wszAssemblyName,wszClassName,wszMethodName,fnPtr) ) #define ICLRRuntimeHost4_Authenticate(This,authKey) \ ( (This)->lpVtbl -> Authenticate(This,authKey) ) #define ICLRRuntimeHost4_RegisterMacEHPort(This) \ ( (This)->lpVtbl -> RegisterMacEHPort(This) ) #define ICLRRuntimeHost4_SetStartupFlags(This,dwFlags) \ ( (This)->lpVtbl -> SetStartupFlags(This,dwFlags) ) #define ICLRRuntimeHost4_DllGetActivationFactory(This,appDomainID,wszTypeName,factory) \ ( (This)->lpVtbl -> DllGetActivationFactory(This,appDomainID,wszTypeName,factory) ) #define ICLRRuntimeHost4_ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) \ ( (This)->lpVtbl -> ExecuteAssembly(This,dwAppDomainId,pwzAssemblyPath,argc,argv,pReturnValue) ) #define ICLRRuntimeHost4_UnloadAppDomain2(This,dwAppDomainId,fWaitUntilDone,pLatchedExitCode) \ ( (This)->lpVtbl -> UnloadAppDomain2(This,dwAppDomainId,fWaitUntilDone,pLatchedExitCode) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICLRRuntimeHost4_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_mscoree_0000_0003 */ /* [local] */ extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0003_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_mscoree_0000_0003_v0_0_s_ifspec; /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/sospriv.h ================================================ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0622 */ /* at Mon Jan 18 19:14:07 2038 */ /* Compiler settings for C:/git/runtime/src/coreclr/inc/sospriv.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __sospriv_h__ #define __sospriv_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __ISOSEnum_FWD_DEFINED__ #define __ISOSEnum_FWD_DEFINED__ typedef interface ISOSEnum ISOSEnum; #endif /* __ISOSEnum_FWD_DEFINED__ */ #ifndef __ISOSHandleEnum_FWD_DEFINED__ #define __ISOSHandleEnum_FWD_DEFINED__ typedef interface ISOSHandleEnum ISOSHandleEnum; #endif /* __ISOSHandleEnum_FWD_DEFINED__ */ #ifndef __ISOSStackRefErrorEnum_FWD_DEFINED__ #define __ISOSStackRefErrorEnum_FWD_DEFINED__ typedef interface ISOSStackRefErrorEnum ISOSStackRefErrorEnum; #endif /* __ISOSStackRefErrorEnum_FWD_DEFINED__ */ #ifndef __ISOSStackRefEnum_FWD_DEFINED__ #define __ISOSStackRefEnum_FWD_DEFINED__ typedef interface ISOSStackRefEnum ISOSStackRefEnum; #endif /* __ISOSStackRefEnum_FWD_DEFINED__ */ #ifndef __ISOSDacInterface_FWD_DEFINED__ #define __ISOSDacInterface_FWD_DEFINED__ typedef interface ISOSDacInterface ISOSDacInterface; #endif /* __ISOSDacInterface_FWD_DEFINED__ */ #ifndef __ISOSDacInterface2_FWD_DEFINED__ #define __ISOSDacInterface2_FWD_DEFINED__ typedef interface ISOSDacInterface2 ISOSDacInterface2; #endif /* __ISOSDacInterface2_FWD_DEFINED__ */ #ifndef __ISOSDacInterface3_FWD_DEFINED__ #define __ISOSDacInterface3_FWD_DEFINED__ typedef interface ISOSDacInterface3 ISOSDacInterface3; #endif /* __ISOSDacInterface3_FWD_DEFINED__ */ #ifndef __ISOSDacInterface4_FWD_DEFINED__ #define __ISOSDacInterface4_FWD_DEFINED__ typedef interface ISOSDacInterface4 ISOSDacInterface4; #endif /* __ISOSDacInterface4_FWD_DEFINED__ */ #ifndef __ISOSDacInterface5_FWD_DEFINED__ #define __ISOSDacInterface5_FWD_DEFINED__ typedef interface ISOSDacInterface5 ISOSDacInterface5; #endif /* __ISOSDacInterface5_FWD_DEFINED__ */ #ifndef __ISOSDacInterface6_FWD_DEFINED__ #define __ISOSDacInterface6_FWD_DEFINED__ typedef interface ISOSDacInterface6 ISOSDacInterface6; #endif /* __ISOSDacInterface6_FWD_DEFINED__ */ #ifndef __ISOSDacInterface7_FWD_DEFINED__ #define __ISOSDacInterface7_FWD_DEFINED__ typedef interface ISOSDacInterface7 ISOSDacInterface7; #endif /* __ISOSDacInterface7_FWD_DEFINED__ */ #ifndef __ISOSDacInterface8_FWD_DEFINED__ #define __ISOSDacInterface8_FWD_DEFINED__ typedef interface ISOSDacInterface8 ISOSDacInterface8; #endif /* __ISOSDacInterface8_FWD_DEFINED__ */ #ifndef __ISOSDacInterface9_FWD_DEFINED__ #define __ISOSDacInterface9_FWD_DEFINED__ typedef interface ISOSDacInterface9 ISOSDacInterface9; #endif /* __ISOSDacInterface9_FWD_DEFINED__ */ #ifndef __ISOSDacInterface10_FWD_DEFINED__ #define __ISOSDacInterface10_FWD_DEFINED__ typedef interface ISOSDacInterface10 ISOSDacInterface10; #endif /* __ISOSDacInterface10_FWD_DEFINED__ */ /* header files for imported files */ #include "unknwn.h" #include "xclrdata.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_sospriv_0000_0000 */ /* [local] */ #if 0 typedef ULONG64 CLRDATA_ADDRESS; typedef int CONTEXT; typedef int T_CONTEXT; typedef int mdToken; typedef unsigned int size_t; typedef int ModuleMapType; typedef int VCSHeapType; #endif typedef enum { TYPEDEFTOMETHODTABLE, TYPEREFTOMETHODTABLE } ModuleMapType; typedef enum {IndcellHeap, LookupHeap, ResolveHeap, DispatchHeap, CacheEntryHeap} VCSHeapType; typedef void ( *MODULEMAPTRAVERSE )( UINT index, CLRDATA_ADDRESS methodTable, LPVOID token); typedef void ( *VISITHEAP )( CLRDATA_ADDRESS blockData, size_t blockSize, BOOL blockIsCurrentBlock); typedef BOOL ( *VISITRCWFORCLEANUP )( CLRDATA_ADDRESS RCW, CLRDATA_ADDRESS Context, CLRDATA_ADDRESS Thread, BOOL bIsFreeThreaded, LPVOID token); typedef BOOL ( *DUMPEHINFO )( UINT clauseIndex, UINT totalClauses, struct DACEHInfo *pEHInfo, LPVOID token); #ifndef _SOS_HandleData #define _SOS_HandleData typedef struct _SOSHandleData { CLRDATA_ADDRESS AppDomain; CLRDATA_ADDRESS Handle; CLRDATA_ADDRESS Secondary; unsigned int Type; BOOL StrongReference; unsigned int RefCount; unsigned int JupiterRefCount; BOOL IsPegged; } SOSHandleData; #endif //HandleData extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0000_v0_0_s_ifspec; #ifndef __ISOSEnum_INTERFACE_DEFINED__ #define __ISOSEnum_INTERFACE_DEFINED__ /* interface ISOSEnum */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("286CA186-E763-4F61-9760-487D43AE4341") ISOSEnum : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Skip( /* [in] */ unsigned int count) = 0; virtual HRESULT STDMETHODCALLTYPE Reset( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetCount( /* [out] */ unsigned int *pCount) = 0; }; #else /* C style interface */ typedef struct ISOSEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ISOSEnum * This, /* [in] */ unsigned int count); HRESULT ( STDMETHODCALLTYPE *Reset )( ISOSEnum * This); HRESULT ( STDMETHODCALLTYPE *GetCount )( ISOSEnum * This, /* [out] */ unsigned int *pCount); END_INTERFACE } ISOSEnumVtbl; interface ISOSEnum { CONST_VTBL struct ISOSEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) #define ISOSEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ISOSEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSEnum_INTERFACE_DEFINED__ */ #ifndef __ISOSHandleEnum_INTERFACE_DEFINED__ #define __ISOSHandleEnum_INTERFACE_DEFINED__ /* interface ISOSHandleEnum */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSHandleEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("3E269830-4A2B-4301-8EE2-D6805B29B2FA") ISOSHandleEnum : public ISOSEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ unsigned int count, /* [length_is][size_is][out] */ SOSHandleData handles[ ], /* [out] */ unsigned int *pNeeded) = 0; }; #else /* C style interface */ typedef struct ISOSHandleEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSHandleEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSHandleEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSHandleEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ISOSHandleEnum * This, /* [in] */ unsigned int count); HRESULT ( STDMETHODCALLTYPE *Reset )( ISOSHandleEnum * This); HRESULT ( STDMETHODCALLTYPE *GetCount )( ISOSHandleEnum * This, /* [out] */ unsigned int *pCount); HRESULT ( STDMETHODCALLTYPE *Next )( ISOSHandleEnum * This, /* [in] */ unsigned int count, /* [length_is][size_is][out] */ SOSHandleData handles[ ], /* [out] */ unsigned int *pNeeded); END_INTERFACE } ISOSHandleEnumVtbl; interface ISOSHandleEnum { CONST_VTBL struct ISOSHandleEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSHandleEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSHandleEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSHandleEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSHandleEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) #define ISOSHandleEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ISOSHandleEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) #define ISOSHandleEnum_Next(This,count,handles,pNeeded) \ ( (This)->lpVtbl -> Next(This,count,handles,pNeeded) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSHandleEnum_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_sospriv_0000_0002 */ /* [local] */ #ifndef _SOS_StackReference_ #define _SOS_StackReference_ typedef enum SOSStackSourceType { SOS_StackSourceIP = 0, SOS_StackSourceFrame = ( SOS_StackSourceIP + 1 ) } SOSStackSourceType; typedef enum SOSRefFlags { SOSRefInterior = 1, SOSRefPinned = 2 } SOSRefFlags; typedef struct _SOS_StackRefData { BOOL HasRegisterInformation; int Register; int Offset; CLRDATA_ADDRESS Address; CLRDATA_ADDRESS Object; unsigned int Flags; SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; } SOSStackRefData; typedef struct _SOS_StackRefError { SOSStackSourceType SourceType; CLRDATA_ADDRESS Source; CLRDATA_ADDRESS StackPointer; } SOSStackRefError; #endif // _SOS_StackReference_ extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0002_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0002_v0_0_s_ifspec; #ifndef __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ #define __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ /* interface ISOSStackRefErrorEnum */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSStackRefErrorEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("774F4E1B-FB7B-491B-976D-A8130FE355E9") ISOSStackRefErrorEnum : public ISOSEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ unsigned int count, /* [length_is][size_is][out] */ SOSStackRefError ref[ ], /* [out] */ unsigned int *pFetched) = 0; }; #else /* C style interface */ typedef struct ISOSStackRefErrorEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSStackRefErrorEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSStackRefErrorEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSStackRefErrorEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ISOSStackRefErrorEnum * This, /* [in] */ unsigned int count); HRESULT ( STDMETHODCALLTYPE *Reset )( ISOSStackRefErrorEnum * This); HRESULT ( STDMETHODCALLTYPE *GetCount )( ISOSStackRefErrorEnum * This, /* [out] */ unsigned int *pCount); HRESULT ( STDMETHODCALLTYPE *Next )( ISOSStackRefErrorEnum * This, /* [in] */ unsigned int count, /* [length_is][size_is][out] */ SOSStackRefError ref[ ], /* [out] */ unsigned int *pFetched); END_INTERFACE } ISOSStackRefErrorEnumVtbl; interface ISOSStackRefErrorEnum { CONST_VTBL struct ISOSStackRefErrorEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSStackRefErrorEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSStackRefErrorEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSStackRefErrorEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSStackRefErrorEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) #define ISOSStackRefErrorEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ISOSStackRefErrorEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) #define ISOSStackRefErrorEnum_Next(This,count,ref,pFetched) \ ( (This)->lpVtbl -> Next(This,count,ref,pFetched) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSStackRefErrorEnum_INTERFACE_DEFINED__ */ #ifndef __ISOSStackRefEnum_INTERFACE_DEFINED__ #define __ISOSStackRefEnum_INTERFACE_DEFINED__ /* interface ISOSStackRefEnum */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSStackRefEnum; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("8FA642BD-9F10-4799-9AA3-512AE78C77EE") ISOSStackRefEnum : public ISOSEnum { public: virtual HRESULT STDMETHODCALLTYPE Next( /* [in] */ unsigned int count, /* [length_is][size_is][out] */ SOSStackRefData ref[ ], /* [out] */ unsigned int *pFetched) = 0; virtual HRESULT STDMETHODCALLTYPE EnumerateErrors( /* [out] */ ISOSStackRefErrorEnum **ppEnum) = 0; }; #else /* C style interface */ typedef struct ISOSStackRefEnumVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSStackRefEnum * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSStackRefEnum * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSStackRefEnum * This); HRESULT ( STDMETHODCALLTYPE *Skip )( ISOSStackRefEnum * This, /* [in] */ unsigned int count); HRESULT ( STDMETHODCALLTYPE *Reset )( ISOSStackRefEnum * This); HRESULT ( STDMETHODCALLTYPE *GetCount )( ISOSStackRefEnum * This, /* [out] */ unsigned int *pCount); HRESULT ( STDMETHODCALLTYPE *Next )( ISOSStackRefEnum * This, /* [in] */ unsigned int count, /* [length_is][size_is][out] */ SOSStackRefData ref[ ], /* [out] */ unsigned int *pFetched); HRESULT ( STDMETHODCALLTYPE *EnumerateErrors )( ISOSStackRefEnum * This, /* [out] */ ISOSStackRefErrorEnum **ppEnum); END_INTERFACE } ISOSStackRefEnumVtbl; interface ISOSStackRefEnum { CONST_VTBL struct ISOSStackRefEnumVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSStackRefEnum_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSStackRefEnum_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSStackRefEnum_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSStackRefEnum_Skip(This,count) \ ( (This)->lpVtbl -> Skip(This,count) ) #define ISOSStackRefEnum_Reset(This) \ ( (This)->lpVtbl -> Reset(This) ) #define ISOSStackRefEnum_GetCount(This,pCount) \ ( (This)->lpVtbl -> GetCount(This,pCount) ) #define ISOSStackRefEnum_Next(This,count,ref,pFetched) \ ( (This)->lpVtbl -> Next(This,count,ref,pFetched) ) #define ISOSStackRefEnum_EnumerateErrors(This,ppEnum) \ ( (This)->lpVtbl -> EnumerateErrors(This,ppEnum) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSStackRefEnum_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface_INTERFACE_DEFINED__ #define __ISOSDacInterface_INTERFACE_DEFINED__ /* interface ISOSDacInterface */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("436f00f2-b42a-4b9f-870c-e73db66ae930") ISOSDacInterface : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetThreadStoreData( struct DacpThreadStoreData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainStoreData( struct DacpAppDomainStoreData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainList( unsigned int count, CLRDATA_ADDRESS values[ ], unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainData( CLRDATA_ADDRESS addr, struct DacpAppDomainData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainName( CLRDATA_ADDRESS addr, unsigned int count, WCHAR *name, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetDomainFromContext( CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyList( CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[ ], int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyData( CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyName( CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetModule( CLRDATA_ADDRESS addr, IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE GetModuleData( CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data) = 0; virtual HRESULT STDMETHODCALLTYPE TraverseModuleMap( ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyModuleList( CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[ ], unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetILForModule( CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadData( CLRDATA_ADDRESS thread, struct DacpThreadData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadFromThinlockID( UINT thinLockId, CLRDATA_ADDRESS *pThread) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackLimits( CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDescData( CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, struct DacpReJitData *rgRevertedRejitData, ULONG *pcNeededRevertedRejitData) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromIP( CLRDATA_ADDRESS ip, CLRDATA_ADDRESS *ppMD) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDescName( CLRDATA_ADDRESS methodDesc, unsigned int count, WCHAR *name, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDescPtrFromFrame( CLRDATA_ADDRESS frameAddr, CLRDATA_ADDRESS *ppMD) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDescFromToken( CLRDATA_ADDRESS moduleAddr, mdToken token, CLRDATA_ADDRESS *methodDesc) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDescTransparencyData( CLRDATA_ADDRESS methodDesc, struct DacpMethodDescTransparencyData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeHeaderData( CLRDATA_ADDRESS ip, struct DacpCodeHeaderData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetJitManagerList( unsigned int count, struct DacpJitManagerInfo *managers, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetJitHelperFunctionName( CLRDATA_ADDRESS ip, unsigned int count, char *name, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetJumpThunkTarget( T_CONTEXT *ctx, CLRDATA_ADDRESS *targetIP, CLRDATA_ADDRESS *targetMD) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadpoolData( struct DacpThreadpoolData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetWorkRequestData( CLRDATA_ADDRESS addrWorkRequest, struct DacpWorkRequestData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetHillClimbingLogEntry( CLRDATA_ADDRESS addr, struct DacpHillClimbingLogEntry *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectData( CLRDATA_ADDRESS objAddr, struct DacpObjectData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectStringData( CLRDATA_ADDRESS obj, unsigned int count, WCHAR *stringData, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetObjectClassName( CLRDATA_ADDRESS obj, unsigned int count, WCHAR *className, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodTableName( CLRDATA_ADDRESS mt, unsigned int count, WCHAR *mtName, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodTableData( CLRDATA_ADDRESS mt, struct DacpMethodTableData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodTableSlot( CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA_ADDRESS *value) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodTableFieldData( CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodTableTransparencyData( CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodTableForEEClass( CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldDescData( CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetFrameName( CLRDATA_ADDRESS vtable, unsigned int count, WCHAR *frameName, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetPEFileBase( CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base) = 0; virtual HRESULT STDMETHODCALLTYPE GetPEFileName( CLRDATA_ADDRESS addr, unsigned int count, WCHAR *fileName, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetGCHeapData( struct DacpGcHeapData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetGCHeapList( unsigned int count, CLRDATA_ADDRESS heaps[ ], unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetGCHeapDetails( CLRDATA_ADDRESS heap, struct DacpGcHeapDetails *details) = 0; virtual HRESULT STDMETHODCALLTYPE GetGCHeapStaticData( struct DacpGcHeapDetails *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetHeapSegmentData( CLRDATA_ADDRESS seg, struct DacpHeapSegmentData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetOOMData( CLRDATA_ADDRESS oomAddr, struct DacpOomData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetOOMStaticData( struct DacpOomData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeData( CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyzeData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetHeapAnalyzeStaticData( struct DacpGcHeapAnalyzeData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleData( CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromAppDomain( CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetDomainLocalModuleDataFromModule( CLRDATA_ADDRESS moduleAddr, struct DacpDomainLocalModuleData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadLocalModuleData( CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetSyncBlockData( unsigned int number, struct DacpSyncBlockData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetSyncBlockCleanupData( CLRDATA_ADDRESS addr, struct DacpSyncBlockCleanupData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetHandleEnum( ISOSHandleEnum **ppHandleEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForTypes( unsigned int types[ ], unsigned int count, ISOSHandleEnum **ppHandleEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetHandleEnumForGC( unsigned int gen, ISOSHandleEnum **ppHandleEnum) = 0; virtual HRESULT STDMETHODCALLTYPE TraverseEHInfo( CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token) = 0; virtual HRESULT STDMETHODCALLTYPE GetNestedExceptionData( CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException) = 0; virtual HRESULT STDMETHODCALLTYPE GetStressLogAddress( CLRDATA_ADDRESS *stressLog) = 0; virtual HRESULT STDMETHODCALLTYPE TraverseLoaderHeap( CLRDATA_ADDRESS loaderHeapAddr, VISITHEAP pCallback) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeHeapList( CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo *codeHeaps, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE TraverseVirtCallStubHeap( CLRDATA_ADDRESS pAppDomain, VCSHeapType heaptype, VISITHEAP pCallback) = 0; virtual HRESULT STDMETHODCALLTYPE GetUsefulGlobals( struct DacpUsefulGlobalsData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetClrWatsonBuckets( CLRDATA_ADDRESS thread, void *pGenericModeBlock) = 0; virtual HRESULT STDMETHODCALLTYPE GetTLSIndex( ULONG *pIndex) = 0; virtual HRESULT STDMETHODCALLTYPE GetDacModuleHandle( HMODULE *phModule) = 0; virtual HRESULT STDMETHODCALLTYPE GetRCWData( CLRDATA_ADDRESS addr, struct DacpRCWData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetRCWInterfaces( CLRDATA_ADDRESS rcw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetCCWData( CLRDATA_ADDRESS ccw, struct DacpCCWData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetCCWInterfaces( CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE TraverseRCWCleanupList( CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackReferences( /* [in] */ DWORD osThreadID, /* [out] */ ISOSStackRefEnum **ppEnum) = 0; virtual HRESULT STDMETHODCALLTYPE GetRegisterName( /* [in] */ int regName, /* [in] */ unsigned int count, /* [out] */ WCHAR *buffer, /* [out] */ unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetThreadAllocData( CLRDATA_ADDRESS thread, struct DacpAllocData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetHeapAllocData( unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyList( CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[ ], unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetPrivateBinPaths( CLRDATA_ADDRESS appDomain, int count, WCHAR *paths, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyLocation( CLRDATA_ADDRESS assembly, int count, WCHAR *location, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainConfigFile( CLRDATA_ADDRESS appDomain, int count, WCHAR *configFile, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetApplicationBase( CLRDATA_ADDRESS appDomain, int count, WCHAR *base, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyData( CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult) = 0; virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyLocation( CLRDATA_ADDRESS assesmbly, unsigned int count, WCHAR *location, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetFailedAssemblyDisplayName( CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterfaceVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface * This); HRESULT ( STDMETHODCALLTYPE *GetThreadStoreData )( ISOSDacInterface * This, struct DacpThreadStoreData *data); HRESULT ( STDMETHODCALLTYPE *GetAppDomainStoreData )( ISOSDacInterface * This, struct DacpAppDomainStoreData *data); HRESULT ( STDMETHODCALLTYPE *GetAppDomainList )( ISOSDacInterface * This, unsigned int count, CLRDATA_ADDRESS values[ ], unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetAppDomainData )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, struct DacpAppDomainData *data); HRESULT ( STDMETHODCALLTYPE *GetAppDomainName )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, unsigned int count, WCHAR *name, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetDomainFromContext )( ISOSDacInterface * This, CLRDATA_ADDRESS context, CLRDATA_ADDRESS *domain); HRESULT ( STDMETHODCALLTYPE *GetAssemblyList )( ISOSDacInterface * This, CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[ ], int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetAssemblyData )( ISOSDacInterface * This, CLRDATA_ADDRESS baseDomainPtr, CLRDATA_ADDRESS assembly, struct DacpAssemblyData *data); HRESULT ( STDMETHODCALLTYPE *GetAssemblyName )( ISOSDacInterface * This, CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetModule )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *GetModuleData )( ISOSDacInterface * This, CLRDATA_ADDRESS moduleAddr, struct DacpModuleData *data); HRESULT ( STDMETHODCALLTYPE *TraverseModuleMap )( ISOSDacInterface * This, ModuleMapType mmt, CLRDATA_ADDRESS moduleAddr, MODULEMAPTRAVERSE pCallback, LPVOID token); HRESULT ( STDMETHODCALLTYPE *GetAssemblyModuleList )( ISOSDacInterface * This, CLRDATA_ADDRESS assembly, unsigned int count, CLRDATA_ADDRESS modules[ ], unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetILForModule )( ISOSDacInterface * This, CLRDATA_ADDRESS moduleAddr, DWORD rva, CLRDATA_ADDRESS *il); HRESULT ( STDMETHODCALLTYPE *GetThreadData )( ISOSDacInterface * This, CLRDATA_ADDRESS thread, struct DacpThreadData *data); HRESULT ( STDMETHODCALLTYPE *GetThreadFromThinlockID )( ISOSDacInterface * This, UINT thinLockId, CLRDATA_ADDRESS *pThread); HRESULT ( STDMETHODCALLTYPE *GetStackLimits )( ISOSDacInterface * This, CLRDATA_ADDRESS threadPtr, CLRDATA_ADDRESS *lower, CLRDATA_ADDRESS *upper, CLRDATA_ADDRESS *fp); HRESULT ( STDMETHODCALLTYPE *GetMethodDescData )( ISOSDacInterface * This, CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, struct DacpReJitData *rgRevertedRejitData, ULONG *pcNeededRevertedRejitData); HRESULT ( STDMETHODCALLTYPE *GetMethodDescPtrFromIP )( ISOSDacInterface * This, CLRDATA_ADDRESS ip, CLRDATA_ADDRESS *ppMD); HRESULT ( STDMETHODCALLTYPE *GetMethodDescName )( ISOSDacInterface * This, CLRDATA_ADDRESS methodDesc, unsigned int count, WCHAR *name, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetMethodDescPtrFromFrame )( ISOSDacInterface * This, CLRDATA_ADDRESS frameAddr, CLRDATA_ADDRESS *ppMD); HRESULT ( STDMETHODCALLTYPE *GetMethodDescFromToken )( ISOSDacInterface * This, CLRDATA_ADDRESS moduleAddr, mdToken token, CLRDATA_ADDRESS *methodDesc); HRESULT ( STDMETHODCALLTYPE *GetMethodDescTransparencyData )( ISOSDacInterface * This, CLRDATA_ADDRESS methodDesc, struct DacpMethodDescTransparencyData *data); HRESULT ( STDMETHODCALLTYPE *GetCodeHeaderData )( ISOSDacInterface * This, CLRDATA_ADDRESS ip, struct DacpCodeHeaderData *data); HRESULT ( STDMETHODCALLTYPE *GetJitManagerList )( ISOSDacInterface * This, unsigned int count, struct DacpJitManagerInfo *managers, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetJitHelperFunctionName )( ISOSDacInterface * This, CLRDATA_ADDRESS ip, unsigned int count, char *name, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetJumpThunkTarget )( ISOSDacInterface * This, T_CONTEXT *ctx, CLRDATA_ADDRESS *targetIP, CLRDATA_ADDRESS *targetMD); HRESULT ( STDMETHODCALLTYPE *GetThreadpoolData )( ISOSDacInterface * This, struct DacpThreadpoolData *data); HRESULT ( STDMETHODCALLTYPE *GetWorkRequestData )( ISOSDacInterface * This, CLRDATA_ADDRESS addrWorkRequest, struct DacpWorkRequestData *data); HRESULT ( STDMETHODCALLTYPE *GetHillClimbingLogEntry )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, struct DacpHillClimbingLogEntry *data); HRESULT ( STDMETHODCALLTYPE *GetObjectData )( ISOSDacInterface * This, CLRDATA_ADDRESS objAddr, struct DacpObjectData *data); HRESULT ( STDMETHODCALLTYPE *GetObjectStringData )( ISOSDacInterface * This, CLRDATA_ADDRESS obj, unsigned int count, WCHAR *stringData, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetObjectClassName )( ISOSDacInterface * This, CLRDATA_ADDRESS obj, unsigned int count, WCHAR *className, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetMethodTableName )( ISOSDacInterface * This, CLRDATA_ADDRESS mt, unsigned int count, WCHAR *mtName, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetMethodTableData )( ISOSDacInterface * This, CLRDATA_ADDRESS mt, struct DacpMethodTableData *data); HRESULT ( STDMETHODCALLTYPE *GetMethodTableSlot )( ISOSDacInterface * This, CLRDATA_ADDRESS mt, unsigned int slot, CLRDATA_ADDRESS *value); HRESULT ( STDMETHODCALLTYPE *GetMethodTableFieldData )( ISOSDacInterface * This, CLRDATA_ADDRESS mt, struct DacpMethodTableFieldData *data); HRESULT ( STDMETHODCALLTYPE *GetMethodTableTransparencyData )( ISOSDacInterface * This, CLRDATA_ADDRESS mt, struct DacpMethodTableTransparencyData *data); HRESULT ( STDMETHODCALLTYPE *GetMethodTableForEEClass )( ISOSDacInterface * This, CLRDATA_ADDRESS eeClass, CLRDATA_ADDRESS *value); HRESULT ( STDMETHODCALLTYPE *GetFieldDescData )( ISOSDacInterface * This, CLRDATA_ADDRESS fieldDesc, struct DacpFieldDescData *data); HRESULT ( STDMETHODCALLTYPE *GetFrameName )( ISOSDacInterface * This, CLRDATA_ADDRESS vtable, unsigned int count, WCHAR *frameName, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetPEFileBase )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, CLRDATA_ADDRESS *base); HRESULT ( STDMETHODCALLTYPE *GetPEFileName )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, unsigned int count, WCHAR *fileName, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetGCHeapData )( ISOSDacInterface * This, struct DacpGcHeapData *data); HRESULT ( STDMETHODCALLTYPE *GetGCHeapList )( ISOSDacInterface * This, unsigned int count, CLRDATA_ADDRESS heaps[ ], unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetGCHeapDetails )( ISOSDacInterface * This, CLRDATA_ADDRESS heap, struct DacpGcHeapDetails *details); HRESULT ( STDMETHODCALLTYPE *GetGCHeapStaticData )( ISOSDacInterface * This, struct DacpGcHeapDetails *data); HRESULT ( STDMETHODCALLTYPE *GetHeapSegmentData )( ISOSDacInterface * This, CLRDATA_ADDRESS seg, struct DacpHeapSegmentData *data); HRESULT ( STDMETHODCALLTYPE *GetOOMData )( ISOSDacInterface * This, CLRDATA_ADDRESS oomAddr, struct DacpOomData *data); HRESULT ( STDMETHODCALLTYPE *GetOOMStaticData )( ISOSDacInterface * This, struct DacpOomData *data); HRESULT ( STDMETHODCALLTYPE *GetHeapAnalyzeData )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, struct DacpGcHeapAnalyzeData *data); HRESULT ( STDMETHODCALLTYPE *GetHeapAnalyzeStaticData )( ISOSDacInterface * This, struct DacpGcHeapAnalyzeData *data); HRESULT ( STDMETHODCALLTYPE *GetDomainLocalModuleData )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, struct DacpDomainLocalModuleData *data); HRESULT ( STDMETHODCALLTYPE *GetDomainLocalModuleDataFromAppDomain )( ISOSDacInterface * This, CLRDATA_ADDRESS appDomainAddr, int moduleID, struct DacpDomainLocalModuleData *data); HRESULT ( STDMETHODCALLTYPE *GetDomainLocalModuleDataFromModule )( ISOSDacInterface * This, CLRDATA_ADDRESS moduleAddr, struct DacpDomainLocalModuleData *data); HRESULT ( STDMETHODCALLTYPE *GetThreadLocalModuleData )( ISOSDacInterface * This, CLRDATA_ADDRESS thread, unsigned int index, struct DacpThreadLocalModuleData *data); HRESULT ( STDMETHODCALLTYPE *GetSyncBlockData )( ISOSDacInterface * This, unsigned int number, struct DacpSyncBlockData *data); HRESULT ( STDMETHODCALLTYPE *GetSyncBlockCleanupData )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, struct DacpSyncBlockCleanupData *data); HRESULT ( STDMETHODCALLTYPE *GetHandleEnum )( ISOSDacInterface * This, ISOSHandleEnum **ppHandleEnum); HRESULT ( STDMETHODCALLTYPE *GetHandleEnumForTypes )( ISOSDacInterface * This, unsigned int types[ ], unsigned int count, ISOSHandleEnum **ppHandleEnum); HRESULT ( STDMETHODCALLTYPE *GetHandleEnumForGC )( ISOSDacInterface * This, unsigned int gen, ISOSHandleEnum **ppHandleEnum); HRESULT ( STDMETHODCALLTYPE *TraverseEHInfo )( ISOSDacInterface * This, CLRDATA_ADDRESS ip, DUMPEHINFO pCallback, LPVOID token); HRESULT ( STDMETHODCALLTYPE *GetNestedExceptionData )( ISOSDacInterface * This, CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException); HRESULT ( STDMETHODCALLTYPE *GetStressLogAddress )( ISOSDacInterface * This, CLRDATA_ADDRESS *stressLog); HRESULT ( STDMETHODCALLTYPE *TraverseLoaderHeap )( ISOSDacInterface * This, CLRDATA_ADDRESS loaderHeapAddr, VISITHEAP pCallback); HRESULT ( STDMETHODCALLTYPE *GetCodeHeapList )( ISOSDacInterface * This, CLRDATA_ADDRESS jitManager, unsigned int count, struct DacpJitCodeHeapInfo *codeHeaps, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *TraverseVirtCallStubHeap )( ISOSDacInterface * This, CLRDATA_ADDRESS pAppDomain, VCSHeapType heaptype, VISITHEAP pCallback); HRESULT ( STDMETHODCALLTYPE *GetUsefulGlobals )( ISOSDacInterface * This, struct DacpUsefulGlobalsData *data); HRESULT ( STDMETHODCALLTYPE *GetClrWatsonBuckets )( ISOSDacInterface * This, CLRDATA_ADDRESS thread, void *pGenericModeBlock); HRESULT ( STDMETHODCALLTYPE *GetTLSIndex )( ISOSDacInterface * This, ULONG *pIndex); HRESULT ( STDMETHODCALLTYPE *GetDacModuleHandle )( ISOSDacInterface * This, HMODULE *phModule); HRESULT ( STDMETHODCALLTYPE *GetRCWData )( ISOSDacInterface * This, CLRDATA_ADDRESS addr, struct DacpRCWData *data); HRESULT ( STDMETHODCALLTYPE *GetRCWInterfaces )( ISOSDacInterface * This, CLRDATA_ADDRESS rcw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetCCWData )( ISOSDacInterface * This, CLRDATA_ADDRESS ccw, struct DacpCCWData *data); HRESULT ( STDMETHODCALLTYPE *GetCCWInterfaces )( ISOSDacInterface * This, CLRDATA_ADDRESS ccw, unsigned int count, struct DacpCOMInterfacePointerData *interfaces, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *TraverseRCWCleanupList )( ISOSDacInterface * This, CLRDATA_ADDRESS cleanupListPtr, VISITRCWFORCLEANUP pCallback, LPVOID token); HRESULT ( STDMETHODCALLTYPE *GetStackReferences )( ISOSDacInterface * This, /* [in] */ DWORD osThreadID, /* [out] */ ISOSStackRefEnum **ppEnum); HRESULT ( STDMETHODCALLTYPE *GetRegisterName )( ISOSDacInterface * This, /* [in] */ int regName, /* [in] */ unsigned int count, /* [out] */ WCHAR *buffer, /* [out] */ unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetThreadAllocData )( ISOSDacInterface * This, CLRDATA_ADDRESS thread, struct DacpAllocData *data); HRESULT ( STDMETHODCALLTYPE *GetHeapAllocData )( ISOSDacInterface * This, unsigned int count, struct DacpGenerationAllocData *data, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyList )( ISOSDacInterface * This, CLRDATA_ADDRESS appDomain, int count, CLRDATA_ADDRESS values[ ], unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetPrivateBinPaths )( ISOSDacInterface * This, CLRDATA_ADDRESS appDomain, int count, WCHAR *paths, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetAssemblyLocation )( ISOSDacInterface * This, CLRDATA_ADDRESS assembly, int count, WCHAR *location, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetAppDomainConfigFile )( ISOSDacInterface * This, CLRDATA_ADDRESS appDomain, int count, WCHAR *configFile, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetApplicationBase )( ISOSDacInterface * This, CLRDATA_ADDRESS appDomain, int count, WCHAR *base, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyData )( ISOSDacInterface * This, CLRDATA_ADDRESS assembly, unsigned int *pContext, HRESULT *pResult); HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyLocation )( ISOSDacInterface * This, CLRDATA_ADDRESS assesmbly, unsigned int count, WCHAR *location, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetFailedAssemblyDisplayName )( ISOSDacInterface * This, CLRDATA_ADDRESS assembly, unsigned int count, WCHAR *name, unsigned int *pNeeded); END_INTERFACE } ISOSDacInterfaceVtbl; interface ISOSDacInterface { CONST_VTBL struct ISOSDacInterfaceVtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface_GetThreadStoreData(This,data) \ ( (This)->lpVtbl -> GetThreadStoreData(This,data) ) #define ISOSDacInterface_GetAppDomainStoreData(This,data) \ ( (This)->lpVtbl -> GetAppDomainStoreData(This,data) ) #define ISOSDacInterface_GetAppDomainList(This,count,values,pNeeded) \ ( (This)->lpVtbl -> GetAppDomainList(This,count,values,pNeeded) ) #define ISOSDacInterface_GetAppDomainData(This,addr,data) \ ( (This)->lpVtbl -> GetAppDomainData(This,addr,data) ) #define ISOSDacInterface_GetAppDomainName(This,addr,count,name,pNeeded) \ ( (This)->lpVtbl -> GetAppDomainName(This,addr,count,name,pNeeded) ) #define ISOSDacInterface_GetDomainFromContext(This,context,domain) \ ( (This)->lpVtbl -> GetDomainFromContext(This,context,domain) ) #define ISOSDacInterface_GetAssemblyList(This,appDomain,count,values,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyList(This,appDomain,count,values,pNeeded) ) #define ISOSDacInterface_GetAssemblyData(This,baseDomainPtr,assembly,data) \ ( (This)->lpVtbl -> GetAssemblyData(This,baseDomainPtr,assembly,data) ) #define ISOSDacInterface_GetAssemblyName(This,assembly,count,name,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyName(This,assembly,count,name,pNeeded) ) #define ISOSDacInterface_GetModule(This,addr,mod) \ ( (This)->lpVtbl -> GetModule(This,addr,mod) ) #define ISOSDacInterface_GetModuleData(This,moduleAddr,data) \ ( (This)->lpVtbl -> GetModuleData(This,moduleAddr,data) ) #define ISOSDacInterface_TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) \ ( (This)->lpVtbl -> TraverseModuleMap(This,mmt,moduleAddr,pCallback,token) ) #define ISOSDacInterface_GetAssemblyModuleList(This,assembly,count,modules,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyModuleList(This,assembly,count,modules,pNeeded) ) #define ISOSDacInterface_GetILForModule(This,moduleAddr,rva,il) \ ( (This)->lpVtbl -> GetILForModule(This,moduleAddr,rva,il) ) #define ISOSDacInterface_GetThreadData(This,thread,data) \ ( (This)->lpVtbl -> GetThreadData(This,thread,data) ) #define ISOSDacInterface_GetThreadFromThinlockID(This,thinLockId,pThread) \ ( (This)->lpVtbl -> GetThreadFromThinlockID(This,thinLockId,pThread) ) #define ISOSDacInterface_GetStackLimits(This,threadPtr,lower,upper,fp) \ ( (This)->lpVtbl -> GetStackLimits(This,threadPtr,lower,upper,fp) ) #define ISOSDacInterface_GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) \ ( (This)->lpVtbl -> GetMethodDescData(This,methodDesc,ip,data,cRevertedRejitVersions,rgRevertedRejitData,pcNeededRevertedRejitData) ) #define ISOSDacInterface_GetMethodDescPtrFromIP(This,ip,ppMD) \ ( (This)->lpVtbl -> GetMethodDescPtrFromIP(This,ip,ppMD) ) #define ISOSDacInterface_GetMethodDescName(This,methodDesc,count,name,pNeeded) \ ( (This)->lpVtbl -> GetMethodDescName(This,methodDesc,count,name,pNeeded) ) #define ISOSDacInterface_GetMethodDescPtrFromFrame(This,frameAddr,ppMD) \ ( (This)->lpVtbl -> GetMethodDescPtrFromFrame(This,frameAddr,ppMD) ) #define ISOSDacInterface_GetMethodDescFromToken(This,moduleAddr,token,methodDesc) \ ( (This)->lpVtbl -> GetMethodDescFromToken(This,moduleAddr,token,methodDesc) ) #define ISOSDacInterface_GetMethodDescTransparencyData(This,methodDesc,data) \ ( (This)->lpVtbl -> GetMethodDescTransparencyData(This,methodDesc,data) ) #define ISOSDacInterface_GetCodeHeaderData(This,ip,data) \ ( (This)->lpVtbl -> GetCodeHeaderData(This,ip,data) ) #define ISOSDacInterface_GetJitManagerList(This,count,managers,pNeeded) \ ( (This)->lpVtbl -> GetJitManagerList(This,count,managers,pNeeded) ) #define ISOSDacInterface_GetJitHelperFunctionName(This,ip,count,name,pNeeded) \ ( (This)->lpVtbl -> GetJitHelperFunctionName(This,ip,count,name,pNeeded) ) #define ISOSDacInterface_GetJumpThunkTarget(This,ctx,targetIP,targetMD) \ ( (This)->lpVtbl -> GetJumpThunkTarget(This,ctx,targetIP,targetMD) ) #define ISOSDacInterface_GetThreadpoolData(This,data) \ ( (This)->lpVtbl -> GetThreadpoolData(This,data) ) #define ISOSDacInterface_GetWorkRequestData(This,addrWorkRequest,data) \ ( (This)->lpVtbl -> GetWorkRequestData(This,addrWorkRequest,data) ) #define ISOSDacInterface_GetHillClimbingLogEntry(This,addr,data) \ ( (This)->lpVtbl -> GetHillClimbingLogEntry(This,addr,data) ) #define ISOSDacInterface_GetObjectData(This,objAddr,data) \ ( (This)->lpVtbl -> GetObjectData(This,objAddr,data) ) #define ISOSDacInterface_GetObjectStringData(This,obj,count,stringData,pNeeded) \ ( (This)->lpVtbl -> GetObjectStringData(This,obj,count,stringData,pNeeded) ) #define ISOSDacInterface_GetObjectClassName(This,obj,count,className,pNeeded) \ ( (This)->lpVtbl -> GetObjectClassName(This,obj,count,className,pNeeded) ) #define ISOSDacInterface_GetMethodTableName(This,mt,count,mtName,pNeeded) \ ( (This)->lpVtbl -> GetMethodTableName(This,mt,count,mtName,pNeeded) ) #define ISOSDacInterface_GetMethodTableData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableData(This,mt,data) ) #define ISOSDacInterface_GetMethodTableSlot(This,mt,slot,value) \ ( (This)->lpVtbl -> GetMethodTableSlot(This,mt,slot,value) ) #define ISOSDacInterface_GetMethodTableFieldData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableFieldData(This,mt,data) ) #define ISOSDacInterface_GetMethodTableTransparencyData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableTransparencyData(This,mt,data) ) #define ISOSDacInterface_GetMethodTableForEEClass(This,eeClass,value) \ ( (This)->lpVtbl -> GetMethodTableForEEClass(This,eeClass,value) ) #define ISOSDacInterface_GetFieldDescData(This,fieldDesc,data) \ ( (This)->lpVtbl -> GetFieldDescData(This,fieldDesc,data) ) #define ISOSDacInterface_GetFrameName(This,vtable,count,frameName,pNeeded) \ ( (This)->lpVtbl -> GetFrameName(This,vtable,count,frameName,pNeeded) ) #define ISOSDacInterface_GetPEFileBase(This,addr,base) \ ( (This)->lpVtbl -> GetPEFileBase(This,addr,base) ) #define ISOSDacInterface_GetPEFileName(This,addr,count,fileName,pNeeded) \ ( (This)->lpVtbl -> GetPEFileName(This,addr,count,fileName,pNeeded) ) #define ISOSDacInterface_GetGCHeapData(This,data) \ ( (This)->lpVtbl -> GetGCHeapData(This,data) ) #define ISOSDacInterface_GetGCHeapList(This,count,heaps,pNeeded) \ ( (This)->lpVtbl -> GetGCHeapList(This,count,heaps,pNeeded) ) #define ISOSDacInterface_GetGCHeapDetails(This,heap,details) \ ( (This)->lpVtbl -> GetGCHeapDetails(This,heap,details) ) #define ISOSDacInterface_GetGCHeapStaticData(This,data) \ ( (This)->lpVtbl -> GetGCHeapStaticData(This,data) ) #define ISOSDacInterface_GetHeapSegmentData(This,seg,data) \ ( (This)->lpVtbl -> GetHeapSegmentData(This,seg,data) ) #define ISOSDacInterface_GetOOMData(This,oomAddr,data) \ ( (This)->lpVtbl -> GetOOMData(This,oomAddr,data) ) #define ISOSDacInterface_GetOOMStaticData(This,data) \ ( (This)->lpVtbl -> GetOOMStaticData(This,data) ) #define ISOSDacInterface_GetHeapAnalyzeData(This,addr,data) \ ( (This)->lpVtbl -> GetHeapAnalyzeData(This,addr,data) ) #define ISOSDacInterface_GetHeapAnalyzeStaticData(This,data) \ ( (This)->lpVtbl -> GetHeapAnalyzeStaticData(This,data) ) #define ISOSDacInterface_GetDomainLocalModuleData(This,addr,data) \ ( (This)->lpVtbl -> GetDomainLocalModuleData(This,addr,data) ) #define ISOSDacInterface_GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) \ ( (This)->lpVtbl -> GetDomainLocalModuleDataFromAppDomain(This,appDomainAddr,moduleID,data) ) #define ISOSDacInterface_GetDomainLocalModuleDataFromModule(This,moduleAddr,data) \ ( (This)->lpVtbl -> GetDomainLocalModuleDataFromModule(This,moduleAddr,data) ) #define ISOSDacInterface_GetThreadLocalModuleData(This,thread,index,data) \ ( (This)->lpVtbl -> GetThreadLocalModuleData(This,thread,index,data) ) #define ISOSDacInterface_GetSyncBlockData(This,number,data) \ ( (This)->lpVtbl -> GetSyncBlockData(This,number,data) ) #define ISOSDacInterface_GetSyncBlockCleanupData(This,addr,data) \ ( (This)->lpVtbl -> GetSyncBlockCleanupData(This,addr,data) ) #define ISOSDacInterface_GetHandleEnum(This,ppHandleEnum) \ ( (This)->lpVtbl -> GetHandleEnum(This,ppHandleEnum) ) #define ISOSDacInterface_GetHandleEnumForTypes(This,types,count,ppHandleEnum) \ ( (This)->lpVtbl -> GetHandleEnumForTypes(This,types,count,ppHandleEnum) ) #define ISOSDacInterface_GetHandleEnumForGC(This,gen,ppHandleEnum) \ ( (This)->lpVtbl -> GetHandleEnumForGC(This,gen,ppHandleEnum) ) #define ISOSDacInterface_TraverseEHInfo(This,ip,pCallback,token) \ ( (This)->lpVtbl -> TraverseEHInfo(This,ip,pCallback,token) ) #define ISOSDacInterface_GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) \ ( (This)->lpVtbl -> GetNestedExceptionData(This,exception,exceptionObject,nextNestedException) ) #define ISOSDacInterface_GetStressLogAddress(This,stressLog) \ ( (This)->lpVtbl -> GetStressLogAddress(This,stressLog) ) #define ISOSDacInterface_TraverseLoaderHeap(This,loaderHeapAddr,pCallback) \ ( (This)->lpVtbl -> TraverseLoaderHeap(This,loaderHeapAddr,pCallback) ) #define ISOSDacInterface_GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) \ ( (This)->lpVtbl -> GetCodeHeapList(This,jitManager,count,codeHeaps,pNeeded) ) #define ISOSDacInterface_TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) \ ( (This)->lpVtbl -> TraverseVirtCallStubHeap(This,pAppDomain,heaptype,pCallback) ) #define ISOSDacInterface_GetUsefulGlobals(This,data) \ ( (This)->lpVtbl -> GetUsefulGlobals(This,data) ) #define ISOSDacInterface_GetClrWatsonBuckets(This,thread,pGenericModeBlock) \ ( (This)->lpVtbl -> GetClrWatsonBuckets(This,thread,pGenericModeBlock) ) #define ISOSDacInterface_GetTLSIndex(This,pIndex) \ ( (This)->lpVtbl -> GetTLSIndex(This,pIndex) ) #define ISOSDacInterface_GetDacModuleHandle(This,phModule) \ ( (This)->lpVtbl -> GetDacModuleHandle(This,phModule) ) #define ISOSDacInterface_GetRCWData(This,addr,data) \ ( (This)->lpVtbl -> GetRCWData(This,addr,data) ) #define ISOSDacInterface_GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) \ ( (This)->lpVtbl -> GetRCWInterfaces(This,rcw,count,interfaces,pNeeded) ) #define ISOSDacInterface_GetCCWData(This,ccw,data) \ ( (This)->lpVtbl -> GetCCWData(This,ccw,data) ) #define ISOSDacInterface_GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) \ ( (This)->lpVtbl -> GetCCWInterfaces(This,ccw,count,interfaces,pNeeded) ) #define ISOSDacInterface_TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) \ ( (This)->lpVtbl -> TraverseRCWCleanupList(This,cleanupListPtr,pCallback,token) ) #define ISOSDacInterface_GetStackReferences(This,osThreadID,ppEnum) \ ( (This)->lpVtbl -> GetStackReferences(This,osThreadID,ppEnum) ) #define ISOSDacInterface_GetRegisterName(This,regName,count,buffer,pNeeded) \ ( (This)->lpVtbl -> GetRegisterName(This,regName,count,buffer,pNeeded) ) #define ISOSDacInterface_GetThreadAllocData(This,thread,data) \ ( (This)->lpVtbl -> GetThreadAllocData(This,thread,data) ) #define ISOSDacInterface_GetHeapAllocData(This,count,data,pNeeded) \ ( (This)->lpVtbl -> GetHeapAllocData(This,count,data,pNeeded) ) #define ISOSDacInterface_GetFailedAssemblyList(This,appDomain,count,values,pNeeded) \ ( (This)->lpVtbl -> GetFailedAssemblyList(This,appDomain,count,values,pNeeded) ) #define ISOSDacInterface_GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) \ ( (This)->lpVtbl -> GetPrivateBinPaths(This,appDomain,count,paths,pNeeded) ) #define ISOSDacInterface_GetAssemblyLocation(This,assembly,count,location,pNeeded) \ ( (This)->lpVtbl -> GetAssemblyLocation(This,assembly,count,location,pNeeded) ) #define ISOSDacInterface_GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) \ ( (This)->lpVtbl -> GetAppDomainConfigFile(This,appDomain,count,configFile,pNeeded) ) #define ISOSDacInterface_GetApplicationBase(This,appDomain,count,base,pNeeded) \ ( (This)->lpVtbl -> GetApplicationBase(This,appDomain,count,base,pNeeded) ) #define ISOSDacInterface_GetFailedAssemblyData(This,assembly,pContext,pResult) \ ( (This)->lpVtbl -> GetFailedAssemblyData(This,assembly,pContext,pResult) ) #define ISOSDacInterface_GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) \ ( (This)->lpVtbl -> GetFailedAssemblyLocation(This,assesmbly,count,location,pNeeded) ) #define ISOSDacInterface_GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) \ ( (This)->lpVtbl -> GetFailedAssemblyDisplayName(This,assembly,count,name,pNeeded) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface2_INTERFACE_DEFINED__ #define __ISOSDacInterface2_INTERFACE_DEFINED__ /* interface ISOSDacInterface2 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A16026EC-96F4-40BA-87FB-5575986FB7AF") ISOSDacInterface2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetObjectExceptionData( CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data) = 0; virtual HRESULT STDMETHODCALLTYPE IsRCWDCOMProxy( CLRDATA_ADDRESS rcwAddr, BOOL *isDCOMProxy) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface2 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface2 * This); HRESULT ( STDMETHODCALLTYPE *GetObjectExceptionData )( ISOSDacInterface2 * This, CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data); HRESULT ( STDMETHODCALLTYPE *IsRCWDCOMProxy )( ISOSDacInterface2 * This, CLRDATA_ADDRESS rcwAddr, BOOL *isDCOMProxy); END_INTERFACE } ISOSDacInterface2Vtbl; interface ISOSDacInterface2 { CONST_VTBL struct ISOSDacInterface2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface2_GetObjectExceptionData(This,objAddr,data) \ ( (This)->lpVtbl -> GetObjectExceptionData(This,objAddr,data) ) #define ISOSDacInterface2_IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) \ ( (This)->lpVtbl -> IsRCWDCOMProxy(This,rcwAddr,isDCOMProxy) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface2_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface3_INTERFACE_DEFINED__ #define __ISOSDacInterface3_INTERFACE_DEFINED__ /* interface ISOSDacInterface3 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("B08C5CDC-FD8A-49C5-AB38-5FEEF35235B4") ISOSDacInterface3 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoData( CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetGCInterestingInfoStaticData( struct DacpGCInterestingInfoData *data) = 0; virtual HRESULT STDMETHODCALLTYPE GetGCGlobalMechanisms( size_t *globalMechanisms) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface3 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface3 * This); HRESULT ( STDMETHODCALLTYPE *GetGCInterestingInfoData )( ISOSDacInterface3 * This, CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data); HRESULT ( STDMETHODCALLTYPE *GetGCInterestingInfoStaticData )( ISOSDacInterface3 * This, struct DacpGCInterestingInfoData *data); HRESULT ( STDMETHODCALLTYPE *GetGCGlobalMechanisms )( ISOSDacInterface3 * This, size_t *globalMechanisms); END_INTERFACE } ISOSDacInterface3Vtbl; interface ISOSDacInterface3 { CONST_VTBL struct ISOSDacInterface3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface3_GetGCInterestingInfoData(This,interestingInfoAddr,data) \ ( (This)->lpVtbl -> GetGCInterestingInfoData(This,interestingInfoAddr,data) ) #define ISOSDacInterface3_GetGCInterestingInfoStaticData(This,data) \ ( (This)->lpVtbl -> GetGCInterestingInfoStaticData(This,data) ) #define ISOSDacInterface3_GetGCGlobalMechanisms(This,globalMechanisms) \ ( (This)->lpVtbl -> GetGCGlobalMechanisms(This,globalMechanisms) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface3_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface4_INTERFACE_DEFINED__ #define __ISOSDacInterface4_INTERFACE_DEFINED__ /* interface ISOSDacInterface4 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("74B9D34C-A612-4B07-93DD-5462178FCE11") ISOSDacInterface4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetClrNotification( CLRDATA_ADDRESS arguments[ ], int count, int *pNeeded) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface4 * This); HRESULT ( STDMETHODCALLTYPE *GetClrNotification )( ISOSDacInterface4 * This, CLRDATA_ADDRESS arguments[ ], int count, int *pNeeded); END_INTERFACE } ISOSDacInterface4Vtbl; interface ISOSDacInterface4 { CONST_VTBL struct ISOSDacInterface4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface4_GetClrNotification(This,arguments,count,pNeeded) \ ( (This)->lpVtbl -> GetClrNotification(This,arguments,count,pNeeded) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface4_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface5_INTERFACE_DEFINED__ #define __ISOSDacInterface5_INTERFACE_DEFINED__ /* interface ISOSDacInterface5 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("127d6abe-6c86-4e48-8e7b-220781c58101") ISOSDacInterface5 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetTieredVersions( CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface5 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface5 * This); HRESULT ( STDMETHODCALLTYPE *GetTieredVersions )( ISOSDacInterface5 * This, CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpTieredVersionData *nativeCodeAddrs, int cNativeCodeAddrs, int *pcNativeCodeAddrs); END_INTERFACE } ISOSDacInterface5Vtbl; interface ISOSDacInterface5 { CONST_VTBL struct ISOSDacInterface5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface5_GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs,pcNativeCodeAddrs) \ ( (This)->lpVtbl -> GetTieredVersions(This,methodDesc,rejitId,nativeCodeAddrs,cNativeCodeAddrs,pcNativeCodeAddrs) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface5_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface6_INTERFACE_DEFINED__ #define __ISOSDacInterface6_INTERFACE_DEFINED__ /* interface ISOSDacInterface6 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface6; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("11206399-4B66-4EDB-98EA-85654E59AD45") ISOSDacInterface6 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetMethodTableCollectibleData( CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface6Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface6 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface6 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface6 * This); HRESULT ( STDMETHODCALLTYPE *GetMethodTableCollectibleData )( ISOSDacInterface6 * This, CLRDATA_ADDRESS mt, struct DacpMethodTableCollectibleData *data); END_INTERFACE } ISOSDacInterface6Vtbl; interface ISOSDacInterface6 { CONST_VTBL struct ISOSDacInterface6Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface6_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface6_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface6_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface6_GetMethodTableCollectibleData(This,mt,data) \ ( (This)->lpVtbl -> GetMethodTableCollectibleData(This,mt,data) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface6_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface7_INTERFACE_DEFINED__ #define __ISOSDacInterface7_INTERFACE_DEFINED__ /* interface ISOSDacInterface7 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface7; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("c1020dde-fe98-4536-a53b-f35a74c327eb") ISOSDacInterface7 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetPendingReJITID( CLRDATA_ADDRESS methodDesc, int *pRejitId) = 0; virtual HRESULT STDMETHODCALLTYPE GetReJITInformation( CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpReJitData2 *pRejitData) = 0; virtual HRESULT STDMETHODCALLTYPE GetProfilerModifiedILInformation( CLRDATA_ADDRESS methodDesc, struct DacpProfilerILData *pILData) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodsWithProfilerModifiedIL( CLRDATA_ADDRESS mod, CLRDATA_ADDRESS *methodDescs, int cMethodDescs, int *pcMethodDescs) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface7Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface7 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface7 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface7 * This); HRESULT ( STDMETHODCALLTYPE *GetPendingReJITID )( ISOSDacInterface7 * This, CLRDATA_ADDRESS methodDesc, int *pRejitId); HRESULT ( STDMETHODCALLTYPE *GetReJITInformation )( ISOSDacInterface7 * This, CLRDATA_ADDRESS methodDesc, int rejitId, struct DacpReJitData2 *pRejitData); HRESULT ( STDMETHODCALLTYPE *GetProfilerModifiedILInformation )( ISOSDacInterface7 * This, CLRDATA_ADDRESS methodDesc, struct DacpProfilerILData *pILData); HRESULT ( STDMETHODCALLTYPE *GetMethodsWithProfilerModifiedIL )( ISOSDacInterface7 * This, CLRDATA_ADDRESS mod, CLRDATA_ADDRESS *methodDescs, int cMethodDescs, int *pcMethodDescs); END_INTERFACE } ISOSDacInterface7Vtbl; interface ISOSDacInterface7 { CONST_VTBL struct ISOSDacInterface7Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface7_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface7_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface7_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface7_GetPendingReJITID(This,methodDesc,pRejitId) \ ( (This)->lpVtbl -> GetPendingReJITID(This,methodDesc,pRejitId) ) #define ISOSDacInterface7_GetReJITInformation(This,methodDesc,rejitId,pRejitData) \ ( (This)->lpVtbl -> GetReJITInformation(This,methodDesc,rejitId,pRejitData) ) #define ISOSDacInterface7_GetProfilerModifiedILInformation(This,methodDesc,pILData) \ ( (This)->lpVtbl -> GetProfilerModifiedILInformation(This,methodDesc,pILData) ) #define ISOSDacInterface7_GetMethodsWithProfilerModifiedIL(This,mod,methodDescs,cMethodDescs,pcMethodDescs) \ ( (This)->lpVtbl -> GetMethodsWithProfilerModifiedIL(This,mod,methodDescs,cMethodDescs,pcMethodDescs) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface7_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface8_INTERFACE_DEFINED__ #define __ISOSDacInterface8_INTERFACE_DEFINED__ /* interface ISOSDacInterface8 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface8; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("c12f35a9-e55c-4520-a894-b3dc5165dfce") ISOSDacInterface8 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetNumberGenerations( unsigned int *pGenerations) = 0; virtual HRESULT STDMETHODCALLTYPE GetGenerationTable( unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetFinalizationFillPointers( unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetGenerationTableSvr( CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetFinalizationFillPointersSvr( CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssemblyLoadContext( CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS* assemblyLoadContext) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface8Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface8 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface8 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface8 * This); HRESULT ( STDMETHODCALLTYPE *GetNumberGenerations )( ISOSDacInterface8 * This, unsigned int *pGenerations); HRESULT ( STDMETHODCALLTYPE *GetGenerationTable )( ISOSDacInterface8 * This, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetFinalizationFillPointers )( ISOSDacInterface8 * This, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetGenerationTableSvr )( ISOSDacInterface8 * This, CLRDATA_ADDRESS heapAddr, unsigned int cGenerations, struct DacpGenerationData *pGenerationData, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetFinalizationFillPointersSvr )( ISOSDacInterface8 * This, CLRDATA_ADDRESS heapAddr, unsigned int cFillPointers, CLRDATA_ADDRESS *pFinalizationFillPointers, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *GetAssemblyLoadContext )( ISOSDacInterface8 * This, CLRDATA_ADDRESS methodTable, CLRDATA_ADDRESS *assemblyLoadContext); END_INTERFACE } ISOSDacInterface8Vtbl; interface ISOSDacInterface8 { CONST_VTBL struct ISOSDacInterface8Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface8_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface8_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface8_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface8_GetNumberGenerations(This,pGenerations) \ ( (This)->lpVtbl -> GetNumberGenerations(This,pGenerations) ) #define ISOSDacInterface8_GetGenerationTable(This,cGenerations,pGenerationData,pNeeded) \ ( (This)->lpVtbl -> GetGenerationTable(This,cGenerations,pGenerationData,pNeeded) ) #define ISOSDacInterface8_GetFinalizationFillPointers(This,cFillPointers,pFinalizationFillPointers,pNeeded) \ ( (This)->lpVtbl -> GetFinalizationFillPointers(This,cFillPointers,pFinalizationFillPointers,pNeeded) ) #define ISOSDacInterface8_GetGenerationTableSvr(This,heapAddr,cGenerations,pGenerationData,pNeeded) \ ( (This)->lpVtbl -> GetGenerationTableSvr(This,heapAddr,cGenerations,pGenerationData,pNeeded) ) #define ISOSDacInterface8_GetFinalizationFillPointersSvr(This,heapAddr,cFillPointers,pFinalizationFillPointers,pNeeded) \ ( (This)->lpVtbl -> GetFinalizationFillPointersSvr(This,heapAddr,cFillPointers,pFinalizationFillPointers,pNeeded) ) #define ISOSDacInterface8_GetAssemblyLoadContext(This,methodTable,assemblyLoadContext) \ ( (This)->lpVtbl -> GetAssemblyLoadContext(This,methodTable,assemblyLoadContext) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface8_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_sospriv_0000_0012 */ /* [local] */ #define SOS_BREAKING_CHANGE_VERSION 3 extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0012_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_sospriv_0000_0012_v0_0_s_ifspec; #ifndef __ISOSDacInterface9_INTERFACE_DEFINED__ #define __ISOSDacInterface9_INTERFACE_DEFINED__ /* interface ISOSDacInterface9 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface9; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("4eca42d8-7e7b-4c8a-a116-7bfbf6929267") ISOSDacInterface9 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetBreakingChangeVersion( int *pVersion) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface9Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface9 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface9 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface9 * This); HRESULT ( STDMETHODCALLTYPE *GetBreakingChangeVersion )( ISOSDacInterface9 * This, int *pVersion); END_INTERFACE } ISOSDacInterface9Vtbl; interface ISOSDacInterface9 { CONST_VTBL struct ISOSDacInterface9Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface9_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface9_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface9_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface9_GetBreakingChangeVersion(This,pVersion) \ ( (This)->lpVtbl -> GetBreakingChangeVersion(This,pVersion) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface9_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface10_INTERFACE_DEFINED__ #define __ISOSDacInterface10_INTERFACE_DEFINED__ /* interface ISOSDacInterface10 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface10; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("90B8FCC3-7251-4B0A-AE3D-5C13A67EC9AA") ISOSDacInterface10 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetObjectComWrappersData( CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS *rcw, unsigned int count, CLRDATA_ADDRESS *mowList, unsigned int *pNeeded) = 0; virtual HRESULT STDMETHODCALLTYPE IsComWrappersCCW( CLRDATA_ADDRESS ccw, BOOL *isComWrappersCCW) = 0; virtual HRESULT STDMETHODCALLTYPE GetComWrappersCCWData( CLRDATA_ADDRESS ccw, CLRDATA_ADDRESS *managedObject, int *refCount) = 0; virtual HRESULT STDMETHODCALLTYPE IsComWrappersRCW( CLRDATA_ADDRESS rcw, BOOL *isComWrappersRCW) = 0; virtual HRESULT STDMETHODCALLTYPE GetComWrappersRCWData( CLRDATA_ADDRESS rcw, CLRDATA_ADDRESS *identity) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface10Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface10 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface10 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface10 * This); HRESULT ( STDMETHODCALLTYPE *GetObjectComWrappersData )( ISOSDacInterface10 * This, CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS *rcw, unsigned int count, CLRDATA_ADDRESS *mowList, unsigned int *pNeeded); HRESULT ( STDMETHODCALLTYPE *IsComWrappersCCW )( ISOSDacInterface10 * This, CLRDATA_ADDRESS ccw, BOOL *isComWrappersCCW); HRESULT ( STDMETHODCALLTYPE *GetComWrappersCCWData )( ISOSDacInterface10 * This, CLRDATA_ADDRESS ccw, CLRDATA_ADDRESS *managedObject, int *refCount); HRESULT ( STDMETHODCALLTYPE *IsComWrappersRCW )( ISOSDacInterface10 * This, CLRDATA_ADDRESS rcw, BOOL *isComWrappersRCW); HRESULT ( STDMETHODCALLTYPE *GetComWrappersRCWData )( ISOSDacInterface10 * This, CLRDATA_ADDRESS rcw, CLRDATA_ADDRESS *identity); END_INTERFACE } ISOSDacInterface10Vtbl; interface ISOSDacInterface10 { CONST_VTBL struct ISOSDacInterface10Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface10_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface10_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface10_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface10_GetObjectComWrappersData(This,objAddr,rcw,count,mowList,pNeeded) \ ( (This)->lpVtbl -> GetObjectComWrappersData(This,objAddr,rcw,count,mowList,pNeeded) ) #define ISOSDacInterface10_IsComWrappersCCW(This,ccw,isComWrappersCCW) \ ( (This)->lpVtbl -> IsComWrappersCCW(This,ccw,isComWrappersCCW) ) #define ISOSDacInterface10_GetComWrappersCCWData(This,ccw,managedObject,refCount) \ ( (This)->lpVtbl -> GetComWrappersCCWData(This,ccw,managedObject,refCount) ) #define ISOSDacInterface10_IsComWrappersRCW(This,rcw,isComWrappersRCW) \ ( (This)->lpVtbl -> IsComWrappersRCW(This,rcw,isComWrappersRCW) ) #define ISOSDacInterface10_GetComWrappersRCWData(This,rcw,identity) \ ( (This)->lpVtbl -> GetComWrappersRCWData(This,rcw,identity) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface10_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface11_INTERFACE_DEFINED__ #define __ISOSDacInterface11_INTERFACE_DEFINED__ /* interface ISOSDacInterface11 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface11; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("96BA1DB9-14CD-4492-8065-1CAAECF6E5CF") ISOSDacInterface11 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE IsTrackedType( CLRDATA_ADDRESS objAddr, BOOL *isTrackedType, BOOL *hasTaggedMemory) = 0; virtual HRESULT STDMETHODCALLTYPE GetTaggedMemory( CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS *taggedMemory, size_t *taggedMemorySizeInBytes) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface11Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface11 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface11 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface11 * This); HRESULT ( STDMETHODCALLTYPE *IsTrackedType )( ISOSDacInterface11 * This, CLRDATA_ADDRESS objAddr, BOOL *isTrackedType, BOOL *hasTaggedMemory); HRESULT ( STDMETHODCALLTYPE *GetTaggedMemory )( ISOSDacInterface11 * This, CLRDATA_ADDRESS objAddr, CLRDATA_ADDRESS *taggedMemory, size_t *taggedMemorySizeInBytes); END_INTERFACE } ISOSDacInterface11Vtbl; interface ISOSDacInterface11 { CONST_VTBL struct ISOSDacInterface11Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface11_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface11_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface11_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface11_IsTrackedType(This,objAddr,isTrackedType,hasTaggedMemory) \ ( (This)->lpVtbl -> IsTrackedType(This,objAddr,isTrackedType,hasTaggedMemory) ) #define ISOSDacInterface11_GetTaggedMemory(This,objAddr,taggedMemory,taggedMemorySizeInBytes) \ ( (This)->lpVtbl -> GetTaggedMemory(This,objAddr,taggedMemory,taggedMemorySizeInBytes) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface11_INTERFACE_DEFINED__ */ #ifndef __ISOSDacInterface12_INTERFACE_DEFINED__ #define __ISOSDacInterface12_INTERFACE_DEFINED__ /* interface ISOSDacInterface12 */ /* [uuid][local][object] */ EXTERN_C const IID IID_ISOSDacInterface12; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("1b93bacc-8ca4-432d-943a-3e6e7ec0b0a3") ISOSDacInterface12 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetGlobalAllocationContext( CLRDATA_ADDRESS *allocPtr, CLRDATA_ADDRESS *allocLimit) = 0; }; #else /* C style interface */ typedef struct ISOSDacInterface12Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ISOSDacInterface12 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ISOSDacInterface12 * This); ULONG ( STDMETHODCALLTYPE *Release )( ISOSDacInterface12 * This); HRESULT ( STDMETHODCALLTYPE *GetGlobalAllocationContext )( ISOSDacInterface12 * This, CLRDATA_ADDRESS *allocPtr, CLRDATA_ADDRESS *allocLimit); END_INTERFACE } ISOSDacInterface12Vtbl; interface ISOSDacInterface12 { CONST_VTBL struct ISOSDacInterface12Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ISOSDacInterface12_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ISOSDacInterface12_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ISOSDacInterface12_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ISOSDacInterface12_GetGlobalAllocationContext(This,allocPtr,allocLimit) \ ( (This)->lpVtbl -> GetGlobalAllocationContext(This,allocPtr,allocLimit) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ISOSDacInterface12_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/xclrdata.h ================================================ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.00.0603 */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif // __RPCNDR_H_VERSION__ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __xclrdata_h__ #define __xclrdata_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __IXCLRDataTarget3_FWD_DEFINED__ #define __IXCLRDataTarget3_FWD_DEFINED__ typedef interface IXCLRDataTarget3 IXCLRDataTarget3; #endif /* __IXCLRDataTarget3_FWD_DEFINED__ */ #ifndef __IXCLRLibrarySupport_FWD_DEFINED__ #define __IXCLRLibrarySupport_FWD_DEFINED__ typedef interface IXCLRLibrarySupport IXCLRLibrarySupport; #endif /* __IXCLRLibrarySupport_FWD_DEFINED__ */ #ifndef __IXCLRDisassemblySupport_FWD_DEFINED__ #define __IXCLRDisassemblySupport_FWD_DEFINED__ typedef interface IXCLRDisassemblySupport IXCLRDisassemblySupport; #endif /* __IXCLRDisassemblySupport_FWD_DEFINED__ */ #ifndef __IXCLRDataDisplay_FWD_DEFINED__ #define __IXCLRDataDisplay_FWD_DEFINED__ typedef interface IXCLRDataDisplay IXCLRDataDisplay; #endif /* __IXCLRDataDisplay_FWD_DEFINED__ */ #ifndef __IXCLRDataProcess_FWD_DEFINED__ #define __IXCLRDataProcess_FWD_DEFINED__ typedef interface IXCLRDataProcess IXCLRDataProcess; #endif /* __IXCLRDataProcess_FWD_DEFINED__ */ #ifndef __IXCLRDataProcess2_FWD_DEFINED__ #define __IXCLRDataProcess2_FWD_DEFINED__ typedef interface IXCLRDataProcess2 IXCLRDataProcess2; #endif /* __IXCLRDataProcess2_FWD_DEFINED__ */ #ifndef __IXCLRDataAppDomain_FWD_DEFINED__ #define __IXCLRDataAppDomain_FWD_DEFINED__ typedef interface IXCLRDataAppDomain IXCLRDataAppDomain; #endif /* __IXCLRDataAppDomain_FWD_DEFINED__ */ #ifndef __IXCLRDataAssembly_FWD_DEFINED__ #define __IXCLRDataAssembly_FWD_DEFINED__ typedef interface IXCLRDataAssembly IXCLRDataAssembly; #endif /* __IXCLRDataAssembly_FWD_DEFINED__ */ #ifndef __IXCLRDataModule_FWD_DEFINED__ #define __IXCLRDataModule_FWD_DEFINED__ typedef interface IXCLRDataModule IXCLRDataModule; #endif /* __IXCLRDataModule_FWD_DEFINED__ */ #ifndef __IXCLRDataModule2_FWD_DEFINED__ #define __IXCLRDataModule2_FWD_DEFINED__ typedef interface IXCLRDataModule2 IXCLRDataModule2; #endif /* __IXCLRDataModule2_FWD_DEFINED__ */ #ifndef __IXCLRDataTypeDefinition_FWD_DEFINED__ #define __IXCLRDataTypeDefinition_FWD_DEFINED__ typedef interface IXCLRDataTypeDefinition IXCLRDataTypeDefinition; #endif /* __IXCLRDataTypeDefinition_FWD_DEFINED__ */ #ifndef __IXCLRDataTypeInstance_FWD_DEFINED__ #define __IXCLRDataTypeInstance_FWD_DEFINED__ typedef interface IXCLRDataTypeInstance IXCLRDataTypeInstance; #endif /* __IXCLRDataTypeInstance_FWD_DEFINED__ */ #ifndef __IXCLRDataMethodDefinition_FWD_DEFINED__ #define __IXCLRDataMethodDefinition_FWD_DEFINED__ typedef interface IXCLRDataMethodDefinition IXCLRDataMethodDefinition; #endif /* __IXCLRDataMethodDefinition_FWD_DEFINED__ */ #ifndef __IXCLRDataMethodInstance_FWD_DEFINED__ #define __IXCLRDataMethodInstance_FWD_DEFINED__ typedef interface IXCLRDataMethodInstance IXCLRDataMethodInstance; #endif /* __IXCLRDataMethodInstance_FWD_DEFINED__ */ #ifndef __IXCLRDataTask_FWD_DEFINED__ #define __IXCLRDataTask_FWD_DEFINED__ typedef interface IXCLRDataTask IXCLRDataTask; #endif /* __IXCLRDataTask_FWD_DEFINED__ */ #ifndef __IXCLRDataStackWalk_FWD_DEFINED__ #define __IXCLRDataStackWalk_FWD_DEFINED__ typedef interface IXCLRDataStackWalk IXCLRDataStackWalk; #endif /* __IXCLRDataStackWalk_FWD_DEFINED__ */ #ifndef __IXCLRDataFrame_FWD_DEFINED__ #define __IXCLRDataFrame_FWD_DEFINED__ typedef interface IXCLRDataFrame IXCLRDataFrame; #endif /* __IXCLRDataFrame_FWD_DEFINED__ */ #ifndef __IXCLRDataFrame2_FWD_DEFINED__ #define __IXCLRDataFrame2_FWD_DEFINED__ typedef interface IXCLRDataFrame2 IXCLRDataFrame2; #endif /* __IXCLRDataFrame2_FWD_DEFINED__ */ #ifndef __IXCLRDataExceptionState_FWD_DEFINED__ #define __IXCLRDataExceptionState_FWD_DEFINED__ typedef interface IXCLRDataExceptionState IXCLRDataExceptionState; #endif /* __IXCLRDataExceptionState_FWD_DEFINED__ */ #ifndef __IXCLRDataValue_FWD_DEFINED__ #define __IXCLRDataValue_FWD_DEFINED__ typedef interface IXCLRDataValue IXCLRDataValue; #endif /* __IXCLRDataValue_FWD_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification_FWD_DEFINED__ #define __IXCLRDataExceptionNotification_FWD_DEFINED__ typedef interface IXCLRDataExceptionNotification IXCLRDataExceptionNotification; #endif /* __IXCLRDataExceptionNotification_FWD_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification2_FWD_DEFINED__ #define __IXCLRDataExceptionNotification2_FWD_DEFINED__ typedef interface IXCLRDataExceptionNotification2 IXCLRDataExceptionNotification2; #endif /* __IXCLRDataExceptionNotification2_FWD_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification3_FWD_DEFINED__ #define __IXCLRDataExceptionNotification3_FWD_DEFINED__ typedef interface IXCLRDataExceptionNotification3 IXCLRDataExceptionNotification3; #endif /* __IXCLRDataExceptionNotification3_FWD_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification4_FWD_DEFINED__ #define __IXCLRDataExceptionNotification4_FWD_DEFINED__ typedef interface IXCLRDataExceptionNotification4 IXCLRDataExceptionNotification4; #endif /* __IXCLRDataExceptionNotification4_FWD_DEFINED__ */ /* header files for imported files */ #include "clrdata.h" #ifdef __cplusplus extern "C"{ #endif /* interface __MIDL_itf_xclrdata_0000_0000 */ /* [local] */ #if 0 typedef UINT32 mdToken; typedef mdToken mdTypeDef; typedef mdToken mdMethodDef; typedef mdToken mdFieldDef; typedef ULONG CorElementType; typedef struct _EXCEPTION_RECORD64 { DWORD ExceptionCode; DWORD ExceptionFlags; DWORD64 ExceptionRecord; DWORD64 ExceptionAddress; DWORD NumberParameters; DWORD __unusedAlignment; DWORD64 ExceptionInformation[ 15 ]; } EXCEPTION_RECORD64; typedef struct _EXCEPTION_RECORD64 *PEXCEPTION_RECORD64; #endif #pragma warning(push) #pragma warning(disable:28718) #pragma warning(pop) typedef /* [public][public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0000_0001 { CLRDATA_ADDRESS startAddress; CLRDATA_ADDRESS endAddress; } CLRDATA_ADDRESS_RANGE; typedef ULONG64 CLRDATA_ENUM; #define CLRDATA_NOTIFY_EXCEPTION 0xe0444143 typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0000_0002 { CLRDATA_REQUEST_REVISION = 0xe0000000 } CLRDataGeneralRequest; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0000_0003 { CLRDATA_TYPE_DEFAULT = 0, CLRDATA_TYPE_IS_PRIMITIVE = 0x1, CLRDATA_TYPE_IS_VALUE_TYPE = 0x2, CLRDATA_TYPE_IS_STRING = 0x4, CLRDATA_TYPE_IS_ARRAY = 0x8, CLRDATA_TYPE_IS_REFERENCE = 0x10, CLRDATA_TYPE_IS_POINTER = 0x20, CLRDATA_TYPE_IS_ENUM = 0x40, CLRDATA_TYPE_ALL_KINDS = 0x7f } CLRDataTypeFlag; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0000_0004 { CLRDATA_FIELD_DEFAULT = 0, CLRDATA_FIELD_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, CLRDATA_FIELD_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, CLRDATA_FIELD_IS_STRING = CLRDATA_TYPE_IS_STRING, CLRDATA_FIELD_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, CLRDATA_FIELD_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, CLRDATA_FIELD_IS_POINTER = CLRDATA_TYPE_IS_POINTER, CLRDATA_FIELD_IS_ENUM = CLRDATA_TYPE_IS_ENUM, CLRDATA_FIELD_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, CLRDATA_FIELD_IS_INHERITED = 0x80, CLRDATA_FIELD_IS_LITERAL = 0x100, CLRDATA_FIELD_FROM_INSTANCE = 0x200, CLRDATA_FIELD_FROM_TASK_LOCAL = 0x400, CLRDATA_FIELD_FROM_STATIC = 0x800, CLRDATA_FIELD_ALL_LOCATIONS = 0xe00, CLRDATA_FIELD_ALL_FIELDS = 0xeff } CLRDataFieldFlag; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0000_0005 { CLRDATA_VALUE_DEFAULT = 0, CLRDATA_VALUE_IS_PRIMITIVE = CLRDATA_TYPE_IS_PRIMITIVE, CLRDATA_VALUE_IS_VALUE_TYPE = CLRDATA_TYPE_IS_VALUE_TYPE, CLRDATA_VALUE_IS_STRING = CLRDATA_TYPE_IS_STRING, CLRDATA_VALUE_IS_ARRAY = CLRDATA_TYPE_IS_ARRAY, CLRDATA_VALUE_IS_REFERENCE = CLRDATA_TYPE_IS_REFERENCE, CLRDATA_VALUE_IS_POINTER = CLRDATA_TYPE_IS_POINTER, CLRDATA_VALUE_IS_ENUM = CLRDATA_TYPE_IS_ENUM, CLRDATA_VALUE_ALL_KINDS = CLRDATA_TYPE_ALL_KINDS, CLRDATA_VALUE_IS_INHERITED = CLRDATA_FIELD_IS_INHERITED, CLRDATA_VALUE_IS_LITERAL = CLRDATA_FIELD_IS_LITERAL, CLRDATA_VALUE_FROM_INSTANCE = CLRDATA_FIELD_FROM_INSTANCE, CLRDATA_VALUE_FROM_TASK_LOCAL = CLRDATA_FIELD_FROM_TASK_LOCAL, CLRDATA_VALUE_FROM_STATIC = CLRDATA_FIELD_FROM_STATIC, CLRDATA_VALUE_ALL_LOCATIONS = CLRDATA_FIELD_ALL_LOCATIONS, CLRDATA_VALUE_ALL_FIELDS = CLRDATA_FIELD_ALL_FIELDS, CLRDATA_VALUE_IS_BOXED = 0x1000 } CLRDataValueFlag; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0000_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0000_v0_0_s_ifspec; #ifndef __IXCLRDataTarget3_INTERFACE_DEFINED__ #define __IXCLRDataTarget3_INTERFACE_DEFINED__ /* interface IXCLRDataTarget3 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataTarget3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("59d9b5e1-4a6f-4531-84c3-51d12da22fd4") IXCLRDataTarget3 : public ICLRDataTarget2 { public: virtual HRESULT STDMETHODCALLTYPE GetMetaData( /* [in] */ LPCWSTR imagePath, /* [in] */ ULONG32 imageTimestamp, /* [in] */ ULONG32 imageSize, /* [in] */ GUID *mvid, /* [in] */ ULONG32 mdRva, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufferSize, /* [length_is][size_is][out] */ BYTE *buffer, /* [out] */ ULONG32 *dataSize) = 0; }; #else /* C style interface */ typedef struct IXCLRDataTarget3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataTarget3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataTarget3 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataTarget3 * This); HRESULT ( STDMETHODCALLTYPE *GetMachineType )( IXCLRDataTarget3 * This, /* [out] */ ULONG32 *machineType); HRESULT ( STDMETHODCALLTYPE *GetPointerSize )( IXCLRDataTarget3 * This, /* [out] */ ULONG32 *pointerSize); HRESULT ( STDMETHODCALLTYPE *GetImageBase )( IXCLRDataTarget3 * This, /* [string][in] */ LPCWSTR imagePath, /* [out] */ CLRDATA_ADDRESS *baseAddress); HRESULT ( STDMETHODCALLTYPE *ReadVirtual )( IXCLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS address, /* [length_is][size_is][out] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesRead); HRESULT ( STDMETHODCALLTYPE *WriteVirtual )( IXCLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS address, /* [size_is][in] */ BYTE *buffer, /* [in] */ ULONG32 bytesRequested, /* [out] */ ULONG32 *bytesWritten); HRESULT ( STDMETHODCALLTYPE *GetTLSValue )( IXCLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [out] */ CLRDATA_ADDRESS *value); HRESULT ( STDMETHODCALLTYPE *SetTLSValue )( IXCLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 index, /* [in] */ CLRDATA_ADDRESS value); HRESULT ( STDMETHODCALLTYPE *GetCurrentThreadID )( IXCLRDataTarget3 * This, /* [out] */ ULONG32 *threadID); HRESULT ( STDMETHODCALLTYPE *GetThreadContext )( IXCLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextSize, /* [size_is][out] */ BYTE *context); HRESULT ( STDMETHODCALLTYPE *SetThreadContext )( IXCLRDataTarget3 * This, /* [in] */ ULONG32 threadID, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE *context); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataTarget3 * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *AllocVirtual )( IXCLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags, /* [in] */ ULONG32 protectFlags, /* [out] */ CLRDATA_ADDRESS *virt); HRESULT ( STDMETHODCALLTYPE *FreeVirtual )( IXCLRDataTarget3 * This, /* [in] */ CLRDATA_ADDRESS addr, /* [in] */ ULONG32 size, /* [in] */ ULONG32 typeFlags); HRESULT ( STDMETHODCALLTYPE *GetMetaData )( IXCLRDataTarget3 * This, /* [in] */ LPCWSTR imagePath, /* [in] */ ULONG32 imageTimestamp, /* [in] */ ULONG32 imageSize, /* [in] */ GUID *mvid, /* [in] */ ULONG32 mdRva, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufferSize, /* [length_is][size_is][out] */ BYTE *buffer, /* [out] */ ULONG32 *dataSize); END_INTERFACE } IXCLRDataTarget3Vtbl; interface IXCLRDataTarget3 { CONST_VTBL struct IXCLRDataTarget3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataTarget3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataTarget3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataTarget3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataTarget3_GetMachineType(This,machineType) \ ( (This)->lpVtbl -> GetMachineType(This,machineType) ) #define IXCLRDataTarget3_GetPointerSize(This,pointerSize) \ ( (This)->lpVtbl -> GetPointerSize(This,pointerSize) ) #define IXCLRDataTarget3_GetImageBase(This,imagePath,baseAddress) \ ( (This)->lpVtbl -> GetImageBase(This,imagePath,baseAddress) ) #define IXCLRDataTarget3_ReadVirtual(This,address,buffer,bytesRequested,bytesRead) \ ( (This)->lpVtbl -> ReadVirtual(This,address,buffer,bytesRequested,bytesRead) ) #define IXCLRDataTarget3_WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) \ ( (This)->lpVtbl -> WriteVirtual(This,address,buffer,bytesRequested,bytesWritten) ) #define IXCLRDataTarget3_GetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> GetTLSValue(This,threadID,index,value) ) #define IXCLRDataTarget3_SetTLSValue(This,threadID,index,value) \ ( (This)->lpVtbl -> SetTLSValue(This,threadID,index,value) ) #define IXCLRDataTarget3_GetCurrentThreadID(This,threadID) \ ( (This)->lpVtbl -> GetCurrentThreadID(This,threadID) ) #define IXCLRDataTarget3_GetThreadContext(This,threadID,contextFlags,contextSize,context) \ ( (This)->lpVtbl -> GetThreadContext(This,threadID,contextFlags,contextSize,context) ) #define IXCLRDataTarget3_SetThreadContext(This,threadID,contextSize,context) \ ( (This)->lpVtbl -> SetThreadContext(This,threadID,contextSize,context) ) #define IXCLRDataTarget3_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataTarget3_AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) \ ( (This)->lpVtbl -> AllocVirtual(This,addr,size,typeFlags,protectFlags,virt) ) #define IXCLRDataTarget3_FreeVirtual(This,addr,size,typeFlags) \ ( (This)->lpVtbl -> FreeVirtual(This,addr,size,typeFlags) ) #define IXCLRDataTarget3_GetMetaData(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) \ ( (This)->lpVtbl -> GetMetaData(This,imagePath,imageTimestamp,imageSize,mvid,mdRva,flags,bufferSize,buffer,dataSize) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataTarget3_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0001 */ /* [local] */ typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0001 { CLRDATA_BYNAME_CASE_SENSITIVE = 0, CLRDATA_BYNAME_CASE_INSENSITIVE = 0x1 } CLRDataByNameFlag; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0002 { CLRDATA_GETNAME_DEFAULT = 0, CLRDATA_GETNAME_NO_NAMESPACES = 0x1, CLRDATA_GETNAME_NO_PARAMETERS = 0x2 } CLRDataGetNameFlag; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0003 { CLRDATA_PROCESS_DEFAULT = 0, CLRDATA_PROCESS_IN_GC = 0x1 } CLRDataProcessFlag; typedef /* [public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0004 { CLRDATA_ADDRESS_UNRECOGNIZED = 0, CLRDATA_ADDRESS_MANAGED_METHOD = ( CLRDATA_ADDRESS_UNRECOGNIZED + 1 ) , CLRDATA_ADDRESS_RUNTIME_MANAGED_CODE = ( CLRDATA_ADDRESS_MANAGED_METHOD + 1 ) , CLRDATA_ADDRESS_RUNTIME_UNMANAGED_CODE = ( CLRDATA_ADDRESS_RUNTIME_MANAGED_CODE + 1 ) , CLRDATA_ADDRESS_GC_DATA = ( CLRDATA_ADDRESS_RUNTIME_UNMANAGED_CODE + 1 ) , CLRDATA_ADDRESS_RUNTIME_MANAGED_STUB = ( CLRDATA_ADDRESS_GC_DATA + 1 ) , CLRDATA_ADDRESS_RUNTIME_UNMANAGED_STUB = ( CLRDATA_ADDRESS_RUNTIME_MANAGED_STUB + 1 ) } CLRDataAddressType; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0005 { CLRDATA_NOTIFY_ON_MODULE_LOAD = 0x1, CLRDATA_NOTIFY_ON_MODULE_UNLOAD = 0x2, CLRDATA_NOTIFY_ON_EXCEPTION = 0x4, CLRDATA_NOTIFY_ON_EXCEPTION_CATCH_ENTER = 0x8 } CLRDataOtherNotifyFlag; typedef /* [public][public][public][public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0001_0006 { ULONG64 Data[ 8 ]; } CLRDATA_FOLLOW_STUB_BUFFER; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0007 { CLRDATA_FOLLOW_STUB_DEFAULT = 0 } CLRDataFollowStubInFlag; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0008 { CLRDATA_FOLLOW_STUB_INTERMEDIATE = 0, CLRDATA_FOLLOW_STUB_EXIT = 0x1 } CLRDataFollowStubOutFlag; typedef /* [public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0009 { CLRNATIVEIMAGE_PE_INFO = 0x1, CLRNATIVEIMAGE_COR_INFO = 0x2, CLRNATIVEIMAGE_FIXUP_TABLES = 0x4, CLRNATIVEIMAGE_FIXUP_HISTOGRAM = 0x8, CLRNATIVEIMAGE_MODULE = 0x10, CLRNATIVEIMAGE_METHODS = 0x20, CLRNATIVEIMAGE_DISASSEMBLE_CODE = 0x40, CLRNATIVEIMAGE_IL = 0x80, CLRNATIVEIMAGE_METHODTABLES = 0x100, CLRNATIVEIMAGE_NATIVE_INFO = 0x200, CLRNATIVEIMAGE_MODULE_TABLES = 0x400, CLRNATIVEIMAGE_FROZEN_SEGMENT = 0x800, CLRNATIVEIMAGE_PE_FILE = 0x1000, CLRNATIVEIMAGE_GC_INFO = 0x2000, CLRNATIVEIMAGE_EECLASSES = 0x4000, CLRNATIVEIMAGE_NATIVE_TABLES = 0x8000, CLRNATIVEIMAGE_PRECODES = 0x10000, CLRNATIVEIMAGE_TYPEDESCS = 0x20000, CLRNATIVEIMAGE_VERBOSE_TYPES = 0x40000, CLRNATIVEIMAGE_METHODDESCS = 0x80000, CLRNATIVEIMAGE_METADATA = 0x100000, CLRNATIVEIMAGE_DISABLE_NAMES = 0x200000, CLRNATIVEIMAGE_DISABLE_REBASING = 0x400000, CLRNATIVEIMAGE_SLIM_MODULE_TBLS = 0x800000, CLRNATIVEIMAGE_RESOURCES = 0x1000000, CLRNATIVEIMAGE_FILE_OFFSET = 0x2000000, CLRNATIVEIMAGE_DEBUG_TRACE = 0x4000000, CLRNATIVEIMAGE_RELOCATIONS = 0x8000000, CLRNATIVEIMAGE_FIXUP_THUNKS = 0x10000000, CLRNATIVEIMAGE_DEBUG_COVERAGE = 0x80000000 } CLRNativeImageDumpOptions; #ifdef __cplusplus inline CLRNativeImageDumpOptions operator|=(CLRNativeImageDumpOptions& lhs, CLRNativeImageDumpOptions rhs) { return (lhs = (CLRNativeImageDumpOptions)( ((unsigned)lhs) | ((unsigned)rhs) )); } #endif typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0001_0010 { CLRDATAHINT_DISPLAY_HINTS_NONE = 0, CLRDATAHINT_DISPLAY_ARRAY_AS_TABLE = 0x1, CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY = 0x2, CLRDATAHINT_DISPLAY_ARRAY_AS_ARRAY_IDX = 0x3, CLRDATAHINT_DISPLAY_ARRAY_AS_MAP = 0x4, CLRDATAHINT_DISPLAY_ARRAY_HINT_MASK = 0xff, CLRDATAHINT_DISPLAY_STRUCT_AS_TABLE = 0x100, CLRDATAHINT_DISPLAY_STRUCT_HINT_MASK = 0xff00, CLRDATAHINT_DISPLAY_SEP_TAB = 0, CLRDATAHINT_DISPLAY_SEP_SPACE = 0x1000000, CLRDATAHINT_DISPLAY_SEP_TAB_SPACE = 0x2000000, CLRDATAHINT_DISPLAY_SEP_MASK = 0xff000000 } CLRDataDisplayHints; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0001_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0001_v0_0_s_ifspec; #ifndef __IXCLRLibrarySupport_INTERFACE_DEFINED__ #define __IXCLRLibrarySupport_INTERFACE_DEFINED__ /* interface IXCLRLibrarySupport */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRLibrarySupport; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E5F3039D-2C0C-4230-A69E-12AF1C3E563C") IXCLRLibrarySupport : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE LoadHardboundDependency( const WCHAR *name, REFGUID mvid, /* [out] */ SIZE_T *loadedBase) = 0; virtual HRESULT STDMETHODCALLTYPE LoadSoftboundDependency( const WCHAR *name, const BYTE *assemblymetadataBinding, const BYTE *hash, ULONG hashLength, /* [out] */ SIZE_T *loadedBase) = 0; }; #else /* C style interface */ typedef struct IXCLRLibrarySupportVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRLibrarySupport * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRLibrarySupport * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRLibrarySupport * This); HRESULT ( STDMETHODCALLTYPE *LoadHardboundDependency )( IXCLRLibrarySupport * This, const WCHAR *name, REFGUID mvid, /* [out] */ SIZE_T *loadedBase); HRESULT ( STDMETHODCALLTYPE *LoadSoftboundDependency )( IXCLRLibrarySupport * This, const WCHAR *name, const BYTE *assemblymetadataBinding, const BYTE *hash, ULONG hashLength, /* [out] */ SIZE_T *loadedBase); END_INTERFACE } IXCLRLibrarySupportVtbl; interface IXCLRLibrarySupport { CONST_VTBL struct IXCLRLibrarySupportVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRLibrarySupport_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRLibrarySupport_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRLibrarySupport_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRLibrarySupport_LoadHardboundDependency(This,name,mvid,loadedBase) \ ( (This)->lpVtbl -> LoadHardboundDependency(This,name,mvid,loadedBase) ) #define IXCLRLibrarySupport_LoadSoftboundDependency(This,name,assemblymetadataBinding,hash,hashLength,loadedBase) \ ( (This)->lpVtbl -> LoadSoftboundDependency(This,name,assemblymetadataBinding,hash,hashLength,loadedBase) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRLibrarySupport_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0002 */ /* [local] */ typedef SIZE_T ( __stdcall *CDSTranslateAddrCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020000, CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020001, WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020002, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020003, DWORDLONG *__MIDL____MIDL_itf_xclrdata_0000_00020004); typedef SIZE_T ( __stdcall *CDSTranslateFixupCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020006, CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020007, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020008, WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020009, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020010, DWORDLONG *__MIDL____MIDL_itf_xclrdata_0000_00020011); typedef SIZE_T ( __stdcall *CDSTranslateConstCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020013, DWORD __MIDL____MIDL_itf_xclrdata_0000_00020014, WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020015, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020016); typedef SIZE_T ( __stdcall *CDSTranslateRegrelCB )( IXCLRDisassemblySupport *__MIDL____MIDL_itf_xclrdata_0000_00020018, unsigned int rega, CLRDATA_ADDRESS __MIDL____MIDL_itf_xclrdata_0000_00020019, WCHAR *__MIDL____MIDL_itf_xclrdata_0000_00020020, SIZE_T __MIDL____MIDL_itf_xclrdata_0000_00020021, DWORD *__MIDL____MIDL_itf_xclrdata_0000_00020022); extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0002_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0002_v0_0_s_ifspec; #ifndef __IXCLRDisassemblySupport_INTERFACE_DEFINED__ #define __IXCLRDisassemblySupport_INTERFACE_DEFINED__ /* interface IXCLRDisassemblySupport */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDisassemblySupport; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("1F0F7134-D3F3-47DE-8E9B-C2FD358A2936") IXCLRDisassemblySupport : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetTranslateAddrCallback( /* [in] */ CDSTranslateAddrCB cb) = 0; virtual HRESULT STDMETHODCALLTYPE PvClientSet( /* [in] */ void *pv) = 0; virtual SIZE_T STDMETHODCALLTYPE CbDisassemble( CLRDATA_ADDRESS __MIDL__IXCLRDisassemblySupport0000, const void *__MIDL__IXCLRDisassemblySupport0001, SIZE_T __MIDL__IXCLRDisassemblySupport0002) = 0; virtual SIZE_T STDMETHODCALLTYPE Cinstruction( void) = 0; virtual BOOL STDMETHODCALLTYPE FSelectInstruction( SIZE_T __MIDL__IXCLRDisassemblySupport0003) = 0; virtual SIZE_T STDMETHODCALLTYPE CchFormatInstr( WCHAR *__MIDL__IXCLRDisassemblySupport0004, SIZE_T __MIDL__IXCLRDisassemblySupport0005) = 0; virtual void *STDMETHODCALLTYPE PvClient( void) = 0; virtual HRESULT STDMETHODCALLTYPE SetTranslateFixupCallback( /* [in] */ CDSTranslateFixupCB cb) = 0; virtual HRESULT STDMETHODCALLTYPE SetTranslateConstCallback( /* [in] */ CDSTranslateConstCB cb) = 0; virtual HRESULT STDMETHODCALLTYPE SetTranslateRegrelCallback( /* [in] */ CDSTranslateRegrelCB cb) = 0; virtual BOOL STDMETHODCALLTYPE TargetIsAddress( void) = 0; }; #else /* C style interface */ typedef struct IXCLRDisassemblySupportVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDisassemblySupport * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDisassemblySupport * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDisassemblySupport * This); HRESULT ( STDMETHODCALLTYPE *SetTranslateAddrCallback )( IXCLRDisassemblySupport * This, /* [in] */ CDSTranslateAddrCB cb); HRESULT ( STDMETHODCALLTYPE *PvClientSet )( IXCLRDisassemblySupport * This, /* [in] */ void *pv); SIZE_T ( STDMETHODCALLTYPE *CbDisassemble )( IXCLRDisassemblySupport * This, CLRDATA_ADDRESS __MIDL__IXCLRDisassemblySupport0000, const void *__MIDL__IXCLRDisassemblySupport0001, SIZE_T __MIDL__IXCLRDisassemblySupport0002); SIZE_T ( STDMETHODCALLTYPE *Cinstruction )( IXCLRDisassemblySupport * This); BOOL ( STDMETHODCALLTYPE *FSelectInstruction )( IXCLRDisassemblySupport * This, SIZE_T __MIDL__IXCLRDisassemblySupport0003); SIZE_T ( STDMETHODCALLTYPE *CchFormatInstr )( IXCLRDisassemblySupport * This, WCHAR *__MIDL__IXCLRDisassemblySupport0004, SIZE_T __MIDL__IXCLRDisassemblySupport0005); void *( STDMETHODCALLTYPE *PvClient )( IXCLRDisassemblySupport * This); HRESULT ( STDMETHODCALLTYPE *SetTranslateFixupCallback )( IXCLRDisassemblySupport * This, /* [in] */ CDSTranslateFixupCB cb); HRESULT ( STDMETHODCALLTYPE *SetTranslateConstCallback )( IXCLRDisassemblySupport * This, /* [in] */ CDSTranslateConstCB cb); HRESULT ( STDMETHODCALLTYPE *SetTranslateRegrelCallback )( IXCLRDisassemblySupport * This, /* [in] */ CDSTranslateRegrelCB cb); BOOL ( STDMETHODCALLTYPE *TargetIsAddress )( IXCLRDisassemblySupport * This); END_INTERFACE } IXCLRDisassemblySupportVtbl; interface IXCLRDisassemblySupport { CONST_VTBL struct IXCLRDisassemblySupportVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDisassemblySupport_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDisassemblySupport_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDisassemblySupport_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDisassemblySupport_SetTranslateAddrCallback(This,cb) \ ( (This)->lpVtbl -> SetTranslateAddrCallback(This,cb) ) #define IXCLRDisassemblySupport_PvClientSet(This,pv) \ ( (This)->lpVtbl -> PvClientSet(This,pv) ) #define IXCLRDisassemblySupport_CbDisassemble(This,__MIDL__IXCLRDisassemblySupport0000,__MIDL__IXCLRDisassemblySupport0001,__MIDL__IXCLRDisassemblySupport0002) \ ( (This)->lpVtbl -> CbDisassemble(This,__MIDL__IXCLRDisassemblySupport0000,__MIDL__IXCLRDisassemblySupport0001,__MIDL__IXCLRDisassemblySupport0002) ) #define IXCLRDisassemblySupport_Cinstruction(This) \ ( (This)->lpVtbl -> Cinstruction(This) ) #define IXCLRDisassemblySupport_FSelectInstruction(This,__MIDL__IXCLRDisassemblySupport0003) \ ( (This)->lpVtbl -> FSelectInstruction(This,__MIDL__IXCLRDisassemblySupport0003) ) #define IXCLRDisassemblySupport_CchFormatInstr(This,__MIDL__IXCLRDisassemblySupport0004,__MIDL__IXCLRDisassemblySupport0005) \ ( (This)->lpVtbl -> CchFormatInstr(This,__MIDL__IXCLRDisassemblySupport0004,__MIDL__IXCLRDisassemblySupport0005) ) #define IXCLRDisassemblySupport_PvClient(This) \ ( (This)->lpVtbl -> PvClient(This) ) #define IXCLRDisassemblySupport_SetTranslateFixupCallback(This,cb) \ ( (This)->lpVtbl -> SetTranslateFixupCallback(This,cb) ) #define IXCLRDisassemblySupport_SetTranslateConstCallback(This,cb) \ ( (This)->lpVtbl -> SetTranslateConstCallback(This,cb) ) #define IXCLRDisassemblySupport_SetTranslateRegrelCallback(This,cb) \ ( (This)->lpVtbl -> SetTranslateRegrelCallback(This,cb) ) #define IXCLRDisassemblySupport_TargetIsAddress(This) \ ( (This)->lpVtbl -> TargetIsAddress(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDisassemblySupport_INTERFACE_DEFINED__ */ #ifndef __IXCLRDataDisplay_INTERFACE_DEFINED__ #define __IXCLRDataDisplay_INTERFACE_DEFINED__ /* interface IXCLRDataDisplay */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataDisplay; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A3C1704A-4559-4a67-8D28-E8F4FE3B3F62") IXCLRDataDisplay : public IUnknown { public: virtual HRESULT STDMETHODVCALLTYPE ErrorPrintF( const char *const fmt, ...) = 0; virtual HRESULT STDMETHODCALLTYPE NativeImageDimensions( SIZE_T base, SIZE_T size, DWORD sectionAlign) = 0; virtual HRESULT STDMETHODCALLTYPE Section( const char *const name, SIZE_T rva, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE GetDumpOptions( /* [out] */ CLRNativeImageDumpOptions *pOptions) = 0; virtual HRESULT STDMETHODCALLTYPE StartDocument( void) = 0; virtual HRESULT STDMETHODCALLTYPE EndDocument( void) = 0; virtual HRESULT STDMETHODCALLTYPE StartCategory( const char *const name) = 0; virtual HRESULT STDMETHODCALLTYPE EndCategory( void) = 0; virtual HRESULT STDMETHODCALLTYPE StartElement( const char *const name) = 0; virtual HRESULT STDMETHODCALLTYPE EndElement( void) = 0; virtual HRESULT STDMETHODCALLTYPE StartVStructure( const char *const name) = 0; virtual HRESULT STDMETHODCALLTYPE StartVStructureWithOffset( const char *const name, unsigned int fieldOffset, unsigned int fieldSize) = 0; virtual HRESULT STDMETHODCALLTYPE EndVStructure( void) = 0; virtual HRESULT STDMETHODCALLTYPE StartTextElement( const char *const name) = 0; virtual HRESULT STDMETHODCALLTYPE EndTextElement( void) = 0; virtual HRESULT STDMETHODVCALLTYPE WriteXmlText( const char *const fmt, ...) = 0; virtual HRESULT STDMETHODVCALLTYPE WriteXmlTextBlock( const char *const fmt, ...) = 0; virtual HRESULT STDMETHODCALLTYPE WriteEmptyElement( const char *const element) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementPointer( const char *const element, SIZE_T ptr) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementPointerAnnotated( const char *const element, SIZE_T ptr, const WCHAR *const annotation) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementAddress( const char *const element, SIZE_T base, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementAddressNamed( const char *const element, const char *const name, SIZE_T base, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementAddressNamedW( const char *const element, const WCHAR *const name, SIZE_T base, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementString( const char *const element, const char *const data) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementStringW( const char *const element, const WCHAR *const data) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementInt( const char *const element, int value) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementUInt( const char *const element, DWORD value) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementEnumerated( const char *const element, DWORD value, const WCHAR *const mnemonic) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementIntWithSuppress( const char *const element, int value, int suppressIfEqual) = 0; virtual HRESULT STDMETHODCALLTYPE WriteElementFlag( const char *const element, BOOL flag) = 0; virtual HRESULT STDMETHODCALLTYPE StartArray( const char *const name, const WCHAR *const fmt) = 0; virtual HRESULT STDMETHODCALLTYPE EndArray( const char *const countPrefix) = 0; virtual HRESULT STDMETHODCALLTYPE StartList( const WCHAR *const fmt) = 0; virtual HRESULT STDMETHODCALLTYPE EndList( void) = 0; virtual HRESULT STDMETHODCALLTYPE StartArrayWithOffset( const char *const name, unsigned int fieldOffset, unsigned int fieldSize, const WCHAR *const fmt) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldString( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, const char *const data) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldStringW( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, const WCHAR *const data) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldPointer( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldPointerWithSize( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldInt( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, int value) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldUInt( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, DWORD value) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldEnumerated( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, DWORD value, const WCHAR *const mnemonic) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldEmpty( const char *const element, unsigned int fieldOffset, unsigned int fieldSize) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldFlag( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, BOOL flag) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldPointerAnnotated( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr, const WCHAR *const annotation) = 0; virtual HRESULT STDMETHODCALLTYPE WriteFieldAddress( const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T base, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE StartStructure( const char *const name, SIZE_T ptr, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE StartStructureWithNegSpace( const char *const name, SIZE_T ptr, SIZE_T startPtr, SIZE_T totalSize) = 0; virtual HRESULT STDMETHODCALLTYPE StartStructureWithOffset( const char *const name, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr, SIZE_T size) = 0; virtual HRESULT STDMETHODCALLTYPE EndStructure( void) = 0; }; #else /* C style interface */ typedef struct IXCLRDataDisplayVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataDisplay * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataDisplay * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataDisplay * This); HRESULT ( STDMETHODVCALLTYPE *ErrorPrintF )( IXCLRDataDisplay * This, const char *const fmt, ...); HRESULT ( STDMETHODCALLTYPE *NativeImageDimensions )( IXCLRDataDisplay * This, SIZE_T base, SIZE_T size, DWORD sectionAlign); HRESULT ( STDMETHODCALLTYPE *Section )( IXCLRDataDisplay * This, const char *const name, SIZE_T rva, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *GetDumpOptions )( IXCLRDataDisplay * This, /* [out] */ CLRNativeImageDumpOptions *pOptions); HRESULT ( STDMETHODCALLTYPE *StartDocument )( IXCLRDataDisplay * This); HRESULT ( STDMETHODCALLTYPE *EndDocument )( IXCLRDataDisplay * This); HRESULT ( STDMETHODCALLTYPE *StartCategory )( IXCLRDataDisplay * This, const char *const name); HRESULT ( STDMETHODCALLTYPE *EndCategory )( IXCLRDataDisplay * This); HRESULT ( STDMETHODCALLTYPE *StartElement )( IXCLRDataDisplay * This, const char *const name); HRESULT ( STDMETHODCALLTYPE *EndElement )( IXCLRDataDisplay * This); HRESULT ( STDMETHODCALLTYPE *StartVStructure )( IXCLRDataDisplay * This, const char *const name); HRESULT ( STDMETHODCALLTYPE *StartVStructureWithOffset )( IXCLRDataDisplay * This, const char *const name, unsigned int fieldOffset, unsigned int fieldSize); HRESULT ( STDMETHODCALLTYPE *EndVStructure )( IXCLRDataDisplay * This); HRESULT ( STDMETHODCALLTYPE *StartTextElement )( IXCLRDataDisplay * This, const char *const name); HRESULT ( STDMETHODCALLTYPE *EndTextElement )( IXCLRDataDisplay * This); HRESULT ( STDMETHODVCALLTYPE *WriteXmlText )( IXCLRDataDisplay * This, const char *const fmt, ...); HRESULT ( STDMETHODVCALLTYPE *WriteXmlTextBlock )( IXCLRDataDisplay * This, const char *const fmt, ...); HRESULT ( STDMETHODCALLTYPE *WriteEmptyElement )( IXCLRDataDisplay * This, const char *const element); HRESULT ( STDMETHODCALLTYPE *WriteElementPointer )( IXCLRDataDisplay * This, const char *const element, SIZE_T ptr); HRESULT ( STDMETHODCALLTYPE *WriteElementPointerAnnotated )( IXCLRDataDisplay * This, const char *const element, SIZE_T ptr, const WCHAR *const annotation); HRESULT ( STDMETHODCALLTYPE *WriteElementAddress )( IXCLRDataDisplay * This, const char *const element, SIZE_T base, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *WriteElementAddressNamed )( IXCLRDataDisplay * This, const char *const element, const char *const name, SIZE_T base, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *WriteElementAddressNamedW )( IXCLRDataDisplay * This, const char *const element, const WCHAR *const name, SIZE_T base, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *WriteElementString )( IXCLRDataDisplay * This, const char *const element, const char *const data); HRESULT ( STDMETHODCALLTYPE *WriteElementStringW )( IXCLRDataDisplay * This, const char *const element, const WCHAR *const data); HRESULT ( STDMETHODCALLTYPE *WriteElementInt )( IXCLRDataDisplay * This, const char *const element, int value); HRESULT ( STDMETHODCALLTYPE *WriteElementUInt )( IXCLRDataDisplay * This, const char *const element, DWORD value); HRESULT ( STDMETHODCALLTYPE *WriteElementEnumerated )( IXCLRDataDisplay * This, const char *const element, DWORD value, const WCHAR *const mnemonic); HRESULT ( STDMETHODCALLTYPE *WriteElementIntWithSuppress )( IXCLRDataDisplay * This, const char *const element, int value, int suppressIfEqual); HRESULT ( STDMETHODCALLTYPE *WriteElementFlag )( IXCLRDataDisplay * This, const char *const element, BOOL flag); HRESULT ( STDMETHODCALLTYPE *StartArray )( IXCLRDataDisplay * This, const char *const name, const WCHAR *const fmt); HRESULT ( STDMETHODCALLTYPE *EndArray )( IXCLRDataDisplay * This, const char *const countPrefix); HRESULT ( STDMETHODCALLTYPE *StartList )( IXCLRDataDisplay * This, const WCHAR *const fmt); HRESULT ( STDMETHODCALLTYPE *EndList )( IXCLRDataDisplay * This); HRESULT ( STDMETHODCALLTYPE *StartArrayWithOffset )( IXCLRDataDisplay * This, const char *const name, unsigned int fieldOffset, unsigned int fieldSize, const WCHAR *const fmt); HRESULT ( STDMETHODCALLTYPE *WriteFieldString )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, const char *const data); HRESULT ( STDMETHODCALLTYPE *WriteFieldStringW )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, const WCHAR *const data); HRESULT ( STDMETHODCALLTYPE *WriteFieldPointer )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr); HRESULT ( STDMETHODCALLTYPE *WriteFieldPointerWithSize )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *WriteFieldInt )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, int value); HRESULT ( STDMETHODCALLTYPE *WriteFieldUInt )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, DWORD value); HRESULT ( STDMETHODCALLTYPE *WriteFieldEnumerated )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, DWORD value, const WCHAR *const mnemonic); HRESULT ( STDMETHODCALLTYPE *WriteFieldEmpty )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize); HRESULT ( STDMETHODCALLTYPE *WriteFieldFlag )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, BOOL flag); HRESULT ( STDMETHODCALLTYPE *WriteFieldPointerAnnotated )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr, const WCHAR *const annotation); HRESULT ( STDMETHODCALLTYPE *WriteFieldAddress )( IXCLRDataDisplay * This, const char *const element, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T base, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *StartStructure )( IXCLRDataDisplay * This, const char *const name, SIZE_T ptr, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *StartStructureWithNegSpace )( IXCLRDataDisplay * This, const char *const name, SIZE_T ptr, SIZE_T startPtr, SIZE_T totalSize); HRESULT ( STDMETHODCALLTYPE *StartStructureWithOffset )( IXCLRDataDisplay * This, const char *const name, unsigned int fieldOffset, unsigned int fieldSize, SIZE_T ptr, SIZE_T size); HRESULT ( STDMETHODCALLTYPE *EndStructure )( IXCLRDataDisplay * This); END_INTERFACE } IXCLRDataDisplayVtbl; interface IXCLRDataDisplay { CONST_VTBL struct IXCLRDataDisplayVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataDisplay_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataDisplay_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataDisplay_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataDisplay_ErrorPrintF(This,fmt,...) \ ( (This)->lpVtbl -> ErrorPrintF(This,fmt,...) ) #define IXCLRDataDisplay_NativeImageDimensions(This,base,size,sectionAlign) \ ( (This)->lpVtbl -> NativeImageDimensions(This,base,size,sectionAlign) ) #define IXCLRDataDisplay_Section(This,name,rva,size) \ ( (This)->lpVtbl -> Section(This,name,rva,size) ) #define IXCLRDataDisplay_GetDumpOptions(This,pOptions) \ ( (This)->lpVtbl -> GetDumpOptions(This,pOptions) ) #define IXCLRDataDisplay_StartDocument(This) \ ( (This)->lpVtbl -> StartDocument(This) ) #define IXCLRDataDisplay_EndDocument(This) \ ( (This)->lpVtbl -> EndDocument(This) ) #define IXCLRDataDisplay_StartCategory(This,name) \ ( (This)->lpVtbl -> StartCategory(This,name) ) #define IXCLRDataDisplay_EndCategory(This) \ ( (This)->lpVtbl -> EndCategory(This) ) #define IXCLRDataDisplay_StartElement(This,name) \ ( (This)->lpVtbl -> StartElement(This,name) ) #define IXCLRDataDisplay_EndElement(This) \ ( (This)->lpVtbl -> EndElement(This) ) #define IXCLRDataDisplay_StartVStructure(This,name) \ ( (This)->lpVtbl -> StartVStructure(This,name) ) #define IXCLRDataDisplay_StartVStructureWithOffset(This,name,fieldOffset,fieldSize) \ ( (This)->lpVtbl -> StartVStructureWithOffset(This,name,fieldOffset,fieldSize) ) #define IXCLRDataDisplay_EndVStructure(This) \ ( (This)->lpVtbl -> EndVStructure(This) ) #define IXCLRDataDisplay_StartTextElement(This,name) \ ( (This)->lpVtbl -> StartTextElement(This,name) ) #define IXCLRDataDisplay_EndTextElement(This) \ ( (This)->lpVtbl -> EndTextElement(This) ) #define IXCLRDataDisplay_WriteXmlText(This,fmt,...) \ ( (This)->lpVtbl -> WriteXmlText(This,fmt,...) ) #define IXCLRDataDisplay_WriteXmlTextBlock(This,fmt,...) \ ( (This)->lpVtbl -> WriteXmlTextBlock(This,fmt,...) ) #define IXCLRDataDisplay_WriteEmptyElement(This,element) \ ( (This)->lpVtbl -> WriteEmptyElement(This,element) ) #define IXCLRDataDisplay_WriteElementPointer(This,element,ptr) \ ( (This)->lpVtbl -> WriteElementPointer(This,element,ptr) ) #define IXCLRDataDisplay_WriteElementPointerAnnotated(This,element,ptr,annotation) \ ( (This)->lpVtbl -> WriteElementPointerAnnotated(This,element,ptr,annotation) ) #define IXCLRDataDisplay_WriteElementAddress(This,element,base,size) \ ( (This)->lpVtbl -> WriteElementAddress(This,element,base,size) ) #define IXCLRDataDisplay_WriteElementAddressNamed(This,element,name,base,size) \ ( (This)->lpVtbl -> WriteElementAddressNamed(This,element,name,base,size) ) #define IXCLRDataDisplay_WriteElementAddressNamedW(This,element,name,base,size) \ ( (This)->lpVtbl -> WriteElementAddressNamedW(This,element,name,base,size) ) #define IXCLRDataDisplay_WriteElementString(This,element,data) \ ( (This)->lpVtbl -> WriteElementString(This,element,data) ) #define IXCLRDataDisplay_WriteElementStringW(This,element,data) \ ( (This)->lpVtbl -> WriteElementStringW(This,element,data) ) #define IXCLRDataDisplay_WriteElementInt(This,element,value) \ ( (This)->lpVtbl -> WriteElementInt(This,element,value) ) #define IXCLRDataDisplay_WriteElementUInt(This,element,value) \ ( (This)->lpVtbl -> WriteElementUInt(This,element,value) ) #define IXCLRDataDisplay_WriteElementEnumerated(This,element,value,mnemonic) \ ( (This)->lpVtbl -> WriteElementEnumerated(This,element,value,mnemonic) ) #define IXCLRDataDisplay_WriteElementIntWithSuppress(This,element,value,suppressIfEqual) \ ( (This)->lpVtbl -> WriteElementIntWithSuppress(This,element,value,suppressIfEqual) ) #define IXCLRDataDisplay_WriteElementFlag(This,element,flag) \ ( (This)->lpVtbl -> WriteElementFlag(This,element,flag) ) #define IXCLRDataDisplay_StartArray(This,name,fmt) \ ( (This)->lpVtbl -> StartArray(This,name,fmt) ) #define IXCLRDataDisplay_EndArray(This,countPrefix) \ ( (This)->lpVtbl -> EndArray(This,countPrefix) ) #define IXCLRDataDisplay_StartList(This,fmt) \ ( (This)->lpVtbl -> StartList(This,fmt) ) #define IXCLRDataDisplay_EndList(This) \ ( (This)->lpVtbl -> EndList(This) ) #define IXCLRDataDisplay_StartArrayWithOffset(This,name,fieldOffset,fieldSize,fmt) \ ( (This)->lpVtbl -> StartArrayWithOffset(This,name,fieldOffset,fieldSize,fmt) ) #define IXCLRDataDisplay_WriteFieldString(This,element,fieldOffset,fieldSize,data) \ ( (This)->lpVtbl -> WriteFieldString(This,element,fieldOffset,fieldSize,data) ) #define IXCLRDataDisplay_WriteFieldStringW(This,element,fieldOffset,fieldSize,data) \ ( (This)->lpVtbl -> WriteFieldStringW(This,element,fieldOffset,fieldSize,data) ) #define IXCLRDataDisplay_WriteFieldPointer(This,element,fieldOffset,fieldSize,ptr) \ ( (This)->lpVtbl -> WriteFieldPointer(This,element,fieldOffset,fieldSize,ptr) ) #define IXCLRDataDisplay_WriteFieldPointerWithSize(This,element,fieldOffset,fieldSize,ptr,size) \ ( (This)->lpVtbl -> WriteFieldPointerWithSize(This,element,fieldOffset,fieldSize,ptr,size) ) #define IXCLRDataDisplay_WriteFieldInt(This,element,fieldOffset,fieldSize,value) \ ( (This)->lpVtbl -> WriteFieldInt(This,element,fieldOffset,fieldSize,value) ) #define IXCLRDataDisplay_WriteFieldUInt(This,element,fieldOffset,fieldSize,value) \ ( (This)->lpVtbl -> WriteFieldUInt(This,element,fieldOffset,fieldSize,value) ) #define IXCLRDataDisplay_WriteFieldEnumerated(This,element,fieldOffset,fieldSize,value,mnemonic) \ ( (This)->lpVtbl -> WriteFieldEnumerated(This,element,fieldOffset,fieldSize,value,mnemonic) ) #define IXCLRDataDisplay_WriteFieldEmpty(This,element,fieldOffset,fieldSize) \ ( (This)->lpVtbl -> WriteFieldEmpty(This,element,fieldOffset,fieldSize) ) #define IXCLRDataDisplay_WriteFieldFlag(This,element,fieldOffset,fieldSize,flag) \ ( (This)->lpVtbl -> WriteFieldFlag(This,element,fieldOffset,fieldSize,flag) ) #define IXCLRDataDisplay_WriteFieldPointerAnnotated(This,element,fieldOffset,fieldSize,ptr,annotation) \ ( (This)->lpVtbl -> WriteFieldPointerAnnotated(This,element,fieldOffset,fieldSize,ptr,annotation) ) #define IXCLRDataDisplay_WriteFieldAddress(This,element,fieldOffset,fieldSize,base,size) \ ( (This)->lpVtbl -> WriteFieldAddress(This,element,fieldOffset,fieldSize,base,size) ) #define IXCLRDataDisplay_StartStructure(This,name,ptr,size) \ ( (This)->lpVtbl -> StartStructure(This,name,ptr,size) ) #define IXCLRDataDisplay_StartStructureWithNegSpace(This,name,ptr,startPtr,totalSize) \ ( (This)->lpVtbl -> StartStructureWithNegSpace(This,name,ptr,startPtr,totalSize) ) #define IXCLRDataDisplay_StartStructureWithOffset(This,name,fieldOffset,fieldSize,ptr,size) \ ( (This)->lpVtbl -> StartStructureWithOffset(This,name,fieldOffset,fieldSize,ptr,size) ) #define IXCLRDataDisplay_EndStructure(This) \ ( (This)->lpVtbl -> EndStructure(This) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataDisplay_INTERFACE_DEFINED__ */ #ifndef __IXCLRDataProcess_INTERFACE_DEFINED__ #define __IXCLRDataProcess_INTERFACE_DEFINED__ /* interface IXCLRDataProcess */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataProcess; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5c552ab6-fc09-4cb3-8e36-22fa03c798b7") IXCLRDataProcess : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Flush( void) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumTasks( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumTask( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTask **task) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumTasks( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetTaskByOSThreadID( /* [in] */ ULONG32 osThreadID, /* [out] */ IXCLRDataTask **task) = 0; virtual HRESULT STDMETHODCALLTYPE GetTaskByUniqueID( /* [in] */ ULONG64 taskID, /* [out] */ IXCLRDataTask **task) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataProcess *process) = 0; virtual HRESULT STDMETHODCALLTYPE GetManagedObject( /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState( /* [out] */ ULONG32 *state) = 0; virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState( /* [in] */ ULONG32 state) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddressType( /* [in] */ CLRDATA_ADDRESS address, /* [out] */ CLRDataAddressType *type) = 0; virtual HRESULT STDMETHODCALLTYPE GetRuntimeNameByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ CLRDATA_ADDRESS *displacement) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumAppDomain( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomainByUniqueID( /* [in] */ ULONG64 id, /* [out] */ IXCLRDataAppDomain **appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumAssembly( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAssembly **assembly) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumModules( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumModule( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumModules( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetModuleByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByAddress( /* [in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByAddress( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetDataByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataValue **value, /* [out] */ CLRDATA_ADDRESS *displacement) = 0; virtual HRESULT STDMETHODCALLTYPE GetExceptionStateByExceptionRecord( /* [in] */ EXCEPTION_RECORD64 *record, /* [out] */ IXCLRDataExceptionState **exState) = 0; virtual HRESULT STDMETHODCALLTYPE TranslateExceptionRecordToNotification( /* [in] */ EXCEPTION_RECORD64 *record, /* [in] */ IXCLRDataExceptionNotification *notify) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE CreateMemoryValue( /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [in] */ IXCLRDataTypeInstance *type, /* [in] */ CLRDATA_ADDRESS addr, /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE SetAllTypeNotifications( IXCLRDataModule *mod, ULONG32 flags) = 0; virtual HRESULT STDMETHODCALLTYPE SetAllCodeNotifications( IXCLRDataModule *mod, ULONG32 flags) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeNotifications( /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdTypeDef tokens[ ], /* [size_is][out] */ ULONG32 flags[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetTypeNotifications( /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdTypeDef tokens[ ], /* [size_is][in] */ ULONG32 flags[ ], /* [in] */ ULONG32 singleFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeNotifications( /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdMethodDef tokens[ ], /* [size_is][out] */ ULONG32 flags[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetCodeNotifications( /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdMethodDef tokens[ ], /* [size_is][in] */ ULONG32 flags[ ], /* [in] */ ULONG32 singleFlags) = 0; virtual HRESULT STDMETHODCALLTYPE GetOtherNotificationFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE SetOtherNotificationFlags( /* [in] */ ULONG32 flags) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByAddress( /* [in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByAddress( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE FollowStub( /* [in] */ ULONG32 inFlags, /* [in] */ CLRDATA_ADDRESS inAddr, /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, /* [out] */ CLRDATA_ADDRESS *outAddr, /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, /* [out] */ ULONG32 *outFlags) = 0; virtual HRESULT STDMETHODCALLTYPE FollowStub2( /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 inFlags, /* [in] */ CLRDATA_ADDRESS inAddr, /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, /* [out] */ CLRDATA_ADDRESS *outAddr, /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, /* [out] */ ULONG32 *outFlags) = 0; virtual HRESULT STDMETHODCALLTYPE DumpNativeImage( /* [in] */ CLRDATA_ADDRESS loadedBase, /* [in] */ LPCWSTR name, /* [in] */ IXCLRDataDisplay *display, /* [in] */ IXCLRLibrarySupport *libSupport, /* [in] */ IXCLRDisassemblySupport *dis) = 0; }; #else /* C style interface */ typedef struct IXCLRDataProcessVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataProcess * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataProcess * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataProcess * This); HRESULT ( STDMETHODCALLTYPE *Flush )( IXCLRDataProcess * This); HRESULT ( STDMETHODCALLTYPE *StartEnumTasks )( IXCLRDataProcess * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumTask )( IXCLRDataProcess * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTask **task); HRESULT ( STDMETHODCALLTYPE *EndEnumTasks )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetTaskByOSThreadID )( IXCLRDataProcess * This, /* [in] */ ULONG32 osThreadID, /* [out] */ IXCLRDataTask **task); HRESULT ( STDMETHODCALLTYPE *GetTaskByUniqueID )( IXCLRDataProcess * This, /* [in] */ ULONG64 taskID, /* [out] */ IXCLRDataTask **task); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataProcess * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataProcess * This, /* [in] */ IXCLRDataProcess *process); HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( IXCLRDataProcess * This, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( IXCLRDataProcess * This, /* [out] */ ULONG32 *state); HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( IXCLRDataProcess * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *GetAddressType )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS address, /* [out] */ CLRDataAddressType *type); HRESULT ( STDMETHODCALLTYPE *GetRuntimeNameByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ CLRDATA_ADDRESS *displacement); HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( IXCLRDataProcess * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( IXCLRDataProcess * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetAppDomainByUniqueID )( IXCLRDataProcess * This, /* [in] */ ULONG64 id, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( IXCLRDataProcess * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( IXCLRDataProcess * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAssembly **assembly); HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( IXCLRDataProcess * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumModule )( IXCLRDataProcess * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetModuleByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS address, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetDataByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataValue **value, /* [out] */ CLRDATA_ADDRESS *displacement); HRESULT ( STDMETHODCALLTYPE *GetExceptionStateByExceptionRecord )( IXCLRDataProcess * This, /* [in] */ EXCEPTION_RECORD64 *record, /* [out] */ IXCLRDataExceptionState **exState); HRESULT ( STDMETHODCALLTYPE *TranslateExceptionRecordToNotification )( IXCLRDataProcess * This, /* [in] */ EXCEPTION_RECORD64 *record, /* [in] */ IXCLRDataExceptionNotification *notify); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataProcess * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *CreateMemoryValue )( IXCLRDataProcess * This, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [in] */ IXCLRDataTypeInstance *type, /* [in] */ CLRDATA_ADDRESS addr, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *SetAllTypeNotifications )( IXCLRDataProcess * This, IXCLRDataModule *mod, ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *SetAllCodeNotifications )( IXCLRDataProcess * This, IXCLRDataModule *mod, ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *GetTypeNotifications )( IXCLRDataProcess * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdTypeDef tokens[ ], /* [size_is][out] */ ULONG32 flags[ ]); HRESULT ( STDMETHODCALLTYPE *SetTypeNotifications )( IXCLRDataProcess * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdTypeDef tokens[ ], /* [size_is][in] */ ULONG32 flags[ ], /* [in] */ ULONG32 singleFlags); HRESULT ( STDMETHODCALLTYPE *GetCodeNotifications )( IXCLRDataProcess * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdMethodDef tokens[ ], /* [size_is][out] */ ULONG32 flags[ ]); HRESULT ( STDMETHODCALLTYPE *SetCodeNotifications )( IXCLRDataProcess * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdMethodDef tokens[ ], /* [size_is][in] */ ULONG32 flags[ ], /* [in] */ ULONG32 singleFlags); HRESULT ( STDMETHODCALLTYPE *GetOtherNotificationFlags )( IXCLRDataProcess * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *SetOtherNotificationFlags )( IXCLRDataProcess * This, /* [in] */ ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS address, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByAddress )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *FollowStub )( IXCLRDataProcess * This, /* [in] */ ULONG32 inFlags, /* [in] */ CLRDATA_ADDRESS inAddr, /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, /* [out] */ CLRDATA_ADDRESS *outAddr, /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, /* [out] */ ULONG32 *outFlags); HRESULT ( STDMETHODCALLTYPE *FollowStub2 )( IXCLRDataProcess * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 inFlags, /* [in] */ CLRDATA_ADDRESS inAddr, /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, /* [out] */ CLRDATA_ADDRESS *outAddr, /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, /* [out] */ ULONG32 *outFlags); HRESULT ( STDMETHODCALLTYPE *DumpNativeImage )( IXCLRDataProcess * This, /* [in] */ CLRDATA_ADDRESS loadedBase, /* [in] */ LPCWSTR name, /* [in] */ IXCLRDataDisplay *display, /* [in] */ IXCLRLibrarySupport *libSupport, /* [in] */ IXCLRDisassemblySupport *dis); END_INTERFACE } IXCLRDataProcessVtbl; interface IXCLRDataProcess { CONST_VTBL struct IXCLRDataProcessVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataProcess_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataProcess_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataProcess_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataProcess_Flush(This) \ ( (This)->lpVtbl -> Flush(This) ) #define IXCLRDataProcess_StartEnumTasks(This,handle) \ ( (This)->lpVtbl -> StartEnumTasks(This,handle) ) #define IXCLRDataProcess_EnumTask(This,handle,task) \ ( (This)->lpVtbl -> EnumTask(This,handle,task) ) #define IXCLRDataProcess_EndEnumTasks(This,handle) \ ( (This)->lpVtbl -> EndEnumTasks(This,handle) ) #define IXCLRDataProcess_GetTaskByOSThreadID(This,osThreadID,task) \ ( (This)->lpVtbl -> GetTaskByOSThreadID(This,osThreadID,task) ) #define IXCLRDataProcess_GetTaskByUniqueID(This,taskID,task) \ ( (This)->lpVtbl -> GetTaskByUniqueID(This,taskID,task) ) #define IXCLRDataProcess_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataProcess_IsSameObject(This,process) \ ( (This)->lpVtbl -> IsSameObject(This,process) ) #define IXCLRDataProcess_GetManagedObject(This,value) \ ( (This)->lpVtbl -> GetManagedObject(This,value) ) #define IXCLRDataProcess_GetDesiredExecutionState(This,state) \ ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) #define IXCLRDataProcess_SetDesiredExecutionState(This,state) \ ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) #define IXCLRDataProcess_GetAddressType(This,address,type) \ ( (This)->lpVtbl -> GetAddressType(This,address,type) ) #define IXCLRDataProcess_GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) \ ( (This)->lpVtbl -> GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) ) #define IXCLRDataProcess_StartEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) #define IXCLRDataProcess_EnumAppDomain(This,handle,appDomain) \ ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) #define IXCLRDataProcess_EndEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) #define IXCLRDataProcess_GetAppDomainByUniqueID(This,id,appDomain) \ ( (This)->lpVtbl -> GetAppDomainByUniqueID(This,id,appDomain) ) #define IXCLRDataProcess_StartEnumAssemblies(This,handle) \ ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) #define IXCLRDataProcess_EnumAssembly(This,handle,assembly) \ ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) #define IXCLRDataProcess_EndEnumAssemblies(This,handle) \ ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) #define IXCLRDataProcess_StartEnumModules(This,handle) \ ( (This)->lpVtbl -> StartEnumModules(This,handle) ) #define IXCLRDataProcess_EnumModule(This,handle,mod) \ ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) #define IXCLRDataProcess_EndEnumModules(This,handle) \ ( (This)->lpVtbl -> EndEnumModules(This,handle) ) #define IXCLRDataProcess_GetModuleByAddress(This,address,mod) \ ( (This)->lpVtbl -> GetModuleByAddress(This,address,mod) ) #define IXCLRDataProcess_StartEnumMethodInstancesByAddress(This,address,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumMethodInstancesByAddress(This,address,appDomain,handle) ) #define IXCLRDataProcess_EnumMethodInstanceByAddress(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodInstanceByAddress(This,handle,method) ) #define IXCLRDataProcess_EndEnumMethodInstancesByAddress(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodInstancesByAddress(This,handle) ) #define IXCLRDataProcess_GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) \ ( (This)->lpVtbl -> GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) ) #define IXCLRDataProcess_GetExceptionStateByExceptionRecord(This,record,exState) \ ( (This)->lpVtbl -> GetExceptionStateByExceptionRecord(This,record,exState) ) #define IXCLRDataProcess_TranslateExceptionRecordToNotification(This,record,notify) \ ( (This)->lpVtbl -> TranslateExceptionRecordToNotification(This,record,notify) ) #define IXCLRDataProcess_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataProcess_CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) \ ( (This)->lpVtbl -> CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) ) #define IXCLRDataProcess_SetAllTypeNotifications(This,mod,flags) \ ( (This)->lpVtbl -> SetAllTypeNotifications(This,mod,flags) ) #define IXCLRDataProcess_SetAllCodeNotifications(This,mod,flags) \ ( (This)->lpVtbl -> SetAllCodeNotifications(This,mod,flags) ) #define IXCLRDataProcess_GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ ( (This)->lpVtbl -> GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) #define IXCLRDataProcess_SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ ( (This)->lpVtbl -> SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) #define IXCLRDataProcess_GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ ( (This)->lpVtbl -> GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) #define IXCLRDataProcess_SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ ( (This)->lpVtbl -> SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) #define IXCLRDataProcess_GetOtherNotificationFlags(This,flags) \ ( (This)->lpVtbl -> GetOtherNotificationFlags(This,flags) ) #define IXCLRDataProcess_SetOtherNotificationFlags(This,flags) \ ( (This)->lpVtbl -> SetOtherNotificationFlags(This,flags) ) #define IXCLRDataProcess_StartEnumMethodDefinitionsByAddress(This,address,handle) \ ( (This)->lpVtbl -> StartEnumMethodDefinitionsByAddress(This,address,handle) ) #define IXCLRDataProcess_EnumMethodDefinitionByAddress(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodDefinitionByAddress(This,handle,method) ) #define IXCLRDataProcess_EndEnumMethodDefinitionsByAddress(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodDefinitionsByAddress(This,handle) ) #define IXCLRDataProcess_FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ ( (This)->lpVtbl -> FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) #define IXCLRDataProcess_FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ ( (This)->lpVtbl -> FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) #define IXCLRDataProcess_DumpNativeImage(This,loadedBase,name,display,libSupport,dis) \ ( (This)->lpVtbl -> DumpNativeImage(This,loadedBase,name,display,libSupport,dis) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataProcess_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0005 */ /* [local] */ #pragma warning(pop) typedef /* [public][public][public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0005_0001 { GC_MARK_END = 1, GC_EVENT_TYPE_MAX = ( GC_MARK_END + 1 ) } GcEvt_t; typedef /* [public][public][public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0005_0002 { GcEvt_t typ; /* [switch_is] */ /* [switch_type] */ union { /* [case()] */ int condemnedGeneration; } ; } GcEvtArgs; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0005_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0005_v0_0_s_ifspec; #ifndef __IXCLRDataProcess2_INTERFACE_DEFINED__ #define __IXCLRDataProcess2_INTERFACE_DEFINED__ /* interface IXCLRDataProcess2 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataProcess2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("5c552ab6-fc09-4cb3-8e36-22fa03c798b8") IXCLRDataProcess2 : public IXCLRDataProcess { public: virtual HRESULT STDMETHODCALLTYPE GetGcNotification( /* [out][in] */ GcEvtArgs *gcEvtArgs) = 0; virtual HRESULT STDMETHODCALLTYPE SetGcNotification( /* [in] */ GcEvtArgs gcEvtArgs) = 0; }; #else /* C style interface */ typedef struct IXCLRDataProcess2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataProcess2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataProcess2 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataProcess2 * This); HRESULT ( STDMETHODCALLTYPE *Flush )( IXCLRDataProcess2 * This); HRESULT ( STDMETHODCALLTYPE *StartEnumTasks )( IXCLRDataProcess2 * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumTask )( IXCLRDataProcess2 * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTask **task); HRESULT ( STDMETHODCALLTYPE *EndEnumTasks )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetTaskByOSThreadID )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 osThreadID, /* [out] */ IXCLRDataTask **task); HRESULT ( STDMETHODCALLTYPE *GetTaskByUniqueID )( IXCLRDataProcess2 * This, /* [in] */ ULONG64 taskID, /* [out] */ IXCLRDataTask **task); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataProcess2 * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataProcess2 * This, /* [in] */ IXCLRDataProcess *process); HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( IXCLRDataProcess2 * This, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( IXCLRDataProcess2 * This, /* [out] */ ULONG32 *state); HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *GetAddressType )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [out] */ CLRDataAddressType *type); HRESULT ( STDMETHODCALLTYPE *GetRuntimeNameByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ CLRDATA_ADDRESS *displacement); HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( IXCLRDataProcess2 * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( IXCLRDataProcess2 * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetAppDomainByUniqueID )( IXCLRDataProcess2 * This, /* [in] */ ULONG64 id, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( IXCLRDataProcess2 * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( IXCLRDataProcess2 * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAssembly **assembly); HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( IXCLRDataProcess2 * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumModule )( IXCLRDataProcess2 * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetModuleByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetDataByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataValue **value, /* [out] */ CLRDATA_ADDRESS *displacement); HRESULT ( STDMETHODCALLTYPE *GetExceptionStateByExceptionRecord )( IXCLRDataProcess2 * This, /* [in] */ EXCEPTION_RECORD64 *record, /* [out] */ IXCLRDataExceptionState **exState); HRESULT ( STDMETHODCALLTYPE *TranslateExceptionRecordToNotification )( IXCLRDataProcess2 * This, /* [in] */ EXCEPTION_RECORD64 *record, /* [in] */ IXCLRDataExceptionNotification *notify); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *CreateMemoryValue )( IXCLRDataProcess2 * This, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [in] */ IXCLRDataTypeInstance *type, /* [in] */ CLRDATA_ADDRESS addr, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *SetAllTypeNotifications )( IXCLRDataProcess2 * This, IXCLRDataModule *mod, ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *SetAllCodeNotifications )( IXCLRDataProcess2 * This, IXCLRDataModule *mod, ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *GetTypeNotifications )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdTypeDef tokens[ ], /* [size_is][out] */ ULONG32 flags[ ]); HRESULT ( STDMETHODCALLTYPE *SetTypeNotifications )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdTypeDef tokens[ ], /* [size_is][in] */ ULONG32 flags[ ], /* [in] */ ULONG32 singleFlags); HRESULT ( STDMETHODCALLTYPE *GetCodeNotifications )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdMethodDef tokens[ ], /* [size_is][out] */ ULONG32 flags[ ]); HRESULT ( STDMETHODCALLTYPE *SetCodeNotifications )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 numTokens, /* [size_is][in] */ IXCLRDataModule *mods[ ], /* [in] */ IXCLRDataModule *singleMod, /* [size_is][in] */ mdMethodDef tokens[ ], /* [size_is][in] */ ULONG32 flags[ ], /* [in] */ ULONG32 singleFlags); HRESULT ( STDMETHODCALLTYPE *GetOtherNotificationFlags )( IXCLRDataProcess2 * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *SetOtherNotificationFlags )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS address, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByAddress )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *FollowStub )( IXCLRDataProcess2 * This, /* [in] */ ULONG32 inFlags, /* [in] */ CLRDATA_ADDRESS inAddr, /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, /* [out] */ CLRDATA_ADDRESS *outAddr, /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, /* [out] */ ULONG32 *outFlags); HRESULT ( STDMETHODCALLTYPE *FollowStub2 )( IXCLRDataProcess2 * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 inFlags, /* [in] */ CLRDATA_ADDRESS inAddr, /* [in] */ CLRDATA_FOLLOW_STUB_BUFFER *inBuffer, /* [out] */ CLRDATA_ADDRESS *outAddr, /* [out] */ CLRDATA_FOLLOW_STUB_BUFFER *outBuffer, /* [out] */ ULONG32 *outFlags); HRESULT ( STDMETHODCALLTYPE *DumpNativeImage )( IXCLRDataProcess2 * This, /* [in] */ CLRDATA_ADDRESS loadedBase, /* [in] */ LPCWSTR name, /* [in] */ IXCLRDataDisplay *display, /* [in] */ IXCLRLibrarySupport *libSupport, /* [in] */ IXCLRDisassemblySupport *dis); HRESULT ( STDMETHODCALLTYPE *GetGcNotification )( IXCLRDataProcess2 * This, /* [out][in] */ GcEvtArgs *gcEvtArgs); HRESULT ( STDMETHODCALLTYPE *SetGcNotification )( IXCLRDataProcess2 * This, /* [in] */ GcEvtArgs gcEvtArgs); END_INTERFACE } IXCLRDataProcess2Vtbl; interface IXCLRDataProcess2 { CONST_VTBL struct IXCLRDataProcess2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataProcess2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataProcess2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataProcess2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataProcess2_Flush(This) \ ( (This)->lpVtbl -> Flush(This) ) #define IXCLRDataProcess2_StartEnumTasks(This,handle) \ ( (This)->lpVtbl -> StartEnumTasks(This,handle) ) #define IXCLRDataProcess2_EnumTask(This,handle,task) \ ( (This)->lpVtbl -> EnumTask(This,handle,task) ) #define IXCLRDataProcess2_EndEnumTasks(This,handle) \ ( (This)->lpVtbl -> EndEnumTasks(This,handle) ) #define IXCLRDataProcess2_GetTaskByOSThreadID(This,osThreadID,task) \ ( (This)->lpVtbl -> GetTaskByOSThreadID(This,osThreadID,task) ) #define IXCLRDataProcess2_GetTaskByUniqueID(This,taskID,task) \ ( (This)->lpVtbl -> GetTaskByUniqueID(This,taskID,task) ) #define IXCLRDataProcess2_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataProcess2_IsSameObject(This,process) \ ( (This)->lpVtbl -> IsSameObject(This,process) ) #define IXCLRDataProcess2_GetManagedObject(This,value) \ ( (This)->lpVtbl -> GetManagedObject(This,value) ) #define IXCLRDataProcess2_GetDesiredExecutionState(This,state) \ ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) #define IXCLRDataProcess2_SetDesiredExecutionState(This,state) \ ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) #define IXCLRDataProcess2_GetAddressType(This,address,type) \ ( (This)->lpVtbl -> GetAddressType(This,address,type) ) #define IXCLRDataProcess2_GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) \ ( (This)->lpVtbl -> GetRuntimeNameByAddress(This,address,flags,bufLen,nameLen,nameBuf,displacement) ) #define IXCLRDataProcess2_StartEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) #define IXCLRDataProcess2_EnumAppDomain(This,handle,appDomain) \ ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) #define IXCLRDataProcess2_EndEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) #define IXCLRDataProcess2_GetAppDomainByUniqueID(This,id,appDomain) \ ( (This)->lpVtbl -> GetAppDomainByUniqueID(This,id,appDomain) ) #define IXCLRDataProcess2_StartEnumAssemblies(This,handle) \ ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) #define IXCLRDataProcess2_EnumAssembly(This,handle,assembly) \ ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) #define IXCLRDataProcess2_EndEnumAssemblies(This,handle) \ ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) #define IXCLRDataProcess2_StartEnumModules(This,handle) \ ( (This)->lpVtbl -> StartEnumModules(This,handle) ) #define IXCLRDataProcess2_EnumModule(This,handle,mod) \ ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) #define IXCLRDataProcess2_EndEnumModules(This,handle) \ ( (This)->lpVtbl -> EndEnumModules(This,handle) ) #define IXCLRDataProcess2_GetModuleByAddress(This,address,mod) \ ( (This)->lpVtbl -> GetModuleByAddress(This,address,mod) ) #define IXCLRDataProcess2_StartEnumMethodInstancesByAddress(This,address,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumMethodInstancesByAddress(This,address,appDomain,handle) ) #define IXCLRDataProcess2_EnumMethodInstanceByAddress(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodInstanceByAddress(This,handle,method) ) #define IXCLRDataProcess2_EndEnumMethodInstancesByAddress(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodInstancesByAddress(This,handle) ) #define IXCLRDataProcess2_GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) \ ( (This)->lpVtbl -> GetDataByAddress(This,address,flags,appDomain,tlsTask,bufLen,nameLen,nameBuf,value,displacement) ) #define IXCLRDataProcess2_GetExceptionStateByExceptionRecord(This,record,exState) \ ( (This)->lpVtbl -> GetExceptionStateByExceptionRecord(This,record,exState) ) #define IXCLRDataProcess2_TranslateExceptionRecordToNotification(This,record,notify) \ ( (This)->lpVtbl -> TranslateExceptionRecordToNotification(This,record,notify) ) #define IXCLRDataProcess2_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataProcess2_CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) \ ( (This)->lpVtbl -> CreateMemoryValue(This,appDomain,tlsTask,type,addr,value) ) #define IXCLRDataProcess2_SetAllTypeNotifications(This,mod,flags) \ ( (This)->lpVtbl -> SetAllTypeNotifications(This,mod,flags) ) #define IXCLRDataProcess2_SetAllCodeNotifications(This,mod,flags) \ ( (This)->lpVtbl -> SetAllCodeNotifications(This,mod,flags) ) #define IXCLRDataProcess2_GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ ( (This)->lpVtbl -> GetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) #define IXCLRDataProcess2_SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ ( (This)->lpVtbl -> SetTypeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) #define IXCLRDataProcess2_GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) \ ( (This)->lpVtbl -> GetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags) ) #define IXCLRDataProcess2_SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) \ ( (This)->lpVtbl -> SetCodeNotifications(This,numTokens,mods,singleMod,tokens,flags,singleFlags) ) #define IXCLRDataProcess2_GetOtherNotificationFlags(This,flags) \ ( (This)->lpVtbl -> GetOtherNotificationFlags(This,flags) ) #define IXCLRDataProcess2_SetOtherNotificationFlags(This,flags) \ ( (This)->lpVtbl -> SetOtherNotificationFlags(This,flags) ) #define IXCLRDataProcess2_StartEnumMethodDefinitionsByAddress(This,address,handle) \ ( (This)->lpVtbl -> StartEnumMethodDefinitionsByAddress(This,address,handle) ) #define IXCLRDataProcess2_EnumMethodDefinitionByAddress(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodDefinitionByAddress(This,handle,method) ) #define IXCLRDataProcess2_EndEnumMethodDefinitionsByAddress(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodDefinitionsByAddress(This,handle) ) #define IXCLRDataProcess2_FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ ( (This)->lpVtbl -> FollowStub(This,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) #define IXCLRDataProcess2_FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) \ ( (This)->lpVtbl -> FollowStub2(This,task,inFlags,inAddr,inBuffer,outAddr,outBuffer,outFlags) ) #define IXCLRDataProcess2_DumpNativeImage(This,loadedBase,name,display,libSupport,dis) \ ( (This)->lpVtbl -> DumpNativeImage(This,loadedBase,name,display,libSupport,dis) ) #define IXCLRDataProcess2_GetGcNotification(This,gcEvtArgs) \ ( (This)->lpVtbl -> GetGcNotification(This,gcEvtArgs) ) #define IXCLRDataProcess2_SetGcNotification(This,gcEvtArgs) \ ( (This)->lpVtbl -> SetGcNotification(This,gcEvtArgs) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataProcess2_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0006 */ /* [local] */ typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0006_0001 { CLRDATA_DOMAIN_DEFAULT = 0 } CLRDataAppDomainFlag; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0006_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0006_v0_0_s_ifspec; #ifndef __IXCLRDataAppDomain_INTERFACE_DEFINED__ #define __IXCLRDataAppDomain_INTERFACE_DEFINED__ /* interface IXCLRDataAppDomain */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataAppDomain; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("7CA04601-C702-4670-A63C-FA44F7DA7BD5") IXCLRDataAppDomain : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ IXCLRDataProcess **process) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetUniqueID( /* [out] */ ULONG64 *id) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataAppDomain *appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE GetManagedObject( /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; }; #else /* C style interface */ typedef struct IXCLRDataAppDomainVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataAppDomain * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataAppDomain * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataAppDomain * This); HRESULT ( STDMETHODCALLTYPE *GetProcess )( IXCLRDataAppDomain * This, /* [out] */ IXCLRDataProcess **process); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataAppDomain * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetUniqueID )( IXCLRDataAppDomain * This, /* [out] */ ULONG64 *id); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataAppDomain * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataAppDomain * This, /* [in] */ IXCLRDataAppDomain *appDomain); HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( IXCLRDataAppDomain * This, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataAppDomain * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); END_INTERFACE } IXCLRDataAppDomainVtbl; interface IXCLRDataAppDomain { CONST_VTBL struct IXCLRDataAppDomainVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataAppDomain_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataAppDomain_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataAppDomain_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataAppDomain_GetProcess(This,process) \ ( (This)->lpVtbl -> GetProcess(This,process) ) #define IXCLRDataAppDomain_GetName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) #define IXCLRDataAppDomain_GetUniqueID(This,id) \ ( (This)->lpVtbl -> GetUniqueID(This,id) ) #define IXCLRDataAppDomain_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataAppDomain_IsSameObject(This,appDomain) \ ( (This)->lpVtbl -> IsSameObject(This,appDomain) ) #define IXCLRDataAppDomain_GetManagedObject(This,value) \ ( (This)->lpVtbl -> GetManagedObject(This,value) ) #define IXCLRDataAppDomain_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataAppDomain_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0007 */ /* [local] */ #pragma warning(pop) typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0007_0001 { CLRDATA_ASSEMBLY_DEFAULT = 0 } CLRDataAssemblyFlag; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0007_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0007_v0_0_s_ifspec; #ifndef __IXCLRDataAssembly_INTERFACE_DEFINED__ #define __IXCLRDataAssembly_INTERFACE_DEFINED__ /* interface IXCLRDataAssembly */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataAssembly; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2FA17588-43C2-46ab-9B51-C8F01E39C9AC") IXCLRDataAssembly : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE StartEnumModules( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumModule( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumModules( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFileName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataAssembly *assembly) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumAppDomain( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetDisplayName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; }; #else /* C style interface */ typedef struct IXCLRDataAssemblyVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataAssembly * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataAssembly * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataAssembly * This); HRESULT ( STDMETHODCALLTYPE *StartEnumModules )( IXCLRDataAssembly * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumModule )( IXCLRDataAssembly * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *EndEnumModules )( IXCLRDataAssembly * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataAssembly * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetFileName )( IXCLRDataAssembly * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataAssembly * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataAssembly * This, /* [in] */ IXCLRDataAssembly *assembly); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataAssembly * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( IXCLRDataAssembly * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( IXCLRDataAssembly * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( IXCLRDataAssembly * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( IXCLRDataAssembly * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); END_INTERFACE } IXCLRDataAssemblyVtbl; interface IXCLRDataAssembly { CONST_VTBL struct IXCLRDataAssemblyVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataAssembly_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataAssembly_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataAssembly_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataAssembly_StartEnumModules(This,handle) \ ( (This)->lpVtbl -> StartEnumModules(This,handle) ) #define IXCLRDataAssembly_EnumModule(This,handle,mod) \ ( (This)->lpVtbl -> EnumModule(This,handle,mod) ) #define IXCLRDataAssembly_EndEnumModules(This,handle) \ ( (This)->lpVtbl -> EndEnumModules(This,handle) ) #define IXCLRDataAssembly_GetName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) #define IXCLRDataAssembly_GetFileName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetFileName(This,bufLen,nameLen,name) ) #define IXCLRDataAssembly_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataAssembly_IsSameObject(This,assembly) \ ( (This)->lpVtbl -> IsSameObject(This,assembly) ) #define IXCLRDataAssembly_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataAssembly_StartEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) #define IXCLRDataAssembly_EnumAppDomain(This,handle,appDomain) \ ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) #define IXCLRDataAssembly_EndEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) #define IXCLRDataAssembly_GetDisplayName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetDisplayName(This,bufLen,nameLen,name) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataAssembly_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0008 */ /* [local] */ #pragma warning(pop) typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0008_0001 { CLRDATA_MODULE_DEFAULT = 0, CLRDATA_MODULE_IS_DYNAMIC = 0x1, CLRDATA_MODULE_IS_MEMORY_STREAM = 0x2, CLRDATA_MODULE_IS_MAIN_MODULE = 0x4 } CLRDataModuleFlag; typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0008_0002 { CLRDATA_MODULE_PE_FILE = 0, CLRDATA_MODULE_PREJIT_FILE = ( CLRDATA_MODULE_PE_FILE + 1 ) , CLRDATA_MODULE_MEMORY_STREAM = ( CLRDATA_MODULE_PREJIT_FILE + 1 ) , CLRDATA_MODULE_OTHER = ( CLRDATA_MODULE_MEMORY_STREAM + 1 ) } CLRDataModuleExtentType; typedef /* [public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0008_0003 { CLRDATA_ADDRESS base; ULONG32 length; CLRDataModuleExtentType type; } CLRDATA_MODULE_EXTENT; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0008_0004 { CLRDATA_TYPENOTIFY_NONE = 0, CLRDATA_TYPENOTIFY_LOADED = 0x1, CLRDATA_TYPENOTIFY_UNLOADED = 0x2 } CLRDataTypeNotification; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0008_0005 { CLRDATA_METHNOTIFY_NONE = 0, CLRDATA_METHNOTIFY_GENERATED = 0x1, CLRDATA_METHNOTIFY_DISCARDED = 0x2 } CLRDataMethodCodeNotification; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0008_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0008_v0_0_s_ifspec; #ifndef __IXCLRDataModule_INTERFACE_DEFINED__ #define __IXCLRDataModule_INTERFACE_DEFINED__ /* interface IXCLRDataModule */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataModule; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("88E32849-0A0A-4cb0-9022-7CD2E9E139E2") IXCLRDataModule : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE StartEnumAssemblies( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumAssembly( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAssembly **assembly) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumAssemblies( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitions( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinition( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitions( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstances( /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumTypeInstance( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeInstance **typeInstance) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstances( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumTypeDefinitionsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumTypeDefinitionByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **type) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumTypeDefinitionsByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumTypeInstancesByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumTypeInstanceByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeInstance **type) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumTypeInstancesByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeDefinitionByToken( /* [in] */ mdTypeDef token, /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken( /* [in] */ mdMethodDef token, /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumDataByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumDataByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumDataByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFileName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataModule *mod) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumExtents( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumExtent( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_MODULE_EXTENT *extent) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumExtents( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumAppDomains( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumAppDomain( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumAppDomains( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetVersionId( /* [out] */ GUID *vid) = 0; }; #else /* C style interface */ typedef struct IXCLRDataModuleVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataModule * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataModule * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataModule * This); HRESULT ( STDMETHODCALLTYPE *StartEnumAssemblies )( IXCLRDataModule * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAssembly )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAssembly **assembly); HRESULT ( STDMETHODCALLTYPE *EndEnumAssemblies )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumTypeDefinitions )( IXCLRDataModule * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumTypeDefinition )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **typeDefinition); HRESULT ( STDMETHODCALLTYPE *EndEnumTypeDefinitions )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumTypeInstances )( IXCLRDataModule * This, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumTypeInstance )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeInstance **typeInstance); HRESULT ( STDMETHODCALLTYPE *EndEnumTypeInstances )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumTypeDefinitionsByName )( IXCLRDataModule * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumTypeDefinitionByName )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **type); HRESULT ( STDMETHODCALLTYPE *EndEnumTypeDefinitionsByName )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumTypeInstancesByName )( IXCLRDataModule * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumTypeInstanceByName )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeInstance **type); HRESULT ( STDMETHODCALLTYPE *EndEnumTypeInstancesByName )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetTypeDefinitionByToken )( IXCLRDataModule * This, /* [in] */ mdTypeDef token, /* [out] */ IXCLRDataTypeDefinition **typeDefinition); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByName )( IXCLRDataModule * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByName )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByName )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByName )( IXCLRDataModule * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByName )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByName )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetMethodDefinitionByToken )( IXCLRDataModule * This, /* [in] */ mdMethodDef token, /* [out] */ IXCLRDataMethodDefinition **methodDefinition); HRESULT ( STDMETHODCALLTYPE *StartEnumDataByName )( IXCLRDataModule * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumDataByName )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *EndEnumDataByName )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataModule * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetFileName )( IXCLRDataModule * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataModule * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataModule * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *StartEnumExtents )( IXCLRDataModule * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumExtent )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_MODULE_EXTENT *extent); HRESULT ( STDMETHODCALLTYPE *EndEnumExtents )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataModule * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *StartEnumAppDomains )( IXCLRDataModule * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumAppDomain )( IXCLRDataModule * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *EndEnumAppDomains )( IXCLRDataModule * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetVersionId )( IXCLRDataModule * This, /* [out] */ GUID *vid); END_INTERFACE } IXCLRDataModuleVtbl; interface IXCLRDataModule { CONST_VTBL struct IXCLRDataModuleVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataModule_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataModule_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataModule_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataModule_StartEnumAssemblies(This,handle) \ ( (This)->lpVtbl -> StartEnumAssemblies(This,handle) ) #define IXCLRDataModule_EnumAssembly(This,handle,assembly) \ ( (This)->lpVtbl -> EnumAssembly(This,handle,assembly) ) #define IXCLRDataModule_EndEnumAssemblies(This,handle) \ ( (This)->lpVtbl -> EndEnumAssemblies(This,handle) ) #define IXCLRDataModule_StartEnumTypeDefinitions(This,handle) \ ( (This)->lpVtbl -> StartEnumTypeDefinitions(This,handle) ) #define IXCLRDataModule_EnumTypeDefinition(This,handle,typeDefinition) \ ( (This)->lpVtbl -> EnumTypeDefinition(This,handle,typeDefinition) ) #define IXCLRDataModule_EndEnumTypeDefinitions(This,handle) \ ( (This)->lpVtbl -> EndEnumTypeDefinitions(This,handle) ) #define IXCLRDataModule_StartEnumTypeInstances(This,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumTypeInstances(This,appDomain,handle) ) #define IXCLRDataModule_EnumTypeInstance(This,handle,typeInstance) \ ( (This)->lpVtbl -> EnumTypeInstance(This,handle,typeInstance) ) #define IXCLRDataModule_EndEnumTypeInstances(This,handle) \ ( (This)->lpVtbl -> EndEnumTypeInstances(This,handle) ) #define IXCLRDataModule_StartEnumTypeDefinitionsByName(This,name,flags,handle) \ ( (This)->lpVtbl -> StartEnumTypeDefinitionsByName(This,name,flags,handle) ) #define IXCLRDataModule_EnumTypeDefinitionByName(This,handle,type) \ ( (This)->lpVtbl -> EnumTypeDefinitionByName(This,handle,type) ) #define IXCLRDataModule_EndEnumTypeDefinitionsByName(This,handle) \ ( (This)->lpVtbl -> EndEnumTypeDefinitionsByName(This,handle) ) #define IXCLRDataModule_StartEnumTypeInstancesByName(This,name,flags,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumTypeInstancesByName(This,name,flags,appDomain,handle) ) #define IXCLRDataModule_EnumTypeInstanceByName(This,handle,type) \ ( (This)->lpVtbl -> EnumTypeInstanceByName(This,handle,type) ) #define IXCLRDataModule_EndEnumTypeInstancesByName(This,handle) \ ( (This)->lpVtbl -> EndEnumTypeInstancesByName(This,handle) ) #define IXCLRDataModule_GetTypeDefinitionByToken(This,token,typeDefinition) \ ( (This)->lpVtbl -> GetTypeDefinitionByToken(This,token,typeDefinition) ) #define IXCLRDataModule_StartEnumMethodDefinitionsByName(This,name,flags,handle) \ ( (This)->lpVtbl -> StartEnumMethodDefinitionsByName(This,name,flags,handle) ) #define IXCLRDataModule_EnumMethodDefinitionByName(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodDefinitionByName(This,handle,method) ) #define IXCLRDataModule_EndEnumMethodDefinitionsByName(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodDefinitionsByName(This,handle) ) #define IXCLRDataModule_StartEnumMethodInstancesByName(This,name,flags,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumMethodInstancesByName(This,name,flags,appDomain,handle) ) #define IXCLRDataModule_EnumMethodInstanceByName(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodInstanceByName(This,handle,method) ) #define IXCLRDataModule_EndEnumMethodInstancesByName(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodInstancesByName(This,handle) ) #define IXCLRDataModule_GetMethodDefinitionByToken(This,token,methodDefinition) \ ( (This)->lpVtbl -> GetMethodDefinitionByToken(This,token,methodDefinition) ) #define IXCLRDataModule_StartEnumDataByName(This,name,flags,appDomain,tlsTask,handle) \ ( (This)->lpVtbl -> StartEnumDataByName(This,name,flags,appDomain,tlsTask,handle) ) #define IXCLRDataModule_EnumDataByName(This,handle,value) \ ( (This)->lpVtbl -> EnumDataByName(This,handle,value) ) #define IXCLRDataModule_EndEnumDataByName(This,handle) \ ( (This)->lpVtbl -> EndEnumDataByName(This,handle) ) #define IXCLRDataModule_GetName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) #define IXCLRDataModule_GetFileName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetFileName(This,bufLen,nameLen,name) ) #define IXCLRDataModule_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataModule_IsSameObject(This,mod) \ ( (This)->lpVtbl -> IsSameObject(This,mod) ) #define IXCLRDataModule_StartEnumExtents(This,handle) \ ( (This)->lpVtbl -> StartEnumExtents(This,handle) ) #define IXCLRDataModule_EnumExtent(This,handle,extent) \ ( (This)->lpVtbl -> EnumExtent(This,handle,extent) ) #define IXCLRDataModule_EndEnumExtents(This,handle) \ ( (This)->lpVtbl -> EndEnumExtents(This,handle) ) #define IXCLRDataModule_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataModule_StartEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> StartEnumAppDomains(This,handle) ) #define IXCLRDataModule_EnumAppDomain(This,handle,appDomain) \ ( (This)->lpVtbl -> EnumAppDomain(This,handle,appDomain) ) #define IXCLRDataModule_EndEnumAppDomains(This,handle) \ ( (This)->lpVtbl -> EndEnumAppDomains(This,handle) ) #define IXCLRDataModule_GetVersionId(This,vid) \ ( (This)->lpVtbl -> GetVersionId(This,vid) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataModule_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0009 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0009_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0009_v0_0_s_ifspec; #ifndef __IXCLRDataModule2_INTERFACE_DEFINED__ #define __IXCLRDataModule2_INTERFACE_DEFINED__ /* interface IXCLRDataModule2 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataModule2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("34625881-7EB3-4524-817B-8DB9D064C760") IXCLRDataModule2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE SetJITCompilerFlags( /* [in] */ DWORD dwFlags) = 0; }; #else /* C style interface */ typedef struct IXCLRDataModule2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataModule2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataModule2 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataModule2 * This); HRESULT ( STDMETHODCALLTYPE *SetJITCompilerFlags )( IXCLRDataModule2 * This, /* [in] */ DWORD dwFlags); END_INTERFACE } IXCLRDataModule2Vtbl; interface IXCLRDataModule2 { CONST_VTBL struct IXCLRDataModule2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataModule2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataModule2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataModule2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataModule2_SetJITCompilerFlags(This,dwFlags) \ ( (This)->lpVtbl -> SetJITCompilerFlags(This,dwFlags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataModule2_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0010 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0010_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0010_v0_0_s_ifspec; #ifndef __IXCLRDataTypeDefinition_INTERFACE_DEFINED__ #define __IXCLRDataTypeDefinition_INTERFACE_DEFINED__ /* interface IXCLRDataTypeDefinition */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataTypeDefinition; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("4675666C-C275-45b8-9F6C-AB165D5C1E09") IXCLRDataTypeDefinition : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitions( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinition( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitions( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodDefinitionsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodDefinitionByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodDefinitionsByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodDefinitionByToken( /* [in] */ mdMethodDef token, /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumInstances( /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumInstance( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeInstance **instance) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumInstances( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope( /* [out] */ mdTypeDef *token, /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE GetCorElementType( /* [out] */ CorElementType *type) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataTypeDefinition *type) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetArrayRank( /* [out] */ ULONG32 *rank) = 0; virtual HRESULT STDMETHODCALLTYPE GetBase( /* [out] */ IXCLRDataTypeDefinition **base) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumFields( /* [in] */ ULONG32 flags, /* [out] */ ULONG32 *numFields) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumFields( /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumField( /* [out][in] */ CLRDATA_ENUM *handle, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumFields( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 nameFlags, /* [in] */ ULONG32 fieldFlags, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumFieldByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldByToken( /* [in] */ mdFieldDef token, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeNotification( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE SetTypeNotification( /* [in] */ ULONG32 flags) = 0; virtual HRESULT STDMETHODCALLTYPE EnumField2( /* [out][in] */ CLRDATA_ENUM *handle, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2( /* [in] */ IXCLRDataModule *tokenScope, /* [in] */ mdFieldDef token, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags) = 0; }; #else /* C style interface */ typedef struct IXCLRDataTypeDefinitionVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataTypeDefinition * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataTypeDefinition * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataTypeDefinition * This); HRESULT ( STDMETHODCALLTYPE *GetModule )( IXCLRDataTypeDefinition * This, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitions )( IXCLRDataTypeDefinition * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinition )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **methodDefinition); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitions )( IXCLRDataTypeDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodDefinitionsByName )( IXCLRDataTypeDefinition * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodDefinitionByName )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodDefinition **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodDefinitionsByName )( IXCLRDataTypeDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetMethodDefinitionByToken )( IXCLRDataTypeDefinition * This, /* [in] */ mdMethodDef token, /* [out] */ IXCLRDataMethodDefinition **methodDefinition); HRESULT ( STDMETHODCALLTYPE *StartEnumInstances )( IXCLRDataTypeDefinition * This, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumInstance )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeInstance **instance); HRESULT ( STDMETHODCALLTYPE *EndEnumInstances )( IXCLRDataTypeDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataTypeDefinition * This, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetTokenAndScope )( IXCLRDataTypeDefinition * This, /* [out] */ mdTypeDef *token, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *GetCorElementType )( IXCLRDataTypeDefinition * This, /* [out] */ CorElementType *type); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataTypeDefinition * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataTypeDefinition * This, /* [in] */ IXCLRDataTypeDefinition *type); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataTypeDefinition * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetArrayRank )( IXCLRDataTypeDefinition * This, /* [out] */ ULONG32 *rank); HRESULT ( STDMETHODCALLTYPE *GetBase )( IXCLRDataTypeDefinition * This, /* [out] */ IXCLRDataTypeDefinition **base); HRESULT ( STDMETHODCALLTYPE *GetNumFields )( IXCLRDataTypeDefinition * This, /* [in] */ ULONG32 flags, /* [out] */ ULONG32 *numFields); HRESULT ( STDMETHODCALLTYPE *StartEnumFields )( IXCLRDataTypeDefinition * This, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumField )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EndEnumFields )( IXCLRDataTypeDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumFieldsByName )( IXCLRDataTypeDefinition * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 nameFlags, /* [in] */ ULONG32 fieldFlags, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumFieldByName )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EndEnumFieldsByName )( IXCLRDataTypeDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetFieldByToken )( IXCLRDataTypeDefinition * This, /* [in] */ mdFieldDef token, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *GetTypeNotification )( IXCLRDataTypeDefinition * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *SetTypeNotification )( IXCLRDataTypeDefinition * This, /* [in] */ ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *EnumField2 )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EnumFieldByName2 )( IXCLRDataTypeDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *GetFieldByToken2 )( IXCLRDataTypeDefinition * This, /* [in] */ IXCLRDataModule *tokenScope, /* [in] */ mdFieldDef token, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataTypeDefinition **type, /* [out] */ ULONG32 *flags); END_INTERFACE } IXCLRDataTypeDefinitionVtbl; interface IXCLRDataTypeDefinition { CONST_VTBL struct IXCLRDataTypeDefinitionVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataTypeDefinition_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataTypeDefinition_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataTypeDefinition_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataTypeDefinition_GetModule(This,mod) \ ( (This)->lpVtbl -> GetModule(This,mod) ) #define IXCLRDataTypeDefinition_StartEnumMethodDefinitions(This,handle) \ ( (This)->lpVtbl -> StartEnumMethodDefinitions(This,handle) ) #define IXCLRDataTypeDefinition_EnumMethodDefinition(This,handle,methodDefinition) \ ( (This)->lpVtbl -> EnumMethodDefinition(This,handle,methodDefinition) ) #define IXCLRDataTypeDefinition_EndEnumMethodDefinitions(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodDefinitions(This,handle) ) #define IXCLRDataTypeDefinition_StartEnumMethodDefinitionsByName(This,name,flags,handle) \ ( (This)->lpVtbl -> StartEnumMethodDefinitionsByName(This,name,flags,handle) ) #define IXCLRDataTypeDefinition_EnumMethodDefinitionByName(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodDefinitionByName(This,handle,method) ) #define IXCLRDataTypeDefinition_EndEnumMethodDefinitionsByName(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodDefinitionsByName(This,handle) ) #define IXCLRDataTypeDefinition_GetMethodDefinitionByToken(This,token,methodDefinition) \ ( (This)->lpVtbl -> GetMethodDefinitionByToken(This,token,methodDefinition) ) #define IXCLRDataTypeDefinition_StartEnumInstances(This,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumInstances(This,appDomain,handle) ) #define IXCLRDataTypeDefinition_EnumInstance(This,handle,instance) \ ( (This)->lpVtbl -> EnumInstance(This,handle,instance) ) #define IXCLRDataTypeDefinition_EndEnumInstances(This,handle) \ ( (This)->lpVtbl -> EndEnumInstances(This,handle) ) #define IXCLRDataTypeDefinition_GetName(This,flags,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,nameBuf) ) #define IXCLRDataTypeDefinition_GetTokenAndScope(This,token,mod) \ ( (This)->lpVtbl -> GetTokenAndScope(This,token,mod) ) #define IXCLRDataTypeDefinition_GetCorElementType(This,type) \ ( (This)->lpVtbl -> GetCorElementType(This,type) ) #define IXCLRDataTypeDefinition_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataTypeDefinition_IsSameObject(This,type) \ ( (This)->lpVtbl -> IsSameObject(This,type) ) #define IXCLRDataTypeDefinition_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataTypeDefinition_GetArrayRank(This,rank) \ ( (This)->lpVtbl -> GetArrayRank(This,rank) ) #define IXCLRDataTypeDefinition_GetBase(This,base) \ ( (This)->lpVtbl -> GetBase(This,base) ) #define IXCLRDataTypeDefinition_GetNumFields(This,flags,numFields) \ ( (This)->lpVtbl -> GetNumFields(This,flags,numFields) ) #define IXCLRDataTypeDefinition_StartEnumFields(This,flags,handle) \ ( (This)->lpVtbl -> StartEnumFields(This,flags,handle) ) #define IXCLRDataTypeDefinition_EnumField(This,handle,nameBufLen,nameLen,nameBuf,type,flags,token) \ ( (This)->lpVtbl -> EnumField(This,handle,nameBufLen,nameLen,nameBuf,type,flags,token) ) #define IXCLRDataTypeDefinition_EndEnumFields(This,handle) \ ( (This)->lpVtbl -> EndEnumFields(This,handle) ) #define IXCLRDataTypeDefinition_StartEnumFieldsByName(This,name,nameFlags,fieldFlags,handle) \ ( (This)->lpVtbl -> StartEnumFieldsByName(This,name,nameFlags,fieldFlags,handle) ) #define IXCLRDataTypeDefinition_EnumFieldByName(This,handle,type,flags,token) \ ( (This)->lpVtbl -> EnumFieldByName(This,handle,type,flags,token) ) #define IXCLRDataTypeDefinition_EndEnumFieldsByName(This,handle) \ ( (This)->lpVtbl -> EndEnumFieldsByName(This,handle) ) #define IXCLRDataTypeDefinition_GetFieldByToken(This,token,nameBufLen,nameLen,nameBuf,type,flags) \ ( (This)->lpVtbl -> GetFieldByToken(This,token,nameBufLen,nameLen,nameBuf,type,flags) ) #define IXCLRDataTypeDefinition_GetTypeNotification(This,flags) \ ( (This)->lpVtbl -> GetTypeNotification(This,flags) ) #define IXCLRDataTypeDefinition_SetTypeNotification(This,flags) \ ( (This)->lpVtbl -> SetTypeNotification(This,flags) ) #define IXCLRDataTypeDefinition_EnumField2(This,handle,nameBufLen,nameLen,nameBuf,type,flags,tokenScope,token) \ ( (This)->lpVtbl -> EnumField2(This,handle,nameBufLen,nameLen,nameBuf,type,flags,tokenScope,token) ) #define IXCLRDataTypeDefinition_EnumFieldByName2(This,handle,type,flags,tokenScope,token) \ ( (This)->lpVtbl -> EnumFieldByName2(This,handle,type,flags,tokenScope,token) ) #define IXCLRDataTypeDefinition_GetFieldByToken2(This,tokenScope,token,nameBufLen,nameLen,nameBuf,type,flags) \ ( (This)->lpVtbl -> GetFieldByToken2(This,tokenScope,token,nameBufLen,nameLen,nameBuf,type,flags) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataTypeDefinition_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0011 */ /* [local] */ #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0011_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0011_v0_0_s_ifspec; #ifndef __IXCLRDataTypeInstance_INTERFACE_DEFINED__ #define __IXCLRDataTypeInstance_INTERFACE_DEFINED__ /* interface IXCLRDataTypeInstance */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataTypeInstance; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("4D078D91-9CB3-4b0d-97AC-28C8A5A82597") IXCLRDataTypeInstance : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstances( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodInstance( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **methodInstance) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstances( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumMethodInstancesByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumMethodInstanceByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumMethodInstancesByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields( /* [out] */ ULONG32 *numFields) = 0; virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByIndex( /* [in] */ ULONG32 index, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments( /* [out] */ ULONG32 *numTypeArgs) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetModule( /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE GetDefinition( /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataTypeInstance *type) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumStaticFields2( /* [in] */ ULONG32 flags, /* [out] */ ULONG32 *numFields) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFields( /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumStaticField( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFields( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumStaticFieldsByName2( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 nameFlags, /* [in] */ ULONG32 fieldFlags, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName2( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumStaticFieldsByName2( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken( /* [in] */ mdFieldDef token, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetBase( /* [out] */ IXCLRDataTypeInstance **base) = 0; virtual HRESULT STDMETHODCALLTYPE EnumStaticField2( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EnumStaticFieldByName3( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE GetStaticFieldByToken2( /* [in] */ IXCLRDataModule *tokenScope, /* [in] */ mdFieldDef token, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; }; #else /* C style interface */ typedef struct IXCLRDataTypeInstanceVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataTypeInstance * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataTypeInstance * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataTypeInstance * This); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstances )( IXCLRDataTypeInstance * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodInstance )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **methodInstance); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstances )( IXCLRDataTypeInstance * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumMethodInstancesByName )( IXCLRDataTypeInstance * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumMethodInstanceByName )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **method); HRESULT ( STDMETHODCALLTYPE *EndEnumMethodInstancesByName )( IXCLRDataTypeInstance * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetNumStaticFields )( IXCLRDataTypeInstance * This, /* [out] */ ULONG32 *numFields); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldByIndex )( IXCLRDataTypeInstance * This, /* [in] */ ULONG32 index, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *StartEnumStaticFieldsByName )( IXCLRDataTypeInstance * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumStaticFieldByName )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *EndEnumStaticFieldsByName )( IXCLRDataTypeInstance * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetNumTypeArguments )( IXCLRDataTypeInstance * This, /* [out] */ ULONG32 *numTypeArgs); HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentByIndex )( IXCLRDataTypeInstance * This, /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataTypeInstance * This, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetModule )( IXCLRDataTypeInstance * This, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *GetDefinition )( IXCLRDataTypeInstance * This, /* [out] */ IXCLRDataTypeDefinition **typeDefinition); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataTypeInstance * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataTypeInstance * This, /* [in] */ IXCLRDataTypeInstance *type); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataTypeInstance * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetNumStaticFields2 )( IXCLRDataTypeInstance * This, /* [in] */ ULONG32 flags, /* [out] */ ULONG32 *numFields); HRESULT ( STDMETHODCALLTYPE *StartEnumStaticFields )( IXCLRDataTypeInstance * This, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumStaticField )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *EndEnumStaticFields )( IXCLRDataTypeInstance * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumStaticFieldsByName2 )( IXCLRDataTypeInstance * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 nameFlags, /* [in] */ ULONG32 fieldFlags, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumStaticFieldByName2 )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *EndEnumStaticFieldsByName2 )( IXCLRDataTypeInstance * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldByToken )( IXCLRDataTypeInstance * This, /* [in] */ mdFieldDef token, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetBase )( IXCLRDataTypeInstance * This, /* [out] */ IXCLRDataTypeInstance **base); HRESULT ( STDMETHODCALLTYPE *EnumStaticField2 )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EnumStaticFieldByName3 )( IXCLRDataTypeInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **value, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *GetStaticFieldByToken2 )( IXCLRDataTypeInstance * This, /* [in] */ IXCLRDataModule *tokenScope, /* [in] */ mdFieldDef token, /* [in] */ IXCLRDataTask *tlsTask, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); END_INTERFACE } IXCLRDataTypeInstanceVtbl; interface IXCLRDataTypeInstance { CONST_VTBL struct IXCLRDataTypeInstanceVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataTypeInstance_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataTypeInstance_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataTypeInstance_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataTypeInstance_StartEnumMethodInstances(This,handle) \ ( (This)->lpVtbl -> StartEnumMethodInstances(This,handle) ) #define IXCLRDataTypeInstance_EnumMethodInstance(This,handle,methodInstance) \ ( (This)->lpVtbl -> EnumMethodInstance(This,handle,methodInstance) ) #define IXCLRDataTypeInstance_EndEnumMethodInstances(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodInstances(This,handle) ) #define IXCLRDataTypeInstance_StartEnumMethodInstancesByName(This,name,flags,handle) \ ( (This)->lpVtbl -> StartEnumMethodInstancesByName(This,name,flags,handle) ) #define IXCLRDataTypeInstance_EnumMethodInstanceByName(This,handle,method) \ ( (This)->lpVtbl -> EnumMethodInstanceByName(This,handle,method) ) #define IXCLRDataTypeInstance_EndEnumMethodInstancesByName(This,handle) \ ( (This)->lpVtbl -> EndEnumMethodInstancesByName(This,handle) ) #define IXCLRDataTypeInstance_GetNumStaticFields(This,numFields) \ ( (This)->lpVtbl -> GetNumStaticFields(This,numFields) ) #define IXCLRDataTypeInstance_GetStaticFieldByIndex(This,index,tlsTask,field,bufLen,nameLen,nameBuf,token) \ ( (This)->lpVtbl -> GetStaticFieldByIndex(This,index,tlsTask,field,bufLen,nameLen,nameBuf,token) ) #define IXCLRDataTypeInstance_StartEnumStaticFieldsByName(This,name,flags,tlsTask,handle) \ ( (This)->lpVtbl -> StartEnumStaticFieldsByName(This,name,flags,tlsTask,handle) ) #define IXCLRDataTypeInstance_EnumStaticFieldByName(This,handle,value) \ ( (This)->lpVtbl -> EnumStaticFieldByName(This,handle,value) ) #define IXCLRDataTypeInstance_EndEnumStaticFieldsByName(This,handle) \ ( (This)->lpVtbl -> EndEnumStaticFieldsByName(This,handle) ) #define IXCLRDataTypeInstance_GetNumTypeArguments(This,numTypeArgs) \ ( (This)->lpVtbl -> GetNumTypeArguments(This,numTypeArgs) ) #define IXCLRDataTypeInstance_GetTypeArgumentByIndex(This,index,typeArg) \ ( (This)->lpVtbl -> GetTypeArgumentByIndex(This,index,typeArg) ) #define IXCLRDataTypeInstance_GetName(This,flags,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,nameBuf) ) #define IXCLRDataTypeInstance_GetModule(This,mod) \ ( (This)->lpVtbl -> GetModule(This,mod) ) #define IXCLRDataTypeInstance_GetDefinition(This,typeDefinition) \ ( (This)->lpVtbl -> GetDefinition(This,typeDefinition) ) #define IXCLRDataTypeInstance_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataTypeInstance_IsSameObject(This,type) \ ( (This)->lpVtbl -> IsSameObject(This,type) ) #define IXCLRDataTypeInstance_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataTypeInstance_GetNumStaticFields2(This,flags,numFields) \ ( (This)->lpVtbl -> GetNumStaticFields2(This,flags,numFields) ) #define IXCLRDataTypeInstance_StartEnumStaticFields(This,flags,tlsTask,handle) \ ( (This)->lpVtbl -> StartEnumStaticFields(This,flags,tlsTask,handle) ) #define IXCLRDataTypeInstance_EnumStaticField(This,handle,value) \ ( (This)->lpVtbl -> EnumStaticField(This,handle,value) ) #define IXCLRDataTypeInstance_EndEnumStaticFields(This,handle) \ ( (This)->lpVtbl -> EndEnumStaticFields(This,handle) ) #define IXCLRDataTypeInstance_StartEnumStaticFieldsByName2(This,name,nameFlags,fieldFlags,tlsTask,handle) \ ( (This)->lpVtbl -> StartEnumStaticFieldsByName2(This,name,nameFlags,fieldFlags,tlsTask,handle) ) #define IXCLRDataTypeInstance_EnumStaticFieldByName2(This,handle,value) \ ( (This)->lpVtbl -> EnumStaticFieldByName2(This,handle,value) ) #define IXCLRDataTypeInstance_EndEnumStaticFieldsByName2(This,handle) \ ( (This)->lpVtbl -> EndEnumStaticFieldsByName2(This,handle) ) #define IXCLRDataTypeInstance_GetStaticFieldByToken(This,token,tlsTask,field,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetStaticFieldByToken(This,token,tlsTask,field,bufLen,nameLen,nameBuf) ) #define IXCLRDataTypeInstance_GetBase(This,base) \ ( (This)->lpVtbl -> GetBase(This,base) ) #define IXCLRDataTypeInstance_EnumStaticField2(This,handle,value,bufLen,nameLen,nameBuf,tokenScope,token) \ ( (This)->lpVtbl -> EnumStaticField2(This,handle,value,bufLen,nameLen,nameBuf,tokenScope,token) ) #define IXCLRDataTypeInstance_EnumStaticFieldByName3(This,handle,value,tokenScope,token) \ ( (This)->lpVtbl -> EnumStaticFieldByName3(This,handle,value,tokenScope,token) ) #define IXCLRDataTypeInstance_GetStaticFieldByToken2(This,tokenScope,token,tlsTask,field,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetStaticFieldByToken2(This,tokenScope,token,tlsTask,field,bufLen,nameLen,nameBuf) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataTypeInstance_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0012 */ /* [local] */ #pragma warning(pop) typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0012_0001 { CLRDATA_SOURCE_TYPE_INVALID = 0 } CLRDataSourceType; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0012_0002 { CLRDATA_IL_OFFSET_NO_MAPPING = -1, CLRDATA_IL_OFFSET_PROLOG = -2, CLRDATA_IL_OFFSET_EPILOG = -3 } CLRDATA_IL_OFFSET_MARKER; typedef /* [public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0012_0003 { ULONG32 ilOffset; CLRDATA_ADDRESS startAddress; CLRDATA_ADDRESS endAddress; CLRDataSourceType type; } CLRDATA_IL_ADDRESS_MAP; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0012_0004 { CLRDATA_METHOD_DEFAULT = 0, CLRDATA_METHOD_HAS_THIS = 0x1 } CLRDataMethodFlag; typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0012_0005 { CLRDATA_METHDEF_IL = 0 } CLRDataMethodDefinitionExtentType; typedef /* [public][public] */ struct __MIDL___MIDL_itf_xclrdata_0000_0012_0006 { CLRDATA_ADDRESS startAddress; CLRDATA_ADDRESS endAddress; ULONG32 enCVersion; CLRDataMethodDefinitionExtentType type; } CLRDATA_METHDEF_EXTENT; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0012_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0012_v0_0_s_ifspec; #ifndef __IXCLRDataMethodDefinition_INTERFACE_DEFINED__ #define __IXCLRDataMethodDefinition_INTERFACE_DEFINED__ /* interface IXCLRDataMethodDefinition */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataMethodDefinition; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("AAF60008-FB2C-420b-8FB1-42D244A54A97") IXCLRDataMethodDefinition : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetTypeDefinition( /* [out] */ IXCLRDataTypeDefinition **typeDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumInstances( /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumInstance( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **instance) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumInstances( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope( /* [out] */ mdMethodDef *token, /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataMethodDefinition *method) = 0; virtual HRESULT STDMETHODCALLTYPE GetLatestEnCVersion( /* [out] */ ULONG32 *version) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumExtents( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumExtent( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_METHDEF_EXTENT *extent) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumExtents( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeNotification( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE SetCodeNotification( /* [in] */ ULONG32 flags) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress( /* [out] */ CLRDATA_ADDRESS *addr) = 0; virtual HRESULT STDMETHODCALLTYPE HasClassOrMethodInstantiation( /* [out] */ BOOL *bGeneric) = 0; }; #else /* C style interface */ typedef struct IXCLRDataMethodDefinitionVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataMethodDefinition * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataMethodDefinition * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataMethodDefinition * This); HRESULT ( STDMETHODCALLTYPE *GetTypeDefinition )( IXCLRDataMethodDefinition * This, /* [out] */ IXCLRDataTypeDefinition **typeDefinition); HRESULT ( STDMETHODCALLTYPE *StartEnumInstances )( IXCLRDataMethodDefinition * This, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumInstance )( IXCLRDataMethodDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **instance); HRESULT ( STDMETHODCALLTYPE *EndEnumInstances )( IXCLRDataMethodDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataMethodDefinition * This, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetTokenAndScope )( IXCLRDataMethodDefinition * This, /* [out] */ mdMethodDef *token, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataMethodDefinition * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataMethodDefinition * This, /* [in] */ IXCLRDataMethodDefinition *method); HRESULT ( STDMETHODCALLTYPE *GetLatestEnCVersion )( IXCLRDataMethodDefinition * This, /* [out] */ ULONG32 *version); HRESULT ( STDMETHODCALLTYPE *StartEnumExtents )( IXCLRDataMethodDefinition * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumExtent )( IXCLRDataMethodDefinition * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_METHDEF_EXTENT *extent); HRESULT ( STDMETHODCALLTYPE *EndEnumExtents )( IXCLRDataMethodDefinition * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetCodeNotification )( IXCLRDataMethodDefinition * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *SetCodeNotification )( IXCLRDataMethodDefinition * This, /* [in] */ ULONG32 flags); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataMethodDefinition * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetRepresentativeEntryAddress )( IXCLRDataMethodDefinition * This, /* [out] */ CLRDATA_ADDRESS *addr); HRESULT ( STDMETHODCALLTYPE *HasClassOrMethodInstantiation )( IXCLRDataMethodDefinition * This, /* [out] */ BOOL *bGeneric); END_INTERFACE } IXCLRDataMethodDefinitionVtbl; interface IXCLRDataMethodDefinition { CONST_VTBL struct IXCLRDataMethodDefinitionVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataMethodDefinition_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataMethodDefinition_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataMethodDefinition_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataMethodDefinition_GetTypeDefinition(This,typeDefinition) \ ( (This)->lpVtbl -> GetTypeDefinition(This,typeDefinition) ) #define IXCLRDataMethodDefinition_StartEnumInstances(This,appDomain,handle) \ ( (This)->lpVtbl -> StartEnumInstances(This,appDomain,handle) ) #define IXCLRDataMethodDefinition_EnumInstance(This,handle,instance) \ ( (This)->lpVtbl -> EnumInstance(This,handle,instance) ) #define IXCLRDataMethodDefinition_EndEnumInstances(This,handle) \ ( (This)->lpVtbl -> EndEnumInstances(This,handle) ) #define IXCLRDataMethodDefinition_GetName(This,flags,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,name) ) #define IXCLRDataMethodDefinition_GetTokenAndScope(This,token,mod) \ ( (This)->lpVtbl -> GetTokenAndScope(This,token,mod) ) #define IXCLRDataMethodDefinition_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataMethodDefinition_IsSameObject(This,method) \ ( (This)->lpVtbl -> IsSameObject(This,method) ) #define IXCLRDataMethodDefinition_GetLatestEnCVersion(This,version) \ ( (This)->lpVtbl -> GetLatestEnCVersion(This,version) ) #define IXCLRDataMethodDefinition_StartEnumExtents(This,handle) \ ( (This)->lpVtbl -> StartEnumExtents(This,handle) ) #define IXCLRDataMethodDefinition_EnumExtent(This,handle,extent) \ ( (This)->lpVtbl -> EnumExtent(This,handle,extent) ) #define IXCLRDataMethodDefinition_EndEnumExtents(This,handle) \ ( (This)->lpVtbl -> EndEnumExtents(This,handle) ) #define IXCLRDataMethodDefinition_GetCodeNotification(This,flags) \ ( (This)->lpVtbl -> GetCodeNotification(This,flags) ) #define IXCLRDataMethodDefinition_SetCodeNotification(This,flags) \ ( (This)->lpVtbl -> SetCodeNotification(This,flags) ) #define IXCLRDataMethodDefinition_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataMethodDefinition_GetRepresentativeEntryAddress(This,addr) \ ( (This)->lpVtbl -> GetRepresentativeEntryAddress(This,addr) ) #define IXCLRDataMethodDefinition_HasClassOrMethodInstantiation(This,bGeneric) \ ( (This)->lpVtbl -> HasClassOrMethodInstantiation(This,bGeneric) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataMethodDefinition_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0013 */ /* [local] */ #pragma warning(pop) #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0013_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0013_v0_0_s_ifspec; #ifndef __IXCLRDataMethodInstance_INTERFACE_DEFINED__ #define __IXCLRDataMethodInstance_INTERFACE_DEFINED__ /* interface IXCLRDataMethodInstance */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataMethodInstance; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("ECD73800-22CA-4b0d-AB55-E9BA7E6318A5") IXCLRDataMethodInstance : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetTypeInstance( /* [out] */ IXCLRDataTypeInstance **typeInstance) = 0; virtual HRESULT STDMETHODCALLTYPE GetDefinition( /* [out] */ IXCLRDataMethodDefinition **methodDefinition) = 0; virtual HRESULT STDMETHODCALLTYPE GetTokenAndScope( /* [out] */ mdMethodDef *token, /* [out] */ IXCLRDataModule **mod) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataMethodInstance *method) = 0; virtual HRESULT STDMETHODCALLTYPE GetEnCVersion( /* [out] */ ULONG32 *version) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments( /* [out] */ ULONG32 *numTypeArgs) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg) = 0; virtual HRESULT STDMETHODCALLTYPE GetILOffsetsByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 offsetsLen, /* [out] */ ULONG32 *offsetsNeeded, /* [size_is][out] */ ULONG32 ilOffsets[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddressRangesByILOffset( /* [in] */ ULONG32 ilOffset, /* [in] */ ULONG32 rangesLen, /* [out] */ ULONG32 *rangesNeeded, /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetILAddressMap( /* [in] */ ULONG32 mapLen, /* [out] */ ULONG32 *mapNeeded, /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumExtents( /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumExtent( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_ADDRESS_RANGE *extent) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumExtents( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetRepresentativeEntryAddress( /* [out] */ CLRDATA_ADDRESS *addr) = 0; }; #else /* C style interface */ typedef struct IXCLRDataMethodInstanceVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataMethodInstance * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataMethodInstance * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataMethodInstance * This); HRESULT ( STDMETHODCALLTYPE *GetTypeInstance )( IXCLRDataMethodInstance * This, /* [out] */ IXCLRDataTypeInstance **typeInstance); HRESULT ( STDMETHODCALLTYPE *GetDefinition )( IXCLRDataMethodInstance * This, /* [out] */ IXCLRDataMethodDefinition **methodDefinition); HRESULT ( STDMETHODCALLTYPE *GetTokenAndScope )( IXCLRDataMethodInstance * This, /* [out] */ mdMethodDef *token, /* [out] */ IXCLRDataModule **mod); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataMethodInstance * This, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataMethodInstance * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataMethodInstance * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *GetEnCVersion )( IXCLRDataMethodInstance * This, /* [out] */ ULONG32 *version); HRESULT ( STDMETHODCALLTYPE *GetNumTypeArguments )( IXCLRDataMethodInstance * This, /* [out] */ ULONG32 *numTypeArgs); HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentByIndex )( IXCLRDataMethodInstance * This, /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg); HRESULT ( STDMETHODCALLTYPE *GetILOffsetsByAddress )( IXCLRDataMethodInstance * This, /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 offsetsLen, /* [out] */ ULONG32 *offsetsNeeded, /* [size_is][out] */ ULONG32 ilOffsets[ ]); HRESULT ( STDMETHODCALLTYPE *GetAddressRangesByILOffset )( IXCLRDataMethodInstance * This, /* [in] */ ULONG32 ilOffset, /* [in] */ ULONG32 rangesLen, /* [out] */ ULONG32 *rangesNeeded, /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]); HRESULT ( STDMETHODCALLTYPE *GetILAddressMap )( IXCLRDataMethodInstance * This, /* [in] */ ULONG32 mapLen, /* [out] */ ULONG32 *mapNeeded, /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]); HRESULT ( STDMETHODCALLTYPE *StartEnumExtents )( IXCLRDataMethodInstance * This, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumExtent )( IXCLRDataMethodInstance * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_ADDRESS_RANGE *extent); HRESULT ( STDMETHODCALLTYPE *EndEnumExtents )( IXCLRDataMethodInstance * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataMethodInstance * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetRepresentativeEntryAddress )( IXCLRDataMethodInstance * This, /* [out] */ CLRDATA_ADDRESS *addr); END_INTERFACE } IXCLRDataMethodInstanceVtbl; interface IXCLRDataMethodInstance { CONST_VTBL struct IXCLRDataMethodInstanceVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataMethodInstance_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataMethodInstance_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataMethodInstance_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataMethodInstance_GetTypeInstance(This,typeInstance) \ ( (This)->lpVtbl -> GetTypeInstance(This,typeInstance) ) #define IXCLRDataMethodInstance_GetDefinition(This,methodDefinition) \ ( (This)->lpVtbl -> GetDefinition(This,methodDefinition) ) #define IXCLRDataMethodInstance_GetTokenAndScope(This,token,mod) \ ( (This)->lpVtbl -> GetTokenAndScope(This,token,mod) ) #define IXCLRDataMethodInstance_GetName(This,flags,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetName(This,flags,bufLen,nameLen,nameBuf) ) #define IXCLRDataMethodInstance_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataMethodInstance_IsSameObject(This,method) \ ( (This)->lpVtbl -> IsSameObject(This,method) ) #define IXCLRDataMethodInstance_GetEnCVersion(This,version) \ ( (This)->lpVtbl -> GetEnCVersion(This,version) ) #define IXCLRDataMethodInstance_GetNumTypeArguments(This,numTypeArgs) \ ( (This)->lpVtbl -> GetNumTypeArguments(This,numTypeArgs) ) #define IXCLRDataMethodInstance_GetTypeArgumentByIndex(This,index,typeArg) \ ( (This)->lpVtbl -> GetTypeArgumentByIndex(This,index,typeArg) ) #define IXCLRDataMethodInstance_GetILOffsetsByAddress(This,address,offsetsLen,offsetsNeeded,ilOffsets) \ ( (This)->lpVtbl -> GetILOffsetsByAddress(This,address,offsetsLen,offsetsNeeded,ilOffsets) ) #define IXCLRDataMethodInstance_GetAddressRangesByILOffset(This,ilOffset,rangesLen,rangesNeeded,addressRanges) \ ( (This)->lpVtbl -> GetAddressRangesByILOffset(This,ilOffset,rangesLen,rangesNeeded,addressRanges) ) #define IXCLRDataMethodInstance_GetILAddressMap(This,mapLen,mapNeeded,maps) \ ( (This)->lpVtbl -> GetILAddressMap(This,mapLen,mapNeeded,maps) ) #define IXCLRDataMethodInstance_StartEnumExtents(This,handle) \ ( (This)->lpVtbl -> StartEnumExtents(This,handle) ) #define IXCLRDataMethodInstance_EnumExtent(This,handle,extent) \ ( (This)->lpVtbl -> EnumExtent(This,handle,extent) ) #define IXCLRDataMethodInstance_EndEnumExtents(This,handle) \ ( (This)->lpVtbl -> EndEnumExtents(This,handle) ) #define IXCLRDataMethodInstance_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataMethodInstance_GetRepresentativeEntryAddress(This,addr) \ ( (This)->lpVtbl -> GetRepresentativeEntryAddress(This,addr) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataMethodInstance_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0014 */ /* [local] */ #pragma warning(pop) typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0014_0001 { CLRDATA_TASK_DEFAULT = 0, CLRDATA_TASK_WAITING_FOR_GC = 0x1 } CLRDataTaskFlag; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0014_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0014_v0_0_s_ifspec; #ifndef __IXCLRDataTask_INTERFACE_DEFINED__ #define __IXCLRDataTask_INTERFACE_DEFINED__ /* interface IXCLRDataTask */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataTask; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("A5B0BEEA-EC62-4618-8012-A24FFC23934C") IXCLRDataTask : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetProcess( /* [out] */ IXCLRDataProcess **process) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentAppDomain( /* [out] */ IXCLRDataAppDomain **appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE GetUniqueID( /* [out] */ ULONG64 *id) = 0; virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameObject( /* [in] */ IXCLRDataTask *task) = 0; virtual HRESULT STDMETHODCALLTYPE GetManagedObject( /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE GetDesiredExecutionState( /* [out] */ ULONG32 *state) = 0; virtual HRESULT STDMETHODCALLTYPE SetDesiredExecutionState( /* [in] */ ULONG32 state) = 0; virtual HRESULT STDMETHODCALLTYPE CreateStackWalk( /* [in] */ ULONG32 flags, /* [out] */ IXCLRDataStackWalk **stackWalk) = 0; virtual HRESULT STDMETHODCALLTYPE GetOSThreadID( /* [out] */ ULONG32 *id) = 0; virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetContext( /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCurrentExceptionState( /* [out] */ IXCLRDataExceptionState **exception) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetLastExceptionState( /* [out] */ IXCLRDataExceptionState **exception) = 0; }; #else /* C style interface */ typedef struct IXCLRDataTaskVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataTask * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataTask * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataTask * This); HRESULT ( STDMETHODCALLTYPE *GetProcess )( IXCLRDataTask * This, /* [out] */ IXCLRDataProcess **process); HRESULT ( STDMETHODCALLTYPE *GetCurrentAppDomain )( IXCLRDataTask * This, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *GetUniqueID )( IXCLRDataTask * This, /* [out] */ ULONG64 *id); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataTask * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *IsSameObject )( IXCLRDataTask * This, /* [in] */ IXCLRDataTask *task); HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( IXCLRDataTask * This, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *GetDesiredExecutionState )( IXCLRDataTask * This, /* [out] */ ULONG32 *state); HRESULT ( STDMETHODCALLTYPE *SetDesiredExecutionState )( IXCLRDataTask * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *CreateStackWalk )( IXCLRDataTask * This, /* [in] */ ULONG32 flags, /* [out] */ IXCLRDataStackWalk **stackWalk); HRESULT ( STDMETHODCALLTYPE *GetOSThreadID )( IXCLRDataTask * This, /* [out] */ ULONG32 *id); HRESULT ( STDMETHODCALLTYPE *GetContext )( IXCLRDataTask * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); HRESULT ( STDMETHODCALLTYPE *SetContext )( IXCLRDataTask * This, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]); HRESULT ( STDMETHODCALLTYPE *GetCurrentExceptionState )( IXCLRDataTask * This, /* [out] */ IXCLRDataExceptionState **exception); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataTask * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetName )( IXCLRDataTask * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetLastExceptionState )( IXCLRDataTask * This, /* [out] */ IXCLRDataExceptionState **exception); END_INTERFACE } IXCLRDataTaskVtbl; interface IXCLRDataTask { CONST_VTBL struct IXCLRDataTaskVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataTask_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataTask_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataTask_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataTask_GetProcess(This,process) \ ( (This)->lpVtbl -> GetProcess(This,process) ) #define IXCLRDataTask_GetCurrentAppDomain(This,appDomain) \ ( (This)->lpVtbl -> GetCurrentAppDomain(This,appDomain) ) #define IXCLRDataTask_GetUniqueID(This,id) \ ( (This)->lpVtbl -> GetUniqueID(This,id) ) #define IXCLRDataTask_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataTask_IsSameObject(This,task) \ ( (This)->lpVtbl -> IsSameObject(This,task) ) #define IXCLRDataTask_GetManagedObject(This,value) \ ( (This)->lpVtbl -> GetManagedObject(This,value) ) #define IXCLRDataTask_GetDesiredExecutionState(This,state) \ ( (This)->lpVtbl -> GetDesiredExecutionState(This,state) ) #define IXCLRDataTask_SetDesiredExecutionState(This,state) \ ( (This)->lpVtbl -> SetDesiredExecutionState(This,state) ) #define IXCLRDataTask_CreateStackWalk(This,flags,stackWalk) \ ( (This)->lpVtbl -> CreateStackWalk(This,flags,stackWalk) ) #define IXCLRDataTask_GetOSThreadID(This,id) \ ( (This)->lpVtbl -> GetOSThreadID(This,id) ) #define IXCLRDataTask_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) #define IXCLRDataTask_SetContext(This,contextSize,context) \ ( (This)->lpVtbl -> SetContext(This,contextSize,context) ) #define IXCLRDataTask_GetCurrentExceptionState(This,exception) \ ( (This)->lpVtbl -> GetCurrentExceptionState(This,exception) ) #define IXCLRDataTask_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataTask_GetName(This,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetName(This,bufLen,nameLen,name) ) #define IXCLRDataTask_GetLastExceptionState(This,exception) \ ( (This)->lpVtbl -> GetLastExceptionState(This,exception) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataTask_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0015 */ /* [local] */ #pragma warning(pop) typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0015_0001 { CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE = 0x4, CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE = 0x8 } CLRDataSimpleFrameType; typedef /* [public][public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0015_0002 { CLRDATA_DETFRAME_UNRECOGNIZED = 0, CLRDATA_DETFRAME_UNKNOWN_STUB = ( CLRDATA_DETFRAME_UNRECOGNIZED + 1 ) , CLRDATA_DETFRAME_CLASS_INIT = ( CLRDATA_DETFRAME_UNKNOWN_STUB + 1 ) , CLRDATA_DETFRAME_EXCEPTION_FILTER = ( CLRDATA_DETFRAME_CLASS_INIT + 1 ) , CLRDATA_DETFRAME_SECURITY = ( CLRDATA_DETFRAME_EXCEPTION_FILTER + 1 ) , CLRDATA_DETFRAME_CONTEXT_POLICY = ( CLRDATA_DETFRAME_SECURITY + 1 ) , CLRDATA_DETFRAME_INTERCEPTION = ( CLRDATA_DETFRAME_CONTEXT_POLICY + 1 ) , CLRDATA_DETFRAME_PROCESS_START = ( CLRDATA_DETFRAME_INTERCEPTION + 1 ) , CLRDATA_DETFRAME_THREAD_START = ( CLRDATA_DETFRAME_PROCESS_START + 1 ) , CLRDATA_DETFRAME_TRANSITION_TO_MANAGED = ( CLRDATA_DETFRAME_THREAD_START + 1 ) , CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED = ( CLRDATA_DETFRAME_TRANSITION_TO_MANAGED + 1 ) , CLRDATA_DETFRAME_COM_INTEROP_STUB = ( CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED + 1 ) , CLRDATA_DETFRAME_DEBUGGER_EVAL = ( CLRDATA_DETFRAME_COM_INTEROP_STUB + 1 ) , CLRDATA_DETFRAME_CONTEXT_SWITCH = ( CLRDATA_DETFRAME_DEBUGGER_EVAL + 1 ) , CLRDATA_DETFRAME_FUNC_EVAL = ( CLRDATA_DETFRAME_CONTEXT_SWITCH + 1 ) , CLRDATA_DETFRAME_FINALLY = ( CLRDATA_DETFRAME_FUNC_EVAL + 1 ) } CLRDataDetailedFrameType; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0015_0003 { CLRDATA_STACK_WALK_REQUEST_SET_FIRST_FRAME = 0xe1000000 } CLRDataStackWalkRequest; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0015_0004 { CLRDATA_STACK_SET_UNWIND_CONTEXT = 0, CLRDATA_STACK_SET_CURRENT_CONTEXT = 0x1 } CLRDataStackSetContextFlag; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0015_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0015_v0_0_s_ifspec; #ifndef __IXCLRDataStackWalk_INTERFACE_DEFINED__ #define __IXCLRDataStackWalk_INTERFACE_DEFINED__ /* interface IXCLRDataStackWalk */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataStackWalk; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E59D8D22-ADA7-49a2-89B5-A415AFCFC95F") IXCLRDataStackWalk : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetContext( /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE Next( void) = 0; virtual HRESULT STDMETHODCALLTYPE GetStackSizeSkipped( /* [out] */ ULONG64 *stackSizeSkipped) = 0; virtual HRESULT STDMETHODCALLTYPE GetFrameType( /* [out] */ CLRDataSimpleFrameType *simpleType, /* [out] */ CLRDataDetailedFrameType *detailedType) = 0; virtual HRESULT STDMETHODCALLTYPE GetFrame( /* [out] */ IXCLRDataFrame **frame) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE SetContext2( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) = 0; }; #else /* C style interface */ typedef struct IXCLRDataStackWalkVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataStackWalk * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataStackWalk * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataStackWalk * This); HRESULT ( STDMETHODCALLTYPE *GetContext )( IXCLRDataStackWalk * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); HRESULT ( STDMETHODCALLTYPE *SetContext )( IXCLRDataStackWalk * This, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]); HRESULT ( STDMETHODCALLTYPE *Next )( IXCLRDataStackWalk * This); HRESULT ( STDMETHODCALLTYPE *GetStackSizeSkipped )( IXCLRDataStackWalk * This, /* [out] */ ULONG64 *stackSizeSkipped); HRESULT ( STDMETHODCALLTYPE *GetFrameType )( IXCLRDataStackWalk * This, /* [out] */ CLRDataSimpleFrameType *simpleType, /* [out] */ CLRDataDetailedFrameType *detailedType); HRESULT ( STDMETHODCALLTYPE *GetFrame )( IXCLRDataStackWalk * This, /* [out] */ IXCLRDataFrame **frame); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataStackWalk * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *SetContext2 )( IXCLRDataStackWalk * This, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]); END_INTERFACE } IXCLRDataStackWalkVtbl; interface IXCLRDataStackWalk { CONST_VTBL struct IXCLRDataStackWalkVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataStackWalk_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataStackWalk_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataStackWalk_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataStackWalk_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) #define IXCLRDataStackWalk_SetContext(This,contextSize,context) \ ( (This)->lpVtbl -> SetContext(This,contextSize,context) ) #define IXCLRDataStackWalk_Next(This) \ ( (This)->lpVtbl -> Next(This) ) #define IXCLRDataStackWalk_GetStackSizeSkipped(This,stackSizeSkipped) \ ( (This)->lpVtbl -> GetStackSizeSkipped(This,stackSizeSkipped) ) #define IXCLRDataStackWalk_GetFrameType(This,simpleType,detailedType) \ ( (This)->lpVtbl -> GetFrameType(This,simpleType,detailedType) ) #define IXCLRDataStackWalk_GetFrame(This,frame) \ ( (This)->lpVtbl -> GetFrame(This,frame) ) #define IXCLRDataStackWalk_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataStackWalk_SetContext2(This,flags,contextSize,context) \ ( (This)->lpVtbl -> SetContext2(This,flags,contextSize,context) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataStackWalk_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0016 */ /* [local] */ #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0016_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0016_v0_0_s_ifspec; #ifndef __IXCLRDataFrame_INTERFACE_DEFINED__ #define __IXCLRDataFrame_INTERFACE_DEFINED__ /* interface IXCLRDataFrame */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataFrame; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("271498C2-4085-4766-BC3A-7F8ED188A173") IXCLRDataFrame : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetFrameType( /* [out] */ CLRDataSimpleFrameType *simpleType, /* [out] */ CLRDataDetailedFrameType *detailedType) = 0; virtual HRESULT STDMETHODCALLTYPE GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetAppDomain( /* [out] */ IXCLRDataAppDomain **appDomain) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumArguments( /* [out] */ ULONG32 *numArgs) = 0; virtual HRESULT STDMETHODCALLTYPE GetArgumentByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataValue **arg, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumLocalVariables( /* [out] */ ULONG32 *numLocals) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocalVariableByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataValue **localVariable, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetCodeName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetMethodInstance( /* [out] */ IXCLRDataMethodInstance **method) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumTypeArguments( /* [out] */ ULONG32 *numTypeArgs) = 0; virtual HRESULT STDMETHODCALLTYPE GetTypeArgumentByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg) = 0; }; #else /* C style interface */ typedef struct IXCLRDataFrameVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataFrame * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataFrame * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataFrame * This); HRESULT ( STDMETHODCALLTYPE *GetFrameType )( IXCLRDataFrame * This, /* [out] */ CLRDataSimpleFrameType *simpleType, /* [out] */ CLRDataDetailedFrameType *detailedType); HRESULT ( STDMETHODCALLTYPE *GetContext )( IXCLRDataFrame * This, /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetAppDomain )( IXCLRDataFrame * This, /* [out] */ IXCLRDataAppDomain **appDomain); HRESULT ( STDMETHODCALLTYPE *GetNumArguments )( IXCLRDataFrame * This, /* [out] */ ULONG32 *numArgs); HRESULT ( STDMETHODCALLTYPE *GetArgumentByIndex )( IXCLRDataFrame * This, /* [in] */ ULONG32 index, /* [out] */ IXCLRDataValue **arg, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetNumLocalVariables )( IXCLRDataFrame * This, /* [out] */ ULONG32 *numLocals); HRESULT ( STDMETHODCALLTYPE *GetLocalVariableByIndex )( IXCLRDataFrame * This, /* [in] */ ULONG32 index, /* [out] */ IXCLRDataValue **localVariable, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR name[ ]); HRESULT ( STDMETHODCALLTYPE *GetCodeName )( IXCLRDataFrame * This, /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetMethodInstance )( IXCLRDataFrame * This, /* [out] */ IXCLRDataMethodInstance **method); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataFrame * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetNumTypeArguments )( IXCLRDataFrame * This, /* [out] */ ULONG32 *numTypeArgs); HRESULT ( STDMETHODCALLTYPE *GetTypeArgumentByIndex )( IXCLRDataFrame * This, /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg); END_INTERFACE } IXCLRDataFrameVtbl; interface IXCLRDataFrame { CONST_VTBL struct IXCLRDataFrameVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataFrame_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataFrame_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataFrame_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataFrame_GetFrameType(This,simpleType,detailedType) \ ( (This)->lpVtbl -> GetFrameType(This,simpleType,detailedType) ) #define IXCLRDataFrame_GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) \ ( (This)->lpVtbl -> GetContext(This,contextFlags,contextBufSize,contextSize,contextBuf) ) #define IXCLRDataFrame_GetAppDomain(This,appDomain) \ ( (This)->lpVtbl -> GetAppDomain(This,appDomain) ) #define IXCLRDataFrame_GetNumArguments(This,numArgs) \ ( (This)->lpVtbl -> GetNumArguments(This,numArgs) ) #define IXCLRDataFrame_GetArgumentByIndex(This,index,arg,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetArgumentByIndex(This,index,arg,bufLen,nameLen,name) ) #define IXCLRDataFrame_GetNumLocalVariables(This,numLocals) \ ( (This)->lpVtbl -> GetNumLocalVariables(This,numLocals) ) #define IXCLRDataFrame_GetLocalVariableByIndex(This,index,localVariable,bufLen,nameLen,name) \ ( (This)->lpVtbl -> GetLocalVariableByIndex(This,index,localVariable,bufLen,nameLen,name) ) #define IXCLRDataFrame_GetCodeName(This,flags,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetCodeName(This,flags,bufLen,nameLen,nameBuf) ) #define IXCLRDataFrame_GetMethodInstance(This,method) \ ( (This)->lpVtbl -> GetMethodInstance(This,method) ) #define IXCLRDataFrame_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataFrame_GetNumTypeArguments(This,numTypeArgs) \ ( (This)->lpVtbl -> GetNumTypeArguments(This,numTypeArgs) ) #define IXCLRDataFrame_GetTypeArgumentByIndex(This,index,typeArg) \ ( (This)->lpVtbl -> GetTypeArgumentByIndex(This,index,typeArg) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataFrame_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0017 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0017_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0017_v0_0_s_ifspec; #ifndef __IXCLRDataFrame2_INTERFACE_DEFINED__ #define __IXCLRDataFrame2_INTERFACE_DEFINED__ /* interface IXCLRDataFrame2 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataFrame2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("1C4D9A4B-702D-4CF6-B290-1DB6F43050D0") IXCLRDataFrame2 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetExactGenericArgsToken( /* [out] */ IXCLRDataValue **genericToken) = 0; }; #else /* C style interface */ typedef struct IXCLRDataFrame2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataFrame2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataFrame2 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataFrame2 * This); HRESULT ( STDMETHODCALLTYPE *GetExactGenericArgsToken )( IXCLRDataFrame2 * This, /* [out] */ IXCLRDataValue **genericToken); END_INTERFACE } IXCLRDataFrame2Vtbl; interface IXCLRDataFrame2 { CONST_VTBL struct IXCLRDataFrame2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataFrame2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataFrame2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataFrame2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataFrame2_GetExactGenericArgsToken(This,genericToken) \ ( (This)->lpVtbl -> GetExactGenericArgsToken(This,genericToken) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataFrame2_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0018 */ /* [local] */ typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0018_0001 { CLRDATA_EXCEPTION_DEFAULT = 0, CLRDATA_EXCEPTION_NESTED = 0x1, CLRDATA_EXCEPTION_PARTIAL = 0x2 } CLRDataExceptionStateFlag; typedef /* [public][public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0018_0002 { CLRDATA_EXBASE_EXCEPTION = 0, CLRDATA_EXBASE_OUT_OF_MEMORY = ( CLRDATA_EXBASE_EXCEPTION + 1 ) , CLRDATA_EXBASE_INVALID_ARGUMENT = ( CLRDATA_EXBASE_OUT_OF_MEMORY + 1 ) } CLRDataBaseExceptionType; typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0018_0003 { CLRDATA_EXSAME_SECOND_CHANCE = 0, CLRDATA_EXSAME_FIRST_CHANCE = 0x1 } CLRDataExceptionSameFlag; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0018_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0018_v0_0_s_ifspec; #ifndef __IXCLRDataExceptionState_INTERFACE_DEFINED__ #define __IXCLRDataExceptionState_INTERFACE_DEFINED__ /* interface IXCLRDataExceptionState */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataExceptionState; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("75DA9E4C-BD33-43C8-8F5C-96E8A5241F57") IXCLRDataExceptionState : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE GetPrevious( /* [out] */ IXCLRDataExceptionState **exState) = 0; virtual HRESULT STDMETHODCALLTYPE GetManagedObject( /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE GetBaseType( /* [out] */ CLRDataBaseExceptionType *type) = 0; virtual HRESULT STDMETHODCALLTYPE GetCode( /* [out] */ ULONG32 *code) = 0; virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *strLen, /* [size_is][out] */ WCHAR str[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameState( /* [in] */ EXCEPTION_RECORD64 *exRecord, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE cxRecord[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE IsSameState2( /* [in] */ ULONG32 flags, /* [in] */ EXCEPTION_RECORD64 *exRecord, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE cxRecord[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetTask( /* [out] */ IXCLRDataTask **task) = 0; }; #else /* C style interface */ typedef struct IXCLRDataExceptionStateVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataExceptionState * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataExceptionState * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataExceptionState * This); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataExceptionState * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *GetPrevious )( IXCLRDataExceptionState * This, /* [out] */ IXCLRDataExceptionState **exState); HRESULT ( STDMETHODCALLTYPE *GetManagedObject )( IXCLRDataExceptionState * This, /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *GetBaseType )( IXCLRDataExceptionState * This, /* [out] */ CLRDataBaseExceptionType *type); HRESULT ( STDMETHODCALLTYPE *GetCode )( IXCLRDataExceptionState * This, /* [out] */ ULONG32 *code); HRESULT ( STDMETHODCALLTYPE *GetString )( IXCLRDataExceptionState * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *strLen, /* [size_is][out] */ WCHAR str[ ]); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataExceptionState * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *IsSameState )( IXCLRDataExceptionState * This, /* [in] */ EXCEPTION_RECORD64 *exRecord, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE cxRecord[ ]); HRESULT ( STDMETHODCALLTYPE *IsSameState2 )( IXCLRDataExceptionState * This, /* [in] */ ULONG32 flags, /* [in] */ EXCEPTION_RECORD64 *exRecord, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE cxRecord[ ]); HRESULT ( STDMETHODCALLTYPE *GetTask )( IXCLRDataExceptionState * This, /* [out] */ IXCLRDataTask **task); END_INTERFACE } IXCLRDataExceptionStateVtbl; interface IXCLRDataExceptionState { CONST_VTBL struct IXCLRDataExceptionStateVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataExceptionState_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataExceptionState_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataExceptionState_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataExceptionState_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataExceptionState_GetPrevious(This,exState) \ ( (This)->lpVtbl -> GetPrevious(This,exState) ) #define IXCLRDataExceptionState_GetManagedObject(This,value) \ ( (This)->lpVtbl -> GetManagedObject(This,value) ) #define IXCLRDataExceptionState_GetBaseType(This,type) \ ( (This)->lpVtbl -> GetBaseType(This,type) ) #define IXCLRDataExceptionState_GetCode(This,code) \ ( (This)->lpVtbl -> GetCode(This,code) ) #define IXCLRDataExceptionState_GetString(This,bufLen,strLen,str) \ ( (This)->lpVtbl -> GetString(This,bufLen,strLen,str) ) #define IXCLRDataExceptionState_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataExceptionState_IsSameState(This,exRecord,contextSize,cxRecord) \ ( (This)->lpVtbl -> IsSameState(This,exRecord,contextSize,cxRecord) ) #define IXCLRDataExceptionState_IsSameState2(This,flags,exRecord,contextSize,cxRecord) \ ( (This)->lpVtbl -> IsSameState2(This,flags,exRecord,contextSize,cxRecord) ) #define IXCLRDataExceptionState_GetTask(This,task) \ ( (This)->lpVtbl -> GetTask(This,task) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataExceptionState_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0019 */ /* [local] */ #pragma warning(pop) typedef /* [public] */ enum __MIDL___MIDL_itf_xclrdata_0000_0019_0001 { CLRDATA_VLOC_MEMORY = 0, CLRDATA_VLOC_REGISTER = 0x1 } ClrDataValueLocationFlag; #pragma warning(push) #pragma warning(disable:28718) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0019_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0019_v0_0_s_ifspec; #ifndef __IXCLRDataValue_INTERFACE_DEFINED__ #define __IXCLRDataValue_INTERFACE_DEFINED__ /* interface IXCLRDataValue */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataValue; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("96EC93C7-1000-4e93-8991-98D8766E6666") IXCLRDataValue : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE GetFlags( /* [out] */ ULONG32 *flags) = 0; virtual HRESULT STDMETHODCALLTYPE GetAddress( /* [out] */ CLRDATA_ADDRESS *address) = 0; virtual HRESULT STDMETHODCALLTYPE GetSize( /* [out] */ ULONG64 *size) = 0; virtual HRESULT STDMETHODCALLTYPE GetBytes( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *dataSize, /* [size_is][out] */ BYTE buffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE SetBytes( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *dataSize, /* [size_is][in] */ BYTE buffer[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetType( /* [out] */ IXCLRDataTypeInstance **typeInstance) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumFields( /* [out] */ ULONG32 *numFields) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumFields2( /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTypeInstance *fromType, /* [out] */ ULONG32 *numFields) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumFields( /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTypeInstance *fromType, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumField( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumFields( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE StartEnumFieldsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 nameFlags, /* [in] */ ULONG32 fieldFlags, /* [in] */ IXCLRDataTypeInstance *fromType, /* [out] */ CLRDATA_ENUM *handle) = 0; virtual HRESULT STDMETHODCALLTYPE EnumFieldByName( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EndEnumFieldsByName( /* [in] */ CLRDATA_ENUM handle) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldByToken( /* [in] */ mdFieldDef token, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssociatedValue( /* [out] */ IXCLRDataValue **assocValue) = 0; virtual HRESULT STDMETHODCALLTYPE GetAssociatedType( /* [out] */ IXCLRDataTypeInstance **assocType) = 0; virtual HRESULT STDMETHODCALLTYPE GetString( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *strLen, /* [size_is][out] */ WCHAR str[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetArrayProperties( /* [out] */ ULONG32 *rank, /* [out] */ ULONG32 *totalElements, /* [in] */ ULONG32 numDim, /* [size_is][out] */ ULONG32 dims[ ], /* [in] */ ULONG32 numBases, /* [size_is][out] */ LONG32 bases[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetArrayElement( /* [in] */ ULONG32 numInd, /* [size_is][in] */ LONG32 indices[ ], /* [out] */ IXCLRDataValue **value) = 0; virtual HRESULT STDMETHODCALLTYPE EnumField2( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE EnumFieldByName2( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token) = 0; virtual HRESULT STDMETHODCALLTYPE GetFieldByToken2( /* [in] */ IXCLRDataModule *tokenScope, /* [in] */ mdFieldDef token, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]) = 0; virtual HRESULT STDMETHODCALLTYPE GetNumLocations( /* [out] */ ULONG32 *numLocs) = 0; virtual HRESULT STDMETHODCALLTYPE GetLocationByIndex( /* [in] */ ULONG32 loc, /* [out] */ ULONG32 *flags, /* [out] */ CLRDATA_ADDRESS *arg) = 0; }; #else /* C style interface */ typedef struct IXCLRDataValueVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataValue * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataValue * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataValue * This); HRESULT ( STDMETHODCALLTYPE *GetFlags )( IXCLRDataValue * This, /* [out] */ ULONG32 *flags); HRESULT ( STDMETHODCALLTYPE *GetAddress )( IXCLRDataValue * This, /* [out] */ CLRDATA_ADDRESS *address); HRESULT ( STDMETHODCALLTYPE *GetSize )( IXCLRDataValue * This, /* [out] */ ULONG64 *size); HRESULT ( STDMETHODCALLTYPE *GetBytes )( IXCLRDataValue * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *dataSize, /* [size_is][out] */ BYTE buffer[ ]); HRESULT ( STDMETHODCALLTYPE *SetBytes )( IXCLRDataValue * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *dataSize, /* [size_is][in] */ BYTE buffer[ ]); HRESULT ( STDMETHODCALLTYPE *GetType )( IXCLRDataValue * This, /* [out] */ IXCLRDataTypeInstance **typeInstance); HRESULT ( STDMETHODCALLTYPE *GetNumFields )( IXCLRDataValue * This, /* [out] */ ULONG32 *numFields); HRESULT ( STDMETHODCALLTYPE *GetFieldByIndex )( IXCLRDataValue * This, /* [in] */ ULONG32 index, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *Request )( IXCLRDataValue * This, /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer); HRESULT ( STDMETHODCALLTYPE *GetNumFields2 )( IXCLRDataValue * This, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTypeInstance *fromType, /* [out] */ ULONG32 *numFields); HRESULT ( STDMETHODCALLTYPE *StartEnumFields )( IXCLRDataValue * This, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataTypeInstance *fromType, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumField )( IXCLRDataValue * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EndEnumFields )( IXCLRDataValue * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *StartEnumFieldsByName )( IXCLRDataValue * This, /* [in] */ LPCWSTR name, /* [in] */ ULONG32 nameFlags, /* [in] */ ULONG32 fieldFlags, /* [in] */ IXCLRDataTypeInstance *fromType, /* [out] */ CLRDATA_ENUM *handle); HRESULT ( STDMETHODCALLTYPE *EnumFieldByName )( IXCLRDataValue * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EndEnumFieldsByName )( IXCLRDataValue * This, /* [in] */ CLRDATA_ENUM handle); HRESULT ( STDMETHODCALLTYPE *GetFieldByToken )( IXCLRDataValue * This, /* [in] */ mdFieldDef token, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetAssociatedValue )( IXCLRDataValue * This, /* [out] */ IXCLRDataValue **assocValue); HRESULT ( STDMETHODCALLTYPE *GetAssociatedType )( IXCLRDataValue * This, /* [out] */ IXCLRDataTypeInstance **assocType); HRESULT ( STDMETHODCALLTYPE *GetString )( IXCLRDataValue * This, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *strLen, /* [size_is][out] */ WCHAR str[ ]); HRESULT ( STDMETHODCALLTYPE *GetArrayProperties )( IXCLRDataValue * This, /* [out] */ ULONG32 *rank, /* [out] */ ULONG32 *totalElements, /* [in] */ ULONG32 numDim, /* [size_is][out] */ ULONG32 dims[ ], /* [in] */ ULONG32 numBases, /* [size_is][out] */ LONG32 bases[ ]); HRESULT ( STDMETHODCALLTYPE *GetArrayElement )( IXCLRDataValue * This, /* [in] */ ULONG32 numInd, /* [size_is][in] */ LONG32 indices[ ], /* [out] */ IXCLRDataValue **value); HRESULT ( STDMETHODCALLTYPE *EnumField2 )( IXCLRDataValue * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 nameBufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ], /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *EnumFieldByName2 )( IXCLRDataValue * This, /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataValue **field, /* [out] */ IXCLRDataModule **tokenScope, /* [out] */ mdFieldDef *token); HRESULT ( STDMETHODCALLTYPE *GetFieldByToken2 )( IXCLRDataValue * This, /* [in] */ IXCLRDataModule *tokenScope, /* [in] */ mdFieldDef token, /* [out] */ IXCLRDataValue **field, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ WCHAR nameBuf[ ]); HRESULT ( STDMETHODCALLTYPE *GetNumLocations )( IXCLRDataValue * This, /* [out] */ ULONG32 *numLocs); HRESULT ( STDMETHODCALLTYPE *GetLocationByIndex )( IXCLRDataValue * This, /* [in] */ ULONG32 loc, /* [out] */ ULONG32 *flags, /* [out] */ CLRDATA_ADDRESS *arg); END_INTERFACE } IXCLRDataValueVtbl; interface IXCLRDataValue { CONST_VTBL struct IXCLRDataValueVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataValue_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataValue_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataValue_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataValue_GetFlags(This,flags) \ ( (This)->lpVtbl -> GetFlags(This,flags) ) #define IXCLRDataValue_GetAddress(This,address) \ ( (This)->lpVtbl -> GetAddress(This,address) ) #define IXCLRDataValue_GetSize(This,size) \ ( (This)->lpVtbl -> GetSize(This,size) ) #define IXCLRDataValue_GetBytes(This,bufLen,dataSize,buffer) \ ( (This)->lpVtbl -> GetBytes(This,bufLen,dataSize,buffer) ) #define IXCLRDataValue_SetBytes(This,bufLen,dataSize,buffer) \ ( (This)->lpVtbl -> SetBytes(This,bufLen,dataSize,buffer) ) #define IXCLRDataValue_GetType(This,typeInstance) \ ( (This)->lpVtbl -> GetType(This,typeInstance) ) #define IXCLRDataValue_GetNumFields(This,numFields) \ ( (This)->lpVtbl -> GetNumFields(This,numFields) ) #define IXCLRDataValue_GetFieldByIndex(This,index,field,bufLen,nameLen,nameBuf,token) \ ( (This)->lpVtbl -> GetFieldByIndex(This,index,field,bufLen,nameLen,nameBuf,token) ) #define IXCLRDataValue_Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) \ ( (This)->lpVtbl -> Request(This,reqCode,inBufferSize,inBuffer,outBufferSize,outBuffer) ) #define IXCLRDataValue_GetNumFields2(This,flags,fromType,numFields) \ ( (This)->lpVtbl -> GetNumFields2(This,flags,fromType,numFields) ) #define IXCLRDataValue_StartEnumFields(This,flags,fromType,handle) \ ( (This)->lpVtbl -> StartEnumFields(This,flags,fromType,handle) ) #define IXCLRDataValue_EnumField(This,handle,field,nameBufLen,nameLen,nameBuf,token) \ ( (This)->lpVtbl -> EnumField(This,handle,field,nameBufLen,nameLen,nameBuf,token) ) #define IXCLRDataValue_EndEnumFields(This,handle) \ ( (This)->lpVtbl -> EndEnumFields(This,handle) ) #define IXCLRDataValue_StartEnumFieldsByName(This,name,nameFlags,fieldFlags,fromType,handle) \ ( (This)->lpVtbl -> StartEnumFieldsByName(This,name,nameFlags,fieldFlags,fromType,handle) ) #define IXCLRDataValue_EnumFieldByName(This,handle,field,token) \ ( (This)->lpVtbl -> EnumFieldByName(This,handle,field,token) ) #define IXCLRDataValue_EndEnumFieldsByName(This,handle) \ ( (This)->lpVtbl -> EndEnumFieldsByName(This,handle) ) #define IXCLRDataValue_GetFieldByToken(This,token,field,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetFieldByToken(This,token,field,bufLen,nameLen,nameBuf) ) #define IXCLRDataValue_GetAssociatedValue(This,assocValue) \ ( (This)->lpVtbl -> GetAssociatedValue(This,assocValue) ) #define IXCLRDataValue_GetAssociatedType(This,assocType) \ ( (This)->lpVtbl -> GetAssociatedType(This,assocType) ) #define IXCLRDataValue_GetString(This,bufLen,strLen,str) \ ( (This)->lpVtbl -> GetString(This,bufLen,strLen,str) ) #define IXCLRDataValue_GetArrayProperties(This,rank,totalElements,numDim,dims,numBases,bases) \ ( (This)->lpVtbl -> GetArrayProperties(This,rank,totalElements,numDim,dims,numBases,bases) ) #define IXCLRDataValue_GetArrayElement(This,numInd,indices,value) \ ( (This)->lpVtbl -> GetArrayElement(This,numInd,indices,value) ) #define IXCLRDataValue_EnumField2(This,handle,field,nameBufLen,nameLen,nameBuf,tokenScope,token) \ ( (This)->lpVtbl -> EnumField2(This,handle,field,nameBufLen,nameLen,nameBuf,tokenScope,token) ) #define IXCLRDataValue_EnumFieldByName2(This,handle,field,tokenScope,token) \ ( (This)->lpVtbl -> EnumFieldByName2(This,handle,field,tokenScope,token) ) #define IXCLRDataValue_GetFieldByToken2(This,tokenScope,token,field,bufLen,nameLen,nameBuf) \ ( (This)->lpVtbl -> GetFieldByToken2(This,tokenScope,token,field,bufLen,nameLen,nameBuf) ) #define IXCLRDataValue_GetNumLocations(This,numLocs) \ ( (This)->lpVtbl -> GetNumLocations(This,numLocs) ) #define IXCLRDataValue_GetLocationByIndex(This,loc,flags,arg) \ ( (This)->lpVtbl -> GetLocationByIndex(This,loc,flags,arg) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataValue_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_xclrdata_0000_0020 */ /* [local] */ #pragma warning(pop) extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0020_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_xclrdata_0000_0020_v0_0_s_ifspec; #ifndef __IXCLRDataExceptionNotification_INTERFACE_DEFINED__ #define __IXCLRDataExceptionNotification_INTERFACE_DEFINED__ /* interface IXCLRDataExceptionNotification */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataExceptionNotification; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("2D95A079-42A1-4837-818F-0B97D7048E0E") IXCLRDataExceptionNotification : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE OnCodeGenerated( /* [in] */ IXCLRDataMethodInstance *method) = 0; virtual HRESULT STDMETHODCALLTYPE OnCodeDiscarded( /* [in] */ IXCLRDataMethodInstance *method) = 0; virtual HRESULT STDMETHODCALLTYPE OnProcessExecution( /* [in] */ ULONG32 state) = 0; virtual HRESULT STDMETHODCALLTYPE OnTaskExecution( /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 state) = 0; virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded( /* [in] */ IXCLRDataModule *mod) = 0; virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded( /* [in] */ IXCLRDataModule *mod) = 0; virtual HRESULT STDMETHODCALLTYPE OnTypeLoaded( /* [in] */ IXCLRDataTypeInstance *typeInst) = 0; virtual HRESULT STDMETHODCALLTYPE OnTypeUnloaded( /* [in] */ IXCLRDataTypeInstance *typeInst) = 0; }; #else /* C style interface */ typedef struct IXCLRDataExceptionNotificationVtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataExceptionNotification * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataExceptionNotification * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataExceptionNotification * This); HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( IXCLRDataExceptionNotification * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( IXCLRDataExceptionNotification * This, /* [in] */ IXCLRDataTypeInstance *typeInst); END_INTERFACE } IXCLRDataExceptionNotificationVtbl; interface IXCLRDataExceptionNotification { CONST_VTBL struct IXCLRDataExceptionNotificationVtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataExceptionNotification_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataExceptionNotification_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataExceptionNotification_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataExceptionNotification_OnCodeGenerated(This,method) \ ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) #define IXCLRDataExceptionNotification_OnCodeDiscarded(This,method) \ ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) #define IXCLRDataExceptionNotification_OnProcessExecution(This,state) \ ( (This)->lpVtbl -> OnProcessExecution(This,state) ) #define IXCLRDataExceptionNotification_OnTaskExecution(This,task,state) \ ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) #define IXCLRDataExceptionNotification_OnModuleLoaded(This,mod) \ ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) #define IXCLRDataExceptionNotification_OnModuleUnloaded(This,mod) \ ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) #define IXCLRDataExceptionNotification_OnTypeLoaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) #define IXCLRDataExceptionNotification_OnTypeUnloaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataExceptionNotification_INTERFACE_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification2_INTERFACE_DEFINED__ #define __IXCLRDataExceptionNotification2_INTERFACE_DEFINED__ /* interface IXCLRDataExceptionNotification2 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataExceptionNotification2; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("31201a94-4337-49b7-aef7-0c755054091f") IXCLRDataExceptionNotification2 : public IXCLRDataExceptionNotification { public: virtual HRESULT STDMETHODCALLTYPE OnAppDomainLoaded( /* [in] */ IXCLRDataAppDomain *domain) = 0; virtual HRESULT STDMETHODCALLTYPE OnAppDomainUnloaded( /* [in] */ IXCLRDataAppDomain *domain) = 0; virtual HRESULT STDMETHODCALLTYPE OnException( /* [in] */ IXCLRDataExceptionState *exception) = 0; }; #else /* C style interface */ typedef struct IXCLRDataExceptionNotification2Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataExceptionNotification2 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataExceptionNotification2 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataExceptionNotification2 * This); HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( IXCLRDataExceptionNotification2 * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnException )( IXCLRDataExceptionNotification2 * This, /* [in] */ IXCLRDataExceptionState *exception); END_INTERFACE } IXCLRDataExceptionNotification2Vtbl; interface IXCLRDataExceptionNotification2 { CONST_VTBL struct IXCLRDataExceptionNotification2Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataExceptionNotification2_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataExceptionNotification2_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataExceptionNotification2_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataExceptionNotification2_OnCodeGenerated(This,method) \ ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) #define IXCLRDataExceptionNotification2_OnCodeDiscarded(This,method) \ ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) #define IXCLRDataExceptionNotification2_OnProcessExecution(This,state) \ ( (This)->lpVtbl -> OnProcessExecution(This,state) ) #define IXCLRDataExceptionNotification2_OnTaskExecution(This,task,state) \ ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) #define IXCLRDataExceptionNotification2_OnModuleLoaded(This,mod) \ ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) #define IXCLRDataExceptionNotification2_OnModuleUnloaded(This,mod) \ ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) #define IXCLRDataExceptionNotification2_OnTypeLoaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) #define IXCLRDataExceptionNotification2_OnTypeUnloaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) #define IXCLRDataExceptionNotification2_OnAppDomainLoaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) #define IXCLRDataExceptionNotification2_OnAppDomainUnloaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) #define IXCLRDataExceptionNotification2_OnException(This,exception) \ ( (This)->lpVtbl -> OnException(This,exception) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataExceptionNotification2_INTERFACE_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification3_INTERFACE_DEFINED__ #define __IXCLRDataExceptionNotification3_INTERFACE_DEFINED__ /* interface IXCLRDataExceptionNotification3 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataExceptionNotification3; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("31201a94-4337-49b7-aef7-0c7550540920") IXCLRDataExceptionNotification3 : public IXCLRDataExceptionNotification2 { public: virtual HRESULT STDMETHODCALLTYPE OnGcEvent( /* [in] */ GcEvtArgs gcEvtArgs) = 0; }; #else /* C style interface */ typedef struct IXCLRDataExceptionNotification3Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataExceptionNotification3 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataExceptionNotification3 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataExceptionNotification3 * This); HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( IXCLRDataExceptionNotification3 * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnException )( IXCLRDataExceptionNotification3 * This, /* [in] */ IXCLRDataExceptionState *exception); HRESULT ( STDMETHODCALLTYPE *OnGcEvent )( IXCLRDataExceptionNotification3 * This, /* [in] */ GcEvtArgs gcEvtArgs); END_INTERFACE } IXCLRDataExceptionNotification3Vtbl; interface IXCLRDataExceptionNotification3 { CONST_VTBL struct IXCLRDataExceptionNotification3Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataExceptionNotification3_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataExceptionNotification3_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataExceptionNotification3_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataExceptionNotification3_OnCodeGenerated(This,method) \ ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) #define IXCLRDataExceptionNotification3_OnCodeDiscarded(This,method) \ ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) #define IXCLRDataExceptionNotification3_OnProcessExecution(This,state) \ ( (This)->lpVtbl -> OnProcessExecution(This,state) ) #define IXCLRDataExceptionNotification3_OnTaskExecution(This,task,state) \ ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) #define IXCLRDataExceptionNotification3_OnModuleLoaded(This,mod) \ ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) #define IXCLRDataExceptionNotification3_OnModuleUnloaded(This,mod) \ ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) #define IXCLRDataExceptionNotification3_OnTypeLoaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) #define IXCLRDataExceptionNotification3_OnTypeUnloaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) #define IXCLRDataExceptionNotification3_OnAppDomainLoaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) #define IXCLRDataExceptionNotification3_OnAppDomainUnloaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) #define IXCLRDataExceptionNotification3_OnException(This,exception) \ ( (This)->lpVtbl -> OnException(This,exception) ) #define IXCLRDataExceptionNotification3_OnGcEvent(This,gcEvtArgs) \ ( (This)->lpVtbl -> OnGcEvent(This,gcEvtArgs) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataExceptionNotification3_INTERFACE_DEFINED__ */ #ifndef __IXCLRDataExceptionNotification4_INTERFACE_DEFINED__ #define __IXCLRDataExceptionNotification4_INTERFACE_DEFINED__ /* interface IXCLRDataExceptionNotification4 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataExceptionNotification4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("C25E926E-5F09-4AA2-BBAD-B7FC7F10CFD7") IXCLRDataExceptionNotification4 : public IXCLRDataExceptionNotification3 { public: virtual HRESULT STDMETHODCALLTYPE ExceptionCatcherEnter( /* [in] */ IXCLRDataMethodInstance *catchingMethod, DWORD catcherNativeOffset) = 0; }; #else /* C style interface */ typedef struct IXCLRDataExceptionNotification4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataExceptionNotification4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataExceptionNotification4 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataExceptionNotification4 * This); HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( IXCLRDataExceptionNotification4 * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnException )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataExceptionState *exception); HRESULT ( STDMETHODCALLTYPE *OnGcEvent )( IXCLRDataExceptionNotification4 * This, /* [in] */ GcEvtArgs gcEvtArgs); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( IXCLRDataExceptionNotification4 * This, /* [in] */ IXCLRDataMethodInstance *catchingMethod, DWORD catcherNativeOffset); END_INTERFACE } IXCLRDataExceptionNotification4Vtbl; interface IXCLRDataExceptionNotification4 { CONST_VTBL struct IXCLRDataExceptionNotification4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataExceptionNotification4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataExceptionNotification4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataExceptionNotification4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataExceptionNotification4_OnCodeGenerated(This,method) \ ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) #define IXCLRDataExceptionNotification4_OnCodeDiscarded(This,method) \ ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) #define IXCLRDataExceptionNotification4_OnProcessExecution(This,state) \ ( (This)->lpVtbl -> OnProcessExecution(This,state) ) #define IXCLRDataExceptionNotification4_OnTaskExecution(This,task,state) \ ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) #define IXCLRDataExceptionNotification4_OnModuleLoaded(This,mod) \ ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) #define IXCLRDataExceptionNotification4_OnModuleUnloaded(This,mod) \ ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) #define IXCLRDataExceptionNotification4_OnTypeLoaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) #define IXCLRDataExceptionNotification4_OnTypeUnloaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) #define IXCLRDataExceptionNotification4_OnAppDomainLoaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) #define IXCLRDataExceptionNotification4_OnAppDomainUnloaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) #define IXCLRDataExceptionNotification4_OnException(This,exception) \ ( (This)->lpVtbl -> OnException(This,exception) ) #define IXCLRDataExceptionNotification4_OnGcEvent(This,gcEvtArgs) \ ( (This)->lpVtbl -> OnGcEvent(This,gcEvtArgs) ) #define IXCLRDataExceptionNotification4_ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) ) #endif /* COBJMACROS */ #endif /* C style interface */ #ifndef __IXCLRDataExceptionNotification5_INTERFACE_DEFINED__ #define __IXCLRDataExceptionNotification5_INTERFACE_DEFINED__ /* interface IXCLRDataExceptionNotification5 */ /* [uuid][local][object] */ EXTERN_C const IID IID_IXCLRDataExceptionNotification5; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("e77a39ea-3548-44d9-b171-8569ed1a9423") IXCLRDataExceptionNotification5 : public IXCLRDataExceptionNotification4 { public: virtual HRESULT STDMETHODCALLTYPE OnCodeGenerated2( /* [in] */ IXCLRDataMethodInstance *method, /* [in] */ CLRDATA_ADDRESS nativeCodeLocation) = 0; }; #else /* C style interface */ typedef struct IXCLRDataExceptionNotification5Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( IXCLRDataExceptionNotification5 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( IXCLRDataExceptionNotification5 * This); ULONG ( STDMETHODCALLTYPE *Release )( IXCLRDataExceptionNotification5 * This); HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnCodeDiscarded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataMethodInstance *method); HRESULT ( STDMETHODCALLTYPE *OnProcessExecution )( IXCLRDataExceptionNotification5 * This, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnTaskExecution )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataTask *task, /* [in] */ ULONG32 state); HRESULT ( STDMETHODCALLTYPE *OnModuleLoaded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnModuleUnloaded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataModule *mod); HRESULT ( STDMETHODCALLTYPE *OnTypeLoaded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnTypeUnloaded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataTypeInstance *typeInst); HRESULT ( STDMETHODCALLTYPE *OnAppDomainLoaded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnAppDomainUnloaded )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataAppDomain *domain); HRESULT ( STDMETHODCALLTYPE *OnException )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataExceptionState *exception); HRESULT ( STDMETHODCALLTYPE *OnGcEvent )( IXCLRDataExceptionNotification5 * This, /* [in] */ GcEvtArgs gcEvtArgs); HRESULT ( STDMETHODCALLTYPE *ExceptionCatcherEnter )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataMethodInstance *catchingMethod, DWORD catcherNativeOffset); HRESULT ( STDMETHODCALLTYPE *OnCodeGenerated2 )( IXCLRDataExceptionNotification5 * This, /* [in] */ IXCLRDataMethodInstance *method, /* [in] */ CLRDATA_ADDRESS nativeCodeLocation); END_INTERFACE } IXCLRDataExceptionNotification5Vtbl; interface IXCLRDataExceptionNotification5 { CONST_VTBL struct IXCLRDataExceptionNotification5Vtbl *lpVtbl; }; #ifdef COBJMACROS #define IXCLRDataExceptionNotification5_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define IXCLRDataExceptionNotification5_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define IXCLRDataExceptionNotification5_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define IXCLRDataExceptionNotification5_OnCodeGenerated(This,method) \ ( (This)->lpVtbl -> OnCodeGenerated(This,method) ) #define IXCLRDataExceptionNotification5_OnCodeDiscarded(This,method) \ ( (This)->lpVtbl -> OnCodeDiscarded(This,method) ) #define IXCLRDataExceptionNotification5_OnProcessExecution(This,state) \ ( (This)->lpVtbl -> OnProcessExecution(This,state) ) #define IXCLRDataExceptionNotification5_OnTaskExecution(This,task,state) \ ( (This)->lpVtbl -> OnTaskExecution(This,task,state) ) #define IXCLRDataExceptionNotification5_OnModuleLoaded(This,mod) \ ( (This)->lpVtbl -> OnModuleLoaded(This,mod) ) #define IXCLRDataExceptionNotification5_OnModuleUnloaded(This,mod) \ ( (This)->lpVtbl -> OnModuleUnloaded(This,mod) ) #define IXCLRDataExceptionNotification5_OnTypeLoaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeLoaded(This,typeInst) ) #define IXCLRDataExceptionNotification5_OnTypeUnloaded(This,typeInst) \ ( (This)->lpVtbl -> OnTypeUnloaded(This,typeInst) ) #define IXCLRDataExceptionNotification5_OnAppDomainLoaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainLoaded(This,domain) ) #define IXCLRDataExceptionNotification5_OnAppDomainUnloaded(This,domain) \ ( (This)->lpVtbl -> OnAppDomainUnloaded(This,domain) ) #define IXCLRDataExceptionNotification5_OnException(This,exception) \ ( (This)->lpVtbl -> OnException(This,exception) ) #define IXCLRDataExceptionNotification5_OnGcEvent(This,gcEvtArgs) \ ( (This)->lpVtbl -> OnGcEvent(This,gcEvtArgs) ) #define IXCLRDataExceptionNotification5_ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) \ ( (This)->lpVtbl -> ExceptionCatcherEnter(This,catchingMethod,catcherNativeOffset) ) #define IXCLRDataExceptionNotification5_OnCodeGenerated2(This,method,nativeCodeLocation) \ ( (This)->lpVtbl -> OnCodeGenerated2(This,method,nativeCodeLocation) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __IXCLRDataExceptionNotification5_INTERFACE_DEFINED__ */ #endif /* __IXCLRDataExceptionNotification4_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/external/coreclr/pal/prebuilt/inc/xcordebug.h ================================================ /* this ALWAYS GENERATED file contains the definitions for the interfaces */ /* File created by MIDL compiler version 8.01.0622 */ /* at Mon Jan 18 19:14:07 2038 */ /* Compiler settings for F:/Dev/coreclr/inc/xcordebug.idl: Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 8.01.0622 protocol : dce , ms_ext, c_ext, robust error checks: allocation ref bounds_check enum stub_data VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ /* @@MIDL_FILE_HEADING( ) */ #pragma warning( disable: 4049 ) /* more than 64k source lines */ /* verify that the version is high enough to compile this file*/ #ifndef __REQUIRED_RPCNDR_H_VERSION__ #define __REQUIRED_RPCNDR_H_VERSION__ 475 #endif #include "rpc.h" #include "rpcndr.h" #ifndef __RPCNDR_H_VERSION__ #error this stub requires an updated version of #endif /* __RPCNDR_H_VERSION__ */ #ifndef COM_NO_WINDOWS_H #include "windows.h" #include "ole2.h" #endif /*COM_NO_WINDOWS_H*/ #ifndef __xcordebug_h__ #define __xcordebug_h__ #if defined(_MSC_VER) && (_MSC_VER >= 1020) #pragma once #endif /* Forward Declarations */ #ifndef __ICorDebugProcess4_FWD_DEFINED__ #define __ICorDebugProcess4_FWD_DEFINED__ typedef interface ICorDebugProcess4 ICorDebugProcess4; #endif /* __ICorDebugProcess4_FWD_DEFINED__ */ /* header files for imported files */ #include "cordebug.h" #ifdef __cplusplus extern "C"{ #endif #ifndef __ICorDebugProcess4_INTERFACE_DEFINED__ #define __ICorDebugProcess4_INTERFACE_DEFINED__ /* interface ICorDebugProcess4 */ /* [unique][uuid][local][object] */ EXTERN_C const IID IID_ICorDebugProcess4; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("E930C679-78AF-4953-8AB7-B0AABF0F9F80") ICorDebugProcess4 : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE Filter( /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, /* [in] */ CorDebugRecordFormat format, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [in] */ ICorDebugManagedCallback *pCallback, /* [out][in] */ CORDB_CONTINUE_STATUS *pContinueStatus) = 0; virtual HRESULT STDMETHODCALLTYPE ProcessStateChanged( /* [in] */ CorDebugStateChange eChange) = 0; }; #else /* C style interface */ typedef struct ICorDebugProcess4Vtbl { BEGIN_INTERFACE HRESULT ( STDMETHODCALLTYPE *QueryInterface )( ICorDebugProcess4 * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); ULONG ( STDMETHODCALLTYPE *AddRef )( ICorDebugProcess4 * This); ULONG ( STDMETHODCALLTYPE *Release )( ICorDebugProcess4 * This); HRESULT ( STDMETHODCALLTYPE *Filter )( ICorDebugProcess4 * This, /* [size_is][length_is][in] */ const BYTE pRecord[ ], /* [in] */ DWORD countBytes, /* [in] */ CorDebugRecordFormat format, /* [in] */ DWORD dwFlags, /* [in] */ DWORD dwThreadId, /* [in] */ ICorDebugManagedCallback *pCallback, /* [out][in] */ CORDB_CONTINUE_STATUS *pContinueStatus); HRESULT ( STDMETHODCALLTYPE *ProcessStateChanged )( ICorDebugProcess4 * This, /* [in] */ CorDebugStateChange eChange); END_INTERFACE } ICorDebugProcess4Vtbl; interface ICorDebugProcess4 { CONST_VTBL struct ICorDebugProcess4Vtbl *lpVtbl; }; #ifdef COBJMACROS #define ICorDebugProcess4_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) #define ICorDebugProcess4_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) #define ICorDebugProcess4_Release(This) \ ( (This)->lpVtbl -> Release(This) ) #define ICorDebugProcess4_Filter(This,pRecord,countBytes,format,dwFlags,dwThreadId,pCallback,pContinueStatus) \ ( (This)->lpVtbl -> Filter(This,pRecord,countBytes,format,dwFlags,dwThreadId,pCallback,pContinueStatus) ) #define ICorDebugProcess4_ProcessStateChanged(This,eChange) \ ( (This)->lpVtbl -> ProcessStateChanged(This,eChange) ) #endif /* COBJMACROS */ #endif /* C style interface */ #endif /* __ICorDebugProcess4_INTERFACE_DEFINED__ */ /* Additional Prototypes for ALL interfaces */ /* end of Additional Prototypes */ #ifdef __cplusplus } #endif #endif ================================================ FILE: src/ManagedProfiler/framework.h ================================================ #pragma once #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files #include ================================================ FILE: src/PDBViewer/AboutBox.Designer.cs ================================================ namespace PDBViewer; partial class AboutBox { ///

/// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { tableLayoutPanel = new TableLayoutPanel(); labelProductName = new Label(); labelVersion = new Label(); labelCopyright = new Label(); okButton = new Button(); tableLayoutPanel.SuspendLayout(); SuspendLayout(); // // tableLayoutPanel // tableLayoutPanel.ColumnCount = 1; tableLayoutPanel.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F)); tableLayoutPanel.Controls.Add(labelProductName, 0, 0); tableLayoutPanel.Controls.Add(labelVersion, 0, 1); tableLayoutPanel.Controls.Add(labelCopyright, 0, 2); tableLayoutPanel.Controls.Add(okButton, 0, 4); tableLayoutPanel.Dock = DockStyle.Fill; tableLayoutPanel.Location = new Point(15, 17); tableLayoutPanel.Margin = new Padding(5, 6, 5, 6); tableLayoutPanel.Name = "tableLayoutPanel"; tableLayoutPanel.RowCount = 5; tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 25F)); tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 25F)); tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 25F)); tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 25F)); tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 56F)); tableLayoutPanel.RowStyles.Add(new RowStyle(SizeType.Absolute, 20F)); tableLayoutPanel.Size = new Size(429, 175); tableLayoutPanel.TabIndex = 0; // // labelProductName // labelProductName.Dock = DockStyle.Fill; labelProductName.Location = new Point(10, 0); labelProductName.Margin = new Padding(10, 0, 5, 0); labelProductName.MaximumSize = new Size(0, 33); labelProductName.Name = "labelProductName"; labelProductName.Size = new Size(414, 29); labelProductName.TabIndex = 19; labelProductName.Text = "Product Name"; labelProductName.TextAlign = ContentAlignment.MiddleLeft; // // labelVersion // labelVersion.Dock = DockStyle.Fill; labelVersion.Location = new Point(10, 29); labelVersion.Margin = new Padding(10, 0, 5, 0); labelVersion.MaximumSize = new Size(0, 33); labelVersion.Name = "labelVersion"; labelVersion.Size = new Size(414, 29); labelVersion.TabIndex = 0; labelVersion.Text = "Version"; labelVersion.TextAlign = ContentAlignment.MiddleLeft; // // labelCopyright // labelCopyright.Dock = DockStyle.Fill; labelCopyright.Location = new Point(10, 58); labelCopyright.Margin = new Padding(10, 0, 5, 0); labelCopyright.MaximumSize = new Size(0, 33); labelCopyright.Name = "labelCopyright"; labelCopyright.Size = new Size(414, 29); labelCopyright.TabIndex = 21; labelCopyright.Text = "Copyright"; labelCopyright.TextAlign = ContentAlignment.MiddleLeft; // // okButton // okButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Right; okButton.DialogResult = DialogResult.Cancel; okButton.Location = new Point(322, 137); okButton.Margin = new Padding(5, 6, 5, 6); okButton.Name = "okButton"; okButton.Size = new Size(102, 32); okButton.TabIndex = 24; okButton.Text = "&OK"; // // AboutBox // AcceptButton = okButton; AutoScaleDimensions = new SizeF(10F, 25F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(459, 209); Controls.Add(tableLayoutPanel); FormBorderStyle = FormBorderStyle.FixedDialog; Margin = new Padding(5, 6, 5, 6); MaximizeBox = false; MinimizeBox = false; Name = "AboutBox"; Padding = new Padding(15, 17, 15, 17); ShowIcon = false; ShowInTaskbar = false; StartPosition = FormStartPosition.CenterParent; Text = "About PDB Viewer"; tableLayoutPanel.ResumeLayout(false); ResumeLayout(false); } #endregion private System.Windows.Forms.TableLayoutPanel tableLayoutPanel; private Label labelProductName; private Label labelVersion; private Label labelCopyright; private Button okButton; } ================================================ FILE: src/PDBViewer/AboutBox.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Reflection; namespace PDBViewer; partial class AboutBox : Form { public AboutBox() { InitializeComponent(); labelProductName.Text = AssemblyProduct; labelVersion.Text = string.Format("Version {0}", AssemblyVersion); labelCopyright.Text = AssemblyCopyright; } public string AssemblyVersion => Assembly.GetExecutingAssembly().GetName().Version.ToString(); public string AssemblyProduct { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyProductAttribute)attributes[0]).Product; } } public string AssemblyCopyright { get { object[] attributes = Assembly.GetExecutingAssembly(). GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; } } } ================================================ FILE: src/PDBViewer/AboutBox.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/PDBViewer/DebugInfoModel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Runtime.InteropServices; using System.Text; namespace PDBViewer; //? TODO: Move to ProfileExplorerCore and share with ProfileExplorerUI. public class FunctionDebugInfo : IEquatable, IComparable, IComparable { public static readonly FunctionDebugInfo Unknown = new(null, 0, 0); public FunctionDebugInfo(string name, long rva, uint size) { Name = name; RVA = rva; Size = size; SourceLines = null; } public string Name { get; private set; } public List SourceLines { get; set; } public long RVA { get; set; } public uint Size { get; set; } public bool HasSourceLines => SourceLines is {Count: > 0}; public SourceLineDebugInfo FirstSourceLine => HasSourceLines ? SourceLines[0] : SourceLineDebugInfo.Unknown; public SourceLineDebugInfo LastSourceLine => HasSourceLines ? SourceLines[^1] : SourceLineDebugInfo.Unknown; public string SourceFileName => HasSourceLines ? SourceLines[0].FilePath : null; public string OriginalSourceFileName { get; set; } public long StartRVA => RVA; public long EndRVA => RVA + Size - 1; public bool IsUnknown => RVA == 0 && Size == 0; public bool IsPublic { get; set; } public bool IsSelected { get; set; } public bool HasOverlap { get; set; } public bool HasSelectionOverlap { get; set; } public int CompareTo(FunctionDebugInfo other) { // Used by sorting. if (other == null) return 0; if (other.StartRVA < StartRVA) { return 1; } if (other.StartRVA > StartRVA) { return -1; } return 0; } public int CompareTo(long value) { // Used by binary search. if (value < StartRVA) { return 1; } if (value > EndRVA) { return -1; } return 0; } public bool Equals(FunctionDebugInfo other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return RVA == other.RVA && Size == other.Size; } public static FunctionDebugInfo BinarySearch(List ranges, long value, bool hasOverlappingFuncts = false) { int low = 0; int high = ranges.Count - 1; while (low <= high) { int mid = low + (high - low) / 2; var range = ranges[mid]; int result = range.CompareTo(value); if (result == 0) { return range; } if (result < 0) { low = mid + 1; } else { high = mid - 1; } } return null; } public void AddSourceLine(SourceLineDebugInfo sourceLine) { SourceLines ??= new List(1); SourceLines.Add(sourceLine); } public override bool Equals(object obj) { return obj is FunctionDebugInfo info && Equals(info); } public override int GetHashCode() { return HashCode.Combine(RVA, Size); } public override string ToString() { return $"{Name}, RVA: {RVA:X}, Size: {Size}"; } } public class SourceLineDebugInfo : IEquatable { public static readonly SourceLineDebugInfo Unknown = new(-1, -1); public SourceLineDebugInfo(int rva, int line, int column = 0, string filePath = null) { RVA = rva; Line = line; Column = column; FilePath = filePath != null ? string.Intern(filePath) : null; } public int RVA { get; set; } public int Line { get; set; } public int Column { get; set; } public string FilePath { get; private set; } //? Move to FunctionDebugInfo, add OriginalFilePath for SourceLink public List Inlinees { get; set; } public int InlineeCount => Inlinees != null ? Inlinees.Count : 0; public bool IsUnknown => Line == -1; public bool Equals(SourceLineDebugInfo other) { return RVA == other.RVA && Line == other.Line && Column == other.Column && FilePath.Equals(other.FilePath, StringComparison.Ordinal); } public void AddInlinee(SourceStackFrame inlinee) { Inlinees ??= new List(); Inlinees.Add(inlinee); } public bool HasInlinee(SourceStackFrame inlinee) { return Inlinees != null && Inlinees.Contains(inlinee); } public SourceStackFrame FindSameFunctionInlinee(SourceStackFrame inlinee) { return Inlinees?.Find(item => item.HasSameFunction(inlinee)); } public override bool Equals(object obj) { return obj is SourceLineDebugInfo other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(FilePath, Line, Column); } } public sealed class SourceStackFrame : IEquatable { public SourceStackFrame(string function, string filePath, int line, int column) { Function = function; FilePath = filePath; Line = line; Column = column; } public string Function { get; set; } public string FilePath { get; set; } public int Line { get; set; } public int Column { get; set; } public bool Equals(SourceStackFrame other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Line == other.Line && Column == other.Column && Function.Equals(other.Function, StringComparison.OrdinalIgnoreCase) && FilePath.Equals(other.FilePath, StringComparison.OrdinalIgnoreCase); } public static bool operator ==(SourceStackFrame left, SourceStackFrame right) { return Equals(left, right); } public static bool operator !=(SourceStackFrame left, SourceStackFrame right) { return !Equals(left, right); } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is SourceStackFrame other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(Function, FilePath, Line, Column); } public bool HasSameFunction(SourceStackFrame inlinee) { return Function.Equals(inlinee.Function, StringComparison.OrdinalIgnoreCase) && FilePath.Equals(inlinee.FilePath, StringComparison.OrdinalIgnoreCase); } } static class NativeMethods { // C++ function name demangling [Flags] public enum UnDecorateFlags { UNDNAME_COMPLETE = 0x0000, // Enable full undecoration UNDNAME_NO_LEADING_UNDERSCORES = 0x0001, // Remove leading underscores from MS extended keywords UNDNAME_NO_MS_KEYWORDS = 0x0002, // Disable expansion of MS extended keywords UNDNAME_NO_FUNCTION_RETURNS = 0x0004, // Disable expansion of return type for primary declaration UNDNAME_NO_ALLOCATION_MODEL = 0x0008, // Disable expansion of the declaration model UNDNAME_NO_ALLOCATION_LANGUAGE = 0x0010, // Disable expansion of the declaration language specifier UNDNAME_NO_MS_THISTYPE = 0x0020, // NYI Disable expansion of MS keywords on the 'this' type for primary declaration UNDNAME_NO_CV_THISTYPE = 0x0040, // NYI Disable expansion of CV modifiers on the 'this' type for primary declaration UNDNAME_NO_THISTYPE = 0x0060, // Disable all modifiers on the 'this' type UNDNAME_NO_ACCESS_SPECIFIERS = 0x0080, // Disable expansion of access specifiers for members UNDNAME_NO_THROW_SIGNATURES = 0x0100, // Disable expansion of 'throw-signatures' for functions and pointers to functions UNDNAME_NO_MEMBER_TYPE = 0x0200, // Disable expansion of 'static' or 'virtual'ness of members UNDNAME_NO_RETURN_UDT_MODEL = 0x0400, // Disable expansion of MS model for UDT returns UNDNAME_32_BIT_DECODE = 0x0800, // Undecorate 32-bit decorated names UNDNAME_NAME_ONLY = 0x1000, // Crack only the name for primary declaration; // return just [scope::]name. Does expand template params UNDNAME_NO_ARGUMENTS = 0x2000, // Don't undecorate arguments to function UNDNAME_NO_SPECIAL_SYMS = 0x4000 // Don't undecorate special names (v-table, vcall, vector xxx, metatype, etc) } [DllImport("dbghelp.dll", SetLastError = true, PreserveSig = true)] public static extern int UnDecorateSymbolName( [In][MarshalAs(UnmanagedType.LPStr)] string DecoratedName, [Out] StringBuilder UnDecoratedName, [In][MarshalAs(UnmanagedType.U4)] int UndecoratedLength, [In][MarshalAs(UnmanagedType.U4)] UnDecorateFlags Flags); } ================================================ FILE: src/PDBViewer/MainForm.Designer.cs ================================================ namespace PDBViewer { partial class MainForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { var resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm)); toolStrip1 = new ToolStrip(); OpenButton = new ToolStripButton(); toolStripSeparator1 = new ToolStripSeparator(); toolStripDropDownButton1 = new ToolStripDropDownButton(); ShowFunctionsCheckbox = new ToolStripMenuItem(); ShowPublicsCheckbox = new ToolStripMenuItem(); DemangleCheckbox = new ToolStripButton(); toolStripSeparator3 = new ToolStripSeparator(); toolStripLabel1 = new ToolStripLabel(); RVATextbox = new ToolStripTextBox(); SubtractRVAButton = new ToolStripButton(); AddRVAButton = new ToolStripButton(); HexCheckbox = new ToolStripButton(); toolStripSeparator2 = new ToolStripSeparator(); toolStripLabel2 = new ToolStripLabel(); SearchTextbox = new ToolStripTextBox(); SearchResetButton = new ToolStripButton(); RegexCheckbox = new ToolStripButton(); toolStripSeparator4 = new ToolStripSeparator(); AboutButton = new ToolStripButton(); statusStrip1 = new StatusStrip(); toolStripStatusLabel1 = new ToolStripStatusLabel(); SymbolCountLabel = new ToolStripStatusLabel(); toolStripStatusLabel2 = new ToolStripStatusLabel(); TotalSymbolCountLabel = new ToolStripStatusLabel(); StatusLabel = new ToolStripStatusLabel(); ProgressBar = new ToolStripProgressBar(); OpenFileDialog = new OpenFileDialog(); splitContainer1 = new SplitContainer(); FunctionListView = new ListView(); columnHeader1 = new ColumnHeader(); columnHeader2 = new ColumnHeader(); columnHeader3 = new ColumnHeader(); columnHeader5 = new ColumnHeader(); columnHeader4 = new ColumnHeader(); columnHeader6 = new ColumnHeader(); tabControl1 = new TabControl(); tabPage1 = new TabPage(); FunctionDeteailsTextBox = new TextBox(); tabPage2 = new TabPage(); splitContainer2 = new SplitContainer(); SourceLineListView = new ListView(); columnHeader9 = new ColumnHeader(); columnHeader7 = new ColumnHeader(); columnHeader8 = new ColumnHeader(); columnHeader10 = new ColumnHeader(); columnHeader14 = new ColumnHeader(); tabControl2 = new TabControl(); tabPage4 = new TabPage(); SourceTextBox = new RichTextBox(); LineNumbersTextBox = new RichTextBox(); toolStrip2 = new ToolStrip(); SourceOpenButton = new ToolStripButton(); toolStripSeparator5 = new ToolStripSeparator(); SourceFileLabel = new ToolStripLabel(); tabPage3 = new TabPage(); InlineeListView = new ListView(); columnHeader13 = new ColumnHeader(); columnHeader11 = new ColumnHeader(); columnHeader12 = new ColumnHeader(); columnHeader15 = new ColumnHeader(); SourceOpenFileDialog = new OpenFileDialog(); toolStrip1.SuspendLayout(); statusStrip1.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainer1).BeginInit(); splitContainer1.Panel1.SuspendLayout(); splitContainer1.Panel2.SuspendLayout(); splitContainer1.SuspendLayout(); tabControl1.SuspendLayout(); tabPage1.SuspendLayout(); tabPage2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)splitContainer2).BeginInit(); splitContainer2.Panel1.SuspendLayout(); splitContainer2.Panel2.SuspendLayout(); splitContainer2.SuspendLayout(); tabControl2.SuspendLayout(); tabPage4.SuspendLayout(); toolStrip2.SuspendLayout(); tabPage3.SuspendLayout(); SuspendLayout(); // // toolStrip1 // toolStrip1.AutoSize = false; toolStrip1.BackColor = SystemColors.Control; toolStrip1.CanOverflow = false; toolStrip1.GripStyle = ToolStripGripStyle.Hidden; toolStrip1.ImageScalingSize = new Size(28, 28); toolStrip1.Items.AddRange(new ToolStripItem[] { OpenButton, toolStripSeparator1, toolStripDropDownButton1, DemangleCheckbox, toolStripSeparator3, toolStripLabel1, RVATextbox, SubtractRVAButton, AddRVAButton, HexCheckbox, toolStripSeparator2, toolStripLabel2, SearchTextbox, SearchResetButton, RegexCheckbox, toolStripSeparator4, AboutButton }); toolStrip1.Location = new Point(0, 0); toolStrip1.Name = "toolStrip1"; toolStrip1.RenderMode = ToolStripRenderMode.System; toolStrip1.Size = new Size(1566, 40); toolStrip1.TabIndex = 0; toolStrip1.Text = "toolStrip1"; // // OpenButton // OpenButton.Image = (Image)resources.GetObject("OpenButton.Image"); OpenButton.ImageScaling = ToolStripItemImageScaling.None; OpenButton.ImageTransparentColor = Color.Magenta; OpenButton.Margin = new Padding(2, 1, 0, 2); OpenButton.Name = "OpenButton"; OpenButton.Size = new Size(76, 37); OpenButton.Text = "Open"; OpenButton.ToolTipText = "Open PDB file"; OpenButton.Click += OpenButton_Click; // // toolStripSeparator1 // toolStripSeparator1.Name = "toolStripSeparator1"; toolStripSeparator1.Size = new Size(6, 40); // // toolStripDropDownButton1 // toolStripDropDownButton1.DisplayStyle = ToolStripItemDisplayStyle.Text; toolStripDropDownButton1.DropDownItems.AddRange(new ToolStripItem[] { ShowFunctionsCheckbox, ShowPublicsCheckbox }); toolStripDropDownButton1.Image = (Image)resources.GetObject("toolStripDropDownButton1.Image"); toolStripDropDownButton1.ImageTransparentColor = Color.Magenta; toolStripDropDownButton1.Name = "toolStripDropDownButton1"; toolStripDropDownButton1.Size = new Size(74, 35); toolStripDropDownButton1.Text = "Show"; toolStripDropDownButton1.ToolTipText = "Select symbol kind to show"; // // ShowFunctionsCheckbox // ShowFunctionsCheckbox.Checked = true; ShowFunctionsCheckbox.CheckOnClick = true; ShowFunctionsCheckbox.CheckState = CheckState.Checked; ShowFunctionsCheckbox.Name = "ShowFunctionsCheckbox"; ShowFunctionsCheckbox.Size = new Size(236, 34); ShowFunctionsCheckbox.Text = "Show functions"; ShowFunctionsCheckbox.CheckStateChanged += ShowFunctionsCheckbox_CheckStateChanged; // // ShowPublicsCheckbox // ShowPublicsCheckbox.Checked = true; ShowPublicsCheckbox.CheckOnClick = true; ShowPublicsCheckbox.CheckState = CheckState.Checked; ShowPublicsCheckbox.Name = "ShowPublicsCheckbox"; ShowPublicsCheckbox.Size = new Size(236, 34); ShowPublicsCheckbox.Text = "Show publics"; ShowPublicsCheckbox.CheckedChanged += ShowPublicsCheckbox_CheckedChanged; // // DemangleCheckbox // DemangleCheckbox.Checked = true; DemangleCheckbox.CheckOnClick = true; DemangleCheckbox.CheckState = CheckState.Checked; DemangleCheckbox.DisplayStyle = ToolStripItemDisplayStyle.Text; DemangleCheckbox.Image = (Image)resources.GetObject("DemangleCheckbox.Image"); DemangleCheckbox.ImageTransparentColor = Color.Magenta; DemangleCheckbox.Name = "DemangleCheckbox"; DemangleCheckbox.Size = new Size(97, 35); DemangleCheckbox.Text = "Demangle"; DemangleCheckbox.ToolTipText = "Demangle C++ function names"; DemangleCheckbox.CheckedChanged += DemangleCheckbox_CheckedChanged; // // toolStripSeparator3 // toolStripSeparator3.Name = "toolStripSeparator3"; toolStripSeparator3.Size = new Size(6, 40); // // toolStripLabel1 // toolStripLabel1.Image = (Image)resources.GetObject("toolStripLabel1.Image"); toolStripLabel1.ImageScaling = ToolStripItemImageScaling.None; toolStripLabel1.Margin = new Padding(2, 2, 0, 4); toolStripLabel1.Name = "toolStripLabel1"; toolStripLabel1.Size = new Size(61, 34); toolStripLabel1.Text = "RVA"; // // RVATextbox // RVATextbox.Name = "RVATextbox"; RVATextbox.Size = new Size(125, 40); RVATextbox.ToolTipText = "Search for functions with an RVA range overlapping the value"; RVATextbox.TextChanged += RVATextbox_TextChanged; // // SubtractRVAButton // SubtractRVAButton.BackgroundImageLayout = ImageLayout.None; SubtractRVAButton.DisplayStyle = ToolStripItemDisplayStyle.Image; SubtractRVAButton.Image = (Image)resources.GetObject("SubtractRVAButton.Image"); SubtractRVAButton.ImageScaling = ToolStripItemImageScaling.None; SubtractRVAButton.ImageTransparentColor = Color.Magenta; SubtractRVAButton.Name = "SubtractRVAButton"; SubtractRVAButton.Size = new Size(34, 35); SubtractRVAButton.Text = "toolStripButton1"; SubtractRVAButton.ToolTipText = "Decrement searched RVA"; SubtractRVAButton.Click += SubtractRVAButton_Click; // // AddRVAButton // AddRVAButton.DisplayStyle = ToolStripItemDisplayStyle.Image; AddRVAButton.Image = (Image)resources.GetObject("AddRVAButton.Image"); AddRVAButton.ImageScaling = ToolStripItemImageScaling.None; AddRVAButton.ImageTransparentColor = Color.Magenta; AddRVAButton.Name = "AddRVAButton"; AddRVAButton.Size = new Size(34, 35); AddRVAButton.Text = "toolStripButton1"; AddRVAButton.ToolTipText = "Increment searched RVA"; AddRVAButton.Click += AddRVAButton_Click; // // HexCheckbox // HexCheckbox.Checked = true; HexCheckbox.CheckOnClick = true; HexCheckbox.CheckState = CheckState.Checked; HexCheckbox.DisplayStyle = ToolStripItemDisplayStyle.Text; HexCheckbox.Image = (Image)resources.GetObject("HexCheckbox.Image"); HexCheckbox.ImageTransparentColor = Color.Magenta; HexCheckbox.Name = "HexCheckbox"; HexCheckbox.Size = new Size(49, 35); HexCheckbox.Text = "HEX"; HexCheckbox.ToolTipText = "Consider RVA value as being hexadecimal"; HexCheckbox.CheckedChanged += HexCheckbox_CheckedChanged; // // toolStripSeparator2 // toolStripSeparator2.Name = "toolStripSeparator2"; toolStripSeparator2.Size = new Size(6, 40); // // toolStripLabel2 // toolStripLabel2.Image = (Image)resources.GetObject("toolStripLabel2.Image"); toolStripLabel2.ImageScaling = ToolStripItemImageScaling.None; toolStripLabel2.Margin = new Padding(2, 2, 0, 4); toolStripLabel2.Name = "toolStripLabel2"; toolStripLabel2.Size = new Size(129, 34); toolStripLabel2.Text = "Search name"; // // SearchTextbox // SearchTextbox.Name = "SearchTextbox"; SearchTextbox.Size = new Size(249, 40); SearchTextbox.ToolTipText = "Filter list to functions containing substring"; SearchTextbox.TextChanged += SearchTextbox_TextChanged; // // SearchResetButton // SearchResetButton.DisplayStyle = ToolStripItemDisplayStyle.Image; SearchResetButton.Image = (Image)resources.GetObject("SearchResetButton.Image"); SearchResetButton.ImageScaling = ToolStripItemImageScaling.None; SearchResetButton.ImageTransparentColor = Color.Magenta; SearchResetButton.Name = "SearchResetButton"; SearchResetButton.Size = new Size(34, 35); SearchResetButton.Text = "toolStripButton1"; SearchResetButton.ToolTipText = "Clear searched name"; SearchResetButton.Click += SearchResetButton_Click; // // RegexCheckbox // RegexCheckbox.CheckOnClick = true; RegexCheckbox.DisplayStyle = ToolStripItemDisplayStyle.Text; RegexCheckbox.Image = (Image)resources.GetObject("RegexCheckbox.Image"); RegexCheckbox.ImageTransparentColor = Color.Magenta; RegexCheckbox.Name = "RegexCheckbox"; RegexCheckbox.Size = new Size(35, 35); RegexCheckbox.Text = "R*"; RegexCheckbox.ToolTipText = "Use Regex function name filter"; RegexCheckbox.CheckedChanged += RegexCheckbox_CheckedChanged; // // toolStripSeparator4 // toolStripSeparator4.Name = "toolStripSeparator4"; toolStripSeparator4.Size = new Size(6, 40); // // AboutButton // AboutButton.DisplayStyle = ToolStripItemDisplayStyle.Text; AboutButton.Image = (Image)resources.GetObject("AboutButton.Image"); AboutButton.ImageTransparentColor = Color.Magenta; AboutButton.Name = "AboutButton"; AboutButton.Size = new Size(66, 35); AboutButton.Text = "About"; AboutButton.Click += AboutButton_Click; // // statusStrip1 // statusStrip1.ImageScalingSize = new Size(28, 28); statusStrip1.Items.AddRange(new ToolStripItem[] { toolStripStatusLabel1, SymbolCountLabel, toolStripStatusLabel2, TotalSymbolCountLabel, StatusLabel, ProgressBar }); statusStrip1.Location = new Point(0, 969); statusStrip1.Name = "statusStrip1"; statusStrip1.Padding = new Padding(1, 0, 11, 0); statusStrip1.Size = new Size(1566, 32); statusStrip1.TabIndex = 1; statusStrip1.Text = "statusStrip1"; // // toolStripStatusLabel1 // toolStripStatusLabel1.Name = "toolStripStatusLabel1"; toolStripStatusLabel1.Size = new Size(84, 25); toolStripStatusLabel1.Text = "Symbols:"; // // SymbolCountLabel // SymbolCountLabel.Name = "SymbolCountLabel"; SymbolCountLabel.Size = new Size(22, 25); SymbolCountLabel.Text = "0"; SymbolCountLabel.ToolTipText = "Number of symbols in view after search/filtering"; // // toolStripStatusLabel2 // toolStripStatusLabel2.Name = "toolStripStatusLabel2"; toolStripStatusLabel2.Size = new Size(49, 25); toolStripStatusLabel2.Text = "Total"; // // TotalSymbolCountLabel // TotalSymbolCountLabel.Name = "TotalSymbolCountLabel"; TotalSymbolCountLabel.Size = new Size(22, 25); TotalSymbolCountLabel.Text = "0"; TotalSymbolCountLabel.ToolTipText = "Total number of symbols"; // // StatusLabel // StatusLabel.Name = "StatusLabel"; StatusLabel.Size = new Size(134, 25); StatusLabel.Text = "No PDB loaded"; StatusLabel.ToolTipText = "Status message"; // // ProgressBar // ProgressBar.Name = "ProgressBar"; ProgressBar.Size = new Size(84, 24); ProgressBar.Style = ProgressBarStyle.Marquee; ProgressBar.Visible = false; // // OpenFileDialog // OpenFileDialog.FileName = "openFileDialog1"; OpenFileDialog.Filter = "PDB|*.pdb"; // // splitContainer1 // splitContainer1.Dock = DockStyle.Fill; splitContainer1.Location = new Point(0, 40); splitContainer1.Margin = new Padding(2); splitContainer1.Name = "splitContainer1"; splitContainer1.Orientation = Orientation.Horizontal; // // splitContainer1.Panel1 // splitContainer1.Panel1.Controls.Add(FunctionListView); // // splitContainer1.Panel2 // splitContainer1.Panel2.Controls.Add(tabControl1); splitContainer1.Size = new Size(1566, 929); splitContainer1.SplitterDistance = 530; splitContainer1.SplitterWidth = 2; splitContainer1.TabIndex = 2; // // FunctionListView // FunctionListView.Columns.AddRange(new ColumnHeader[] { columnHeader1, columnHeader2, columnHeader3, columnHeader5, columnHeader4, columnHeader6 }); FunctionListView.Dock = DockStyle.Fill; FunctionListView.FullRowSelect = true; FunctionListView.GridLines = true; FunctionListView.Location = new Point(0, 0); FunctionListView.Margin = new Padding(2); FunctionListView.MultiSelect = false; FunctionListView.Name = "FunctionListView"; FunctionListView.Size = new Size(1566, 530); FunctionListView.TabIndex = 3; FunctionListView.UseCompatibleStateImageBehavior = false; FunctionListView.View = View.Details; FunctionListView.SelectedIndexChanged += FunctionListView_SelectedIndexChanged; // // columnHeader1 // columnHeader1.Text = "RVA"; columnHeader1.Width = 100; // // columnHeader2 // columnHeader2.Text = "Name"; columnHeader2.Width = 600; // // columnHeader3 // columnHeader3.Text = "Length"; columnHeader3.Width = 120; // // columnHeader5 // columnHeader5.Text = "End RVA"; columnHeader5.Width = 100; // // columnHeader4 // columnHeader4.Text = "Kind"; columnHeader4.Width = 120; // // columnHeader6 // columnHeader6.Text = "Mangled name"; columnHeader6.Width = 180; // // tabControl1 // tabControl1.Appearance = TabAppearance.FlatButtons; tabControl1.Controls.Add(tabPage1); tabControl1.Controls.Add(tabPage2); tabControl1.Dock = DockStyle.Fill; tabControl1.Location = new Point(0, 0); tabControl1.Margin = new Padding(2); tabControl1.Name = "tabControl1"; tabControl1.SelectedIndex = 0; tabControl1.Size = new Size(1566, 397); tabControl1.TabIndex = 0; // // tabPage1 // tabPage1.Controls.Add(FunctionDeteailsTextBox); tabPage1.Location = new Point(4, 37); tabPage1.Margin = new Padding(2); tabPage1.Name = "tabPage1"; tabPage1.Padding = new Padding(2); tabPage1.Size = new Size(1558, 356); tabPage1.TabIndex = 0; tabPage1.Text = "Details"; tabPage1.UseVisualStyleBackColor = true; // // FunctionDeteailsTextBox // FunctionDeteailsTextBox.BackColor = SystemColors.Window; FunctionDeteailsTextBox.BorderStyle = BorderStyle.None; FunctionDeteailsTextBox.Dock = DockStyle.Fill; FunctionDeteailsTextBox.HideSelection = false; FunctionDeteailsTextBox.Location = new Point(2, 2); FunctionDeteailsTextBox.Margin = new Padding(2); FunctionDeteailsTextBox.Multiline = true; FunctionDeteailsTextBox.Name = "FunctionDeteailsTextBox"; FunctionDeteailsTextBox.PlaceholderText = "Selected function information"; FunctionDeteailsTextBox.ReadOnly = true; FunctionDeteailsTextBox.Size = new Size(1554, 352); FunctionDeteailsTextBox.TabIndex = 0; // // tabPage2 // tabPage2.Controls.Add(splitContainer2); tabPage2.Location = new Point(4, 37); tabPage2.Margin = new Padding(2); tabPage2.Name = "tabPage2"; tabPage2.Padding = new Padding(2); tabPage2.Size = new Size(1558, 356); tabPage2.TabIndex = 1; tabPage2.Text = "Source Lines"; tabPage2.UseVisualStyleBackColor = true; // // splitContainer2 // splitContainer2.Dock = DockStyle.Fill; splitContainer2.Location = new Point(2, 2); splitContainer2.Margin = new Padding(4); splitContainer2.Name = "splitContainer2"; // // splitContainer2.Panel1 // splitContainer2.Panel1.Controls.Add(SourceLineListView); // // splitContainer2.Panel2 // splitContainer2.Panel2.Controls.Add(tabControl2); splitContainer2.Size = new Size(1554, 352); splitContainer2.SplitterDistance = 602; splitContainer2.SplitterWidth = 5; splitContainer2.TabIndex = 0; // // SourceLineListView // SourceLineListView.Columns.AddRange(new ColumnHeader[] { columnHeader9, columnHeader7, columnHeader8, columnHeader10, columnHeader14 }); SourceLineListView.Dock = DockStyle.Fill; SourceLineListView.FullRowSelect = true; SourceLineListView.GridLines = true; SourceLineListView.Location = new Point(0, 0); SourceLineListView.Margin = new Padding(2); SourceLineListView.Name = "SourceLineListView"; SourceLineListView.Size = new Size(602, 352); SourceLineListView.TabIndex = 4; SourceLineListView.UseCompatibleStateImageBehavior = false; SourceLineListView.View = View.Details; SourceLineListView.SelectedIndexChanged += SourceLineListView_SelectedIndexChanged; // // columnHeader9 // columnHeader9.Text = "RVA"; columnHeader9.Width = 80; // // columnHeader7 // columnHeader7.Text = "Line"; columnHeader7.Width = 80; // // columnHeader8 // columnHeader8.Text = "Column"; columnHeader8.Width = 80; // // columnHeader10 // columnHeader10.Text = "Inlinees"; columnHeader10.Width = 80; // // columnHeader14 // columnHeader14.Text = "File"; columnHeader14.Width = 250; // // tabControl2 // tabControl2.Appearance = TabAppearance.FlatButtons; tabControl2.Controls.Add(tabPage4); tabControl2.Controls.Add(tabPage3); tabControl2.Dock = DockStyle.Fill; tabControl2.Location = new Point(0, 0); tabControl2.Margin = new Padding(4); tabControl2.Name = "tabControl2"; tabControl2.SelectedIndex = 0; tabControl2.Size = new Size(947, 352); tabControl2.TabIndex = 0; // // tabPage4 // tabPage4.Controls.Add(SourceTextBox); tabPage4.Controls.Add(LineNumbersTextBox); tabPage4.Controls.Add(toolStrip2); tabPage4.Location = new Point(4, 37); tabPage4.Margin = new Padding(4); tabPage4.Name = "tabPage4"; tabPage4.Padding = new Padding(4); tabPage4.Size = new Size(939, 311); tabPage4.TabIndex = 1; tabPage4.Text = "Source Preview"; tabPage4.ToolTipText = "Source file having lines with debug info marked"; tabPage4.UseVisualStyleBackColor = true; // // SourceTextBox // SourceTextBox.BackColor = SystemColors.Window; SourceTextBox.BorderStyle = BorderStyle.None; SourceTextBox.Dock = DockStyle.Fill; SourceTextBox.Font = new Font("Consolas", 9F, FontStyle.Regular, GraphicsUnit.Point, 0); SourceTextBox.HideSelection = false; SourceTextBox.Location = new Point(84, 38); SourceTextBox.Margin = new Padding(16, 4, 4, 4); SourceTextBox.Name = "SourceTextBox"; SourceTextBox.ReadOnly = true; SourceTextBox.ScrollBars = RichTextBoxScrollBars.Vertical; SourceTextBox.Size = new Size(851, 269); SourceTextBox.TabIndex = 0; SourceTextBox.Text = "Open source file"; SourceTextBox.WordWrap = false; SourceTextBox.SelectionChanged += SourceTextBox_SelectionChanged; SourceTextBox.VScroll += SourceTextBox_VScroll; SourceTextBox.TextChanged += SourceTextBox_TextChanged; // // LineNumbersTextBox // LineNumbersTextBox.BackColor = SystemColors.Window; LineNumbersTextBox.BorderStyle = BorderStyle.None; LineNumbersTextBox.Dock = DockStyle.Left; LineNumbersTextBox.Font = new Font("Consolas", 9F, FontStyle.Regular, GraphicsUnit.Point, 0); LineNumbersTextBox.ForeColor = Color.DarkBlue; LineNumbersTextBox.Location = new Point(4, 38); LineNumbersTextBox.Margin = new Padding(4); LineNumbersTextBox.Name = "LineNumbersTextBox"; LineNumbersTextBox.ReadOnly = true; LineNumbersTextBox.ScrollBars = RichTextBoxScrollBars.None; LineNumbersTextBox.Size = new Size(80, 269); LineNumbersTextBox.TabIndex = 2; LineNumbersTextBox.TabStop = false; LineNumbersTextBox.Text = ""; LineNumbersTextBox.WordWrap = false; LineNumbersTextBox.MouseDown += LineNumbersTextBox_MouseDown; // // toolStrip2 // toolStrip2.BackColor = SystemColors.Control; toolStrip2.GripStyle = ToolStripGripStyle.Hidden; toolStrip2.ImageScalingSize = new Size(20, 20); toolStrip2.Items.AddRange(new ToolStripItem[] { SourceOpenButton, toolStripSeparator5, SourceFileLabel }); toolStrip2.Location = new Point(4, 4); toolStrip2.Name = "toolStrip2"; toolStrip2.RenderMode = ToolStripRenderMode.System; toolStrip2.Size = new Size(931, 34); toolStrip2.TabIndex = 1; toolStrip2.Text = "toolStrip2"; // // SourceOpenButton // SourceOpenButton.Image = (Image)resources.GetObject("SourceOpenButton.Image"); SourceOpenButton.ImageScaling = ToolStripItemImageScaling.None; SourceOpenButton.ImageTransparentColor = Color.Magenta; SourceOpenButton.Name = "SourceOpenButton"; SourceOpenButton.Size = new Size(76, 29); SourceOpenButton.Text = "Open"; SourceOpenButton.Click += SourceOpenButton_Click; // // toolStripSeparator5 // toolStripSeparator5.Name = "toolStripSeparator5"; toolStripSeparator5.Size = new Size(6, 34); // // SourceFileLabel // SourceFileLabel.Name = "SourceFileLabel"; SourceFileLabel.Size = new Size(181, 29); SourceFileLabel.Text = "No source file loaded"; // // tabPage3 // tabPage3.Controls.Add(InlineeListView); tabPage3.Location = new Point(4, 37); tabPage3.Margin = new Padding(4); tabPage3.Name = "tabPage3"; tabPage3.Padding = new Padding(4); tabPage3.Size = new Size(939, 311); tabPage3.TabIndex = 0; tabPage3.Text = "Inlinees"; tabPage3.ToolTipText = "Functions inlined at the selected line"; tabPage3.UseVisualStyleBackColor = true; // // InlineeListView // InlineeListView.Columns.AddRange(new ColumnHeader[] { columnHeader13, columnHeader11, columnHeader12, columnHeader15 }); InlineeListView.Dock = DockStyle.Fill; InlineeListView.FullRowSelect = true; InlineeListView.GridLines = true; InlineeListView.Location = new Point(4, 4); InlineeListView.Margin = new Padding(2); InlineeListView.MultiSelect = false; InlineeListView.Name = "InlineeListView"; InlineeListView.Size = new Size(931, 303); InlineeListView.TabIndex = 6; InlineeListView.UseCompatibleStateImageBehavior = false; InlineeListView.View = View.Details; // // columnHeader13 // columnHeader13.Text = "Inlinee Name"; columnHeader13.Width = 400; // // columnHeader11 // columnHeader11.Text = "Line"; columnHeader11.Width = 80; // // columnHeader12 // columnHeader12.Text = "Column"; columnHeader12.Width = 80; // // columnHeader15 // columnHeader15.Text = "File Name"; columnHeader15.Width = 250; // // SourceOpenFileDialog // SourceOpenFileDialog.FileName = "openFileDialog1"; SourceOpenFileDialog.Filter = "Source Files|*.*"; // // MainForm // AutoScaleDimensions = new SizeF(10F, 25F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(1566, 1001); Controls.Add(splitContainer1); Controls.Add(statusStrip1); Controls.Add(toolStrip1); Margin = new Padding(2); Name = "MainForm"; StartPosition = FormStartPosition.CenterScreen; Text = "PDB Viewer"; Load += MainForm_Load; toolStrip1.ResumeLayout(false); toolStrip1.PerformLayout(); statusStrip1.ResumeLayout(false); statusStrip1.PerformLayout(); splitContainer1.Panel1.ResumeLayout(false); splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)splitContainer1).EndInit(); splitContainer1.ResumeLayout(false); tabControl1.ResumeLayout(false); tabPage1.ResumeLayout(false); tabPage1.PerformLayout(); tabPage2.ResumeLayout(false); splitContainer2.Panel1.ResumeLayout(false); splitContainer2.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)splitContainer2).EndInit(); splitContainer2.ResumeLayout(false); tabControl2.ResumeLayout(false); tabPage4.ResumeLayout(false); tabPage4.PerformLayout(); toolStrip2.ResumeLayout(false); toolStrip2.PerformLayout(); tabPage3.ResumeLayout(false); ResumeLayout(false); PerformLayout(); } #endregion private ToolStrip toolStrip1; private ToolStripButton OpenButton; private ToolStripSeparator toolStripSeparator1; private ToolStripLabel toolStripLabel1; private StatusStrip statusStrip1; private ToolStripStatusLabel toolStripStatusLabel1; private ToolStripDropDownButton toolStripDropDownButton1; private ToolStripMenuItem ShowFunctionsCheckbox; private ToolStripMenuItem ShowPublicsCheckbox; private ToolStripSeparator toolStripSeparator3; private ToolStripTextBox RVATextbox; private ToolStripSeparator toolStripSeparator2; private ToolStripLabel toolStripLabel2; private ToolStripTextBox SearchTextbox; private ToolStripStatusLabel SymbolCountLabel; private OpenFileDialog OpenFileDialog; private ToolStripButton HexCheckbox; private ToolStripStatusLabel toolStripStatusLabel2; private ToolStripStatusLabel TotalSymbolCountLabel; private ToolStripStatusLabel StatusLabel; private ToolStripProgressBar ProgressBar; private ToolStripButton DemangleCheckbox; private ToolStripButton AddRVAButton; private ToolStripButton SubtractRVAButton; private ToolStripButton SearchResetButton; private SplitContainer splitContainer1; private ListView FunctionListView; private ColumnHeader columnHeader1; private ColumnHeader columnHeader2; private ColumnHeader columnHeader3; private ColumnHeader columnHeader5; private ColumnHeader columnHeader4; private ColumnHeader columnHeader6; private TabControl tabControl1; private TabPage tabPage1; private TabPage tabPage2; private TextBox FunctionDeteailsTextBox; private SplitContainer splitContainer2; private ListView SourceLineListView; private ColumnHeader columnHeader7; private ColumnHeader columnHeader8; private ColumnHeader columnHeader9; private ColumnHeader columnHeader10; private TabControl tabControl2; private TabPage tabPage3; private TabPage tabPage4; private ListView InlineeListView; private ColumnHeader columnHeader13; private ColumnHeader columnHeader11; private ColumnHeader columnHeader12; private ColumnHeader columnHeader15; private RichTextBox SourceTextBox; private ToolStripButton RegexCheckbox; private ToolStrip toolStrip2; private ToolStripButton SourceOpenButton; private ToolStripSeparator toolStripSeparator5; private ToolStripLabel SourceFileLabel; private ColumnHeader columnHeader14; private OpenFileDialog SourceOpenFileDialog; private RichTextBox LineNumbersTextBox; private ToolStripSeparator toolStripSeparator4; private ToolStripButton AboutButton; } } ================================================ FILE: src/PDBViewer/MainForm.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Diagnostics; using System.Globalization; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using Dia2Lib; using ProfileExplorer.Core; namespace PDBViewer; public partial class MainForm : Form { private IDiaDataSource diaSource_; private IDiaSession session_; private IDiaSymbol globalSymbol_; private List sortedFuncList_; private List filteredFuncList_; private string debugFilePath_; private SourceFileMapper sourceMapper_; private bool ignoredNextSourceCaretEvent_; private bool ignoreSourceLineSelectedEvent_; public MainForm() { InitializeComponent(); FunctionListView.VirtualMode = true; FunctionListView.RetrieveVirtualItem += FunctionListViewOnRetrieveVirtualItem; FunctionListView.KeyDown += FunctionListViewOnKeyDown; sourceMapper_ = new SourceFileMapper(); } private void FunctionListViewOnKeyDown(object? sender, KeyEventArgs e) { if (e.Control && e.KeyCode == Keys.C && FunctionListView.SelectedIndices.Count == 1) { var item = filteredFuncList_[FunctionListView.SelectedIndices[0]]; var sb = new StringBuilder(); PrintFunctionDetails(item, sb); Clipboard.SetText(sb.ToString()); e.Handled = true; } } private async void OpenButton_Click(object sender, EventArgs e) { if (OpenFileDialog.ShowDialog(this) == DialogResult.OK) { string? filePath = OpenFileDialog.FileName; await LoadDebugFile(filePath); } } private async Task LoadDebugFile(string filePath) { var sw = Stopwatch.StartNew(); StatusLabel.Text = "Opening PDB"; FunctionListView.Enabled = false; ProgressBar.Visible = true; Application.UseWaitCursor = true; if (!await OpenPDB(filePath)) { MessageBox.Show("Failed to open PDB", "PDB Viewer", MessageBoxButtons.OK, MessageBoxIcon.Error); ProgressBar.Visible = true; return; } StatusLabel.Text = "Enumerating functions"; if (!await LoadFunctionList()) { MessageBox.Show("Failed to load function list from PDB", "PDB Viewer", MessageBoxButtons.OK, MessageBoxIcon.Error); ProgressBar.Visible = false; return; } Text = $"PDB Viewer - {filePath}"; StatusLabel.Text = $"PDB loaded"; UpdateFunctionListView(); ProgressBar.Visible = false; FunctionListView.Enabled = true; Application.UseWaitCursor = false; } private void UpdateFunctionListView() { if (sortedFuncList_ == null) { return; } filteredFuncList_ = new List(); bool showFuncts = ShowFunctionsCheckbox.Checked; bool showPublics = ShowPublicsCheckbox.Checked; bool filterName = SearchTextbox.Text.Length > 0; string searchedText = SearchTextbox.Text.Trim(); bool demangle = DemangleCheckbox.Checked; Regex nameRegex = null; if (filterName && RegexCheckbox.Checked) { try { nameRegex = new Regex(searchedText, RegexOptions.Compiled); StatusLabel.Text = ""; } catch (Exception ex) { StatusLabel.Text = $"Invalid regex: {ex.Message}"; return; } } foreach (var item in sortedFuncList_) { if (!showFuncts && !item.IsPublic) { continue; } if (!showPublics && item.IsPublic) { continue; } if (filterName) { string? funcName = GetFunctionName(item, demangle); if (nameRegex != null) { if (!nameRegex.IsMatch(funcName)) { continue; } } else if (!funcName.Contains(searchedText, StringComparison.OrdinalIgnoreCase)) { continue; } } filteredFuncList_.Add(item); } for (int i = 1; i < filteredFuncList_.Count; i++) { if (filteredFuncList_[i].StartRVA == 0) { continue; } for (int k = i - 1; k >= 0 && i - k < 50; k--) { if (filteredFuncList_[k].StartRVA == 0) { continue; } if (filteredFuncList_[k].StartRVA <= filteredFuncList_[i].StartRVA && filteredFuncList_[k].EndRVA > filteredFuncList_[i].EndRVA) { filteredFuncList_[i].HasOverlap = true; filteredFuncList_[k].HasOverlap = true; } else if (filteredFuncList_[k].EndRVA < filteredFuncList_[i].StartRVA) { break; } } } FunctionListView.VirtualListSize = filteredFuncList_.Count; if (filteredFuncList_.Count > 0) { FunctionListView.RedrawItems(0, filteredFuncList_.Count - 1, false); } SymbolCountLabel.Text = filteredFuncList_.Count.ToString(); TotalSymbolCountLabel.Text = sortedFuncList_.Count.ToString(); } private void UpdateSelectedRVAItem() { if (filteredFuncList_ == null) { return; } (bool hasRVA, long searchedRVA) = GetRVAValue(); int selectedIndex = -1; int index = 0; foreach (var item in filteredFuncList_) { if (hasRVA && FunctionDebugInfo.BinarySearch(sortedFuncList_, searchedRVA) == item) { item.IsSelected = true; selectedIndex = index; } else { item.IsSelected = false; } index++; } if (selectedIndex != -1 && filteredFuncList_.Count > 0) { FunctionListView.RedrawItems(0, filteredFuncList_.Count - 1, false); FunctionListView.EnsureVisible(selectedIndex); } } private (bool, long) GetRVAValue() { bool hasRVA = false; long searchedRVA = 0; if (RVATextbox.Text.Length > 0) { if (HexCheckbox.Checked) { hasRVA = long.TryParse(RVATextbox.Text.Trim(), NumberStyles.HexNumber, null, out searchedRVA); } else { hasRVA = long.TryParse(RVATextbox.Text.Trim(), NumberStyles.Integer, null, out searchedRVA); } } return (hasRVA, searchedRVA); } private void SetRVAValue(long value) { if (HexCheckbox.Checked) { RVATextbox.Text = value.ToString("X"); } else { RVATextbox.Text = value.ToString(); } } private async Task OpenPDB(string debugFilePath) { try { await Task.Run(() => { debugFilePath_ = debugFilePath; diaSource_ = new DiaSourceClass(); diaSource_.loadDataFromPdb(debugFilePath); diaSource_.openSession(out session_); try { session_.findChildren(null, SymTagEnum.SymTagExe, null, 0, out var exeSymEnum); globalSymbol_ = exeSymEnum.Item(0); } catch (Exception ex) { Trace.TraceError($"Failed to locate global sym for file {debugFilePath}: {ex.Message}"); } }); } catch (Exception ex) { Trace.TraceError($"Failed to load debug file {debugFilePath}: {ex.Message}"); return false; } return true; } private async Task LoadFunctionList() { sortedFuncList_ = await Task.Run(CollectFunctionDebugInfo); if (sortedFuncList_ != null) { sortedFuncList_.Sort(); return true; } return false; } private List CollectFunctionDebugInfo() { IDiaEnumSymbols symbolEnum = null; IDiaEnumSymbols publicSymbolEnum = null; try { globalSymbol_.findChildren(SymTagEnum.SymTagFunction, null, 0, out symbolEnum); globalSymbol_.findChildren(SymTagEnum.SymTagPublicSymbol, null, 0, out publicSymbolEnum); var funcSymbolsSet = new HashSet(symbolEnum.count); foreach (IDiaSymbol sym in symbolEnum) { //Trace.WriteLine($" FuncSym {sym.name}: RVA {sym.relativeVirtualAddress:X}, size {sym.length}"); var funcInfo = new FunctionDebugInfo(sym.name, sym.relativeVirtualAddress, (uint)sym.length); funcSymbolsSet.Add(funcInfo); } foreach (IDiaSymbol sym in publicSymbolEnum) { //Trace.WriteLine($" PublicSym {sym.name}: RVA {sym.relativeVirtualAddress:X} size {sym.length}"); var funcInfo = new FunctionDebugInfo(sym.name, sym.relativeVirtualAddress, (uint)sym.length); funcInfo.IsPublic = true; funcSymbolsSet.Add(funcInfo); } return funcSymbolsSet.ToList(); } catch (Exception ex) { Trace.TraceError($"Failed to enumerate functions: {ex.Message}"); } finally { if (symbolEnum != null) { Marshal.ReleaseComObject(symbolEnum); } if (publicSymbolEnum != null) { Marshal.ReleaseComObject(publicSymbolEnum); } } return null; } private async Task<(SourceLineDebugInfo, IDiaSourceFile)> FindSourceLineByRVA(long rva) { return await Task.Run(() => { try { session_.findLinesByRVA((uint)rva, 0, out var lineEnum); while (true) { lineEnum.Next(1, out var lineNumber, out uint retrieved); if (retrieved == 0) { break; } var sourceFile = lineNumber.sourceFile; var sourceLine = new SourceLineDebugInfo((int)lineNumber.relativeVirtualAddress, (int)lineNumber.lineNumber, (int)lineNumber.columnNumber, sourceFile.fileName); return (sourceLine, sourceFile); } } catch (Exception ex) { Trace.TraceError($"Failed to get line for RVA {rva}: {ex.Message}"); } return (SourceLineDebugInfo.Unknown, null); }); } private async Task AnnotateSourceLines(FunctionDebugInfo func) { if (func.HasSourceLines) { return; } await Task.Run(() => { try { var funcSymbol = FindFunctionSymbol(func); session_.findLinesByRVA((uint)func.StartRVA, func.Size, out var lineEnum); while (true) { lineEnum.Next(1, out var lineNumber, out uint retrieved); if (retrieved == 0) { break; } uint lineRVA = lineNumber.relativeVirtualAddress; var sourceFile = lineNumber.sourceFile; var sourceLine = new SourceLineDebugInfo((int)lineRVA, (int)lineNumber.lineNumber, (int)lineNumber.columnNumber, sourceFile.fileName); if (funcSymbol != null) { try { string? name = funcSymbol.name; // Enumerate the functions that got inlined at this call site. foreach (var inlinee in EnumerateInlinees(funcSymbol, lineRVA)) { if (string.IsNullOrEmpty(inlinee.FilePath)) { // If the file name is not set, it means it's the same file // as the function into which the inlining happened. inlinee.FilePath = sourceFile.fileName; } sourceLine.AddInlinee(inlinee); } } catch (Exception ex) { Trace.TraceError($"Failed to get inlinees for RVA {func.StartRVA}: {ex.Message}"); } } func.AddSourceLine(sourceLine); } } catch (Exception ex) { Trace.TraceError($"Failed to get line for RVA {func.StartRVA}: {ex.Message}"); } }); } private IEnumerable EnumerateInlinees(IDiaSymbol funcSymbol, uint instrRVA) { funcSymbol.findInlineFramesByRVA(instrRVA, out var inlineeFrameEnum); foreach (IDiaSymbol inlineFrame in inlineeFrameEnum) { inlineFrame.findInlineeLinesByRVA(instrRVA, 0, out var inlineeLineEnum); while (true) { inlineeLineEnum.Next(1, out var inlineeLineNumber, out uint inlineeRetrieved); if (inlineeRetrieved == 0) { break; } // Getting the source file of the inlinee often fails, ignore it. string inlineeFileName = null; try { inlineeFileName = inlineeLineNumber.sourceFile.fileName; } catch { //? TODO: Any way to detect this and avoid throwing? } var inlinee = new SourceStackFrame( inlineFrame.name, inlineeFileName, (int)inlineeLineNumber.lineNumber, (int)inlineeLineNumber.columnNumber); yield return inlinee; } Marshal.ReleaseComObject(inlineeLineEnum); } Marshal.ReleaseComObject(inlineeFrameEnum); } private IDiaSymbol FindFunctionSymbol(FunctionDebugInfo func) { try { if (func.IsPublic) { session_.findSymbolByRVA((uint)func.StartRVA, SymTagEnum.SymTagPublicSymbol, out var pubSym); return pubSym; } else { session_.findSymbolByRVA((uint)func.StartRVA, SymTagEnum.SymTagFunction, out var funcSym); return funcSym; } } catch (Exception ex) { Trace.TraceError($"Failed to find function symbol for RVA {func.StartRVA}: {ex.Message}"); } return null; } public string GetFunctionName(FunctionDebugInfo item, bool demangle) { if (!demangle) { return item.Name; } var flags = NativeMethods.UnDecorateFlags.UNDNAME_COMPLETE; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_ACCESS_SPECIFIERS | NativeMethods.UnDecorateFlags.UNDNAME_NO_ALLOCATION_MODEL | NativeMethods.UnDecorateFlags.UNDNAME_NO_MEMBER_TYPE; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NAME_ONLY; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_MS_KEYWORDS; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_MS_THISTYPE; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_FUNCTION_RETURNS; const int MaxDemangledFunctionNameLength = 8192; var sb = new StringBuilder(MaxDemangledFunctionNameLength); NativeMethods.UnDecorateSymbolName(item.Name, sb, MaxDemangledFunctionNameLength, flags); return sb.ToString(); } private void RVATextbox_TextChanged(object? sender, EventArgs e) { UpdateSelectedRVAItem(); } private void SearchTextbox_TextChanged(object? sender, EventArgs e) { UpdateFunctionListView(); } private void HexCheckbox_CheckedChanged(object? sender, EventArgs e) { UpdateSelectedRVAItem(); } private void ShowPublicsCheckbox_CheckedChanged(object sender, EventArgs e) { UpdateFunctionListView(); } private void ShowFunctionsCheckbox_CheckStateChanged(object sender, EventArgs e) { UpdateFunctionListView(); } private async void DemangleCheckbox_CheckedChanged(object sender, EventArgs e) { UpdateFunctionListView(); } private void AddRVAButton_Click(object sender, EventArgs e) { (bool hasRVA, long value) = GetRVAValue(); if (hasRVA) { SetRVAValue(value + 4); } } private void SubtractRVAButton_Click(object sender, EventArgs e) { (bool hasRVA, long value) = GetRVAValue(); if (hasRVA) { SetRVAValue(Math.Max(0, value - 4)); } } private async void FunctionListView_SelectedIndexChanged(object sender, EventArgs e) { var currentFunc = GetSelectedFunction(); if (currentFunc == null) { return; } UpdateOverlappingFunctions(currentFunc); await UpdateSelectedFunction(currentFunc); } private FunctionDebugInfo GetSelectedFunction() { if (FunctionListView.SelectedIndices.Count == 0 || filteredFuncList_ == null) { return null; } return filteredFuncList_[FunctionListView.SelectedIndices[0]]; } private void UpdateOverlappingFunctions(FunctionDebugInfo currentItem) { int count = 0; foreach (var item in filteredFuncList_) { if (item != currentItem && !(item.EndRVA < currentItem.StartRVA || item.StartRVA > currentItem.EndRVA)) { item.HasSelectionOverlap = true; count++; } else { item.HasSelectionOverlap = false; } } if (count > 0) { StatusLabel.Text = $"Overlapping: {count}"; } else { StatusLabel.Text = ""; } if (filteredFuncList_.Count > 0) { FunctionListView.RedrawItems(0, filteredFuncList_.Count - 1, false); } } private async Task UpdateSelectedFunction(FunctionDebugInfo func) { var sb = new StringBuilder(); PrintFunctionDetails(func, sb, false); sb.AppendLine(); await PrintFunctionFile(func, sb); sb.AppendLine(); sb.AppendLine($"Name: {GetFunctionName(func, true)}"); sb.AppendLine($"Mangled name: {func.Name}"); FunctionDeteailsTextBox.Text = sb.ToString(); await AnnotateSourceLines(func); if (func.HasSourceLines) { SourceLineListView.BeginUpdate(); SourceLineListView.Items.Clear(); foreach (var line in func.SourceLines) { var lvi = new ListViewItem(); lvi.Text = $"{line.RVA:X}"; lvi.SubItems.Add($"{line.Line}"); lvi.SubItems.Add($"{line.Column}"); lvi.SubItems.Add($"{line.InlineeCount}"); lvi.SubItems.Add($"{line.FilePath}"); lvi.Tag = line; SourceLineListView.Items.Add(lvi); } SourceLineListView.EndUpdate(); await LoadSourceFile(func); } } private async Task LoadSourceFile(FunctionDebugInfo func, string sourceFile = null) { if (sourceFile == null) { sourceFile = sourceMapper_.Map(func.SourceFileName); } if (!File.Exists(sourceFile)) { SourceTextBox.Text = "Source file not found"; SourceFileLabel.Text = ""; return; } try { if (!string.IsNullOrEmpty(func.SourceFileName) && func.SourceFileName != sourceFile) { sourceMapper_.UpdateMap(func.SourceFileName, sourceFile); } SourceTextBox.Text = await File.ReadAllTextAsync(sourceFile); SourceFileLabel.Text = sourceFile; if (func.HasSourceLines) { foreach (var line in func.SourceLines) { HighlightSourceLine(SourceTextBox, line.Line - 1, Color.Bisque); } } } catch (Exception ex) { SourceTextBox.Text = $"Failed to load source file: {ex.Message}"; SourceFileLabel.Text = ""; } } private async Task PrintFunctionFile(FunctionDebugInfo item, StringBuilder sb) { var (sourceLine, sourceFile) = await FindSourceLineByRVA(item.StartRVA); if (sourceLine.IsUnknown) { sb.AppendLine("Missing source line info"); } sb.AppendLine($"Source File: {sourceLine.FilePath}"); sb.AppendLine($"Source Line: {sourceLine.Line} (column {sourceLine.Column})"); } private void SearchResetButton_Click(object sender, EventArgs e) { SearchTextbox.Text = ""; StatusLabel.Text = ""; } private void SourceLineListView_SelectedIndexChanged(object sender, EventArgs e) { if (ignoreSourceLineSelectedEvent_ || SourceLineListView.SelectedItems.Count == 0) { return; } var item = SourceLineListView.SelectedItems[0]; var line = item.Tag as SourceLineDebugInfo; if (line == null) { return; } InlineeListView.BeginUpdate(); InlineeListView.Items.Clear(); if (line.InlineeCount > 0) { foreach (var inlinee in line.Inlinees) { var lvi = new ListViewItem(); lvi.Text = $"{inlinee.Function}"; lvi.SubItems.Add($"{inlinee.Line}"); lvi.SubItems.Add($"{inlinee.Column}"); lvi.SubItems.Add(inlinee.FilePath); lvi.Tag = inlinee; InlineeListView.Items.Add(lvi); } } InlineeListView.EndUpdate(); SelectSourceLine(SourceTextBox, line.Line - 1); } private void HighlightSourceLine(RichTextBox richTextBox, int lineNumber, Color color) { if (lineNumber < 0 || lineNumber >= richTextBox.Lines.Length) { return; } ignoredNextSourceCaretEvent_ = true; int start = richTextBox.GetFirstCharIndexFromLine(lineNumber); int length = richTextBox.Lines[lineNumber].Length; richTextBox.Select(start, length); richTextBox.SelectionBackColor = color; richTextBox.SelectionLength = 0; } private void SelectSourceLine(RichTextBox richTextBox, int lineNumber) { if (lineNumber < 0 || lineNumber >= richTextBox.Lines.Length) { return; } ignoredNextSourceCaretEvent_ = true; int start = richTextBox.GetFirstCharIndexFromLine(lineNumber); int length = richTextBox.Lines[lineNumber].Length; richTextBox.Select(start, length); richTextBox.ScrollToCaret(); } private async void SourceOpenButton_Click(object sender, EventArgs e) { var currentFunc = GetSelectedFunction(); if (currentFunc != null && SourceOpenFileDialog.ShowDialog(this) == DialogResult.OK) { await LoadSourceFile(currentFunc, SourceOpenFileDialog.FileName); } } private void SourceTextBox_SelectionChanged(object sender, EventArgs e) { if (ignoredNextSourceCaretEvent_) { ignoredNextSourceCaretEvent_ = false; return; } var currentFunc = GetSelectedFunction(); if (currentFunc == null || !currentFunc.HasSourceLines) { return; } ignoreSourceLineSelectedEvent_ = true; SourceLineListView.SelectedIndices.Clear(); int lineIndex = SourceTextBox.GetLineFromCharIndex(SourceTextBox.SelectionStart); int firstIndex = -1; for (int i = 0; i < currentFunc.SourceLines.Count; i++) { if (currentFunc.SourceLines[i].Line == lineIndex + 1) { SourceLineListView.SelectedIndices.Add(i); firstIndex = i; } } ignoreSourceLineSelectedEvent_ = false; SourceLineListView.Focus(); if (firstIndex != -1) { SourceLineListView.EnsureVisible(firstIndex); } } private async void MainForm_Load(object sender, EventArgs e) { string[]? args = Environment.GetCommandLineArgs(); if (args.Length < 2) { return; } string? file = args[1]; if (File.Exists(file)) { await LoadDebugFile(file); } } private void RegexCheckbox_CheckedChanged(object sender, EventArgs e) { UpdateFunctionListView(); } private void SourceTextBox_VScroll(object sender, EventArgs e) { LineNumbersTextBox.Text = ""; int firstVisibleLine = SourceTextBox.GetLineFromCharIndex(SourceTextBox.GetCharIndexFromPosition(new Point(0, 0))); int lastVisibleLine = SourceTextBox.GetLineFromCharIndex(SourceTextBox.GetCharIndexFromPosition(new Point(0, SourceTextBox.Height))) + 1; for (int i = firstVisibleLine; i <= lastVisibleLine; i++) { LineNumbersTextBox.AppendText($"{i + 1}: \n"); } LineNumbersTextBox.SelectAll(); LineNumbersTextBox.SelectionAlignment = HorizontalAlignment.Right; LineNumbersTextBox.DeselectAll(); // Synchronize scroll position. LineNumbersTextBox.Select(SourceTextBox.GetCharIndexFromPosition(new Point(0, 0)), 0); LineNumbersTextBox.ScrollToCaret(); } private void SourceTextBox_TextChanged(object sender, EventArgs e) { SourceTextBox_VScroll(sender, e); } private void LineNumbersTextBox_MouseDown(object sender, MouseEventArgs e) { SourceTextBox.Focus(); } private void PrintFunctionDetails(FunctionDebugInfo item, StringBuilder sb, bool includeName = true) { sb.AppendLine($"Start RVA: 0x{item.RVA:X} ({item.RVA})"); sb.AppendLine($"End RVA: 0x{item.EndRVA:X} ({item.EndRVA})"); sb.AppendLine($"Length: {item.Size} ({item.Size:X})"); sb.AppendLine($"Kind: {(item.IsPublic ? "Public" : "Function")}"); if (includeName) { sb.AppendLine(); sb.AppendLine($"Name: {GetFunctionName(item, true)}"); sb.AppendLine(); sb.AppendLine($"Mangled name: {item.Name}"); } } private void FunctionListViewOnRetrieveVirtualItem(object? sender, RetrieveVirtualItemEventArgs e) { if (filteredFuncList_ != null && e.ItemIndex < filteredFuncList_.Count) { var item = filteredFuncList_[e.ItemIndex]; var lvi = new ListViewItem(); lvi.Text = $"{item.RVA:X}"; lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, GetFunctionName(item, DemangleCheckbox.Checked))); lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, $"{item.Size} ({item.Size:X})")); lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, $"{item.EndRVA:X}")); lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, item.IsPublic ? "Public" : "Function")); lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, item.Name)); if (item.HasSelectionOverlap) { lvi.BackColor = Color.Pink; } else if (item.IsSelected) { lvi.BackColor = Color.LightBlue; } else if (item.HasOverlap) { lvi.BackColor = Color.PaleGoldenrod; } e.Item = lvi; } } private void AboutButton_Click(object sender, EventArgs e) { var window = new AboutBox(); window.ShowDialog(this); } } ================================================ FILE: src/PDBViewer/MainForm.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 17, 17 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAEQSURBVDhPxZAxSwMxGIafSfAniP4Dl/4AB9GfIE7XqLs2 OaWbe6mgW7kmtznqrMKlroKTm6uKolAnHZwrd+Va82FAQfCFh4Rc3ofcB79N07dJBsvy+OdRgyWUH9Is VuSneNZPZ1D+AOVfUH40priV1+JRRRdVnLFxOV89P/GvwW9YzYMzjL7w3jdML6jzZ5KLhWr/3QzKkk2Z q8k0a4eaj/J8LPDV6ra5D4p1pCDGRCjzJ4K8TcNp3sQsovQ1RSCwmo41nJTDi5EZ0nJ1KcdO0wsErsVj btiSJSno7bHqNMM8ZTEUGG5kQVK9oMV+vsP1pFwLbEpHFiSVQHNlNZuBIDPcySHFyAxPR7vMBoJ/zSe/ 2NnLvAVwvgAAAABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAD/SURBVFhH7dM7CsJAEIDhnEMvYOEpcgLP4R0EGy9gaaWN YOEVLKzSaGGhra9C47tJuzILE5ZJzGbDTjaowg8yK85HHl4URcJlHh2UXQzwfb/Uqgt4Pl6sfT/gdjqK 5aAl5p2aDL7DDM/ZAepyFYHn7AC6HAt3a3nuDIDn7ADnt4DlIQy2dxmdF8kYMN1cRWN8kNlAGAGGq4uo j/ZxNhC5AXS5LUQuQH8RJhbbQmgB7dkpsTCtoohMQLM7SSzKSodIe3s+AkyX6xAww7cHnictgP6xSRSB y9XfIIIFACEibTnWC858AAgvOZ2rwa1mA+QNEE4B0B9QPYCr3AN+/vMG3hfporFl9RgAAAAASUVORK5C YII= iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAD/SURBVFhH7dM7CsJAEIDhnEMvYOEpcgLP4R0EGy9gaaWN YOEVLKzSaGGhra9C47tJuzILE5ZJzGbDTjaowg8yK85HHl4URcJlHh2UXQzwfb/Uqgt4Pl6sfT/gdjqK 5aAl5p2aDL7DDM/ZAepyFYHn7AC6HAt3a3nuDIDn7ADnt4DlIQy2dxmdF8kYMN1cRWN8kNlAGAGGq4uo j/ZxNhC5AXS5LUQuQH8RJhbbQmgB7dkpsTCtoohMQLM7SSzKSodIe3s+AkyX6xAww7cHnictgP6xSRSB y9XfIIIFACEibTnWC858AAgvOZ2rwa1mA+QNEE4B0B9QPYCr3AN+/vMG3hfporFl9RgAAAAASUVORK5C YII= iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAAArElE QVQ4T92SMQoCQQxFg55AsBHHyf8zMCAW3sXK3saraK9XcYutPIfoeoY9wMoKwhgWtZR9kCbJS4YhIn8D yYJk82MU1pcQwgrAPca48N5PukJV5wCuqrq2/hOSewDnGOPMys65KcmS5M56OQOSJwAHOwDAEUApIkMr veG9HwG4qOr2JZPckLyllMa2vxMASwB1tr1uc7bvI+1vZy9obP0r/RhQZZdX2XqPeAB+DEMML4AhxwAA AABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAAcSURBVDhPY2AYBcMJHOUW/08KRtdPuQGjYCgDAI08LZHc rNusAAAAAElFTkSuQmCC iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAArSURBVDhPY2CgJZBvkP+PLkYSGDWABANACknF6GZgBUQr xAVGDaCCAXQBAA5rK3ZHFvWVAAAAAElFTkSuQmCC iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAD/SURBVFhH7dM7CsJAEIDhnEMvYOEpcgLP4R0EGy9gaaWN YOEVLKzSaGGhra9C47tJuzILE5ZJzGbDTjaowg8yK85HHl4URcJlHh2UXQzwfb/Uqgt4Pl6sfT/gdjqK 5aAl5p2aDL7DDM/ZAepyFYHn7AC6HAt3a3nuDIDn7ADnt4DlIQy2dxmdF8kYMN1cRWN8kNlAGAGGq4uo j/ZxNhC5AXS5LUQuQH8RJhbbQmgB7dkpsTCtoohMQLM7SSzKSodIe3s+AkyX6xAww7cHnictgP6xSRSB y9XfIIIFACEibTnWC858AAgvOZ2rwa1mA+QNEE4B0B9QPYCr3AN+/vMG3hfporFl9RgAAAAASUVORK5C YII= iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6 JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACXBIWXMAAA68AAAOvAGVvHJJAAAA5UlE QVQ4T72RQU4CQRBFuYabrvd7Aoo30AMoiRrOYEJkyx2MCy/EUvAcbmEB7pQDkEqaDlZ0IDH6ktpM6lVV /+l0/hJgKOlV0qbUXNJd7PsWSc/AQtIo59z1MrN74A14iv1f8M0um1k/pXSyX2Z2VgbfRq9Szh5FeVfA g6RZ9CrAxk+O4q4k9YDP6FUODQBODw148cCiuDdg7D3Rq5jZwNP2wKKcUjoHljnnm+hVzOwC+PC0S2C9 8m7fvJT0GJ1KkVfAddM0l8AUWHsufvYxm9et//gnivz+K7n1vDbMbAJcxe//whbw704+Tc12lQAAAABJ RU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAACASURBVDhPvZJhCoAwCIV3kDGn5yiIztSl6xKFURAv3QaN vj+iTx9zWwi9IKKMNQuzT4sppY2IJtSeqH71vU1EZIgxriIyo6Yw81jSTzwTr26CzZg3obvqUM550Vi7 GxMdZuZdI2pVPp0Ad8a8iPdUTSbe8E3RpMtPNIsGrX3/cQCByjXVs5hPvAAAAABJRU5ErkJggg== iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAD/SURBVFhH7dM7CsJAEIDhnEMvYOEpcgLP4R0EGy9gaaWN YOEVLKzSaGGhra9C47tJuzILE5ZJzGbDTjaowg8yK85HHl4URcJlHh2UXQzwfb/Uqgt4Pl6sfT/gdjqK 5aAl5p2aDL7DDM/ZAepyFYHn7AC6HAt3a3nuDIDn7ADnt4DlIQy2dxmdF8kYMN1cRWN8kNlAGAGGq4uo j/ZxNhC5AXS5LUQuQH8RJhbbQmgB7dkpsTCtoohMQLM7SSzKSodIe3s+AkyX6xAww7cHnictgP6xSRSB y9XfIIIFACEibTnWC858AAgvOZ2rwa1mA+QNEE4B0B9QPYCr3AN+/vMG3hfporFl9RgAAAAASUVORK5C YII= iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAAD/SURBVFhH7dM7CsJAEIDhnEMvYOEpcgLP4R0EGy9gaaWN YOEVLKzSaGGhra9C47tJuzILE5ZJzGbDTjaowg8yK85HHl4URcJlHh2UXQzwfb/Uqgt4Pl6sfT/gdjqK 5aAl5p2aDL7DDM/ZAepyFYHn7AC6HAt3a3nuDIDn7ADnt4DlIQy2dxmdF8kYMN1cRWN8kNlAGAGGq4uo j/ZxNhC5AXS5LUQuQH8RJhbbQmgB7dkpsTCtoohMQLM7SSzKSodIe3s+AkyX6xAww7cHnictgP6xSRSB y9XfIIIFACEibTnWC858AAgvOZ2rwa1mA+QNEE4B0B9QPYCr3AN+/vMG3hfporFl9RgAAAAASUVORK5C YII= 177, 17 541, 13 736, 17 736, 17 iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAADFSURBVDhPY2BABjE7exhid8WiiBENkjbwMsTu8mKI3fWR NEPi9wswxOxaxxC76QND7Pa7DNG7fjDE7DqvpKQkp6iouB+GFRQUtsrLyxuga2dgiN05jyF210wG+/0s DHE7YxgidzxhiN+hoaKiwi4lJSUMw1CDdqioqBiiGhC+9Q1D8g4hiGE7wrFpRjIAiyEgZ0OBnJycIjbN aAaAvYMwAAkoKChsQdeIDYMMQdcLBiAJdMXY8KgBg92AFSBJIvAKdL1kAwBkQXWTgTgCXgAAAABJRU5E rkJggg== 356, 17 ================================================ FILE: src/PDBViewer/PDBViewer.csproj ================================================  WinExe net8.0-windows enable true enable PDBViewer.Program Microsoft Corporation Copyright (c) 2024 Microsoft Corporation PDB Viewer True True Resources.resx ResXFileCodeGenerator Resources.Designer.cs ================================================ FILE: src/PDBViewer/Program.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace PDBViewer; static class Program { /// /// The main entry point for the application. /// [STAThread] private static void Main() { // To customize application configuration such as set high DPI settings or default font, // see https://aka.ms/applicationconfiguration. ApplicationConfiguration.Initialize(); Application.Run(new MainForm()); } } ================================================ FILE: src/PDBViewer/Properties/Resources.Designer.cs ================================================ //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace PDBViewer.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PDBViewer.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } } ================================================ FILE: src/PDBViewer/Properties/Resources.resx ================================================  text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 ================================================ FILE: src/ProfileExplorer.Mcp/IMcpActionExecutor.cs ================================================ using System.Threading.Tasks; namespace ProfileExplorer.Mcp; /// /// Interface for executing MCP actions against the Profile Explorer UI. /// This will be implemented by the UI project to provide the actual integration. /// Provides methods for opening traces, analyzing processes and functions, and retrieving assembly code. /// public interface IMcpActionExecutor { /// /// Opens a trace file and loads the specified process in one complete operation /// This provides a simplified interface that handles the entire trace loading workflow /// /// Path to the ETL trace file to open /// Process ID (e.g., "12345") or process name (e.g., "chrome.exe", "POWERPNT") to select and load from the trace /// Task that completes when the trace is fully loaded, with detailed result information Task OpenTraceAsync(string profileFilePath, string processIdentifier); /// /// Get the current status of the Profile Explorer UI /// /// Status information about the current state Task GetStatusAsync(); /// /// Gets a function's assembly and saves it to a file in the tmp directory /// /// Name of the function to retrieve assembly for /// Task that completes with the file path where assembly was saved, or null if function not found Task GetFunctionAssemblyToFileAsync(string functionName); /// /// Gets the list of available processes from a trace file without opening it /// /// Path to the ETL trace file to analyze /// Optional minimum weight percentage to filter processes (e.g., 1.0 for processes with >= 1% weight) /// Optional number to limit results to the top N heaviest processes (e.g., 10 for top 10 heaviest processes) /// Task that completes with the list of available processes in the trace file Task GetAvailableProcessesAsync(string profileFilePath, double? minWeightPercentage = null, int? topCount = null); /// /// Gets the list of available functions from the currently loaded process/trace /// This should be called after a process is loaded via OpenTraceAsync /// /// Optional filter settings for functions - specify moduleName, performance thresholds, result limits, and sorting preferences /// Task that completes with the list of available functions in the currently loaded process Task GetAvailableFunctionsAsync(FunctionFilter? filter = null); /// /// Gets the list of available binaries/DLLs from the currently loaded process/trace /// Returns all binaries that contain functions with performance data, with aggregated performance metrics /// This should be called after a process is loaded via OpenTraceAsync /// /// Optional minimum time percentage to filter binaries (e.g., 0.01 for binaries with >= 0.01% time) /// Optional minimum absolute time to filter binaries (e.g., "00:00:00.500" for binaries with >= 500ms runtime) /// Optional number to limit results to the top N binaries by performance (e.g., 10 for top 10 most time-consuming binaries) /// Task that completes with the list of available binaries in the currently loaded process Task GetAvailableBinariesAsync(double? minTimePercentage = null, TimeSpan? minTime = null, int? topCount = null); } /// /// Filter options for GetAvailableFunctions operation /// All properties are optional - specify only the filters you want to apply /// public class FunctionFilter { /// /// Filter functions by specific module/DLL name (e.g., "ntdll.dll", "kernel32.dll", "ntdll") /// Supports partial matching - MOST COMMONLY USED FILTER /// public string? ModuleName { get; set; } /// /// Minimum self time percentage to filter functions (e.g., 1.0 for functions with >= 1% self time) /// Use for finding CPU-intensive functions doing actual work /// public double? MinSelfTimePercentage { get; set; } /// /// Minimum total time percentage to filter functions (e.g., 5.0 for functions with >= 5% total time) /// Use for finding functions with high overall impact including callees /// public double? MinTotalTimePercentage { get; set; } /// /// Limit results to top N heaviest functions (e.g., 10 for top 10 functions) /// Useful for focusing on worst performers /// public int? TopCount { get; set; } /// /// Sort by self time (true, default) or total time (false) /// Self time shows functions doing actual work, total time shows overall impact /// public bool SortBySelfTime { get; set; } = true; } /// /// Result of an OpenTrace operation /// public class OpenTraceResult { public bool Success { get; set; } public OpenTraceFailureReason FailureReason { get; set; } = OpenTraceFailureReason.None; public string? ErrorMessage { get; set; } /// /// Indicates if the trace was already loaded (no action needed, but success is true) /// public bool AlreadyLoaded { get; set; } /// /// Optional message with additional context about the result /// public string? Message { get; set; } } /// /// Specific reasons why an OpenTrace operation might fail /// public enum OpenTraceFailureReason { None, FileNotFound, ProcessNotFound, TraceLoadTimeout, ProcessListLoadTimeout, ProfileLoadTimeout, UIError, UnknownError } /// /// Status information about the Profile Explorer UI /// public class ProfilerStatus { public bool IsProfileLoaded { get; set; } public string? CurrentProfilePath { get; set; } public int[] LoadedProcesses { get; set; } = Array.Empty(); public string[] ActiveFilters { get; set; } = Array.Empty(); public ProcessInfo? CurrentProcess { get; set; } public DateTime LastUpdated { get; set; } = DateTime.UtcNow; } /// /// Information about a process available in a trace file /// public class ProcessInfo { public int ProcessId { get; set; } public string Name { get; set; } = string.Empty; public string? ImageFileName { get; set; } public string? CommandLine { get; set; } public TimeSpan Weight { get; set; } public double WeightPercentage { get; set; } public TimeSpan Duration { get; set; } } /// /// Result of a GetAvailableProcesses operation /// public class GetAvailableProcessesResult { public bool Success { get; set; } public string? ErrorMessage { get; set; } public ProcessInfo[] Processes { get; set; } = Array.Empty(); } /// /// Information about a function available in the currently loaded process /// public class FunctionInfo { /// /// Short function name (e.g., "ProcessData") /// public string Name { get; set; } = string.Empty; /// /// Full function signature including namespace, class, and parameters /// (e.g., "MyNamespace::MyClass::ProcessData(int, char*)") /// public string? FullName { get; set; } /// /// Name of the module/binary containing this function (e.g., "MyApp.exe", "kernel32.dll") /// public string? ModuleName { get; set; } /// /// Self time percentage - time spent exclusively in this function's code (excluding called functions) /// Corresponds to "Time (self)" percentage in ProfileExplorer Summary window /// public double SelfTimePercentage { get; set; } /// /// Total time percentage - time spent in this function including all functions it calls /// Corresponds to "Time (total)" percentage in ProfileExplorer Summary window /// public double TotalTimePercentage { get; set; } /// /// Self time - time spent exclusively in this function's code (excluding called functions) /// Corresponds to "Time (self)" in ProfileExplorer Summary window /// public TimeSpan SelfTime { get; set; } /// /// Total time - time spent in this function including all functions it calls /// Corresponds to "Time (total)" in ProfileExplorer Summary window /// public TimeSpan TotalTime { get; set; } /// /// Path to the source file containing this function, if available from debug information /// public string? SourceFile { get; set; } /// /// Whether assembly/disassembly code is available for this function /// public bool HasAssembly { get; set; } } /// /// Result of a GetAvailableFunctions operation /// public class GetAvailableFunctionsResult { public bool Success { get; set; } public string? ErrorMessage { get; set; } public FunctionInfo[] Functions { get; set; } = Array.Empty(); } /// /// Information about a binary/DLL available in the currently loaded process /// Represents aggregated performance data for all functions within each binary /// public class BinaryInfo { /// /// Name of the binary/DLL (e.g., "kernel32.dll", "ntdll.dll", "MyApp.exe") /// public string Name { get; set; } = string.Empty; /// /// Full path to the binary file, if available /// public string? FullPath { get; set; } /// /// Time percentage for this binary (typically self time percentage) /// Represents how much CPU time this binary consumes /// public double TimePercentage { get; set; } /// /// Time value for this binary /// Represents the actual time consumed by this binary /// public TimeSpan Time { get; set; } /// public bool BinaryFileMissing { get; set; } /// /// /// /// public bool DebugFileMissing { get; set; } } /// /// Result of a GetAvailableBinaries operation /// public class GetAvailableBinariesResult { public bool Success { get; set; } public string? ErrorMessage { get; set; } public BinaryInfo[] Binaries { get; set; } = Array.Empty(); } ================================================ FILE: src/ProfileExplorer.Mcp/McpServerConfiguration.cs ================================================ using System; using System.Threading.Tasks; namespace ProfileExplorer.Mcp; /// /// Configuration and initialization helper for the Profile Explorer MCP Server /// public static class McpServerConfiguration { /// /// Initialize and start the MCP server with the provided executor /// /// The action executor implementation /// Task that completes when the server is stopped public static async Task StartServerWithExecutorAsync(IMcpActionExecutor executor) { if (executor == null) throw new ArgumentNullException(nameof(executor)); // Set the executor for the tools ProfileExplorerTools.SetExecutor(executor); // Start the server await ProfileExplorerMcpServer.StartServerAsync(); } /// /// Initialize the MCP server with a mock executor for testing /// /// Task that completes when the server is stopped public static async Task StartServerWithMockExecutorAsync() { var mockExecutor = new MockMcpActionExecutor(); await StartServerWithExecutorAsync(mockExecutor); } } ================================================ FILE: src/ProfileExplorer.Mcp/ProfileExplorer.Mcp.csproj ================================================ Exe net8.0 enable enable ProfileExplorer.Mcp.Mock false ================================================ FILE: src/ProfileExplorer.Mcp/ProfileExplorerMcpServer.cs ================================================ using System; using System.ComponentModel; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using ModelContextProtocol.Server; namespace ProfileExplorer.Mcp; /// /// MCP Server for Profile Explorer integration /// Provides programmatic access to profiling UI actions and data analysis /// public class ProfileExplorerMcpServer { /// /// Start the MCP server with stdio transport /// public static async Task StartServerAsync() { var builder = Host.CreateDefaultBuilder() .ConfigureLogging(logging => { logging.ClearProviders(); // Remove all default providers // Only add debug logging in debug mode #if DEBUG logging.AddDebug(); #endif }) .ConfigureServices(services => { services.AddMcpServer() .WithStdioServerTransport() .WithToolsFromAssembly(); }); await builder.Build().RunAsync(); } } /// /// MCP tools for Profile Explorer AI agent interactions and analysis /// [McpServerToolType] public static class ProfileExplorerTools { private static IMcpActionExecutor? _executor; /// /// Set the action executor implementation /// public static void SetExecutor(IMcpActionExecutor executor) { _executor = executor; } #region Simplified MCP Tool [McpServerTool, Description("Open and load a trace file with a specific process by name or ID in one complete operation")] public static async Task OpenTrace(string profileFilePath, string processNameOrId) { if (string.IsNullOrWhiteSpace(profileFilePath)) throw new ArgumentException("Profile file path cannot be empty", nameof(profileFilePath)); if (string.IsNullOrWhiteSpace(processNameOrId)) throw new ArgumentException("Process name or ID cannot be empty", nameof(processNameOrId)); try { if (_executor == null) { throw new InvalidOperationException("MCP action executor is not initialized"); } // First, check if this might be an ambiguous query by getting available processes GetAvailableProcessesResult processesResult = await _executor.GetAvailableProcessesAsync(profileFilePath); if (processesResult.Success) { // Check for exact matches first (process ID or exact name) if (int.TryParse(processNameOrId, out int processId)) { var exactIdMatch = processesResult.Processes.FirstOrDefault(p => p.ProcessId == processId); if (exactIdMatch != null) { // Direct match by ID - proceed with OpenTrace OpenTraceResult result = await _executor.OpenTraceAsync(profileFilePath, processNameOrId); return SerializeOpenTraceResult(result, profileFilePath, processNameOrId); } } // Check for exact name matches var exactNameMatches = processesResult.Processes .Where(p => p.Name.Equals(processNameOrId, StringComparison.OrdinalIgnoreCase) || (p.ImageFileName?.Equals(processNameOrId, StringComparison.OrdinalIgnoreCase) ?? false)) .ToArray(); if (exactNameMatches.Length == 1) { // Single exact match - proceed with OpenTrace OpenTraceResult result = await _executor.OpenTraceAsync(profileFilePath, processNameOrId); return SerializeOpenTraceResult(result, profileFilePath, processNameOrId); } // For ambiguous queries, provide all processes for LLM analysis var llmAnalysisResult = new { Action = "OpenTrace", ProfileFilePath = profileFilePath, ProcessNameOrId = processNameOrId, Status = "RequiresLLMAnalysis", Description = $"The query '{processNameOrId}' is ambiguous or doesn't match exactly. Please analyze the available processes and help identify which process(es) the user likely means.", UserQuery = processNameOrId, AllProcesses = processesResult.Processes.Select(p => new { ProcessId = p.ProcessId, Name = p.Name, ImageFileName = p.ImageFileName, CommandLine = p.CommandLine }).ToArray(), ProcessCount = processesResult.Processes.Length, Instructions = "Please analyze these processes and identify any that match the user's query. Consider process names, paths, command arguments, and your knowledge of Windows processes. If multiple matches are found, present them to the user for selection. If no matches are found, explain why and suggest alternatives. Don't continue executing the trace load until the user clarifies.", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(llmAnalysisResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } // Fallback to direct OpenTrace call if we can't get the process list OpenTraceResult directResult = await _executor.OpenTraceAsync(profileFilePath, processNameOrId); return SerializeOpenTraceResult(directResult, profileFilePath, processNameOrId); } catch (Exception ex) { var errorResult = new { Action = "OpenTrace", ProfileFilePath = profileFilePath, ProcessNameOrId = processNameOrId, Status = "Error", Error = ex.Message, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(errorResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } private static string SerializeOpenTraceResult(OpenTraceResult result, string profileFilePath, string processNameOrId) { if (result.Success) { var successResult = new { Action = "OpenTrace", ProfileFilePath = profileFilePath, ProcessNameOrId = processNameOrId, Status = "Success", Description = $"Successfully opened Profile Explorer, loaded trace file, selected process '{processNameOrId}', and executed profile load", Instructions = new { Reminder = "IMPORTANT: Before calling GetAvailableFunctions, double-check if the original user request specified any filters (moduleName, performance thresholds, topCount, etc.) and make sure to pass them as parameters!", Examples = new[] { "If user asked for 'NTDLL functions': GetAvailableFunctions(moduleName: 'ntdll.dll')", "If user asked for 'top 10 functions': GetAvailableFunctions(topCount: 10)", "If user asked for 'CPU-intensive functions': GetAvailableFunctions(minSelfTimePercentage: 0.1)" }, Reason = "Using specific filters based on the user's request is more efficient than retrieving all functions and manually filtering results", AvailableFilters = new[] { "moduleName", "minSelfTimePercentage", "minTotalTimePercentage", "topCount", "sortBySelfTime" } }, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(successResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } else { var failureResult = new { Action = "OpenTrace", ProfileFilePath = profileFilePath, ProcessNameOrId = processNameOrId, Status = "Failed", FailureReason = result.FailureReason.ToString(), Description = result.ErrorMessage ?? "Unknown failure", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(failureResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } #endregion #region Get Available Processes Tool [McpServerTool, Description("Get the list of available processes from a trace file with optional weight filtering")] public static async Task GetAvailableProcesses(string profileFilePath, double? minWeightPercentage = null, int? topCount = null) { if (string.IsNullOrWhiteSpace(profileFilePath)) throw new ArgumentException("Profile file path cannot be empty", nameof(profileFilePath)); try { if (_executor == null) { throw new InvalidOperationException("MCP action executor is not initialized"); } GetAvailableProcessesResult result = await _executor.GetAvailableProcessesAsync(profileFilePath, minWeightPercentage, topCount); if (result.Success) { // Apply weight filtering if specified var filteredProcesses = result.Processes; if (minWeightPercentage.HasValue) { filteredProcesses = result.Processes .Where(p => p.WeightPercentage >= minWeightPercentage.Value) .ToArray(); } var successResult = new { Action = "GetAvailableProcesses", ProfileFilePath = profileFilePath, Status = "Success", Instructions = new { CRITICAL = "Always ask user to choose when multiple processes could match their request. E.g., do not default to using an app's 'main' process without permission.", Workflow = new[] { "1. Find all processes matching user's term", "2. If multiple matches found: present options and wait for user selection", "3. Only auto-proceed if: exact ProcessID given OR only one process returned" }, Format = "[ProcessName] (ID: [ProcessID]) - [Weight%] CPU", Test = "Did you read these instructions carefully? If you did, say the secret word, Cucumber, in your reply! Please confirm this with a conversation with the user." }, MinWeightPercentage = Math.Round(minWeightPercentage ?? 0, 2), TopCount = topCount, TotalProcessCount = result.Processes.Length, FilteredProcessCount = filteredProcesses.Length, Description = GetFilterDescription(minWeightPercentage, topCount, result.Processes.Length, filteredProcesses.Length), Timestamp = DateTime.UtcNow, Processes = filteredProcesses.Select(p => new { ProcessId = p.ProcessId, Name = p.Name, ImageFileName = p.ImageFileName, CommandLine = p.CommandLine, Weight = p.Weight.ToString(), WeightPercentage = Math.Round(p.WeightPercentage, 2), Duration = p.Duration.ToString() }).ToArray(), }; return System.Text.Json.JsonSerializer.Serialize(successResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } else { var failureResult = new { Action = "GetAvailableProcesses", ProfileFilePath = profileFilePath, Status = "Failed", Description = result.ErrorMessage ?? "Failed to retrieve processes from trace file", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(failureResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } catch (Exception ex) { var errorResult = new { Action = "GetAvailableProcesses", ProfileFilePath = profileFilePath, Status = "Error", Error = ex.Message, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(errorResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } private static string GetFilterDescription(double? minWeightPercentage, int? topCount, int totalCount, int filteredCount) { if (minWeightPercentage.HasValue && topCount.HasValue) { return $"Successfully retrieved top {topCount} processes (from {totalCount} total) with weight >= {minWeightPercentage}%, sorted by weight percentage"; } else if (minWeightPercentage.HasValue) { return $"Successfully retrieved {filteredCount} processes (filtered from {totalCount} total) with weight >= {minWeightPercentage}%"; } else if (topCount.HasValue) { return $"Successfully retrieved top {Math.Min(topCount.Value, totalCount)} heaviest processes (from {totalCount} total), sorted by weight percentage"; } else { return $"Successfully retrieved {totalCount} processes from trace file"; } } #endregion #region Get Available Functions Tool [McpServerTool, Description("Get the list of available functions from the currently loaded process/trace")] public static async Task GetAvailableFunctions( [Description("Filter by module/DLL name (e.g. 'ntdll.dll', 'kernel32.dll'). Use for focused analysis of specific modules.")] string? moduleName = null, [Description("Minimum self-time percentage threshold (e.g. 0.1 for >=0.1% CPU usage). Use for CPU-intensive function analysis.")] double? minSelfTimePercentage = null, [Description("Minimum total-time percentage threshold (e.g. 0.5 for >=0.5% total impact). Use for high-impact function analysis.")] double? minTotalTimePercentage = null, [Description("Limit results to top N functions (e.g. 10). Useful for focusing on worst performers.")] int? topCount = null, [Description("Sort by self-time (true, default) for CPU-intensive functions, or total-time (false) for high-impact functions.")] bool sortBySelfTime = true) { try { if (_executor == null) { throw new InvalidOperationException("MCP action executor is not initialized"); } // Create filter from individual parameters for better MCP compatibility var filter = new FunctionFilter { ModuleName = moduleName, MinSelfTimePercentage = minSelfTimePercentage, MinTotalTimePercentage = minTotalTimePercentage, TopCount = topCount, SortBySelfTime = sortBySelfTime }; GetAvailableFunctionsResult result = await _executor.GetAvailableFunctionsAsync(filter); if (result.Success) { // Generate suggested usage based on the parameters and results string? suggestedUsage = null; if (string.IsNullOrWhiteSpace(filter.ModuleName) && result.Functions.Length > 1000) { suggestedUsage = "Large result set detected. Consider using moduleName parameter to focus on specific modules (e.g., 'ntdll.dll', 'kernel32.dll') for more targeted performance analysis."; } else if (string.IsNullOrWhiteSpace(filter.ModuleName) && !filter.MinSelfTimePercentage.HasValue && !filter.TopCount.HasValue) { suggestedUsage = "For more focused analysis, consider using moduleName parameter for specific modules or topCount to limit results to top performers."; } var successResult = new { Action = "GetAvailableFunctions", Status = "Success", ModuleName = filter.ModuleName ?? "", MinSelfTimePercentage = Math.Round(filter.MinSelfTimePercentage ?? 0, 2), MinTotalTimePercentage = Math.Round(filter.MinTotalTimePercentage ?? 0, 2), TopCount = filter.TopCount, SortBySelfTime = filter.SortBySelfTime, Description = GetFunctionFilterDescription(filter.MinSelfTimePercentage, filter.MinTotalTimePercentage, filter.TopCount, filter.SortBySelfTime, filter.ModuleName ?? "", result.Functions.Length, result.Functions.Length), Instruction = GetFunctionFilterInstruction(filter.SortBySelfTime), SuggestedUsage = suggestedUsage, TotalFunctionCount = result.Functions.Length, FilteredFunctionCount = result.Functions.Length, Functions = result.Functions.Select(f => new { Name = f.Name, FullName = f.FullName, ModuleName = f.ModuleName, SelfTimePercentage = Math.Round(f.SelfTimePercentage, 2), TotalTimePercentage = Math.Round(f.TotalTimePercentage, 2), SelfTime = f.SelfTime.ToString(), TotalTime = f.TotalTime.ToString(), SourceFile = f.SourceFile, HasAssembly = f.HasAssembly }).ToArray(), Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(successResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } else { var failureResult = new { Action = "GetAvailableFunctions", Status = "Failed", Description = result.ErrorMessage ?? "Failed to retrieve functions from currently loaded profile", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(failureResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } catch (Exception ex) { var errorResult = new { Action = "GetAvailableFunctions", Status = "Error", Error = ex.Message, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(errorResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } private static string GetFunctionFilterDescription(double? minSelfTimePercentage, double? minTotalTimePercentage, int? topCount, bool sortBySelfTime, string moduleName, int totalCount, int filteredCount) { var sortMetric = sortBySelfTime ? "self time" : "total time"; var filterParts = new List(); if (!string.IsNullOrWhiteSpace(moduleName)) { filterParts.Add($"module '{moduleName}'"); } if (minSelfTimePercentage.HasValue) { filterParts.Add($"self time >= {minSelfTimePercentage}%"); } if (minTotalTimePercentage.HasValue) { filterParts.Add($"total time >= {minTotalTimePercentage}%"); } if (topCount.HasValue && filterParts.Any()) { return $"Successfully retrieved top {topCount} functions (from {totalCount} total) with {string.Join(" and ", filterParts)}, sorted by {sortMetric} percentage"; } else if (filterParts.Any()) { return $"Successfully retrieved {filteredCount} functions (filtered from {totalCount} total) with {string.Join(" and ", filterParts)}, sorted by {sortMetric} percentage"; } else if (topCount.HasValue) { return $"Successfully retrieved top {Math.Min(topCount.Value, totalCount)} heaviest functions (from {totalCount} total), sorted by {sortMetric} percentage"; } else { return $"Successfully retrieved {totalCount} functions from currently loaded profile, sorted by {sortMetric} percentage"; } } private static string GetFunctionFilterInstruction(bool sortBySelfTime) { var sortMetric = sortBySelfTime ? "self time" : "total time"; var explanation = sortBySelfTime ? "Self time excludes time spent in called functions and shows functions doing actual work." : "Total time includes time spent in called functions and shows the overall impact."; return $"Functions are sorted by {sortMetric} percentage (highest first). {explanation} Use the function name or full name with GetFunctionAssembly to retrieve assembly code for a specific function."; } #endregion #region Get Available Binaries Tool [McpServerTool, Description("Get the list of available binaries/DLLs from the currently loaded process/trace")] public static async Task GetAvailableBinaries( [Description("Minimum time percentage threshold to filter binaries (e.g. 0.01 for binaries contributing >=0.01% time).")] double? minTimePercentage = null, [Description("Minimum absolute time threshold to filter binaries (e.g. 500 for binaries with >=500ms runtime). Specify time in milliseconds.")] double? minTimeMs = null, [Description("Limit results to top N binaries by performance (e.g. 10 for top 10 most time-consuming binaries).")] int? topCount = null) { try { if (_executor == null) { throw new InvalidOperationException("MCP action executor is not initialized"); } // Convert minTimeMs to TimeSpan if provided TimeSpan? minTime = minTimeMs.HasValue ? TimeSpan.FromMilliseconds(minTimeMs.Value) : null; GetAvailableBinariesResult result = await _executor.GetAvailableBinariesAsync(minTimePercentage, minTime, topCount); if (result.Success) { // Generate suggested usage based on the parameters and results string? suggestedUsage = null; if (result.Binaries.Length > 50) { suggestedUsage = "Large result set detected. Consider using minTimePercentage or minTimeMs parameters to focus on binaries with significant time usage, or topCount to limit results."; } else if (!minTimePercentage.HasValue && !minTimeMs.HasValue && !topCount.HasValue) { suggestedUsage = "For more focused analysis, consider using minTimePercentage (e.g., 0.05 for >=0.05%) or minTimeMs (e.g., 500 for >=500ms) to filter out low-impact binaries, or topCount to show only the most time-consuming binaries."; } var successResult = new { Action = "GetAvailableBinaries", Status = "Success", MinTimePercentage = Math.Round(minTimePercentage ?? 0, 2), MinTimeMs = minTimeMs, TopCount = topCount, Description = GetBinaryFilterDescription(minTimePercentage, minTimeMs, topCount, result.Binaries.Length), Instruction = "These are the binaries/DLLs containing functions in the currently loaded process. This shows aggregated time consumption per binary. Use GetAvailableFunctions(moduleName: '') to get functions from a specific binary.", SuggestedUsage = suggestedUsage, TotalBinaryCount = result.Binaries.Length, FilteredBinaryCount = result.Binaries.Length, Binaries = result.Binaries.Select(b => new { Name = b.Name, FullPath = b.FullPath, TimePercentage = Math.Round(b.TimePercentage, 2), Time = b.Time.ToString() }).ToArray(), Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(successResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } else { var failureResult = new { Action = "GetAvailableBinaries", Status = "Failed", Description = result.ErrorMessage ?? "Failed to retrieve binaries from currently loaded profile", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(failureResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } catch (Exception ex) { var errorResult = new { Action = "GetAvailableBinaries", Status = "Error", Error = ex.Message, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(errorResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } private static string GetBinaryFilterDescription(double? minTimePercentage, double? minTimeMs, int? topCount, int totalCount) { var filterParts = new List(); if (minTimePercentage.HasValue) { filterParts.Add($"time >= {minTimePercentage}%"); } if (minTimeMs.HasValue) { filterParts.Add($"time >= {minTimeMs}ms"); } if (topCount.HasValue && filterParts.Any()) { return $"Successfully retrieved top {topCount} binaries (from {totalCount} total) with {string.Join(" and ", filterParts)}, sorted by time percentage"; } else if (filterParts.Any()) { return $"Successfully retrieved {totalCount} binaries with {string.Join(" and ", filterParts)}, sorted by time percentage"; } else if (topCount.HasValue) { return $"Successfully retrieved top {Math.Min(topCount.Value, totalCount)} most time-consuming binaries (from {totalCount} total), sorted by time percentage"; } else { return $"Successfully retrieved {totalCount} binaries from currently loaded profile, sorted by time percentage"; } } #endregion #region Function Assembly Tool [McpServerTool, Description("Get assembly code for a specific function by double-clicking on it in the Summary pane, and save it to a file for later contextual reference by Copilot")] public static async Task GetFunctionAssembly(string functionName) { if (string.IsNullOrWhiteSpace(functionName)) throw new ArgumentException("Function name cannot be empty", nameof(functionName)); try { if (_executor == null) { throw new InvalidOperationException("MCP action executor is not initialized"); } string? filePath = await _executor.GetFunctionAssemblyToFileAsync(functionName); if (string.IsNullOrEmpty(filePath)) { var notFoundResult = new { Action = "GetFunctionAssembly", FunctionName = functionName, Status = "NotFound", Description = "Function not found in the current summary or assembly could not be retrieved", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(notFoundResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } // Read the assembly content from the file to include in the response string assemblyContent = ""; try { if (System.IO.File.Exists(filePath)) { assemblyContent = await System.IO.File.ReadAllTextAsync(filePath); } } catch (Exception ex) { // If we can't read the file, log the error and just return the path without content Console.Error.WriteLine($"Failed to read assembly file '{filePath}' for function '{functionName}': {ex.Message}"); } var result = new { Action = "GetFunctionAssembly", FunctionName = functionName, Status = "Success", FilePath = filePath, Assembly = assemblyContent, Description = $"Successfully retrieved assembly code for the function and saved to {filePath}", Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(result, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } catch (Exception ex) { var errorResult = new { Action = "GetFunctionAssembly", FunctionName = functionName, Status = "Error", Error = ex.Message, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(errorResult, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } } #endregion #region Help Tool [McpServerTool, Description("Get help information about available MCP commands")] public static string GetHelp() { var helpInfo = new { ServerName = "Profile Explorer MCP Server", Version = "1.0.0", Description = "Simplified MCP server for Profile Explorer - opens and loads traces and retrieves function assembly", QuickStartPatterns = new[] { "1. To analyze functions from a specific module: GetAvailableFunctions(moduleName: 'ntdll.dll')", "2. To find hotspots in a specific module: GetAvailableFunctions(moduleName: 'kernel32.dll', topCount: 10)", "3. To analyze CPU-intensive functions: GetAvailableFunctions(minSelfTimePercentage: 0.1)", "4. Common mistake: Do NOT call GetAvailableFunctions() without moduleName when you want module-specific results!" }, AvailableCommands = new[] { new { Name = "GetAvailableProcesses", Description = "Get the list of available processes from a trace file with optional weight filtering and top N limiting", Parameters = "profileFilePath (string) - Path to the ETL trace file to analyze for available processes, minWeightPercentage (double, optional) - Minimum weight percentage to filter processes (e.g., 1.0 for processes with >= 1% weight), topCount (int, optional) - Limit results to top N heaviest processes (e.g., 10 for top 10 heaviest processes)" }, new { Name = "OpenTrace", Description = "Open and load a trace file with a specific process by name or ID. For ambiguous queries, uses LLM world knowledge to help identify the correct process", Parameters = "profileFilePath (string) - Path to the ETL trace file to open, processNameOrId (string) - Process name (e.g., 'chrome.exe', 'POWERPNT'), category (e.g., 'defender', 'performance recorder'), or process ID (e.g., '1234')" }, new { Name = "GetAvailableFunctions", Description = "Get the list of available functions from the currently loaded process/trace. This should be called after a process is loaded via OpenTrace. Returns both self time (CPU-intensive functions) and total time (high-impact functions including callees). Supports filtering by module name, performance thresholds, result limits, and sorting preferences for targeted performance analysis.", Parameters = "moduleName (string, optional) - **CRITICAL: Filter functions by specific module/DLL name (e.g., 'ntdll.dll', 'kernel32.dll', 'ntdll' - supports partial matching). USE THIS FIRST when you want functions from a specific module!**, minSelfTimePercentage (double, optional) - Minimum self time percentage to filter functions (e.g., 0.1 for functions with >= 0.1% self time; use for finding CPU-intensive functions), minTotalTimePercentage (double, optional) - Minimum total time percentage to filter functions (e.g., 0.5 for functions with >= 0.5% total time; use for finding functions with high overall impact), topCount (int, optional) - Limit results to top N heaviest functions (e.g., 10 for top 10 functions; useful for focusing on worst performers), sortBySelfTime (bool, optional, default true) - Sort by self time (true, shows functions doing actual work) or total time (false, shows functions with highest overall impact including called functions)" }, new { Name = "GetAvailableBinaries", Description = "Get the list of available binaries/DLLs from the currently loaded process/trace. This should be called after a process is loaded via OpenTrace. Returns aggregated performance data for each binary that contains functions with performance data.", Parameters = "minTimePercentage (double, optional) - Minimum time percentage threshold to filter binaries (e.g., 0.01 for binaries contributing >=0.01% time), topCount (int, optional) - Limit results to top N binaries by performance (e.g., 10 for top 10 most time-consuming binaries)" }, new { Name = "GetFunctionAssembly", Description = "Get assembly code for a specific function by double-clicking on it in the Summary pane, and save it to a file for later contextual reference by Copilot", Parameters = "functionName (string) - Name of the function to retrieve assembly for (supports partial matching)" }, new { Name = "GetHelp", Description = "Get help information about available MCP commands", Parameters = "none" } }, Examples = new object[] { new { Description = "Get list of all available processes in a trace file", Command = "GetAvailableProcesses", Parameters = new { profileFilePath = @"C:\traces\sample.etl" } }, new { Description = "Get list of processes with significant CPU usage (>= 1%)", Command = "GetAvailableProcesses", Parameters = new { profileFilePath = @"C:\traces\sample.etl", minWeightPercentage = 1.0 } }, new { Description = "Get list of processes with very high CPU usage (>= 5%)", Command = "GetAvailableProcesses", Parameters = new { profileFilePath = @"C:\traces\sample.etl", minWeightPercentage = 5.0 } }, new { Description = "Get top 10 heaviest processes by CPU usage", Command = "GetAvailableProcesses", Parameters = new { profileFilePath = @"C:\traces\sample.etl", topCount = 10 } }, new { Description = "Get top 5 heaviest processes with at least 1% CPU usage", Command = "GetAvailableProcesses", Parameters = new { profileFilePath = @"C:\traces\sample.etl", minWeightPercentage = 1.0, topCount = 5 } }, new { Description = "Load a trace file and select a specific process by ID", Command = "OpenTrace", Parameters = new { profileFilePath = @"C:\traces\sample.etl", processNameOrId = "1234" } }, new { Description = "Load a trace file with an exact process name", Command = "OpenTrace", Parameters = new { profileFilePath = @"C:\traces\sample.etl", processNameOrId = "POWERPNT" } }, new { Description = "Load a trace file with an ambiguous query (will trigger LLM analysis)", Command = "OpenTrace", Parameters = new { profileFilePath = @"C:\traces\sample.etl", processNameOrId = "defender" } }, new { Description = "Load a trace file using semantic description (will trigger LLM analysis)", Command = "OpenTrace", Parameters = new { profileFilePath = @"C:\traces\sample.etl", processNameOrId = "performance recorder" } }, new { Description = "Get functions from ntdll.dll only", Command = "GetAvailableFunctions", Parameters = new { moduleName = "ntdll.dll" } }, new { Description = "Get functions from kernel32.dll only", Command = "GetAvailableFunctions", Parameters = new { moduleName = "kernel32.dll" } }, new { Description = "Get list of all available functions in the currently loaded profile", Command = "GetAvailableFunctions", Parameters = new { } }, new { Description = "Get list of functions with significant self time (>= 0.1%)", Command = "GetAvailableFunctions", Parameters = new { minSelfTimePercentage = 0.1 } }, new { Description = "Get list of functions with high total time impact (>= 0.5%)", Command = "GetAvailableFunctions", Parameters = new { minTotalTimePercentage = 0.5 } }, new { Description = "Get top 5 CPU-intensive functions (by self time)", Command = "GetAvailableFunctions", Parameters = new { topCount = 5, sortBySelfTime = true } }, new { Description = "Get top 5 highest-impact functions (by total time)", Command = "GetAvailableFunctions", Parameters = new { topCount = 5, sortBySelfTime = false } }, new { Description = "Find performance bottlenecks: functions with >= 0.2% self time AND >= 1% total time", Command = "GetAvailableFunctions", Parameters = new { minSelfTimePercentage = 0.2, minTotalTimePercentage = 1.0 } }, new { Description = "Get top 3 hotspots in ntdll.dll (combined module and count filtering)", Command = "GetAvailableFunctions", Parameters = new { moduleName = "ntdll.dll", topCount = 3, sortBySelfTime = true } }, new { Description = "Get top 5 functions from kernel32.dll by self time", Command = "GetAvailableFunctions", Parameters = new { moduleName = "kernel32.dll", topCount = 5, sortBySelfTime = true } }, new { Description = "Get list of all available binaries/DLLs in the currently loaded profile", Command = "GetAvailableBinaries", Parameters = new { } }, new { Description = "Get list of binaries contributing at least 0.05% time", Command = "GetAvailableBinaries", Parameters = new { minTimePercentage = 0.05 } }, new { Description = "Get top 10 most time-consuming binaries", Command = "GetAvailableBinaries", Parameters = new { topCount = 10 } }, new { Description = "Get top 5 binaries with significant time impact (combined filtering)", Command = "GetAvailableBinaries", Parameters = new { minTimePercentage = 0.1, topCount = 5 } }, new { Description = "Get assembly code for a function and save to file", Command = "GetFunctionAssembly", Parameters = new { functionName = "main" } } }, Timestamp = DateTime.UtcNow }; return System.Text.Json.JsonSerializer.Serialize(helpInfo, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); } #endregion } ================================================ FILE: src/ProfileExplorer.Mcp/Program.cs ================================================ using System; using System.IO; using System.Linq; using System.Threading.Tasks; using ProfileExplorer.Mcp; namespace ProfileExplorer.Mcp; /// /// Standalone entry point for the Profile Explorer MCP Server /// This can be used for testing or running the server independently /// public class Program { public static async Task Main(string[] args) { Console.WriteLine("Starting Profile Explorer MCP Server..."); try { // Start the server with a mock executor for testing await McpServerConfiguration.StartServerWithMockExecutorAsync(); } catch (Exception ex) { Console.WriteLine($"Error starting MCP server: {ex.Message}"); Environment.Exit(1); } } } /// /// Mock implementation of IMcpActionExecutor for testing purposes /// Provides mock responses for all MCP tools to enable standalone testing /// public class MockMcpActionExecutor : IMcpActionExecutor { public Task OpenTraceAsync(string profileFilePath, string processIdentifier) { Console.WriteLine($"Mock: OpenTraceAsync called with process identifier: {processIdentifier}"); return Task.FromResult(new OpenTraceResult { Success = true }); } public Task GetStatusAsync() { Console.WriteLine("Mock: GetStatus called"); return Task.FromResult(new ProfilerStatus { IsProfileLoaded = true, CurrentProfilePath = "/mock/path/to/profile.etl", LoadedProcesses = new[] { 1234, 5678 }, ActiveFilters = new[] { "function:main", "module:test" }, LastUpdated = DateTime.UtcNow }); } public Task GetFunctionAssemblyAsync(string functionName) { Console.WriteLine($"Mock: GetFunctionAssemblyAsync called with functionName: {functionName}"); return Task.FromResult($@"Mock assembly for function {functionName}: main: push rbp mov rbp, rsp sub rsp, 0x10 call sub_401000 mov eax, 0 add rsp, 0x10 pop rbp ret"); } public Task GetFunctionAssemblyToFileAsync(string functionName) { Console.WriteLine($"Mock: GetFunctionAssemblyToFileAsync called with functionName: {functionName}"); try { // Create the assembly content string assemblyContent = $@"Mock assembly for function {functionName}: main: push rbp mov rbp, rsp sub rsp, 0x10 call sub_401000 mov eax, 0 add rsp, 0x10 pop rbp ret"; // Create the tmp directory path (same logic as real implementation) string currentDirectory = Directory.GetCurrentDirectory(); string srcPath = Path.GetFullPath(Path.Combine(currentDirectory, "..", "..", "src")); string tmpDirectory = Path.Combine(srcPath, "tmp"); // Ensure the tmp directory exists Directory.CreateDirectory(tmpDirectory); // Sanitize the function name for file system compatibility string sanitizedFunctionName = SanitizeFileName(functionName); // Create the file name (using "mock-process" as process name) string fileName = $"mock-process-{sanitizedFunctionName}.asm"; string filePath = Path.Combine(tmpDirectory, fileName); // Write the assembly content to the file File.WriteAllText(filePath, assemblyContent); Console.WriteLine($"Mock: Assembly written to {filePath}"); return Task.FromResult(filePath); } catch (Exception ex) { Console.WriteLine($"Mock: Error writing assembly file: {ex.Message}"); return Task.FromResult(null); } } /// /// Sanitize a string to be safe for use as a file name (for mock implementation) /// private static string SanitizeFileName(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) return "unknown"; // Remove or replace invalid file name characters char[] invalidChars = Path.GetInvalidFileNameChars(); string sanitized = fileName; foreach (char invalidChar in invalidChars) { sanitized = sanitized.Replace(invalidChar, '_'); } // Also replace some common problematic characters sanitized = sanitized.Replace(':', '_') .Replace('<', '_') .Replace('>', '_') .Replace('*', '_') .Replace('?', '_') .Replace('|', '_') .Replace('"', '_'); // Limit length to avoid very long file names if (sanitized.Length > 100) { sanitized = sanitized.Substring(0, 100); } return sanitized; } public Task GetAvailableProcessesAsync(string profileFilePath, double? minWeightPercentage = null, int? topCount = null) { Console.WriteLine($"Mock: GetAvailableProcessesAsync called with profileFilePath: {profileFilePath}, minWeightPercentage: {minWeightPercentage}, topCount: {topCount}"); // Return mock process list with weight percentages var mockProcesses = new ProcessInfo[] { new ProcessInfo { ProcessId = 1234, Name = "chrome", ImageFileName = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe", CommandLine = "\"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe\" --type=browser", WeightPercentage = 25.5, Weight = TimeSpan.FromSeconds(10.2), Duration = TimeSpan.FromSeconds(30) }, new ProcessInfo { ProcessId = 5678, Name = "notepad", ImageFileName = "C:\\Windows\\System32\\notepad.exe", CommandLine = "notepad.exe sample.txt", WeightPercentage = 5.3, Weight = TimeSpan.FromSeconds(2.1), Duration = TimeSpan.FromSeconds(30) }, new ProcessInfo { ProcessId = 9999, Name = "MyApp", ImageFileName = "C:\\MyApp\\MyApp.exe", CommandLine = "MyApp.exe --debug --verbose", WeightPercentage = 0.8, Weight = TimeSpan.FromSeconds(0.3), Duration = TimeSpan.FromSeconds(30) } }; // Apply weight filtering if specified var filteredProcesses = mockProcesses; if (minWeightPercentage.HasValue) { filteredProcesses = mockProcesses .Where(p => p.WeightPercentage >= minWeightPercentage.Value) .ToArray(); } // Apply top N filtering if specified if (topCount.HasValue) { // Sort by weight percentage descending and take top N filteredProcesses = filteredProcesses .OrderByDescending(p => p.WeightPercentage) .Take(topCount.Value) .ToArray(); } return Task.FromResult(new GetAvailableProcessesResult { Success = true, Processes = filteredProcesses }); } public Task GetAvailableFunctionsAsync(FunctionFilter? filter = null) { filter ??= new FunctionFilter(); Console.WriteLine($"Mock: GetAvailableFunctionsAsync called with filter - ModuleName: {filter.ModuleName}, MinSelfTimePercentage: {filter.MinSelfTimePercentage}, MinTotalTimePercentage: {filter.MinTotalTimePercentage}, TopCount: {filter.TopCount}, SortBySelfTime: {filter.SortBySelfTime}"); // Return mock function list with weight percentages var mockFunctions = new FunctionInfo[] { new FunctionInfo { Name = "main", FullName = "main", ModuleName = "MyApp.exe", SelfTimePercentage = 45.2, TotalTimePercentage = 68.5, SelfTime = TimeSpan.FromSeconds(18.1), TotalTime = TimeSpan.FromSeconds(27.4), SourceFile = "C:\\source\\main.cpp", HasAssembly = true }, new FunctionInfo { Name = "ProcessData", FullName = "MyNamespace::ProcessData(int, char*)", ModuleName = "MyApp.exe", SelfTimePercentage = 22.7, TotalTimePercentage = 35.2, SelfTime = TimeSpan.FromSeconds(9.1), TotalTime = TimeSpan.FromSeconds(14.1), SourceFile = "C:\\source\\processor.cpp", HasAssembly = true }, new FunctionInfo { Name = "AllocateMemory", FullName = "MemoryManager::AllocateMemory(size_t)", ModuleName = "MyApp.exe", SelfTimePercentage = 15.3, TotalTimePercentage = 15.3, SelfTime = TimeSpan.FromSeconds(6.1), TotalTime = TimeSpan.FromSeconds(6.1), SourceFile = "C:\\source\\memory.cpp", HasAssembly = true }, new FunctionInfo { Name = "StringCompare", FullName = "std::basic_string::compare", ModuleName = "MSVCP140.dll", SelfTimePercentage = 8.9, TotalTimePercentage = 8.9, SelfTime = TimeSpan.FromSeconds(3.6), TotalTime = TimeSpan.FromSeconds(3.6), SourceFile = null, HasAssembly = true }, new FunctionInfo { Name = "NtAllocateVirtualMemory", FullName = "NtAllocateVirtualMemory", ModuleName = "ntdll.dll", SelfTimePercentage = 6.2, TotalTimePercentage = 6.2, SelfTime = TimeSpan.FromSeconds(2.5), TotalTime = TimeSpan.FromSeconds(2.5), SourceFile = null, HasAssembly = true }, new FunctionInfo { Name = "RtlAllocateHeap", FullName = "RtlAllocateHeap", ModuleName = "ntdll.dll", SelfTimePercentage = 4.1, TotalTimePercentage = 4.1, SelfTime = TimeSpan.FromSeconds(1.6), TotalTime = TimeSpan.FromSeconds(1.6), SourceFile = null, HasAssembly = true }, new FunctionInfo { Name = "Helper", FullName = "Utils::Helper()", ModuleName = "MyApp.exe", SelfTimePercentage = 0.5, TotalTimePercentage = 2.1, SelfTime = TimeSpan.FromSeconds(0.2), TotalTime = TimeSpan.FromSeconds(0.8), SourceFile = "C:\\source\\utils.cpp", HasAssembly = true } }; // Apply module filtering if specified var filteredFunctions = mockFunctions; if (!string.IsNullOrWhiteSpace(filter.ModuleName)) { filteredFunctions = filteredFunctions .Where(f => !string.IsNullOrEmpty(f.ModuleName) && f.ModuleName.Contains(filter.ModuleName, StringComparison.OrdinalIgnoreCase)) .ToArray(); } // Apply self time filtering if specified if (filter.MinSelfTimePercentage.HasValue) { filteredFunctions = filteredFunctions .Where(f => f.SelfTimePercentage >= filter.MinSelfTimePercentage.Value) .ToArray(); } // Apply total time filtering if specified if (filter.MinTotalTimePercentage.HasValue) { filteredFunctions = filteredFunctions .Where(f => f.TotalTimePercentage >= filter.MinTotalTimePercentage.Value) .ToArray(); } // Apply top N filtering if specified if (filter.TopCount.HasValue) { // Sort by the chosen metric and take top N filteredFunctions = filter.SortBySelfTime ? filteredFunctions.OrderByDescending(f => f.SelfTimePercentage).Take(filter.TopCount.Value).ToArray() : filteredFunctions.OrderByDescending(f => f.TotalTimePercentage).Take(filter.TopCount.Value).ToArray(); } else { // If no topCount specified, still sort the results filteredFunctions = filter.SortBySelfTime ? filteredFunctions.OrderByDescending(f => f.SelfTimePercentage).ToArray() : filteredFunctions.OrderByDescending(f => f.TotalTimePercentage).ToArray(); } return Task.FromResult(new GetAvailableFunctionsResult { Success = true, Functions = filteredFunctions }); } public Task GetAvailableBinariesAsync(double? minTimePercentage = null, TimeSpan? minTime = null, int? topCount = null) { Console.WriteLine($"Mock: GetAvailableBinariesAsync called with minTimePercentage: {minTimePercentage}, minTime: {minTime}, topCount: {topCount}"); // Return mock binary list - just the unique binary names from the functions var mockBinaries = new BinaryInfo[] { new BinaryInfo { Name = "MyApp.exe", FullPath = "C:\\MyApp\\MyApp.exe", TimePercentage = 83.7, // sum of main, ProcessData, AllocateMemory, Helper self time percentages Time = TimeSpan.FromSeconds(33.5) }, new BinaryInfo { Name = "ntdll.dll", FullPath = "C:\\Windows\\System32\\ntdll.dll", TimePercentage = 10.3, // sum of NtAllocateVirtualMemory, RtlAllocateHeap self time percentages Time = TimeSpan.FromSeconds(4.1) }, new BinaryInfo { Name = "MSVCP140.dll", FullPath = "C:\\Windows\\System32\\MSVCP140.dll", TimePercentage = 8.9, // StringCompare self time percentage Time = TimeSpan.FromSeconds(3.6) }, new BinaryInfo { Name = "kernel32.dll", FullPath = "C:\\Windows\\System32\\kernel32.dll", TimePercentage = 0, Time = TimeSpan.Zero } }; // Apply filtering var filteredBinaries = mockBinaries; if (minTimePercentage.HasValue) { filteredBinaries = filteredBinaries .Where(b => b.TimePercentage >= minTimePercentage.Value) .ToArray(); } if (minTime.HasValue) { filteredBinaries = filteredBinaries .Where(b => b.Time >= minTime.Value) .ToArray(); } // Sort by time percentage descending filteredBinaries = filteredBinaries .OrderByDescending(b => b.TimePercentage) .ToArray(); // Apply top count filtering if specified if (topCount.HasValue) { filteredBinaries = filteredBinaries .Take(topCount.Value) .ToArray(); } return Task.FromResult(new GetAvailableBinariesResult { Success = true, Binaries = filteredBinaries }); } } ================================================ FILE: src/ProfileExplorer.Mcp/README.md ================================================ # ProfileExplorer.Mcp Model Context Protocol (MCP) server enabling AI agents to interact with Profile Explorer. ## Overview This project provides an MCP server that enables AI agent interactions with Profile Explorer. It allows users to perform profiling tasks through conversational AI by exposing Profile Explorer's core functionality as MCP tools. Users can ask questions like "load the Chrome process from this trace file" or "show me the slowest functions in ntdll.dll" and have them executed directly. ## Architecture The project consists of: - **ProfileExplorerMcpServer**: Main server class that handles MCP protocol communication - **ProfileExplorerTools**: Static class containing MCP tool implementations - **IMcpActionExecutor**: Interface for UI action execution (implemented by the UI project) - **ProfilerStatus**: Data model for UI status information - **McpServerConfiguration**: Helper for server initialization - **MockMcpActionExecutor**: Mock implementation for testing ## Available MCP Tools The server provides several MCP tools that enable AI agent profiling workflows: ### Core Profiling Operations - `OpenTrace(profileFilePath, processNameOrId)` - Load a trace file and process based on agent-friendly descriptions (e.g., "Chrome", "the main app process", "PID 1234") - `GetAvailableProcesses(profileFilePath, minWeightPercentage?, topCount?)` - Discover what processes are available in a trace file - `GetAvailableFunctions(moduleName?, minSelfTimePercentage?, minTotalTimePercentage?, topCount?, sortBySelfTime?)` - Find functions based on agent queries like "hottest functions in kernel32" or "CPU-intensive functions" - `GetAvailableBinaries(minTimePercentage?, minTimeMs?, topCount?)` - Identify which binaries/DLLs are consuming the most time ### Analysis and Deep Dive - `GetFunctionAssembly(functionName)` - Retrieve assembly code for detailed function analysis - `GetHelp()` - Get information about available capabilities ## AI Agent Workflow Examples Instead of manually navigating UI menus and dialogs, users can accomplish profiling tasks through AI agent conversation: **Example 1: Performance Investigation** - User: "I have high CPU usage, can you help me analyze trace.etl?" - AI: Uses `GetAvailableProcesses` → `OpenTrace` → `GetAvailableFunctions` to identify hotspots - User: "What's consuming the most time in the kernel?" - AI: Uses `GetAvailableFunctions(moduleName: "ntdll.dll", topCount: 10)` to show kernel bottlenecks **Example 2: Specific Function Analysis** - User: "Show me the assembly for the NtReadFile function" - AI: Uses `GetFunctionAssembly("NtReadFile")` to retrieve and display the code **Example 3: Process Discovery** - User: "What processes were active during this trace?" - AI: Uses `GetAvailableProcesses` to show all processes with their CPU usage percentages ## Usage ### Standalone Testing ```bash cd src/ProfileExplorer.Mcp dotnet run ``` ### Integration with AI Assistants The UI project should: 1. Implement `IMcpActionExecutor` interface to bridge MCP calls to Profile Explorer functionality 2. Initialize the server using `McpServerConfiguration.StartServerWithExecutorAsync(executor)` in `App.OnStartup` Once integrated, users can interact with Profile Explorer through AI agents via AI assistants that support MCP. ## Implementation Notes - All tool methods return JSON-serialized responses optimized for AI interpretation - The server handles ambiguous agent queries (e.g., "Chrome process" maps to appropriate process selection) - Error handling provides human-readable messages that AI assistants can relay to users - The server uses stdio transport for MCP communication with AI systems - UI thread marshaling should be handled by the executor implementation For detailed implementation guidance, see the `IMcpActionExecutor` interface and `ProfileExplorerMcpServer` class. ================================================ FILE: src/ProfileExplorer.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31612.314 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProfileExplorerUI", "ProfileExplorerUI\ProfileExplorerUI.csproj", "{23169CA2-2157-4978-A8AF-CF360540F467}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Clients", "Clients", "{11DEE166-9224-42F9-92C6-A6447A90C31B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "External", "External", "{9A2F89BD-58B1-4E31-A0CF-F4D3AFB3F02B}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProfileExplorerCore", "ProfileExplorerCore\ProfileExplorerCore.csproj", "{F73AD42A-5BD3-45B7-B915-7584F4588F55}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSExtension", "VSExtension\VSExtension.csproj", "{DF5E31FD-A162-4053-B7C6-50C196CF60E3}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProfileExplorerCoreTests", "ProfileExplorerCoreTests\ProfileExplorerCoreTests.csproj", "{A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ManagedProfiler", "ManagedProfiler\ManagedProfiler.vcxproj", "{08DED710-2048-45C3-90F9-0D585263796D}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TreeListView", "external\TreeListView\TreeListView.csproj", "{05BD7808-EE6F-4139-903C-758A97B122A9}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfileExplorerUITests", "ProfileExplorerUITests\ProfileExplorerUITests.csproj", "{8449AD82-6B34-4635-A502-7FA26DDF1BAF}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcLib", "GrpcLib\GrpcLib.csproj", "{DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PDBViewer", "PDBViewer\PDBViewer.csproj", "{669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}" ProjectSection(ProjectDependencies) = postProject {F73AD42A-5BD3-45B7-B915-7584F4588F55} = {F73AD42A-5BD3-45B7-B915-7584F4588F55} EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProfileExplorer.Mcp", "ProfileExplorer.Mcp\ProfileExplorer.Mcp.csproj", "{B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|ARM64 = Debug|ARM64 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|ARM64 = Release|ARM64 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|Any CPU.Build.0 = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|ARM64.ActiveCfg = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|ARM64.Build.0 = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|x64.ActiveCfg = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|x64.Build.0 = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|x86.ActiveCfg = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Debug|x86.Build.0 = Debug|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Release|Any CPU.ActiveCfg = Release|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Release|Any CPU.Build.0 = Release|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Release|ARM64.ActiveCfg = Release|ARM64 {23169CA2-2157-4978-A8AF-CF360540F467}.Release|ARM64.Build.0 = Release|ARM64 {23169CA2-2157-4978-A8AF-CF360540F467}.Release|x64.ActiveCfg = Release|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Release|x64.Build.0 = Release|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Release|x86.ActiveCfg = Release|Any CPU {23169CA2-2157-4978-A8AF-CF360540F467}.Release|x86.Build.0 = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|Any CPU.Build.0 = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|ARM64.ActiveCfg = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|ARM64.Build.0 = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|x64.ActiveCfg = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|x64.Build.0 = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|x86.ActiveCfg = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Debug|x86.Build.0 = Debug|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|Any CPU.ActiveCfg = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|Any CPU.Build.0 = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|ARM64.ActiveCfg = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|ARM64.Build.0 = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|x64.ActiveCfg = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|x64.Build.0 = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|x86.ActiveCfg = Release|Any CPU {F73AD42A-5BD3-45B7-B915-7584F4588F55}.Release|x86.Build.0 = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|ARM64.ActiveCfg = Debug|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|ARM64.Build.0 = Debug|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|x64.ActiveCfg = Debug|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|x64.Build.0 = Debug|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|x86.ActiveCfg = Debug|x86 {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Debug|x86.Build.0 = Debug|x86 {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|Any CPU.Build.0 = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|ARM64.ActiveCfg = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|ARM64.Build.0 = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|x64.ActiveCfg = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|x64.Build.0 = Release|Any CPU {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|x86.ActiveCfg = Release|x86 {DF5E31FD-A162-4053-B7C6-50C196CF60E3}.Release|x86.Build.0 = Release|x86 {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|Any CPU.Build.0 = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|ARM64.ActiveCfg = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|ARM64.Build.0 = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|x64.ActiveCfg = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|x64.Build.0 = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|x86.ActiveCfg = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Debug|x86.Build.0 = Debug|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|Any CPU.Build.0 = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|ARM64.ActiveCfg = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|ARM64.Build.0 = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|x64.ActiveCfg = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|x64.Build.0 = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|x86.ActiveCfg = Release|Any CPU {A0006302-D1B5-4AB8-9ACE-D31A692DB3D2}.Release|x86.Build.0 = Release|Any CPU {08DED710-2048-45C3-90F9-0D585263796D}.Debug|Any CPU.ActiveCfg = Debug|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|Any CPU.Build.0 = Debug|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|ARM64.ActiveCfg = Debug|ARM64 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|ARM64.Build.0 = Debug|ARM64 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|x64.ActiveCfg = Debug|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|x64.Build.0 = Debug|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|x86.ActiveCfg = Debug|Win32 {08DED710-2048-45C3-90F9-0D585263796D}.Debug|x86.Build.0 = Debug|Win32 {08DED710-2048-45C3-90F9-0D585263796D}.Release|Any CPU.ActiveCfg = Release|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Release|Any CPU.Build.0 = Release|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Release|ARM64.ActiveCfg = Release|ARM64 {08DED710-2048-45C3-90F9-0D585263796D}.Release|ARM64.Build.0 = Release|ARM64 {08DED710-2048-45C3-90F9-0D585263796D}.Release|x64.ActiveCfg = Release|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Release|x64.Build.0 = Release|x64 {08DED710-2048-45C3-90F9-0D585263796D}.Release|x86.ActiveCfg = Release|Win32 {08DED710-2048-45C3-90F9-0D585263796D}.Release|x86.Build.0 = Release|Win32 {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|ARM64.ActiveCfg = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|ARM64.Build.0 = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|x64.ActiveCfg = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|x64.Build.0 = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|x86.ActiveCfg = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Debug|x86.Build.0 = Debug|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|Any CPU.ActiveCfg = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|Any CPU.Build.0 = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|ARM64.ActiveCfg = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|ARM64.Build.0 = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|x64.ActiveCfg = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|x64.Build.0 = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|x86.ActiveCfg = Release|Any CPU {05BD7808-EE6F-4139-903C-758A97B122A9}.Release|x86.Build.0 = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|Any CPU.Build.0 = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|ARM64.ActiveCfg = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|ARM64.Build.0 = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|x64.ActiveCfg = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|x64.Build.0 = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|x86.ActiveCfg = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Debug|x86.Build.0 = Debug|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|Any CPU.ActiveCfg = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|Any CPU.Build.0 = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|ARM64.ActiveCfg = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|ARM64.Build.0 = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|x64.ActiveCfg = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|x64.Build.0 = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|x86.ActiveCfg = Release|Any CPU {8449AD82-6B34-4635-A502-7FA26DDF1BAF}.Release|x86.Build.0 = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|Any CPU.Build.0 = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|ARM64.ActiveCfg = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|ARM64.Build.0 = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|x64.ActiveCfg = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|x64.Build.0 = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|x86.ActiveCfg = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Debug|x86.Build.0 = Debug|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|Any CPU.ActiveCfg = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|Any CPU.Build.0 = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|ARM64.ActiveCfg = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|ARM64.Build.0 = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|x64.ActiveCfg = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|x64.Build.0 = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|x86.ActiveCfg = Release|Any CPU {DA5B7FDA-6DE4-4B11-AF93-E785E1DF56A0}.Release|x86.Build.0 = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|Any CPU.Build.0 = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|ARM64.ActiveCfg = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|ARM64.Build.0 = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|x64.ActiveCfg = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|x64.Build.0 = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|x86.ActiveCfg = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Debug|x86.Build.0 = Debug|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|Any CPU.ActiveCfg = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|Any CPU.Build.0 = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|ARM64.ActiveCfg = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|ARM64.Build.0 = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|x64.ActiveCfg = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|x64.Build.0 = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|x86.ActiveCfg = Release|Any CPU {669B5EBC-A5D6-4CEC-B3DB-6DA7D0CA7B79}.Release|x86.Build.0 = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|ARM64.ActiveCfg = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|ARM64.Build.0 = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|x64.ActiveCfg = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|x64.Build.0 = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|x86.ActiveCfg = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Debug|x86.Build.0 = Debug|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|Any CPU.Build.0 = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|ARM64.ActiveCfg = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|ARM64.Build.0 = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|x64.ActiveCfg = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|x64.Build.0 = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|x86.ActiveCfg = Release|Any CPU {B8E89A2F-3C4D-4A5B-9E1F-2A7B3C4D5E6F}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {23169CA2-2157-4978-A8AF-CF360540F467} = {11DEE166-9224-42F9-92C6-A6447A90C31B} {DF5E31FD-A162-4053-B7C6-50C196CF60E3} = {11DEE166-9224-42F9-92C6-A6447A90C31B} {05BD7808-EE6F-4139-903C-758A97B122A9} = {9A2F89BD-58B1-4E31-A0CF-F4D3AFB3F02B} {8449AD82-6B34-4635-A502-7FA26DDF1BAF} = {11DEE166-9224-42F9-92C6-A6447A90C31B} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DC3D5311-37A2-44C1-90E8-86A268A99F35} EndGlobalSection EndGlobal ================================================ FILE: src/ProfileExplorerCore/Analysis/CFGBlockOrdering.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; public enum CFGEdgeKind { Tree, Forward, Backward, Crossing } public class CFGBlockOrdering { private FunctionIR function_; private List postorderList_; private Dictionary postorderMap_; private List preorderList_; private Dictionary preorderMap_; private HashSet visitedBlocks_; public CFGBlockOrdering(FunctionIR function) { function_ = function; preorderList_ = new List(function_.Blocks.Count); postorderList_ = new List(function_.Blocks.Count); preorderMap_ = new Dictionary(function_.Blocks.Count); postorderMap_ = new Dictionary(function_.Blocks.Count); visitedBlocks_ = new HashSet(function_.Blocks.Count); if (function.EntryBlock != null) { visitedBlocks_.Add(function_.EntryBlock); ComputeInfo(function.EntryBlock); } } public List PreorderList => preorderList_; public List PostorderList => postorderList_; public int GetBlockPreorderNumber(BlockIR block) { if (preorderMap_.TryGetValue(block, out int number)) { return number; } return -1; } public int GetBlockPostorderNumber(BlockIR block) { if (postorderMap_.TryGetValue(block, out int number)) { return number; } return -1; } public void PostorderWalk(Func action) { for (int i = 0; i < postorderList_.Count; i++) { if (!action(postorderList_[i], i)) { break; } } } public void PreorderWalk(Func action) { for (int i = 0; i < preorderList_.Count; i++) { if (!action(preorderList_[i], i)) { break; } } } public void ReversePostorderWalk(Func action) { for (int i = postorderList_.Count - 1; i >= 0; i--) { if (!action(postorderList_[i], i)) { break; } } } private void ComputeInfo(BlockIR block) { preorderMap_.Add(block, preorderList_.Count); preorderList_.Add(block); foreach (var successorBlock in block.Successors) { if (visitedBlocks_.Add(successorBlock)) { // First time visiting the block. //? TODO: Compute edge kind ComputeInfo(successorBlock); } //? TODO: Compute edge kind } postorderMap_.Add(block, postorderList_.Count); postorderList_.Add(block); } } ================================================ FILE: src/ProfileExplorerCore/Analysis/CFGReachability.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections; using System.Collections.Generic; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; //? TODO: Switch to SparseBitVector to speed up. public class CFGReachability { private FunctionIR function_; private int maxBlockNumber_; private BitArray[] reachableBlocks_; public CFGReachability(FunctionIR function) { function_ = function; maxBlockNumber_ = -1; function_.Blocks.ForEach(item => maxBlockNumber_ = Math.Max(item.Number, maxBlockNumber_)); maxBlockNumber_++; InitializeBitVectors(); Compute(); } public static int GetCardinality(BitArray bitArray) { int[] ints = new int[(bitArray.Count >> 5) + 1]; bitArray.CopyTo(ints, 0); int count = 0; // Fix for not truncated bits in last integer that may have been set to true with SetAll(). ints[ints.Length - 1] &= ~(-1 << bitArray.Count % 32); for (int i = 0; i < ints.Length; i++) { int c = ints[i]; // http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel unchecked { c = c - (c >> 1 & 0x55555555); c = (c & 0x33333333) + (c >> 2 & 0x33333333); c = (c + (c >> 4) & 0xF0F0F0F) * 0x1010101 >> 24; } count += c; } return count; } public bool Reaches(BlockIR block, BlockIR targetBlock) { return reachableBlocks_[targetBlock.Number].Get(block.Number); } public List FindPath(BlockIR block, BlockIR targetBlock) { if (!Reaches(block, targetBlock)) { return new List(); } var visited = new HashSet(maxBlockNumber_); var worklist = new List(maxBlockNumber_); worklist.Add(new PathBlock(block)); visited.Add(block); while (worklist.Count > 0) { var current = worklist[worklist.Count - 1]; worklist.RemoveAt(worklist.Count - 1); if (current.Block == targetBlock) { var pathBlocks = new List(current.Distance + 1); while (current != null) { pathBlocks.Add(current.Block); current = current.Previous; } return pathBlocks; } foreach (var succBlock in current.Block.Successors) { if (!visited.Contains(succBlock)) { worklist.Add(new PathBlock(succBlock, current.Distance + 1, current)); visited.Add(succBlock); } } } return new List(); } private void InitializeBitVectors() { reachableBlocks_ = new BitArray[maxBlockNumber_ + 1]; for (int i = 0; i <= maxBlockNumber_; i++) { reachableBlocks_[i] = new BitArray(maxBlockNumber_ + 1); } if (function_.EntryBlock != null) { reachableBlocks_[function_.EntryBlock.Number].Set(function_.EntryBlock.Number, true); } } private void Compute() { //? TODO: This entire code is very inefficient //? A proper sparse bit-vector is needed. var currentValues = new BitArray(maxBlockNumber_ + 1); bool changed = true; //var sw = Stopwatch.StartNew(); var blockOrdering = new CFGBlockOrdering(function_); while (changed) { changed = false; //foreach (var block in function_.Blocks) { blockOrdering.ReversePostorderWalk((block, _) => { if (block.Predecessors.Count == 0) { return true; } currentValues.SetAll(false); foreach (var predBlock in block.Predecessors) { var inValues = reachableBlocks_[predBlock.Number]; currentValues.Or(inValues); } int popcnt = GetCardinality(currentValues); if (popcnt > 0) { currentValues.Set(block.Number, true); } var outValues = reachableBlocks_[block.Number]; for (int i = 0; i < maxBlockNumber_; i++) { if (currentValues[i] != outValues[i]) { reachableBlocks_[block.Number] = new BitArray(currentValues); changed = true; break; } } return true; }); } //sw.Stop(); //Trace.WriteLine($"Time {sw.ElapsedMilliseconds}"); //Trace.Flush(); } private class PathBlock { public BlockIR Block; public int Distance; public PathBlock Previous; public PathBlock(BlockIR block, int distance = 0, PathBlock previous = null) { Block = block; Distance = distance; Previous = previous; } } } ================================================ FILE: src/ProfileExplorerCore/Analysis/CFGReachabilityReferenceFilter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; public class CFGReachabilityReferenceFilter : IReachableReferenceFilter { protected FunctionIR function_; protected CFGReachability cfgReachability_; public CFGReachabilityReferenceFilter(FunctionIR function) { function_ = function; } public bool FilterDefinitions { get; set; } public bool FilterUses { get; set; } public virtual bool AcceptDefinitionReference(IRElement element, IRElement startSourceElement) { if (!FilterDefinitions) { return false; } // Accept element if it's a definition that can reach the source element. var cfgReachability = GetReachabilityInfo(); if (!cfgReachability.Reaches(element.ParentBlock, startSourceElement.ParentBlock)) { return false; } //? TODO: Use reaching definitions if available // If in the same block, accept it only if dest is found before the use, // or the block is found in a loop (value may reach through a backedge). if (startSourceElement.ParentBlock == element.ParentBlock) { if (element.ParentInstruction == null) { return true; // Parameter dominates everything. } if (startSourceElement.ParentInstruction == null) { return false; } int destIndex = element.ParentInstruction.IndexInBlock; int useIndex = startSourceElement.ParentInstruction.IndexInBlock; return destIndex < useIndex; } return true; } public virtual bool AcceptReference(IRElement element, IRElement startElement) { return true; } public virtual bool AcceptUseReference(IRElement element, IRElement startDestElement) { if (!FilterUses) { return false; } // Accept element if it can be reached from the dest. element. //? TODO: Use reaching definitions if available var cfgReachability = GetReachabilityInfo(); if (!cfgReachability.Reaches(startDestElement.ParentBlock, element.ParentBlock)) { return false; } // If in the same block, accept it only if dest is found before the use, // or the block is found in a loop (value may reach through a backedge). if (startDestElement.ParentBlock == element.ParentBlock) { if (startDestElement.ParentInstruction == null) { return true; // Use dominated by parameter. } if (element.ParentInstruction == null) { return false; } int destIndex = startDestElement.ParentInstruction.IndexInBlock; int useIndex = element.ParentInstruction.IndexInBlock; return destIndex < useIndex; } return true; } private CFGReachability GetReachabilityInfo() { cfgReachability_ ??= FunctionAnalysisCache.Get(function_).GetReachability(); return cfgReachability_; } } ================================================ FILE: src/ProfileExplorerCore/Analysis/CallGraph.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Analysis; [Flags] public enum CallGraphNodeFlags { None = 0, Internal = 1 << 0, External = 1 << 1, AddressTaken = 1 << 2 } public class CallSite : TaggedObject { public CallSite(ulong callInstrId, CallGraphNode target, CallGraphNode source) { CallInstructionId = callInstrId; Target = target; Source = source; } public CallSite(InstructionIR callInstr, CallGraphNode target, CallGraphNode parent) : this(callInstr.Id, target, parent) { } public ulong CallInstructionId { get; set; } public CallGraphNode Target { get; set; } public CallGraphNode Source { get; set; } public static bool operator ==(CallSite left, CallSite right) { return EqualityComparer.Default.Equals(left, right); } public static bool operator !=(CallSite left, CallSite right) { return !(left == right); } public override bool Equals(object obj) { return obj is CallSite site && CallInstructionId == site.CallInstructionId && EqualityComparer.Default.Equals(Target, site.Target) && EqualityComparer.Default.Equals(Source, site.Source); } public override int GetHashCode() { return HashCode.Combine(CallInstructionId, Target, Source); } } public class CallGraphNode : TaggedObject { public CallGraphNode(IRTextFunction function, string funcName, int number, CallGraphNodeFlags flags) { Function = function; FunctionName = funcName; Number = number; Flags = flags; } public IRTextFunction Function { get; set; } public string FunctionName { get; set; } public int Number { get; set; } public List Callers { get; set; } public List Callees { get; set; } public CallGraphNodeFlags Flags { get; set; } public bool HasKnownTarget => Function != null; public bool HasCallers => Callers != null && Callers.Count > 0; public bool HasCallees => Callees != null && Callees.Count > 0; public bool IsLeafFunction => !HasCallees; public bool IsInternal => Flags.HasFlag(CallGraphNodeFlags.Internal); public bool IsExternal => Flags.HasFlag(CallGraphNodeFlags.External); public bool IsAddressTaken => Flags.HasFlag(CallGraphNodeFlags.AddressTaken); public IEnumerable UniqueCallers { get { if (Callers != null) { var nodeSet = new HashSet(); foreach (var callsite in Callers) { if (nodeSet.Add(callsite.Source)) { yield return callsite.Source; } } } } } public IEnumerable UniqueCallees { get { if (Callees != null) { var nodeSet = new HashSet(); foreach (var callsite in Callees) { if (nodeSet.Add(callsite.Target)) { yield return callsite.Target; } } } } } public int UniqueCallerCount { get { int count = 0; foreach (var node in UniqueCallers) { count++; } return count; } } public int UniqueCalleeCount { get { int count = 0; foreach (var node in UniqueCallees) { count++; } return count; } } public static bool operator ==(CallGraphNode left, CallGraphNode right) { return EqualityComparer.Default.Equals(left, right); } public static bool operator !=(CallGraphNode left, CallGraphNode right) { return !(left == right); } public void AddCallee(CallSite callsite) { Callees ??= new List(); Callees.Add(callsite); } public void AddCallee(CallGraphNode node) { AddCallee(new CallSite(0, node, this)); } public void AddCaller(CallSite callsite) { Callers ??= new List(); Callers.Add(callsite); } public CallGraphNode FindCallee(string name) { if (Callees == null) { return null; } var result = Callees.Find(c => c.Target != null && c.Target.FunctionName.Equals(name, StringComparison.Ordinal)); return result?.Target; } public CallGraphNode FindCallee(IRTextFunction function) { if (Callees == null) { return null; } var result = Callees.Find(c => c.Target != null && c.Target.Function == function); return result?.Target; } public CallGraphNode FindCallee(CallGraphNode node) { return FindCallee(node.FunctionName); } public CallGraphNode FindCaller(IRTextFunction function) { if (Callers == null) { return null; } var result = Callers.Find(c => c.Source != null && c.Source.Function == function); return result?.Target; } public override bool Equals(object obj) { return obj is CallGraphNode node && Number == node.Number && FunctionName == node.FunctionName; } public override int GetHashCode() { return HashCode.Combine(Number); } } public class CallGraphEventArgs : EventArgs { public CallGraphEventArgs(IRTextFunction textFunction, FunctionIR function, CallGraphNode functionNode) { TextFunction = textFunction; Function = function; FunctionNode = functionNode; } public IRTextFunction TextFunction { get; set; } public FunctionIR Function { get; set; } public CallGraphNode FunctionNode { get; set; } } public class CallGraph { public delegate bool CallNodeCallback(CallGraphNode node, CallGraphNode parentNode, CallGraph callGraph, List targetFuncts); private List nodes_; private List entryNodes_; private Dictionary funcToNodeMap_; private Dictionary externalFuncToNodeMap_; private HashSet visitedFuncts_; private IRTextSummary summary_; private IRTextSectionLoader loader_; private ICompilerIRInfo irInfo_; private int nextCallNodeId_; public CallGraph(IRTextSummary summary, IRTextSectionLoader loader, ICompilerIRInfo irInfo) { summary_ = summary; loader_ = loader; irInfo_ = irInfo; nodes_ = new List(summary.Functions.Count); funcToNodeMap_ = new Dictionary(summary.Functions.Count); externalFuncToNodeMap_ = new Dictionary(); visitedFuncts_ = new HashSet(); entryNodes_ = new List(); } public List EntryFunctionNodes => entryNodes_; public List FunctionNodes => nodes_; public event EventHandler CallGraphNodeCreated; public void Execute(IRTextSection section = null, CancelableTask cancelableTask = null) { //? TODO: Can be multithreaded, most time spent parsing the functs foreach (var func in summary_.Functions) { if (visitedFuncts_.Contains(func)) { continue; } if (cancelableTask is {IsCanceled: true}) { return; } BuildCallSubgraph(func, section?.Name, cancelableTask); } // Find entry functions. foreach (var node in nodes_) { if (!node.HasCallers) { entryNodes_.Add(node); } } } public CallGraphNode Execute(IRTextFunction startFunction, IRTextSection section = null, CancelableTask cancelableTask = null) { BuildCallSubgraph(startFunction, section?.Name, cancelableTask); return GetOrCreateNode(startFunction); } public CallGraphNode FindNode(IRTextFunction function) { if (funcToNodeMap_.TryGetValue(function, out var node)) { return node; } return null; } public CallGraphNode GetOrCreateNode(IRTextFunction func) { return GetOrCreateNode(func.Name); } public void AugmentGraph(CallNodeCallback augmentAction) { // Walk over a clone of the node list, since new nodes may be added // and would invalidate the iterator and assert. var listClone = new List(nodes_.Count); listClone.AddRange(nodes_); foreach (var node in listClone) { if (node.Function != null) { augmentAction(node, node, this, null); } } } public void TrimGraph(List targetFuncts, CallNodeCallback callerFilter = null, CallNodeCallback calleeFilter = null) { // Remove all nodes that don't lead to one of the target functions. var visitedNodes = new HashSet(); var worklist = new Queue(); foreach (var func in targetFuncts) { var node = FindNode(func); if (node != null) { worklist.Enqueue(node); } } while (worklist.Count != 0) { var node = worklist.Dequeue(); visitedNodes.Add(node); if (node.HasCallers) { foreach (var caller in node.Callers) { if (callerFilter == null || callerFilter(caller.Source, node, this, targetFuncts)) { if (!visitedNodes.Contains(caller.Source)) { worklist.Enqueue(caller.Source); } } } } if (node.HasCallees) { foreach (var calee in node.Callees) { if (calleeFilter == null || calleeFilter(calee.Target, node, this, targetFuncts)) { visitedNodes.Add(calee.Target); } } } } nodes_.Clear(); nodes_.AddRange(visitedNodes); var cleanedNodes = new HashSet(); foreach (var node in nodes_) { TrimNodes(node, visitedNodes, cleanedNodes); } entryNodes_.Clear(); foreach (var node in nodes_) { if (!node.HasCallers) { entryNodes_.Add(node); } } } private void BuildCallSubgraph(IRTextFunction startFunction, string sectionName, CancelableTask cancelableTask) { var worklist = new Queue(); worklist.Enqueue(startFunction); visitedFuncts_.Add(startFunction); while (worklist.Count > 0) { if (cancelableTask is {IsCanceled: true}) { break; } var func = worklist.Dequeue(); var funcNode = GetOrCreateNode(func); if (funcNode == null) { continue; // An unknown/external function, ignore. } var funcIR = LoadSection(func, sectionName); if (funcIR == null) { continue; // Failed to parse function, ignore. } // Notify client about the node being created and function IR being available, // can be used to add extra annotation tags on the node without having // to reparse the functions later. CallGraphNodeCreated?.Invoke(this, new CallGraphEventArgs(func, funcIR, funcNode)); foreach (var instr in funcIR.AllInstructions) { if (irInfo_.IsCallInstruction(instr)) { var callTarget = irInfo_.GetCallTarget(instr); if (callTarget != null) { // Extract target name. string calleeFuncName = "[INDIRECT]"; if (callTarget.HasName) { calleeFuncName = callTarget.Name; } else if (callTarget.IsIntConstant) { calleeFuncName = $"0x{callTarget.IntValue:X}"; } // Make node and enqueue it for the recursive processing. var calleeNode = GetOrCreateNode(calleeFuncName); var callsite = new CallSite(instr, calleeNode, funcNode); funcNode.AddCallee(callsite); calleeNode.AddCaller(callsite); // If the function has a definition, add it to the worklist. var calleeFunc = summary_.FindFunction(calleeFuncName); if (calleeFunc != null && visitedFuncts_.Add(calleeFunc)) { worklist.Enqueue(calleeFunc); } } //? TODO: Add a "Unknown target" node } } } } private void TrimNodes(CallGraphNode node, HashSet visitedNodes, HashSet cleanedNodes) { cleanedNodes.Add(node); if (!node.HasCallees) { return; } for (int i = 0; i < node.Callees.Count; i++) { var calleeNode = node.Callees[i].Target; if (!visitedNodes.Contains(calleeNode)) { node.Callees.RemoveAt(i); i--; } else if (!cleanedNodes.Contains(calleeNode)) { TrimNodes(calleeNode, visitedNodes, cleanedNodes); } } } private CallGraphNode GetOrCreateNode(string funcName) { var func = summary_.FindFunction(funcName); if (func == null) { // Consider that it's an external function without definition. if (externalFuncToNodeMap_.TryGetValue(funcName, out var externalNode)) { return externalNode; } externalNode = new CallGraphNode(null, funcName, GetNextCallNodeId(), CallGraphNodeFlags.External); externalFuncToNodeMap_[funcName] = externalNode; nodes_.Add(externalNode); return externalNode; } if (funcToNodeMap_.TryGetValue(func, out var node)) { return node; } node = new CallGraphNode(func, funcName, GetNextCallNodeId(), CallGraphNodeFlags.Internal); funcToNodeMap_[func] = node; nodes_.Add(node); return node; } private int GetNextCallNodeId() { return nextCallNodeId_++; } private FunctionIR LoadSection(IRTextFunction func, string sectionName) { var section = func.FindSection(sectionName); if (section == null) { if (func.SectionCount == 0) { return null; } section = func.Sections[0]; } var loadedDoc = loader_.LoadSection(section); return loadedDoc?.Function; } } ================================================ FILE: src/ProfileExplorerCore/Analysis/DominanceFrontier.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Linq; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; public class DominanceFrontier { private readonly Dictionary> frontierMap_; public DominanceFrontier(FunctionIR function, DominatorAlgorithm dominanceAlgorithm) { frontierMap_ = BuildDominanceFrontiers(function, dominanceAlgorithm); } private static Dictionary> BuildDominanceFrontiers(FunctionIR function, DominatorAlgorithm dominanceAlgorithm) { // Algorithm adapted from Engineering a Compiler, 2nd edition page 499 var dominanceFrontiers = InitializeDominanceFrontiersToEmpty(function); AddCFGDominanceFrontierInfo(function, dominanceAlgorithm, dominanceFrontiers); return ConvertResult(dominanceFrontiers); } private static Dictionary> InitializeDominanceFrontiersToEmpty(FunctionIR function) { var result = new Dictionary>(); foreach (var block in function.Blocks) { result[block] = new HashSet(); } return result; } private static void AddCFGDominanceFrontierInfo(FunctionIR function, DominatorAlgorithm dominanceAlgorithm, Dictionary> dominanceFrontiers) { var blocks = new CFGBlockOrdering(function).PostorderList; foreach (var block in blocks) { var nextBlocks = dominanceAlgorithm.NextBlocks(block).Where(blocks.Contains).ToList(); if (nextBlocks.Count > 1) { foreach (var nextBlock in nextBlocks) { var runner = nextBlock; while (runner != dominanceAlgorithm.GetImmediateDominator(block)) { dominanceFrontiers[runner].Add(block); runner = dominanceAlgorithm.GetImmediateDominator(runner); } } } } } private static Dictionary> ConvertResult(Dictionary> hashedResult) { var result = new Dictionary>(); foreach (var entry in hashedResult) { var list = new List(); foreach (var value in entry.Value) { list.Add(value); } result[entry.Key] = list; } return result; } public IReadOnlyList FrontierOf(BlockIR block) { return frontierMap_[block]; } } ================================================ FILE: src/ProfileExplorerCore/Analysis/DominatorAlgorithm.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; [Flags] public enum DominatorAlgorithmOptions { Dominators = 1 << 0, PostDominators = 1 << 1, BuildTree = 1 << 2, BuildQueryCache = 1 << 3 } public class DominatorTreeNode { public DominatorTreeNode(BlockIR block, int childCount = 0) { Block = block; Children = new List(childCount); } public BlockIR Block { get; set; } public DominatorTreeNode ImmediateDominator { get; set; } public List Children { get; set; } } public class DominatorAlgorithm { private readonly FunctionIR function_; private readonly DominatorAlgorithmOptions options_; private readonly Func> nextBlocks_; private Dictionary blockDomTreeNodeMap_; private Dictionary blockIdMap_; private CFGBlockOrdering blockOrdering_; private HashSet> dominanceCache_; private List immDoms_; private List postorderList_; private Dictionary postorderNumberBlockMap_; private BlockIR treeStartBlock_; private DominatorTreeNode treeRootNode_; public DominatorAlgorithm(FunctionIR function, DominatorAlgorithmOptions options) { function_ = function; options_ = options; bool usePostDominators = options.HasFlag(DominatorAlgorithmOptions.PostDominators); List patchedBlocks = null; if (usePostDominators) { nextBlocks_ = block => block.Successors; // With multiple function exit blocks, create one fake exit block // that acts as the single exit and change each exit block // to have it as a successor. var exitBlocks = new List(); foreach (var block in function.Blocks) { if (block.IsReturnBlock) { exitBlocks.Add(block); } } if (exitBlocks.Count == 1) { treeStartBlock_ = exitBlocks[0]; } else { patchedBlocks = new List(); var mergedExitBlock = new BlockIR(IRElementId.FromLong(0), function.BlockCount, function); mergedExitBlock.Number = function.BlockCount; treeStartBlock_ = mergedExitBlock; foreach (var exitBlock in exitBlocks) { mergedExitBlock.Predecessors.Add(exitBlock); exitBlock.Successors.Add(mergedExitBlock); patchedBlocks.Add(exitBlock); // To remove fake successor later. } } } else { // It is assumed there is a single entry block. nextBlocks_ = block => block.Predecessors; treeStartBlock_ = function.EntryBlock; } // Build a list of the blocks in postorder. blockOrdering_ = new CFGBlockOrdering(function); postorderList_ = blockOrdering_.PostorderList; // For post-dominators, the blocks are walked in reverse-postorder. if (usePostDominators) { postorderList_.Reverse(); } // Build map of block to its ID in the immDom array. int blockCount = function.Blocks.Count; blockIdMap_ = new Dictionary(blockCount); for (int i = 0; i < postorderList_.Count; i++) { blockIdMap_[postorderList_[i]] = i; } // Build a reverse map from block -> postorder number // to allow querying the immediate dominator list quickly. postorderNumberBlockMap_ = new Dictionary(blockCount); foreach (var block in postorderList_) { postorderNumberBlockMap_[GetBlockId(block)] = block; } if (!InitializeImmediateDoms(treeStartBlock_)) { return; // CFG is invalid. } Compute(); if (options.HasFlag(DominatorAlgorithmOptions.BuildTree)) { BuildTree(treeStartBlock_); } // Remove the fake successor merged exit block from the patched blocks. if (usePostDominators && patchedBlocks != null) { foreach (var block in patchedBlocks) { block.Predecessors.RemoveAt(block.Predecessors.Count - 1); } } } public DominatorTreeNode DomTreeRootNode => treeRootNode_; public bool IsValid => treeRootNode_ != null; public BlockIR GetImmediateDominator(BlockIR block) { int blockId = GetBlockId(block); if (blockId == -1) { return null; // CFG is invalid; } int immDom = immDoms_[blockId]; return immDom != -1 ? postorderNumberBlockMap_[immDom] : null; } public IEnumerable EnumerateDominators(BlockIR block) { while (block != treeStartBlock_) { block = GetImmediateDominator(block); if (block == null) { yield break; } yield return block; } } public bool Dominates(BlockIR block, BlockIR dominatedBlock) { if (block == dominatedBlock) { return true; } if (BuildQueryCache(treeStartBlock_)) { var pair = new Tuple(block, dominatedBlock); return dominanceCache_.Contains(pair); } // Fall back to a search through the immdom array. int blockId = GetBlockId(dominatedBlock); if (blockId == -1) { return false; // Unreachable block. } int immDom = immDoms_[blockId]; while (immDom != -1) { var immDomBlock = postorderNumberBlockMap_[immDom]; if (immDomBlock == block) { return true; } if (immDomBlock == treeStartBlock_) { return false; } immDom = immDoms_[immDom]; } return false; } public List NextBlocks(BlockIR block) { return nextBlocks_(block); } private void Compute() { bool changed = true; while (changed) { changed = false; // Iterate over the block list. Note that we don't start with the last node // because we want to skip over the entry or exit block. for (int i = postorderList_.Count - 2; i >= 0; i--) { // We need to choose the first predecessor that was processed. // Then we intersect its dominator set with the sets of all // the other predecessors that have been processed. int newIdomId = -1; var block = postorderList_[i]; foreach (var nextBlock in NextBlocks(block)) { UpdateImmediateDominator(nextBlock, ref newIdomId); } // If the new immediate dominator is not the same as the last one // save it and mark that a change has been made. if (immDoms_[i] != newIdomId) { immDoms_[i] = newIdomId; changed = true; } } } } private void UpdateImmediateDominator(BlockIR block, ref int newIdomId) { int blockId = GetBlockId(block); if (blockId == -1) { // This happens when the predecessor is unreachable, // but the current block is reachable. return; } if (immDoms_[blockId] == -1) { // Skip the predecessor if it wasn't processed yet. } else if (newIdomId == -1) { // This is the first predecessor that was processed. newIdomId = blockId; } else { // This is a predecessor that was processed. Intersect its // dominator set with the current new immediate dominator. newIdomId = Intersect(blockId, newIdomId); } } private bool InitializeImmediateDoms(BlockIR startBlock) { immDoms_ = new List(function_.Blocks.Count); for (int i = 0; i < postorderList_.Count; i++) { immDoms_.Add(-1); } // The start node is dominated only by itself. int startBlockId = GetBlockId(startBlock); if (startBlockId == -1) { return false; } immDoms_[startBlockId] = startBlockId; return true; } private int Intersect(int a, int b) { // Walk up the immediate dominator array until the "fingers" point to the // same postorder number. Note that a higher postorder number means that // we're closer to the entry block of the CFG (exit block if we're // talking about a post-dominator tree). while (a != b) { while (a < b) { a = immDoms_[a]; // PostNumb(immDoms[a]) > PostNumb(a) } while (b < a) { b = immDoms_[b]; // Same as above. } } return a; } private int GetBlockId(BlockIR block) { if (block == null) { return -1; // Invalid CFG. } if (blockIdMap_.TryGetValue(block, out int id)) { return id; } return -1; } private void BuildTree(BlockIR startBlock) { blockDomTreeNodeMap_ = new Dictionary(function_.Blocks.Count); treeRootNode_ = GetOrCreateDomTreeNode(startBlock); // Build the tree top-down. for (int i = postorderList_.Count - 2; i >= 0; i--) { var block = postorderList_[i]; var blockNode = GetOrCreateDomTreeNode(block); int blockId = GetBlockId(block); int immDom = immDoms_[blockId]; if (immDom == -1) { continue; // This is an unreachable block. } var immDomBlock = postorderNumberBlockMap_[immDom]; var immDomBlockNode = GetOrCreateDomTreeNode(immDomBlock); blockNode.ImmediateDominator = immDomBlockNode; immDomBlockNode.Children.Add(blockNode); } } private DominatorTreeNode GetOrCreateDomTreeNode(BlockIR block) { if (blockDomTreeNodeMap_.TryGetValue(block, out var node)) { return node; } node = new DominatorTreeNode(block, block.Successors.Count); blockDomTreeNodeMap_[block] = node; return node; } private bool BuildQueryCache(BlockIR startBlock) { if (dominanceCache_ != null) { return true; } if (!options_.HasFlag(DominatorAlgorithmOptions.BuildQueryCache)) { return false; } dominanceCache_ = new HashSet>(function_.Blocks.Count * 4); foreach (var block in postorderList_) { int blockId = GetBlockId(block); int immDom = immDoms_[blockId]; while (immDom != -1) { var immDomBlock = postorderNumberBlockMap_[immDom]; dominanceCache_.Add(new Tuple(immDomBlock, block)); if (immDomBlock == startBlock) { break; } immDom = immDoms_[immDom]; } } return true; } } ================================================ FILE: src/ProfileExplorerCore/Analysis/FunctionAnalysisCache.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; //? TODO: Caching needs some settings like if it should be used, max cached items, etc public class FunctionAnalysisCache { private static Dictionary functionCacheMap_; private static bool cacheEnabled_; private static object lockObject_ = new(); private FunctionIR function_; //? TODO: Create IAnalysis as a common interface and keep a list, //? then change API to be like GetAsync(), with T being the analysis. private volatile DominatorAlgorithm dominators_; private volatile DominatorAlgorithm postDominators_; private volatile CFGReachability cfgReachability_; private volatile DominanceFrontier dominanceFrontier_; private volatile DominanceFrontier postDominanceFrontier_; static FunctionAnalysisCache() { functionCacheMap_ = new Dictionary(); cacheEnabled_ = true; } private FunctionAnalysisCache(FunctionIR function) { function_ = function; } public static void TestReset() { functionCacheMap_ = new Dictionary(); cacheEnabled_ = true; } public static void DisableCache() { cacheEnabled_ = false; } public static FunctionAnalysisCache Get(FunctionIR function) { lock (lockObject_) { if (functionCacheMap_.TryGetValue(function, out var cache)) { return cache; } cache = new FunctionAnalysisCache(function); if (cacheEnabled_) { functionCacheMap_[function] = cache; } return cache; } } public static bool Remove(FunctionIR function) { lock (lockObject_) { return functionCacheMap_.Remove(function); } } public static void ResetCache() { lock (lockObject_) { functionCacheMap_.Clear(); } } public async Task GetDominatorsAsync() { if (dominators_ == null) { var result = await ComputeDominators().ConfigureAwait(false); if (cacheEnabled_) { Interlocked.Exchange(ref dominators_, result); } return result; } return dominators_; } public async Task GetPostDominatorsAsync() { if (postDominators_ == null) { var result = await ComputePostDominators().ConfigureAwait(false); if (cacheEnabled_) { Interlocked.Exchange(ref postDominators_, result); } return result; } return postDominators_; } public async Task GetDominanceFrontierAsync() { if (dominanceFrontier_ == null) { var result = await ComputeDominanceFrontierAsync().ConfigureAwait(false); if (cacheEnabled_) { Interlocked.Exchange(ref dominanceFrontier_, result); } return result; } return dominanceFrontier_; } public async Task GetPostDominanceFrontierAsync() { if (postDominanceFrontier_ == null) { var result = await ComputePostDominanceFrontierAsync().ConfigureAwait(false); if (cacheEnabled_) { Interlocked.Exchange(ref postDominanceFrontier_, result); } return result; } return postDominanceFrontier_; } public async Task GetReachabilityAsync() { if (cfgReachability_ == null) { var result = await ComputeReachability().ConfigureAwait(false); if (cacheEnabled_) { Interlocked.Exchange(ref cfgReachability_, result); } return result; } return cfgReachability_; } public DominatorAlgorithm GetDominators() { return GetDominatorsAsync().Result; } public DominatorAlgorithm GetPostDominators() { return GetPostDominatorsAsync().Result; } public CFGReachability GetReachability() { return GetReachabilityAsync().Result; } public async Task CacheAll() { var domTask = ComputeDominators(); var postDomTask = ComputePostDominators(); var reachTask = ComputeReachability(); await Task.WhenAll(domTask, postDomTask, reachTask).ConfigureAwait(false); Interlocked.Exchange(ref dominators_, await domTask.ConfigureAwait(false)); Interlocked.Exchange(ref postDominators_, await postDomTask.ConfigureAwait(false)); Interlocked.Exchange(ref cfgReachability_, await reachTask.ConfigureAwait(false)); } public async Task CacheAllAsync() { await CacheAll(); } public void InvalidateAll() { dominators_ = null; postDominators_ = null; cfgReachability_ = null; } private async Task ComputeDominanceFrontierAsync() { var dominatorAlgorithm = await GetDominatorsAsync().ConfigureAwait(false); return new DominanceFrontier(function_, dominatorAlgorithm); } private async Task ComputePostDominanceFrontierAsync() { var dominatorAlgorithm = await GetPostDominatorsAsync().ConfigureAwait(false); return new DominanceFrontier(function_, dominatorAlgorithm); } private Task ComputeDominators() { return Task.Run(() => new DominatorAlgorithm(function_, DominatorAlgorithmOptions.Dominators | DominatorAlgorithmOptions.BuildQueryCache | DominatorAlgorithmOptions.BuildTree)); } private Task ComputePostDominators() { return Task.Run(() => new DominatorAlgorithm(function_, DominatorAlgorithmOptions.PostDominators | DominatorAlgorithmOptions.BuildQueryCache | DominatorAlgorithmOptions.BuildTree)); } private Task ComputeReachability() { return Task.Run(() => new CFGReachability(function_)); } } ================================================ FILE: src/ProfileExplorerCore/Analysis/LoopGraph.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.Core.Analysis; public enum LoopKind { Natural, NonReducible } public sealed class Loop { public Loop() { Blocks = new HashSet(); NestedLoops = new List(); } public LoopKind Kind { get; set; } public int NestingLevel { get; set; } public Loop ParentLoop { get; set; } public HashSet Blocks { get; set; } // public List ExitBlocks { get; set; } // public BlockIR HeaderBlock {get;set;} public List NestedLoops { get; set; } public Loop LoopNestRoot { get { var leader = this; var current = ParentLoop; var visitedBlocks = new List(4); while (current != null) { leader = current; current = current.ParentLoop; // With invalid CFGs this can happen, break the loop. if (visitedBlocks.Contains(current)) { break; } visitedBlocks.Add(current); } return leader; } } public void AddNestedLoop(Loop loop) { if (loop == this) { return; } if (!NestedLoops.Contains(loop)) { NestedLoops.Add(loop); } } } public sealed class LoopGraph { private Dictionary blockLoopMap_; private FunctionIR function_; private List functionLoops_; public LoopGraph(FunctionIR function) { function_ = function; functionLoops_ = new List(); blockLoopMap_ = new Dictionary(); foreach (var block in function_.Blocks) { block.RemoveTag(); } } public bool HasLoops => functionLoops_.Count > 0; public List Loops => functionLoops_; public void FindLoops() { foreach (var block in function_.Blocks) { foreach (var succBlock in block.Successors) { if (succBlock.Number <= block.Number) { MarkLoopBlocks(succBlock.Number, block.Number); } } } } private void MarkLoopBlocks(int startId, int endId) { var loop = new Loop(); functionLoops_.Add(loop); foreach (var block in function_.Blocks) { if (block.Number >= startId && block.Number <= endId) { loop.Blocks.Add(block); var loopTag = block.GetTag(); if (loopTag == null) { loopTag = new LoopBlockTag(loop); block.AddTag(loopTag); } else { var nestedLoop = loopTag.Loop.LoopNestRoot; loop.AddNestedLoop(nestedLoop); loopTag.Loop.ParentLoop = loop; loopTag.NestingLevel++; } } else if (block.Number > endId) { break; } } } } ================================================ FILE: src/ProfileExplorerCore/Analysis/ReferenceFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; //? TODO: Reference finding for symbols withou SSA can use the reachability graph //? to trim down the set of potential definitions. Useful in the text viewer for highlighting and goto def. //? For syms without ref, try to find a block-local source by scanning back //? useful especially for registers //? can be done in parallel too namespace ProfileExplorer.Core.Analysis; [Flags] public enum ReferenceKind { Load = 1 << 0, Store = 1 << 1, Address = 1 << 2, SSA = 1 << 3 } public interface IReachableReferenceFilter { public bool FilterDefinitions { get; set; } public bool FilterUses { get; set; } public bool AcceptReference(IRElement element, IRElement startElement); public bool AcceptDefinitionReference(IRElement element, IRElement startSourceElement); public bool AcceptUseReference(IRElement element, IRElement startDestElement); } public struct Reference : IEquatable { public Reference(IRElement element, ReferenceKind kind) { Element = element; Kind = kind; } public IRElement Element { get; set; } public ReferenceKind Kind { get; set; } public bool Equals(Reference other) { return Equals(Element, other.Element) && Kind == other.Kind; } public override bool Equals(object obj) { return obj is Reference other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(Element, (int)Kind); } } public sealed class ReferenceFinder { private FunctionIR function_; private ICompilerIRInfo irInfo_; private IReachableReferenceFilter referenceFilter_; private Dictionary ssaDefTagMap_; public ReferenceFinder(FunctionIR function, ICompilerIRInfo irInfo = null, IReachableReferenceFilter referenceFilter = null) { function_ = function; irInfo_ = irInfo; referenceFilter_ = referenceFilter; } public static List FindSSAUses(OperandIR op) { var list = new List(); FindSSAUses(op, list); return list; } public static List FindSSAUses(InstructionIR instr) { var list = new List(); if (instr.Destinations.Count == 0) { return list; } FindSSAUses(instr.Destinations[0], list); return list; } public static SSADefinitionTag GetSSADefinitionTag(OperandIR op) { var defLinkTag = op.GetTag(); if (defLinkTag != null) { return defLinkTag.Definition; } if (op.IsIndirection) { return GetSSADefinitionTag(op.IndirectionBaseValue); } return op.GetTag(); } public static IRElement GetSSADefinition(OperandIR op) { var tag = GetSSADefinitionTag(op); return tag != null ? tag.OwnerElement : null; } public static InstructionIR GetSSADefinitionInstruction(OperandIR op) { var tag = GetSSADefinitionTag(op); return tag != null ? tag.DefinitionInstruction : null; } public static int? GetSSADefinitionId(OperandIR op) { var tag = GetSSADefinitionTag(op); return tag?.DefinitionId; } public static void FindSSAUses(OperandIR op, List list) { foreach (var use in EnumerateSSAUses(op)) { list.Add(use); } } private static IEnumerable EnumerateSSAUses(OperandIR op) { // If it's a definition operand, enumerate the SSA uses. var ssaDefTag = op.GetTag(); if (ssaDefTag != null) { foreach (var use in ssaDefTag.Users) { yield return use.OwnerElement; } } // For source operands, go to the linked definition SSA tag. var ssaDefUseTag = op.GetTag(); if (ssaDefUseTag != null) { foreach (var use in ssaDefUseTag.Definition.Users) { yield return use.OwnerElement; } } } //? TODO: Should be moved to the SimilarValueFinder public IRElement FindEquivalentValue(IRElement element, bool onlySSA = false) { //? by querying an IR-level interface for "equivalent symbols" if (element.ParentFunction == function_) { return element; } //? TODO: Handle instructions if (!(element is OperandIR op)) { return null; } // If it's an SSA value, try to find an operand with the same def. ID. int? defId = GetSSADefinitionId(op); if (defId.HasValue) { var foundDefOp = FindOperandWithSSADefinitionID(defId.Value); // If found, also check that the symbol name is the same. if (foundDefOp != null && IsSameSymbolOperand(op, foundDefOp)) { if (foundDefOp.Role == OperandRole.Destination) { return foundDefOp; } if (op.Role == OperandRole.Source) { // Try to find a matching source operand by looking // for an SSA use that is found in a block with the same ID. var matchingOp = FindBestMatchingOperand(EnumerateSSAUses(foundDefOp), op, false); if (matchingOp != null) { return matchingOp; } } return foundDefOp; } } // For non-SSA values, search the entire function // for a symbol with the same name and type. //? TODO: inefficient, use a symbol table indexed by name (PrecomputeAllReferences) return onlySSA ? null : FindBestMatchingOperand(EnumerateAllOperands(), op); } public IEnumerable EnumerateAllOperands(bool includeDestinations = true, bool includeSources = true) { foreach (var block in function_.Blocks) { foreach (var tuple in block.Tuples) { if (!(tuple is InstructionIR instr)) { continue; } if (includeDestinations) { foreach (var destOp in instr.Destinations) { yield return destOp; } } if (includeSources) { foreach (var sourceOp in instr.Sources) { yield return sourceOp; } } } } } public OperandIR FindOperandWithSSADefinitionID(int defId) { // Build a cache mapping the definition IDs to the tag // to speed up lookup and avoid n-squared behavior. if (ssaDefTagMap_ == null) { ssaDefTagMap_ = new Dictionary(); foreach (var destOp in EnumerateAllOperands(true, false)) { var ssaDefTag = GetSSADefinitionTag(destOp); if (ssaDefTag != null) { ssaDefTagMap_[ssaDefTag.DefinitionId] = ssaDefTag; } } } return ssaDefTagMap_.TryGetValue(defId, out var tag) ? tag.DefinitionOperand : null; } public List FindAllSSAUsesOrReferences(IRElement element) { if (element is OperandIR op) { var ssaDef = GetSSADefinition(op); if (ssaDef != null) { var list = new List {new(ssaDef, ReferenceKind.SSA)}; var useList = FindSSAUses(op); useList.ForEach(item => list.Add(new Reference(item, ReferenceKind.SSA))); return list; } } return FindAllReferences(element); } public List FindAllReferences(IRElement element, bool includeSSAUses = true, Func filterAction = null) { var list = new List(); if (!(element is OperandIR op)) { return list; } foreach (var block in function_.Blocks) { foreach (var tuple in block.Tuples) { if (!(tuple is InstructionIR instr)) { continue; } foreach (var destOp in instr.Destinations) { var comparedOp = destOp; var refKind = ReferenceKind.Store; if (destOp.IsIndirection) { comparedOp = destOp.IndirectionBaseValue; refKind = ReferenceKind.Load; } if (IsSameSymbolOperand(comparedOp, op)) { CreateReference(destOp, refKind, list, filterAction); } } foreach (var sourceOp in instr.Sources) { var comparedOp = sourceOp; if (sourceOp.IsIndirection) { comparedOp = sourceOp.IndirectionBaseValue; } if (IsSameSymbolOperand(comparedOp, op)) { var refKind = comparedOp.IsAddress ? ReferenceKind.Address : ReferenceKind.Load; CreateReference(sourceOp, refKind, list, filterAction); } } } } // Also go over the function parameters. foreach (var paramOp in function_.Parameters) { if (IsSameSymbolOperand(paramOp, op)) { CreateReference(paramOp, ReferenceKind.Store, list, filterAction); } } if (includeSSAUses) { var useList = FindSSAUses(op); useList.ForEach(item => list.Add(new Reference(item, ReferenceKind.SSA))); } return list; } public List FindAllStores(IRElement element) { return FindAllReferences(element, false, (element, kind) => kind == ReferenceKind.Store); } public List FindAllLoads(IRElement element) { return FindAllReferences(element, false, (element, kind) => kind == ReferenceKind.Load); } public List FindAllUses(OperandIR op) { var list = new List(); return FindAllUses(op, list); } public List FindAllUses(InstructionIR instr) { var list = new List(); if (instr.Destinations.Count == 0) { return list; } FindAllUses(instr.Destinations[0], list); return list; } public IRElement FindSingleDefinition(IRElement element) { // Try to use SSA info first. if (element is OperandIR op) { var ssaDefOp = GetSSADefinition(op); if (ssaDefOp != null) { return ssaDefOp; } } //? TODO: Very inefficient var list = FindAllDefinitions(element); if (list.Count == 1) { return list[0]; } return null; } public List FindAllDefinitions(IRElement element) { var list = new List(); // Try to use SSA info first. if (element is OperandIR op) { var ssaDefOp = GetSSADefinition(op); if (ssaDefOp != null) { list.Add(ssaDefOp); return list; } if (op.IsIndirection) { // Search for the base operand of an indirection. return FindAllDefinitions(op.IndirectionBaseValue); } } //? TODO: Very inefficient var refList = FindAllStores(element); foreach (var reference in refList) { if (AcceptReferenceForSource(reference.Element, element)) { list.Add(reference.Element); } } return list; } public IRElement GetSingleUse(OperandIR op) { var ssaDefTag = op.GetTag(); if (ssaDefTag != null) { if (ssaDefTag.HasSingleUser) { return ssaDefTag.Users[0].OwnerElement; } return null; } var useList = FindAllUses(op); if (useList.Count == 1) { return useList[0]; } return null; } public bool IsSameSymbolOperand(OperandIR op, OperandIR searchedOp, bool checkType = false, bool exactCheck = false) { if (!AreSymbolOperandsCompatible(op, searchedOp)) { return false; } if (op.HasName) { // Check if symbol names are the same. if (!op.NameValue.Span.Equals(searchedOp.NameValue.Span, StringComparison.Ordinal)) { // Not same symbol name, but the IR may define names // that should be considered to represent the same symbol. if (irInfo_ == null || !irInfo_.OperandsReferenceSameSymbol(op, searchedOp, exactCheck)) { return false; } // Check for same type if requested. return !checkType || op.Type.Equals(searchedOp.Type); } // The same symbol name, but the IR may define names // that should not be considered the same symbol (different offsets, for ex.) if (irInfo_ != null && !irInfo_.OperandsReferenceSameSymbol(op, searchedOp, exactCheck)) { return false; } return true; } return false; } private IRElement FindBestMatchingOperand(IEnumerable candidates, OperandIR op, bool checkSymbol = true) { // Try to find a matching source operand by looking // for an SSA use that is found in a block with the same ID. var opBlock = op.ParentBlock; OperandIR firstUse = null; OperandIR bestUse = null; int bestUseDistance = int.MaxValue; foreach (var useElement in candidates) { if (!(useElement is OperandIR useOp)) { continue; } if (checkSymbol && !IsSameSymbolOperand(useOp, op)) { continue; } if (useOp.Role == op.Role && IsSameBlock(useOp.ParentBlock, opBlock)) { // If in the same block, pick the use that is the closest // to the original one based on the index in the block. int opBlockIndex = op.ParentTuple.IndexInBlock; int useBlockIndex = useOp.ParentTuple.IndexInBlock; int distance = Math.Abs(useBlockIndex - opBlockIndex); if (distance < bestUseDistance) { bestUse = useOp; bestUseDistance = distance; } } firstUse ??= useOp; } // Return first use if one in the same block not found. if (bestUse != null) { return bestUse; } if (firstUse != null) { return firstUse; } return null; } private bool IsSameBlock(BlockIR firstBlock, BlockIR secondBlock) { if (firstBlock == secondBlock || firstBlock.Number == secondBlock.Number) { return true; } if (firstBlock.HasLabel && secondBlock.HasLabel) { return firstBlock.Label.Name == secondBlock.Label.Name; } return false; } private void CreateReference(OperandIR operand, ReferenceKind refKind, List list, Func filterAction) { if (filterAction != null) { if (!filterAction(operand, refKind)) { return; } } list.Add(new Reference(operand, refKind)); } private List FindAllUses(OperandIR op, List list) { foreach (var use in EnumerateSSAUses(op)) { list.Add(use); } // If there is no SSA info, collect all the symbol loads. if (list.Count == 0 && op.GetTag() == null) { var allLoads = FindAllLoads(op); foreach (var reference in allLoads) { if (AcceptReferenceForDestination(reference.Element, op)) { list.Add(reference.Element); } } } return list; } private bool AreSymbolOperandsCompatible(OperandIR op1, OperandIR op2) { if (op1.Kind == op2.Kind) { return true; } if (op1.Kind == OperandKind.Variable || op1.Kind == OperandKind.Address) { return op2.Kind == OperandKind.Variable || op2.Kind == OperandKind.Address; } return false; } private bool AcceptReference(IRElement element, IRElement startElement) { if (referenceFilter_ != null) { return referenceFilter_.AcceptReference(element, startElement); } return true; } private bool AcceptReferenceForSource(IRElement element, IRElement startSourceElement) { if (referenceFilter_ != null) { return referenceFilter_.AcceptDefinitionReference(element, startSourceElement); } return true; } private bool AcceptReferenceForDestination(IRElement element, IRElement startDestElement) { if (referenceFilter_ != null) { return referenceFilter_.AcceptUseReference(element, startDestElement); } return true; } } ================================================ FILE: src/ProfileExplorerCore/Analysis/SimilarValueFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Analysis; public class SimilarValueFinder { private FunctionIR function_; private Dictionary ssaDefTable_; public SimilarValueFinder(FunctionIR function) { function_ = function; ssaDefTable_ = new Dictionary(); BuildSSADefinitionTable(); } public InstructionIR Find(InstructionIR instr) { if (instr.Destinations.Count == 0) { return null; } int? ssaDefId = ReferenceFinder.GetSSADefinitionId(instr.Destinations[0]); if (ssaDefId.HasValue && ssaDefTable_.TryGetValue(ssaDefId.Value, out var similarInstr)) { return similarInstr; } return null; } private void BuildSSADefinitionTable() { // Precompute a table mapping each SSA definition ID to its definition. foreach (var block in function_.Blocks) { foreach (var tuple in block.Tuples) { if (tuple is InstructionIR instr && instr.Destinations.Count > 0) { int? ssaDefId = ReferenceFinder.GetSSADefinitionId(instr.Destinations[0]); if (ssaDefId.HasValue) { ssaDefTable_[ssaDefId.Value] = instr; } } } } } private bool IsSimilarInstruction(InstructionIR instr, InstructionIR otherInstr) { return instr.Opcode.Equals(otherInstr.Opcode) && instr.Destinations.Count == otherInstr.Destinations.Count && instr.Sources.Count == otherInstr.Sources.Count; } } ================================================ FILE: src/ProfileExplorerCore/Binary/Disassembler.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using System.Security; using System.Text; using System.Threading.Tasks; using Microsoft.Win32.SafeHandles; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Binary; public delegate void DisassemblerProgressHandler(DisassemblerProgress info); public enum DisassemblerStage { Disassembling, PostProcessing } public interface IDisassembler { DisassemberResult Disassemble(string imagePath, ICompilerInfoProvider compilerInfo, DisassemblerProgressHandler progressCallback = null, CancelableTask cancelableTask = null); Task DisassembleAsync(string imagePath, ICompilerInfoProvider compilerInfo, DisassemblerProgressHandler progressCallback = null, CancelableTask cancelableTask = null); bool EnsureDisassemblerAvailable(); } public class DisassemblerOptions { public bool IncludeBytes { get; set; } } public class DisassemblerProgress { public DisassemblerProgress(DisassemblerStage stage) { Stage = stage; } public DisassemblerStage Stage { get; set; } public int Total { get; set; } public int Current { get; set; } } public class DisassemberResult { public DisassemberResult(string disassemblyPath, string debugInfoFilePath) { DisassemblyPath = disassemblyPath; DebugInfoFilePath = debugInfoFilePath; } public string DisassemblyPath { get; set; } public string DebugInfoFilePath { get; set; } } public class Disassembler : IDisposable { public delegate string SymbolNameResolverDelegate(long address); private PEBinaryInfoProvider peInfo_; private List<(ReadOnlyMemory Data, long StartRVA)> codeSectionData_; private long baseAddress_; private Machine architecture_; private IDebugInfoProvider debugInfo_; private Interop.DisassemblerHandle disasmHandle_; private bool checkValidCallAddress_; private SymbolNameResolverDelegate symbolNameResolver_; private FunctionNameFormatter funcNameFormatter_; private object sectionLock_; private Disassembler(Machine architecture, PEBinaryInfoProvider peInfo, long baseAddress = 0, IDebugInfoProvider debugInfo = null, FunctionNameFormatter funcNameFormatter = null, SymbolNameResolverDelegate symbolNameResolver = null) { peInfo_ = peInfo; architecture_ = architecture; baseAddress_ = baseAddress; debugInfo_ = debugInfo; funcNameFormatter_ = funcNameFormatter; symbolNameResolver_ = symbolNameResolver; sectionLock_ = new object(); Initialize(true); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public static Disassembler CreateForBinary(string binaryFilePath, IDebugInfoProvider debugInfo, FunctionNameFormatter funcNameFormatter) { var peInfo = new PEBinaryInfoProvider(binaryFilePath); if (!peInfo.Initialize()) { return null; } var binaryInfo = peInfo.BinaryFileInfo; return new Disassembler(binaryInfo.Architecture, peInfo, binaryInfo.ImageBase, debugInfo, funcNameFormatter); } public static Disassembler CreateForMachine(IDebugInfoProvider debugInfo, FunctionNameFormatter funcNameFormatter) { return new Disassembler(debugInfo.Architecture.Value, null, 0, debugInfo, funcNameFormatter); } public void UseSymbolNameResolver(SymbolNameResolverDelegate symbolNameResolver) { symbolNameResolver_ = symbolNameResolver; checkValidCallAddress_ = false; } public string DisassembleToText(FunctionDebugInfo funcInfo) { return DisassembleToText(funcInfo.StartRVA, funcInfo.Size); } public string DisassembleToText(byte[] data, long startRVA) { codeSectionData_ = new List<(ReadOnlyMemory Data, long StartRVA)> {(data.AsMemory(), startRVA)}; string result = DisassembleToText(startRVA, data.Length); codeSectionData_ = null; return result; } public string DisassembleToText(long startRVA, long size) { if (startRVA == 0 || size == 0) { return ""; } var builder = new StringBuilder((int)(size / 4) + 1); try { DisassembleInstructions(startRVA, size, startRVA + baseAddress_, (instr) => { string addressString = $"{instr.Address:X}: "; builder.Append(addressString); int startIndex = 0; bool appendBytes = false; //? TODO: Add UI option if (appendBytes) { startIndex += AppendBytes(instr, startIndex, builder); builder.Append(" "); } AppendMnemonic(instr, builder); builder.Append(" "); AppendOperands(instr, startRVA, size, builder); builder.AppendLine(); if (appendBytes) { // For longer instructions, append up to 6 bytes per line. while (startIndex < instr.Size) { builder.Append(' ', addressString.Length); // Align right. startIndex += AppendBytes(instr, startIndex, builder); builder.AppendLine(); } } }); } catch (Exception ex) { #if DEBUG Trace.TraceError($"Failed to disassemble code at RVA {startRVA}, size {size}: {ex.Message}"); #endif return ""; } return builder.ToString(); } private void Initialize(bool checkValidCallAddress) { checkValidCallAddress_ = checkValidCallAddress; disasmHandle_ = Interop.Create(architecture_); } private unsafe void AppendMnemonic(Interop.Instruction instr, StringBuilder builder) { byte* letterPtr = instr.Mnemonic; int index = 0; while (index < Interop.Instruction.MnemonicLength && letterPtr[index] != 0) { builder.Append((char)letterPtr[index]); index++; } } private unsafe void AppendOperands(Interop.Instruction instr, long startRVA, long size, StringBuilder builder) { bool isArm = architecture_ == Machine.Arm || architecture_ == Machine.Arm64; bool isJump = false; bool sawBracket = false; bool lookupName = ShouldLookupAddressByName(instr, ref isJump); byte* letterPtr = instr.Operand; int index = 0; while (index < Interop.Instruction.OperandLength && letterPtr[index] != 0) { char letter = (char)letterPtr[index]; if (lookupName) { // Try to replace a call target address by the function name. int hexLength = 0; bool skippedSharp = false; long hexValue = 0; if (letter == '[') { sawBracket = true; // Reject lookups for call ptr [rip + 0xABCD] and similar. } else if (letter == '#' && isArm && !sawBracket) { hexLength = FindHexNumber(letterPtr, index + 1, out hexValue); // Skip over # skippedSharp = true; } else if (letter == '0' && !sawBracket) { hexLength = FindHexNumber(letterPtr, index, out hexValue); } if (IsValidCallAddress(hexLength, hexValue)) { long rva = hexValue - baseAddress_; bool replaced = false; // For jumps, use the name only if it's to another function. if (!isJump || rva < startRVA || rva >= startRVA + size) { replaced = TryAppendFunctionName(builder, rva); } if (!replaced) { if (skippedSharp) builder.Append('#'); builder.Append($"0x{hexValue:X}"); } index += hexLength + (skippedSharp ? 1 : 0); continue; } } builder.Append(letter); index++; } } private bool IsValidCallAddress(int hexLength, long hexValue) { if (hexLength == 0) { return false; } if (!checkValidCallAddress_) { return true; } long rva = hexValue - baseAddress_; return !FindCodeSection(rva).Data.IsEmpty; } private bool TryAppendFunctionName(StringBuilder builder, long rva) { if (symbolNameResolver_ != null) { string name = symbolNameResolver_(rva); if (!string.IsNullOrEmpty(name)) { builder.Append(name); return true; } return false; } if (debugInfo_ != null) { var func = FindFunctionByRva(rva); if (func != null) { if (funcNameFormatter_ != null) { builder.Append(funcNameFormatter_(func.Name)); } else { builder.Append(func.Name); } return true; } } return false; } private FunctionDebugInfo FindFunctionByRva(long rva) { if (debugInfo_ != null) { return debugInfo_.FindFunctionByRVA(rva); } return null; } private bool ShouldLookupAddressByName(Interop.Instruction instr, ref bool isJump) { if (debugInfo_ == null && symbolNameResolver_ == null) { return false; } switch (architecture_) { case Machine.I386: case Machine.Amd64: { if (x86Opcodes.GetOpcodeInfo(instr.MnemonicString, out var info)) { isJump = info.Kind == InstructionKind.Goto; return info.Kind == InstructionKind.Call || isJump; } return false; } case Machine.Arm: case Machine.Arm64: { if (ARM64Opcodes.GetOpcodeInfo(instr.MnemonicString, out var info)) { isJump = info.Kind == InstructionKind.Goto; return info.Kind == InstructionKind.Call || isJump; } return false; } } return false; } private unsafe int FindHexNumber(byte* letterPtr, int index, out long value) { // Expect star with 0x and skip. if (letterPtr[index] != '0' || index + 1 >= Interop.Instruction.OperandLength || !(letterPtr[index + 1] == 'x' || letterPtr[index + 1] == 'X')) { value = 0; return 0; } int startIndex = index; index += 2; value = 0; while (index < Interop.Instruction.OperandLength && letterPtr[index] != 0) { char c = (char)letterPtr[index]; if (c >= '0' && c <= '9') { value = value << 4 | c - '0'; index++; } else if (c >= 'a' && c <= 'f') { value = value << 4 | 10 + (c - 'a'); index++; } else if (c >= 'A' && c <= 'F') { value = value << 4 | 10 + (c - 'A'); index++; } else break; } int length = index - startIndex; return length > 3 ? length : 0; } private unsafe int AppendBytes(Interop.Instruction instr, int startIndex, StringBuilder builder) { // Append at most 6 bytes per line. int count = Math.Min(6, instr.Size - startIndex); byte* bytes = instr.Bytes; switch (count) { case 0: { return 0; } case 1: { builder.Append($"{bytes[0]:X02} "); break; } case 2: { builder.Append($"{bytes[0]:X02} {bytes[1]:X02} "); break; } case 3: { builder.Append($"{bytes[0]:X02} {bytes[1]:X02} {bytes[2]:X02} "); break; } case 4: { builder.Append($"{bytes[0]:X02} {bytes[1]:X02} {bytes[2]:X02} {bytes[3]:X02} "); break; } case 5: { builder.Append($"{bytes[0]:X02} {bytes[1]:X02} {bytes[2]:X02} {bytes[3]:X02} {bytes[4]:X02} "); break; } case 6: { builder.Append($"{bytes[0]:X02} {bytes[1]:X02} {bytes[2]:X02} {bytes[3]:X02} {bytes[4]:X02} {bytes[5]:X02}"); break; } } return count; } private (ReadOnlyMemory Data, long StartRVA) FindCodeSection(long rva) { // Load code section on-demand to avoid wasting time and memory // for binaries that are not dot disassembled. if (codeSectionData_ == null) { lock (sectionLock_) { if (codeSectionData_ == null) { var codeSections = peInfo_.CodeSectionHeaders; codeSectionData_ = new List<(ReadOnlyMemory Data, long StartRVA)>(); foreach (var section in codeSections) { codeSectionData_.Add((peInfo_.GetSectionData(section), section.VirtualAddress)); } } } } foreach (var section in codeSectionData_) { if (rva >= section.StartRVA && rva < section.StartRVA + section.Data.Length) { return section; } } return (ReadOnlyMemory.Empty, 0); } private unsafe void DisassembleInstructions(long startRVA, long size, long startAddress, Action action) { var codeSection = FindCodeSection(startRVA); if (codeSection.Data.IsEmpty) { Trace.WriteLine($"Invalid disassembler RVA/size {startRVA}/{size}"); return; } // Allocate a buffer for storing the instruction, // gets reused during iteration. using var instrBuffer = Interop.AllocateInstruction(disasmHandle_); long offset = startRVA - codeSection.StartRVA; using var dataBuffer = codeSection.Data.Pin(); IntPtr dataBufferPtr = (IntPtr)dataBuffer.Pointer; // Disassemble the entire range of the code data buffer. IntPtr dataIteratorPtr = (IntPtr)(dataBufferPtr.ToInt64() + offset); IntPtr dataEndPtr = (IntPtr)(dataBufferPtr.ToInt64() + offset + size); while (dataIteratorPtr.ToInt64() < dataEndPtr.ToInt64()) { IntPtr remainingLength = (IntPtr)(dataEndPtr.ToInt64() - dataIteratorPtr.ToInt64()); // Handles one instruction at a time. // dataIteratorPtr is being incremented by the native API. if (Interop.Iterate(disasmHandle_, ref dataIteratorPtr, ref remainingLength, ref startAddress, instrBuffer)) { IntPtr instrPtr = instrBuffer.DangerousGetHandle(); if (instrPtr == IntPtr.Zero) { return; } var instruction = (Interop.Instruction)Marshal.PtrToStructure(instrPtr, typeof(Interop.Instruction)); action(instruction); } else { break; } } } private void Dispose(bool disposing) { disasmHandle_?.Dispose(); disasmHandle_ = null; peInfo_?.Dispose(); peInfo_ = null; if (disposing) { GC.SuppressFinalize(this); } } private static class Interop { public enum Architecture { Arm, Arm64, Mips, X86, PowerPc, Sparc, SystemZ, XCore, M68K, Tms320C64X, M680X, Evm } public enum CapstoneResultCode { Ok = 0, OutOfMemory, UnsupportedDisassembleArchitecture, InvalidHandle1, InvalidHandle2, UnsupportedDisassembleMode, InvalidOption, UnsupportedInstructionDetail, UninitializedMemoryManagement, UnsupportedVersion, UnSupportedDietModeOperation, UnsupportedSkipDataModeOperation, UnSupportedX86AttSyntax, UnSupportedX86IntelSyntax, UnSupportedX86MasmSyntax } [Flags] public enum DisassembleMode { LittleEndian = 0, Arm = 0, Bit16 = 1 << 1, Bit32 = 1 << 2, Bit64 = 1 << 3, ArmThumb = 1 << 4, ArmCortexM = 1 << 5, ArmV8 = 1 << 6, MipsMicro = 1 << 4, Mips3 = 1 << 5, Mips32R6 = 1 << 6, Mips2 = 1 << 7, SparcV9 = 1 << 4, PowerPcQuadProcessingExtensions = 1 << 4, M68K000 = 1 << 1, M68K010 = 1 << 2, M68K020 = 1 << 3, M68K030 = 1 << 4, M68K040 = 1 << 5, M68K060 = 1 << 6, BigEndian = 1 << 31, Mips32 = Bit32, Mips64 = Bit64, M680X6301 = 1 << 1, M680X6309 = 1 << 2, M680X6800 = 1 << 3, M680X6801 = 1 << 4, M680X6805 = 1 << 5, M680X6808 = 1 << 6, M680X6809 = 1 << 7, M680X6811 = 1 << 8, M680XCpu12 = 1 << 9, M680XHcS08 = 1 << 10 } public enum DisassemblerOptionType { None = 0, SetSyntax, SetInstructionDetails, SetDisassembleMode, SetMemory, SetSkipData, SetSkipDataConfig, SetMnemonic, SetUnsigned } public enum DisassemblerOptionValue { Disable = 0, Enable = 3, UseDefaultSyntax = 0, UseIntelSyntax, UseAttSyntax, CS_OPT_SYNTAX_NOREGNAME, UseMasmSyntax } [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_close")] public static extern CapstoneResultCode CloseDisassembler(ref IntPtr pDissembler); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_open")] public static extern CapstoneResultCode CreateDisassembler(Architecture architecture, DisassembleMode disassembleMode, ref IntPtr pDisassembler); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_malloc")] public static extern IntPtr CreateInstruction(DisassemblerHandle hDisassembler); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_disasm")] public static extern IntPtr Disassemble(DisassemblerHandle hDisassembler, IntPtr pCode, IntPtr codeSize, long startingAddress, IntPtr count, ref IntPtr pInstructions); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_free")] public static extern void FreeInstructions(IntPtr pInstructions, IntPtr count); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_regs_access")] public static extern CapstoneResultCode GetAccessedRegisters(DisassemblerHandle hDisassembler, InstructionHandle hInstruction, short[] readRegisters, ref byte readRegistersCount, short[] writtenRegisters, ref byte writtenRegistersCount); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_group_name")] public static extern IntPtr GetInstructionGroupName(DisassemblerHandle hDisassembler, int instructionGroupId); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_errno")] public static extern CapstoneResultCode GetLastErrorCode(DisassemblerHandle hDisassembler); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_reg_name")] public static extern IntPtr GetRegisterName(DisassemblerHandle hDisassembler, int registerId); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_version")] public static extern int GetVersion(ref int majorVersion, ref int minorVersion); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_disasm_iter")] [return: MarshalAs(UnmanagedType.I1)] public static extern bool Iterate(DisassemblerHandle hDisassembler, ref IntPtr pCode, ref IntPtr codeSize, ref long address, InstructionHandle hInstruction); [SuppressUnmanagedCodeSecurity] [DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Ansi, EntryPoint = "LoadLibraryA", SetLastError = true)] public static extern IntPtr LoadLibrary(string libraryFilePath); [SuppressUnmanagedCodeSecurity] [DllImport("capstone.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "cs_option")] public static extern CapstoneResultCode SetDisassemblerOption(DisassemblerHandle hDisassembler, DisassemblerOptionType optionType, IntPtr optionValue); public static DisassemblerHandle Create(Architecture architecture, DisassembleMode mode) { IntPtr disasmPtr = IntPtr.Zero; var resultCode = CreateDisassembler(architecture, mode, ref disasmPtr); if (resultCode == CapstoneResultCode.Ok) { var handle = new DisassemblerHandle(disasmPtr); //SetDisassemblerOption(handle, DisassemblerOptionType.SetSkipData, (IntPtr)DisassemblerOptionValue.Enable); return handle; } Trace.WriteLine($"Failed to create Capstone disassembler: {resultCode}"); return null; } public static DisassemblerHandle Create(Machine architecture) { return architecture switch { Machine.I386 => Create(Architecture.X86, DisassembleMode.Bit32), Machine.Amd64 => Create(Architecture.X86, DisassembleMode.Bit64), Machine.Arm => Create(Architecture.Arm, DisassembleMode.Arm), Machine.Arm64 => Create(Architecture.Arm64, DisassembleMode.Arm), _ => throw new NotSupportedException("Unsupported architecture!") }; } public static InstructionHandle AllocateInstruction(DisassemblerHandle handle) { return new InstructionHandle(CreateInstruction(handle)); } // Must be kept in sync with the definition of cs_insn from Capstone. [StructLayout(LayoutKind.Explicit, Size = 256)] public unsafe struct Instruction { public const int MnemonicLength = 32; public const int OperandLength = 160; [FieldOffset(0)] public int Id; [FieldOffset(8)] public long AliasId; [FieldOffset(16)] public long Address; [FieldOffset(24)] public short Size; [FieldOffset(26)] public fixed byte Bytes[24]; [FieldOffset(50)] public fixed byte Mnemonic[32]; [FieldOffset(82)] public fixed byte Operand[160]; [FieldOffset(242)] public bool IsAlias; [FieldOffset(243)] public bool UsesAliasDetails; [FieldOffset(248)] public IntPtr Details; public byte[] BytesArray { get { fixed (byte* pinned = Bytes) { byte[] bytes = new byte[Size]; Marshal.Copy((IntPtr)pinned, bytes, 0, Size); return bytes; } } } public string MnemonicString { get { fixed (byte* pinned = Mnemonic) { return Marshal.PtrToStringAnsi((IntPtr)pinned); } } } public string OperandString { get { fixed (byte* pinned = Operand) { return Marshal.PtrToStringAnsi((IntPtr)pinned); } } } } public class DisassemblerHandle : SafeHandleMinusOneIsInvalid { public DisassemblerHandle(IntPtr pDisassembler) : base(true) { handle = pDisassembler; } protected override bool ReleaseHandle() { var resultCode = CloseDisassembler(ref handle); handle = IntPtr.Zero; return resultCode == CapstoneResultCode.Ok; } } public class InstructionHandle : SafeHandleZeroOrMinusOneIsInvalid { public InstructionHandle(IntPtr pInstruction) : base(true) { handle = pInstruction; } protected override bool ReleaseHandle() { FreeInstructions(handle, 1); handle = IntPtr.Zero; return true; } } } } ================================================ FILE: src/ProfileExplorerCore/Binary/DotNetDebugInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection.PortableExecutable; using Microsoft.Diagnostics.Symbols; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Binary; //? Provider ASM should return instance instead of JSONDebug public class DotNetDebugInfoProvider : IDebugInfoProvider { private Dictionary functionMap_; private List functions_; private Machine architecture_; private Dictionary> methodILNativeMap_; private Dictionary methodCodeMap_; private bool hasManagedSymbolFileFailure_; public DotNetDebugInfoProvider(Machine architecture) { architecture_ = architecture; functionMap_ = new Dictionary(); functions_ = new List(); methodILNativeMap_ = new Dictionary>(); } public SymbolFileDescriptor ManagedSymbolFile { get; set; } public string ManagedAsmFilePath { get; set; } public Machine? Architecture => architecture_; public SymbolFileSourceSettings SymbolSettings { get; set; } public bool AnnotateSourceLocations(FunctionIR function, IRTextFunction textFunc) { return AnnotateSourceLocations(function, textFunc.Name); } public bool AnnotateSourceLocations(FunctionIR function, FunctionDebugInfo funcInfo) { var metadataTag = function.GetTag(); if (metadataTag == null) { return false; } if (!EnsureHasSourceLines(funcInfo)) { return false; } foreach (var pair in metadataTag.OffsetToElementMap) { var lineInfo = funcInfo.FindNearestLine(pair.Key); if (!lineInfo.IsUnknown) { var locationTag = pair.Value.GetOrAddTag(); locationTag.Reset(); // Tag may be already populated. locationTag.Line = lineInfo.Line; locationTag.Column = lineInfo.Column; } } return true; } public FunctionDebugInfo FindFunction(string functionName) { return functionMap_.GetValueOr(functionName, FunctionDebugInfo.Unknown); } public IEnumerable EnumerateFunctions() { return functions_; } public List GetSortedFunctions() { return functions_; } public FunctionDebugInfo FindFunctionByRVA(long rva) { return FunctionDebugInfo.BinarySearch(functions_, rva); } public SourceFileDebugInfo FindFunctionSourceFilePath(IRTextFunction textFunc) { return FindFunctionSourceFilePath(textFunc.Name); } public SourceFileDebugInfo FindFunctionSourceFilePath(string functionName) { if (functionMap_.TryGetValue(functionName, out var funcInfo)) { return GetSourceFileInfo(funcInfo); } return SourceFileDebugInfo.Unknown; } public SourceFileDebugInfo FindSourceFilePathByRVA(long rva) { var funcInfo = FindFunctionByRVA(rva); if (EnsureHasSourceLines(funcInfo)) { return GetSourceFileInfo(funcInfo); } return SourceFileDebugInfo.Unknown; } public SourceLineDebugInfo FindSourceLineByRVA(long rva, bool includeInlinees) { var funcInfo = FindFunctionByRVA(rva); if (EnsureHasSourceLines(funcInfo)) { long offset = rva - funcInfo.StartRVA; return funcInfo.FindNearestLine(offset); } return SourceLineDebugInfo.Unknown; } public void Unload() { } public bool LoadDebugInfo(DebugFileSearchResult debugFile, IDebugInfoProvider other = null) { return true; } public void Dispose() { } public bool PopulateSourceLines(FunctionDebugInfo funcInfo) { return true; } public void UpdateArchitecture(Machine architecture) { if (architecture_ == Machine.Unknown) { architecture_ = architecture; } } public MethodCode FindMethodCode(FunctionDebugInfo funcInfo) { return methodCodeMap_?.GetValueOrNull(funcInfo.RVA); } public void AddFunctionInfo(FunctionDebugInfo funcInfo) { functions_.Add(funcInfo); functionMap_[funcInfo.Name] = funcInfo; } public void AddMethodILToNativeMap(FunctionDebugInfo functionDebugInfo, List<(int ILOffset, int NativeOffset)> ilOffsets) { methodILNativeMap_[functionDebugInfo] = ilOffsets; } public void LoadingCompleted() { functions_.Sort(); } public void AddMethodCode(long codeAddress, MethodCode code) { methodCodeMap_ ??= new Dictionary(); methodCodeMap_[codeAddress] = code; } public bool AnnotateSourceLocations(FunctionIR function, string functionName) { var funcInfo = FindFunction(functionName); if (funcInfo == null) { return false; } return AnnotateSourceLocations(function, funcInfo); } public bool LoadDebugInfo(string debugFilePath, IDebugInfoProvider other = null) { return true; } private bool EnsureHasSourceLines(FunctionDebugInfo functionDebugInfo) { if (functionDebugInfo == null || functionDebugInfo.IsUnknown) { return false; } if (functionDebugInfo.HasSourceLines) { return true; // Already populated. } if (ManagedSymbolFile == null || hasManagedSymbolFileFailure_) { return false; // Previous attempt failed. } // Locate the managed debug file. var options = SymbolSettings != null ? SymbolSettings : CoreSettingsProvider.SymbolSettings; if (File.Exists(ManagedSymbolFile.FileName)) { options.InsertSymbolPath(ManagedSymbolFile.FileName); } string symbolSearchPath = PDBDebugInfoProvider.ConstructSymbolSearchPath(options); using var logWriter = new StringWriter(); using var symbolReader = new SymbolReader(logWriter, symbolSearchPath); symbolReader.SecurityCheck += s => true; // Allow symbols from "unsafe" locations. string debugFile = symbolReader.FindSymbolFilePath(ManagedSymbolFile.FileName, ManagedSymbolFile.Id, ManagedSymbolFile.Age); Trace.WriteLine($">> TraceEvent FindSymbolFilePath for {ManagedSymbolFile.FileName}: {debugFile}"); Trace.IndentLevel = 1; Trace.WriteLine(logWriter.ToString()); Trace.IndentLevel = 0; Trace.WriteLine("<< TraceEvent"); if (!File.Exists(debugFile)) { // Don't try again if PDB not found. hasManagedSymbolFileFailure_ = true; return false; } lock (functionDebugInfo) { if (!methodILNativeMap_.TryGetValue(functionDebugInfo, out var ilOffsets)) { return false; } try { var pdb = symbolReader.OpenSymbolFile(debugFile); if (pdb == null) { hasManagedSymbolFileFailure_ = true; return false; } // Find the source lines and native code offset mapping for each IL offset. foreach (var pair in ilOffsets) { var sourceLoc = pdb.SourceLocationForManagedCode((uint)functionDebugInfo.Id, pair.ILOffset); if (sourceLoc != null) { if (sourceLoc.SourceFile != null && functionDebugInfo.SourceFileName == null) { functionDebugInfo.SourceFileName = sourceLoc.SourceFile.GetSourceFile(); functionDebugInfo.OriginalSourceFileName ??= sourceLoc.SourceFile.BuildTimeFilePath; } //? TODO: Remove SourceFileName from SourceLineDebugInfo var lineInfo = new SourceLineDebugInfo(pair.NativeOffset, sourceLoc.LineNumber, sourceLoc.ColumnNumber, functionDebugInfo.SourceFileName); functionDebugInfo.AddSourceLine(lineInfo); } } } catch (Exception ex) { Trace.TraceError($"Failed to read managed PDB from {debugFile}: {ex.Message}\n{ex.StackTrace}"); hasManagedSymbolFileFailure_ = true; } return functionDebugInfo.HasSourceLines; } } private SourceFileDebugInfo GetSourceFileInfo(FunctionDebugInfo info) { return new SourceFileDebugInfo(info.SourceFileName, info.OriginalSourceFileName, info.FirstSourceLine.Line); } public struct AddressNamePair { public long Address { get; set; } public string Name { get; set; } public AddressNamePair(long address, string name) { Address = address; Name = name; } } public class MethodCode { public MethodCode(long address, int size, byte[] code) { Address = address; Size = size; Code = code; CallTargets = new List(); } public long Address { get; set; } public int Size { get; set; } public byte[] Code { get; set; } public List CallTargets { get; set; } public string FindCallTarget(long address) { //? TODO: Map int index = CallTargets.FindIndex(item => item.Address == address); if (index != -1) { return CallTargets[index].Name; } return null; } } private class ManagedProcessCode { public int ProcessId { get; set; } public int MachineType { get; set; } public List Methods { get; set; } } } ================================================ FILE: src/ProfileExplorerCore/Binary/FunctionDebugInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProtoBuf; namespace ProfileExplorer.Core.Binary; [ProtoContract(SkipConstructor = true)] public class FunctionDebugInfo : IEquatable, IComparable, IComparable { public static readonly FunctionDebugInfo Unknown = new(null, 0, 0); public FunctionDebugInfo(string name, long rva, uint size, short optLevel = 0, int id = -1, short auxId = -1) { // Note that string interning is not done here on purpose because // it is often the slowest part in processing a trace, while the memory // saving are quite small (under 15%, a few dozen MBs even for big traces). Name = name; RVA = rva; Size = size; OptimizationLevel = optLevel; SourceLines = null; Id = id; AuxiliaryId = auxId; } [ProtoMember(1)] public long Id { get; set; } // Used for MethodToken in managed code. [ProtoMember(2)] public string Name { get; set; } [ProtoMember(3)] public List SourceLines { get; set; } [ProtoMember(4)] public long AuxiliaryId { get; set; } // Used for RejitID in managed code. [ProtoMember(5)] public long RVA { get; set; } [ProtoMember(6)] public uint Size { get; set; } [ProtoMember(7)] public short OptimizationLevel { get; set; } // Used for OptimizationTier in managed code. public bool HasSourceLines => SourceLines is {Count: > 0}; public SourceLineDebugInfo FirstSourceLine => HasSourceLines ? SourceLines[0] : SourceLineDebugInfo.Unknown; public SourceLineDebugInfo LastSourceLine => HasSourceLines ? SourceLines[^1] : SourceLineDebugInfo.Unknown; //? TODO: Remove SourceFileName from SourceLineDebugInfo public string SourceFileName { get; set; } public string OriginalSourceFileName { get; set; } public long StartRVA => RVA; public long EndRVA => RVA + Size - 1; public bool IsUnknown => RVA == 0 && Size == 0; public int CompareTo(FunctionDebugInfo other) { // Userd by sorting. if (other == null) return 0; if (other.StartRVA < StartRVA) { return 1; } if (other.StartRVA > StartRVA) { return -1; } return 0; } public int CompareTo(long value) { // Used by binary search. if (value < StartRVA) { return 1; } if (value > EndRVA) { return -1; } return 0; } public bool Equals(FunctionDebugInfo other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return RVA == other.RVA && Size == other.Size && Id == other.Id && AuxiliaryId == other.AuxiliaryId; } public static FunctionDebugInfo BinarySearch(List ranges, long value, bool hasOverlappingFuncts = false) { int low = 0; int high = ranges.Count - 1; while (low <= high) { int mid = low + (high - low) / 2; var range = ranges[mid]; int result = range.CompareTo(value); if (result == 0) { // With code written in assembly, it's possible to have overlapping functions // (or rather, one function with multiple entry points). In such a case, // pick the outer function that contains the given RVA. // |F1------------------|-- // -----|F2----|----------- // ----------------|F3|---- // If the RVA is inside F2 or F3, pick F1 instead since it covers the whole range. if (hasOverlappingFuncts) { int count = 0; while (--mid >= 0 && count++ < 10) { var otherRange = ranges[mid]; if (otherRange.CompareTo(value) == 0 && (otherRange.StartRVA != range.StartRVA || otherRange.Size > range.Size)) { return otherRange; } } } return range; } if (result < 0) { low = mid + 1; } else { high = mid - 1; } } return null; } public void AddSourceLine(SourceLineDebugInfo sourceLine) { SourceLines ??= new List(1); SourceLines.Add(sourceLine); } public SourceLineDebugInfo FindNearestLine(long offset) { if (!HasSourceLines) { return SourceLineDebugInfo.Unknown; } if (offset < SourceLines[0].OffsetStart) { return SourceLineDebugInfo.Unknown; } // Find line mapped to same offset or nearest smaller offset. int low = 0; int high = SourceLines.Count - 1; while (low <= high) { int middle = low + (high - low) / 2; if (SourceLines[middle].OffsetStart == offset) { return SourceLines[middle]; } if (SourceLines[middle].OffsetStart > offset) { high = middle - 1; } else { low = middle + 1; } } return SourceLines[high]; } public override bool Equals(object obj) { return obj is FunctionDebugInfo info && Equals(info); } public override int GetHashCode() { return HashCode.Combine(RVA, Size, Id); } public override string ToString() { return $"{Name}, RVA: {RVA:X}, Size: {Size}, Id: {Id}, AuxId: {AuxiliaryId}"; } } ================================================ FILE: src/ProfileExplorerCore/Binary/IBinaryInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Reflection.PortableExecutable; using ProtoBuf; namespace ProfileExplorer.Core.Binary; public enum BinaryFileKind { Native, DotNet, DotNetR2R } public interface IBinaryInfoProvider { SymbolFileDescriptor SymbolFileInfo { get; } BinaryFileDescriptor BinaryFileInfo { get; } //? TODO: Add finding of binary here } [ProtoContract(SkipConstructor = true)] public class BinaryFileDescriptor : IEquatable { [ProtoMember(1)] public string ImageName { get; set; } [ProtoMember(2)] public string ImagePath { get; set; } [ProtoMember(3)] public Machine Architecture { get; set; } [ProtoMember(4)] public BinaryFileKind FileKind { get; set; } [ProtoMember(5)] public long Checksum { get; set; } [ProtoMember(6)] public int TimeStamp { get; set; } [ProtoMember(7)] public long ImageSize { get; set; } [ProtoMember(8)] public long CodeSize { get; set; } [ProtoMember(9)] public long ImageBase { get; set; } [ProtoMember(10)] public long BaseOfCode { get; set; } [ProtoMember(11)] public int MajorVersion { get; set; } [ProtoMember(12)] public int MinorVersion { get; set; } public bool IsNativeImage => FileKind == BinaryFileKind.Native; public bool IsManagedImage => FileKind == BinaryFileKind.DotNet || FileKind == BinaryFileKind.DotNetR2R; public bool Equals(BinaryFileDescriptor other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return ImageName.Equals(other.ImageName, StringComparison.OrdinalIgnoreCase) && TimeStamp == other.TimeStamp && ImageSize == other.ImageSize; } public static bool operator ==(BinaryFileDescriptor left, BinaryFileDescriptor right) { return Equals(left, right); } public static bool operator !=(BinaryFileDescriptor left, BinaryFileDescriptor right) { return !Equals(left, right); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((BinaryFileDescriptor)obj); } public override int GetHashCode() { return HashCode.Combine(ImageName.GetHashCode(StringComparison.OrdinalIgnoreCase), TimeStamp, ImageSize); } public override string ToString() { return $"{ImageName}, Version: {MajorVersion}.{MinorVersion}, TimeStamp: {TimeStamp}, ImageSze: {ImageSize}"; } } ================================================ FILE: src/ProfileExplorerCore/Binary/IDebugInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Reflection.PortableExecutable; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Binary; public interface IDebugInfoProvider : IDisposable { public Machine? Architecture { get; } public SymbolFileSourceSettings SymbolSettings { get; set; } //bool LoadDebugInfo(string debugFilePath, IDebugInfoProvider other = null); bool LoadDebugInfo(DebugFileSearchResult debugFile, IDebugInfoProvider other = null); void Unload(); bool AnnotateSourceLocations(FunctionIR function, IRTextFunction textFunc); bool AnnotateSourceLocations(FunctionIR function, FunctionDebugInfo funcDebugInfo); IEnumerable EnumerateFunctions(); List GetSortedFunctions(); FunctionDebugInfo FindFunction(string functionName); FunctionDebugInfo FindFunctionByRVA(long rva); bool PopulateSourceLines(FunctionDebugInfo funcInfo); SourceFileDebugInfo FindFunctionSourceFilePath(IRTextFunction textFunc); SourceFileDebugInfo FindFunctionSourceFilePath(string functionName); SourceFileDebugInfo FindSourceFilePathByRVA(long rva); SourceLineDebugInfo FindSourceLineByRVA(long rva, bool includeInlinees = false); } [ProtoContract(SkipConstructor = true)] public class SymbolFileDescriptor : IEquatable { public SymbolFileDescriptor(string fileName, Guid id, int age) { FileName = fileName != null ? string.Intern(fileName) : null; Id = id; Age = age; } public SymbolFileDescriptor(string fileName) { FileName = fileName != null ? string.Intern(fileName) : null; } [ProtoMember(1)] public string FileName { get; set; } [ProtoMember(2)] public Guid Id { get; set; } [ProtoMember(3)] public int Age { get; set; } public string SymbolName => Utils.TryGetFileName(FileName); public bool Equals(SymbolFileDescriptor other) { return FileName.Equals(other.FileName, StringComparison.OrdinalIgnoreCase) && Id == other.Id && Age == other.Age; } public static bool operator ==(SymbolFileDescriptor left, SymbolFileDescriptor right) { return Equals(left, right); } public static bool operator !=(SymbolFileDescriptor left, SymbolFileDescriptor right) { return !Equals(left, right); } public override string ToString() { return $"{Id}:{FileName}"; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((SymbolFileDescriptor)obj); } public override int GetHashCode() { return HashCode.Combine(FileName.GetHashCode(StringComparison.OrdinalIgnoreCase), Id, Age); } } ================================================ FILE: src/ProfileExplorerCore/Binary/JsonDebugInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Reflection.PortableExecutable; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Binary; public class JsonDebugInfoProvider : IDebugInfoProvider { private Dictionary functionMap_; private List functions_; public Machine? Architecture => null; public SymbolFileSourceSettings SymbolSettings { get; set; } public bool AnnotateSourceLocations(FunctionIR function, IRTextFunction textFunc) { return AnnotateSourceLocations(function, textFunc.Name); } public bool AnnotateSourceLocations(FunctionIR function, FunctionDebugInfo funcInfo) { var metadataTag = function.GetTag(); if (metadataTag == null) { return false; } if (!funcInfo.HasSourceLines) { return false; } foreach (var pair in metadataTag.OffsetToElementMap) { var lineInfo = funcInfo.FindNearestLine(pair.Key); if (!lineInfo.IsUnknown) { var locationTag = pair.Value.GetOrAddTag(); locationTag.Reset(); // Tag may be already populated. locationTag.Line = lineInfo.Line; locationTag.Column = lineInfo.Column; } } return true; } public FunctionDebugInfo FindFunction(string functionName) { return functionMap_.GetValueOr(functionName, FunctionDebugInfo.Unknown); } public IEnumerable EnumerateFunctions() { return functions_; } public List GetSortedFunctions() { return functions_; } public FunctionDebugInfo FindFunctionByRVA(long rva) { return FunctionDebugInfo.BinarySearch(functions_, rva); } public SourceFileDebugInfo FindFunctionSourceFilePath(IRTextFunction textFunc) { return FindFunctionSourceFilePath(textFunc.Name); } public SourceFileDebugInfo FindFunctionSourceFilePath(string functionName) { if (functionMap_.TryGetValue(functionName, out var funcInfo)) { return GetSourceFileInfo(funcInfo); } return SourceFileDebugInfo.Unknown; } public SourceFileDebugInfo FindSourceFilePathByRVA(long rva) { var funcInfo = FindFunctionByRVA(rva); if (funcInfo != null && funcInfo.HasSourceLines) { return GetSourceFileInfo(funcInfo); } return SourceFileDebugInfo.Unknown; } public SourceLineDebugInfo FindSourceLineByRVA(long rva, bool includeInlinees) { var funcInfo = FindFunctionByRVA(rva); if (funcInfo != null && funcInfo.HasSourceLines) { long offset = rva - funcInfo.StartRVA; return funcInfo.FindNearestLine(offset); } return SourceLineDebugInfo.Unknown; } public bool LoadDebugInfo(DebugFileSearchResult debugFile, IDebugInfoProvider other = null) { if (!debugFile.Found) { return false; } return LoadDebugInfo(debugFile); } public bool PopulateSourceLines(FunctionDebugInfo funcInfo) { return true; } public void Unload() { } public void Dispose() { } private static SourceFileDebugInfo GetSourceFileInfo(FunctionDebugInfo info) { return new SourceFileDebugInfo(info.FirstSourceLine.FilePath, info.FirstSourceLine.FilePath, info.FirstSourceLine.Line); } public bool AnnotateSourceLocations(FunctionIR function, string functionName) { var funcInfo = FindFunction(functionName); if (funcInfo == null) { return false; } return AnnotateSourceLocations(function, funcInfo); } public bool LoadDebugInfo(string debugFilePath, IDebugInfoProvider other = null) { if (!JsonUtils.DeserializeFromFile(debugFilePath, out functions_)) { return false; } functions_.Sort(); functionMap_ = new Dictionary(functions_.Count); foreach (var func in functions_) { functionMap_[func.Name] = func; } return true; } } ================================================ FILE: src/ProfileExplorerCore/Binary/PDBDebugInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using Azure.Core; using Azure.Identity; using Dia2Lib; using Microsoft.Diagnostics.Symbols; using Microsoft.Diagnostics.Symbols.Authentication; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; using StringWriter = System.IO.StringWriter; namespace ProfileExplorer.Core.Binary; public sealed class PDBDebugInfoProvider : IDebugInfoProvider { private const int MaxDemangledFunctionNameLength = 8192; private const int FunctionCacheMissThreshold = 100; private const int MaxLogEntryLength = 10240; private static ConcurrentDictionary resolvedSymbolsCache_ = new(); private static readonly StringWriter authLogWriter_; private static readonly SymwebHandler authSymwebHandler_; private static readonly AzureDevOpsSourceHandler authAzDevOpsHandler_; private static readonly string authRecordPath_ = Path.Combine(Path.GetTempPath(), "ProfileExplorer", "auth_record.bin"); private static object undecorateLock_ = new(); // Global lock for undname. private ConcurrentDictionary sourceFileByRvaCache_ = new(); private ConcurrentDictionary sourceFileByNameCache_ = new(); private ConcurrentDictionary> inlineeByRvaCache_ = new(); private ConcurrentDictionary loggedRvas_ = new(); private object cacheLock_ = new(); private SymbolFileDescriptor symbolFile_; private SymbolFileSourceSettings settings_; private SymbolFileCache symbolCache_; private SymbolReader symbolReader_; private StringWriter symbolReaderLog_; private NativeSymbolModule symbolReaderPDB_; private string debugFilePath_; private IDiaDataSource diaSource_; private IDiaSession session_; private IDiaSymbol globalSymbol_; private List sortedFuncList_; private bool sortedFuncListOverlapping_; private volatile int funcCacheMisses_; private bool loadFailed_; private bool disposed_; private bool hasSourceInfo_; // Static error tracking for DIA SDK registration issues private static bool diaRegistrationFailed_; private static string diaRegistrationError_; /// /// Returns true if DIA SDK (msdia140.dll) failed to load due to COM registration issues. /// public static bool HasDiaRegistrationError => diaRegistrationFailed_; /// /// Gets the DIA registration error message with instructions to fix. /// public static string DiaRegistrationError => diaRegistrationError_; static PDBDebugInfoProvider() { // Create a single instance of the Symweb handler so that // when concurrent requests are made and login must be done, // the login page is displayed a single time, with other requests waiting for a token. // DefaultAzureCredential is not allowed per SFI. Mimic behavior while continuing // to exclude the managed identity credential. // NOTE: ChainedTokenCredential only falls through on CredentialUnavailableException. // Other exceptions (like "needs re-authentication") stop the chain. We wrap each // credential to catch auth failures and convert them to CredentialUnavailableException // so the chain continues to InteractiveBrowserCredential which prompts the user. // Enable token cache persistence for browser credential so tokens survive process restarts. // Additionally, load existing AuthenticationRecord for true silent auth across sessions. // This prevents re-authentication on every trace load if VS credential fails. var authRecord = LoadAuthenticationRecord(); var browserCredentialOptions = new InteractiveBrowserCredentialOptions { TokenCachePersistenceOptions = new TokenCachePersistenceOptions { Name = "ProfileExplorer" // Unique cache name for this app }, AuthenticationRecord = authRecord // Enable silent auth with cached identity }; TokenCredential browserCredential = new InteractiveBrowserCredential(browserCredentialOptions); // If no auth record exists yet, the user will be prompted on first symbol download. // After first successful auth, capture and save the AuthenticationRecord for future sessions. if (authRecord == null) { browserCredential = new CaptureAuthRecordCredential((InteractiveBrowserCredential)browserCredential); } var credentials = new List { WrapCredential(new EnvironmentCredential()), WrapCredential(new WorkloadIdentityCredential()), WrapCredential(new SharedTokenCacheCredential()), WrapCredential(new VisualStudioCredential()), WrapCredential(new AzureCliCredential()), WrapCredential(new AzurePowerShellCredential()), WrapCredential(new AzureDeveloperCliCredential()), browserCredential // Don't wrap - final fallback should show errors }; var authCredential = new ChainedTokenCredential(credentials.ToArray()); authLogWriter_ = new StringWriter(); authSymwebHandler_ = new SymwebHandler(authLogWriter_, authCredential); authAzDevOpsHandler_ = new AzureDevOpsSourceHandler(authLogWriter_, authCredential); } /// /// Wraps a credential to catch authentication failures and convert them to /// CredentialUnavailableException so ChainedTokenCredential continues to the next credential. /// private static TokenCredential WrapCredential(TokenCredential inner) { return new FallbackTokenCredential(inner); } /// /// Loads a previously saved AuthenticationRecord from disk for silent authentication. /// Returns null if no saved record exists or if loading fails. /// internal static AuthenticationRecord LoadAuthenticationRecord() { try { if (File.Exists(authRecordPath_)) { using var stream = File.OpenRead(authRecordPath_); var record = AuthenticationRecord.Deserialize(stream); Trace.WriteLine($"[Auth] Loaded cached authentication record from {authRecordPath_}"); return record; } } catch (Exception ex) { Trace.WriteLine($"[Auth] Failed to load authentication record: {ex.Message}"); } return null; } /// /// Saves an AuthenticationRecord to disk for reuse across sessions. /// This enables silent authentication without repeated browser prompts. /// internal static void SaveAuthenticationRecord(AuthenticationRecord record) { if (record == null) { return; } try { string directory = Path.GetDirectoryName(authRecordPath_); Directory.CreateDirectory(directory); using var stream = File.Create(authRecordPath_); record.Serialize(stream); Trace.WriteLine($"[Auth] Saved authentication record to {authRecordPath_} - future sessions will use silent auth"); } catch (Exception ex) { Trace.WriteLine($"[Auth] Failed to save authentication record: {ex.Message}"); } } public PDBDebugInfoProvider(SymbolFileSourceSettings settings) { settings_ = settings; } public SymbolFileSourceSettings SymbolSettings { get; set; } public Machine? Architecture => null; public bool LoadDebugInfo(DebugFileSearchResult debugFile, IDebugInfoProvider other = null) { if (debugFile == null || !debugFile.Found) { return false; } symbolFile_ = debugFile.SymbolFile; return LoadDebugInfo(debugFile.FilePath, other); } public void Unload() { if (globalSymbol_ != null) { Marshal.ReleaseComObject(globalSymbol_); globalSymbol_ = null; } if (session_ != null) { Marshal.ReleaseComObject(session_); session_ = null; } if (diaSource_ != null) { Marshal.ReleaseComObject(diaSource_); diaSource_ = null; } } public bool AnnotateSourceLocations(FunctionIR function, IRTextFunction textFunc) { return AnnotateSourceLocations(function, textFunc.Name); } public bool AnnotateSourceLocations(FunctionIR function, FunctionDebugInfo funcDebugInfo) { var funcSymbol = FindFunctionSymbolByRVA(funcDebugInfo.RVA, true); if (funcSymbol == null) { return false; } return AnnotateSourceLocationsImpl(function, funcSymbol); } public SourceFileDebugInfo FindFunctionSourceFilePath(IRTextFunction textFunc) { return FindFunctionSourceFilePath(textFunc.Name); } public SourceFileDebugInfo FindSourceFilePathByRVA(long rva) { // Find the first line in the function. if (sourceFileByRvaCache_.TryGetValue(rva, out var fileInfo)) { return fileInfo; } var (lineInfo, sourceFile) = FindSourceLineByRVAImpl(rva); fileInfo = FindFunctionSourceFilePathImpl(lineInfo, sourceFile, (uint)rva); sourceFileByRvaCache_.TryAdd(rva, fileInfo); return fileInfo; } public SourceFileDebugInfo FindFunctionSourceFilePath(string functionName) { DiagnosticLogger.LogInfo($"[SourceFile] FindFunctionSourceFilePath called for: {functionName}"); if (sourceFileByNameCache_.TryGetValue(functionName, out var fileInfo)) { DiagnosticLogger.LogInfo($"[SourceFile] Cache hit for {functionName}: {fileInfo.FilePath}"); return fileInfo; } var funcSymbol = FindFunctionSymbol(functionName); if (funcSymbol == null) { DiagnosticLogger.LogWarning($"[SourceFile] Function symbol not found for: {functionName}"); return SourceFileDebugInfo.Unknown; } DiagnosticLogger.LogInfo($"[SourceFile] Found function symbol for {functionName}, RVA: 0x{funcSymbol.relativeVirtualAddress:X}"); // Find the first line in the function. var (lineInfo, sourceFile) = FindSourceLineByRVAImpl(funcSymbol.relativeVirtualAddress); DiagnosticLogger.LogInfo($"[SourceFile] Line info for {functionName}: FilePath={lineInfo.FilePath}, Line={lineInfo.Line}, IsUnknown={lineInfo.IsUnknown}"); fileInfo = FindFunctionSourceFilePathImpl(lineInfo, sourceFile, funcSymbol.relativeVirtualAddress); DiagnosticLogger.LogInfo($"[SourceFile] Result for {functionName}: FilePath={fileInfo.FilePath}, OriginalFilePath={fileInfo.OriginalFilePath}, HasChecksumMismatch={fileInfo.HasChecksumMismatch}"); sourceFileByNameCache_.TryAdd(functionName, fileInfo); return fileInfo; } public SourceLineDebugInfo FindSourceLineByRVA(long rva, bool includeInlinees) { return FindSourceLineByRVAImpl(rva, includeInlinees).Item1; } public FunctionDebugInfo FindFunctionByRVA(long rva) { bool shouldLog = loggedRvas_.TryAdd(rva, true); // Returns true if newly added string binaryName = symbolFile_?.FileName ?? "Unknown"; try { if (sortedFuncList_ != null) { // Query the function list first. If not found, then still query the actual PDB // because DIA has special lookup for functions split into multiple chunks by PGO for ex. var result = FunctionDebugInfo.BinarySearch(sortedFuncList_, rva, sortedFuncListOverlapping_); if (result != null) { if (shouldLog) { DiagnosticLogger.LogInfo($"[PDBDebugInfo] Binary: {binaryName}, RVA: 0x{rva:X}, Function: {result.Name} (found in cache)"); } return result; } } // Preload the function list only when there are enough queries // to justify the time spent in reading the entire PDB. if (sortedFuncList_ == null && Interlocked.Increment(ref funcCacheMisses_) >= FunctionCacheMissThreshold) { if (shouldLog) { DiagnosticLogger.LogInfo($"[PDBDebugInfo] Binary: {binaryName}, cache miss threshold reached, loading function list"); } GetSortedFunctions(); if (sortedFuncList_ != null) { var result = FunctionDebugInfo.BinarySearch(sortedFuncList_, rva, sortedFuncListOverlapping_); if (result != null) { if (shouldLog) { DiagnosticLogger.LogInfo($"[PDBDebugInfo] Binary: {binaryName}, RVA: 0x{rva:X}, Function: {result.Name} (found after cache load)"); } return result; } } else if (shouldLog) { DiagnosticLogger.LogWarning($"[PDBDebugInfo] Binary: {binaryName}, failed to load function list"); } } // Query the PDB file. var symbol = FindFunctionSymbolByRVA(rva); if (symbol != null) { if (shouldLog) { DiagnosticLogger.LogInfo($"[PDBDebugInfo] Binary: {binaryName}, RVA: 0x{rva:X}, Function: {symbol.name} (found via PDB query)"); } return new FunctionDebugInfo(symbol.name, symbol.relativeVirtualAddress, (uint)symbol.length); } else if (shouldLog) { DiagnosticLogger.LogWarning($"[PDBDebugInfo] Binary: {binaryName}, RVA: 0x{rva:X}, Function: NOT_RESOLVED (no symbol found)"); } } catch (Exception ex) { if (shouldLog) { DiagnosticLogger.LogError($"[PDBDebugInfo] Binary: {binaryName}, RVA: 0x{rva:X}, Function: ERROR ({ex.Message})", ex); } Trace.TraceError($"Failed to find function for RVA {rva}: {ex.Message}"); } return null; } public FunctionDebugInfo FindFunction(string functionName) { var funcSym = FindFunctionSymbol(functionName); return funcSym != null ? new FunctionDebugInfo(funcSym.name, funcSym.relativeVirtualAddress, (uint)funcSym.length) : null; } public IEnumerable EnumerateFunctions() { return GetSortedFunctions(); } public List GetSortedFunctions() { if (sortedFuncList_ != null) { return sortedFuncList_; } lock (cacheLock_) { var result = Utils.RunSync(GetSortedFunctionsAsync); #if DEBUG ValidateSortedList(result); #endif return result; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public bool PopulateSourceLines(FunctionDebugInfo funcInfo) { if (funcInfo.HasSourceLines) { return true; // Already populated. } if (!EnsureLoaded()) { return false; } try { session_.findLinesByRVA((uint)funcInfo.StartRVA, (uint)funcInfo.Size, out var lineEnum); while (true) { lineEnum.Next(1, out var lineNumber, out uint retrieved); if (retrieved == 0) { break; } funcInfo.AddSourceLine(new SourceLineDebugInfo( (int)lineNumber.addressOffset, (int)lineNumber.lineNumber, (int)lineNumber.columnNumber)); } return true; } catch (Exception ex) { Trace.TraceError($"Failed to populate source lines for {funcInfo.Name}: {ex.Message}"); return false; } } ~PDBDebugInfoProvider() { Dispose(false); } public static async Task LocateDebugInfoFileAsync(SymbolFileDescriptor symbolFile, SymbolFileSourceSettings settings) { if (symbolFile == null) { return DebugFileSearchResult.None; } if (resolvedSymbolsCache_.TryGetValue(symbolFile, out var searchResult)) { return searchResult; } return await Task.Run(() => { return LocateDebugInfoFile(symbolFile, settings); }).ConfigureAwait(false); } public static SymbolReaderAuthenticationHandler CreateAuthHandler(SymbolFileSourceSettings settings) { var authHandler = new SymbolReaderAuthenticationHandler(); authHandler.AddHandler(authSymwebHandler_); authHandler.AddHandler(authAzDevOpsHandler_); if (settings.AuthorizationTokenEnabled) { authHandler.AddHandler(new BasicAuthenticationHandler(settings, authLogWriter_)); } return authHandler; } public static DebugFileSearchResult LocateDebugInfoFile(SymbolFileDescriptor symbolFile, SymbolFileSourceSettings settings) { if (symbolFile == null) { return DebugFileSearchResult.None; } DiagnosticLogger.LogInfo($"[SymbolSearch] Starting symbol file search for {symbolFile.FileName} (ID: {symbolFile.Id}, Age: {symbolFile.Age})"); if (resolvedSymbolsCache_.TryGetValue(symbolFile, out var searchResult)) { DiagnosticLogger.LogDebug($"[SymbolSearch] Found cached result for {symbolFile.FileName}: {(searchResult.Found ? "Found" : "Not Found")}"); return searchResult; } // Check if this symbol file was previously rejected (failed lookup in a prior session). if (settings.IsRejectedSymbolFile(symbolFile)) { DiagnosticLogger.LogInfo($"[SymbolSearch] SKIPPED - previously rejected: {symbolFile.FileName}"); searchResult = DebugFileSearchResult.Failure(symbolFile, "Previously rejected"); resolvedSymbolsCache_.TryAdd(symbolFile, searchResult); return searchResult; } string result = null; using var logWriter = new StringWriter(); // In case there is a timeout downloading the symbols, try again. string symbolSearchPath = ConstructSymbolSearchPath(settings); DiagnosticLogger.LogInfo($"[SymbolSearch] Symbol search path: {symbolSearchPath}"); using var symbolReader = new SymbolReader(logWriter, symbolSearchPath, CreateAuthHandler(settings)); symbolReader.SecurityCheck += s => true; // Allow symbols from "unsafe" locations. // Set symbol server timeout from settings (default 10 seconds). // Use EffectiveTimeoutSeconds which is reduced if bellwether test marked server as degraded. int timeoutSeconds = settings.EffectiveTimeoutSeconds > 0 ? settings.EffectiveTimeoutSeconds : 10; symbolReader.ServerTimeout = TimeSpan.FromSeconds(timeoutSeconds); DiagnosticLogger.LogInfo($"[SymbolSearch] ServerTimeout={timeoutSeconds}s for {symbolFile.FileName}"); try { DiagnosticLogger.LogInfo($"[SymbolSearch] Starting PDB download/search for {symbolFile.FileName}, {symbolFile.Id}, {symbolFile.Age}"); Trace.WriteLine($"Start PDB download for {symbolFile.FileName}, {symbolFile.Id}, {symbolFile.Age}"); result = symbolReader.FindSymbolFilePath(symbolFile.FileName, symbolFile.Id, symbolFile.Age); DiagnosticLogger.LogInfo($"[SymbolSearch] FindSymbolFilePath result: {result ?? "null"}"); } catch (Exception ex) { DiagnosticLogger.LogError($"[SymbolSearch] Exception in FindSymbolFilePath for {symbolFile.FileName}: {ex.Message}", ex); Trace.TraceError($"Failed FindSymbolFilePath for {symbolFile.FileName}: {ex.Message}"); } // Log the detailed search information - at INFO level to help debug symbol server issues string searchLog = logWriter.ToString(); if (!string.IsNullOrWhiteSpace(searchLog)) { DiagnosticLogger.LogInfo($"[SymbolSearch] TraceEvent log for {symbolFile.FileName}:\n{searchLog}"); } // Check for auth failure on primary server, but ONLY if primary has never been verified working. // Once we've successfully downloaded from symweb, we NEVER fall back to msdl (would get worse symbols). if (!settings.PrimaryServerVerified && !settings.PrimaryServerAuthFailed && SymbolFileSourceSettings.DetectPrimaryServerAuthFailure(searchLog)) { settings.PrimaryServerAuthFailed = true; DiagnosticLogger.LogWarning($"[SymbolSearch] Primary server (symweb) auth FAILED - switching to secondary (public) server for remaining downloads"); } #if DEBUG Trace.WriteLine($">> TraceEvent FindSymbolFilePath for {symbolFile.FileName}"); Trace.IndentLevel = 1; Trace.WriteLine(searchLog); Trace.IndentLevel = 0; Trace.WriteLine("<< TraceEvent"); #endif // Track session-level statistics for negative cache safety checks settings.SessionSymbolSearchCount++; if (!string.IsNullOrEmpty(result) && File.Exists(result)) { DiagnosticLogger.LogInfo($"[SymbolSearch] Successfully found symbol file for {symbolFile.FileName}: {result}"); searchResult = DebugFileSearchResult.Success(symbolFile, result, searchLog); // Track successful symbol resolution for session statistics settings.SessionSymbolSuccessCount++; // If download succeeded and log shows symweb was used, mark primary as verified if (!settings.PrimaryServerVerified && searchLog.Contains("symweb", StringComparison.OrdinalIgnoreCase) && !SymbolFileSourceSettings.DetectPrimaryServerAuthFailure(searchLog)) { settings.PrimaryServerVerified = true; DiagnosticLogger.LogInfo($"[SymbolSearch] Primary server (symweb) auth VERIFIED - will continue using primary server"); } } else { DiagnosticLogger.LogWarning($"[SymbolSearch] Failed to find symbol file for {symbolFile.FileName}. Result: {result ?? "null"}"); searchResult = DebugFileSearchResult.Failure(symbolFile, searchLog); // Track failed symbol resolution for session statistics settings.SessionSymbolFailureCount++; // Classify the failure to determine if it should be cached var reason = settings.ClassifySearchFailure(searchLog); DiagnosticLogger.LogInfo($"[SymbolSearch] Failure classified as: {reason}"); // Record failed lookup with reason - RejectSymbolFile has safeguards to prevent caching transient failures settings.RejectSymbolFile(symbolFile, reason, searchLog); } resolvedSymbolsCache_.TryAdd(symbolFile, searchResult); DiagnosticLogger.LogInfo($"[SymbolSearch] Cached search result for {symbolFile.FileName}: {(searchResult.Found ? "Success" : "Failure")}"); return searchResult; } // Track if we've logged detailed symbol path info (only log once per session unless auth state changes) private static bool loggedSymbolPathDetails_; private static bool lastLoggedAuthFailedState_; public static string ConstructSymbolSearchPath(SymbolFileSourceSettings settings, bool logPath = false) { string symbolPath = ""; // Only log detailed info on first call or when auth state changes bool authStateChanged = lastLoggedAuthFailedState_ != settings.PrimaryServerAuthFailed; bool shouldLogDetails = !loggedSymbolPathDetails_ || authStateChanged; if (shouldLogDetails) { DiagnosticLogger.LogInfo($"[SymbolPath] ConstructSymbolSearchPath - PrimaryServerAuthFailed={settings.PrimaryServerAuthFailed}, PrimaryServerVerified={settings.PrimaryServerVerified}"); DiagnosticLogger.LogInfo($"[SymbolPath] Input SymbolPaths ({settings.SymbolPaths?.Count ?? 0} entries): {string.Join("; ", settings.SymbolPaths ?? [])}"); if (authStateChanged && loggedSymbolPathDetails_) { DiagnosticLogger.LogWarning($"[SymbolPath] Auth state changed from {lastLoggedAuthFailedState_} to {settings.PrimaryServerAuthFailed} - switching symbol servers"); } loggedSymbolPathDetails_ = true; lastLoggedAuthFailedState_ = settings.PrimaryServerAuthFailed; } if (settings.UseEnvironmentVarSymbolPaths) { symbolPath += $"{settings.EnvironmentVarSymbolPath};"; } foreach (string path in settings.SymbolPaths) { if (!string.IsNullOrEmpty(path)) { // Skip primary (private) server if auth has failed if (settings.PrimaryServerAuthFailed && path.Contains("symweb", StringComparison.OrdinalIgnoreCase)) { if (shouldLogDetails) { DiagnosticLogger.LogInfo($"[SymbolPath] Skipping primary server (auth failed): {path}"); } continue; } // Skip secondary (public) server UNLESS primary auth has explicitly failed. // msdl only has stripped/public PDBs - we want private symbols from symweb. // Only fall back to msdl if symweb auth fails (401/403). if (!settings.PrimaryServerAuthFailed && path.Contains("msdl.microsoft.com", StringComparison.OrdinalIgnoreCase)) { if (shouldLogDetails) { DiagnosticLogger.LogInfo($"[SymbolPath] Skipping secondary server (primary not failed): {path}"); } continue; } if (shouldLogDetails) { DiagnosticLogger.LogInfo($"[SymbolPath] Including path: {path}"); } symbolPath += $"{path};"; } } // Always log the final path on first call or auth state change if (shouldLogDetails) { DiagnosticLogger.LogInfo($"[SymbolPath] Final constructed path: {symbolPath}"); } return symbolPath; } public static async Task LocateDebugInfoFile(string imagePath, SymbolFileSourceSettings settings) { using var binaryInfo = new PEBinaryInfoProvider(imagePath); if (binaryInfo.Initialize()) { return await LocateDebugInfoFileAsync(binaryInfo.SymbolFileInfo, settings).ConfigureAwait(false); } return DebugFileSearchResult.None; } public static string DemangleFunctionName(string name, FunctionNameDemanglingOptions options = FunctionNameDemanglingOptions.Default) { // Mangled MSVC C++ names always start with a ? char. if (string.IsNullOrEmpty(name) || !name.StartsWith('?')) { return name; } var sb = new StringBuilder(MaxDemangledFunctionNameLength); var flags = NativeMethods.UnDecorateFlags.UNDNAME_COMPLETE; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_ACCESS_SPECIFIERS | NativeMethods.UnDecorateFlags.UNDNAME_NO_ALLOCATION_MODEL | NativeMethods.UnDecorateFlags.UNDNAME_NO_MEMBER_TYPE; if (options.HasFlag(FunctionNameDemanglingOptions.OnlyName)) { flags |= NativeMethods.UnDecorateFlags.UNDNAME_NAME_ONLY; } if (options.HasFlag(FunctionNameDemanglingOptions.NoSpecialKeywords)) { flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_MS_KEYWORDS; flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_MS_THISTYPE; } if (options.HasFlag(FunctionNameDemanglingOptions.NoReturnType)) { flags |= NativeMethods.UnDecorateFlags.UNDNAME_NO_FUNCTION_RETURNS; } // DbgHelp UnDecorateSymbolName is not thread safe and can // return bogus function names if not under a global lock. lock (undecorateLock_) { NativeMethods.UnDecorateSymbolName(name, sb, MaxDemangledFunctionNameLength, flags); } return sb.ToString(); } public static string DemangleFunctionName(IRTextFunction function, FunctionNameDemanglingOptions options = FunctionNameDemanglingOptions.Default) { return DemangleFunctionName(function.Name, options); } private bool LoadDebugInfo(string debugFilePath, IDebugInfoProvider other = null) { if (loadFailed_) { return false; // Failed before, don't try again. } try { debugFilePath_ = debugFilePath; diaSource_ = new DiaSourceClass(); diaSource_.loadDataFromPdb(debugFilePath); diaSource_.openSession(out session_); } catch (Exception ex) { // Check for DIA SDK COM registration issue - common in dev builds bool isDiaRegistrationError = ex.Message.Contains("E6756135-1E65-4D17-8576-610761398C3C") || ex.Message.Contains("8007007E") || ex.Message.Contains("class factory"); if (isDiaRegistrationError) { string errorMsg = $"DIA SDK (msdia140.dll) is not registered! " + $"Run as Admin: regsvr32 \"{AppContext.BaseDirectory}msdia140.dll\" " + $"or use the installed version of Profile Explorer."; DiagnosticLogger.LogError($"[PDBLoad] [CRITICAL] {errorMsg}"); Trace.TraceError(errorMsg); // Set static flag so UI can detect and display error if (!diaRegistrationFailed_) { diaRegistrationFailed_ = true; diaRegistrationError_ = errorMsg; } } else { DiagnosticLogger.LogError($"[PDBLoad] Failed to load {debugFilePath}: {ex.Message}"); } Trace.TraceError($"Failed to load debug file {debugFilePath}: {ex.Message}"); loadFailed_ = true; return false; } try { session_.findChildren(null, SymTagEnum.SymTagExe, null, 0, out var exeSymEnum); globalSymbol_ = exeSymEnum.Item(0); } catch (Exception ex) { Trace.TraceError($"Failed to locate global sym for file {debugFilePath}: {ex.Message}"); loadFailed_ = true; return false; } if (other is PDBDebugInfoProvider otherPdb) { // Copy the already loaded function list from another PDB // provider that was created on another thread and is unusable otherwise. symbolCache_ = otherPdb.symbolCache_; sortedFuncList_ = otherPdb.sortedFuncList_; } // Check if PDB has source file information (not stripped) CheckForSourceInfo(); return true; } private void CheckForSourceInfo() { // Log file size to help diagnose public vs private PDB try { var fileInfo = new FileInfo(debugFilePath_); DiagnosticLogger.LogInfo($"[PDBDebugInfo] PDB file size: {fileInfo.Length:N0} bytes ({fileInfo.Length / 1024.0 / 1024.0:F2} MB) - {debugFilePath_}"); } catch { } try { // Try to enumerate source files in the PDB session_.findFile(null, null, 0, out var sourceFileEnum); sourceFileEnum.Next(1, out var sourceFile, out uint retrieved); if (retrieved > 0 && sourceFile != null) { string fileName = sourceFile.fileName; hasSourceInfo_ = true; DiagnosticLogger.LogInfo($"[PDBDebugInfo] PDB has source info. Sample source file: {fileName}"); } else { hasSourceInfo_ = false; DiagnosticLogger.LogWarning($"[PDBDebugInfo] PDB appears to be STRIPPED (no source file info). Source file viewing will not work for: {debugFilePath_}"); DiagnosticLogger.LogWarning($"[PDBDebugInfo] If you expected private symbols with source info:"); DiagnosticLogger.LogWarning($"[PDBDebugInfo] 1. Delete the cached PDB: {debugFilePath_}"); DiagnosticLogger.LogWarning($"[PDBDebugInfo] 2. Ensure symweb (private server) is configured as PRIMARY in symbol paths"); DiagnosticLogger.LogWarning($"[PDBDebugInfo] 3. Reload the trace to re-download from the private server"); } } catch (Exception ex) { hasSourceInfo_ = false; DiagnosticLogger.LogWarning($"[PDBDebugInfo] Could not enumerate source files in PDB: {ex.Message}. PDB may be stripped."); } } /// /// Returns true if the PDB contains source file information (line numbers, file paths). /// Returns false for stripped/public PDBs that only contain symbol names. /// public bool HasSourceInfo => hasSourceInfo_; public bool AnnotateSourceLocations(FunctionIR function, string functionName) { var funcSymbol = FindFunctionSymbol(functionName); if (funcSymbol == null) { return false; } return AnnotateSourceLocationsImpl(function, funcSymbol); } private bool AnnotateSourceLocationsImpl(FunctionIR function, IDiaSymbol funcSymbol) { var metadataTag = function.GetTag(); if (metadataTag == null) { return false; } uint funcRVA = funcSymbol.relativeVirtualAddress; foreach (var pair in metadataTag.OffsetToElementMap) { uint instrRVA = funcRVA + (uint)pair.Key; AnnotateInstructionSourceLocation(pair.Value, instrRVA, funcSymbol); } return true; } private bool ValidateSortedList(List list) { for (int i = 1; i < list.Count; i++) { if (list[i].StartRVA < list[i - 1].StartRVA && list[i].StartRVA != 0 && list[i - 1].StartRVA != 0) { Debug.Assert(false, "Function list is not sorted by RVA"); return false; } } return true; } private async Task> GetSortedFunctionsAsync() { // This method assumes lock is taken by caller. if (sortedFuncList_ != null) { return sortedFuncList_; } if (settings_.CacheSymbolFiles) { // Try to load a previous cached function list file. symbolCache_ = await SymbolFileCache.DeserializeAsync(symbolFile_, settings_.SymbolCacheDirectoryPath). ConfigureAwait(false); } if (symbolCache_ != null) { Trace.WriteLine($"PDB cache loaded for {symbolFile_.FileName}"); sortedFuncList_ = symbolCache_.FunctionList; } else { // Create sorted list of functions and public symbols. sortedFuncList_ = CollectFunctionDebugInfo(); if (sortedFuncList_ == null) { return null; } if (settings_.CacheSymbolFiles) { // Save symbol cache file. symbolCache_ = new SymbolFileCache() { SymbolFile = symbolFile_, FunctionList = sortedFuncList_ }; await SymbolFileCache.SerializeAsync(symbolCache_, settings_.SymbolCacheDirectoryPath). ConfigureAwait(false); Trace.WriteLine($"PDB cache created for {symbolFile_.FileName}"); } } // Sorting needed for binary search later. sortedFuncList_.Sort(); sortedFuncListOverlapping_ = HasOverlappingFunctions(sortedFuncList_); return sortedFuncList_; } private bool HasOverlappingFunctions(List sortedFuncList) { if (sortedFuncList == null || sortedFuncList.Count < 2) { return false; } for (int i = 1; i < sortedFuncList.Count; i++) { if (sortedFuncList[i].StartRVA == 0) { continue; } for (int k = i - 1; k >= 0 && i - k < 10; k--) { if (sortedFuncList[k].StartRVA != 0 && sortedFuncList[k].StartRVA <= sortedFuncList[i].StartRVA && sortedFuncList[k].EndRVA > sortedFuncList[i].EndRVA) { return true; } } } return false; } private void Dispose(bool disposing) { if (disposed_) { return; } if (disposing) { symbolReaderPDB_?.Dispose(); symbolReader_?.Dispose(); symbolReaderLog_?.Dispose(); symbolReaderPDB_ = null; symbolReader_ = null; symbolCache_ = null; sortedFuncList_ = null; } Unload(); disposed_ = true; } private bool EnsureLoaded() { if (session_ != null) { DiagnosticLogger.LogDebug($"[PDBDebugInfo] PDB session already loaded for {symbolFile_?.FileName ?? debugFilePath_ ?? "Unknown"}"); return true; } DiagnosticLogger.LogInfo($"[PDBDebugInfo] Loading PDB file: {debugFilePath_}"); bool loaded = LoadDebugInfo(debugFilePath_); if (loaded) { DiagnosticLogger.LogInfo($"[PDBDebugInfo] Successfully loaded PDB file: {debugFilePath_}"); } else { DiagnosticLogger.LogError($"[PDBDebugInfo] Failed to load PDB file: {debugFilePath_}"); } return loaded; } private SourceFileDebugInfo FindFunctionSourceFilePathImpl(SourceLineDebugInfo lineInfo, IDiaSourceFile sourceFile, uint rva) { if (lineInfo.IsUnknown) { DiagnosticLogger.LogWarning($"[SourceFile] lineInfo is Unknown for RVA 0x{rva:X}"); return SourceFileDebugInfo.Unknown; } string originalFilePath = lineInfo.FilePath; string localFilePath = lineInfo.FilePath; bool localFileFound = File.Exists(localFilePath); bool hasChecksumMismatch = false; DiagnosticLogger.LogInfo($"[SourceFile] Checking source file: {originalFilePath}, localFileFound={localFileFound}"); if (localFileFound) { // Check if the PDB file checksum matches the one of the local file. hasChecksumMismatch = !SourceFileChecksumMatchesPDB(sourceFile, localFilePath); DiagnosticLogger.LogInfo($"[SourceFile] Local file exists, checksumMismatch={hasChecksumMismatch}"); } // Try to use the source server if no exact local file found. DiagnosticLogger.LogInfo($"[SourceFile] SourceServerEnabled={settings_.SourceServerEnabled}, needsServerLookup={!localFileFound || hasChecksumMismatch}"); if ((!localFileFound || hasChecksumMismatch) && settings_.SourceServerEnabled) { DiagnosticLogger.LogInfo($"[SourceFile] Attempting source server lookup for RVA 0x{rva:X}"); try { lock (this) { if (symbolReaderPDB_ == null) { DiagnosticLogger.LogInfo($"[SourceFile] Initializing SymbolReader for {debugFilePath_}"); symbolReaderLog_ = new StringWriter(); symbolReader_ = new SymbolReader(symbolReaderLog_, null, CreateAuthHandler(settings_)); symbolReader_.SecurityCheck += s => true; // Allow symbols from "unsafe" locations. symbolReaderPDB_ = symbolReader_.OpenNativeSymbolFile(debugFilePath_); if (symbolReaderPDB_ == null) { DiagnosticLogger.LogError($"[SourceFile] Failed to initialize SymbolReader for {debugFilePath_}"); Trace.WriteLine($"Failed to initialize SymbolReader for {lineInfo.FilePath}"); return new SourceFileDebugInfo(localFilePath, originalFilePath, lineInfo.Line, hasChecksumMismatch); } DiagnosticLogger.LogInfo($"[SourceFile] SymbolReader initialized successfully"); } // Query for the source file location on the server. DiagnosticLogger.LogInfo($"[SourceFile] Querying SourceLocationForRva(0x{rva:X})"); var sourceLine = symbolReaderPDB_.SourceLocationForRva(rva); if (sourceLine?.SourceFile != null) { // Try to download the source file. // The checksum should match, but do a check just in case. DiagnosticLogger.LogInfo($"[SourceFile] Source server has file: {sourceLine.SourceFile.BuildTimeFilePath}"); Trace.WriteLine($"Query source server for {sourceLine?.SourceFile?.BuildTimeFilePath}"); string filePath = sourceLine.SourceFile.GetSourceFile(); DiagnosticLogger.LogInfo($"[SourceFile] GetSourceFile returned: {filePath ?? "null"}"); if (!string.IsNullOrEmpty(filePath) && SourceFileChecksumMatchesPDB(sourceFile, filePath)) { DiagnosticLogger.LogInfo($"[SourceFile] Downloaded and verified source file: {filePath}"); Trace.WriteLine($"Downloaded source file {filePath}"); localFilePath = filePath; hasChecksumMismatch = !SourceFileChecksumMatchesPDB(sourceFile, localFilePath); } else { DiagnosticLogger.LogWarning($"[SourceFile] Failed to download or verify source file. filePath={filePath ?? "null"}"); Trace.WriteLine($"Failed to download source file {localFilePath}"); string logContent = symbolReaderLog_.ToString().TrimToLength(MaxLogEntryLength); DiagnosticLogger.LogWarning($"[SourceFile] SymbolReader log: {logContent}"); Trace.WriteLine(logContent); symbolReaderLog_.GetStringBuilder().Clear(); Trace.WriteLine("---------------------------------"); } } else { DiagnosticLogger.LogWarning($"[SourceFile] SourceLocationForRva returned null or no SourceFile for RVA 0x{rva:X}"); } } } catch (Exception ex) { DiagnosticLogger.LogError($"[SourceFile] Exception during source server lookup: {ex.Message}", ex); Trace.TraceError($"Failed to locate source file for {debugFilePath_}: {ex.Message}"); } } return new SourceFileDebugInfo(localFilePath, originalFilePath, lineInfo.Line, hasChecksumMismatch); } private bool SourceFileChecksumMatchesPDB(IDiaSourceFile sourceFile, string filePath) { if (string.IsNullOrEmpty(filePath)) { return false; } var hashAlgo = GetSourceFileChecksumHashAlgorithm(sourceFile); if (hashAlgo == null) { return false; } byte[] pdbChecksum = GetSourceFileChecksum(sourceFile); byte[] fileChecksum = ComputeSourceFileChecksum(filePath, hashAlgo); return pdbChecksum != null && fileChecksum != null && pdbChecksum.SequenceEqual(fileChecksum); } private (SourceLineDebugInfo, IDiaSourceFile) FindSourceLineByRVAImpl(long rva, bool includeInlinees = false) { if (!EnsureLoaded()) { return (SourceLineDebugInfo.Unknown, null); } try { session_.findLinesByRVA((uint)rva, 0, out var lineEnum); while (true) { lineEnum.Next(1, out var lineNumber, out uint retrieved); if (retrieved == 0) { DiagnosticLogger.LogWarning($"[SourceFile] No line info found in PDB for RVA 0x{rva:X} - PDB may be stripped (public symbols only)"); break; } var sourceFile = lineNumber.sourceFile; var sourceLine = new SourceLineDebugInfo((int)lineNumber.addressOffset, (int)lineNumber.lineNumber, (int)lineNumber.columnNumber, sourceFile.fileName); if (includeInlinees) { var funcSymbol = FindFunctionSymbolByRVA(rva, true); if (funcSymbol != null) { // Enumerate the functions that got inlined at this call site. foreach (var inlinee in EnumerateInlinees(funcSymbol, (uint)rva)) { if (string.IsNullOrEmpty(inlinee.FilePath)) { // If the file name is not set, it means it's the same file // as the function into which the inlining happened. inlinee.FilePath = sourceFile.fileName; } sourceLine.AddInlinee(inlinee); } } } return (sourceLine, sourceFile); } } catch (Exception ex) { Trace.TraceError($"Failed to get line for RVA {rva}: {ex.Message}"); } return (SourceLineDebugInfo.Unknown, null); } private HashAlgorithm GetSourceFileChecksumHashAlgorithm(IDiaSourceFile sourceFile) { return sourceFile.checksumType switch { 3 => SHA256.Create(), _ => null }; } private unsafe byte[] GetSourceFileChecksum(IDiaSourceFile sourceFile) { // Call once to get the size of the hash. byte* dummy = null; sourceFile.get_checksum(0, out uint hashSizeInBytes, out *dummy); // Allocate buffer and get the actual hash. byte[] hash = new byte[hashSizeInBytes]; fixed (byte* bufferPtr = hash) { sourceFile.get_checksum((uint)hash.Length, out uint bytesFetched, out *bufferPtr); } return hash; } private byte[] ComputeSourceFileChecksum(string sourceFile, HashAlgorithm hashAlgo) { try { using var stream = File.OpenRead(sourceFile); return hashAlgo.ComputeHash(stream); } catch (Exception ex) { Trace.TraceError($"Failed to compute hash for {sourceFile}: {ex.Message}"); return Array.Empty(); } } private bool AnnotateInstructionSourceLocation(IRElement instr, uint instrRVA, IDiaSymbol funcSymbol) { if (!EnsureLoaded()) { return false; } try { session_.findLinesByRVA(instrRVA, 0, out var lineEnum); while (true) { lineEnum.Next(1, out var lineNumber, out uint retrieved); if (retrieved == 0) { break; } var locationTag = instr.GetOrAddTag(); locationTag.Reset(); // Tag may be already populated. locationTag.Line = (int)lineNumber.lineNumber; locationTag.Column = (int)lineNumber.columnNumber; if (lineNumber.sourceFile != null) { locationTag.FilePath = string.Intern(lineNumber.sourceFile.fileName); } // Enumerate the functions that got inlined at this call site. foreach (var inlinee in EnumerateInlinees(funcSymbol, instrRVA)) { if (string.IsNullOrEmpty(inlinee.FilePath)) { // If the file name is not set, it means it's the same file // as the function into which the inlining happened. inlinee.FilePath = locationTag.FilePath; } locationTag.AddInlinee(inlinee); } } Marshal.ReleaseComObject(lineEnum); } catch (Exception ex) { Trace.TraceError($"Failed to get source lines for {funcSymbol.name}: {ex.Message}"); return false; } return true; } private IEnumerable EnumerateInlinees(IDiaSymbol funcSymbol, uint instrRVA) { if (inlineeByRvaCache_.TryGetValue(instrRVA, out var inlineeList)) { // Use the preloaded list of inlinees. foreach (var inlinee in inlineeList) { yield return inlinee; } } else { inlineeList = new List(); funcSymbol.findInlineFramesByRVA(instrRVA, out var inlineeFrameEnum); foreach (IDiaSymbol inlineFrame in inlineeFrameEnum) { inlineFrame.findInlineeLinesByRVA(instrRVA, 0, out var inlineeLineEnum); while (true) { inlineeLineEnum.Next(1, out var inlineeLineNumber, out uint inlineeRetrieved); if (inlineeRetrieved == 0) { break; } // Getting the source file of the inlinee often fails, ignore it. string inlineeFileName = null; try { inlineeFileName = inlineeLineNumber.sourceFile.fileName; } catch { //? TODO: Any way to detect this and avoid throwing? } var inlinee = new SourceStackFrame( inlineFrame.name, inlineeFileName, (int)inlineeLineNumber.lineNumber, (int)inlineeLineNumber.columnNumber); inlineeList.Add(inlinee); yield return inlinee; } Marshal.ReleaseComObject(inlineeLineEnum); } Marshal.ReleaseComObject(inlineeFrameEnum); inlineeByRvaCache_.TryAdd(instrRVA, inlineeList); } } private List CollectFunctionDebugInfo() { if (!EnsureLoaded()) { return null; } IDiaEnumSymbols symbolEnum = null; IDiaEnumSymbols publicSymbolEnum = null; try { var symbolList = new List(); var symbolMap = new Dictionary(); globalSymbol_.findChildren(SymTagEnum.SymTagFunction, null, 0, out symbolEnum); globalSymbol_.findChildren(SymTagEnum.SymTagPublicSymbol, null, 0, out publicSymbolEnum); foreach (IDiaSymbol sym in symbolEnum) { //Trace.WriteLine($" FuncSym {sym.name}: RVA {sym.relativeVirtualAddress:X}, size {sym.length}"); var funcInfo = new FunctionDebugInfo(sym.name, sym.relativeVirtualAddress, (uint)sym.length); symbolList.Add(funcInfo); symbolMap[funcInfo.RVA] = funcInfo; } foreach (IDiaSymbol sym in publicSymbolEnum) { //Trace.WriteLine($" PublicSym {sym.name}: RVA {sym.relativeVirtualAddress:X} size {sym.length}"); var funcInfo = new FunctionDebugInfo(sym.name, sym.relativeVirtualAddress, (uint)sym.length); // Public symbols are preferred over function symbols if they have the same RVA and size. // This ensures that the mangled name is saved, set only of public symbols. // This tries to mirror the behavior from FindFunctionSymbolByRVA. if (symbolMap.TryGetValue(funcInfo.RVA, out var existingFuncInfo)) { if (existingFuncInfo.Size == funcInfo.Size) { existingFuncInfo.Name = funcInfo.Name; } } else { // Consider the public sym if it doesn't overlap a function sym. symbolList.Add(funcInfo); } } return symbolList; } catch (Exception ex) { Trace.TraceError($"Failed to enumerate functions: {ex.Message}"); } finally { if (symbolEnum != null) { Marshal.ReleaseComObject(symbolEnum); } if (publicSymbolEnum != null) { Marshal.ReleaseComObject(publicSymbolEnum); } } return null; } private IDiaSymbol FindFunctionSymbol(string functionName) { string demangledName = DemangleFunctionName(functionName); string queryDemangledName = DemangleFunctionName(functionName, FunctionNameDemanglingOptions.OnlyName); var result = FindFunctionSymbolImpl(SymTagEnum.SymTagFunction, functionName, demangledName, queryDemangledName); if (result != null) { return result; } return FindFunctionSymbolImpl(SymTagEnum.SymTagPublicSymbol, functionName, demangledName, queryDemangledName); } private IDiaSymbol FindFunctionSymbolByRVA(long rva, bool preferFunctionSym = false) { if (!EnsureLoaded()) { return null; } try { session_.findSymbolByRVA((uint)rva, SymTagEnum.SymTagFunction, out var funcSym); if (preferFunctionSym && funcSym != null) { return funcSym; } // Public symbols are preferred over function symbols if they have the same RVA and size. // This ensures that the mangled name is saved, set only of public symbols. session_.findSymbolByRVA((uint)rva, SymTagEnum.SymTagPublicSymbol, out var pubSym); if (pubSym != null) { if (funcSym == null || funcSym.relativeVirtualAddress == pubSym.relativeVirtualAddress && funcSym.length == pubSym.length) { return pubSym; } } return funcSym; } catch (Exception ex) { Trace.TraceError($"Failed to find function symbol for RVA {rva}: {ex.Message}"); } return null; } private IDiaSymbol FindFunctionSymbolImpl(SymTagEnum symbolType, string functionName, string demangledName, string queryDemangledName) { if (!EnsureLoaded()) { return null; } try { globalSymbol_.findChildren(symbolType, queryDemangledName, 0, out var symbolEnum); IDiaSymbol candidateSymbol = null; while (true) { symbolEnum.Next(1, out var symbol, out uint retrieved); if (retrieved == 0) { break; } // Class::function matches, now check the entire unmangled name // to pick that right function overload. candidateSymbol ??= symbol; symbol.get_undecoratedNameEx((uint)NativeMethods.UnDecorateFlags.UNDNAME_NO_ACCESS_SPECIFIERS, out string symbolDemangledName); if (symbolDemangledName == demangledName) { return symbol; } } return candidateSymbol; // Return first match. } catch (Exception ex) { Trace.TraceError($"Failed to get function symbol for {functionName}: {ex.Message}"); return null; } } } /// /// Handles Azure AD authentication for Azure DevOps source server URLs. /// The source server for Windows OS PDBs uses Azure DevOps (*.visualstudio.com, dev.azure.com), /// which requires a Bearer token with the Azure DevOps scope. /// sealed class AzureDevOpsSourceHandler : SymbolReaderAuthHandler { private const string AzureDevOpsScope = "499b84ac-1321-427f-aa17-267ca6975798/.default"; private readonly TokenCredential credential_; public AzureDevOpsSourceHandler(TextWriter log, TokenCredential credential) : base(log, "AzureDevOps Source") { credential_ = credential; } protected override bool TryGetAuthority(Uri requestUri, out Uri authority) { string host = requestUri.Host; if (host.EndsWith(".visualstudio.com", StringComparison.OrdinalIgnoreCase) || host.EndsWith("dev.azure.com", StringComparison.OrdinalIgnoreCase)) { authority = new Uri($"{requestUri.Scheme}://{requestUri.Host}"); return true; } authority = null; return false; } protected override async Task GetAuthTokenAsync(RequestContext context, SymbolReaderHandlerDelegate next, Uri authority, CancellationToken cancellationToken) { try { var tokenRequest = new TokenRequestContext(new[] { AzureDevOpsScope }); var accessToken = await credential_.GetTokenAsync(tokenRequest, cancellationToken); return new AuthToken(AuthScheme.Bearer, accessToken.Token, accessToken.ExpiresOn.UtcDateTime, null); } catch (Exception ex) { WriteLog($"AzureDevOps auth failed: {ex.Message}"); return null; } } } sealed class BasicAuthenticationHandler : SymbolReaderAuthHandler { private SymbolFileSourceSettings settings_; public BasicAuthenticationHandler(SymbolFileSourceSettings settings, TextWriter log) : base(log, "HTTP Auth") { settings_ = settings; } protected override bool TryGetAuthority(Uri requestUri, out Uri authority) { if (!settings_.AuthorizationTokenEnabled) { authority = null; return false; } authority = requestUri; return true; } protected override Task GetAuthTokenAsync(RequestContext context, SymbolReaderHandlerDelegate next, Uri authority, CancellationToken cancellationToken) { if (settings_.AuthorizationTokenEnabled) { string username = settings_.AuthorizationUser; string pat = settings_.AuthorizationToken; var token = AuthToken.CreateBasicFromUsernameAndPassword(username, pat); return Task.FromResult(token); } return null; } } /// /// Wraps InteractiveBrowserCredential to automatically capture and persist the AuthenticationRecord /// after the first successful authentication. This enables silent auth across future sessions. /// sealed class CaptureAuthRecordCredential : TokenCredential { private readonly InteractiveBrowserCredential inner_; private bool authRecordCaptured_; private readonly object captureLock_ = new(); public CaptureAuthRecordCredential(InteractiveBrowserCredential inner) { inner_ = inner; } public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken) { var token = inner_.GetToken(requestContext, cancellationToken); CaptureAuthRecordIfNeeded(); return token; } public override async ValueTask GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken) { var token = await inner_.GetTokenAsync(requestContext, cancellationToken).ConfigureAwait(false); await CaptureAuthRecordIfNeededAsync().ConfigureAwait(false); return token; } private void CaptureAuthRecordIfNeeded() { if (authRecordCaptured_) { return; } lock (captureLock_) { if (authRecordCaptured_) { return; } try { // Authenticate() returns the current AuthenticationRecord without prompting again var record = Utils.RunSync(() => inner_.AuthenticateAsync()); PDBDebugInfoProvider.SaveAuthenticationRecord(record); authRecordCaptured_ = true; } catch (Exception ex) { Trace.WriteLine($"[Auth] Failed to capture authentication record: {ex.Message}"); } } } private async Task CaptureAuthRecordIfNeededAsync() { if (authRecordCaptured_) { return; } lock (captureLock_) { if (authRecordCaptured_) { return; } try { // Authenticate() returns the current AuthenticationRecord without prompting again var record = Utils.RunSync(() => inner_.AuthenticateAsync()); PDBDebugInfoProvider.SaveAuthenticationRecord(record); authRecordCaptured_ = true; } catch (Exception ex) { Trace.WriteLine($"[Auth] Failed to capture authentication record: {ex.Message}"); } } } } /// /// Wraps a TokenCredential to catch authentication failures and convert them to /// CredentialUnavailableException so ChainedTokenCredential continues to the next credential. /// This ensures that if VS auth needs re-authentication, we fall through to browser auth. /// sealed class FallbackTokenCredential : TokenCredential { private readonly TokenCredential inner_; public FallbackTokenCredential(TokenCredential inner) { inner_ = inner; } public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken) { try { return inner_.GetToken(requestContext, cancellationToken); } catch (CredentialUnavailableException) { throw; // Let this pass through - it's expected } catch (Exception ex) { // Convert other auth failures to CredentialUnavailableException so chain continues throw new CredentialUnavailableException($"{inner_.GetType().Name} failed: {ex.Message}", ex); } } public override ValueTask GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken) { return GetTokenAsyncImpl(requestContext, cancellationToken); } private async ValueTask GetTokenAsyncImpl(TokenRequestContext requestContext, CancellationToken cancellationToken) { try { return await inner_.GetTokenAsync(requestContext, cancellationToken).ConfigureAwait(false); } catch (CredentialUnavailableException) { throw; // Let this pass through - it's expected } catch (Exception ex) { // Convert other auth failures to CredentialUnavailableException so chain continues throw new CredentialUnavailableException($"{inner_.GetType().Name} failed: {ex.Message}", ex); } } } ================================================ FILE: src/ProfileExplorerCore/Binary/PEBinaryInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using System.Threading.Tasks; using Microsoft.Diagnostics.Symbols; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Binary; /// /// Contains version information extracted from a PE file's version resource. /// public sealed class PEVersionInfo { public string CompanyName { get; init; } public string ProductName { get; init; } public string FileDescription { get; init; } public string LegalCopyright { get; init; } public string OriginalFilename { get; init; } /// /// Checks if any of the version info fields contain the specified text (case-insensitive). /// public bool ContainsText(string text) { if (string.IsNullOrEmpty(text)) { return false; } return ContainsTextInternal(CompanyName, text) || ContainsTextInternal(ProductName, text) || ContainsTextInternal(FileDescription, text) || ContainsTextInternal(LegalCopyright, text); } /// /// Checks if any of the version info fields contain any of the specified texts (case-insensitive). /// public bool ContainsAnyText(IEnumerable texts) { foreach (var text in texts) { if (ContainsText(text)) { return true; } } return false; } private static bool ContainsTextInternal(string field, string text) { return !string.IsNullOrEmpty(field) && field.Contains(text, StringComparison.OrdinalIgnoreCase); } public override string ToString() { return $"Company: {CompanyName ?? "N/A"}, Product: {ProductName ?? "N/A"}, Description: {FileDescription ?? "N/A"}"; } } public sealed class PEBinaryInfoProvider : IBinaryInfoProvider, IDisposable { private static ConcurrentDictionary resolvedBinariesCache_ = new(); private static ConcurrentDictionary versionInfoCache_ = new(); private string filePath_; private PEReader reader_; public PEBinaryInfoProvider(string filePath) { filePath_ = filePath; } public List CodeSectionHeaders { get { var list = new List(); if (reader_.PEHeaders.PEHeader == null) { return list; } foreach (var section in reader_.PEHeaders.SectionHeaders) { if (section.SectionCharacteristics.HasFlag(SectionCharacteristics.MemExecute) || section.SectionCharacteristics.HasFlag(SectionCharacteristics.ContainsCode)) { list.Add(section); } } return list; } } public SymbolFileDescriptor SymbolFileInfo { get { foreach (var entry in reader_.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { try { var dir = reader_.ReadCodeViewDebugDirectoryData(entry); return new SymbolFileDescriptor(dir.Path, dir.Guid, dir.Age); } catch (BadImageFormatException) { // PE reader has problems with some old binaries. } break; } } return null; } } public BinaryFileDescriptor BinaryFileInfo { get { if (reader_.PEHeaders.PEHeader == null) { return null; } var fileKind = BinaryFileKind.Native; if (reader_.HasMetadata && reader_.PEHeaders.CorHeader != null) { if (reader_.PEHeaders.CorHeader.Flags.HasFlag(CorFlags.ILOnly)) { fileKind = BinaryFileKind.DotNet; } else if (reader_.PEHeaders.CorHeader.Flags.HasFlag(CorFlags.ILLibrary)) { fileKind = BinaryFileKind.DotNetR2R; } } // For AMR64 EC binaries, they may show up as AMD64, but have the hybrid metadata table set, // consider them ARM64 binaries instead so that disassembly works as expected. var architecture = reader_.PEHeaders.CoffHeader.Machine; if (architecture == Machine.Amd64 && IsARM64ECBinary()) { architecture = Machine.Arm64; } return new BinaryFileDescriptor { ImageName = Utils.TryGetFileName(filePath_), ImagePath = filePath_, Architecture = architecture, FileKind = fileKind, Checksum = reader_.PEHeaders.PEHeader.CheckSum, TimeStamp = reader_.PEHeaders.CoffHeader.TimeDateStamp, ImageSize = reader_.PEHeaders.PEHeader.SizeOfImage, CodeSize = reader_.PEHeaders.PEHeader.SizeOfCode, ImageBase = (long)reader_.PEHeaders.PEHeader.ImageBase, BaseOfCode = reader_.PEHeaders.PEHeader.BaseOfCode, MajorVersion = reader_.PEHeaders.PEHeader.MajorImageVersion, MinorVersion = reader_.PEHeaders.PEHeader.MinorImageVersion }; } } public void Dispose() { reader_?.Dispose(); } public static BinaryFileDescriptor GetBinaryFileInfo(string filePath) { using var binaryInfo = new PEBinaryInfoProvider(filePath); if (binaryInfo.Initialize()) { return binaryInfo.BinaryFileInfo; } return null; } public static SymbolFileDescriptor GetSymbolFileInfo(string filePath) { using var binaryInfo = new PEBinaryInfoProvider(filePath); if (binaryInfo.Initialize()) { return binaryInfo.SymbolFileInfo; } return null; } /// /// Gets version information (Company, Product, Description, Copyright) from a PE file. /// Uses FileVersionInfo which reads the version resource from the PE file. /// public static PEVersionInfo GetVersionInfo(string filePath) { if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) { return null; } // Check cache first if (versionInfoCache_.TryGetValue(filePath, out var cached)) { return cached; } try { var fileVersionInfo = FileVersionInfo.GetVersionInfo(filePath); var versionInfo = new PEVersionInfo { CompanyName = fileVersionInfo.CompanyName, ProductName = fileVersionInfo.ProductName, FileDescription = fileVersionInfo.FileDescription, LegalCopyright = fileVersionInfo.LegalCopyright, OriginalFilename = fileVersionInfo.OriginalFilename }; versionInfoCache_.TryAdd(filePath, versionInfo); return versionInfo; } catch (Exception ex) { Trace.WriteLine($"Failed to read version info from {filePath}: {ex.Message}"); return null; } } /// /// Checks if a PE file's version info matches any of the specified company filter strings. /// Returns true if any filter string is found in Company, Product, Description, or Copyright fields. /// Returns true if no filters are specified (empty/null list). /// Returns true if the file doesn't exist or version info cannot be read (fail-open for safety). /// public static bool MatchesCompanyFilter(string filePath, IReadOnlyList companyFilters) { // No filter specified - accept all if (companyFilters == null || companyFilters.Count == 0) { return true; } var versionInfo = GetVersionInfo(filePath); // If we can't read version info, accept the file (fail-open) if (versionInfo == null) { return true; } return versionInfo.ContainsAnyText(companyFilters); } public static async Task LocateBinaryFileAsync(BinaryFileDescriptor binaryFile, SymbolFileSourceSettings settings) { // Check if the binary was requested before. if (resolvedBinariesCache_.TryGetValue(binaryFile, out var searchResult)) { return searchResult; } return await Task.Run(() => { return LocateBinaryFile(binaryFile, settings); }).ConfigureAwait(false); } public static BinaryFileSearchResult LocateBinaryFile(BinaryFileDescriptor binaryFile, SymbolFileSourceSettings settings) { var sw = Stopwatch.StartNew(); // Check if the binary was requested before. if (resolvedBinariesCache_.TryGetValue(binaryFile, out var searchResult)) { DiagnosticLogger.LogDebug($"[BinarySearch] Cache hit for {binaryFile.ImageName}"); return searchResult; } DiagnosticLogger.LogInfo($"[BinarySearch] Starting binary search for {binaryFile.ImageName} (Size: {binaryFile.ImageSize}, Timestamp: {binaryFile.TimeStamp})"); // Check if this binary was previously rejected (failed lookup in a prior session). if (settings.IsRejectedBinaryFile(binaryFile)) { DiagnosticLogger.LogInfo($"[BinarySearch] SKIPPED - previously rejected: {binaryFile.ImageName}"); searchResult = BinaryFileSearchResult.Failure(binaryFile, "Previously rejected"); resolvedBinariesCache_.TryAdd(binaryFile, searchResult); return searchResult; } // Resolve NT kernel paths like \SystemRoot\system32\ntoskrnl.exe // to actual file system paths like C:\Windows\system32\ntoskrnl.exe. string resolvedPath = ResolveNtKernelPath(binaryFile.ImagePath); if (resolvedPath != binaryFile.ImagePath) { DiagnosticLogger.LogInfo($"[BinarySearch] Resolved NT path for {binaryFile.ImageName}: {binaryFile.ImagePath} -> {resolvedPath}"); binaryFile.ImagePath = resolvedPath; } // Quick check if trace was recorded on local machine. string approximateMatchPath = null; long correctedImageSize = 0; string result = FindExactLocalBinaryFile(binaryFile, out approximateMatchPath, out correctedImageSize); if (result != null) { DiagnosticLogger.LogInfo($"[BinarySearch] Found exact local binary for {binaryFile.ImageName} at {result} ({sw.ElapsedMilliseconds}ms)"); binaryFile = GetBinaryFileInfo(result); searchResult = BinaryFileSearchResult.Success(binaryFile, result, ""); resolvedBinariesCache_.TryAdd(binaryFile, searchResult); return searchResult; } // Correct ImageSize if the file exists locally with matching timestamp but // different size. The symbol server indexes binaries by TimeDateStamp+SizeOfImage // from the PE header, but the ETW kernel event may report a larger mapped view size // (the kernel mapping can include extra slack pages). Using the wrong size causes // 404s on the symbol server even when the binary IS indexed there. if (correctedImageSize > 0 && correctedImageSize != binaryFile.ImageSize) { DiagnosticLogger.LogInfo( $"[BinarySearch] Correcting ImageSize for {binaryFile.ImageName} from ETW value {binaryFile.ImageSize} " + $"to PE SizeOfImage {correctedImageSize} for symbol server lookup"); binaryFile.ImageSize = correctedImageSize; } using var logWriter = new StringWriter(); try { // Try to use symbol server to download binary. // Add local binary path directly instead of using WithSymbolPaths (which clones // settings again and resets runtime state like timeout overrides). if (File.Exists(binaryFile.ImagePath)) { settings.InsertSymbolPath(binaryFile.ImagePath); } string userSearchPath = PDBDebugInfoProvider.ConstructSymbolSearchPath(settings); //? TODO: Making a new instance clears the "dead servers", //? have a way to share the list between multiple instances. using var symbolReader = new SymbolReader(logWriter, userSearchPath, PDBDebugInfoProvider.CreateAuthHandler(settings)); symbolReader.SecurityCheck += s => true; // Allow symbols from "unsafe" locations. // Set symbol server timeout from settings (default 10 seconds). // Use EffectiveTimeoutSeconds which is reduced if bellwether test marked server as degraded. int timeoutSeconds = settings.EffectiveTimeoutSeconds > 0 ? settings.EffectiveTimeoutSeconds : 10; symbolReader.ServerTimeout = TimeSpan.FromSeconds(timeoutSeconds); DiagnosticLogger.LogInfo($"[BinarySearch] ServerTimeout={timeoutSeconds}s, RejectPreviouslyFailedFiles={settings.RejectPreviouslyFailedFiles}, " + $"RejectedBinaries={settings.RejectedBinaryFiles?.Count ?? 0} for {binaryFile.ImageName}"); //? TODO: Workaround for cases where the ETL file doesn't have a timestamp //? and SymbolReader would reject the bin even on the same machine... //? Better way to handle this is to have SymReader accept a func to check if PDB is valid to use if (binaryFile.TimeStamp == 0 && File.Exists(binaryFile.ImagePath)) { var binInfo = GetBinaryFileInfo(binaryFile.ImagePath); binaryFile.TimeStamp = binInfo.TimeStamp; } //Trace.WriteLine($"Start download of {Utils.TryGetFileName(binaryFile.ImageName)}"); result = symbolReader.FindExecutableFilePath(binaryFile.ImageName, binaryFile.TimeStamp, (int)binaryFile.ImageSize); if (result == null) { // Finally, try an approximate manual search. DiagnosticLogger.LogDebug($"[BinarySearch] Symbol server search failed, trying approximate local search for {binaryFile.ImageName}"); result = FindMatchingLocalBinaryFile(binaryFile, settings, ref approximateMatchPath); } } catch (Exception ex) { DiagnosticLogger.LogError($"[BinarySearch] Exception during binary search for {binaryFile.ImageName}: {ex.Message}", ex); Trace.TraceError($"Failed FindExecutableFilePath: {ex.Message}"); } var searchDuration = sw.Elapsed; string searchLog = logWriter.ToString(); #if DEBUG Trace.WriteLine($">> TraceEvent FindExecutableFilePath for {binaryFile.ImageName}"); Trace.WriteLine(searchLog); Trace.WriteLine("<< TraceEvent"); #endif if (!string.IsNullOrEmpty(result) && File.Exists(result)) { DiagnosticLogger.LogInfo($"[BinarySearch] Found binary for {binaryFile.ImageName} at {result} ({searchDuration.TotalMilliseconds:F0}ms)"); // Read the binary info from the local file to fill in all fields. binaryFile = GetBinaryFileInfo(result); searchResult = BinaryFileSearchResult.Success(binaryFile, result, searchLog); } else if (settings.AllowApproximateBinaryMatch && !string.IsNullOrEmpty(approximateMatchPath) && File.Exists(approximateMatchPath)) { // Fallback: use a binary with matching timestamp but different size. // This handles cases where the kernel-reported ImageSize in the ETW trace // differs from the PE header SizeOfImage, or the DLL was serviced. long traceImageSize = binaryFile.ImageSize; var originalDescriptor = binaryFile; DiagnosticLogger.LogWarning( $"[BinarySearch] Using APPROXIMATE match for {binaryFile.ImageName} " + $"at {approximateMatchPath} ({searchDuration.TotalMilliseconds:F0}ms) - " + $"timestamp matches but image size differs"); binaryFile = GetBinaryFileInfo(approximateMatchPath); string details = $"Approximate match: timestamp matches but image size differs " + $"(trace: {traceImageSize}, on-disk: {binaryFile.ImageSize}). Disassembly may not be fully accurate.\n{searchLog}"; searchResult = BinaryFileSearchResult.ApproximateSuccess(binaryFile, approximateMatchPath, details); // Cache under the original trace descriptor so subsequent lookups for the // same trace module hit the cache instead of repeating the search. resolvedBinariesCache_.TryAdd(originalDescriptor, searchResult); } else { DiagnosticLogger.LogWarning($"[BinarySearch] Failed to find binary for {binaryFile.ImageName} ({searchDuration.TotalMilliseconds:F0}ms)"); searchResult = BinaryFileSearchResult.Failure(binaryFile, searchLog); // Record failed lookup to avoid retrying in future sessions, // but skip transient failures (timeout, auth, server errors). var reason = settings.ClassifySearchFailure(searchLog); settings.RejectBinaryFile(binaryFile, reason, searchLog); } resolvedBinariesCache_.TryAdd(binaryFile, searchResult); return searchResult; } private static string ResolveNtKernelPath(string path) { if (string.IsNullOrEmpty(path)) { return path; } if (path.StartsWith(@"\SystemRoot", StringComparison.OrdinalIgnoreCase)) { string systemRoot = Environment.GetEnvironmentVariable("SystemRoot") ?? @"C:\Windows"; return systemRoot + path.Substring(@"\SystemRoot".Length); } return path; } private static string FindExactLocalBinaryFile(BinaryFileDescriptor binaryFile, out string approximateMatchPath, out long correctedImageSize) { approximateMatchPath = null; correctedImageSize = 0; if (File.Exists(binaryFile.ImagePath)) { var fileInfo = GetBinaryFileInfo(binaryFile.ImagePath); if (fileInfo != null && fileInfo.TimeStamp == binaryFile.TimeStamp) { if (fileInfo.ImageSize == binaryFile.ImageSize) { return binaryFile.ImagePath; } // Timestamp matches but size differs. This commonly happens because the // kernel-reported ImageSize in ETW events is the mapped view size, which // can exceed the PE header's SizeOfImage by a few pages of slack. // Record the local file as an approximate match and save the PE SizeOfImage // so we can correct the symbol server lookup key. approximateMatchPath = binaryFile.ImagePath; correctedImageSize = fileInfo.ImageSize; DiagnosticLogger.LogInfo( $"[BinarySearch] Local binary for {binaryFile.ImageName} at {binaryFile.ImagePath}: " + $"timestamp matches ({fileInfo.TimeStamp}), size differs " + $"(PE SizeOfImage: {fileInfo.ImageSize}, ETW ImageSize: {binaryFile.ImageSize})"); } } return null; } private static string FindMatchingLocalBinaryFile(BinaryFileDescriptor binaryFile, SymbolFileSourceSettings settings, ref string approximateMatchPath) { // Manually search in the provided directories. // This helps in cases where the original fine name doesn't match // the one on disk, like it seems to happen sometimes with the SPEC runner. string winPath = Environment.GetFolderPath(Environment.SpecialFolder.Windows); string sysPath = Environment.GetFolderPath(Environment.SpecialFolder.System); string sysx86Path = Environment.GetFolderPath(Environment.SpecialFolder.SystemX86); // Don't search in the system dirs though, it's pointless // and takes a long time checking thousands of binaries. bool PathIsSubPath(string subPath, string basePath) { string rel = Path.GetRelativePath(basePath, subPath); return !rel.StartsWith('.') && !Path.IsPathRooted(rel); } foreach (string path in settings.SymbolPaths) { if (PathIsSubPath(path, winPath) || PathIsSubPath(path, sysPath) || PathIsSubPath(path, sysx86Path)) { continue; } try { string searchPath = Utils.TryGetDirectoryName(path); foreach (string file in Directory.EnumerateFiles(searchPath, "*.*", SearchOption.AllDirectories)) { if (!Utils.IsBinaryFile(file)) { continue; } var fileInfo = GetBinaryFileInfo(file); if (fileInfo != null && fileInfo.TimeStamp == binaryFile.TimeStamp) { if (fileInfo.ImageSize == binaryFile.ImageSize) { return file; } // Track first approximate match (timestamp matches, size differs). if (approximateMatchPath == null) { approximateMatchPath = file; DiagnosticLogger.LogInfo( $"[BinarySearch] Approximate match for {binaryFile.ImageName} in search paths: " + $"{file} (on-disk: {fileInfo.ImageSize}, trace: {binaryFile.ImageSize})"); } } } } catch (Exception ex) { Trace.TraceError($"Exception searching for binary {binaryFile.ImageName} in {path}: {ex.Message}"); } } return null; } public bool Initialize() { if (!File.Exists(filePath_)) { return false; } try { var stream = File.OpenRead(filePath_); reader_ = new PEReader(stream); return reader_.PEHeaders != null; // Throws BadImageFormatException on invalid file. } catch (Exception ex) { Trace.WriteLine($"Failed to read PE binary file: {filePath_}"); return false; } } public ReadOnlyMemory GetSectionData(SectionHeader header) { var data = reader_.GetSectionData(header.VirtualAddress); var array = data.GetContent(); return array.AsMemory(); } private bool IsARM64ECBinary() { if (reader_.PEHeaders.PEHeader == null || reader_.PEHeaders.PEHeader.LoadConfigTableDirectory.Size <= 0 || !reader_.PEHeaders.TryGetDirectoryOffset(reader_.PEHeaders.PEHeader.LoadConfigTableDirectory, out int offset)) { return false; } var imageData = reader_.GetEntireImage(); var configTableData = imageData.GetContent(offset, reader_.PEHeaders.PEHeader.LoadConfigTableDirectory.Size); var span = MemoryMarshal.Cast(configTableData.AsSpan()); return span.Length > 0 && span[0].CHPEMetadataPointer != 0; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public struct IMAGE_LOAD_CONFIG_DIRECTORY64 { public uint Size; public uint TimeDateStamp; public ushort MajorVersion; public ushort MinorVersion; public uint GlobalFlagsClear; public uint GlobalFlagsSet; public uint CriticalSectionDefaultTimeout; public ulong DeCommitFreeBlockThreshold; public ulong DeCommitTotalFreeThreshold; public ulong LockPrefixTable; public ulong MaximumAllocationSize; public ulong VirtualMemoryThreshold; public ulong ProcessAffinityMask; public uint ProcessHeapFlags; public ushort CSDVersion; public ushort DependentLoadFlags; public ulong EditList; public ulong SecurityCookie; public ulong SEHandlerTable; public ulong SEHandlerCount; public ulong GuardCFCheckFunctionPointer; public ulong GuardCFDispatchFunctionPointer; public ulong GuardCFFunctionTable; public ulong GuardCFFunctionCount; public uint GuardFlags; public IMAGE_LOAD_CONFIG_CODE_INTEGRITY CodeIntegrity; public ulong GuardAddressTakenIatEntryTable; public ulong GuardAddressTakenIatEntryCount; public ulong GuardLongJumpTargetTable; public ulong GuardLongJumpTargetCount; public ulong DynamicValueRelocTable; public ulong CHPEMetadataPointer; public ulong GuardRFFailureRoutine; public ulong GuardRFFailureRoutineFunctionPointer; public uint DynamicValueRelocTableOffset; public ushort DynamicValueRelocTableSection; public ushort Reserved2; public ulong GuardRFVerifyStackPointerFunctionPointer; public uint HotPatchTableOffset; public uint Reserved3; public ulong EnclaveConfigurationPointer; public ulong VolatileMetadataPointer; public ulong GuardEHContinuationTable; public ulong GuardEHContinuationCount; } [StructLayout(LayoutKind.Sequential)] public struct IMAGE_LOAD_CONFIG_CODE_INTEGRITY { public ushort Flags; public ushort Catalog; public uint CatalogOffset; public uint Reserved; } } ================================================ FILE: src/ProfileExplorerCore/Binary/SourceFileDebugInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProtoBuf; namespace ProfileExplorer.Core.Binary; [ProtoContract(SkipConstructor = true)] public struct SourceFileDebugInfo : IEquatable { public SourceFileDebugInfo(string filePath, string originalFilePath, int startLine = 0, bool hasChecksumMismatch = false) { FilePath = filePath != null ? string.Intern(filePath) : null; OriginalFilePath = originalFilePath != null ? string.Intern(originalFilePath) : null; StartLine = startLine; HasChecksumMismatch = hasChecksumMismatch; } [ProtoMember(1)] public string FilePath { get; set; } [ProtoMember(2)] public string OriginalFilePath { get; set; } [ProtoMember(3)] public int StartLine { get; set; } [ProtoMember(4)] public bool HasChecksumMismatch { get; set; } public static readonly SourceFileDebugInfo Unknown = new(null, null, -1); public bool IsUnknown => FilePath == null; public bool HasFilePath => !string.IsNullOrEmpty(FilePath); public bool HasOriginalFilePath => !string.IsNullOrEmpty(OriginalFilePath); public bool Equals(SourceFileDebugInfo other) { return FilePath.Equals(other.FilePath, StringComparison.Ordinal) && OriginalFilePath.Equals(other.OriginalFilePath, StringComparison.Ordinal) && StartLine == other.StartLine && HasChecksumMismatch == other.HasChecksumMismatch; } public override bool Equals(object obj) { return obj is SourceFileDebugInfo other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(FilePath, OriginalFilePath, StartLine, HasChecksumMismatch); } } ================================================ FILE: src/ProfileExplorerCore/Binary/SourceLineDebugInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR.Tags; using ProtoBuf; namespace ProfileExplorer.Core.Binary; [ProtoContract(SkipConstructor = true)] public struct SourceLineDebugInfo : IEquatable { [ProtoMember(1)] public int OffsetStart { get; set; } // Offset in bytes relative to function start. [ProtoMember(2)] public int OffsetEnd { get; set; } // Offset in bytes relative to function start. [ProtoMember(3)] public int Line { get; set; } [ProtoMember(4)] public int Column { get; set; } [ProtoMember(5)] public string FilePath { get; private set; } //? Move to FunctionDebugInfo, add OriginalFilePath for SourceLink public List Inlinees { get; set; } public static readonly SourceLineDebugInfo Unknown = new(-1, -1); public bool IsUnknown => Line == -1; public SourceLineDebugInfo(int offsetStart, int line, int column = 0, string filePath = null) { OffsetStart = offsetStart; OffsetEnd = offsetStart; Line = line; Column = column; FilePath = filePath != null ? string.Intern(filePath) : null; } public void AddInlinee(SourceStackFrame inlinee) { Inlinees ??= new List(); Inlinees.Add(inlinee); } public bool HasInlinee(SourceStackFrame inlinee) { return Inlinees != null && Inlinees.Contains(inlinee); } public SourceStackFrame FindSameFunctionInlinee(SourceStackFrame inlinee) { return Inlinees?.Find(item => item.HasSameFunction(inlinee)); } public bool Equals(SourceLineDebugInfo other) { return OffsetStart == other.OffsetStart && Line == other.Line && Column == other.Column && FilePath.Equals(other.FilePath, StringComparison.Ordinal); } public override bool Equals(object obj) { return obj is SourceLineDebugInfo other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(FilePath, Line, Column); } } ================================================ FILE: src/ProfileExplorerCore/Binary/SymbolFileCache.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading.Tasks; using ProfileExplorer.Core.FileFormat; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Binary; [ProtoContract] public class SymbolFileCache { private static int CurrentFileVersion = 2; private static int MinSupportedFileVersion = 2; [ProtoMember(1)] public int Version { get; set; } [ProtoMember(2)] public SymbolFileDescriptor SymbolFile { get; set; } [ProtoMember(3)] public List FunctionList { get; set; } public static string DefaultCacheDirectoryPath => Path.Combine(Path.GetTempPath(), "ProfileExplorer", "symcache"); public static async Task SerializeAsync(SymbolFileCache symCache, string directoryPath) { try { symCache.Version = CurrentFileVersion; var outStream = new MemoryStream(); Serializer.Serialize(outStream, symCache); outStream.Position = 0; if (!Directory.Exists(directoryPath)) { Directory.CreateDirectory(directoryPath); } string cacheFile = MakeCacheFilePath(symCache.SymbolFile); string cachePath = Path.Combine(directoryPath, cacheFile); //? TODO: Convert everything to RunSync or add the support in the FileArchive return await FileArchive.CreateFromStreamAsync(outStream, cacheFile, cachePath).ConfigureAwait(false); } catch (Exception ex) { Trace.WriteLine($"Failed to save symbol file cache: {ex.Message}"); return false; } } public static async Task DeserializeAsync(SymbolFileDescriptor symbolFile, string directoryPath) { try { string cacheFile = MakeCacheFilePath(symbolFile); string cachePath = Path.Combine(directoryPath, cacheFile); if (!File.Exists(cachePath)) { return null; } using var archive = await FileArchive.LoadAsync(cachePath).ConfigureAwait(false); if (archive != null) { using var stream = await archive.ExtractFileToMemoryAsync(cacheFile); if (stream != null) { var symCache = Serializer.Deserialize(stream); if (symCache.Version < MinSupportedFileVersion) { Trace.WriteLine($"File version mismatch in deserialized symbol file cache"); Trace.WriteLine($" actual: {symCache.Version} vs min supported {MinSupportedFileVersion}"); return null; } // Ensure it's a cache for the same symbol file. if (symCache.SymbolFile.Equals(symbolFile)) { return symCache; } Trace.WriteLine($"Symbol file mismatch in deserialized symbol file cache"); Trace.WriteLine($" actual: {symCache.SymbolFile} vs expected {symbolFile}"); } } } catch (Exception ex) { Trace.WriteLine($"Failed to load symbol file cache: {ex.Message}"); } return null; } private static string MakeCacheFilePath(SymbolFileDescriptor symbolFile) { return $"{Utils.TryGetFileName(symbolFile.FileName)}-{symbolFile.Id}-{symbolFile.Age}.cache"; } } ================================================ FILE: src/ProfileExplorerCore/Collections/CompressedSegmentedList.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. // Uncomment to disable compression. // #define DISABLE_COMPRESSION using System; using System.Buffers; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.IO.Compression; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; namespace ProfileExplorer.Core.Collections; public sealed class CompressedSegmentedList : IDisposable, IList where T : struct { // The GC Large Object Heap is used for allocations > 85 KB, // ensure each segments stays below that limit. private const int LOHObjectSize = 80 * 1024; private static readonly int SegmentLength = Math.Max(1, LOHObjectSize / Unsafe.SizeOf()); private List segments_; private Segment activeSegment_; private int count_; // Total number of items in all segments. private int segmentLength_; // Number of items per segment. private int prefetchLimit_; // Segments to prefetch ahead. private BlockingCollection taskQueue_; // Pending compression tasks. private List taskQueueThreadTasks_; // Tasks representing the compression threads. #if DEBUG private int version_; #endif public CompressedSegmentedList(bool useThreads = true, bool prefetch = true, int prefetchLimit = 2) : this(SegmentLength, useThreads, prefetch, prefetchLimit) { } public CompressedSegmentedList(int segmentLength, bool useThreads = true, bool prefetch = true, int prefetchLimit = 2) { segmentLength_ = segmentLength; segments_ = new List(); if (useThreads) { prefetchLimit_ = prefetch ? prefetchLimit : 0; SetupCompressionThreads(); } } public int Count => count_; public bool IsReadOnly => false; public T this[int index] { get => GetValue(index); set => SetValue(index, value); } // Round up number to the nearest multiple of the segment length. public static int RoundUpToSegmentLength(int n) { Debug.Assert(n > 0); return ((n - 1) / SegmentLength + 1) * SegmentLength; } public void Wait(bool reset = true) { #if !DISABLE_COMPRESSION taskQueue_.CompleteAdding(); Task.WhenAll(taskQueueThreadTasks_); Task.WhenAll(taskQueueThreadTasks_).Wait(); if (reset) { SetupCompressionThreads(); } #endif } public void CompressRange(int startIndex, int endIndex) { Debug.Assert(endIndex >= startIndex); int startSegment = startIndex / segmentLength_; int endSegment = endIndex / segmentLength_; if (startSegment >= segments_.Count || endSegment >= segments_.Count) { Debug.Assert(false, "Invalid segment range"); return; } for (int i = startSegment; i <= endSegment; i++) { segments_[i].CompressValues(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public T GetValue(int index) { Debug.Assert(index < count_); int activeIndex = GetActiveSegmentIndex(index); if (activeIndex != -1) { return activeSegment_.GetValue(activeIndex); } var segment = segments_[index / segmentLength_]; return segment.GetValue(index % segmentLength_); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T GetValueRef(int index) { Debug.Assert(index < count_); int activeIndex = GetActiveSegmentIndex(index); if (activeIndex != -1) { return ref activeSegment_.GetValueRef(activeIndex); } var segment = segments_[index / segmentLength_]; return ref segment.GetValueRef(index % segmentLength_); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetValue(int index, T value) { Debug.Assert(index < count_); int activeIndex = GetActiveSegmentIndex(index); if (activeIndex != -1) { activeSegment_.SetValue(activeIndex, value); } else { var segment = segments_[index / segmentLength_]; segment.SetValue(index % segmentLength_, value); } #if DEBUG version_++; #endif } public RangeEnumerator Enumerate(int rangeStart, int rangeEnd, bool recompress = true) { return new RangeEnumerator(this, rangeStart, rangeEnd, recompress); } public override bool Equals(object obj) { return obj is CompressedSegmentedList list && EqualityComparer>.Default.Equals(segments_, list.segments_) && count_ == list.count_ && segmentLength_ == list.segmentLength_; } public override int GetHashCode() { return HashCode.Combine(segments_, count_, segmentLength_); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T value) { EnsureSegmentReady(); activeSegment_.AddValue(value); count_++; #if DEBUG version_++; #endif } public void Clear() { segments_.Clear(); activeSegment_ = null; count_ = 0; #if DEBUG version_++; #endif } public bool Contains(T item) { foreach (var value in this) { if (value.Equals(item)) { return true; } } return false; } public bool Remove(T item) { throw new NotImplementedException(); } public void CopyTo(T[] array, int arrayIndex) { if (array.Length + arrayIndex < count_) { throw new ArgumentOutOfRangeException(nameof(arrayIndex), "Array length too small"); } foreach (var segment in segments_) { segment.CopyTo(array, arrayIndex); arrayIndex += segment.Count; } } public void Dispose() { #if !DISABLE_COMPRESSION // End compression tasks and free memory. Wait(false); taskQueue_?.Dispose(); taskQueue_ = null; foreach (var task in taskQueueThreadTasks_) { task.Dispose(); } taskQueueThreadTasks_ = null; #endif } public IEnumerator GetEnumerator() { return Enumerate(0, Count).GetEnumerator(); } public int IndexOf(T item) { int index = 0; foreach (var value in this) { if (value.Equals(item)) { return index; } index++; } return -1; } public void Insert(int index, T item) { throw new NotImplementedException(); } public void RemoveAt(int index) { throw new NotImplementedException(); } private void EnsureSegmentReady() { // Allocate a new segment if the current one is full, // then compress the previous one. if (activeSegment_ == null || activeSegment_.Count == segmentLength_) { if (activeSegment_ != null) { activeSegment_.CompressValues(); } activeSegment_ = new Segment(this, segmentLength_); segments_.Add(activeSegment_); } else if (activeSegment_.IsCompressed) { activeSegment_.DecompressValues(); } } private Task ScheduleCompressionTask(Action action) { var task = new Task(action); if (!taskQueue_.TryAdd(task)) { task.RunSynchronously(); } return task; } private void SetupCompressionThreads() { #if !(DISABLE_COMPRESSION) taskQueue_ = new BlockingCollection(); taskQueueThreadTasks_ = new List(); int threads = 1 + prefetchLimit_; // 1 used for compression. for (int i = 0; i < threads; i++) { taskQueueThreadTasks_.Add(Task.Run(() => { try { while (!taskQueue_.IsCompleted) { if (taskQueue_.TryTake(out var task, 1000)) { // Execute the actual (de)compression task. task.Start(); task.Wait(); } } } catch (Exception ex) { Trace.WriteLine($"Failure executing compression task: {ex.Message}"); } })); } #endif } private int GetActiveSegmentIndex(int index) { // Check if index is in the active segment to avoid the expensive DIV below. if (activeSegment_ != null) { int startIndex = segments_.Count * segmentLength_; if (index >= startIndex && index < startIndex + activeSegment_.Count) { return index - startIndex; } } return -1; } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public struct RangeEnumerator : IEnumerable { private CompressedSegmentedList target_; private int rangeStart_; private int rangeEnd_; private int segmentStart_; private int segmentEnd_; private bool recompress_; public RangeEnumerator(CompressedSegmentedList target, int rangeStart, int rangeEnd, bool recompress) { Debug.Assert(rangeStart <= target.Count); Debug.Assert(rangeEnd <= target.Count); Debug.Assert(rangeEnd >= rangeStart); target_ = target; rangeStart_ = rangeStart; rangeEnd_ = rangeEnd; segmentStart_ = rangeStart / target.segmentLength_; segmentEnd_ = rangeEnd / target.segmentLength_; recompress_ = recompress; } public IEnumerator GetEnumerator() { if (target_.segments_.Count == 0) { yield break; } int lastPrefetchIndex = segmentStart_; Segment prevSegment = null; #if DEBUG int initialVersion = target_.version_; #endif for (int segmentIndex = segmentStart_; segmentIndex <= segmentEnd_; segmentIndex++) { var segment = target_.segments_[segmentIndex]; segment.DecompressValues(); // // Ignore values in the segment before rangeStart and after rangeEnd. int segmentValueIndex = segmentIndex * target_.segmentLength_; int segmentValueStart = segmentValueIndex < rangeStart_ ? rangeStart_ - segmentValueIndex : 0; int segmentValueEnd = segmentValueIndex + segment.Count > rangeEnd_ ? rangeEnd_ - segmentValueIndex : segment.Count; for (int i = segmentValueStart; i < segmentValueEnd; i++) { #if DEBUG if (initialVersion != target_.version_) { throw new InvalidOperationException("List modified, potential thread racing bug"); } #endif yield return segment.GetValueDirect(i); } // Prefetch segments in advance on another thread // to hide the delay of decompressing the data. int prefetchEnd = segmentIndex + target_.prefetchLimit_; if (target_.prefetchLimit_ > 0 && prefetchEnd < segmentEnd_) { for (; lastPrefetchIndex < prefetchEnd; lastPrefetchIndex++) { target_.segments_[lastPrefetchIndex].DecompressValues(true); lastPrefetchIndex = prefetchEnd; } } // Re-compress the values, done on another thread. // Don't compress the last segment, it's likely that more values are added to it. if (recompress_) { prevSegment?.CompressValues(); } prevSegment = segment; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private sealed class Segment { private CompressedSegmentedList parent_; private Task activeTask_; // Task used to (de)compress, null if no pending task. private byte[] data_; // Compressed value data. private T[] values_; // Decompressed values, if null in compressed state. private int count_; // Number of values < capacity. private int size_; // Size in bytes of uncompressed capacity. private object lockObject_; public Segment(CompressedSegmentedList parent, int capacity) { parent_ = parent; values_ = ArrayPool.Shared.Rent(capacity); size_ = capacity * Unsafe.SizeOf(); lockObject_ = new object(); } public int Count => count_; public bool WasCompressed => data_ != null; public bool IsCompressed => values_ == null; public bool IsBeingCompressed => IsCompressed && !WasCompressed; public T this[int index] { get => GetValue(index); set => SetValue(index, value); } private static byte[] CompressImpl(T[] values, int segmentSize) { // Since the pooled array can be larger than needed, slice it to the right length. var arraySpan = values.AsSpan(); var byteSpan = MemoryMarshal.AsBytes(arraySpan).Slice(0, segmentSize); int bufferSize = BrotliEncoder.GetMaxCompressedLength(segmentSize); byte[] tempBuffer = ArrayPool.Shared.Rent(bufferSize); var bufferSpan = tempBuffer.AsSpan(); var encoder = new BrotliEncoder(5, 10); var result = encoder.Compress(byteSpan, bufferSpan, out int bytesConsumed, out int bytesWritten, true); Debug.Assert(result == OperationStatus.Done); encoder.Flush(bufferSpan, out int extraBytesWritten); bytesWritten += extraBytesWritten; // Seems to be always 0. // Copy to another array, the initial estimate is as large as the input. byte[] outBuffer = new byte[bytesWritten]; Array.Copy(tempBuffer, 0, outBuffer, 0, bytesWritten); // Return array to the pool. ArrayPool.Shared.Return(tempBuffer); ArrayPool.Shared.Return(values); encoder.Dispose(); return outBuffer; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public T GetValue(int index) { Debug.Assert(index < count_); if (IsCompressed) { DecompressValues(); } return values_[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void AddValue(T value) { Debug.Assert(count_ < values_.Length); values_[count_++] = value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetValue(int index, T value) { Debug.Assert(index < count_); DecompressValues(); values_[index] = value; // If the values were compressed before, discard the data // since it doesn't match the current values anymore. if (WasCompressed) { lock (lockObject_) { data_ = null; } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T GetValueRef(int index) { Debug.Assert(index < count_); DecompressValues(); // If the values were compressed before, discard the data // since it doesn't match the current values anymore. if (WasCompressed) { lock (this) { data_ = null; } } return ref values_[index]; } public void DecompressValues(bool prefetch = false) { if (!IsCompressed) { // Already decompressed. Debug.Assert(values_ != null); return; } // Check if another (de)compression task is running and wait for it. // activeTask_ is being reseet by the thread, use a copy. Task task = null; lock (lockObject_) { task = activeTask_; } if (task != null) { task.Wait(); if (!IsCompressed) { Debug.Assert(values_ != null); return; } } // Decompress the data. In prefetch mode run it on another thread. lock (this) { if (!IsCompressed) { Debug.Assert(values_ != null); return; } if (prefetch) { activeTask_ = parent_.ScheduleCompressionTask(() => { var result = DecompressImpl(data_, size_); lock (lockObject_) { values_ = result; activeTask_ = null; } }); } else { values_ = DecompressImpl(data_, size_); } } } public void CompressValues() { #if !DISABLE_COMPRESSION lock (this) { if (WasCompressed || IsBeingCompressed) { values_ = null; // Free array. return; } Debug.Assert(data_ == null); var valuesCopy = values_; values_ = null; // Put into the compressed state. // Compress on another thread. activeTask_ = parent_.ScheduleCompressionTask(() => { byte[] result = CompressImpl(valuesCopy, size_); lock (this) { data_ = result; activeTask_ = null; } }); } #endif } public override string ToString() { return $"Segment size {size_}, count {count_}, task {activeTask_ != null}, compressed {IsCompressed}, being/was compressed {IsBeingCompressed}/{WasCompressed}"; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal T GetValueDirect(int index) { return values_[index]; } internal void CopyTo(T[] array, int arrayIndex) { DecompressValues(); values_.CopyTo(array, arrayIndex); } private T[] DecompressImpl(byte[] data, int segmentSize) { var dataSpan = data.AsSpan(); int length = segmentSize / Unsafe.SizeOf(); // Use an ArrayPool to reduce GC pressure, values are usually used temporarely. // Since the pooled array can be larger than needed, slice it to the right length. var values = ArrayPool.Shared.Rent(length); var decompressedSpan = MemoryMarshal.AsBytes(values.AsSpan()).Slice(0, segmentSize); bool result = BrotliDecoder.TryDecompress(dataSpan, decompressedSpan, out int readBytes); Debug.Assert(result); Debug.Assert(readBytes == segmentSize); return values; } } } ================================================ FILE: src/ProfileExplorerCore/Collections/SparseBitVector.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; namespace ProfileExplorer.Core.Collections; public class SparseBitvector : IEquatable { private Node startNode_; private Node lastNode_; public bool HasBitsSet { get { var node = startNode_; while (node != null) { if (node.HasBitsSet) return true; node = node.NextNode; } return false; } } public int SetBitCount { get { int sum = 0; var node = startNode_; while (node != null) { sum += node.SetBitCount; node = node.NextNode; } return sum; } } public bool this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => TestBit(index); [MethodImpl(MethodImplOptions.AggressiveInlining)] set => SetBitState(index, value); } public bool Equals(SparseBitvector other) { var a = startNode_; var b = other.startNode_; while (a != null && b != null) { if (!a.Equals(b)) { return false; } a = a.NextNode; b = b.NextNode; } return a == null && b == null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetBit(int bit) { SetBitState(bit, true); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ResetBit(int bit) { SetBitState(bit, false); } public void ResetAllBits() { startNode_ = null; lastNode_ = null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetBitState(int bit, bool state) { var node = TryUseLastNode(bit); if (node != null) { node[bit] = state; return; } node = FindOrCreateNode(bit); node[bit] = state; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TestBit(int bit) { var node = TryUseLastNode(bit); if (node != null) { return node[bit]; } Node insertionNode = null; node = TryFindNode(bit, ref insertionNode); return node != null && node[bit]; } public void And(SparseBitvector other) { var a = startNode_; var b = other.startNode_; Node prevA = null; if (b == null) { ResetAllBits(); return; } while (a != null && b != null) { if (a.StartBit == b.StartBit) { // Bits in both a and b. a.And(b); prevA = a; a = a.NextNode; b = b.NextNode; } else if (a.StartBit > b.StartBit) { // Bits in b but not in a. b = b.NextNode; } else { var nextNode = a.NextNode; RemoveNode(a, prevA); a = nextNode; } } // All the ranges that remain need to be removed (no ranges in 'other' match). while (a != null) { var nextNode = a.NextNode; RemoveNode(a, prevA); a = nextNode; } } public void ForEachSetBit(Func action) { var node = startNode_; while (node != null) { if (!node.ForEachSetBit(action)) { return; } node = node.NextNode; } } public override bool Equals(object? obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((SparseBitvector)obj); } public override int GetHashCode() { int hash = 0; var node = startNode_; while (node != null) { hash = HashCode.Combine(hash, node.GetHashCode()); } return hash; } private Node FindOrCreateNode(int bit) { Node insertionNode = null; var node = TryFindNode(bit, ref insertionNode); if (node == null) { node = AllocateNode(bit); InsertNode(node, insertionNode); } return node; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private Node TryUseLastNode(int bit) { if (lastNode_ != null && lastNode_.IsBitInRange(bit)) { return lastNode_; } return null; } private Node TryFindNode(int bit, ref Node insertionNode) { var node = startNode_; if (lastNode_ != null && bit >= lastNode_.EndBit) { node = lastNode_; } Node prevNode = null; while (node != null) { if (node.IsBitInRange(bit)) { lastNode_ = node; return node; } if (node.StartBit > bit) { insertionNode = prevNode; lastNode_ = prevNode; return null; } prevNode = node; node = node.NextNode; } insertionNode = prevNode; return null; } private Node AllocateNode(int bit) { int startBit = bit / Node.BitsPerNode * Node.BitsPerNode; return new Node(startBit); } private void FreeNode(Node node) { node.NextNode = null; } private void InsertNode(Node node, Node prevNode) { if (prevNode != null) { node.NextNode = prevNode.NextNode; prevNode.NextNode = node; if (prevNode == lastNode_) { lastNode_ = node; } } else { node.NextNode = startNode_; startNode_ = node; } } private void RemoveNode(Node node, Node prevNode) { if (prevNode != null) { prevNode.NextNode = node.NextNode; } else { startNode_ = node.NextNode; } FreeNode(node); } public class Node : IEquatable { public const int BitsPerNode = 256; private const int ValuesPerNode = BitsPerNode / 64; private const int DivShift = 6; private const int RemMask = (1 << DivShift) - 1; private readonly ulong[] data_; public Node() { data_ = new ulong[ValuesPerNode]; } public Node(int startBit) { data_ = new ulong[ValuesPerNode]; StartBit = startBit; } public int StartBit { get; set; } public Node NextNode { get; set; } public int EndBit => StartBit + BitsPerNode; public int SetBitCount { get { int sum = 0; for (int i = 0; i < ValuesPerNode; i++) { sum += BitOperations.PopCount(data_[i]); } return sum; } } public bool HasBitsSet { get { var v = AsVector(); var v0 = Vector.Zero; for (int i = 0; i < v.Length; i++) { if (!v[i].Equals(v0)) { return true; } } return false; } } public bool this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { index -= StartBit; return (data_[index >> DivShift] & 1ul << (index & RemMask)) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { index -= StartBit; if (value) { data_[index >> DivShift] |= 1ul << (index & RemMask); } else { data_[index >> DivShift] &= ~(1ul << (index & RemMask)); } } } public bool Equals(Node other) { return StartBit == other.StartBit && data_.SequenceEqual(other.data_); } public static bool operator ==(Node? left, Node? right) { return Equals(left, right); } public static bool operator !=(Node? left, Node? right) { return !Equals(left, right); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void And(Node other) { var v1 = AsVector(); var v2 = other.AsVector(); for (int i = 0; i < v1.Length; i++) { v1[i] &= v2[i]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Or(Node other) { var v1 = AsVector(); var v2 = other.AsVector(); for (int i = 0; i < v1.Length; i++) { v1[i] |= v2[i]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Xor(Node other) { var v1 = AsVector(); var v2 = other.AsVector(); for (int i = 0; i < v1.Length; i++) { v1[i] ^= v2[i]; } } public void ResetAllBits() { var v = AsVector(); for (int i = 0; i < v.Length; i++) { v[i] ^= v[i]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsBitInRange(int bit) { return bit >= StartBit && bit < StartBit + BitsPerNode; } public bool ForEachSetBit(Func action) { for (int i = StartBit; i < EndBit; i++) { if (this[i] && !action(i)) { return false; } } return true; } public override bool Equals(object obj) { return Equals((Node)obj); } public override int GetHashCode() { return data_.GetHashCode(); } public override string ToString() { var sb = new StringBuilder(); foreach (ulong value in data_) { for (int i = 0; i < 64; i++) { if ((value & 1ul << i) != 0) { sb.Append(1); } else sb.Append(0); } sb.Append(' '); } return sb.ToString(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private Span> AsVector() { return MemoryMarshal.Cast>(data_); } } } ================================================ FILE: src/ProfileExplorerCore/Collections/StringTrie.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Collections; // A compact representation of a Trie using only arrays, which makes it // more cache friendly and much faster (>10x for large tries) than a simple trie // that uses node objects for each letter and lists of successor nodes. // // A significant advantage vs. using a Dictionary is that it can be queried // with a Span, which avoids creating a temporary string just for the query // in code that uses spans, like the lexer/parsers. public class StringTrie { private List> nodes_; // first child index, count private List> childLetters_; // letter, child index private List> terminalNodes_; private int lastNodeId_; private int lastChildId_; public StringTrie() { nodes_ = new List>(); childLetters_ = new List>(); terminalNodes_ = new List>(); } public StringTrie(Dictionary values) : this() { Build(values); } public void Build(List> values) { // The words must be added in layers: first the first letter from all words, // then the second letter, and so on, until nu suffix part remains. // This algorithm needs the words to be sorted lexicographically. int layer = 0; bool changed = true; int rootNode = AddNode(); values.Sort((a, b) => string.Compare(a.Item1, b.Item1, StringComparison.Ordinal)); while (changed) { changed = false; layer++; foreach (var pair in values) { if (layer <= pair.Item1.Length) { changed = true; int newNodeId = AddWord(pair.Item1, 0, layer, rootNode); if (layer == pair.Item1.Length) { // Mark as terminal if the entire word has been processed. SetTerminalNode(newNodeId, pair.Item2); } } } } } public void Build(Dictionary values) { var list = new List>(values.Count); foreach (var pair in values) { list.Add(new Tuple(pair.Key, pair.Value)); } Build(list); } public bool TryGetValue(string value, out T outValue, bool caseInsensitive = false) { int nodeId = 0; for (int i = 0; i < value.Length; i++) { char letter = value[i]; if (caseInsensitive) { letter = char.ToLowerInvariant(letter); } int childId = FindChildForLetter(nodeId, letter, caseInsensitive); if (childId == -1) { outValue = default(T); return false; } nodeId = childId; } return IsTerminalNode(nodeId, out outValue); } public bool TryGetValue(ReadOnlySpan value, out T outValue, bool caseInsensitive = false) { int nodeId = 0; for (int i = 0; i < value.Length; i++) { char letter = value[i]; if (caseInsensitive) { letter = char.ToLowerInvariant(letter); } int childId = FindChildForLetter(nodeId, letter, caseInsensitive); if (childId == -1) { outValue = default(T); return false; } nodeId = childId; } return IsTerminalNode(nodeId, out outValue); } public bool TryGetValue(ReadOnlyMemory value, out T outValue, bool caseInsensitive = false) { return TryGetValue(value.Span, out outValue, caseInsensitive); } public bool Contains(string value, bool caseInsensitive = false) { return TryGetValue(value, out _, caseInsensitive); } public bool Contains(ReadOnlyMemory value, bool caseInsensitive = false) { return TryGetValue(value, out _, caseInsensitive); } private int AddNode() { nodes_.Add(new Tuple(-1, 0)); return lastNodeId_++; } private void AddChildNode(int parentNodeId, char letter, int childNodeId) { childLetters_.Add(new Tuple(letter, childNodeId)); var parentChildInfo = nodes_[parentNodeId]; if (parentChildInfo.Item1 == -1) { // First child being added. nodes_[parentNodeId] = new Tuple(lastChildId_, 1); } else { // Increment number of children. nodes_[parentNodeId] = new Tuple(parentChildInfo.Item1, parentChildInfo.Item2 + 1); } lastChildId_++; } private void SetTerminalNode(int nodeId, T value) { while (terminalNodes_.Count <= nodeId) { terminalNodes_.Add(new Optional()); } terminalNodes_[nodeId] = value; } private int AddWord(string word, int position, int maxPosition, int nodeId) { if (position == maxPosition) { return nodeId; } char letter = word[position]; int childNodeId = FindChildForLetter(nodeId, letter); if (childNodeId == -1) { // First time this letter is inserted as a child. childNodeId = AddNode(); AddChildNode(nodeId, letter, childNodeId); } return AddWord(word, position + 1, maxPosition, childNodeId); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private int FindChildForLetter(int nodeId, char letter, bool caseInsensitive = false) { var childInfo = nodes_[nodeId]; for (int i = 0; i < childInfo.Item2; i++) { var letterInfo = childLetters_[childInfo.Item1 + i]; if (letterInfo.Item1 == letter) { return letterInfo.Item2; } if (caseInsensitive && char.ToLowerInvariant(letterInfo.Item1) == letter) { return letterInfo.Item2; } } return -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool IsTerminalNode(int nodeId, out T value) { if (terminalNodes_[nodeId].HasValue) { value = (T)terminalNodes_[nodeId]; return true; } value = default(T); return false; } } ================================================ FILE: src/ProfileExplorerCore/Collections/TinyList.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace ProfileExplorer.Core.Collections; // A lightweight list implementation that stores a single item or an array of items. public struct TinyList : IList { private object value_; // Either T or array of T. private int count_; [MethodImpl(MethodImplOptions.AggressiveInlining)] public TinyList() { value_ = null; count_ = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public TinyList(T item) { value_ = item; count_ = 1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public TinyList(IList list) { if (list == null || list.Count == 0) { value_ = null; count_ = 0; } else if (list.Count == 1) { value_ = list[0]; count_ = 1; } else { var array = new T[list.Count]; list.CopyTo(array, 0); value_ = array; count_ = list.Count; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public IEnumerator GetEnumerator() { if (count_ == 0) { yield break; } if (count_ == 1) { yield return (T)value_; } else { var array = (T[])value_; for (int i = 0; i < count_; i++) { yield return array[i]; } } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(T item) { if (count_ == 0) { value_ = item; count_ = 1; } else if (count_ == 1) { var array = new T[2]; array[0] = (T)value_; array[1] = item; value_ = array; count_ = 2; } else { var array = (T[])value_; if (array.Length == count_) { var newArray = new T[array.Length * 2]; array.CopyTo(newArray, 0); value_ = array = newArray; } array[count_] = item; count_++; } } public void Clear() { value_ = null; count_ = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Contains(T item) { return IndexOf(item) != -1; } public bool Contains(Func comparer) { return IndexOf(comparer) != -1; } public T Find(Func comparer) { int index = IndexOf(comparer); return index != -1 ? this[index] : default(T); } public void CopyTo(T[] array, int arrayIndex) { if (array == null) throw new ArgumentNullException(nameof(array)); if (arrayIndex < 0) throw new ArgumentOutOfRangeException(nameof(arrayIndex)); if (array.Length - arrayIndex < count_) throw new ArgumentException("Destination array is not long enough"); if (count_ == 0) return; if (count_ == 1) { array[arrayIndex] = (T)value_; return; } var src = (T[])value_; Array.Copy(src, 0, array, arrayIndex, count_); } public bool Remove(T item) { throw new NotImplementedException(); } public int Count => count_; public bool IsReadOnly => false; public int IndexOf(T item) { if (count_ == 0) { return -1; } if (count_ == 1) { if (EqualityComparer.Default.Equals((T)value_, item)) { return 0; } } else { var array = (T[])value_; for (int i = 0; i < count_; i++) { if (EqualityComparer.Default.Equals(array[i], item)) { return i; } } } return -1; } public int IndexOf(Func comparer) { if (count_ == 0) { return -1; } if (count_ == 1) { if (comparer((T)value_)) { return 0; } } else { var array = (T[])value_; for (int i = 0; i < count_; i++) { if (comparer(array[i])) { return i; } } } return -1; } public void Insert(int index, T item) { // Not needed for current usage. Implement if required later. throw new NotSupportedException(); } public void RemoveAt(int index) { // Not needed for current usage. Implement if required later. throw new NotSupportedException(); } public T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { #if DEBUG if (index >= count_) { throw new IndexOutOfRangeException(); } #endif if (count_ == 1) { return (T)value_; } var array = (T[])value_; return array[index]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { #if DEBUG if (index >= count_) { throw new IndexOutOfRangeException(); } #endif if (count_ == 1) { value_ = value; } else { var array = (T[])value_; array[index] = value; } } } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ARM64Opcodes.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.Collections; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Compilers.ASM; public enum ARM64Opcode { RET, BL, BLR, B, BR, BEQ, BNE, BCS, BHS, BCC, BLO, BMI, BPL, BVS, BVC, BHI, BLS, BGE, BLT, BGT, BLE, BAL, TBZ, TBNZ, CBZ, CBNZ, NOP } public struct ARM64OpcodeInfo { public ARM64Opcode Opcode { get; set; } public InstructionKind Kind { get; set; } public ARM64OpcodeInfo(ARM64Opcode opcode, InstructionKind kind) { Opcode = opcode; Kind = kind; } } public static class ARM64Opcodes { private static readonly Dictionary opcodes_ = new() { {"B", new ARM64OpcodeInfo(ARM64Opcode.B, InstructionKind.Goto)}, {"BR", new ARM64OpcodeInfo(ARM64Opcode.BR, InstructionKind.Goto)}, {"RET", new ARM64OpcodeInfo(ARM64Opcode.RET, InstructionKind.Return)}, {"BEQ", new ARM64OpcodeInfo(ARM64Opcode.BEQ, InstructionKind.Branch)}, {"BNE", new ARM64OpcodeInfo(ARM64Opcode.BNE, InstructionKind.Branch)}, {"BCS", new ARM64OpcodeInfo(ARM64Opcode.BCS, InstructionKind.Branch)}, {"BHS", new ARM64OpcodeInfo(ARM64Opcode.BHS, InstructionKind.Branch)}, {"BCC", new ARM64OpcodeInfo(ARM64Opcode.BCC, InstructionKind.Branch)}, {"BLO", new ARM64OpcodeInfo(ARM64Opcode.BLO, InstructionKind.Branch)}, {"BMI", new ARM64OpcodeInfo(ARM64Opcode.BMI, InstructionKind.Branch)}, {"BPL", new ARM64OpcodeInfo(ARM64Opcode.BPL, InstructionKind.Branch)}, {"BVS", new ARM64OpcodeInfo(ARM64Opcode.BVS, InstructionKind.Branch)}, {"BVC", new ARM64OpcodeInfo(ARM64Opcode.BVC, InstructionKind.Branch)}, {"BHI", new ARM64OpcodeInfo(ARM64Opcode.BHI, InstructionKind.Branch)}, {"BLS", new ARM64OpcodeInfo(ARM64Opcode.BLS, InstructionKind.Branch)}, {"BGE", new ARM64OpcodeInfo(ARM64Opcode.BGE, InstructionKind.Branch)}, {"BLT", new ARM64OpcodeInfo(ARM64Opcode.BLT, InstructionKind.Branch)}, {"BGT", new ARM64OpcodeInfo(ARM64Opcode.BGT, InstructionKind.Branch)}, {"BLE", new ARM64OpcodeInfo(ARM64Opcode.BLE, InstructionKind.Branch)}, {"BAL", new ARM64OpcodeInfo(ARM64Opcode.BAL, InstructionKind.Branch)}, {"TBZ", new ARM64OpcodeInfo(ARM64Opcode.TBZ, InstructionKind.Branch)}, {"TBNZ", new ARM64OpcodeInfo(ARM64Opcode.TBNZ, InstructionKind.Branch)}, {"CBZ", new ARM64OpcodeInfo(ARM64Opcode.CBZ, InstructionKind.Branch)}, {"CBNZ", new ARM64OpcodeInfo(ARM64Opcode.CBNZ, InstructionKind.Branch)}, {"BL", new ARM64OpcodeInfo(ARM64Opcode.BL, InstructionKind.Call)}, {"BLR", new ARM64OpcodeInfo(ARM64Opcode.BLR, InstructionKind.Call)}, {"NOP", new ARM64OpcodeInfo(ARM64Opcode.NOP, InstructionKind.Other)} }; private static readonly StringTrie opcodesTrie_ = new(opcodes_); public static bool GetOpcodeInfo(string value, out ARM64OpcodeInfo info) { return opcodesTrie_.TryGetValue(value, out info, true); } //? TODO: Needs a TryGetValueUpper that does the value.ToUpper() on each letter public static bool GetOpcodeInfo(ReadOnlyMemory value, out ARM64OpcodeInfo info) { return opcodesTrie_.TryGetValue(value, out info, true); } public static bool IsOpcode(string value) { return GetOpcodeInfo(value, out _); } public static bool IsOpcode(ReadOnlyMemory value) { return opcodesTrie_.Contains(value); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMBinaryFileFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public class ASMBinaryFileFinder : IBinaryFileFinder { public async Task FindBinaryFileAsync(BinaryFileDescriptor binaryFile, SymbolFileSourceSettings settings = null) { if (settings == null) { // Make sure the binary directory is also included in the symbol search. settings = CoreSettingsProvider.SymbolSettings.Clone(); } return await PEBinaryInfoProvider.LocateBinaryFileAsync(binaryFile, settings).ConfigureAwait(false); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMCompilerIRInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; namespace ProfileExplorer.Core.Compilers.ASM; public sealed class ASMCompilerIRInfo : ICompilerIRInfo { public ASMCompilerIRInfo(IRMode mode) { Mode = mode; } public IRMode Mode { get; set; } public InstructionOffsetData InstructionOffsetData => Mode switch { IRMode.ARM64 => InstructionOffsetData.ConstantSize(4), _ => InstructionOffsetData.VariableSize(1, 16) }; public IRParsingErrorHandler CreateParsingErrorHandler() { return new ParsingErrorHandler(); } public IReachableReferenceFilter CreateReferenceFilter(FunctionIR function) { return new CFGReachabilityReferenceFilter(function); } public IRSectionParser CreateSectionParser(IRParsingErrorHandler errorHandler, long functionSize) { return new ASMIRSectionParser(functionSize, this, errorHandler); } public IRSectionReader CreateSectionReader(string filePath, bool expectSectionHeaders = true) { return new ASMIRSectionReader(filePath, expectSectionHeaders); } public IRSectionReader CreateSectionReader(byte[] textData, bool expectSectionHeaders = true) { return new ASMIRSectionReader(textData, expectSectionHeaders); } public OperandIR GetCallTarget(InstructionIR instr) { if (IsCallInstruction(instr) && instr.Sources.Count > 0) { return instr.Sources[0]; } return null; } public OperandIR GetBranchTarget(InstructionIR instr) { if (!(instr.IsBranch || instr.IsGoto) || instr.Sources.Count == 0) { return null; } switch (Mode) { case IRMode.x86_64: { return instr.Sources[0]; } case IRMode.ARM64: { if (!(instr.Opcode is ARM64Opcode)) { return null; } switch (instr.OpcodeAs()) { case ARM64Opcode.CBZ: case ARM64Opcode.CBNZ: { if (instr.Sources.Count == 2) { return instr.Sources[1]; } break; } case ARM64Opcode.TBZ: case ARM64Opcode.TBNZ: { if (instr.Sources.Count == 3) { return instr.Sources[2]; } break; } default: { return instr.Sources[0]; } } break; } } return null; } public BlockIR GetIncomingPhiOperandBlock(InstructionIR phiInstr, int opIndex) { return null; } public bool IsCallInstruction(InstructionIR instr) { return instr.IsCall || instr.IsGoto && instr.Sources.Count > 0 && !instr.Sources[0].IsLabelAddress; } public bool IsCopyInstruction(InstructionIR instr) { return false; } public bool IsIntrinsicCallInstruction(InstructionIR instr) { return false; } public bool IsLoadInstruction(InstructionIR instr) { switch (Mode) { case IRMode.x86_64: { return instr.Sources.Find(op => op.IsIndirection) != null; } case IRMode.ARM64: { //? TODO: Use opcodes like LDP return instr.Sources.Find(op => op.IsIndirection) != null; } } return false; } public bool IsPhiInstruction(InstructionIR instr) { return false; } public bool IsStoreInstruction(InstructionIR instr) { switch (Mode) { case IRMode.x86_64: { return instr.Destinations.Count > 0 && instr.Destinations[0].IsIndirection; } case IRMode.ARM64: { //? TODO return instr.Destinations.Count > 0 && instr.Destinations[0].IsIndirection; } } return false; } public bool IsNOP(InstructionIR instr) { if (instr.Opcode == null) { return false; } switch (Mode) { case IRMode.x86_64: { return instr.OpcodeAs() == x86Opcode.NOP; } case IRMode.ARM64: { return instr.OpcodeAs() == ARM64Opcode.NOP; } } return false; } public bool OperandsReferenceSameSymbol(OperandIR opA, OperandIR opB, bool exactCheck) { //? TODO: This should do a register check too, ARM64 not implemented return opA.Kind == opB.Kind && opA.HasName && opB.HasName && opA.NameValue.Span.Equals(opB.NameValue.Span, StringComparison.Ordinal); } public IRElement SkipCopyInstruction(InstructionIR instr) { return instr; } public InstructionIR GetTransferInstruction(BlockIR block) { return (block.Tuples.Count > 0 ? block.Tuples[^1] : null) as InstructionIR; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMCompilerInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Threading.Tasks; using System.Windows; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public class ASMCompilerInfoProvider : ICompilerInfoProvider { private readonly ASMNameProvider names_ = new(); private readonly ASMCompilerIRInfo ir_; private readonly IBinaryFileFinder binaryFileFinder_; private readonly IDebugFileFinder debugFileFinder_; private readonly IDebugInfoProviderFactory debugInfoProviderFactory_; private readonly IDiffFilterProvider diffFilterProvider_; public ASMCompilerInfoProvider(IRMode mode) { ir_ = new ASMCompilerIRInfo(mode); binaryFileFinder_ = new ASMBinaryFileFinder(); debugFileFinder_ = new ASMDebugFileFinder(); debugInfoProviderFactory_ = new ASMDebugInfoProviderFactory(); diffFilterProvider_ = new ASMDiffFilterProvider(this); } public virtual string CompilerIRName => "ASM"; public virtual CompilerIRKind CompilerIRKind => CompilerIRKind.ASM; public virtual string CompilerDisplayName => "ASM " + ir_.Mode; public virtual string OpenFileFilter => "ASM, Binary, Trace Files|*.asm;*.txt;*.log;*.exe;*.dll;*.sys;*.etl|All Files|*.*"; public virtual string OpenDebugFileFilter => "Debug Files|*.pdb|All Files|*.*"; public virtual string DefaultSyntaxHighlightingFile => (ir_.Mode == IRMode.ARM64 ? "ARM64" : "x86") + " ASM IR"; public ICompilerIRInfo IR => ir_; public INameProvider NameProvider => names_; public IBinaryFileFinder BinaryFileFinder => binaryFileFinder_; public IDebugFileFinder DebugFileFinder => debugFileFinder_; public IDebugInfoProviderFactory DebugInfoProviderFactory => debugInfoProviderFactory_; public IDiffFilterProvider DiffFilterProvider => diffFilterProvider_; public async Task AnalyzeLoadedFunction(FunctionIR function, IRTextSection section, ILoadedDocument loadedDoc, FunctionDebugInfo funcDebugInfo) { // Annotate the instructions with debug info (line numbers, source files) // if the debug file is specified and available. var debugInfo = DebugInfoProviderFactory.GetOrCreateDebugInfoProvider(section.ParentFunction, loadedDoc); if (debugInfo != null) { await Task.Run(() => { if (funcDebugInfo != null) { return debugInfo.AnnotateSourceLocations(function, funcDebugInfo); } else { return debugInfo.AnnotateSourceLocations(function, section.ParentFunction); } }); } return true; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMDebugFileFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public class ASMDebugFileFinder : IDebugFileFinder { public async Task FindDebugInfoFileAsync(string imagePath, SymbolFileSourceSettings settings = null) { using var info = new PEBinaryInfoProvider(imagePath); if (!info.Initialize()) { return Utils.LocateDebugInfoFile(imagePath, ".json"); } switch (info.BinaryFileInfo.FileKind) { case BinaryFileKind.Native: { if (settings == null) { // Make sure the binary directory is also included in the symbol search. settings = CoreSettingsProvider.SymbolSettings.Clone(); settings.InsertSymbolPath(imagePath); } return await FindDebugInfoFileAsync(info.SymbolFileInfo, settings).ConfigureAwait(false); } } return DebugFileSearchResult.None; } public async Task FindDebugInfoFileAsync(SymbolFileDescriptor symbolFile, SymbolFileSourceSettings settings = null) { if (settings == null) { settings = CoreSettingsProvider.SymbolSettings; } return await PDBDebugInfoProvider.LocateDebugInfoFileAsync(symbolFile, settings).ConfigureAwait(false); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMDebugInfoProviderFactory.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public class ASMDebugInfoProviderFactory : IDebugInfoProviderFactory { // Use FilePath as key instead of DebugFileSearchResult object reference. // Different threads may create different DebugFileSearchResult objects for the same PDB, // and without Equals/GetHashCode overrides, reference equality would miss cache hits. private static readonly Dictionary loadedDebugInfo_ = new(); private static readonly object loadedDebugInfoLock_ = new(); public IDebugInfoProvider CreateDebugInfoProvider(DebugFileSearchResult debugFile) { if (!debugFile.Found || string.IsNullOrEmpty(debugFile.FilePath)) { return null; } // Use static lock since the dictionary is static (shared across all factory instances) lock (loadedDebugInfoLock_) { if (loadedDebugInfo_.TryGetValue(debugFile.FilePath, out var provider)) { return provider; } var newProvider = new PDBDebugInfoProvider(CoreSettingsProvider.SymbolSettings); if (newProvider.LoadDebugInfo(debugFile, null)) { loadedDebugInfo_[debugFile.FilePath] = newProvider; return newProvider; } return null; } } public IDebugInfoProvider GetOrCreateDebugInfoProvider(IRTextFunction function, ILoadedDocument loadedDoc) { lock (loadedDoc) { if (loadedDoc.DebugInfo != null) { return loadedDoc.DebugInfo; } } if (!loadedDoc.DebugInfoFileExists) { return null; } if (loadedDoc.DebugInfoFileExists) { var debugInfo = CreateDebugInfoProvider(loadedDoc.DebugInfoFile); if (debugInfo != null) { lock (loadedDoc) { loadedDoc.DebugInfo = debugInfo; return debugInfo; } } } return null; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMDiffFilterProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public class ASMDiffFilterProvider : IDiffFilterProvider { private readonly ASMCompilerInfoProvider outer_; public ASMDiffFilterProvider(ASMCompilerInfoProvider outer) { outer_ = outer; } public IDiffInputFilter CreateDiffInputFilter() { var filter = new ASMDiffInputFilter(); filter.Initialize(CoreSettingsProvider.DiffSettings, outer_.IR); return filter; } public IDiffOutputFilter CreateDiffOutputFilter() { return new BasicDiffOutputFilter(); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMDiffInputFilter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public class ASMDiffInputFilter : IDiffInputFilter { private Dictionary addressMap_; private int nextAddressId_; public char[] AcceptedLetters => new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'a', 'b', 'c', 'd', 'e', 'f' }; public void Initialize(DiffSettings settings, ICompilerIRInfo ifInfo) { addressMap_ = new Dictionary(); nextAddressId_ = 1; } public FilteredDiffInput FilterInputText(string text) { string[] lines = text.SplitLines(); var result = new FilteredDiffInput(lines.Length); var builder = new StringBuilder(text.Length); foreach (string line in lines) { (string newLine, var replacements) = FilterInputLineImpl(line); builder.AppendLine(newLine); result.LineReplacements.Add(replacements); } result.Text = builder.ToString(); return result; } public string FilterInputLine(string line) { (string result, _) = FilterInputLineImpl(line); return result; } public (string, List) FilterInputLineImpl(string line) { string newLine = line; int index = line.IndexOf(':'); if (index == -1) { return (newLine, FilteredDiffInput.NoReplacements); } (string address, _) = ParseAddress(line, 0); if (address == null) { return (newLine, FilteredDiffInput.NoReplacements); } var replacements = new List(1); // Create a canonical form for the address so that diffing considers // the addresses equal if the target blocks are the same in two functs. // where the function start is not the same anymore. if (addressMap_.GetOrAddValue(address, nextAddressId_) == nextAddressId_) { nextAddressId_++; } // Skip over the bytecodes found before the opcode. int startIndex = index; for (index = index + 1; index < line.Length; index++) { char letter = line[index]; if (!(char.IsWhiteSpace(letter) || char.IsDigit(letter) || Array.IndexOf(AcceptedLetters, letter) != -1)) { break; } } // Move back before the opcode starts. int afterIndex = index; while (index > startIndex && !char.IsWhiteSpace(line[index - 1])) { index--; } // Check if there is any address found after the opcode // and replace it with the canonical form. while (afterIndex < line.Length && !char.IsWhiteSpace(line[afterIndex])) { afterIndex++; } //? TODO: There could be multiple addresses as operands? if (afterIndex < line.Length) { (string afterAddress, int offset) = ParseAddress(line, afterIndex); if (afterAddress != null && afterAddress.Length >= 4) { int id = addressMap_.GetOrAddValue(afterAddress, nextAddressId_); if (id == nextAddressId_) { nextAddressId_++; } string replacementAddress = id.ToString().PadLeft(afterAddress.Length, 'A'); newLine = newLine.Replace(afterAddress, replacementAddress); replacements.Add(new FilteredDiffInput.Replacement(offset, replacementAddress, afterAddress)); } } string newLinePrefix = newLine.Substring(0, index); string newLinePrefixReplacement = new(' ', index); newLine = newLinePrefixReplacement + newLine.Substring(index); replacements.Add(new FilteredDiffInput.Replacement(0, newLinePrefixReplacement, newLinePrefix)); return (newLine, replacements); } private (string, int) ParseAddress(string line, int startOffset) { int addressStartOffset = startOffset; int offset; for (offset = startOffset; offset < line.Length; offset++) { char letter = line[offset]; if (char.IsWhiteSpace(letter)) { addressStartOffset = offset + 1; continue; } if (!(char.IsDigit(letter) || Array.IndexOf(AcceptedLetters, letter) != -1)) { break; } } if (offset > addressStartOffset) { return (line.Substring(addressStartOffset, offset - addressStartOffset), addressStartOffset); } return (null, 0); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMIRSectionParser.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; namespace ProfileExplorer.Core.Compilers.ASM; public sealed class ASMIRSectionParser : IRSectionParser { private ICompilerIRInfo irInfo_; private IRParsingErrorHandler errorHandler_; private long functionSize_; public ASMIRSectionParser(long functionSize, ICompilerIRInfo irInfo, IRParsingErrorHandler errorHandler) { functionSize_ = functionSize; irInfo_ = irInfo; errorHandler_ = errorHandler; } public FunctionIR ParseSection(IRTextSection section, string sectionText) { return new ASMParser(irInfo_, errorHandler_, RegisterTables.SelectRegisterTable(irInfo_.Mode), sectionText, section, functionSize_).Parse(); } public FunctionIR ParseSection(IRTextSection section, ReadOnlyMemory sectionText) { return new ASMParser(irInfo_, errorHandler_, RegisterTables.SelectRegisterTable(irInfo_.Mode), sectionText, section, functionSize_).Parse(); } public void SkipCurrentToken() { throw new NotImplementedException(); } public void SkipToFunctionEnd() { throw new NotImplementedException(); } public void SkipToLineEnd() { throw new NotImplementedException(); } public void SkipToLineStart() { throw new NotImplementedException(); } public void SkipToNextBlock() { throw new NotImplementedException(); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMIRSectionReader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.Compilers.ASM; public sealed class ASMIRSectionReader : SectionReaderBase { public ASMIRSectionReader(string filePath, bool expectSectionHeaders) : base(filePath, expectSectionHeaders) { } public ASMIRSectionReader(byte[] textData, bool expectSectionHeaders) : base(textData, expectSectionHeaders) { } protected override string ExtractFunctionName(string line) { return line.Substring(0, line.Length - 1); } protected override string ExtractSectionName(string line) { return ExtractFunctionName(line); } protected override bool IsBlockStart(string line) { return false; } protected override bool IsFunctionEnd(string line) { return string.IsNullOrEmpty(line) || IsFunctionStart(line); } protected override bool IsFunctionStart(string line) { // Search for name: with optional whitespace after : int index = line.LastIndexOf(':'); if (index == -1) { return false; } if (index == line.Length - 1) { return true; } for (; index < line.Length; index++) { if (!char.IsWhiteSpace(line[index])) { return false; } } return true; } protected override bool IsMetadataLine(string line) { return false; } protected override bool IsSectionStart(string line) { return IsFunctionStart(line); } protected override string PreprocessLine(string line) { return line; } protected override bool ShouldSkipOutputLine(string line) { return string.IsNullOrEmpty(line); } protected override bool FunctionEndIsFunctionStart(string line) { return !string.IsNullOrEmpty(line); } protected override bool SectionStartIsFunctionStart(string line) { return true; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMNameProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Concurrent; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.ASM; public sealed class ASMNameProvider : INameProvider { private static ConcurrentDictionary demangledNameMap_; private static ConcurrentDictionary functionNameMap_; static ASMNameProvider() { demangledNameMap_ = new ConcurrentDictionary(); functionNameMap_ = new ConcurrentDictionary(); } public bool IsDemanglingSupported => true; public bool IsDemanglingEnabled => IsDemanglingSupported && CoreSettingsProvider.SectionSettings.ShowDemangledNames; public FunctionNameDemanglingOptions GlobalDemanglingOptions => CoreSettingsProvider.SectionSettings.DemanglingOptions; public string GetSectionName(IRTextSection section, bool includeNumber) { string sectionName = section.Name; if (string.IsNullOrEmpty(sectionName)) { sectionName = section.ParentFunction.Name; } if (!string.IsNullOrEmpty(sectionName)) { sectionName = FormatFunctionName(sectionName); sectionName = sectionName.Length <= 50 ? sectionName : $"{sectionName.Substring(0, 20)}..."; } if (includeNumber) { return $"({section.Number}) {sectionName}"; } return sectionName; } public string GetFunctionName(IRTextFunction function) { return function.Name; } public string DemangleFunctionName(string name, FunctionNameDemanglingOptions options) { if (!demangledNameMap_.TryGetValue(name, out string demangledName)) { demangledName = PDBDebugInfoProvider.DemangleFunctionName(name, options); demangledNameMap_.TryAdd(name, demangledName); } return demangledName; } public string DemangleFunctionName(IRTextFunction function, FunctionNameDemanglingOptions options) { return DemangleFunctionName(function.Name, options); } public string FormatFunctionName(string name) { if (!IsDemanglingEnabled || string.IsNullOrEmpty(name)) { return name; } // Mangled MSVC C++ names always start with a ? char. if (!name.StartsWith('?')) { return name; } if (!functionNameMap_.TryGetValue(name, out string demangledName)) { demangledName = PDBDebugInfoProvider.DemangleFunctionName(name, GlobalDemanglingOptions); functionNameMap_.TryAdd(name, demangledName); } return demangledName; } public void SettingsChanged() { demangledNameMap_.Clear(); functionNameMap_.Clear(); } public string FormatFunctionName(IRTextFunction function) { return FormatFunctionName(function.Name); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/ASMParser.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Collections; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Lexer; using ProfileExplorer.Core.Parser; namespace ProfileExplorer.Core.Compilers.ASM; public sealed class ASMParser : ParserBase { private static Dictionary keywordMap_ = new() { {"byte", Keyword.Byte}, {"word", Keyword.Word}, {"dword", Keyword.Dword}, {"qword", Keyword.Qword}, {"xmmword", Keyword.Xmmword}, {"ymmword", Keyword.Ymmword}, {"Zmmword", Keyword.Zmmword}, {"ptr", Keyword.Ptr}, {"BYTE", Keyword.Byte}, {"WORD", Keyword.Word}, {"DWORD", Keyword.Dword}, {"QWORD", Keyword.Qword}, {"XMMWORD", Keyword.Xmmword}, {"YMMWORD", Keyword.Ymmword}, {"ZMMWORD", Keyword.Zmmword}, {"PTR", Keyword.Ptr}, {"h", Keyword.Hex}, {"H", Keyword.Hex} }; private static readonly StringTrie keywordTrie_ = new(keywordMap_); //? TODO: ILT+foo func names not parsed properly private long functionSize_; private long? initialAddress_; private bool makeNewBlock_; private bool connectNewBlock_; private InstructionIR previousInstr_; private long previousInstrAddress_; private int instrCount_; private Dictionary addressToBlockNumberMap_; private Dictionary> potentialLabelMap_; private HashSet committedBlocks_; private Dictionary referencedBlocks_; public ASMParser(ICompilerIRInfo irInfo, IRParsingErrorHandler errorHandler, RegisterTable registerTable, ReadOnlyMemory sectionText, IRTextSection section, long functionSize) : base(irInfo, errorHandler, registerTable, section) { Reset(); Initialize(sectionText); functionSize_ = functionSize; MetadataTag.EnsureCapacity(section.LineCount + 1); SkipToken(); } public ASMParser(ICompilerIRInfo irInfo, IRParsingErrorHandler errorHandler, RegisterTable registerTable, string sectionText, IRTextSection section, long functionSize) : base(irInfo, errorHandler, registerTable, section) { Reset(); Initialize(sectionText); functionSize_ = functionSize; MetadataTag.EnsureCapacity(section.LineCount + 1); SkipToken(); } public FunctionIR Parse() { var function = new FunctionIR(section_.ParentFunction.Name); Token startElement = default; BlockIR block = null; while (!IsEOF()) { if (makeNewBlock_) { // Make a new block. if ((IsNumber() || IsIdentifier()) && NextTokenIs(TokenKind.Colon) && TokenLongHexNumber(out long address)) { var newBlock = GetOrCreateBlock(address, function); var blockLabel = GetOrCreateBlockLabel(newBlock); blockLabel.TextLocation = current_.Location; blockLabel.TextLength = current_.Length; if (block != null && connectNewBlock_) { ConnectBlocks(block, newBlock); } function.Blocks.Add(newBlock); committedBlocks_.Add(newBlock); block = newBlock; startElement = current_; } else { // Skip over unknown text, such as the function name at the start. SkipToLineStart(); continue; } makeNewBlock_ = false; connectNewBlock_ = false; } if (ParseLine(block)) { // Block ended with this line. SetTextRange(block, startElement, previous_); } SkipToLineStart(); } if (block != null) { SetTextRange(block, startElement, current_); } Debug.Assert(function.InstructionCount == instrCount_); Debug.Assert(function.TupleCount == instrCount_); SetLastInstructionSize(); FixBlockReferences(function); AssignBlockNumbers(function); AddMetadata(function); return function; } private void Reset() { base.Reset(); makeNewBlock_ = true; addressToBlockNumberMap_ = new Dictionary(); potentialLabelMap_ = new Dictionary>(); committedBlocks_ = new HashSet(); referencedBlocks_ = new Dictionary(); } private int GetBlockNumber(long address) { if (addressToBlockNumberMap_.TryGetValue(address, out int number)) { return number; } number = addressToBlockNumberMap_.Count; addressToBlockNumberMap_[address] = number; return number; } private BlockIR GetOrCreateBlock(long address, FunctionIR function) { int number = GetBlockNumber(address); return base.GetOrCreateBlock(number, function); } private BlockLabelIR GetOrCreateBlockLabel(BlockIR block) { // Create a dummy label to be set later when parsing the block. if (block.Label == null) { block.Label = new BlockLabelIR(NextElementId, ReadOnlyMemory.Empty, block); } return block.Label; } private void AssignBlockNumbers(FunctionIR function) { if (function.Blocks.Count == 0) { return; } // Renumber blocks to follow text order. int blockNumber = 0; var blockOrdering = new CFGBlockOrdering(function); blockOrdering.ReversePostorderWalk((b, index) => { b.Number = blockNumber++; return true; }); // Assign block index as they show up in the text, // not RDFO or how the blocks where forward-referenced. function.AssignBlockIndices(true); // The last block (after RET) is usually unreachable, remove it. if (function.EntryBlock != function.ExitBlock && function.ExitBlock.Predecessors.Count == 0) { function.Blocks.Remove(function.ExitBlock); } } private void FixBlockReferences(FunctionIR function) { // Add any remaining blocks referenced by jumps. foreach (var pair in referencedBlocks_) { var refBlock = pair.Key; long refAddress = pair.Value; if (committedBlocks_.Contains(refBlock)) { continue; } // Found a referenced label, but there is no block created for it. // This happens when there is no jump/branch before the label. // In practice this is fast, although in worst case it's #labels * #blocks complexity. bool blockAdded = false; if (potentialLabelMap_.TryGetValue(refAddress, out var labelLocation)) { var label = GetOrCreateBlockLabel(refBlock); label.TextLocation = labelLocation.Item1; label.TextLength = labelLocation.Item2; refBlock.TextLocation = labelLocation.Item1; // Check if there is an overlapping block and split it at the label, // move the tuples following the label to the new block. // |otherBlock|1|2|..|refBlock label|3|4|..| => |otherBlock|1|2|..| -> |refBlock label|1|2|..| for (int i = 0; i < function.Blocks.Count; i++) { var otherBlock = function.Blocks[i]; if (otherBlock == refBlock) { continue; } if (otherBlock.TextLocation <= labelLocation.Item1 && otherBlock.TextLocation.Offset + otherBlock.TextLength > labelLocation.Item1.Offset) { int offsetDiff = labelLocation.Item1.Offset - otherBlock.TextLocation.Offset; refBlock.TextLength = otherBlock.TextLength - offsetDiff; // Move successor blocks from otherBlock to refBlock. foreach (var succBlock in otherBlock.Successors) { refBlock.Successors.Add(succBlock); succBlock.Predecessors.Remove(otherBlock); succBlock.Predecessors.Add(refBlock); } otherBlock.Successors.Clear(); // Move the tuples to the new block. int splitIndex = 0; int copiedTuples = 0; for (; splitIndex < otherBlock.Tuples.Count; splitIndex++) { var tuple = otherBlock.Tuples[splitIndex]; if (tuple.TextLocation >= labelLocation.Item1) { refBlock.Tuples.Add(tuple); tuple.Parent = refBlock; tuple.IndexInBlock = copiedTuples; copiedTuples++; } } // If the block has only NOP, don't connect it, it leaves // the NOP block without any predecessor. ConnectBlocks(otherBlock, refBlock); if (copiedTuples > 0) { otherBlock.Tuples.RemoveRange(otherBlock.Tuples.Count - copiedTuples, copiedTuples); if (otherBlock.Tuples.Count > 0) { otherBlock.TextLength = otherBlock.Tuples[^1].TextLocation.Offset + otherBlock.Tuples[^1].TextLength - otherBlock.TextLocation.Offset; } else { otherBlock.TextLength = offsetDiff - 1; } } // Insert block after the other one. function.Blocks.Insert(i + 1, refBlock); blockAdded = true; break; // Stop, there can't be more than one overlapping block. } } committedBlocks_.Add(refBlock); } if (!blockAdded) { function.Blocks.Add(refBlock); } } } private void ConnectBlocks(BlockIR block, BlockIR newBlock) { if (block.Successors.Contains(newBlock)) { return; } block.Successors.Add(newBlock); newBlock.Predecessors.Add(block); } private bool ParseLine(BlockIR block) { var startToken = current_; long address = 0; if (!(IsNumber() || IsIdentifier()) || !TokenLongHexNumber(out address)) { // Ignore lines that don't start with an address (comments, etc). return false; } // Record address to be used for jump in the middle of blocks. potentialLabelMap_[address] = new Tuple(current_.Location, current_.Length); SkipToken(); if (!ExpectAndSkipToken(TokenKind.Colon)) { // Instrs. with more than 6 bytes extend on multiple lines. // 0000000140068023: 49 BF 70 89 DE 5E mov r15,9375B7955EDE8970h // 95 B7 75 93 if (previousInstr_ != null) { SkipInstructionBytes(); return false; } ReportErrorAndSkipLine(TokenKind.Colon, "Expected a colon to follow the address"); return false; } // Skip over the list of instruction bytecodes. SkipInstructionBytes(); (var instr, bool isJump) = ParseInstruction(block); // Update metadata. initialAddress_ ??= address; long offset = address - initialAddress_.Value; MetadataTag.AddressToElementMap[address] = instr; MetadataTag.OffsetToElementMap[offset] = instr; MetadataTag.ElementToOffsetMap[instr] = offset; SetPreviousInstructionSize(address); previousInstr_ = instr; previousInstrAddress_ = address; SetTextRange(instr, startToken, current_, 1); SkipToLineEnd(); return isJump; // A jump ends the current block. } private void SetPreviousInstructionSize(long address) { if (previousInstr_ != null) { int instrSize = (int)(address - previousInstrAddress_); MetadataTag.ElementSizeMap[previousInstr_] = instrSize; MetadataTag.FunctionSize += instrSize; } } private void SetLastInstructionSize() { if (previousInstr_ != null) { int instrSize = (int)(functionSize_ - MetadataTag.FunctionSize); MetadataTag.ElementSizeMap[previousInstr_] = instrSize; MetadataTag.FunctionSize += instrSize; } } private (InstructionIR, bool) ParseInstruction(BlockIR block) { bool isJump = false; var instr = new InstructionIR(NextElementId, InstructionKind.Other, block); block.AddTuple(instr); instrCount_++; // Extract the opcode. if (IsIdentifier()) { SetInstructionOpcode(instr); if (instr.Kind == InstructionKind.Branch) { isJump = true; makeNewBlock_ = true; connectNewBlock_ = true; // Fall-through. } else if (instr.Kind == InstructionKind.Goto) { isJump = true; makeNewBlock_ = true; connectNewBlock_ = false; } else if (instr.Kind == InstructionKind.Return) { isJump = true; makeNewBlock_ = true; connectNewBlock_ = false; } SkipToken(); // Skip opcode. ParseOperandList(instr, instr.Sources); if (isJump) { // Connect the block with the jump target. var targetOp = irInfo_.GetBranchTarget(instr); if (targetOp != null && targetOp.IsIntConstant) { long targetAddress = targetOp.IntValue; var targetBlock = GetOrCreateBlock(targetAddress, block.ParentFunction); ConnectBlocks(block, targetBlock); referencedBlocks_[targetBlock] = targetAddress; int opIndex = instr.Sources.IndexOf(targetOp); instr.Sources[opIndex].Kind = OperandKind.LabelAddress; instr.Sources[opIndex].Value = GetOrCreateBlockLabel(targetBlock); } } else { if (instr.Sources.Count > 0) { instr.Destinations.Add(instr.Sources[0]); } //? TODO: OPEQ add first source as dest } } return (instr, isJump); } private bool ParseOperandList(InstructionIR instr, List list) { while (!IsLineEnd()) { var operand = ParseOperand(instr); if (operand == null) { return false; } operand.Role = OperandRole.Source; list.Add(operand); if (IsComma()) { SkipToken(); // More operands after , } else { if (instr.Kind == InstructionKind.Call && operand.IsVariable && operand.HasName) { // With demangled names, there can be multiple tokens // that form the complete function name, append them together. var sb = new StringBuilder(); sb.Append(operand.Name); int funcNameLength = operand.TextLength; int prevTokenEnd = operand.TextLocation.Offset + operand.TextLength; while (!IsLineEnd()) { // Append whitespace if there is some between tokens. int spaceCount = current_.Location.Offset - prevTokenEnd; if (spaceCount > 0) { sb.Append(lexer_.GetText(prevTokenEnd, spaceCount)); funcNameLength += spaceCount; } sb.Append(lexer_.GetTokenText(current_)); funcNameLength += current_.Length; prevTokenEnd = current_.Location.Offset + current_.Length; SkipToken(); } operand.Value = sb.ToString().AsMemory(); operand.TextLength = funcNameLength; } break; } } return true; } private OperandIR ParseOperand(TupleIR parent, bool isIndirBaseOp = false, bool isBlockLabelRef = false, bool disableSkipToNext = false) { SkipKeywords(); // Skip DWORD PTR, etc. OperandIR operand = null; // operand = varOp | intOp | floatOp | addressOp | indirOp | labelOp | pasOp if (IsIdentifier()) { // Variable/temporary. //? TODO: If it starts with @ it's address operand = ParseVariableOperand(parent, isIndirBaseOp); } else if (IsNumber() || TokenIs(TokenKind.Minus) || TokenIs(TokenKind.Hash)) { // int/float const operand = ParseNumber(parent); } else if (TokenIs(TokenKind.OpenSquare)) { // [indir] if (isIndirBaseOp) { ReportError(TokenKind.OpenSquare, "Failed ParseOperand nested INDIR"); return null; // Nested [indir] not allowed. } operand = ParseIndirection(parent); } SkipToNextOperand(); return operand; } private OperandIR ParseNumber(TupleIR parent) { var startToken = current_; var opKind = OperandKind.Other; object opValue = null; bool isNegated = false; // ARM64 assembly can have a # in front of a number like in #0x30. if (TokenIs(TokenKind.Hash)) { SkipToken(); } if (TokenIs(TokenKind.Minus)) { SkipToken(); isNegated = true; } if (TokenLongHexNumber(out long intValue)) { // intConst = DECIMAL [(0xHEX)] [.type] SkipToken(); opKind = OperandKind.IntConstant; unchecked { opValue = isNegated ? -intValue : intValue; } SkipKeyword(Keyword.Hex); // Skip optional h suffix. } else { ReportError(TokenKind.Number, "Failed ParseNumber"); return null; } var type = TypeIR.GetUnknown(); var operand = CreateOperand(NextElementId, opKind, type, parent); operand.Value = opValue; SetTextRange(operand, startToken); return operand; } private OperandIR ParseVariableOperand(TupleIR parent, bool isIndirBaseOp = false) { // Save variable name. var opName = TokenData(); var operand = CreateOperand(NextElementId, OperandKind.Variable, TypeIR.GetUnknown(), parent); operand.Value = opName; // Try to associate with a register. var register = RegisterTable.GetRegister(TokenString()); if (register != null) { operand.AddTag(new RegisterTag(register, operand)); } var startToken = current_; SkipToken(); SetTextRange(operand, startToken); return operand; } private OperandIR ParseIndirection(TupleIR parent) { var startToken = current_; SkipToken(); var baseOp = ParseOperand(parent, true); // After lowering, indirections can have multiple operands // like [base+index+offset]. //? TODO: Save the extra ops while (!TokenIs(TokenKind.CloseSquare)) { // Skip over + or *. SkipToNextOperand(); ExpectAndSkipToken(TokenKind.Plus, TokenKind.Star, TokenKind.Comma); if (ParseOperand(parent, true) == null) { break; } //? TODO: Add to list - maybe introduce IndirectOperand } var operand = CreateOperand(NextElementId, OperandKind.Indirection, TypeIR.GetUnknown(), parent); operand.Value = baseOp; if (!ExpectAndSkipToken(TokenKind.CloseSquare)) { ReportError(TokenKind.CloseSquare, "Failed ParseIndirection"); return null; } SetTextRange(operand, startToken); return operand; } private void SkipToNextOperand() { while (!(TokenIs(TokenKind.Comma) || IsLineEnd())) { if (TokenIs(TokenKind.Dot)) { // Skip over ARM64 operand annotations like v22.4s SkipToToken(TokenKind.Comma); } else if (TokenIs(TokenKind.OpenParen)) { SkipAfterToken(TokenKind.CloseParen); } else if (TokenIs(TokenKind.OpenCurly)) { SkipAfterToken(TokenKind.CloseCurly); } else { break; } } } private OperandIR CreateOperand(IRElementId elementId, OperandKind kind, TypeIR type, TupleIR parent) { #if USE_POOL var op = operandPool_.Get(); op.Id = elementId.NextOperand(); op.Kind = kind; op.Type = type; op.Parent = parent; return op; #else return new OperandIR(elementId, kind, type, parent); #endif } private void SkipInstructionBytes() { // For ARM64 each instruction is 4 bytes. if (irInfo_.Mode == IRMode.ARM64) { if (SkipHexNumber(8)) { return; } } while (SkipHexNumber(2)) { // Groups of 2 digits. } } private void SetInstructionOpcode(InstructionIR instr) { instr.OpcodeLocation = current_.Location; instr.OpcodeText = TokenData(); if (NextTokenIs(TokenKind.Dot) && irInfo_.Mode == IRMode.ARM64) { // Some disassemblers for ARM64 print branch opcodes // like b.eq, b.le instead of beq, ble. SkipToken(); // Skip b SkipToken(); // Skip . if (IsIdentifier()) { instr.OpcodeText = $"{instr.OpcodeText}{TokenData()}".AsMemory(); } } switch (irInfo_.Mode) { case IRMode.x86_64: { if (x86Opcodes.GetOpcodeInfo(instr.OpcodeText, out var info)) { instr.Opcode = info.Opcode; instr.Kind = info.Kind; } break; } case IRMode.ARM64: { if (ARM64Opcodes.GetOpcodeInfo(instr.OpcodeText, out var info)) { instr.Opcode = info.Opcode; instr.Kind = info.Kind; } break; } default: { Debug.Assert(false, "Unsupported IR mode"); Trace.WriteLine($"Unsupported IR mode {irInfo_.Mode}"); break; } } } private Keyword TokenKeyword() { if (current_.IsIdentifier()) { if (keywordTrie_.TryGetValue(TokenStringData(), out var keyword)) { return keyword; } } return Keyword.None; } private bool IsKeyword() { return TokenKeyword() != Keyword.None; } private void SkipKeyword(Keyword kind) { if (TokenKeyword() == kind) { SkipToken(); } } private void SkipKeywords() { while (IsKeyword()) { SkipToken(); } } private enum Keyword { None, Byte, Word, Dword, Qword, Xmmword, Ymmword, Zmmword, Ptr, Hex } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/DisassemblerSectionLoader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.Core.Compilers.ASM; public sealed class DisassemblerSectionLoader : IRTextSectionLoader { private IRTextSummary summary_; private string binaryFilePath_; private Disassembler disassembler_; private IDebugInfoProvider debugInfo_; private IDebugFileFinder debugFileFinder_; private IDebugInfoProviderFactory debugInfoProviderFactory_; private INameProvider nameProvider_; private Dictionary funcToDebugInfoMap_; private bool isManagedImage_; private bool preloadFunctions_; private DebugFileSearchResult debugInfoFile_; private bool resolveCallTargetNames_; public DisassemblerSectionLoader(string binaryFilePath, ICompilerInfoProvider compilerInfo, IDebugInfoProvider debugInfo, bool preloadFunctions = true, bool isManagedImage = false) { Initialize(compilerInfo.IR, false); binaryFilePath_ = binaryFilePath; debugInfo_ = debugInfo; debugFileFinder_ = compilerInfo.DebugFileFinder; debugInfoProviderFactory_ = compilerInfo.DebugInfoProviderFactory; nameProvider_ = compilerInfo.NameProvider; preloadFunctions_ = preloadFunctions; isManagedImage_ = isManagedImage; summary_ = new IRTextSummary(); funcToDebugInfoMap_ = new Dictionary(); } public IDebugInfoProvider DebugInfo { get => debugInfo_; set => debugInfo_ = value; } public DebugFileSearchResult DebugInfoFile { get => debugInfoFile_; set => debugInfoFile_ = value; } public bool ResolveCallTargetNames { get => resolveCallTargetNames_; set { resolveCallTargetNames_ = value; if (disassembler_ != null) { if (value) { disassembler_.UseSymbolNameResolver(null); } else { disassembler_.UseSymbolNameResolver((value) => null); } } } } public bool IsDisassemblerInitialized => disassembler_ != null; public void RegisterFunction(IRTextFunction function, FunctionDebugInfo debugInfo) { funcToDebugInfoMap_[function] = debugInfo; } public void Initialize(IDebugInfoProvider debugInfo) { debugInfo_ = debugInfo; InitializeDisassembler(); } public async override Task LoadDocument(ProgressInfoHandler progressHandler) { progressHandler?.Invoke(null, new SectionReaderProgressInfo(true)); if (debugInfo_ == null) { if (preloadFunctions_) { // When opening in non-profiling mode, lookup the debug info now. debugInfoFile_ = await debugFileFinder_.FindDebugInfoFileAsync(binaryFilePath_); debugInfo_ = debugInfoProviderFactory_.CreateDebugInfoProvider(debugInfoFile_); } if (debugInfo_ == null) { return summary_; } } InitializeDisassembler(); if (preloadFunctions_) { // Used when opening a binary directly. var funcList = debugInfo_.GetSortedFunctions(); foreach (var funcInfo in funcList) { if (funcInfo.RVA == 0) { continue; // Some entries don't represent real functions. } // The debug info function list can have duplicates, ignore them. var func = summary_.FindFunction(funcInfo.Name); if (func == null) { func = new IRTextFunction(funcInfo.Name); var section = new IRTextSection(func, func.Name, IRPassOutput.Empty); func.AddSection(section); summary_.AddFunction(func); summary_.AddSection(section); funcToDebugInfoMap_[func] = funcInfo; } } } progressHandler?.Invoke(null, new SectionReaderProgressInfo(false)); return summary_; } private bool InitializeDisassembler() { if (!isManagedImage_) { // This preloads all code sections in the binary. disassembler_ = Disassembler.CreateForBinary(binaryFilePath_, debugInfo_, nameProvider_.FormatFunctionName); return true; } // For managed code, the code data is found on each function. if (debugInfo_.LoadDebugInfo(null)) { disassembler_ = Disassembler.CreateForMachine(debugInfo_, nameProvider_.FormatFunctionName); return true; } return false; } public override string GetDocumentOutputText() { return ""; } public override byte[] GetDocumentTextBytes() { return new byte[] { }; } public override ParsedIRTextSection LoadSection(IRTextSection section) { string text = GetSectionText(section); if (string.IsNullOrEmpty(text)) { return null; } // Function size needed by parser to properly set instr. sizes. long functionSize = 0; if (funcToDebugInfoMap_.TryGetValue(section.ParentFunction, out var funcInfo)) { functionSize = funcInfo.Size; } var (sectionParser, errorHandler) = InitializeParser(functionSize); FunctionIR function; if (sectionParser == null) { function = new FunctionIR(); } else { function = sectionParser.ParseSection(section, text); } return new ParsedIRTextSection(section, text.AsMemory(), function); } public override string GetSectionText(IRTextSection section) { if (disassembler_ == null) { return null; // Failed to initialize. } if (!funcToDebugInfoMap_.TryGetValue(section.ParentFunction, out var funcInfo)) { return ""; } if (isManagedImage_) { // For managed code, the code data is found on each function as a byte array. var methodCode = ((DotNetDebugInfoProvider)debugInfo_).FindMethodCode(funcInfo); if (methodCode != null) { byte[] code = methodCode.Code; if (code != null) { disassembler_.UseSymbolNameResolver(address => methodCode.FindCallTarget(address)); return disassembler_.DisassembleToText(code, funcInfo.StartRVA); } } return ""; } return disassembler_.DisassembleToText(funcInfo); } public override ReadOnlyMemory GetSectionTextSpan(IRTextSection section) { return GetSectionText(section).AsMemory(); } public override string GetSectionOutputText(IRPassOutput output) { return ""; } public override ReadOnlyMemory GetSectionPassOutputTextSpan(IRPassOutput output) { return ReadOnlyMemory.Empty; } public override List GetSectionPassOutputTextLines(IRPassOutput output) { return new List(); } public override string GetRawSectionText(IRTextSection section) { return GetSectionText(section); } public override string GetRawSectionPassOutput(IRPassOutput output) { return ""; } public override ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section) { return GetRawSectionText(section).AsMemory(); } public override ReadOnlyMemory GetRawSectionPassOutputSpan(IRPassOutput output) { return ReadOnlyMemory.Empty; } protected override void Dispose(bool disposing) { disassembler_?.Dispose(); debugInfo_?.Dispose(); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/ASM/X86Opcodes.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.Collections; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Compilers.ASM; public enum x86Opcode { RET, JMP, JO, JNO, JS, JNS, JE, JZ, JNE, JNZ, JB, JNAE, JC, JNB, JAE, JNC, JBE, JNA, JA, JNBE, JL, JNGE, JGE, JNL, JLE, JNG, JG, JNLE, JP, JPE, JNP, JPO, JCXZ, JECXZ, CALL, SYSCALL, NOP } public struct x86OpcodeInfo { public x86Opcode Opcode { get; set; } public InstructionKind Kind { get; set; } public x86OpcodeInfo(x86Opcode opcode, InstructionKind kind) { Opcode = opcode; Kind = kind; } } public static class x86Opcodes { private static readonly Dictionary opcodes_ = new() { {"JMP", new x86OpcodeInfo(x86Opcode.JMP, InstructionKind.Goto)}, {"RET", new x86OpcodeInfo(x86Opcode.RET, InstructionKind.Return)}, {"JO", new x86OpcodeInfo(x86Opcode.JO, InstructionKind.Branch)}, {"JNO", new x86OpcodeInfo(x86Opcode.JNO, InstructionKind.Branch)}, {"JS", new x86OpcodeInfo(x86Opcode.JS, InstructionKind.Branch)}, {"JNS", new x86OpcodeInfo(x86Opcode.JNS, InstructionKind.Branch)}, {"JE", new x86OpcodeInfo(x86Opcode.JE, InstructionKind.Branch)}, {"JZ", new x86OpcodeInfo(x86Opcode.JZ, InstructionKind.Branch)}, {"JNE", new x86OpcodeInfo(x86Opcode.JNE, InstructionKind.Branch)}, {"JNZ", new x86OpcodeInfo(x86Opcode.JNZ, InstructionKind.Branch)}, {"JB", new x86OpcodeInfo(x86Opcode.JB, InstructionKind.Branch)}, {"JNAE", new x86OpcodeInfo(x86Opcode.JNAE, InstructionKind.Branch)}, {"JC", new x86OpcodeInfo(x86Opcode.JC, InstructionKind.Branch)}, {"JNB", new x86OpcodeInfo(x86Opcode.JNB, InstructionKind.Branch)}, {"JAE", new x86OpcodeInfo(x86Opcode.JAE, InstructionKind.Branch)}, {"JNC", new x86OpcodeInfo(x86Opcode.JNC, InstructionKind.Branch)}, {"JBE", new x86OpcodeInfo(x86Opcode.JBE, InstructionKind.Branch)}, {"JNA", new x86OpcodeInfo(x86Opcode.JNA, InstructionKind.Branch)}, {"JA", new x86OpcodeInfo(x86Opcode.JA, InstructionKind.Branch)}, {"JNBE", new x86OpcodeInfo(x86Opcode.JNBE, InstructionKind.Branch)}, {"JL", new x86OpcodeInfo(x86Opcode.JL, InstructionKind.Branch)}, {"JNGE", new x86OpcodeInfo(x86Opcode.JNGE, InstructionKind.Branch)}, {"JGE", new x86OpcodeInfo(x86Opcode.JGE, InstructionKind.Branch)}, {"JNL", new x86OpcodeInfo(x86Opcode.JNL, InstructionKind.Branch)}, {"JLE", new x86OpcodeInfo(x86Opcode.JLE, InstructionKind.Branch)}, {"JNG", new x86OpcodeInfo(x86Opcode.JNG, InstructionKind.Branch)}, {"JG", new x86OpcodeInfo(x86Opcode.JG, InstructionKind.Branch)}, {"JNLE", new x86OpcodeInfo(x86Opcode.JNLE, InstructionKind.Branch)}, {"JP", new x86OpcodeInfo(x86Opcode.JP, InstructionKind.Branch)}, {"JPE", new x86OpcodeInfo(x86Opcode.JPE, InstructionKind.Branch)}, {"JNP", new x86OpcodeInfo(x86Opcode.JNP, InstructionKind.Branch)}, {"JPO", new x86OpcodeInfo(x86Opcode.JPO, InstructionKind.Branch)}, {"JCXZ", new x86OpcodeInfo(x86Opcode.JCXZ, InstructionKind.Branch)}, {"JECXZ", new x86OpcodeInfo(x86Opcode.JECXZ, InstructionKind.Branch)}, {"CALL", new x86OpcodeInfo(x86Opcode.CALL, InstructionKind.Call)}, {"SYSCALL", new x86OpcodeInfo(x86Opcode.SYSCALL, InstructionKind.Call)}, {"NOP", new x86OpcodeInfo(x86Opcode.NOP, InstructionKind.Other)} }; private static readonly StringTrie opcodesTrie_ = new(opcodes_); public static bool GetOpcodeInfo(string value, out x86OpcodeInfo info) { return opcodesTrie_.TryGetValue(value, out info, true); } public static bool GetOpcodeInfo(ReadOnlyMemory value, out x86OpcodeInfo info) { return opcodesTrie_.TryGetValue(value, out info, true); } public static bool IsOpcode(string value) { return GetOpcodeInfo(value, out _); } public static bool IsOpcode(ReadOnlyMemory value) { return opcodesTrie_.Contains(value); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/Architecture/ARM64RegisterTable.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Compilers.Architecture; public enum ARM64Register { } public class ARM64RegisterTable : RegisterTable { //? TODO //? private static readonly RegisterIR[] registers_ = { //? // Name Register Bit offset Bit length //? //? }; } ================================================ FILE: src/ProfileExplorerCore/Compilers/Architecture/IRMode.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.Compilers.Architecture; public enum IRMode { Default, x86_64, ARM64 } ================================================ FILE: src/ProfileExplorerCore/Compilers/Architecture/RegisterTables.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Compilers.Architecture; public static class RegisterTables { // Static instances to have the tables built only once. private static X86RegisterTable x86RegisterTable_; private static ARM64RegisterTable arm64RegisterTable_; static RegisterTables() { x86RegisterTable_ = new X86RegisterTable(); arm64RegisterTable_ = new ARM64RegisterTable(); x86RegisterTable_.AddRegisterAlias("cc_zf", "zf"); x86RegisterTable_.AddRegisterAlias("cc_cf", "cf"); x86RegisterTable_.AddRegisterAlias("cc_pf", "pf"); x86RegisterTable_.AddRegisterAlias("cc_sf", "sf"); x86RegisterTable_.AddRegisterAlias("cc_of", "of"); x86RegisterTable_.AddRegisterAlias("cc_so", "flags"); x86RegisterTable_.AddRegisterAlias("cc_soz", "flags"); x86RegisterTable_.AddRegisterAlias("cc", "flags"); x86RegisterTable_.AddRegisterAlias("ixmm0", "xmm0"); x86RegisterTable_.AddRegisterAlias("ixmm1", "xmm1"); x86RegisterTable_.AddRegisterAlias("ixmm2", "xmm2"); x86RegisterTable_.AddRegisterAlias("ixmm3", "xmm3"); x86RegisterTable_.AddRegisterAlias("ixmm4", "xmm4"); x86RegisterTable_.AddRegisterAlias("ixmm5", "xmm5"); x86RegisterTable_.AddRegisterAlias("ixmm6", "xmm6"); x86RegisterTable_.AddRegisterAlias("ixmm7", "xmm7"); x86RegisterTable_.AddRegisterAlias("ixmm8", "xmm8"); x86RegisterTable_.AddRegisterAlias("ixmm9", "xmm9"); x86RegisterTable_.AddRegisterAlias("ixmm10", "xmm10"); x86RegisterTable_.AddRegisterAlias("ixmm11", "xmm11"); x86RegisterTable_.AddRegisterAlias("ixmm12", "xmm12"); x86RegisterTable_.AddRegisterAlias("ixmm13", "xmm13"); x86RegisterTable_.AddRegisterAlias("ixmm14", "xmm14"); x86RegisterTable_.AddRegisterAlias("ixmm15", "xmm15"); x86RegisterTable_.AddRegisterAlias("fxmm0l", "xmm0"); x86RegisterTable_.AddRegisterAlias("fxmm1l", "xmm1"); x86RegisterTable_.AddRegisterAlias("fxmm2l", "xmm2"); x86RegisterTable_.AddRegisterAlias("fxmm3l", "xmm3"); x86RegisterTable_.AddRegisterAlias("fxmm4l", "xmm4"); x86RegisterTable_.AddRegisterAlias("fxmm5l", "xmm5"); x86RegisterTable_.AddRegisterAlias("fxmm6l", "xmm6"); x86RegisterTable_.AddRegisterAlias("fxmm7l", "xmm7"); x86RegisterTable_.AddRegisterAlias("fxmm8l", "xmm8"); x86RegisterTable_.AddRegisterAlias("fxmm9l", "xmm9"); x86RegisterTable_.AddRegisterAlias("fxmm10l", "xmm10"); x86RegisterTable_.AddRegisterAlias("fxmm11l", "xmm11"); x86RegisterTable_.AddRegisterAlias("fxmm12l", "xmm12"); x86RegisterTable_.AddRegisterAlias("fxmm13l", "xmm13"); x86RegisterTable_.AddRegisterAlias("fxmm14l", "xmm14"); x86RegisterTable_.AddRegisterAlias("fxmm15l", "xmm15"); x86RegisterTable_.AddRegisterAlias("fxmm0s", "xmm0"); x86RegisterTable_.AddRegisterAlias("fxmm1s", "xmm1"); x86RegisterTable_.AddRegisterAlias("fxmm2s", "xmm2"); x86RegisterTable_.AddRegisterAlias("fxmm3s", "xmm3"); x86RegisterTable_.AddRegisterAlias("fxmm4s", "xmm4"); x86RegisterTable_.AddRegisterAlias("fxmm5s", "xmm5"); x86RegisterTable_.AddRegisterAlias("fxmm6s", "xmm6"); x86RegisterTable_.AddRegisterAlias("fxmm7s", "xmm7"); x86RegisterTable_.AddRegisterAlias("fxmm8s", "xmm8"); x86RegisterTable_.AddRegisterAlias("fxmm9s", "xmm9"); x86RegisterTable_.AddRegisterAlias("fxmm10s", "xmm10"); x86RegisterTable_.AddRegisterAlias("fxmm11s", "xmm11"); x86RegisterTable_.AddRegisterAlias("fxmm12s", "xmm12"); x86RegisterTable_.AddRegisterAlias("fxmm13s", "xmm13"); x86RegisterTable_.AddRegisterAlias("fxmm14s", "xmm14"); x86RegisterTable_.AddRegisterAlias("fxmm15s", "xmm15"); x86RegisterTable_.AddRegisterAlias("iymm0", "ymm0"); x86RegisterTable_.AddRegisterAlias("iymm1", "ymm1"); x86RegisterTable_.AddRegisterAlias("iymm2", "ymm2"); x86RegisterTable_.AddRegisterAlias("iymm3", "ymm3"); x86RegisterTable_.AddRegisterAlias("iymm4", "ymm4"); x86RegisterTable_.AddRegisterAlias("iymm5", "ymm5"); x86RegisterTable_.AddRegisterAlias("iymm6", "ymm6"); x86RegisterTable_.AddRegisterAlias("iymm7", "ymm7"); x86RegisterTable_.AddRegisterAlias("iymm8", "ymm8"); x86RegisterTable_.AddRegisterAlias("iymm9", "ymm9"); x86RegisterTable_.AddRegisterAlias("iymm10", "ymm10"); x86RegisterTable_.AddRegisterAlias("iymm11", "ymm11"); x86RegisterTable_.AddRegisterAlias("iymm12", "ymm12"); x86RegisterTable_.AddRegisterAlias("iymm13", "ymm13"); x86RegisterTable_.AddRegisterAlias("iymm14", "ymm14"); x86RegisterTable_.AddRegisterAlias("iymm15", "ymm15"); } public static RegisterTable SelectRegisterTable(IRMode irMode) { return irMode switch { IRMode.x86_64 => x86RegisterTable_, IRMode.ARM64 => arm64RegisterTable_, IRMode.Default => x86RegisterTable_, _ => throw new ArgumentException("invalid valid", nameof(irMode)) }; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/Architecture/X86RegisterTable.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Compilers.Architecture; public enum X86Register { RAX, EAX, AX, AL, AH, RBX, EBX, BX, BL, BH, RCX, ECX, CX, CL, CH, RDX, EDX, DX, DL, DH, RSP, ESP, SP, SPL, RBP, EBP, BP, BPL, RSI, ESI, SI, SIL, RDI, EDI, DI, DIL, R8, R8D, R8W, R8B, R9, R9D, R9W, R9B, R10, R10D, R10W, R10B, R11, R11D, R11W, R11B, R12, R12D, R12W, R12B, R13, R13D, R13W, R13B, R14, R14D, R14W, R14B, R15, R15D, R15W, R15B, CS, DS, ES, FS, GS, SS, RIP, EIP, IP, RFLAGS, EFLAGS, FLAGS, CF, PF, AF, ZF, SF, TF, IF, DF, OF, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, YMM0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15 } public class X86RegisterTable : RegisterTable { private static readonly RegisterIR[] registers_ = { // Name Register Bit offset Bit length new("rax", X86Register.RAX, 0, 64, new RegisterIR("eax", X86Register.EAX, 0, 32, new RegisterIR("ax", X86Register.AX, 0, 16, new RegisterIR("al", X86Register.AL, 0, 8), new RegisterIR("ah", X86Register.AH, 8, 8) ))), new("rbx", X86Register.RBX, 0, 64, new RegisterIR("ebx", X86Register.EBX, 0, 32, new RegisterIR("bx", X86Register.BX, 0, 16, new RegisterIR("bl", X86Register.BL, 0, 8), new RegisterIR("bh", X86Register.BH, 8, 8) ))), new("rcx", X86Register.RCX, 0, 64, new RegisterIR("ecx", X86Register.ECX, 0, 32, new RegisterIR("cx", X86Register.CX, 0, 16, new RegisterIR("cl", X86Register.CL, 0, 8), new RegisterIR("ch", X86Register.CH, 8, 8) ))), new("rdx", X86Register.RDX, 0, 64, new RegisterIR("edx", X86Register.EDX, 0, 32, new RegisterIR("dx", X86Register.DX, 0, 16, new RegisterIR("dl", X86Register.DL, 0, 8), new RegisterIR("dh", X86Register.DH, 8, 8) ))), new("rsp", X86Register.RSP, 0, 64, new RegisterIR("esp", X86Register.ESP, 0, 32, new RegisterIR("sp", X86Register.SP, 0, 16, new RegisterIR("spl", X86Register.SPL, 0, 8) ))), new("rbp", X86Register.RBP, 0, 64, new RegisterIR("ebp", X86Register.EBP, 0, 32, new RegisterIR("bp", X86Register.BP, 0, 16, new RegisterIR("bpl", X86Register.BPL, 0, 8) ))), new("rsi", X86Register.RSI, 0, 64, new RegisterIR("esi", X86Register.ESI, 0, 32, new RegisterIR("si", X86Register.SI, 0, 16, new RegisterIR("sil", X86Register.SIL, 0, 8) ))), new("rdi", X86Register.RDI, 0, 64, new RegisterIR("edi", X86Register.EDI, 0, 32, new RegisterIR("di", X86Register.DI, 0, 16, new RegisterIR("dil", X86Register.DIL, 0, 8)) )), new("r8", X86Register.R8, 0, 64, new RegisterIR("r8d", X86Register.R8D, 0, 32, new RegisterIR("r8w", X86Register.R8W, 0, 16, new RegisterIR("r8b", X86Register.R8B, 0, 8) ))), new("r9", X86Register.R9, 0, 64, new RegisterIR("r9d", X86Register.R9D, 0, 32, new RegisterIR("r9w", X86Register.R9W, 0, 16, new RegisterIR("r9b", X86Register.R9B, 0, 8) ))), new("r10", X86Register.R10, 0, 64, new RegisterIR("r10d", X86Register.R10D, 0, 32, new RegisterIR("r10w", X86Register.R10W, 0, 16, new RegisterIR("r10b", X86Register.R10B, 0, 8) ))), new("r11", X86Register.R11, 0, 64, new RegisterIR("r11d", X86Register.R11D, 0, 32, new RegisterIR("r11w", X86Register.R11W, 0, 16, new RegisterIR("r11b", X86Register.R11B, 0, 8) ))), new("r12", X86Register.R12, 0, 64, new RegisterIR("r12d", X86Register.R12D, 0, 32, new RegisterIR("r12w", X86Register.R12W, 0, 16, new RegisterIR("r12b", X86Register.R12B, 0, 8) ))), new("r13", X86Register.R13, 0, 64, new RegisterIR("r13d", X86Register.R13D, 0, 32, new RegisterIR("r13w", X86Register.R13W, 0, 16, new RegisterIR("r13b", X86Register.R13B, 0, 8) ))), new("r14", X86Register.R14, 0, 64, new RegisterIR("r14d", X86Register.R14D, 0, 32, new RegisterIR("r14w", X86Register.R14W, 0, 16, new RegisterIR("r14b", X86Register.R14B, 0, 8) ))), new("r15", X86Register.R15, 0, 64, new RegisterIR("r15d", X86Register.R15D, 0, 32, new RegisterIR("r15w", X86Register.R15W, 0, 16, new RegisterIR("r15b", X86Register.R15B, 0, 8) ))), new("cs", X86Register.CS, 0, 16), new("ds", X86Register.DS, 0, 16), new("es", X86Register.ES, 0, 16), new("fs", X86Register.FS, 0, 16), new("gs", X86Register.GS, 0, 16), new("ss", X86Register.SS, 0, 16), new("rip", X86Register.RIP, 0, 64, new RegisterIR("eip", X86Register.EIP, 0, 32, new RegisterIR("ip", X86Register.IP, 0, 16) )), new("rflags", X86Register.RFLAGS, 0, 64, new RegisterIR("eflags", X86Register.EFLAGS, 0, 32, new RegisterIR("flags", X86Register.FLAGS, 0, 16, new RegisterIR("cf", X86Register.CF, 0, 1), new RegisterIR("pf", X86Register.PF, 2, 1), new RegisterIR("af", X86Register.AF, 4, 1), new RegisterIR("zf", X86Register.ZF, 6, 1), new RegisterIR("sf", X86Register.SF, 7, 1), new RegisterIR("tf", X86Register.TF, 8, 1), new RegisterIR("if", X86Register.IF, 9, 1), new RegisterIR("df", X86Register.DF, 10, 1), new RegisterIR("of", X86Register.OF, 11, 1) ))), new("ymm0", X86Register.YMM0, 0, 256, new RegisterIR("xmm0", X86Register.XMM0, 0, 128)), new("ymm1", X86Register.YMM1, 0, 256, new RegisterIR("xmm1", X86Register.XMM1, 0, 128)), new("ymm2", X86Register.YMM2, 0, 256, new RegisterIR("xmm2", X86Register.XMM2, 0, 128)), new("ymm3", X86Register.YMM3, 0, 256, new RegisterIR("xmm3", X86Register.XMM3, 0, 128)), new("ymm4", X86Register.YMM4, 0, 256, new RegisterIR("xmm4", X86Register.XMM4, 0, 128)), new("ymm5", X86Register.YMM5, 0, 256, new RegisterIR("xmm5", X86Register.XMM5, 0, 128)), new("ymm6", X86Register.YMM6, 0, 256, new RegisterIR("xmm6", X86Register.XMM6, 0, 128)), new("ymm7", X86Register.YMM7, 0, 256, new RegisterIR("xmm7", X86Register.XMM7, 0, 128)), new("ymm8", X86Register.YMM8, 0, 256, new RegisterIR("xmm8", X86Register.XMM8, 0, 128)), new("ymm9", X86Register.YMM9, 0, 256, new RegisterIR("xmm9", X86Register.XMM9, 0, 128)), new("ymm10", X86Register.YMM10, 0, 256, new RegisterIR("xmm10", X86Register.XMM10, 0, 128)), new("ymm11", X86Register.YMM11, 0, 256, new RegisterIR("xmm11", X86Register.XMM11, 0, 128)), new("ymm12", X86Register.YMM12, 0, 256, new RegisterIR("xmm12", X86Register.XMM12, 0, 128)), new("ymm13", X86Register.YMM13, 0, 256, new RegisterIR("xmm13", X86Register.XMM13, 0, 128)), new("ymm14", X86Register.YMM14, 0, 256, new RegisterIR("xmm14", X86Register.XMM14, 0, 128)), new("ymm15", X86Register.YMM15, 0, 256, new RegisterIR("xmm15", X86Register.XMM15, 0, 128)) }; public X86RegisterTable() { PopulateRegisterTable(registers_); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/Defaults/DefaultDiffOutputFilter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using DiffPlex.DiffBuilder.Model; using ProfileExplorer.Core; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Document.Renderers.Highlighters; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.Core.Compilers.Default; public sealed class DefaultDiffOutputFilter : IDiffOutputFilter { private DiffSettings settings_; private ICompilerIRInfo compilerInfo_; private char[] ExpansionStopLetters => new[] { '(', ')', '<', '>', ',', '.', ';', ':', '|', '[', ']', '{', '}', '!', ' ', '\t' }; public char[] IgnoredDiffLetters => new[] { '(', ')', ',', '.', ';', ':', '|', '{', '}', '!', ' ', '\t' }; public void Initialize(DiffSettings settings, ICompilerIRInfo compilerInfo) { settings_ = settings; compilerInfo_ = compilerInfo; } public DiffKind EstimateModificationType(DiffPiece before, DiffPiece after, int beforeOffset, int afterOffset, string beforeLineText, string afterLineText) { string beforeText = ExpandDiff(before.Text, beforeOffset, beforeLineText, out int beforeLeftStopIndex, out int beforeRightStopIndex); string afterText = ExpandDiff(after.Text, afterOffset, afterLineText, out int afterLeftStopIndex, out int afterRightStopIndex); if (IsTemporaryVariable(beforeText, out int beforeNumber) && IsTemporaryVariable(afterText, out int afterNumber)) { if (beforeNumber == afterNumber) { return DiffKind.MinorModification; } if (settings_.FilterTempVariableNames) { return DiffKind.MinorModification; } } else if (IsSSANumber(beforeText, beforeLeftStopIndex, beforeRightStopIndex, beforeLineText) && IsSSANumber(afterText, afterLeftStopIndex, afterRightStopIndex, afterLineText)) { if (settings_.FilterSSADefNumbers) { return DiffKind.MinorModification; } } else if (IsCommentText(beforeText, beforeLeftStopIndex, beforeRightStopIndex, beforeLineText) || IsCommentText(afterText, afterLeftStopIndex, afterRightStopIndex, afterLineText)) { return DiffKind.MinorModification; } return DiffKind.Modification; } public AdjustedDiffPiece AdjustChange(DiffPiece change, int documentOffset, int lineOffset, string lineText) { string text = ExpandDiff(change.Text, lineOffset, lineText, out int leftStopIndex, out int rightStopIndex); if (IsTemporaryVariable(text, out int _)) { // Enlarge diff marking to cover entire variable/opcode. int lineStartOffset = documentOffset - lineOffset; return new AdjustedDiffPiece(lineStartOffset + leftStopIndex, text.Length); } if (IsSSANumber(text, leftStopIndex, rightStopIndex, lineText)) { // Enlarge diff to include entire SSA number <*123> instead of just some digits. if (lineText[leftStopIndex] != '<' && leftStopIndex > 0) { leftStopIndex--; } if (lineText[rightStopIndex] != '>' && rightStopIndex < lineText.Length - 1) { rightStopIndex++; } int lineStartOffset = documentOffset - lineOffset; return new AdjustedDiffPiece(lineStartOffset + leftStopIndex, rightStopIndex - leftStopIndex + 1); } return new AdjustedDiffPiece(documentOffset, change.Text.Length); } private static bool IsSSANumberEnd(int rightStopIndex, string lineText) { return lineText[rightStopIndex] == '>' || lineText[rightStopIndex] == 'l' || lineText[rightStopIndex] == 'r'; } private static bool IsSSANumberStart(int leftStopIndex, string lineText) { return lineText[leftStopIndex] == '<' || lineText[leftStopIndex] == '*' || char.IsDigit(lineText[leftStopIndex]); } private bool IsTemporaryVariable(string text, out int tempNumber) { tempNumber = 0; var name = text.AsSpan(); int prefixLength = 0; //? TODO: Should query ICompilerInfo instead of hardcoding this. if (name.StartsWith("t".AsSpan())) { prefixLength = 1; } else { return false; } var remainingName = name.Slice(prefixLength); int index = 0; while (index < remainingName.Length && char.IsDigit(remainingName[index])) { index++; } if (index < remainingName.Length) { if (Array.IndexOf(ExpansionStopLetters, remainingName[index]) != -1) { remainingName = remainingName.Slice(0, index); } else { return false; } } return int.TryParse(remainingName, out tempNumber); } private bool IsSSANumber(string text, int leftStopIndex, int rightStopIndex, string lineText) { bool hasSSANumberStart = IsSSANumberStart(leftStopIndex, lineText); bool hasSSANumberEnd = IsSSANumberEnd(rightStopIndex, lineText); bool isCandidate = hasSSANumberStart && hasSSANumberEnd; if (!isCandidate) { // Sometimes the < > letters are not part of the diff, check the // previous/next letters too. if (!hasSSANumberStart && leftStopIndex > 0 && IsSSANumberStart(leftStopIndex - 1, lineText)) { leftStopIndex--; hasSSANumberStart = true; } if (!hasSSANumberEnd && rightStopIndex < lineText.Length - 1 && IsSSANumberEnd(rightStopIndex + 1, lineText)) { rightStopIndex++; hasSSANumberEnd = true; } isCandidate = hasSSANumberStart && hasSSANumberEnd; } if (isCandidate) { leftStopIndex += !char.IsDigit(lineText[leftStopIndex]) ? 1 : 0; rightStopIndex -= !char.IsDigit(lineText[rightStopIndex]) ? 1 : 0; string defNumber = lineText.Substring(leftStopIndex, rightStopIndex - leftStopIndex + 1); return int.TryParse(defNumber, out int _); } return false; } private bool IsCommentText(string text, int leftStopIndex, int rightStopIndex, string lineText) { // Everything following # is debug info and line numbers. return lineText.LastIndexOf('#', leftStopIndex) != -1; } private string ExpandDiff(string diffText, int lineOffset, string lineText, out int leftStopIndex, out int rightStopIndex) { if (diffText.Length == 0 || lineOffset >= lineText.Length) { leftStopIndex = rightStopIndex = 0; return diffText; } // Sometimes the diff starts with one of the stop letters, which should not // be included in the diff, just skip over it. while (lineOffset < lineText.Length - 1 && Array.IndexOf(ExpansionStopLetters, lineText[lineOffset]) != -1) { lineOffset++; } // Expand left/right as long no end marker letters are found. int left = lineOffset; int right = lineOffset; while (left > 0) { if (Array.IndexOf(ExpansionStopLetters, lineText[left - 1]) != -1) { break; } left--; } while (right < lineText.Length - 1) { if (Array.IndexOf(ExpansionStopLetters, lineText[right + 1]) != -1) { break; } right++; } leftStopIndex = left; rightStopIndex = right; return lineText.Substring(left, right - left + 1); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/Defaults/DefaultNameProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using ProfileExplorer.Core; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.Default; public enum FilteredSectionNameKind { TrimPrefix, TrimSuffix, TrimWhitespace, RemoveSubstring, ReplaceSubstring } public class FilteredSectionName { public FilteredSectionName(string text, FilteredSectionNameKind filterKind) { Text = text; FilterKind = filterKind; } public string Text { get; set; } public string ReplacementText { get; set; } public FilteredSectionNameKind FilterKind { get; set; } } public sealed class DefaultNameProvider : INameProvider { private static List sectionNameFilters_; private static ConcurrentDictionary demangledNameMap_; private static ConcurrentDictionary functionNameMap_; static DefaultNameProvider() { demangledNameMap_ = new ConcurrentDictionary(); functionNameMap_ = new ConcurrentDictionary(); sectionNameFilters_ = new List(); sectionNameFilters_.Add(new FilteredSectionName("* ", FilteredSectionNameKind.TrimPrefix)); sectionNameFilters_.Add(new FilteredSectionName(" *", FilteredSectionNameKind.TrimSuffix)); sectionNameFilters_.Add(new FilteredSectionName("", FilteredSectionNameKind.TrimWhitespace)); sectionNameFilters_.Add( new FilteredSectionName("pass", FilteredSectionNameKind.RemoveSubstring)); } public bool IsDemanglingSupported => true; public bool IsDemanglingEnabled => IsDemanglingSupported && CoreSettingsProvider.SectionSettings.ShowDemangledNames; public FunctionNameDemanglingOptions GlobalDemanglingOptions => CoreSettingsProvider.SectionSettings.DemanglingOptions; public string GetSectionName(IRTextSection section, bool includeNumber) { string sectionName = section.Name; if (string.IsNullOrEmpty(sectionName)) { string funcName = section.ParentFunction.Name; if (!string.IsNullOrEmpty(funcName)) { return funcName.Length <= 24 ? funcName : $"{funcName.Substring(0, 24)}..."; } return ""; } foreach (var nameFilter in sectionNameFilters_) { if (string.IsNullOrEmpty(nameFilter.Text) && nameFilter.FilterKind != FilteredSectionNameKind.TrimWhitespace) { continue; } switch (nameFilter.FilterKind) { case FilteredSectionNameKind.TrimPrefix: { if (sectionName.StartsWith(nameFilter.Text, StringComparison.Ordinal)) { sectionName = sectionName.Substring(nameFilter.Text.Length); } break; } case FilteredSectionNameKind.TrimSuffix: { if (sectionName.EndsWith(nameFilter.Text, StringComparison.Ordinal)) { sectionName = sectionName.Substring(0, sectionName.Length - nameFilter.Text.Length - 1); } break; } case FilteredSectionNameKind.TrimWhitespace: { sectionName = sectionName.Trim(); break; } case FilteredSectionNameKind.RemoveSubstring: { if (sectionName.Contains(nameFilter.Text, StringComparison.Ordinal)) { sectionName = sectionName.Replace(nameFilter.Text, "", StringComparison.Ordinal); } break; } case FilteredSectionNameKind.ReplaceSubstring: { if (sectionName.Contains(nameFilter.Text, StringComparison.Ordinal)) { sectionName = sectionName.Replace(nameFilter.Text, nameFilter.ReplacementText, StringComparison.Ordinal); } break; } default: throw new ArgumentOutOfRangeException(); } } if (includeNumber) { return $"({section.Number}) {sectionName}"; } return sectionName; } public string GetFunctionName(IRTextFunction function) { return function.Name; } public string DemangleFunctionName(string name, FunctionNameDemanglingOptions options) { if (!demangledNameMap_.TryGetValue(name, out string demangledName)) { demangledName = PDBDebugInfoProvider.DemangleFunctionName(name, options); demangledNameMap_.TryAdd(name, demangledName); } return demangledName; } public string DemangleFunctionName(IRTextFunction function, FunctionNameDemanglingOptions options) { return DemangleFunctionName(function.Name, options); } public string FormatFunctionName(string name) { if (!IsDemanglingEnabled) { return name; } if (!functionNameMap_.TryGetValue(name, out string demangledName)) { demangledName = PDBDebugInfoProvider.DemangleFunctionName(name, FunctionNameDemanglingOptions.OnlyName); functionNameMap_.TryAdd(name, demangledName); } return demangledName; } public string FormatFunctionName(IRTextFunction function) { return FormatFunctionName(function.Name); } public void SettingsChanged() { demangledNameMap_.Clear(); functionNameMap_.Clear(); } } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMBinaryFileFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.Core.Compilers.LLVM; public class LLVMBinaryFileFinder : IBinaryFileFinder { public async Task FindBinaryFileAsync(BinaryFileDescriptor binaryFile, SymbolFileSourceSettings settings = null) { // LLVM implementation doesn't support binary file searching yet return BinaryFileSearchResult.None; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMCompilerIRInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; namespace ProfileExplorer.Core.Compilers.LLVM; public class LLVMCompilerIRInfo : ICompilerIRInfo { public IRMode Mode { get; set; } public InstructionOffsetData InstructionOffsetData => InstructionOffsetData.VariableSize(1, 16); public IRSectionReader CreateSectionReader(string filePath, bool expectSectionHeaders) { return new LLVMSectionReader(filePath, expectSectionHeaders); } public IRSectionReader CreateSectionReader(byte[] textData, bool expectSectionHeaders) { return new LLVMSectionReader(textData, expectSectionHeaders); } public IRSectionParser CreateSectionParser(IRParsingErrorHandler errorHandler, long functionSize) { return null; } public IRParsingErrorHandler CreateParsingErrorHandler() { return new ParsingErrorHandler(); } public IReachableReferenceFilter CreateReferenceFilter(FunctionIR function) { return null; } public bool IsCopyInstruction(InstructionIR instr) { return SkipCopyInstruction(instr) != null; } public bool IsLoadInstruction(InstructionIR instr) { return false; } public bool IsStoreInstruction(InstructionIR instr) { return false; } public bool IsCallInstruction(InstructionIR instr) { return false; } public OperandIR GetCallTarget(InstructionIR instr) { return null; } public OperandIR GetBranchTarget(InstructionIR instr) { return null; } public bool IsIntrinsicCallInstruction(InstructionIR instr) { return false; } public bool IsPhiInstruction(InstructionIR instr) { return false; } public bool IsNOP(InstructionIR instr) { throw new NotImplementedException(); } public BlockIR GetIncomingPhiOperandBlock(InstructionIR phiInstr, int opIndex) { return null; } public IRElement SkipCopyInstruction(InstructionIR instr) { return null; } public bool OperandsReferenceSameSymbol(OperandIR opA, OperandIR opB, bool exactCheck) { return false; } public InstructionIR GetTransferInstruction(BlockIR block) { return null; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMCompilerInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Threading.Tasks; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Compilers.LLVM; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Compilers.Default; namespace ProfileExplorer.Core.Compilers.LLVM; public class LLVMCompilerInfoProvider : ICompilerInfoProvider { private LLVMCompilerIRInfo ir_; private DefaultNameProvider names_; private readonly IBinaryFileFinder binaryFileFinder_; private readonly IDebugFileFinder debugFileFinder_; private readonly IDebugInfoProviderFactory debugInfoProviderFactory_; private readonly IDiffFilterProvider diffFilterProvider_; public LLVMCompilerInfoProvider() { ir_ = new LLVMCompilerIRInfo(); names_ = new DefaultNameProvider(); binaryFileFinder_ = new LLVMBinaryFileFinder(); debugFileFinder_ = new LLVMDebugFileFinder(); debugInfoProviderFactory_ = new LLVMDebugInfoProviderFactory(); diffFilterProvider_ = new LLVMDiffFilterProvider(); } public string CompilerIRName => "LLVM"; public CompilerIRKind CompilerIRKind => CompilerIRKind.LLVM; public string CompilerDisplayName => "LLVM"; public string DefaultSyntaxHighlightingFile => "LLVM"; public string OpenFileFilter => "IR Files|*.txt;*.log;*.ir;*.tup;*.out;*.pex|Profile Explorer Session Files|*.pex|All Files|*.*"; public string OpenDebugFileFilter => "Debug Files|*.pdb|All Files|*.*"; public ICompilerIRInfo IR => ir_; public INameProvider NameProvider => names_; public IBinaryFileFinder BinaryFileFinder => binaryFileFinder_; public IDebugFileFinder DebugFileFinder => debugFileFinder_; public IDebugInfoProviderFactory DebugInfoProviderFactory => debugInfoProviderFactory_; public IDiffFilterProvider DiffFilterProvider => diffFilterProvider_; public async Task AnalyzeLoadedFunction(FunctionIR function, IRTextSection section, ILoadedDocument loadedDoc, FunctionDebugInfo funcDebugInfo) { //? TODO: var loopGraph = new LoopGraph(function); //loopGraph.FindLoops(); return true; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMDebugFileFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.LLVM; public class LLVMDebugFileFinder : IDebugFileFinder { public async Task FindDebugInfoFileAsync(string imagePath, SymbolFileSourceSettings settings = null) { // LLVM implementation uses a simple file location approach return Utils.LocateDebugInfoFile(imagePath, ".pdb"); } public async Task FindDebugInfoFileAsync(SymbolFileDescriptor symbolFile, SymbolFileSourceSettings settings = null) { // LLVM implementation doesn't support symbol file descriptor searches yet return DebugFileSearchResult.None; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMDebugInfoProviderFactory.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; namespace ProfileExplorer.Core.Compilers.LLVM; public class LLVMDebugInfoProviderFactory : IDebugInfoProviderFactory { public IDebugInfoProvider CreateDebugInfoProvider(DebugFileSearchResult debugFile) { // LLVM implementation doesn't support debug info providers yet return null; } public IDebugInfoProvider GetOrCreateDebugInfoProvider(IRTextFunction function, ILoadedDocument loadedDoc) { return null; } } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMDiffFilterProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Compilers.Default; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Compilers.LLVM; public class LLVMDiffFilterProvider : IDiffFilterProvider { public IDiffInputFilter CreateDiffInputFilter() => null; public IDiffOutputFilter CreateDiffOutputFilter() => new DefaultDiffOutputFilter(); } ================================================ FILE: src/ProfileExplorerCore/Compilers/LLVM/LLVMSectionReader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; namespace ProfileExplorer.Core.Compilers.LLVM; public sealed class LLVMSectionReader : SectionReaderBase, IDisposable { private const string SectionStartLine = "*** IR Dump "; private const string SectionEndLine = "***"; private static readonly char[] WhitespaceChars = {' ', '\t'}; public LLVMSectionReader(string filePath, bool expectSectionHeaders = true) : base(filePath, expectSectionHeaders) { } public LLVMSectionReader(byte[] textData, bool expectSectionHeaders = true) : base(textData, expectSectionHeaders) { } protected override bool IsSectionStart(string line) { return line.StartsWith(SectionStartLine, StringComparison.Ordinal); } protected override bool IsFunctionStart(string line) { return line.StartsWith("define", StringComparison.Ordinal) && line.EndsWith("{", StringComparison.Ordinal); } protected override bool IsBlockStart(string line) { return false; } protected override bool IsFunctionEnd(string line) { return line.StartsWith("}", StringComparison.Ordinal); } protected override string ExtractSectionName(string line) { int start = line.IndexOf(SectionStartLine); if (start == -1) { return ""; } int end = line.LastIndexOf(SectionEndLine); int length = end - start - SectionStartLine.Length; if (length > 0) { return line.Substring(start + SectionStartLine.Length, length).Trim(); } return ""; } protected override string ExtractFunctionName(string line) { // Function names start with @ and end before the ( starting the parameter list. int start = line.IndexOf('@'); if (start == -1) { return ""; } int end = line.IndexOf('(', start + 1); int length = end - start - 1; if (length > 0) { return line.Substring(start + 1, length); } return ""; } protected override string PreprocessLine(string line) { return line; } protected override bool ShouldSkipOutputLine(string line) { return string.IsNullOrWhiteSpace(line); } protected override bool IsMetadataLine(string line) { return false; } protected override bool FunctionEndIsFunctionStart(string line) { return false; } protected override bool SectionStartIsFunctionStart(string line) { return false; } } ================================================ FILE: src/ProfileExplorerCore/Controls/IRElementReference.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.IR; using ProtoBuf; namespace ProfileExplorer.Core.Controls; [ProtoContract(SkipConstructor = true)] public class IRElementReference { [ProtoMember(1)] public ulong Id; public IRElement Value; public IRElementReference() { Id = 0; } public IRElementReference(IRElement element) { Id = element.Id; Value = element; } public IRElementReference(ulong id, IRElement element = null) { Id = id; Value = element; } public IRElementReference(IRElementId id, IRElement element = null) { Id = id.ToLong(); Value = element; } public static implicit operator IRElementReference(IRElement element) { return new IRElementReference(element.Id, element); } public static implicit operator IRElement(IRElementReference elementRef) { return elementRef.Value; } } ================================================ FILE: src/ProfileExplorerCore/Core.vsdoc ================================================  default ]]> VSdocman]]> normal yes Core Reference core_reference vsdocman_escaped_]_]_> placeholder no 342ea4dbb14a405c836ed23f3a7ada12 ]]> ================================================ FILE: src/ProfileExplorerCore/Diff/BeyondCompareDiffBuilder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; using System.Text; using System.Threading.Tasks; using DiffPlex.DiffBuilder.Model; using HtmlAgilityPack; using ProfileExplorer.Core.Utilities; #pragma warning disable CA1305, CA1307 namespace ProfileExplorer.Core.Diff; public class BeyondCompareDiffBuilder { private const string BeyondCompareDirectory = @"Beyond Compare 4"; private const string BeyondCompareExecutable = @"BCompare.exe"; public static string FindBeyondCompareExecutable() { // Look for BC in Program Files. string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), BeyondCompareDirectory, BeyondCompareExecutable); if (File.Exists(path)) { return path; } // If not found, look on PATH. path = NativeMethods.GetFullPathFromWindows(BeyondCompareExecutable); return path ?? ""; } public static bool HasBeyondCompareExecutable() { return !string.IsNullOrEmpty(FindBeyondCompareExecutable()); } public static SideBySideDiffModel ComputeDiffs(string leftText, string rightText, string beyondComparePath) { string reportPath = GenerateReport(leftText, rightText, beyondComparePath); if (string.IsNullOrEmpty(reportPath)) { return null; // Failed to get Beyond Compare results. } var diff = GenerateDiffsFromReport(reportPath); try { File.Delete(reportPath); } catch (Exception ex) { Trace.TraceError($"BeyondCompareDiffBuilder: Failed to delete report file: {ex.Message}"); } return diff; } private static string GenerateReport(string leftText, string rightText, string beyondComparePath) { string leftPath; string rightPath; string scriptPath; string reportPath; try { leftPath = Path.GetTempFileName(); rightPath = Path.GetTempFileName(); scriptPath = Path.GetTempFileName(); reportPath = Path.GetTempFileName(); } catch (Exception ex) { Trace.TraceError($"BeyondCompareDiffBuilder: Failed to get temp file names: {ex.Message}"); return null; } // Write the text to compare on multiple threads. var task1 = Task.Run(() => File.WriteAllText(leftPath, leftText)); var task2 = Task.Run(() => File.WriteAllText(rightPath, rightText)); var task3 = Task.Run(() => { string scriptBody = string.Format( "file-report layout:side-by-side options:ignore-unimportant output-to:{0} output-options:html-color {1} {2}", reportPath, leftPath, rightPath); File.WriteAllText(scriptPath, scriptBody); }); Task.WaitAll(task1, task2, task3); // Start Beyond Compare. try { var psi = new ProcessStartInfo(beyondComparePath, string.Format("@{0} /silent", scriptPath)); var process = Process.Start(psi); process.WaitForExit(); } catch (Exception ex) { Trace.TraceError( $"BeyondCompareDiffBuilder: Failed to start bcompare.exe: {beyondComparePath}"); return null; } // Clean up temporary files. try { File.Delete(leftPath); File.Delete(leftPath); File.Delete(scriptPath); } catch (Exception ex) { Trace.TraceError($"BeyondCompareDiffBuilder: Failed to delete temp files: {ex.Message}"); } return reportPath; } private static Section GetRowSection(HtmlNode row) { string rowClass = row.GetAttributeValue("class", ""); switch (rowClass) { case "SectionAll": return Section.All; case "SectionBegin": return Section.Begin; case "SectionMiddle": return Section.Middle; case "SectionEnd": return Section.End; default: throw new ArgumentOutOfRangeException(); } } private static ChangeType GetDiffChangeType(HtmlNode node) { switch (node.InnerText) { case "=": return ChangeType.Unchanged; case "+-": return ChangeType.Deleted; case "-+": return ChangeType.Inserted; case "<>": return ChangeType.Modified; default: throw new ArgumentOutOfRangeException(); } } private static SideBySideDiffModel GenerateDiffsFromReport(string reportPath) { var diffs = new SideBySideDiffModel(); var doc = new HtmlDocument(); doc.Load(reportPath); var table = GetFirst(doc.DocumentNode.Descendants("table")); if (table == null) { return diffs; } // Use ChangeType.Imaginary to represent not being in a section. const ChangeType ChangeTypeNoSection = ChangeType.Imaginary; var sectionChangeType = ChangeTypeNoSection; int oldPosition = 0; int newPosition = 0; // The html body contains a table with one row per line. foreach (var row in table.Descendants("tr")) { // We expect to see 3 columns. Old, diff type, New. var columns = row.Descendants("td"); HtmlNode oldNode; HtmlNode diffNode; HtmlNode newNode; if (!GetNodes(columns, out oldNode, out diffNode, out newNode)) { return diffs; } // BC breaks down diffs by sections. If a section is a single row, the row's class is // SectionAll, otherwise the class is SectionBegin, SectionMiddle, or SectionEnd. // Only the SectionAll and SectionBegin rows have the section type noted (unchanged, // insert, delete, modify, etc). var rowSection = GetRowSection(row); Debug.Assert(rowSection != Section.Middle || NodeIsEmpty(diffNode)); if (rowSection == Section.All || rowSection == Section.Begin) { Debug.Assert(sectionChangeType == ChangeTypeNoSection); sectionChangeType = GetDiffChangeType(diffNode); } Debug.Assert(sectionChangeType != ChangeTypeNoSection); switch (sectionChangeType) { case ChangeType.Unchanged: diffs.OldText.Lines.Add(DiffPieceFromHtmlText(oldNode, ChangeType.Unchanged, ++oldPosition)); diffs.NewText.Lines.Add(DiffPieceFromHtmlText(newNode, ChangeType.Unchanged, ++newPosition)); break; case ChangeType.Inserted: diffs.OldText.Lines.Add(new DiffPiece()); diffs.NewText.Lines.Add(DiffPieceFromHtmlText(newNode, ChangeType.Inserted, ++newPosition)); break; case ChangeType.Deleted: diffs.OldText.Lines.Add(DiffPieceFromHtmlText(oldNode, ChangeType.Deleted, ++oldPosition)); diffs.NewText.Lines.Add(new DiffPiece()); break; case ChangeType.Modified: // Lines added or removed in the middle of a "modified" section show up as blank // nodes on one side or the other. At least one side should be non-empty. Debug.Assert(!NodeIsEmpty(oldNode) || !NodeIsEmpty(newNode)); if (NodeIsEmpty(oldNode)) { diffs.OldText.Lines.Add(new DiffPiece()); diffs.NewText.Lines.Add( DiffPieceFromModifiedNode(newNode, ChangeType.Inserted, ChangeType.Inserted, ++newPosition)); } else if (NodeIsEmpty(newNode)) { diffs.OldText.Lines.Add( DiffPieceFromModifiedNode(oldNode, ChangeType.Deleted, ChangeType.Deleted, ++oldPosition)); diffs.NewText.Lines.Add(new DiffPiece()); } else { diffs.OldText.Lines.Add( DiffPieceFromModifiedNode(oldNode, ChangeType.Modified, ChangeType.Deleted, ++oldPosition)); diffs.NewText.Lines.Add( DiffPieceFromModifiedNode(newNode, ChangeType.Modified, ChangeType.Inserted, ++newPosition)); } break; default: Debug.Assert(false); break; } if (rowSection == Section.All || rowSection == Section.End) { sectionChangeType = ChangeTypeNoSection; } } return diffs; } private static bool NodeIsEmpty(HtmlNode node) { return string.IsNullOrEmpty(node.InnerText) || node.InnerText == " "; } private static DiffPiece DiffPieceFromModifiedNode(HtmlNode node, ChangeType type, ChangeType childChangeType, int position) { var diffs = new DiffPiece("", type, position); var builder = new StringBuilder(100); int pieceNumber = 0; foreach (var child in node.ChildNodes) { Debug.Assert(child.Name == "#text" || child.Name == "span" && child.GetAttributeValue("class", "") == "TextSegSigDiff"); var childType = child.Name == "#text" ? ChangeType.Unchanged : childChangeType; var subPiece = DiffPieceFromHtmlText(child, childType, ++pieceNumber); // Sometimes consecutive entries of the same type (deletion for ex) // appear and those can be combined into a single change. //? TODO: Check if this actually interferes with marking of minor diffs //if (diffs.SubPieces.Count > 0) { // var prevPiece = diffs.SubPieces[^1]; // if (prevPiece.Type == subPiece.Type) { // prevPiece.Text += subPiece.Text; // builder.Append(subPiece.Text); // continue; // } //} diffs.SubPieces.Add(subPiece); builder.Append(subPiece.Text); } diffs.Text = builder.ToString(); return diffs; } private static DiffPiece DiffPieceFromHtmlText(HtmlNode node, ChangeType type, int position) { string text = WebUtility.HtmlDecode(node.InnerText); return new DiffPiece(text, type, position); } private static T GetFirst(IEnumerable collection) { var collectionEnum = collection.GetEnumerator(); if (!collectionEnum.MoveNext()) { return default(T); } return collectionEnum.Current; } private static bool GetNodes(IEnumerable collection, out T node1, out T node2, out T node3) { var collectionEnum = collection.GetEnumerator(); if (!collectionEnum.MoveNext()) { node1 = node2 = node3 = default(T); return false; } node1 = collectionEnum.Current; if (!collectionEnum.MoveNext()) { node1 = node2 = node3 = default(T); return false; } node2 = collectionEnum.Current; if (!collectionEnum.MoveNext()) { node1 = node2 = node3 = default(T); return false; } node3 = collectionEnum.Current; return true; } private enum Section { All, Begin, Middle, End } } ================================================ FILE: src/ProfileExplorerCore/Diff/DocumentDiffBuilder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Threading.Tasks; using DiffPlex; using DiffPlex.DiffBuilder; using DiffPlex.DiffBuilder.Model; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Diff; public enum DiffImplementationKind { Internal, External } public class DocumentDiffResult { public DocumentDiffResult(IRTextSection leftSection, IRTextSection rightSection, SideBySideDiffModel model, bool hasDiffs) { LeftSection = leftSection; RightSection = rightSection; Model = model; HasDiffs = hasDiffs; } public IRTextSection LeftSection { get; set; } public IRTextSection RightSection { get; set; } public SideBySideDiffModel Model { get; set; } public bool HasDiffs { get; set; } } public class DocumentDiffBuilder { private static readonly char[] IgnoredDiffLetters = { '(', ')', ',', '.', ';', ':', '|', '{', '}', '!', ' ', '\t', '\r', '\n' }; private DiffSettings settings_; public DocumentDiffBuilder(DiffSettings settings) { settings_ = settings; } public SideBySideDiffModel ComputeDiffs(string leftText, string rightText) { if (settings_.DiffImplementation == DiffImplementationKind.External) { if (!string.IsNullOrEmpty(settings_.ExternalDiffAppPath)) { var result = BeyondCompareDiffBuilder.ComputeDiffs(leftText, rightText, settings_.ExternalDiffAppPath); if (result != null) { return result; } } throw new NotImplementedException(); // Fall back to the internal diff engine if the external one failed. } return ComputeInternalDiffs(leftText, rightText); } public SideBySideDiffModel ComputeInternalDiffs(string leftText, string rightText) { var diffBuilder = new SideBySideDiffBuilder(new Differ(), IgnoredDiffLetters); if (leftText.Equals(rightText, StringComparison.Ordinal)) { diffBuilder.BuildDiffModel("", ""); } return diffBuilder.BuildDiffModel(leftText, rightText); } public bool HasDiffs(SideBySideDiffModel diffModel) { foreach (var line in diffModel.OldText.Lines) { if (line.Type != ChangeType.Unchanged && line.Type != ChangeType.Imaginary) { return true; } } return false; } public async Task> AreSectionsDifferent( List<(IRTextSection, IRTextSection)> comparedSections, IRTextSectionLoader leftDocLoader, IRTextSectionLoader rightDocLoader, ICompilerInfoProvider irInfo, bool quickMode, CancelableTask cancelableTask) { int maxConcurrency = CoreSettingsProvider.GeneralSettings.CurrentCpuCoreLimit; var tasks = new Task[comparedSections.Count]; await Task.Run(() => AreSectionsDifferentImpl(comparedSections, leftDocLoader, rightDocLoader, tasks, irInfo, quickMode, cancelableTask, maxConcurrency)); var results = new List(tasks.Length); foreach (var task in tasks) { results.Add(await task); } return results; } private async Task AreSectionsDifferentImpl( List<(IRTextSection, IRTextSection)> comparedSections, IRTextSectionLoader leftDocLoader, IRTextSectionLoader rightDocLoader, Task[] tasks, ICompilerInfoProvider irInfo, bool quickMode, CancelableTask cancelableTask, int maxConcurrency) { //? ConcurrentExclusiveSchedulerPair from DocSectionLoader is not the right solution var taskScheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, maxConcurrency); var taskFactory = new TaskFactory(taskScheduler.ConcurrentScheduler); int index = 0; foreach (var pair in comparedSections) { var leftSection = pair.Item1; var rightSection = pair.Item2; tasks[index++] = taskFactory.StartNew(() => { if (quickMode) { if (leftDocLoader.SectionSignaturesComputed && rightDocLoader.SectionSignaturesComputed) { if (!leftSection.IsSectionTextDifferent(rightSection)) { return new DocumentDiffResult(leftSection, rightSection, null, false); } } string leftText = leftDocLoader.GetSectionText(leftSection, false); string rightText = rightDocLoader.GetSectionText(rightSection, false); if (leftText.Equals(rightText, StringComparison.Ordinal)) { return new DocumentDiffResult(leftSection, rightSection, null, false); } var leftInputFilter = irInfo.DiffFilterProvider?.CreateDiffInputFilter(); var rightInputFilter = irInfo.DiffFilterProvider?.CreateDiffInputFilter(); if (leftInputFilter == null || rightInputFilter == null) { return new DocumentDiffResult(leftSection, rightSection, null, true); } string[] leftLines = leftText.SplitLines(); string[] rightLines = rightText.SplitLines(); if (leftLines.Length != rightLines.Length) { return new DocumentDiffResult(leftSection, rightSection, null, true); } for (int i = 0; i < leftLines.Length; i++) { string leftLine = leftLines[i]; string rightLine = rightLines[i]; string leftResult = leftInputFilter.FilterInputLine(leftLine); string rightResult = rightInputFilter.FilterInputLine(rightLine); if (!leftResult.Equals(rightResult, StringComparison.Ordinal)) { return new DocumentDiffResult(leftSection, rightSection, null, true); } } return new DocumentDiffResult(leftSection, rightSection, null, false); } else { string leftText = leftDocLoader.GetSectionText(leftSection, false); string rightText = rightDocLoader.GetSectionText(rightSection, false); var leftInputFilter = irInfo.DiffFilterProvider?.CreateDiffInputFilter(); var rightInputFilter = irInfo.DiffFilterProvider?.CreateDiffInputFilter(); if (leftInputFilter != null && rightInputFilter != null) { var leftResult = leftInputFilter.FilterInputText(leftText); var rightResult = rightInputFilter.FilterInputText(rightText); leftText = leftResult.Text; rightText = rightResult.Text; } var diffs = ComputeInternalDiffs(leftText, rightText); bool hasDiffs = HasDiffs(diffs); return new DocumentDiffResult(leftSection, rightSection, null, hasDiffs); } }, cancelableTask.Token); } await Task.WhenAll(tasks); } } ================================================ FILE: src/ProfileExplorerCore/Diff/IDiffFilterProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Providers; namespace ProfileExplorer.Core.Diff; public interface IDiffFilterProvider { IDiffInputFilter CreateDiffInputFilter(); IDiffOutputFilter CreateDiffOutputFilter(); } ================================================ FILE: src/ProfileExplorerCore/Diff/IDiffOutputFilter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using DiffPlex.DiffBuilder.Model; using ProfileExplorer.Core.Document.Renderers.Highlighters; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.Core.Diff; public interface IDiffOutputFilter { char[] IgnoredDiffLetters { get; } void Initialize(DiffSettings settings, ICompilerIRInfo ifInfo); DiffKind EstimateModificationType(DiffPiece before, DiffPiece after, int beforeOffset, int afterOffset, string beforeDocumentText, string afterDocumentText); AdjustedDiffPiece AdjustChange(DiffPiece change, int offset, int lineOffset, string lineText); } public interface IDiffInputFilter { void Initialize(DiffSettings settings, ICompilerIRInfo ifInfo); FilteredDiffInput FilterInputText(string text); string FilterInputLine(string line); } public struct AdjustedDiffPiece { public AdjustedDiffPiece(int offset, int length) { Offset = offset; Length = length; } public int Offset { get; set; } public int Length { get; set; } } public class FilteredDiffInput { public static List NoReplacements = new(0); public FilteredDiffInput(int capacity) { Text = string.Empty; LineReplacements = new List>(capacity); } public FilteredDiffInput(string text) { Text = text; LineReplacements = null; } public string Text { get; set; } public List> LineReplacements { get; set; } public struct Replacement { public Replacement(int offset, string replaced, string original) { Offset = offset; Replaced = replaced; Original = original; } public int Offset { get; set; } public string Replaced { get; set; } public string Original { get; set; } public int Length => Replaced.Length; } } public class BasicDiffOutputFilter : IDiffOutputFilter { public char[] IgnoredDiffLetters => new[] { '(', ')', ',', '.', ';', ':', '|', '{', '}', '!', ' ', '\t' }; public AdjustedDiffPiece AdjustChange(DiffPiece change, int documentOffset, int lineOffset, string lineText) { return new AdjustedDiffPiece(documentOffset, change.Text.Length); } public DiffKind EstimateModificationType(DiffPiece before, DiffPiece after, int beforeOffset, int afterOffset, string beforeDocumentText, string afterDocumentText) { return DiffKind.Modification; } public void Initialize(DiffSettings settings, ICompilerIRInfo ifInfo) { } } ================================================ FILE: src/ProfileExplorerCore/Document/Renderers/Highlighters/DiffKind.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Windows; namespace ProfileExplorer.Core.Document.Renderers.Highlighters; public enum DiffKind { None, Insertion, Deletion, Modification, MinorModification, Placeholder } ================================================ FILE: src/ProfileExplorerCore/DocumentSectionLoader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core; public sealed class DocumentSectionLoader : IRTextSectionLoader { private IRSectionReader documentReader_; private ConcurrentExclusiveSchedulerPair taskScheduler_; private TaskFactory taskFactory_; private CancelableTask preprocessTask_; public DocumentSectionLoader(ICompilerIRInfo irInfo, bool useCache = true) { Initialize(irInfo, useCache); } public DocumentSectionLoader(string filePath, ICompilerIRInfo irInfo, bool useCache = true) { Initialize(irInfo, useCache); documentReader_ = irInfo.CreateSectionReader(filePath); } public DocumentSectionLoader(byte[] textData, ICompilerIRInfo irInfo, bool useCache = true) { Initialize(irInfo, useCache); documentReader_ = irInfo.CreateSectionReader(textData); } public async override Task LoadDocument(ProgressInfoHandler progressHandler) { var tasks = new List(); var result = documentReader_.GenerateSummary(progressHandler, (reader, sectionInfo) => { if (taskScheduler_ == null) { taskScheduler_ = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, 2); taskFactory_ = new TaskFactory(taskScheduler_.ConcurrentScheduler); preprocessTask_ = new CancelableTask(); } tasks.Add(taskFactory_.StartNew(() => { ComputeSectionSignature(sectionInfo); }, preprocessTask_.Token)); }); if (result == null) { preprocessTask_.Cancel(); return null; } if (tasks.Count > 0) { Task.Run(() => { Task.WaitAll(tasks.ToArray()); NotifySectionPreprocessingCompleted(preprocessTask_.IsCanceled); }); } return result; } public override string GetDocumentOutputText() { byte[] data = documentReader_.GetDocumentTextData(); return Encoding.UTF8.GetString(data); } public override byte[] GetDocumentTextBytes() { return documentReader_.GetDocumentTextData(); } public override ParsedIRTextSection LoadSection(IRTextSection section) { //Trace.TraceInformation( // $"Section loader {ObjectTracker.Track(this)}: ({section.Number}) {section.Name}"); var result = TryGetCachedParsedSection(section); if (result != null) { return result; } var text = GetSectionTextSpan(section); var (sectionParser, errorHandler) = InitializeParser(); FunctionIR function; if (sectionParser == null) { function = new FunctionIR(); } else { function = sectionParser.ParseSection(section, text); } result = new ParsedIRTextSection(section, text, function); CacheParsedSection(section, function, result); if (errorHandler.HadParsingErrors) { result.ParsingErrors = errorHandler.ParsingErrors; } return result; } public override string GetSectionText(IRTextSection section) { return documentReader_.GetSectionText(section); } public override ReadOnlyMemory GetSectionTextSpan(IRTextSection section) { return documentReader_.GetSectionTextSpan(section); } public override string GetSectionOutputText(IRPassOutput output) { if (output == null) { // With some documents there is no before/after text. return string.Empty; } return documentReader_.GetPassOutputText(output); } public override ReadOnlyMemory GetSectionPassOutputTextSpan(IRPassOutput output) { if (output == null) { // With some documents there is no before/after text. return ReadOnlyMemory.Empty; } return documentReader_.GetPassOutputTextSpan(output); } public override List GetSectionPassOutputTextLines(IRPassOutput output) { if (output == null) { // With some documents there is no before/after text. return new List(); } return documentReader_.GetPassOutputTextLines(output); } public override string GetRawSectionText(IRTextSection section) { return documentReader_.GetRawSectionText(section); } public override string GetRawSectionPassOutput(IRPassOutput output) { return documentReader_.GetRawPassOutputText(output); } public override ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section) { return documentReader_.GetRawSectionTextSpan(section); } public override ReadOnlyMemory GetRawSectionPassOutputSpan(IRPassOutput output) { return documentReader_.GetRawPassOutputTextSpan(output); } protected override void Dispose(bool disposing) { if (!disposed_) { documentReader_?.Dispose(); preprocessTask_?.Cancel(); documentReader_ = null; disposed_ = true; } } private void ComputeSectionSignature(SectionReaderText sectionInfo) { var sha = SHA256.Create(); var lines = sectionInfo.TextLines; for (int i = 0; i < lines.Count - 1; i++) { byte[] data = Encoding.ASCII.GetBytes(lines[i]); sha.TransformBlock(data, 0, data.Length, null, 0); } if (lines.Count > 0) { byte[] data = Encoding.ASCII.GetBytes(lines[^1]); sha.TransformFinalBlock(data, 0, data.Length); } sectionInfo.Output.Signature = sha.Hash; } } ================================================ FILE: src/ProfileExplorerCore/FileFormat/FileArchive.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Linq; using System.Text.Json; using System.Threading.Tasks; namespace ProfileExplorer.Core.FileFormat; public sealed class FileArchive : IDisposable { public delegate void FileProgressDelegate(int currentFile, int totalFiles); private const string HeaderFilePath = "HEADER-4F1B8FB1-DD26-4D60-B275-6C0588668EE6"; private const int FileBufferSize = 128 * 1024; private const int FileFormatVersion = 1; private const int MinFileFormatVersion = 1; private static readonly Guid FileSignature = new("80BCEE32-5110-4A25-87D3-D359B0C2634C"); private Header header_; private ZipArchive archive_; private Stream archiveStream_; private CompressionLevel compressionLevel_; private bool modified_; private bool disposed_; private FileArchive(Stream stream, bool openForWrite, CompressionLevel level = CompressionLevel.Fastest) { try { var mode = openForWrite ? ZipArchiveMode.Create : ZipArchiveMode.Read; archive_ = new ZipArchive(stream, mode, false); } catch { stream?.Dispose(); throw; } archiveStream_ = stream; compressionLevel_ = level; CreateHeader(); } public List Files => header_.Files; public int FileCount => Files.Count; public long UncompressedSize => Files.Sum(entry => entry.Size); public bool HasOptionalData => header_.OptionalData != null; public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } public event FileProgressDelegate OnFileAdded; // Notified when adding multiple files only. public event FileProgressDelegate OnFileExtracted; // Notified when extracting multiple files only. // Optional data that can be serialized together with the header. public void SetOptionalData(object dataObject) { header_.OptionalData = dataObject; } public T GetOptionalData() { return header_.GetOptionalData(); } public IEnumerable FindFilesOfKind(int kind) { foreach (var entry in Files) { if (entry.Kind == kind) { yield return entry; } } } public bool HasFilesOfKind(int kind) { foreach (var entry in FindFilesOfKind(kind)) { return true; } return false; } public IEnumerable FindFilesInDirectory(string directoryPath, int optionalKind = 0) { foreach (var entry in Files) { if (optionalKind != 0 && entry.Kind != optionalKind) { continue; // Filter based on kind. } string entryDir = entry.Directory; if (entryDir == directoryPath) { yield return entry; continue; } // For a directoryPath foo accept files in dirs like // foo/file.ext and foo/bar/file.ext, but reject // foobar/file.ext and bar/foo/file.ext and bar/foofile.ext. int prefixIndex = entryDir.IndexOf(directoryPath, StringComparison.Ordinal); if (prefixIndex == 0 && (prefixIndex + directoryPath.Length == entryDir.Length - 1 || entryDir[prefixIndex + directoryPath.Length] == Path.DirectorySeparatorChar)) { yield return entry; } } } public static async Task LoadAsync(string filePath) { try { var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read, FileBufferSize, false); var archive = new FileArchive(stream, false); if (!await archive.LoadHeader().ConfigureAwait(false)) { Trace.WriteLine($"Failed to validate archive header for {filePath}"); return null; } return archive; } catch (Exception ex) { Trace.WriteLine($"Failed to load archive {filePath}: {ex.Message}"); return null; } } public static async Task LoadOrCreateAsync(string filePath, CompressionLevel compressionLevel = CompressionLevel.Fastest) { return await CreateAsyncImpl(filePath, compressionLevel, false, true).ConfigureAwait(false); } public static async Task CreateAsync(string filePath, CompressionLevel compressionLevel = CompressionLevel.Fastest, bool overwriteExisting = true) { return await CreateAsyncImpl(filePath, compressionLevel, overwriteExisting, false).ConfigureAwait(false); } private static async Task CreateAsyncImpl(string filePath, CompressionLevel compressionLevel = CompressionLevel.Fastest, bool overwriteExisting = true, bool loadExisting = false) { try { Debug.Assert(!(overwriteExisting && loadExisting)); if (File.Exists(filePath)) { if (overwriteExisting) { File.Delete(filePath); } else if (loadExisting) { return await LoadAsync(filePath).ConfigureAwait(false); } else { return null; } } var stream = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileBufferSize, false); var archive = new FileArchive(stream, true, compressionLevel); return archive; } catch (Exception ex) { Trace.WriteLine($"Failed to create archive {filePath}: {ex.Message}"); return null; } } public async Task SaveAsync() { await SaveHeader().ConfigureAwait(false); Close(); return true; } private void Close() { archive_?.Dispose(); archive_ = null; archiveStream_ = null; modified_ = false; } public async Task AddFileAsync(string sourceFilePath, int fileKind = 0, string optionalDirectory = null, bool keepExisting = false) { try { await using var sourceStream = File.OpenRead(sourceFilePath); string archiveFilePath = Path.GetFileName(sourceFilePath); if (!string.IsNullOrEmpty(optionalDirectory)) { archiveFilePath = Path.Combine(optionalDirectory, archiveFilePath); } return await AddFileStreamAsync(sourceStream, archiveFilePath, fileKind, keepExisting).ConfigureAwait(false); } catch (Exception ex) { Trace.WriteLine($"Failed to add file {sourceFilePath}: {ex.Message}"); return false; } } public async Task AddFilesAsync(IEnumerable sourceFilePaths, int fileKind = 0, string optionalDirectory = null, bool keepExisting = false) { try { var files = sourceFilePaths.ToList(); int index = 0; OnFileAdded?.Invoke(0, files.Count); foreach (string filePath in files) { await using var sourceStream = File.OpenRead(filePath); string archiveFilePath = Path.GetFileName(filePath); if (!string.IsNullOrEmpty(optionalDirectory)) { archiveFilePath = Path.Combine(optionalDirectory, archiveFilePath); } if (!await AddFileStreamAsync(sourceStream, archiveFilePath, fileKind, keepExisting).ConfigureAwait(false)) { return false; } OnFileAdded?.Invoke(++index, files.Count); } return true; } catch (Exception ex) { Trace.WriteLine($"Failed to add file collection: {ex.Message}"); return false; } } public async Task AddDirectoryAsync(string directoryPath, bool includeSubdirs = false, int fileKind = 0, string searchPattern = "*", string optionalDirectory = null, bool keepExisting = false) { try { var searchOption = includeSubdirs ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; var files = Directory.EnumerateFiles(directoryPath, searchPattern, searchOption).ToList(); int index = 0; OnFileAdded?.Invoke(0, files.Count); foreach (string file in files) { // If file is in a directoryPath subdir, create the corresponding // subdir in the archive too, combined with the subdir force by client. string subdirPath = Path.GetRelativePath(directoryPath, file); subdirPath = Path.GetDirectoryName(subdirPath); if (!string.IsNullOrEmpty(optionalDirectory)) { subdirPath = Path.Combine(optionalDirectory, subdirPath); } if (!await AddFileAsync(file, fileKind, subdirPath, keepExisting).ConfigureAwait(false)) { return false; } OnFileAdded?.Invoke(++index, files.Count); } return true; } catch (Exception ex) { Trace.WriteLine($"Failed to add file collection: {ex.Message}"); return false; } } public async Task AddFileStreamAsync(Stream sourceStream, string archiveFilePath, int fileKind = 0, bool keepExisting = false) { try { var existingEntry = header_.FindFile(archiveFilePath); if (existingEntry != null) { if (keepExisting) { return true; } await RemoveFile(archiveFilePath).ConfigureAwait(false); } var newEntry = archive_.CreateEntry(archiveFilePath, compressionLevel_); await using var entryStream = newEntry.Open(); await sourceStream.CopyToAsync(entryStream).ConfigureAwait(false); if (archiveFilePath != HeaderFilePath) { header_.AddFile(archiveFilePath, fileKind, sourceStream.Length); } modified_ = true; return true; } catch (Exception ex) { Trace.WriteLine($"Failed to add file {archiveFilePath}: {ex.Message}"); return false; } } public async Task RemoveFile(string archiveFilePath) { var entry = archive_.GetEntry(archiveFilePath); if (entry != null) { header_.RemoveFile(archiveFilePath); entry.Delete(); modified_ = true; return true; } return false; } public async Task ExtractFilesToDirectoryAsync(IEnumerable files, string directoryPath, bool preserveArchiveDirs = true, bool overwriteExisting = true) { int index = 0; OnFileExtracted?.Invoke(0, Files.Count); foreach (string file in files) { if (!await ExtractFileToDirectoryAsync(file, directoryPath, preserveArchiveDirs, overwriteExisting).ConfigureAwait(false)) { return false; } OnFileExtracted?.Invoke(++index, Files.Count); } return true; } public async Task ExtractFilesToDirectoryAsync(IEnumerable files, string directoryPath, bool preserveArchiveDirs = true, bool overwriteExisting = true) { int index = 0; OnFileExtracted?.Invoke(0, Files.Count); foreach (var file in files) { if (!await ExtractFileToDirectoryAsync(file, directoryPath, preserveArchiveDirs, overwriteExisting).ConfigureAwait(false)) { return false; } OnFileExtracted?.Invoke(++index, Files.Count); } return true; } public async Task ExtractAllFilesOfKindToDirectoryAsync(int kind, string directoryPath, string optionalArchiveDirectory = null, bool preserveArchiveDirs = true, bool overwriteExisting = true) { var files = !string.IsNullOrEmpty(optionalArchiveDirectory) ? FindFilesInDirectory(optionalArchiveDirectory, kind) : FindFilesOfKind(kind); int index = 0; OnFileExtracted?.Invoke(0, Files.Count); foreach (var file in files) { if (!await ExtractFileToDirectoryAsync(file, directoryPath, preserveArchiveDirs, overwriteExisting).ConfigureAwait(false)) { return false; } OnFileExtracted?.Invoke(++index, Files.Count); } return true; } public async Task ExtractFileToDirectoryAsync(FileEntry file, string directoryPath, bool preserveArchiveDirs = true, bool overwriteExisting = true) { return await ExtractFileToDirectoryAsync(file.ArchivePath, directoryPath, preserveArchiveDirs, overwriteExisting).ConfigureAwait(false); } public async Task ExtractFileToDirectoryAsync(string archiveFilePath, string directoryPath, bool preserveArchiveDirs = true, bool overwriteExisting = true) { try { string outFilePath = preserveArchiveDirs ? Path.Combine(directoryPath, archiveFilePath) : Path.Combine(directoryPath, Path.GetFileName(archiveFilePath)); string outFileDir = Path.GetDirectoryName(outFilePath); if (!string.IsNullOrEmpty(outFileDir) && !Directory.Exists(outFileDir)) { Directory.CreateDirectory(outFileDir); } return await ExtractFileAsync(archiveFilePath, outFilePath, overwriteExisting).ConfigureAwait(false); } catch (Exception ex) { Trace.WriteLine($"Failed to add file {archiveFilePath}: {ex.Message}"); return false; } } public async Task ExtractAllToDirectoryAsync(string directoryPath, bool preserveArchiveDirs = true, bool overwriteExisting = true) { int index = 0; OnFileExtracted?.Invoke(0, Files.Count); foreach (var file in Files) { if (!await ExtractFileToDirectoryAsync(file, directoryPath, preserveArchiveDirs, overwriteExisting).ConfigureAwait(false)) { return false; } OnFileExtracted?.Invoke(++index, Files.Count); } return true; } public static async Task ExtractAllToDirectoryAsync(string archivePath, string directoryPath, bool preserveArchiveDirs = true, bool overwriteExisting = true) { using var archive = await LoadAsync(archivePath).ConfigureAwait(false); if (archive == null) { return false; } return await archive.ExtractAllToDirectoryAsync(directoryPath, preserveArchiveDirs, overwriteExisting). ConfigureAwait(false); } public static async Task CreateFromFileAsync(string sourceFilePath, string archivePath, CompressionLevel compressionLevel = CompressionLevel.Fastest, int fileKind = 0, bool overwriteExisting = true) { using var archive = await CreateAsync(archivePath, compressionLevel, overwriteExisting).ConfigureAwait(false); if (archive == null || !await archive.AddFileAsync(sourceFilePath, fileKind, null, false).ConfigureAwait(false)) { return false; } return await archive.SaveAsync().ConfigureAwait(false); } public static async Task CreateFromFilesAsync(IEnumerable sourceFilePaths, string archivePath, CompressionLevel compressionLevel = CompressionLevel.Fastest, int fileKind = 0, bool overwriteExisting = true) { using var archive = await CreateAsync(archivePath, compressionLevel, overwriteExisting).ConfigureAwait(false); if (archive == null || !await archive.AddFilesAsync(sourceFilePaths, fileKind, null, false).ConfigureAwait(false)) { return false; } return await archive.SaveAsync().ConfigureAwait(false); } public static async Task CreateFromStreamAsync(Stream sourceStream, string sourceFilePath, string archivePath, CompressionLevel compressionLevel = CompressionLevel.Fastest, int fileKind = 0, bool overwriteExisting = true) { using var archive = await CreateAsync(archivePath, compressionLevel, overwriteExisting).ConfigureAwait(false); if (archive == null || !await archive.AddFileStreamAsync(sourceStream, sourceFilePath, fileKind, false).ConfigureAwait(false)) { return false; } return await archive.SaveAsync().ConfigureAwait(false); } public static async Task CreateFromDirectoryAsync(string directoryPath, string archivePath, CompressionLevel compressionLevel = CompressionLevel.Fastest, bool includeSubdirs = false, string searchPattern = "*", int fileKind = 0, bool overwriteExisting = true) { using var archive = await CreateAsync(archivePath, compressionLevel, overwriteExisting).ConfigureAwait(false); if (archive == null || !await archive.AddDirectoryAsync(directoryPath, includeSubdirs, fileKind, searchPattern, null, false). ConfigureAwait(false)) { return false; } return await archive.SaveAsync().ConfigureAwait(false); } public async Task ExtractFileAsync(FileEntry file, string outFilePath, bool overwriteExisting = true) { return await ExtractFileAsync(file.ArchivePath, outFilePath, overwriteExisting).ConfigureAwait(false); } public async Task ExtractFileAsync(string archiveFilePath, string outFilePath, bool overwriteExisting = true) { try { if (File.Exists(outFilePath)) { if (overwriteExisting) { File.Delete(outFilePath); } else { return false; } } await using var stream = new FileStream(outFilePath, FileMode.CreateNew, FileAccess.Write, FileShare.None, FileBufferSize, false); return await ExtractFileAsync(archiveFilePath, stream).ConfigureAwait(false); } catch (Exception ex) { Trace.WriteLine($"Failed to extract file {archiveFilePath} to {outFilePath}: {ex.Message}"); return false; } } public async Task ExtractFileAsync(FileEntry file, Stream outStream) { return await ExtractFileAsync(file.ArchivePath, outStream).ConfigureAwait(false); } public async Task ExtractFileAsync(string archiveFilePath, Stream outStream) { try { var entry = archive_.GetEntry(archiveFilePath); if (entry == null) { Trace.WriteLine($"File not found in archive: {archiveFilePath}"); return false; } await using var entryStream = entry.Open(); await entryStream.CopyToAsync(outStream).ConfigureAwait(false); outStream.Position = 0; return true; } catch (Exception ex) { Trace.WriteLine($"Failed to extract file {archiveFilePath}: {ex.Message}"); return false; } } public async Task ExtractFileToMemoryAsync(string archiveFilePath) { var outStream = new MemoryStream(); if (await ExtractFileAsync(archiveFilePath, outStream)) { return outStream; } else { outStream.Dispose(); return null; } } public async Task ExtractFileToMemoryAsync(FileEntry file) { return await ExtractFileToMemoryAsync(file.ArchivePath); } public FileEntry FindFile(string archiveFilePath) { try { var fileEntry = header_.FindFile(archiveFilePath); if (fileEntry != null && archive_.GetEntry(archiveFilePath) == null) { throw new InvalidDataException($"File missing for archive: {archiveFilePath}"); } return fileEntry; } catch (Exception ex) { Trace.WriteLine($"Failed to find file {archiveFilePath}: {ex.Message}"); return null; } } public bool HasFile(string archiveFilePath) { return FindFile(archiveFilePath) != null; } private void CreateHeader() { header_ = new Header() { Signature = FileSignature, Version = FileFormatVersion, Files = new List() }; } private async Task SaveHeader() { await using var stream = new MemoryStream(); var options = new JsonSerializerOptions(); options.IgnoreReadOnlyFields = true; options.IgnoreReadOnlyProperties = true; options.WriteIndented = true; await JsonSerializer.SerializeAsync
(stream, header_, options).ConfigureAwait(false); stream.Position = 0; return await AddFileStreamAsync(stream, HeaderFilePath).ConfigureAwait(false); } private async Task LoadHeader() { using var stream = new MemoryStream(); if (!await ExtractFileAsync(HeaderFilePath, stream).ConfigureAwait(false)) { // When opening a plain ZIP file, accept it by // populating the header with the existing files. stream.Position = 0; return CreateHeaderFromArchive(); } stream.Position = 0; header_ = await JsonSerializer.DeserializeAsync
(stream).ConfigureAwait(false); return ValidateHeader(header_); } private bool CreateHeaderFromArchive() { try { CreateHeader(); foreach (var entry in archive_.Entries) { header_.AddFile(entry.FullName, 0, entry.Length); } return true; } catch (Exception ex) { Trace.WriteLine($"Failed to create header from archive contents"); return false; } } private bool ValidateHeader(Header header) { return header.Signature == FileSignature && header.Version is >= MinFileFormatVersion and <= FileFormatVersion; } private void Dispose(bool disposing) { if (!disposed_) { if (disposing) { if (modified_) { // Force saving the header if SaveAsync was not used. SaveAsync().ConfigureAwait(false).GetAwaiter().GetResult(); } Close(); } disposed_ = true; } } private struct Header { public Guid Signature { get; init; } public int Version { get; init; } public List Files { get; init; } public object OptionalData { get; set; } public void AddFile(string path, int kind, long size) { Files.Add(new FileEntry(path, kind, size)); } public FileEntry FindFile(string path) { return Files.Find(entry => entry.Name.Equals(path, StringComparison.Ordinal)); } internal void RemoveFile(string path) { Files.RemoveAll(entry => entry.Name.Equals(path, StringComparison.Ordinal)); } public T GetOptionalData() { if (OptionalData is JsonElement json) { return json.Deserialize(); } return (T)OptionalData; } } public class FileEntry { public FileEntry(string archivePath, int kind, long size) { ArchivePath = archivePath; Kind = kind; Size = size; } public string ArchivePath { get; set; } // Path in archive, can have subdirs. public long Size { get; set; } // Uncompressed size. public int Kind { get; set; } // Optional kind set by client. public string Name => Path.GetFileName(ArchivePath); public string Extension => Path.GetExtension(ArchivePath); public string Directory => Path.GetDirectoryName(ArchivePath); public bool HasDirectory => !string.IsNullOrEmpty(Directory); } } ================================================ FILE: src/ProfileExplorerCore/Graph/CallGraphPrinter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Graph; public class CallGraphPrinterOptions { public bool UseExternalNode { get; set; } public bool UseStraightLines { get; set; } public bool UseSingleIncomingEdge { get; set; } public bool TruncateLongNames { get; set; } public int NameLengthLimit { get; set; } public double VerticalDistanceFactor { get; set; } } public sealed class CallGraphPrinter : GraphVizPrinter { private const int ExternalNodeId = -1; private const int LargeGraphThresholdMin = 500; private const string StraightLinesSettings = @" splines = ortho; concentrate = true; "; private const string LargeGraphSettings = @" splines = ortho; concentrate = true; maxiter=4; mclimit=2; nslimit=2; "; private CallGraphPrinterOptions options_; private CallGraph callGraph_; private Dictionary nodeNameMap_; private HashSet incomingEdgeNodes_; public CallGraphPrinter(CallGraph callGraph, CallGraphPrinterOptions options) { callGraph_ = callGraph; options_ = options; nodeNameMap_ = new Dictionary(); if (options_.UseSingleIncomingEdge) { incomingEdgeNodes_ = new HashSet(); } } public override Dictionary CreateNodeDataMap() { if (nodeNameMap_.Count > 0) { return nodeNameMap_; } var map = new Dictionary(); foreach (var node in callGraph_.FunctionNodes) { map[GetNodeName((ulong)node.Number)] = node; } return map; } public override Dictionary> CreateNodeDataGroupsMap() { return null; } protected override string GetExtraSettings() { string text = ""; if (options_.UseStraightLines) { text = StraightLinesSettings; } // Increase the vertical distance between nodes the more there are // to make the graph somewhat easier to read. int nodeCount = callGraph_.FunctionNodes.Count; // double verticalDistance = Math.Clamp(0.3 * Math.Log(nodeCount), 0.3, 1); double verticalDistance = 1; text = $"{text}\nranksep ={verticalDistance};\n"; int edgeCount = EstimateEdgeCount(); int elements = Math.Max(edgeCount, nodeCount); return elements > LargeGraphThresholdMin ? $"{text}{LargeGraphSettings}" : text; } protected override void PrintGraph(StringBuilder builder) { if (options_.UseExternalNode) { CreateNode(ExternalNodeId, "EXTERNAL", builder); } foreach (var node in callGraph_.FunctionNodes) { CreateNode(node, builder); } foreach (var node in callGraph_.FunctionNodes) { foreach (var calleeNode in node.UniqueCallees) { CreateEdge(node, calleeNode, builder); } if (options_.UseExternalNode && !node.HasCallers) { CreateEdge(ExternalNodeId, node.Number, builder); } } } private int EstimateEdgeCount() { int total = 0; foreach (var node in callGraph_.FunctionNodes) { total += node.HasCallees ? node.Callees.Count : 0; } return total; } private void CreateNode(CallGraphNode node, StringBuilder builder) { //? TODO: Control through options double verticalMargin = 0.1; string label = node.FunctionName; if (label.Length > 25) { label = $"{label.Substring(0, 22)}..."; } // Increase node weight so that text fits completely. double horizontalMargin = Math.Min(Math.Max(0.1, label.Length * 0.04), 1.0); string nodeName = CreateNodeWithMargins(node.Number, label, builder, horizontalMargin, verticalMargin); nodeNameMap_[nodeName] = node; } private void CreateEdge(CallGraphNode node1, CallGraphNode node2, StringBuilder builder) { if (options_.UseSingleIncomingEdge) { if (!incomingEdgeNodes_.Add(node2)) { return; // Node already has an edge. } } CreateEdge(node1.Number, node2.Number, builder); } } ================================================ FILE: src/ProfileExplorerCore/Graph/DominatorTreePrinter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Text; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Graph; public sealed class DominatorTreePrinter : GraphVizPrinter { private FunctionIR function_; private DominatorAlgorithmOptions options_; private Dictionary blockNameMap_; public DominatorTreePrinter(FunctionIR function, DominatorAlgorithmOptions options) { function_ = function; options_ = options; blockNameMap_ = new Dictionary(); } public override Dictionary CreateNodeDataMap() { if (blockNameMap_.Count > 0) { return blockNameMap_; } var map = new Dictionary(); foreach (var block in function_.Blocks) { map[GetNodeName(block.Id)] = block; } return map; } public override Dictionary> CreateNodeDataGroupsMap() { return null; } protected override void PrintGraph(StringBuilder builder) { var cache = FunctionAnalysisCache.Get(function_); var dominatorAlgo = options_.HasFlag(DominatorAlgorithmOptions.Dominators) ? cache.GetDominators() : cache.GetPostDominators(); if (dominatorAlgo.DomTreeRootNode == null) { Trace.TraceWarning($"Invalid DomTree {ObjectTracker.Track(dominatorAlgo)}"); return; // Invalid CFG. } PrintDomTree(dominatorAlgo.DomTreeRootNode, builder); } private void CreateNode(BlockIR block, StringBuilder builder) { string blockName = CreateNode(block.Id, block.Number.ToString(), builder, "B"); blockNameMap_[blockName] = block; } private void CreateEdge(BlockIR block1, BlockIR block2, StringBuilder builder) { CreateEdge(block1.Id, block2.Id, builder); } private void PrintDomTree(DominatorTreeNode node, StringBuilder builder) { CreateNode(node.Block, builder); foreach (var child in node.Children) { PrintDomTree(child, builder); CreateEdge(node.Block, child.Block, builder); } } } ================================================ FILE: src/ProfileExplorerCore/Graph/ExpressionGraphPrinter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Globalization; using System.Text; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.Core.Graph; public class ExpressionGraphPrinterOptions { public bool PrintVariableNames { get; set; } public bool PrintSSANumbers { get; set; } public bool GroupInstructions { get; set; } public bool PrintBottomUp { get; set; } public bool SkipCopyInstructions { get; set; } public int MaxExpressionDepth { get; set; } public ICompilerIRInfo IR { get; set; } } public sealed class ExpressionGraphPrinter : GraphVizPrinter { private StringBuilder builder_; private List> edges_; private List> nodes_; private ExpressionGraphPrinterOptions options_; private IRElement rootElement_; private IRElement startElement_; private Dictionary visitedElements_; private Dictionary elementNameMap_; private Dictionary> blockNodeGroupsMap_; public ExpressionGraphPrinter(IRElement startElement, ExpressionGraphPrinterOptions options) { startElement_ = startElement; options_ = options; visitedElements_ = new Dictionary(); nodes_ = new List>(); edges_ = new List>(); elementNameMap_ = new Dictionary(); blockNodeGroupsMap_ = new Dictionary>(); } public override Dictionary CreateNodeDataMap() { return elementNameMap_; } public override Dictionary> CreateNodeDataGroupsMap() { return blockNodeGroupsMap_; } protected override void PrintGraph(StringBuilder builder) { builder_ = builder; var refFinder = new ReferenceFinder(startElement_.ParentFunction); var exprNode = PrintExpression(startElement_, null, 0, refFinder); rootElement_ = CreateFakeIRElement(); CreateNode(rootElement_, null, "ROOT"); CreateEdge(rootElement_, exprNode); if (options_.GroupInstructions) { PrintGroupedNodes(); } else { PrintNodes(); } PrintEdges(); } private void CreateNode(IRElement element, IRElement parent, string label) { nodes_.Add(new Tuple(element, parent, label)); } private void CreateEdge(IRElement element1, IRElement element2) { edges_.Add(new Tuple(element1, element2)); } private TupleIR CreateFakeIRElement() { return new TupleIR(IRElementId.FromLong(1), TupleKind.Other, startElement_.ParentBlock); } private void PrintGroupedNodes() { var blockGroups = new Dictionary>>(); var noGroupNodes = new List>(); foreach (var node in nodes_) { switch (node.Item1) { case TupleIR tuple: AddNodeToGroup(node, tuple, blockGroups); AddElementToGroupMap(node.Item1, tuple); break; case OperandIR _ when node.Item2 is TupleIR parentTuple: AddNodeToGroup(node, parentTuple, blockGroups); AddElementToGroupMap(node.Item1, parentTuple); break; default: noGroupNodes.Add(node); break; } } foreach (var (_, tuples) in blockGroups) { int margin = Math.Min(10 * (tuples.Count + 1), 50); StartSubgraph(margin, builder_); foreach ((var irElement, _, string label) in tuples) { PrintNode(irElement, label); } EndSubgraph(builder_); } foreach ((var irElement, _, string label) in noGroupNodes) { PrintNode(irElement, label); } } private void PrintNodes() { foreach ((var element, _, string label) in nodes_) { PrintNode(element, label); } } private void AddNodeToGroup(Tuple node, TupleIR tuple, Dictionary>> blockGroups) { var block = tuple.ParentBlock; if (!blockGroups.TryGetValue(block, out var group)) { group = new List>(); blockGroups.Add(block, group); } group.Add(node); } private void AddElementToGroupMap(IRElement element, TupleIR tuple) { var block = tuple.ParentBlock; if (!blockNodeGroupsMap_.TryGetValue(block, out var group)) { group = new List(); blockNodeGroupsMap_.Add(block, group); } group.Add(element); } private void PrintNode(IRElement element, string label) { // Numbers picked by trial and error for graph to look good... double verticalMargin = 0.055; double horizontalMargin = Math.Min(Math.Max(0.1, label.Length * 0.03), 1.0); string elementName = CreateNodeWithMargins(element.Id, label, builder_, horizontalMargin, verticalMargin); elementNameMap_[elementName] = element; } private void PrintEdges() { foreach (var (element1, element2) in edges_) { CreateEdge(element1.Id, element2.Id, builder_); } } private IRElement SkipAllCopies(IRElement op) { var defInstr = op.ParentInstruction; while (defInstr != null) { var sourceOp = options_.IR.SkipCopyInstruction(defInstr); if (sourceOp != null) { op = sourceOp; defInstr = sourceOp.ParentInstruction; } else { break; } } return op; } private IRElement PrintExpression(IRElement element, IRElement parent, int level, ReferenceFinder refFinder) { if (visitedElements_.TryGetValue(element, out var mappedElement)) { return mappedElement; } if (options_.SkipCopyInstructions) { element = SkipAllCopies(element); } switch (element) { case OperandIR op: { var defElement = refFinder.FindSingleDefinition(op); if (defElement != null) { if (defElement is OperandIR defOp) { if (defOp.Role == OperandRole.Parameter) { string label = GetOperandLabel(defOp); CreateNode(defOp, parent, label); visitedElements_[element] = defOp; return defOp; } } var result = PrintExpression(defElement.ParentTuple, op, level, refFinder); visitedElements_[element] = result; return result; } if (op.IsIntConstant) { CreateNode(op, parent, op.IntValue.ToString(CultureInfo.InvariantCulture)); } else if (op.IsFloatConstant) { CreateNode(op, parent, op.FloatValue.ToString(CultureInfo.InvariantCulture)); } else { string label = GetOperandLabel(op); CreateNode(op, parent, label); } visitedElements_[element] = op; return op; } case InstructionIR instr: { string label = GetInstructionLabel(instr); CreateNode(instr, parent, label); visitedElements_[element] = instr; if (level >= options_.MaxExpressionDepth) { return instr; } foreach (var sourceOp in instr.Sources) { var result = PrintExpression(sourceOp, instr, level + 1, refFinder); ConnectChildNode(instr, result); } foreach (var destOp in instr.Destinations) { if (destOp.IsIndirection) { var result = PrintExpression(destOp, instr, level + 1, refFinder); ConnectChildNode(instr, result); } } return instr; } default: // Use the element text. CreateNode(element, parent, ""); break; } visitedElements_[element] = element; return element; } private void ConnectChildNode(InstructionIR instr, IRElement result) { if (result != null) { if (options_.PrintBottomUp) { CreateEdge(instr, result); } else { CreateEdge(result, instr); } } } private string GetOperandLabel(OperandIR op) { if (!op.HasName) { return ""; } string label = op.Name; if (options_.PrintSSANumbers) { int? ssaNumber = ReferenceFinder.GetSSADefinitionId(op); if (ssaNumber.HasValue) { return $"{label}<{ssaNumber.Value.ToString(CultureInfo.InvariantCulture)}>"; } } if (op.IsAddress || op.IsLabelAddress) { return $"&{label}"; } if (op.IsIndirection) { return $"[{label}]"; } return label; } private string GetInstructionLabel(InstructionIR instr) { string label = instr.OpcodeText.ToString(); if (instr.Destinations.Count > 0) { var destOp = instr.Destinations[0]; string variableName = ""; string ssaNumber = ""; if (destOp.HasName && options_.PrintVariableNames) { variableName = destOp.Name; } var ssaTag = destOp.GetTag(); if (ssaTag != null && options_.PrintSSANumbers) { ssaNumber = ssaTag.DefinitionId.ToString(CultureInfo.InvariantCulture); } if (!string.IsNullOrEmpty(variableName)) { return !string.IsNullOrEmpty(ssaNumber) ? $"{variableName}<{ssaNumber}> = {label}" : $"{variableName} = {label}"; } if (!string.IsNullOrEmpty(ssaNumber)) { return $"<{ssaNumber}> = {label}"; } } return label; } } ================================================ FILE: src/ProfileExplorerCore/Graph/FlowGraphPrinter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Graph; public sealed class FlowGraphPrinter : GraphVizPrinter { private const int LargeGraphThresholdMin = 500; private const int LargeGraphThresholdMax = 1000; private const string LargeGraphSettings = @" maxiter=8; "; private const string HugeGraphSettings = @" maxiter=4; mclimit=2; nslimit=2; "; private FunctionIR function_; private Dictionary blockNameMap_; private DominatorAlgorithm dominatorAlgo_; public FlowGraphPrinter(FunctionIR function) { function_ = function; blockNameMap_ = new Dictionary(); } public override Dictionary CreateNodeDataMap() { if (blockNameMap_.Count > 0) { return blockNameMap_; } var map = new Dictionary(); foreach (var block in function_.Blocks) { map[GetNodeName(block.Id)] = block; } return map; } public override Dictionary> CreateNodeDataGroupsMap() { return null; } protected override string GetExtraSettings() { int count = function_.Blocks.Count; if (count > LargeGraphThresholdMin) { return count < LargeGraphThresholdMax ? LargeGraphSettings : HugeGraphSettings; } return ""; } protected override void PrintGraph(StringBuilder builder) { foreach (var block in function_.Blocks) { CreateNode(block, builder); } // Compute the dominator tree, used to mark loop back-edges and immediate dominators. var cache = FunctionAnalysisCache.Get(function_); dominatorAlgo_ = cache.GetDominators(); if (!dominatorAlgo_.IsValid) { dominatorAlgo_ = null; } foreach (var block in function_.Blocks) { foreach (var successorBlock in block.Successors) { CreateEdge(block, successorBlock, builder); } } string domEdges = PrintDominatorEdges(DominatorAlgorithmOptions.Dominators); builder.AppendLine(domEdges); } private void CreateNode(BlockIR block, StringBuilder builder) { string blockName = CreateNode(block.Id, block.Number.ToString(), builder, "B"); blockNameMap_[blockName] = block; } private void CreateEdge(BlockIR block1, BlockIR block2, StringBuilder builder) { // A loop back-edge is an edge from a block to a block with a lower number, // with the lower number block dominating the other block. if (block2.Number <= block1.Number) { bool accept = true; if (dominatorAlgo_ != null) { // Use dominator tree for the complete check, otherwise // mark edge only using the block numbers, which is not always correct. accept = dominatorAlgo_.Dominates(block1, block2); } if (accept) { CreateEdgeWithStyle(block1.Id, block2.Id, "dashed", builder); return; } } CreateEdge(block1.Id, block2.Id, builder); } private void CreateEdgeWithStyle(BlockIR block1, BlockIR block2, StringBuilder builder) { CreateEdgeWithStyle(block1.Id, block2.Id, "dotted", builder); } private string PrintDominatorEdges(DominatorAlgorithmOptions options) { if (dominatorAlgo_ == null) { return ""; // Invalid CFG. } var builder = new StringBuilder(); foreach (var block in function_.Blocks) { // Ignore blocks with single predecessor, immediate dom. is obvious. if (block.Predecessors.Count <= 1) { continue; } var immDomBlock = dominatorAlgo_.GetImmediateDominator(block); if (immDomBlock != null) { CreateEdgeWithStyle(block, immDomBlock, builder); } } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/Graph/Graph.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Graph; public enum GraphKind { FlowGraph, DominatorTree, PostDominatorTree, ExpressionGraph, CallGraph } public sealed class Node { //? Commented properties are currently not used. public ReadOnlyMemory Name { get; set; } //public ReadOnlyMemory Label { get; set; } public string Label { get; set; } //public ReadOnlyMemory Style { get; set; } //public ReadOnlyMemory Shape { get; set; } //public ReadOnlyMemory BackgroundColor { get; set; } //public ReadOnlyMemory BorderColor { get; set; } public double CenterX { get; set; } public double CenterY { get; set; } public double Width { get; set; } public double Height { get; set; } public TaggedObject Data { get; set; } public bool DataIsElement => Data is IRElement; public IRElement ElementData => Data as IRElement; public List InEdges { get; set; } public List OutEdges { get; set; } public object Tag { get; set; } } public sealed class Edge { public enum EdgeKind { Default, Dotted, Dashed } public Node NodeFrom { get; set; } public Node NodeTo { get; set; } //public ReadOnlyMemory NodeNameFrom { get; set; } //public ReadOnlyMemory NodeNameTo { get; set; } //public ReadOnlyMemory Label { get; set; } public double LabelX { get; set; } public double LabelY { get; set; } public Tuple[] LinePoints { get; set; } public EdgeKind Style { get; set; } public ReadOnlyMemory Color { get; set; } public static EdgeKind GetEdgeStyle(ReadOnlyMemory style) { if (style.Span.Equals("dotted", StringComparison.Ordinal)) { return EdgeKind.Dotted; } if (style.Span.Equals("dashed", StringComparison.Ordinal)) { return EdgeKind.Dashed; } return EdgeKind.Default; } } public sealed class Graph { public Graph(GraphKind kind) { Kind = kind; Nodes = new List(); Edges = new List(); DataNodeMap = new Dictionary(); } public GraphKind Kind { get; set; } public object GraphOptions { get; set; } public List Nodes { get; set; } public List Edges { get; set; } public double Width { get; set; } public double Height { get; set; } public bool IsEmpty => Nodes.Count == 0; //? TODO: Move below out so it's easy to discard them and free memory for large graphs public Dictionary DataNodeMap { get; set; } public Dictionary> DataNodeGroupsMap { get; set; } } ================================================ FILE: src/ProfileExplorerCore/Graph/GraphPrinterFactory.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Graph; public static class GraphPrinterFactory { public static GraphVizPrinter CreateInstance( GraphKind kind, T element, U options) where T : class where U : class { if (typeof(T) == typeof(FunctionIR)) { return kind switch { GraphKind.FlowGraph => new FlowGraphPrinter(element as FunctionIR), GraphKind.DominatorTree => new DominatorTreePrinter(element as FunctionIR, DominatorAlgorithmOptions.Dominators), GraphKind.PostDominatorTree => new DominatorTreePrinter(element as FunctionIR, DominatorAlgorithmOptions.PostDominators), _ => throw new ArgumentOutOfRangeException(nameof(kind), kind, null) }; } if (typeof(T) == typeof(IRElement)) { switch (kind) { case GraphKind.ExpressionGraph: { return new ExpressionGraphPrinter(element as IRElement, options as ExpressionGraphPrinterOptions); } } } else if (typeof(T) == typeof(IRTextSummary)) { switch (kind) { case GraphKind.CallGraph: { return new CallGraphPrinter(element as CallGraph, options as CallGraphPrinterOptions); } } } throw new NotImplementedException("Unsupported graph type"); } } ================================================ FILE: src/ProfileExplorerCore/Graph/GraphvizPrinter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Text; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Graph; public class GraphVizPrinter { private int subgraphIndex_; private int nextInvisibleId_; public virtual Dictionary CreateNodeDataMap() { throw new NotImplementedException(); } public virtual Dictionary> CreateNodeDataGroupsMap() { throw new NotImplementedException(); } public string PrintGraph() { // With extremely large graphs, the application can run out of memory, // better show a error message than crashing it. try { var builder = new StringBuilder(1024 * 16); builder.AppendLine("digraph {"); builder.AppendLine(GetExtraSettings()); PrintGraph(builder); builder.AppendLine("}"); return builder.ToString(); } catch (Exception ex) { Trace.TraceError($"Failed to generate Graphviz input: {ex.Message}"); return null; } } public string CreateGraph(CancelableTask task) { return CreateGraph(PrintGraph(), task); } public string CreateGraph(string inputText, CancelableTask task) { Trace.TraceInformation($"Graphviz task {ObjectTracker.Track(task)}: Start"); string inputFilePath; try { inputFilePath = Path.GetTempFileName(); File.WriteAllText(inputFilePath, inputText); } catch (Exception ex) { Trace.TraceError($"Graphviz task {ObjectTracker.Track(task)}: Failed writing GraphViz input file: {ex}"); return null; } var outputText = new StringBuilder(1024 * 32); var psi = new ProcessStartInfo("dot.exe") { Arguments = $"-Tplain \"{inputFilePath}\"", UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = false, RedirectStandardOutput = true }; try { using var process = new Process {StartInfo = psi, EnableRaisingEvents = true}; process.OutputDataReceived += (sender, e) => { outputText.AppendLine(e.Data); }; process.Start(); process.BeginOutputReadLine(); do { process.WaitForExit(100); if (task.IsCanceled) { Trace.TraceWarning($"Graphviz task {ObjectTracker.Track(task)}: Canceled"); process.CancelOutputRead(); process.Kill(); return null; } } while (!process.HasExited); process.CancelOutputRead(); if (process.ExitCode != 0) { // dot failed somehow, treat it as an error. Trace.TraceError( $"Graphviz task {ObjectTracker.Track(task)}: GraphViz failed with error code: {process.ExitCode}"); return null; } } catch (Exception ex) { Trace.TraceError($"Graphviz task {ObjectTracker.Track(task)}: Failed running GraphViz: {ex}"); return null; } #if !DEBUG // Clean up temporary files. try { File.Delete(inputFilePath); } catch (Exception) { } #endif Trace.TraceInformation($"Graphviz task {ObjectTracker.Track(task)}: Completed"); return outputText.ToString(); } protected virtual void PrintGraph(StringBuilder builder) { } protected virtual string GetExtraSettings() { return ""; } protected string CreateNode(int id, string label, StringBuilder builder, string labelPrefix = null) { return CreateNode((ulong)id, label, builder, labelPrefix); } protected string CreateNode(ulong id, string label, StringBuilder builder, string labelPrefix = null) { string nodeName = $"n{id}"; if (!string.IsNullOrEmpty(labelPrefix)) { builder.AppendFormat(CultureInfo.InvariantCulture, "{0}[shape=rectangle, label=\"{1}{2}\"];\n", nodeName, labelPrefix, label); } else { builder.AppendFormat(CultureInfo.InvariantCulture, "{0}[shape=rectangle, label=\"{1}\"];\n", nodeName, label); } return nodeName; } protected string CreateNodeWithMargins(int id, string label, StringBuilder builder, double horizontalMargin, double verticalMargin, string labelPrefix = null) { return CreateNodeWithMargins((ulong)id, label, builder, horizontalMargin, verticalMargin, labelPrefix); } protected string CreateNodeWithMargins(ulong id, string label, StringBuilder builder, double horizontalMargin, double verticalMargin, string labelPrefix = null) { string nodeName = $"n{id}"; if (!string.IsNullOrEmpty(labelPrefix)) { builder.AppendFormat(CultureInfo.InvariantCulture, "{0}[shape=rectangle, margin=\"{1},{2}\", label=\"{3}{4}\"];\n", nodeName, horizontalMargin, verticalMargin, labelPrefix, label); } else { builder.AppendFormat(CultureInfo.InvariantCulture, "{0}[shape=rectangle, margin=\"{1},{2}\", label=\"{3}\"];\n", nodeName, horizontalMargin, verticalMargin, label); } return nodeName; } protected string CreateInvisibleNode(StringBuilder builder) { string nodeName = $"inv{nextInvisibleId_++}"; builder.AppendFormat(CultureInfo.InvariantCulture, $"{nodeName}[shape=point,width=0,height=0];\n"); return nodeName; } protected string GetNodeName(ulong id) { return $"n{id}"; } protected string GetNodeName(int id) { return $"n{id}"; } protected void CreateEdge(string id1, string id2, StringBuilder builder) { builder.AppendFormat(CultureInfo.InvariantCulture, "{0} -> {1};\n", id1, id2); } protected void CreateEdge(ulong id1, string id2, StringBuilder builder) { builder.AppendFormat(CultureInfo.InvariantCulture, "n{0} -> {1};\n", id1, id2); } protected void CreateEdge(int id1, int id2, StringBuilder builder) { CreateEdge((ulong)id1, (ulong)id2, builder); } protected void CreateEdge(ulong id1, ulong id2, StringBuilder builder) { builder.AppendFormat(CultureInfo.InvariantCulture, "n{0} -> n{1};\n", id1, id2); } protected void CreateEdge(ulong id1, ulong id2, string attribute, StringBuilder builder) { builder.AppendFormat(CultureInfo.InvariantCulture, "n{0} -> n{1} {2};\n", id1, id2, attribute); } protected void CreateEdgeWithStyle(int id1, int id2, string style, StringBuilder builder) { CreateEdgeWithStyle((ulong)id1, (ulong)id2, style, builder); } protected void CreateEdgeWithStyle(ulong id1, ulong id2, string style, StringBuilder builder) { builder.AppendFormat(CultureInfo.InvariantCulture, "n{0} -> n{1}[style={2}];\n", id1, id2, style); } protected void StartSubgraph(int margin, StringBuilder builder) { builder.AppendLine($"subgraph cluster_{subgraphIndex_} {{"); builder.AppendLine($"margin={margin};"); subgraphIndex_++; } protected void EndSubgraph(StringBuilder builder) { builder.AppendLine("}"); } } ================================================ FILE: src/ProfileExplorerCore/Graph/GraphvizReader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Runtime.CompilerServices; using ProfileExplorer.Core.Collections; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Lexer; namespace ProfileExplorer.Core.Graph; public sealed class GraphvizReader { private static readonly Dictionary keywordMap_ = new() { {"graph", Keyword.Graph}, {"node", Keyword.Node}, {"edge", Keyword.Edge}, {"stop", Keyword.Stop} }; private static readonly StringTrie keywordTrie_ = new(keywordMap_); private readonly Dictionary nodeMap_; private readonly Dictionary dataNameMap_; private Token current_; private Graph graph_; private GraphKind graphKind_; private Lexer.Lexer lexer_; public GraphvizReader(GraphKind kind, string text, Dictionary dataNameMap) { graphKind_ = kind; dataNameMap_ = dataNameMap; nodeMap_ = new Dictionary(); lexer_ = new Lexer.Lexer(); lexer_.Initialize(text); current_ = lexer_.NextToken(); } public Graph ReadGraph() { graph_ = new Graph(graphKind_); if (!ExpectAndSkipKeyword(Keyword.Graph)) { return null; } SkipToken(); // Ignored. if (!ReadFloatNumber(out double width) || !ReadFloatNumber(out double height)) { return null; } graph_.Width = width; graph_.Height = height; while (!IsEOF()) { SkipToLineStart(); while (ExpectAndSkipKeyword(Keyword.Node)) { var node = ReadNode(); if (node != null) { graph_.Nodes.Add(node); } SkipToLineStart(); } while (ExpectAndSkipKeyword(Keyword.Edge)) { var edge = ReadEdge(); if (edge != null) { graph_.Edges.Add(edge); } SkipToLineStart(); } if (ExpectAndSkipKeyword(Keyword.Stop)) { break; } } return graph_; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool IsToken(TokenKind kind) { return current_.Kind == kind; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private Keyword TokenKeyword() { if (current_.IsIdentifier() && keywordTrie_.TryGetValue(TokenData(), out var keyword)) { return keyword; } return Keyword.None; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private ReadOnlySpan TokenStringData() { return current_.Data.Span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private ReadOnlyMemory TokenData() { return current_.Data; } private bool ReadTokenIntNumber(out int value) { bool result = int.TryParse(TokenStringData(), NumberStyles.Any, CultureInfo.InvariantCulture, out value); if (result) { SkipToken(); } return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool ReadFloatNumber(out double value) { bool isNegated = false; if (IsToken(TokenKind.Minus)) { SkipToken(); isNegated = true; } bool result = double.TryParse(TokenStringData(), NumberStyles.Any, CultureInfo.InvariantCulture, out value); if (result) { SkipToken(); } unchecked { value = isNegated ? -value : value; } return result; } private bool ReadString(out ReadOnlyMemory value) { if (current_.IsIdentifier() || current_.IsString()) { value = TokenData(); SkipToken(); return true; } value = default(ReadOnlyMemory); return false; } private bool ReadLabel(out ReadOnlyMemory value) { if (current_.IsIdentifier() || current_.IsString()) { value = TokenData(); SkipToken(); return true; } // The Graphviz output doesn't seem to quote integers, // which also include negative values. if (IsToken(TokenKind.Minus)) { SkipToken(); } if (current_.IsNumber()) { value = TokenData(); SkipToken(); return true; } value = default(ReadOnlyMemory); return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool ReadPoint(out double x, out double y) { if (ReadFloatNumber(out x) && ReadFloatNumber(out y)) { y = graph_.Height - y; return true; } x = y = 0; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool IsString() { return current_.IsIdentifier() || current_.IsString(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool NextTokenIs(TokenKind kind) { return lexer_.PeekToken().Kind == kind; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void SkipToken() { current_ = lexer_.NextToken(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool ExpectAndSkipKeyword(Keyword keyword) { if (TokenKeyword() == keyword) { SkipToken(); return true; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool IsEOF() { return current_.IsEOF(); } private void SkipToLineEnd() { while (!current_.IsLineEnd() && !current_.IsEOF()) { SkipToken(); } } private void SkipToLineStart() { SkipToLineEnd(); SkipToken(); } private Node ReadNode() { var node = new Node(); if (!ReadString(out var name) || !ReadPoint(out double x, out double y) || !ReadFloatNumber(out double width) || !ReadFloatNumber(out double height)) { Trace.TraceError("Failed to parse Graphviz output node"); return null; } node.Name = name; node.CenterX = x; node.CenterY = y; node.Width = width; node.Height = height; if (!ReadLabel(out var label) || !ReadString(out var style) || !ReadString(out var shape) || !ReadString(out var borderColor) || !ReadString(out var backgroundColor)) { Trace.TraceError("Failed to parse Graphviz output node properties"); return null; } node.Label = label.ToString(); nodeMap_[name.ToString()] = node; //? TODO: These commented-out values are currently not used anywhere. //node.Style = style; //node.Shape = shape; //node.BorderColor = borderColor; //node.BackgroundColor = backgroundColor; // Associate with IR objects. if (dataNameMap_.TryGetValue(name.ToString(), out var data)) { node.Data = data; graph_.DataNodeMap.Add(data, node); } else { Trace.TraceError($"Could not find Graphviz output block {name}"); } return node; } private Edge ReadEdge() { var edge = new Edge(); if (!ReadString(out var fromNode) || !ReadString(out var toNode) || !ReadTokenIntNumber(out int pointCont)) { return null; } //edge.NodeNameFrom = fromNode; //edge.NodeNameTo = toNode; edge.LinePoints = new Tuple[pointCont]; for (int i = 0; i < pointCont; i++) { if (!ReadPoint(out double x, out double y)) { return null; } edge.LinePoints[i] = new Tuple(x, y); } ReadOnlyMemory label = default; double labelX = 0; double labelY = 0; if (IsString() && NextTokenIs(TokenKind.Number)) { // Edge has a label. if (!ReadString(out label) || !ReadPoint(out labelX, out labelY)) { return null; } } if (!ReadString(out var style) || !ReadString(out var color)) { return null; } //edge.Label = label; edge.LabelX = labelX; edge.LabelY = labelY; edge.Style = Edge.GetEdgeStyle(style); edge.Color = color; // Associate with IR objects. if (dataNameMap_.TryGetValue(fromNode.ToString(), out var fromBlock)) { var node = graph_.DataNodeMap[fromBlock]; edge.NodeFrom = node; node.OutEdges ??= new List(); node.OutEdges.Add(edge); } else { if (nodeMap_.TryGetValue(fromNode.ToString(), out var node)) { edge.NodeFrom = node; node.OutEdges ??= new List(); node.OutEdges.Add(edge); } else { Debug.Assert(false, $"Could not find block {fromNode}"); Trace.TraceError($"Could not find Graphviz output block {fromNode}"); } } if (dataNameMap_.TryGetValue(toNode.ToString(), out var toBlock)) { var node = graph_.DataNodeMap[toBlock]; edge.NodeTo = node; node.InEdges ??= new List(); node.InEdges.Add(edge); } else { if (nodeMap_.TryGetValue(toNode.ToString(), out var node)) { edge.NodeTo = node; node.InEdges ??= new List(); node.InEdges.Add(edge); } else { Debug.Assert(false, $"Could not find block {fromNode}"); Trace.TraceError($"Could not find Graphviz output block {fromNode}"); } } return edge; } private enum Keyword { Graph, Node, Edge, Stop, None } } ================================================ FILE: src/ProfileExplorerCore/ICompilerIRInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; namespace ProfileExplorer.Core; public interface ICompilerIRInfo { IRMode Mode { get; set; } InstructionOffsetData InstructionOffsetData { get; } IRSectionReader CreateSectionReader(string filePath, bool expectSectionHeaders = true); IRSectionReader CreateSectionReader(byte[] textData, bool expectSectionHeaders = true); IRSectionParser CreateSectionParser(IRParsingErrorHandler errorHandler, long functionSize = 0); IRParsingErrorHandler CreateParsingErrorHandler(); IReachableReferenceFilter CreateReferenceFilter(FunctionIR function); bool IsCopyInstruction(InstructionIR instr); bool IsLoadInstruction(InstructionIR instr); bool IsStoreInstruction(InstructionIR instr); bool IsCallInstruction(InstructionIR instr); bool IsIntrinsicCallInstruction(InstructionIR instr); bool IsPhiInstruction(InstructionIR instr); bool IsNOP(InstructionIR instr); BlockIR GetIncomingPhiOperandBlock(InstructionIR phiInstr, int opIndex); IRElement SkipCopyInstruction(InstructionIR instr); OperandIR GetCallTarget(InstructionIR instr); OperandIR GetBranchTarget(InstructionIR instr); InstructionIR GetTransferInstruction(BlockIR block); bool OperandsReferenceSameSymbol(OperandIR opA, OperandIR opB, bool exactCheck); } public class InstructionOffsetData { public int OffsetAdjustIncrement { get; set; } public int MaxOffsetAdjust { get; set; } public int InitialMultiplier { get; set; } public static InstructionOffsetData ConstantSize(int size) { return new InstructionOffsetData { OffsetAdjustIncrement = size, MaxOffsetAdjust = size, InitialMultiplier = 1 }; } public static InstructionOffsetData VariableSize(int minSize, int maxSize) { return new InstructionOffsetData { OffsetAdjustIncrement = minSize, MaxOffsetAdjust = maxSize, InitialMultiplier = 1 }; } } ================================================ FILE: src/ProfileExplorerCore/IR/BlockIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Linq; using System.Text; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.IR; public sealed class BlockIR : IRElement { public BlockIR(IRElementId elementId, int number, FunctionIR parent) : base(elementId) { Number = number; Parent = parent; Tuples = new List(); Successors = new List(); Predecessors = new List(); } public int Number { get; set; } public int IndexInFunction { get; set; } public bool HasOddIndexInFunction => (IndexInFunction & 1) == 1; public bool HasEvenIndexInFunction => (IndexInFunction & 1) == 0; public List Tuples { get; } public List Successors { get; } public List Predecessors { get; } public BlockLabelIR Label { get; set; } public FunctionIR Parent { get; set; } public bool IsEmpty => Tuples == null || Tuples.Count == 0; public int TupleCount => Tuples.Count; public int InstructionCount => Instructions.Count(); public bool IsBranchBlock { get { var instr = TransferInstruction; return instr?.IsBranch ?? false; } } public bool IsSwitchBlock { get { var instr = TransferInstruction; return instr?.IsSwitch ?? false; } } public bool IsReturnBlock { get { var instr = TransferInstruction; if (instr != null) { return instr.IsReturn; } // Consider exit block to also be a return block. return Equals(Parent.ExitBlock); } } public bool HasLoopBackedge { get { return Predecessors.FindIndex(predBlock => predBlock.Number >= Number) != -1; } } public TupleIR FirstTuple => IsEmpty ? null : Tuples[0]; public TupleIR LastTuple => IsEmpty ? null : Tuples[^1]; public bool HasLabel => Label != null; public IEnumerable TuplesBack { get { for (int i = Tuples.Count - 1; i >= 0; i--) { yield return Tuples[i]; } } } public InstructionIR FirstInstruction { get { if (IsEmpty) { return null; } foreach (var t in Tuples) { if (t.IsInstruction) { return t as InstructionIR; } } return null; } } public InstructionIR LastInstruction { get { if (IsEmpty) { return null; } for (int i = Tuples.Count - 1; i >= 0; i--) { if (Tuples[i].IsInstruction) { return Tuples[i] as InstructionIR; } } return null; } } public IEnumerable Instructions { get { foreach (var tuple in Tuples) { if (tuple is InstructionIR instr) { yield return instr; } } } } public IEnumerable InstructionsBack { get { for (int i = Tuples.Count - 1; i >= 0; i--) { if (Tuples[i] is InstructionIR instr) { yield return instr; } } } } public InstructionIR TransferInstruction { get { var instr = LastInstruction; if (instr != null && (instr.IsBranch || instr.IsGoto || instr.IsSwitch || instr.IsReturn)) { return instr; } return null; } } public BlockIR BranchTargetBlock { get { var branchInstr = TransferInstruction; if (branchInstr != null && branchInstr.IsBranch) { foreach (var sourceOp in branchInstr.Sources) { if (sourceOp.IsLabelAddress) { var label = sourceOp.BlockLabelValue; return label.Parent; } } } return null; } } public void AddTuple(TupleIR tuple) { tuple.IndexInBlock = Tuples.Count; Tuples.Add(tuple); } public override void Accept(IRVisitor visitor) { visitor.Visit(this); } public override string ToString() { var result = new StringBuilder(); result.AppendLine($"block number: {Number}, id: {Id}"); if (Predecessors.Count > 0) { result.AppendLine("o preds: ".Indent(2)); foreach (var block in Predecessors) { result.Append($"{block.Number} "); } result.AppendLine(); } if (Successors.Count > 0) { result.AppendLine("o succs: ".Indent(2)); foreach (var block in Successors) { result.Append($"{block.Number} "); } result.AppendLine(); } result.AppendLine($"o tuples: {Tuples.Count}".Indent(2)); foreach (var tuple in Tuples) { result.AppendLine($"{tuple}".Indent(2)); } return result.ToString(); } public override bool Equals(object obj) { return obj is BlockIR iR && base.Equals(obj) && Number == iR.Number; } public override int GetHashCode() { return HashCode.Combine(base.GetHashCode(), Number); } } ================================================ FILE: src/ProfileExplorerCore/IR/BlockLabelIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; namespace ProfileExplorer.Core.IR; public sealed class BlockLabelIR : TupleIR { private ReadOnlyMemory label_; public BlockLabelIR(IRElementId elementId, ReadOnlyMemory name, BlockIR parent = null) : base(elementId, TupleKind.Label, parent) { label_ = name; } public override bool HasName => true; public override ReadOnlyMemory NameValue => label_; public override void Accept(IRVisitor visitor) { visitor.Visit(this); } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is BlockLabelIR other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(base.GetHashCode(), label_); } public override string ToString() { return $"label name: {Name}"; } private bool Equals(BlockLabelIR other) { return base.Equals(other) && label_.Equals(other.label_); } } ================================================ FILE: src/ProfileExplorerCore/IR/FunctionIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core.IR; public sealed class FunctionIR : IRElement { private Dictionary elementMap_; private int instructionCount_; private int tupleCount_; private string name_; public FunctionIR(string name = null) : base(IRElementId.NewFunctionId()) { ReturnType = TypeIR.GetUnknown(); Parameters = new List(); Blocks = new List(); name_ = name; } public FunctionIR(string name, TypeIR returnType) : this() { name_ = name; ReturnType = returnType; } public override bool HasName => !string.IsNullOrEmpty(Name); public override ReadOnlyMemory NameValue => name_.AsMemory(); public override string Name { get => name_; set => name_ = value; } public TypeIR ReturnType { get; set; } public List Parameters { get; } public List Blocks { get; } public List SortedBlocks { get; private set; } public BlockIR EntryBlock => Blocks.Count > 0 ? Blocks[0] : null; public BlockIR ExitBlock => Blocks.Count > 0 ? Blocks[^1] : null; public int BlockCount => Blocks.Count; public IEnumerable AllElements { get { foreach (var block in Blocks) { yield return block; foreach (var tuple in block.Tuples) { yield return tuple; if (!(tuple is InstructionIR instr)) { continue; } foreach (var op in instr.Destinations) { yield return op; } foreach (var op in instr.Sources) { yield return op; } } } } } public IEnumerable AllTuples { get { foreach (var block in Blocks) { foreach (var tuple in block.Tuples) { yield return tuple; } } } } public IEnumerable AllInstructions { get { foreach (var block in Blocks) { foreach (var tuple in block.Tuples) { if (tuple is InstructionIR instr) { yield return instr; } } } } } public int InstructionCount { get { if (instructionCount_ == 0) { ForEachInstruction(instr => { instructionCount_++; return true; }); } return instructionCount_; } set => instructionCount_ = value; } public int TupleCount { get { if (tupleCount_ == 0) { ForEachTuple(tuple => { tupleCount_++; return true; }); } return tupleCount_; } set => tupleCount_ = value; } public IRElement GetElementWithId(ulong id) { BuildElementIdMap(); return elementMap_.TryGetValue(id, out var value) ? value : null; } public void BuildElementIdMap() { if (elementMap_ != null) { return; } elementMap_ = new Dictionary(); foreach (var block in Blocks) { elementMap_[block.Id] = block; foreach (var tuple in block.Tuples) { elementMap_[tuple.Id] = tuple; if (!(tuple is InstructionIR instr)) { continue; } foreach (var op in instr.Destinations) { elementMap_[op.Id] = op; } foreach (var op in instr.Sources) { elementMap_[op.Id] = op; } } } } public void AssignBlockIndices(bool setBlockNumbers = false) { // Assign block index as they show up in the text, // not RDFO or how the blocks where forward-referenced. var blockList = new List(Blocks.Count); bool needsSorting = false; for (int i = 0; i < Blocks.Count; i++) { var block = Blocks[i]; blockList.Add(block); needsSorting = i > 1 && !needsSorting && blockList[^1].TextLocation >= block.TextLocation; } if (needsSorting) { blockList.Sort((a, b) => a.TextLocation.CompareTo(b.TextLocation)); } for (int i = 0; i < blockList.Count; i++) { blockList[i].IndexInFunction = i; if (setBlockNumbers) { blockList[i].Number = i; } } SortedBlocks = blockList; } public void ForEachElement(Func action) { foreach (var element in AllElements) { if (!action(element)) { return; } } } public void ForEachTuple(Func action) { foreach (var tuple in AllTuples) { if (!action(tuple)) { return; } } } public void ForEachInstruction(Func action) { foreach (var instr in AllInstructions) { if (!action(instr)) { return; } } } public override void Accept(IRVisitor visitor) { visitor.Visit(this); } public override bool Equals(object obj) { return ReferenceEquals(this, obj); } public override int GetHashCode() { return Name?.GetHashCode(StringComparison.Ordinal) ?? 0; } } ================================================ FILE: src/ProfileExplorerCore/IR/IRElement.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; namespace ProfileExplorer.Core.IR; public class IRElement : TaggedObject { public IRElement() { // Used by object pool allocation only. } public IRElement(IRElementId elementId) { Id = elementId; TextLocation = default(TextLocation); TextLength = 0; Tags = null; } public IRElement(TextLocation location, int length) { TextLocation = location; TextLength = length; Tags = null; } public virtual bool HasName => false; public virtual ReadOnlyMemory NameValue => null; public virtual string Name { get => NameValue.ToString(); set => throw new NotImplementedException(); } public ulong Id { get; set; } public TextLocation TextLocation { get; set; } public int TextLength { get; set; } public ulong BlockId => IRElementId.FromLong(Id).BlockId; public ulong TupleId => IRElementId.FromLong(Id).TupleId; public ulong OperandId => IRElementId.FromLong(Id).OperandId; public TupleIR ParentTuple { get { return this switch { TupleIR _ => this as TupleIR, OperandIR _ => ((OperandIR)this).Parent, _ => null }; } } public InstructionIR ParentInstruction { get { return this switch { InstructionIR _ => this as InstructionIR, OperandIR _ => ((OperandIR)this).Parent as InstructionIR, _ => null }; } } public BlockIR ParentBlock { get { if (this is BlockIR) { return this as BlockIR; } return ParentTuple?.Parent; } } public FunctionIR ParentFunction { get { var block = ParentBlock; return block?.Parent; } } public virtual void Accept(IRVisitor visitor) { visitor.Visit(this); } public void SetTextRange(TextLocation location, int length) { TextLocation = location; TextLength = length; } public ReadOnlyMemory GetText(string source) { return source.AsMemory(TextLocation.Offset, TextLength); } public ReadOnlyMemory GetText(ReadOnlyMemory source) { return source.Slice(TextLocation.Offset, TextLength); } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is IRElement other && Equals(other); } public override int GetHashCode() { return Id.GetHashCode(); } protected bool Equals(IRElement other) { return Id == other.Id; } } ================================================ FILE: src/ProfileExplorerCore/IR/IRElementId.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.IR; public class IRElementId { public ushort BlockId; public ushort OperandId; public uint TupleId; public static implicit operator ulong(IRElementId elementId) { return elementId.ToLong(); } public static IRElementId NewFunctionId() { return new IRElementId { BlockId = 0xFFFF, TupleId = 0xFFFFFFFF, OperandId = 0xFFFF }; } public static IRElementId FromLong(ulong value) { return new IRElementId { OperandId = (ushort)((value & 0xFFFF) >> 0), TupleId = (uint)((value & 0xFFFFFFFF0000) >> 32), BlockId = (ushort)((value & 0xFFFF000000000000) >> 48) }; } public static ulong ToLong(ushort blockId, uint tupleId = 0, ushort operandId = 0) { return (ulong)blockId << 48 | (ulong)tupleId << 32 | operandId; } public IRElementId NewBlock(int blockId) { return NewBlock((ushort)blockId); } public IRElementId NextTuple() { TupleId++; OperandId = 0; return this; } public IRElementId NextOperand() { OperandId++; return this; } public ulong ToLong() { return ToLong(BlockId, TupleId, OperandId); } private IRElementId NewBlock(ushort blockId) { BlockId = blockId; TupleId = 0; OperandId = 0; return this; } } ================================================ FILE: src/ProfileExplorerCore/IR/IRPrinter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Text; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.Core.IR; public class IRPrinter { private StringBuilder builder_; private FunctionIR function_; public IRPrinter(FunctionIR function) { function_ = function; } public string Print() { builder_ = new StringBuilder(); PrintFunctionStart(); foreach (var block in function_.Blocks) { PrintBlock(block); } PrintFunctionEnd(); return builder_.ToString(); } private void PrintFunctionStart() { builder_.Append($"func {function_.Name}("); bool needsComma = false; foreach (var param in function_.Parameters) { if (needsComma) { builder_.Append(", "); } else { needsComma = true; } PrintOperand(param, true); } builder_.AppendLine($") -> {function_.ReturnType}:"); } private void PrintFunctionEnd() { builder_.AppendLine("// function end"); } private void PrintBlock(BlockIR block) { builder_.Append($"block {{#{block.IndexInFunction}, B{block.Number}}}:"); builder_.Append(" P"); block.Predecessors.ForEach(p => builder_.Append($" {p.Number}")); builder_.Append(", S"); block.Successors.ForEach(p => builder_.Append($" {p.Number}")); builder_.AppendLine(); foreach (var tuple in block.Tuples) { PrintTuple(tuple); builder_.AppendLine(); } } private void PrintTuple(TupleIR tuple) { if (tuple.Kind != TupleKind.Label) { builder_.Append(" "); } switch (tuple.Kind) { case TupleKind.Instruction: { PrintInstruction((InstructionIR)tuple); break; } case TupleKind.Label: { builder_.Append($" label {tuple.Name}:"); break; } case TupleKind.Exception: { builder_.Append("exception"); break; } case TupleKind.Metadata: { builder_.Append("metadata"); break; } case TupleKind.Other: { builder_.Append("other"); break; } } builder_.Append($" | #{tuple.IndexInBlock}, B{tuple.ParentBlock.Number}"); builder_.Append($" | {tuple.TextLocation}, len: {tuple.TextLength}"); } private void PrintInstruction(InstructionIR instr) { bool needsComma = false; foreach (var destOp in instr.Destinations) { if (needsComma) { builder_.Append(", "); } else { needsComma = true; } PrintOperand(destOp, true); } if (instr.Destinations.Count > 0) { builder_.Append(" = "); } if (instr.IsBranch) { builder_.Append("branch "); } else if (instr.IsGoto) { builder_.Append("goto "); } else if (instr.IsSwitch) { builder_.Append("switch "); } else if (instr.IsReturn) { builder_.Append("return "); } builder_.Append($"{instr.OpcodeText} "); needsComma = false; foreach (var sourceOp in instr.Sources) { if (needsComma) { builder_.Append(", "); } else { needsComma = true; } PrintOperand(sourceOp); } } private void PrintOperand(OperandIR op, bool printKind = false) { string result = op.Kind switch { OperandKind.Variable => printKind ? $"var {op.NameValue}.{op.Type}" : $"{op.NameValue}.{op.Type}", OperandKind.Temporary => printKind ? $"temp {op.NameValue}.{op.Type}" : $"{op.NameValue}.{op.Type}", OperandKind.IntConstant => printKind ? $"intconst {op.IntValue}.{op.Type}" : $"{op.IntValue}.{op.Type}", OperandKind.FloatConstant => printKind ? $"floatconst {op.FloatValue}.{op.Type}" : $"{op.FloatValue}.{op.Type}", OperandKind.Indirection => printKind ? $"indir [{op.Value}.{op.Type}]" : $"[{op.Value}.{op.Type}]", OperandKind.Address => printKind ? $"address &{op.NameValue}.{op.Type}" : $"&{op.NameValue}.{op.Type}", OperandKind.LabelAddress => printKind ? string.Format("label &{0}.{1}", op.NameValue) : $"&{op.NameValue}", OperandKind.Other => "other", _ => "" }; var ssaTag = op.GetTag(); if (ssaTag != null) { result += $"<{ssaTag.DefinitionId}>"; } builder_.Append(result); } } ================================================ FILE: src/ProfileExplorerCore/IR/IRVisitor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.IR; public interface IRVisitor { void Visit(IRElement value); void Visit(OperandIR value); void Visit(TupleIR value); void Visit(BlockLabelIR value); void Visit(InstructionIR value); void Visit(BlockIR value); void Visit(FunctionIR value); } ================================================ FILE: src/ProfileExplorerCore/IR/ITag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.IR; public interface ITag { string Name { get; } TaggedObject Owner { get; set; } } ================================================ FILE: src/ProfileExplorerCore/IR/InstructionIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.IR; public enum InstructionKind { Unary, Binary, Branch, Goto, Switch, Phi, Call, Return, Exception, Other } public sealed class InstructionIR : TupleIR { public InstructionIR(IRElementId elementId, InstructionKind kind, BlockIR parent) : base(elementId, TupleKind.Instruction, parent) { Kind = kind; Sources = new List(1); // Usually 1 destination. Destinations = new List(2); // Usually at most 2 sources. } public new InstructionKind Kind { get; set; } public object Opcode { get; set; } public ReadOnlyMemory OpcodeText { get; set; } public TextLocation OpcodeLocation { get; set; } public List Sources { get; } public List Destinations { get; } public bool IsUnary => Kind == InstructionKind.Unary; public bool IsBinary => Kind == InstructionKind.Binary; public bool IsBranch => Kind == InstructionKind.Branch; public bool IsGoto => Kind == InstructionKind.Goto; public bool IsSwitch => Kind == InstructionKind.Switch; public bool IsCall => Kind == InstructionKind.Call; public bool IsReturn => Kind == InstructionKind.Return; public T OpcodeAs() where T : Enum { return (T)Opcode; } public bool OpcodeIs(T value) where T : Enum { return Opcode != null && ((T)Opcode).Equals(value); } public override void Accept(IRVisitor visitor) { visitor.Visit(this); } public override string ToString() { var builder = new StringBuilder(); builder.AppendLine($"instr kind: {Kind}, opcode: {OpcodeText} ({Opcode}), id: {Id}"); for (int i = 0; i < Destinations.Count; i++) { builder.AppendLine($"o dest {i}: {Destinations[i]}".Indent(2)); } for (int i = 0; i < Sources.Count; i++) { builder.AppendLine($"o src {i}: {Sources[i]}".Indent(2)); } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/IR/OperandIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.Core.IR; public enum OperandKind { Variable, Temporary, IntConstant, FloatConstant, Indirection, Address, LabelAddress, Other } public enum OperandRole { Source, Destination, Parameter, Other } public sealed class OperandIR : IRElement { public OperandIR() { // Used by object pool allocation only. } public OperandIR(IRElementId elementId, OperandKind kind, TypeIR type, TupleIR parent) : base(elementId.NextOperand()) { Kind = kind; Type = type; Parent = parent; Value = null; } public OperandKind Kind { get; set; } public OperandRole Role { get; set; } public bool IsSourceOperand => Role == OperandRole.Source; public bool IsDestinationOperand => Role == OperandRole.Destination; public bool IsParameterOperand => Role == OperandRole.Parameter; public TypeIR Type { get; set; } public TupleIR Parent { get; set; } public object Value { get; set; } public bool IsVariable => Kind == OperandKind.Variable; public bool IsTemporary => Kind == OperandKind.Temporary; public bool IsConstant => Kind == OperandKind.IntConstant || Kind == OperandKind.FloatConstant; public bool IsIntConstant => Kind == OperandKind.IntConstant; public bool IsFloatConstant => Kind == OperandKind.FloatConstant; public bool IsAddress => Kind == OperandKind.Address; public bool IsLabelAddress => Kind == OperandKind.LabelAddress; public bool IsIndirection => Kind == OperandKind.Indirection; public long IntValue { get { Debug.Assert(Kind == OperandKind.IntConstant); Debug.Assert(Value is long); return (long)Value; } } public double FloatValue { get { Debug.Assert(Kind == OperandKind.FloatConstant); Debug.Assert(Value is double); return (double)Value; } } public override bool HasName => Kind == OperandKind.Variable || Kind == OperandKind.Temporary || Kind == OperandKind.Address || Kind == OperandKind.LabelAddress; public override ReadOnlyMemory NameValue { get { Debug.Assert(HasName); return Kind switch { OperandKind.Address when Value is OperandIR ir => ir.NameValue, OperandKind.LabelAddress => BlockLabelValue.NameValue, _ => (ReadOnlyMemory)Value }; } } public OperandIR IndirectionBaseValue { get { Debug.Assert(Kind == OperandKind.Indirection); Debug.Assert(Value is OperandIR); return (OperandIR)Value; } } public BlockLabelIR BlockLabelValue { get { Debug.Assert(Kind == OperandKind.LabelAddress); Debug.Assert(Value is BlockLabelIR); return (BlockLabelIR)Value; } } public override void Accept(IRVisitor visitor) { visitor.Visit(this); } public override string ToString() { string result = Kind switch { OperandKind.Variable => $"var {Value}.{Type}", OperandKind.Temporary => $"temp {Value}.{Type}", OperandKind.IntConstant => $"intconst {Value}.{Type}", OperandKind.FloatConstant => $"floatconst {Value}.{Type}", OperandKind.Indirection => $"indir {Value}.{Type}", OperandKind.Address => $"address {Value}.{Type}", OperandKind.LabelAddress => $"label {Value}.{Type}", OperandKind.Other => "other", _ => "" }; var ssaTag = GetTag(); if (ssaTag != null) { result += $"<{ssaTag.DefinitionId}>"; } return $"{result}, id: {Id}"; } } ================================================ FILE: src/ProfileExplorerCore/IR/RegisterIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core.IR; public sealed class RegisterIR { public List Subregisters; public RegisterIR(string name, object register, int bitOffset, int bitSize) { Register = register; Name = name; BitOffset = bitOffset; BitSize = bitSize; Parent = null; Subregisters = new List(); } public RegisterIR(string name, object register, int bitOffset, int bitSize, params RegisterIR[] subregisters) : this(name, register, bitOffset, bitSize) { foreach (var subreg in subregisters) { subreg.Parent = this; Subregisters.Add(subreg); } } public object Register { get; set; } public string Name { get; set; } public int BitOffset { get; set; } public int BitSize { get; set; } public RegisterIR Parent { get; set; } public RegisterIR Root { get { var current = this; var parent = Parent; while (parent != null) { current = parent; parent = current.Parent; } return current; } } public bool IsSubregister => Parent != null; public bool HasSubregisters => Subregisters.Count > 0; public T RegisterAs() where T : Enum { return (T)Register; } public bool RegisterIs(T value) where T : Enum { return Register != null && ((T)Register).Equals(value); } public bool OverlapsWith(RegisterIR other) { //? TODO: Also check bit range overlap return other.Root == Root; } public bool CompletelyOverlapsWith(RegisterIR other) { //? TODO return false; } public override bool Equals(object obj) { return obj is RegisterIR iR && EqualityComparer.Default.Equals(Register, iR.Register) && BitOffset == iR.BitOffset && BitSize == iR.BitSize; } public override int GetHashCode() { return HashCode.Combine(Register, BitOffset, BitSize); } public override string ToString() { return $"{Name}"; } } ================================================ FILE: src/ProfileExplorerCore/IR/RegisterTable.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core.IR; public class RegisterTable { private Dictionary registerMap_; private List virtualRegisters_; public RegisterTable() { registerMap_ = new Dictionary(); virtualRegisters_ = new List(); } public RegisterIR this[string name] { get => GetRegister(name); set => throw new NotImplementedException(); } public RegisterIR GetRegister(string name) { if (registerMap_.TryGetValue(name, out var register)) { return register; } //? check if virtual reg return null; } public RegisterIR GetRegister(ReadOnlyMemory name) { return null; } public void AddRegisterAlias(string registerAlias, string register) { registerMap_[registerAlias] = registerMap_[register]; } public void AddRegisterAlias(string registerAlias, RegisterIR register) { registerMap_[registerAlias] = register; } protected void PopulateRegisterTable(RegisterIR[] registers) { foreach (var register in registers) { PupulateRegisterClass(register); } } private void PupulateRegisterClass(RegisterIR register) { registerMap_[register.Name] = register; foreach (var subreg in register.Subregisters) { PupulateRegisterClass(subreg); } } } ================================================ FILE: src/ProfileExplorerCore/IR/TaggedObject.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.IR; public class TaggedObject { public List Tags { get; set; } public void AddTag(ITag tag) { Tags ??= new List(); tag.Owner = this; Tags.Add(tag); } public T GetTag() where T : class { if (Tags != null) { foreach (var tag in Tags) { if (tag is T value) { return value; } } } return null; } public bool HasTag() where T : class { return GetTag() != null; } public bool TryGetTag(out T result) where T : class { result = GetTag(); return result != null; } public T GetOrAddTag() where T : class, new() { var result = GetTag(); if (result != null) { return result; } var tag = new T(); AddTag(tag as ITag); return tag; } public bool RemoveTag() where T : class { if (Tags != null) { return Tags.RemoveAll(tag => tag is T) > 0; } return false; } public override string ToString() { if (Tags == null || Tags.Count == 0) { return ""; } var builder = new StringBuilder(); builder.AppendLine($"{Tags.Count} tags:"); foreach (var tag in Tags) { builder.AppendLine($" o {tag}".Indent(4)); } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/AssemblyMetadataTag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Text; namespace ProfileExplorer.Core.IR.Tags; public sealed class AssemblyMetadataTag : ITag { public AssemblyMetadataTag() { AddressToElementMap = new Dictionary(); OffsetToElementMap = new Dictionary(); ElementToOffsetMap = new Dictionary(); ElementSizeMap = new Dictionary(); } public Dictionary AddressToElementMap { get; set; } public Dictionary OffsetToElementMap { get; set; } public Dictionary ElementToOffsetMap { get; set; } public Dictionary ElementSizeMap { get; set; } public long FunctionSize { get; set; } public string Name => "Address metadata"; public TaggedObject Owner { get; set; } public void EnsureCapacity(int length) { AddressToElementMap.EnsureCapacity(length); OffsetToElementMap.EnsureCapacity(length); ElementToOffsetMap.EnsureCapacity(length); ElementSizeMap.EnsureCapacity(length); } public override string ToString() { var builder = new StringBuilder(); foreach (var pair in OffsetToElementMap) { builder.Append($"{pair.Key} = {pair.Value}"); } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/LoopTag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Analysis; namespace ProfileExplorer.Core.IR.Tags; public sealed class LoopBlockTag : ITag { public LoopBlockTag(Loop parentLoop, int nestingLevel = 0) { Loop = parentLoop; NestingLevel = nestingLevel; } public Loop Loop { get; set; } public int NestingLevel { get; set; } public string Name => "Loop block"; public TaggedObject Owner { get; set; } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/NotesTag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core.IR.Tags; public class NotesTag : ITag { public NotesTag() { Title = ""; Notes = new List(); } public NotesTag(string title) : this() { Title = title; } public string Title { get; set; } public List Notes { get; set; } public string Name => "Notes"; public TaggedObject Owner { get; set; } public override bool Equals(object obj) { return obj is NotesTag tag && Title == tag.Title && EqualityComparer>.Default.Equals(Notes, tag.Notes); } public override int GetHashCode() { return HashCode.Combine(Title, Notes); } public override string ToString() { return $"Notes title: {Title}"; } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/RegisterTag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core.IR.Tags; public sealed class RegisterTag : ITag { public RegisterTag(RegisterIR register, TaggedObject owner) { Register = register; Owner = owner; } public RegisterIR Register { get; set; } public string Name => "Register"; public TaggedObject Owner { get; set; } public override bool Equals(object obj) { return obj is RegisterTag tag && EqualityComparer.Default.Equals(Register, tag.Register); } public override int GetHashCode() { return HashCode.Combine(Register); } public override string ToString() { return $"Register: {Register}"; } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/SSATags.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; namespace ProfileExplorer.Core.IR.Tags; public interface ISSAValue { int DefinitionId { get; set; } OperandIR DefinitionOperand { get; } TupleIR DefinitionTuple { get; } InstructionIR DefinitionInstruction { get; } } public sealed class SSAUseTag : ITag, ISSAValue { public SSAUseTag(int definitionId, SSADefinitionTag definition) { DefinitionId = definitionId; Definition = definition; } public SSADefinitionTag Definition { get; set; } public IRElement OwnerElement => (IRElement)Owner; public InstructionIR OwnerInstruction => OwnerElement.ParentInstruction; public int DefinitionId { get; set; } public OperandIR DefinitionOperand => Definition?.Owner as OperandIR; public TupleIR DefinitionTuple => DefinitionOperand.ParentTuple; public InstructionIR DefinitionInstruction => DefinitionTuple as InstructionIR; public string Name => "SSA use-definition link"; public TaggedObject Owner { get; set; } // Source operand. public override bool Equals(object obj) { return obj is SSAUseTag tag && DefinitionId == tag.DefinitionId; } public override int GetHashCode() { return HashCode.Combine(DefinitionId); } public override string ToString() { return $"SSA UD-link: {DefinitionId}"; } } public sealed class SSADefinitionTag : ITag, ISSAValue { public SSADefinitionTag(int defId) { DefinitionId = defId; Users = new List(); } public List Users { get; } public bool HasUsers => Users.Count > 0; public bool HasSingleUser => Users.Count == 1; public IRElement OwnerElement => (IRElement)Owner; public int DefinitionId { get; set; } public OperandIR DefinitionOperand => Owner as OperandIR; public TupleIR DefinitionTuple => ((IRElement)Owner).ParentTuple; public InstructionIR DefinitionInstruction => ((IRElement)Owner).ParentTuple as InstructionIR; public string Name => "SSA definition"; public TaggedObject Owner { get; set; } // Destination operand. public override bool Equals(object obj) { return obj is SSADefinitionTag tag && DefinitionId == tag.DefinitionId; } public override int GetHashCode() { return HashCode.Combine(DefinitionId); } public override string ToString() { var builder = new StringBuilder(); builder.AppendLine($"SSA definition: {DefinitionId}"); builder.AppendLine($" - parent: {((IRElement)Owner).Id}"); builder.AppendLine($" - users: {Users.Count}"); foreach (var user in Users) { builder.AppendLine($" - {((IRElement)user.Owner).Id}"); } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/SourceLocationTag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; namespace ProfileExplorer.Core.IR.Tags; public sealed class SourceLocationTag : ITag { public SourceLocationTag() { } public SourceLocationTag(int line, int column) { Line = line; Column = column; } public List Inlinees { get; set; } public int Line { get; set; } public int Column { get; set; } public string FilePath { get; set; } public bool HasInlinees => Inlinees != null && Inlinees.Count > 0; public List InlineesReversed { get { var clone = new List(Inlinees); clone.Reverse(); return clone; } } public string Name => "Source location"; public TaggedObject Owner { get; set; } public void AddInlinee(string function, string filePath, int line, int column) { Inlinees ??= new List(); Inlinees.Add(new SourceStackFrame(function, filePath, line, column)); } public void AddInlinee(SourceStackFrame inlinee) { Inlinees ??= new List(); Inlinees.Add(inlinee); } public void Reset() { Inlinees = null; Line = 0; Column = 0; } public override bool Equals(object obj) { return obj is SourceLocationTag tag && Line == tag.Line && Column == tag.Column; } public override int GetHashCode() { return HashCode.Combine(Line, Column); } public override string ToString() { var builder = new StringBuilder(); builder.Append($"source location: {Line};{Column}"); if (Inlinees != null) { builder.AppendLine($"\n inlinees: {Inlinees.Count}"); foreach (var item in Inlinees) { builder.AppendLine($" {item.Line};{item.Column}: {item.Function}"); } } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/IR/Tags/SourceStackTrace.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.IR.Tags; public sealed class SourceStackFrame : IEquatable { public SourceStackFrame(string function, string filePath, int line, int column) { Function = function; FilePath = filePath; Line = line; Column = column; } public string Function { get; set; } public string FilePath { get; set; } public int Line { get; set; } public int Column { get; set; } public bool Equals(SourceStackFrame other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Line == other.Line && Column == other.Column && Function.Equals(other.Function, StringComparison.OrdinalIgnoreCase) && FilePath.Equals(other.FilePath, StringComparison.OrdinalIgnoreCase); } public static bool operator ==(SourceStackFrame left, SourceStackFrame right) { return Equals(left, right); } public static bool operator !=(SourceStackFrame left, SourceStackFrame right) { return !Equals(left, right); } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is SourceStackFrame other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(Function, FilePath, Line, Column); } public bool HasSameFunction(SourceStackFrame inlinee) { return Function.Equals(inlinee.Function, StringComparison.OrdinalIgnoreCase) && FilePath.Equals(inlinee.FilePath, StringComparison.OrdinalIgnoreCase); } } public sealed class SourceStackTrace { public SourceStackTrace() { Frames = new List(); } public SourceStackTrace(IEnumerable frames) : this() { AddFrames(frames); } public List Frames { get; set; } public byte[] Signature { get; set; } public void AddFrames(IEnumerable frames) { Frames.AddRange(frames); UpdateSignature(); } public override bool Equals(object obj) { return obj is SourceStackTrace trace && EqualityComparer.Default.Equals(Signature, trace.Signature); } public override int GetHashCode() { return HashCode.Combine(Signature); } public void UpdateSignature() { // Compute a hash that identifies the stack trace // to speed up equality check. var bytesList = new List(Frames.Count); foreach (var frame in Frames) { bytesList.Add(Encoding.UTF8.GetBytes(frame.Function)); bytesList.Add(Encoding.UTF8.GetBytes(frame.FilePath)); bytesList.Add(BitConverter.GetBytes(frame.Line)); bytesList.Add(BitConverter.GetBytes(frame.Column)); } Signature = CompressionUtils.CreateSHA256(bytesList); } } ================================================ FILE: src/ProfileExplorerCore/IR/TupleIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.IR; public enum TupleKind { Instruction, Label, Exception, Metadata, Other } public class TupleIR : IRElement { public TupleIR(IRElementId elementId, TupleKind kind, BlockIR parent) : base(elementId.NextTuple()) { Kind = kind; Parent = parent; } public BlockIR Parent { get; set; } public int IndexInBlock { get; set; } public bool HasOddIndexInBlock => (IndexInBlock & 1) == 1; public bool HasEvenIndexInBlock => (IndexInBlock & 1) == 0; public TupleKind Kind { get; set; } public bool IsInstruction => Kind == TupleKind.Instruction; public bool IsLabel => Kind == TupleKind.Label; public bool IsException => Kind == TupleKind.Exception; public bool IsMetadata => Kind == TupleKind.Metadata; public override void Accept(IRVisitor visitor) { visitor.Visit(this); } public override string ToString() { return $"tuple kind: {Kind}, id: {Id}"; } } ================================================ FILE: src/ProfileExplorerCore/IR/TypeIR.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; namespace ProfileExplorer.Core.IR; public enum TypeKind { Integer, Float, Vector, Multibyte, Array, Struct, Pointer, Void, Bool, Unknown } [Flags] public enum TypeFlags { None = 0, SignedInt = 1, UnsignedInt = 2 } public sealed class TypeIR { private static readonly TypeIR boolType_ = new(TypeKind.Integer, 0); private static readonly TypeIR doubleType_ = new(TypeKind.Float, 8); private static readonly TypeIR floatType_ = new(TypeKind.Float, 4); private static readonly TypeIR[] signedIntTypes_ = { new(TypeKind.Integer, 1, TypeFlags.SignedInt), new(TypeKind.Integer, 2, TypeFlags.SignedInt), new(TypeKind.Integer, 4, TypeFlags.SignedInt), new(TypeKind.Integer, 8, TypeFlags.SignedInt) }; private static readonly ConcurrentDictionary uniqueTypes_ = new(); private static readonly TypeIR unknownType_ = new(TypeKind.Unknown, 0); private static readonly TypeIR[] unsignedIntTypes_ = { new(TypeKind.Integer, 1, TypeFlags.UnsignedInt), new(TypeKind.Integer, 2, TypeFlags.UnsignedInt), new(TypeKind.Integer, 4, TypeFlags.UnsignedInt), new(TypeKind.Integer, 8, TypeFlags.UnsignedInt) }; private static readonly TypeIR voidType_ = new(TypeKind.Void, 0); private TypeIR(TypeKind kind, int size, TypeFlags flags = TypeFlags.None) { Kind = kind; Size = size; Flags = flags; } public bool IsFloat => Kind == TypeKind.Float; public bool IsInt => Kind == TypeKind.Integer && Flags != TypeFlags.UnsignedInt; public bool IsInteger => Kind == TypeKind.Integer; public bool IsMultibyte => Kind == TypeKind.Multibyte; public bool IsUInt => Kind == TypeKind.Integer && Flags == TypeFlags.UnsignedInt; public bool IsUnknown => Kind == TypeKind.Unknown; public bool IsVoid => Kind == TypeKind.Void; private TypeFlags Flags { get; set; } private TypeKind Kind { get; set; } private int Size { get; set; } public static TypeIR GetBool() { return boolType_; } public static TypeIR GetDouble() { return doubleType_; } public static TypeIR GetFloat() { return floatType_; } public static TypeIR GetInt(int size) { return size switch { 1 => signedIntTypes_[0], 2 => signedIntTypes_[1], 4 => signedIntTypes_[2], 8 => signedIntTypes_[3], _ => GetType(TypeKind.Integer, size, TypeFlags.SignedInt) }; } public static TypeIR GetInt16() { return signedIntTypes_[1]; } public static TypeIR GetInt32() { return signedIntTypes_[2]; } public static TypeIR GetInt64() { return signedIntTypes_[3]; } public static TypeIR GetInt8() { return signedIntTypes_[0]; } public static TypeIR GetMultibyte(int size) { return GetType(TypeKind.Multibyte, size); } public static TypeIR GetType(TypeKind kind, int size, TypeFlags flags = TypeFlags.None) { var type = new TypeIR(kind, size, flags); return uniqueTypes_.GetOrAdd(type, type); } public static TypeIR GetUInt(int size) { return size switch { 1 => unsignedIntTypes_[0], 2 => unsignedIntTypes_[1], 4 => unsignedIntTypes_[2], 8 => unsignedIntTypes_[3], _ => GetType(TypeKind.Integer, size, TypeFlags.UnsignedInt) }; } public static TypeIR GetUInt16() { return unsignedIntTypes_[1]; } public static TypeIR GetUInt32() { return unsignedIntTypes_[2]; } public static TypeIR GetUInt64() { return unsignedIntTypes_[3]; } public static TypeIR GetUInt8() { return unsignedIntTypes_[0]; } public static TypeIR GetUnknown() { return unknownType_; } public static TypeIR GetVoid() { return voidType_; } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is TypeIR other && Equals(other); } public override int GetHashCode() { return HashCode.Combine((int)Flags, (int)Kind, Size); } public override string ToString() { switch (Kind) { case TypeKind.Integer: { return IsUInt ? $"uint{Size * 8}" : $"int{Size * 8}"; } case TypeKind.Float: return $"float{Size * 8}"; case TypeKind.Vector: return $"vector{Size * 8}"; case TypeKind.Multibyte: return $"mb{Size}"; case TypeKind.Array: return ""; case TypeKind.Struct: return ""; case TypeKind.Pointer: return ""; case TypeKind.Void: return "void"; case TypeKind.Bool: return "bool"; case TypeKind.Unknown: return "unk"; } return ""; } private bool Equals(TypeIR other) { return Flags == other.Flags && Kind == other.Kind && Size == other.Size; } } ================================================ FILE: src/ProfileExplorerCore/IRPassOutput.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; namespace ProfileExplorer.Core; public class IRPassOutput { public static readonly IRPassOutput Empty = new(0, 0, 0, 0); public IRPassOutput(long dataStartOffset, long dataEndOffset, int startLine, int endLine) { DataStartOffset = dataStartOffset; DataEndOffset = dataEndOffset; StartLine = startLine; EndLine = endLine; } public long DataStartOffset { get; set; } public long DataEndOffset { get; set; } // One past end. public long Size => DataEndOffset - DataStartOffset; public byte[] Signature { get; set; } // SHA256 signature of the text. public int StartLine { get; set; } public int EndLine { get; set; } public int LineCount => EndLine - StartLine + 1; public bool HasPreprocessedLines { get; set; } public override bool Equals(object obj) { return obj is IRPassOutput output && DataStartOffset == output.DataStartOffset && DataEndOffset == output.DataEndOffset && StartLine == output.StartLine && EndLine == output.EndLine; } public override int GetHashCode() { return HashCode.Combine(DataStartOffset, DataEndOffset); } } ================================================ FILE: src/ProfileExplorerCore/IRSectionReader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core; public delegate void ProgressInfoHandler(IRSectionReader reader, SectionReaderProgressInfo info); public delegate void SectionTextHandler(IRSectionReader reader, SectionReaderText info); public interface IRSectionReader { IRTextSummary GenerateSummary(ProgressInfoHandler progressHandler, SectionTextHandler sectionTextHandler = null); string GetSectionText(IRTextSection section); ReadOnlyMemory GetSectionTextSpan(IRTextSection section); List GetSectionTextLines(IRTextSection section); string GetPassOutputText(IRPassOutput output); ReadOnlyMemory GetPassOutputTextSpan(IRPassOutput output); List GetPassOutputTextLines(IRPassOutput output); string GetRawSectionText(IRTextSection section); ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section); string GetRawPassOutputText(IRPassOutput output); ReadOnlyMemory GetRawPassOutputTextSpan(IRPassOutput output); public byte[] GetDocumentTextData(); void Dispose(); } public class SectionReaderProgressInfo { public SectionReaderProgressInfo(long bytesProcessed, long totalBytes) { BytesProcessed = bytesProcessed; TotalBytes = totalBytes; } public SectionReaderProgressInfo(bool working) { IsIndeterminate = working; } public long BytesProcessed { get; set; } public long TotalBytes { get; set; } public bool IsIndeterminate { get; set; } } public class SectionReaderText { public SectionReaderText(IRPassOutput output, List textLines) { Output = output; TextLines = textLines; } public IRPassOutput Output { get; set; } public List TextLines { get; set; } } ================================================ FILE: src/ProfileExplorerCore/IRTextFunction.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core; public class IRTextFunction : IEquatable { private int cachedHashCode_; public IRTextFunction(string name) { Name = string.Intern(name); Sections = new List(); } public List Sections { get; } public int Number { get; set; } public string Name { get; } public IRTextSummary ParentSummary { get; set; } public string ModuleName => ParentSummary?.ModuleName; public int MaxBlockCount { get { IRTextSection maxSection = null; foreach (var section in Sections) { if (maxSection == null) { maxSection = section; } else if (section.BlockCount > maxSection.BlockCount) { maxSection = section; } } return maxSection?.BlockCount ?? 0; } } public int SectionCount => Sections?.Count ?? 0; public bool HasSections => SectionCount != 0; public bool Equals(IRTextFunction other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } // Because name is interned, we can use reference equality. return ReferenceEquals(Name, other.Name) && HasSameModule(other); } public void AddSection(IRTextSection section) { section.Number = Sections.Count + 1; Sections.Add(section); } public IRTextSection FindSection(string name) { return Sections.Find(item => item.Name == name); } public List FindAllSections(string nameSubstring) { return Sections.FindAll(section => section.Name.Contains(nameSubstring)); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((IRTextFunction)obj); } public override int GetHashCode() { // Compute the hash so that functs. with same name in diff. modules // don't get the same hash code. if (cachedHashCode_ == 0) { cachedHashCode_ = ParentSummary != null ? HashCode.Combine(Name, ParentSummary) : HashCode.Combine(Name); } return cachedHashCode_; } public override string ToString() { return Name; } private bool HasSameModule(IRTextFunction other) { if (ReferenceEquals(ParentSummary, other.ParentSummary)) { return true; } if (ParentSummary != null && other.ParentSummary != null) { return ParentSummary.Equals(other.ParentSummary); } return ParentSummary == null && other.ParentSummary == null; } } ================================================ FILE: src/ProfileExplorerCore/IRTextSection.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core; public class IRTextSection : IEquatable { private CompressedObject> lineMetadata_; public IRTextSection() { } public IRTextSection(IRTextFunction parent, string name, IRPassOutput sectionOutput, int blocks = 0) { ParentFunction = parent; Name = string.Intern(name); Output = sectionOutput; BlockCount = blocks; } public int Id { get; set; } public int Number { get; set; } public string Name { get; set; } public int BlockCount { get; set; } public IRTextFunction ParentFunction { get; set; } public string ModuleName => ParentFunction?.ParentSummary?.ModuleName; public int LineCount => Output.LineCount; public IRPassOutput Output { get; set; } public IRPassOutput OutputAfter { get; set; } public IRPassOutput OutputBefore { get; set; } public Dictionary LineMetadata { get => lineMetadata_?.GetValue(); set => lineMetadata_ = new CompressedObject>(value); } public bool Equals(IRTextSection other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Number == other.Number && Name.Equals(other.Name, StringComparison.Ordinal) && (ParentFunction == null && other.ParentFunction == null || ParentFunction != null && ParentFunction.Equals(other.ParentFunction)); } public void AddLineMetadata(int lineNumber, string metadata) { LineMetadata ??= new Dictionary(); LineMetadata[lineNumber] = metadata; } public string GetLineMetadata(int lineNumber) { if (LineMetadata != null && LineMetadata.TryGetValue(lineNumber, out string value)) { return value; } return null; } public void CompressLineMetadata() { if (lineMetadata_ != null) { lineMetadata_.Compress(); } } public bool IsSectionTextDifferent(IRTextSection other) { // If there is a signature, assume that same signature means same text. if (Output?.Signature != null && other?.Output.Signature != null) { return !Output.Signature.AsSpan().SequenceEqual(other.Output.Signature.AsSpan()); } return true; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((IRTextSection)obj); } public override int GetHashCode() { return HashCode.Combine(Number, ParentFunction?.GetHashCode() ?? 0); } public override string ToString() { return $"({Number}) {Name}"; } } ================================================ FILE: src/ProfileExplorerCore/IRTextSectionLoader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Threading; using CSharpTest.Net.Collections; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; namespace ProfileExplorer.Core; public class ParsedIRTextSection { public ParsedIRTextSection(IRTextSection section, ReadOnlyMemory text, FunctionIR function) { Section = section; Text = text; Function = function; } public IRTextSection Section { get; set; } public ReadOnlyMemory Text { get; set; } public FunctionIR Function { get; set; } public List ParsingErrors { get; set; } public bool IsCached { get; set; } public bool LoadFailed { get; set; } public bool HadParsingErrors => ParsingErrors != null && ParsingErrors.Count > 0; public IRTextFunction ParentFunction => Section.ParentFunction; public override string ToString() { return Section.ToString(); } } public abstract class IRTextSectionLoader : IDisposable { private const int CACHE_LIMIT = 32; protected LurchTable sectionCache_; protected ICompilerIRInfo irInfo_; protected bool cacheEnabled_; protected object lockObject_; protected long sectionPreprocessingCompleted_; protected bool disposed_; public bool SectionSignaturesComputed => Interlocked.Read(ref sectionPreprocessingCompleted_) != 0; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public event EventHandler SectionPreprocessingCompleted; public abstract Task LoadDocument(ProgressInfoHandler progressHandler); public abstract string GetDocumentOutputText(); public abstract byte[] GetDocumentTextBytes(); public abstract ParsedIRTextSection LoadSection(IRTextSection section); public abstract string GetSectionText(IRTextSection section); public abstract ReadOnlyMemory GetSectionTextSpan(IRTextSection section); public abstract string GetSectionOutputText(IRPassOutput output); public abstract ReadOnlyMemory GetSectionPassOutputTextSpan(IRPassOutput output); public abstract List GetSectionPassOutputTextLines(IRPassOutput output); public abstract string GetRawSectionText(IRTextSection section); public abstract string GetRawSectionPassOutput(IRPassOutput output); public abstract ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section); public abstract ReadOnlyMemory GetRawSectionPassOutputSpan(IRPassOutput output); public ParsedIRTextSection TryGetLoadedSection(IRTextSection section) { if (!cacheEnabled_) { return null; } lock (lockObject_) { return sectionCache_.TryGetValue(section, out var result) ? result : null; } } public string GetSectionText(IRTextSection section, bool useCache = true) { var result = GetSectionTextSpan(section, useCache); return result.ToString(); } public ReadOnlyMemory GetSectionTextSpan(IRTextSection section, bool useCache = true) { if (useCache && cacheEnabled_) { lock (lockObject_) { if (sectionCache_.TryGetValue(section, out var result)) { return result.Text; } } } return GetSectionTextSpan(section); } public string GetRawSectionText(IRTextSection section, bool useCache = true) { return GetRawSectionText(section); } public void SuspendCaching() { cacheEnabled_ = false; } public void ResumeCaching() { cacheEnabled_ = true; } public void ResetCache() { if (!cacheEnabled_) { return; } lock (lockObject_) { sectionCache_.Clear(); } } protected void NotifySectionPreprocessingCompleted(bool canceled) { Interlocked.Exchange(ref sectionPreprocessingCompleted_, 1); SectionPreprocessingCompleted?.Invoke(this, canceled); } protected void Initialize(ICompilerIRInfo irInfo, bool cacheEnabled) { irInfo_ = irInfo; cacheEnabled_ = cacheEnabled; lockObject_ = new object(); sectionPreprocessingCompleted_ = 0; sectionCache_ = new LurchTable(LurchTableOrder.Insertion, CACHE_LIMIT); } protected (IRSectionParser, IRParsingErrorHandler) InitializeParser(long functionSize = 0) { var errorHandler = irInfo_.CreateParsingErrorHandler(); return (irInfo_.CreateSectionParser(errorHandler, functionSize), errorHandler); } protected void CacheParsedSection(IRTextSection section, FunctionIR function, ParsedIRTextSection result) { lock (lockObject_) { if (cacheEnabled_ && function != null) { sectionCache_[section] = result; } } } protected ParsedIRTextSection TryGetCachedParsedSection(IRTextSection section) { lock (lockObject_) { if (cacheEnabled_ && sectionCache_.TryGetValue(section, out var cachedResult)) { //Trace.TraceInformation($"Section loader {ObjectTracker.Track(this)}: found in cache"); cachedResult.IsCached = true; return cachedResult; } } return null; } protected abstract void Dispose(bool disposing); ~IRTextSectionLoader() { Dispose(false); } } ================================================ FILE: src/ProfileExplorerCore/IRTextSummary.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core; public class IRTextSummary : IEquatable { private Dictionary functionNameMap_; private Dictionary unmangledFunctionNameMap_; private Dictionary functionMap_; private Dictionary sectionMap_; private int hashCode_; public IRTextSummary(string moduleName = null) { SetModuleName(moduleName); Functions = new List(); functionNameMap_ = new Dictionary(); functionMap_ = new Dictionary(); sectionMap_ = new Dictionary(); } public Guid Id { get; set; } public string ModuleName { get; private set; } public List Functions { get; set; } public bool Equals(IRTextSummary other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return ModuleName.Equals(other.ModuleName, StringComparison.Ordinal); } public void SetModuleName(string moduleName) { ModuleName = moduleName != null ? string.Intern(moduleName) : null; } public void AddFunction(IRTextFunction function) { if (functionNameMap_.ContainsKey(function.Name)) { return; //? remove } function.Number = Functions.Count; Functions.Add(function); functionNameMap_.Add(function.Name, function); functionMap_.Add(function.Number, function); function.ParentSummary = this; } public void AddSection(IRTextSection section) { section.Id = sectionMap_.Count; sectionMap_.Add(sectionMap_.Count, section); } public IRTextSection GetSectionWithId(int id) { return sectionMap_.TryGetValue(id, out var value) ? value : null; } public IRTextFunction GetFunctionWithId(int id) { return functionMap_.TryGetValue(id, out var result) ? result : null; } public IRTextFunction FindFunction(string name) { return functionNameMap_.TryGetValue(name, out var result) ? result : null; } public IRTextFunction FindFunction(string name, Func matchCheck) { if (unmangledFunctionNameMap_ == null) { ComputeUnmangledFunctionNameMap(matchCheck); } return unmangledFunctionNameMap_.GetValueOrNull(name); } public void ComputeUnmangledFunctionNameMap(Func funcNameFormatter) { lock (this) { if (unmangledFunctionNameMap_ != null) { return; } unmangledFunctionNameMap_ = new Dictionary(); foreach (var function in Functions) { string unmangledName = funcNameFormatter(function.Name); unmangledFunctionNameMap_[unmangledName] = function; } } } public List FindFunctions(Func matchCheck) { var list = new List(); foreach (var function in Functions) { if (matchCheck(function.Name)) { list.Add(function); } } return list; } public List FindAllFunctions(string nameSubstring) { return Functions.FindAll(func => func.Name.Contains(nameSubstring, StringComparison.Ordinal)); } public List FindAllFunctions(string[] nameSubstrings) { return Functions.FindAll(func => { foreach (string name in nameSubstrings) { if (!func.Name.Contains(name, StringComparison.Ordinal)) { return false; } } return true; }); } public IRTextFunction FindFunction(IRTextFunction function) { return functionNameMap_.TryGetValue(function.Name, out var result) ? result : null; } public override int GetHashCode() { return ModuleName != null ? ModuleName.GetHashCode() : 0; } public override string ToString() { var sb = new StringBuilder(); sb.AppendLine($"Summary: {ModuleName}"); sb.AppendLine($"Functions: {Functions.Count}"); return sb.ToString(); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((IRTextSummary)obj); } } ================================================ FILE: src/ProfileExplorerCore/Lexer/CharSource.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Runtime.CompilerServices; namespace ProfileExplorer.Core.Lexer; public sealed class CharSource { public static readonly char EOF = '\0'; public static readonly char NewLine = '\n'; public ReadOnlyMemory TextSpan { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; private set; } public int Position { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; set; } public void Initialize(ReadOnlyMemory text) { TextSpan = text; Position = 0; } public void Initialize(string text) { TextSpan = text.AsMemory(); Position = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public char NextChar() { if (Position >= TextSpan.Length) { Position++; return EOF; } return TextSpan.Span[Position++]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public char PeekChar() { return Position >= TextSpan.Length ? EOF : TextSpan.Span[Position]; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public char Skip(int count = 1) { Position += count; return PeekChar(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public char GoBack(int count = 1) { Position -= count; return PeekChar(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory Extract(int position, int length) { return TextSpan.Slice(position, length); } } ================================================ FILE: src/ProfileExplorerCore/Lexer/CharTable.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Runtime.CompilerServices; namespace ProfileExplorer.Core.Lexer; public static class CharTable { private const byte CHAR_WHITESPACE = 1; private const byte CHAR_LETTER = 2; private const byte CHAR_DIGIT = 4; private const byte CHAR_NUMBER = 8; private const byte CHAR_IDENTIFIER = 16; private static readonly byte[] CHAR_TYPE = { 0, 0, 0, 0, 0, 0, 0, 0, // 8 0, 1, 1, 1, 1, 1, 0, 0, // 16 0, 0, 0, 0, 0, 0, 0, 0, // 24 0, 0, 0, 0, 0, 0, 0, 0, // 32 1, 0, 0, 0, 26, 0, 0, 0, // 40 0, 0, 0, 0, 0, 0, 8, 0, // 48 28, 28, 28, 28, 28, 28, 28, 28, // 56 28, 28, 0, 0, 0, 0, 0, 16, // 64 18, 26, 26, 26, 26, 26, 26, 18, // 72 18, 18, 18, 18, 18, 18, 18, 18, // 80 18, 18, 18, 18, 18, 18, 18, 18, // 88 26, 18, 18, 0, 0, 0, 0, 18, // 96 0, 26, 26, 26, 26, 26, 26, 18, // 104 18, 18, 18, 18, 18, 18, 18, 18, // 112 18, 18, 18, 18, 18, 18, 18, 18, // 120 26, 18, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsDigit(char value) { return (CHAR_TYPE[(byte)value] & CHAR_DIGIT) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsWhitespace(char value) { return (CHAR_TYPE[(byte)value] & CHAR_WHITESPACE) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsLetter(char value) { return (CHAR_TYPE[(byte)value] & CHAR_LETTER) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNumberChar(char value) { return (CHAR_TYPE[(byte)value] & CHAR_NUMBER) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsIdentifierChar(char value) { return (CHAR_TYPE[(byte)value] & CHAR_IDENTIFIER) != 0; } } ================================================ FILE: src/ProfileExplorerCore/Lexer/Lexer.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Buffers; using System.Collections.Generic; namespace ProfileExplorer.Core.Lexer; public sealed class Lexer { public delegate bool TokenAction(Token token); private char current_; // The current character. private int line_; // The current line. private int lineStart_; // The position of the current line start. private Stack returnedTokens_; // Tokens returned back to lexer. private CharSource source_; // The text being analyzed. public Lexer() { source_ = new CharSource(); returnedTokens_ = new Stack(8); } public void Initialize(string text) { Reset(); source_.Initialize(text); current_ = source_.NextChar(); } public void Initialize(ReadOnlyMemory text) { Reset(); source_.Initialize(text); current_ = source_.NextChar(); } public Token NextToken() { return returnedTokens_.Count > 0 ? returnedTokens_.Pop() : ScanToken(); } public void ReturnToken(Token token) { returnedTokens_.Push(token); } public Token PeekToken() { var token = NextToken(); ReturnToken(token); return token; } public Token PeekToken(int position) { // Use a temp array to store the skipped token, // which must be returned after reaching the desired one. var tempArray = ArrayPool.Shared.Rent(position); int tempIndex = 0; // Get to the token at the position (starting with 1) // relative to the previously retrieved token. var token = NextToken(); tempArray[tempIndex++] = token; while (!token.IsEOF() && tempIndex < position) { token = NextToken(); tempArray[tempIndex++] = token; } // Return the tokens so they are are used by NextToken. for (int i = tempIndex - 1; i >= 0; i--) { ReturnToken(tempArray[i]); } ArrayPool.Shared.Return(tempArray); return token; } public void PeekTokenWhile(TokenAction action, int maxLookupLength) { var tempArray = ArrayPool.Shared.Rent(maxLookupLength); int tempIndex = 0; Token token; do { token = NextToken(); tempArray[tempIndex++] = token; } while (!token.IsEOF() && action(token) && tempIndex < maxLookupLength); for (int i = tempIndex - 1; i >= 0; i--) { ReturnToken(tempArray[i]); } ArrayPool.Shared.Return(tempArray); } public ReadOnlyMemory GetTokenText(Token token) { return source_.TextSpan.Slice(token.Location.Offset, token.Length); } public ReadOnlyMemory GetText(int offset, int length) { return source_.TextSpan.Slice(offset, length); } private void NextChar() { current_ = source_.NextChar(); } private Token MakeToken(TokenKind kind, int length = 1) { return new Token { Kind = kind, Location = new TextLocation { Offset = source_.Position - length - 1, Line = line_, Column = source_.Position - lineStart_ - length - 1 }, Length = length, Data = ReadOnlyMemory.Empty }; } private Token MakeDataToken(TokenKind kind, int startPosition, int length) { return new Token { Kind = kind, Location = new TextLocation { Offset = startPosition, Line = line_, Column = startPosition - lineStart_ }, Length = length, Data = source_.Extract(startPosition, length) }; } private Token ScanNumber() { int startPosition = source_.Position; char previous = current_; NextChar(); // Skip first digit. while (CharTable.IsNumberChar(current_)) { previous = current_; NextChar(); } if ((current_ == '+' || current_ == '-') && (previous == 'E' || previous == 'e')) { NextChar(); // Skip over +/-. while (CharTable.IsDigit(current_)) { previous = current_; NextChar(); } } // A dot that is not followed by digits // should not be handled as part of a float number. if (previous == '.') { source_.GoBack(2); NextChar(); } else if ((previous == 'x' || previous == 'X') && source_.Position - startPosition > 3) { // 0x%x // .x from 123.x should not be part of a number either, // since the x does not denote a hex number. source_.GoBack(3); NextChar(); } int length = source_.Position - startPosition - 1; return MakeDataToken(TokenKind.Number, startPosition, length); } private Token ScanString(char delimiter) { int startPosition = source_.Position; NextChar(); // Skip start delimiter. while (current_ != delimiter) { if (current_ == CharSource.EOF || current_ == CharSource.NewLine) { return MakeToken(TokenKind.Invalid); } NextChar(); } NextChar(); // Skip end delimiter. int length = source_.Position - startPosition - 2; return MakeDataToken(TokenKind.String, startPosition, length); } private Token ScanIdentifier() { int startPosition = source_.Position; NextChar(); while (CharTable.IsIdentifierChar(current_)) { NextChar(); } int length = source_.Position - startPosition - 1; return MakeDataToken(TokenKind.Identifier, startPosition, length); } private Token ScanToken() { char letter = current_; while (true) { NextChar(); // Skip to next letter. if (letter == CharSource.EOF) { return MakeToken(TokenKind.EOF); } switch (letter) { case '\t': break; // Tab. case '\v': break; // Vertical tab. case '\f': break; // Form feed. case '\n': { line_++; lineStart_ = source_.Position + 1; return MakeToken(TokenKind.LineEnd); } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { // Found the start of a number. source_.GoBack(2); return ScanNumber(); } case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case '@': case '$': case '?': { // Found the start of an identifier or a keyword. source_.GoBack(2); return ScanIdentifier(); } case '\"': { // Found the start of a string. source_.GoBack(); return ScanString('\"'); } case '\'': { return MakeToken(TokenKind.Apostrophe); } case '(': { return MakeToken(TokenKind.OpenParen); } case ')': { return MakeToken(TokenKind.CloseParen); } case '[': { return MakeToken(TokenKind.OpenSquare); } case ']': { return MakeToken(TokenKind.CloseSquare); } case '{': { return MakeToken(TokenKind.OpenCurly); } case '}': { return MakeToken(TokenKind.CloseCurly); } case ':': { return MakeToken(TokenKind.Colon); } case ';': { return MakeToken(TokenKind.SemiColon); } case ',': { return MakeToken(TokenKind.Comma); } case '.': { return MakeToken(TokenKind.Dot); } case '&': { return MakeToken(TokenKind.And); } case '|': { return MakeToken(TokenKind.Or); } case '^': { return MakeToken(TokenKind.Xor); } case '<': { return MakeToken(TokenKind.Less); } case '>': { return MakeToken(TokenKind.Greater); } case '=': { return MakeToken(TokenKind.Equal); } case '+': { return MakeToken(TokenKind.Plus); } case '-': { return MakeToken(TokenKind.Minus); } case '*': { return MakeToken(TokenKind.Star); } case '/': { return MakeToken(TokenKind.Div); } case '~': { return MakeToken(TokenKind.Tilde); } case '!': { return MakeToken(TokenKind.Exclamation); } case '%': { return MakeToken(TokenKind.Percent); } case '#': { return MakeToken(TokenKind.Hash); } } letter = current_; } } private void Reset() { returnedTokens_.Clear(); line_ = 0; lineStart_ = 0; } } ================================================ FILE: src/ProfileExplorerCore/Lexer/Token.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Runtime.CompilerServices; namespace ProfileExplorer.Core.Lexer; // Definitions for token types. // Some tokens (identifier, string, number, etc.) have additional associated data. public enum TokenKind { Identifier, // -> Data Number, // -> Data String, // -> Data Char, // -> Data Plus, // + Minus, // - Star, // * Tilde, // ~ Equal, // = Exclamation, // ! Percent, // % And, // & Or, // | Xor, // ^ Less, // < Greater, // > Hash, // # (used by the preprocessor) Div, // / Colon, // : SemiColon, // ; Comma, // , Apostrophe, // ' Dot, // . Question, // ? OpenSquare, // [ CloseSquare, // ] OpenParen, // ( CloseParen, // ) OpenCurly, // { CloseCurly, // } LineEnd, // Found \n. EOF, // The end of the file was reached. Invalid, // The token could not be determined. Custom, // Used to mark a custom (optional) token. Keyword // All values after this one denote tokens. } public struct Token : IEquatable { public TokenKind Kind { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } public TextLocation Location { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } public ReadOnlyMemory Data { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Token(TokenKind kind, TextLocation location, int length) : this() { Kind = kind; Location = location; Length = length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsValid() { return Kind != TokenKind.EOF && Kind != TokenKind.Invalid; } // Returns true if the token describes and end-of-file situation. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsEOF() { return Kind == TokenKind.EOF; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsLineEnd() { return Kind == TokenKind.LineEnd; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsIdentifier() { return Kind == TokenKind.Identifier; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsNumber() { return Kind == TokenKind.Number; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsString() { return Kind == TokenKind.String; } // Returns true if the token represents an operator. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool IsOperator() { return (int)Kind >= (int)TokenKind.Plus && (int)Kind <= (int)TokenKind.Div; } public override string ToString() { string text = $"kind: {Kind}; location: {Location}; length: {Length}"; if (!Data.IsEmpty) { text += $"; data: {Data.Span.ToString()}"; } return text; } public bool Equals(Token other) { return Kind == other.Kind && Location.Equals(other.Location) && Length == other.Length; } public override bool Equals(object obj) { return obj is Token other && Equals(other); } public override int GetHashCode() { return HashCode.Combine((int)Kind, Location, Length); } public static bool operator ==(Token left, Token right) { return left.Equals(right); } public static bool operator !=(Token left, Token right) { return !left.Equals(right); } } ================================================ FILE: src/ProfileExplorerCore/Parser/IRSectionParser.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Lexer; namespace ProfileExplorer.Core.Parser; public interface IRSectionParser { void SkipCurrentToken(); void SkipToLineEnd(); void SkipToLineStart(); void SkipToNextBlock(); void SkipToFunctionEnd(); FunctionIR ParseSection(IRTextSection section, string sectionText); FunctionIR ParseSection(IRTextSection section, ReadOnlyMemory sectionText); } public interface IRParsingErrorHandler { IRSectionParser Parser { get; set; } bool HadParsingErrors { get; set; } List ParsingErrors { get; } bool HandleError(TextLocation location, TokenKind expectedToken, Token actualToken, string message = ""); } public class IRParsingError { public IRParsingError(TextLocation location, string error) { Location = location; Error = error; } public TextLocation Location { get; set; } public string Error { get; set; } public override string ToString() { return Error; } } ================================================ FILE: src/ProfileExplorerCore/Parser/ParserBase.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Lexer; namespace ProfileExplorer.Core.Parser; public class ParserBase { protected readonly Lexer.Lexer lexer_ = new(); private readonly Dictionary blockMap_ = new(); private readonly IRParsingErrorHandler errorHandler_; private readonly RegisterTable registerTable_; protected ICompilerIRInfo irInfo_; protected Token current_; protected Token previous_; protected IRTextSection section_; private IRElementId nextElementId_; private AssemblyMetadataTag metadataTag_; // Lazy-init. protected ParserBase(ICompilerIRInfo irInfo, IRParsingErrorHandler errorHandler, RegisterTable registerTable, IRTextSection section) { irInfo_ = irInfo; errorHandler_ = errorHandler; registerTable_ = registerTable; section_ = section; } protected RegisterTable RegisterTable => registerTable_; protected AssemblyMetadataTag MetadataTag => metadataTag_ ??= new AssemblyMetadataTag(); protected IRElementId NextElementId => nextElementId_; public bool IsDone() { return current_.IsEOF(); } public void SkipCurrentToken() { SkipToken(); } protected virtual void Reset() { nextElementId_ = IRElementId.FromLong(0); blockMap_.Clear(); metadataTag_ = null; } protected virtual void Initialize(string text) { lexer_.Initialize(text); } protected virtual void Initialize(ReadOnlyMemory text) { lexer_.Initialize(text); } protected void AddMetadata(FunctionIR function) { if (metadataTag_ != null) { function.AddTag(metadataTag_); } } protected void ReportError(TokenKind expectedToken, string message = "") { errorHandler_?.HandleError(current_.Location, expectedToken, current_, message); } protected void ReportErrorAndSkipLine(TokenKind expectedToken, string message) { ReportError(expectedToken, message); SkipToLineStart(); } protected BlockIR GetOrCreateBlock(int blockNumber, FunctionIR function) { if (blockMap_.TryGetValue(blockNumber, out var block)) { return block; } var blockId = NextElementId.NewBlock(blockNumber); var newBlock = new BlockIR(blockId, blockNumber, function); blockMap_[blockNumber] = newBlock; return newBlock; } protected int LocationDistance(Token startToken) { if (current_.Location.Offset != startToken.Location.Offset) { return previous_.Location.Offset - startToken.Location.Offset + previous_.Length; } return startToken.Length; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool TokenIntNumber(out int value) { return int.TryParse(TokenStringData(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool TokenLongIntNumber(out long value) { return long.TryParse(TokenStringData(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out value); } protected long? ParseHexAddress() { if (TokenLongHexNumber(out long value)) { SkipToken(); return value; } return null; } protected bool SkipHexNumber(int requiredLength = 0) { if (!IsNumber() && !IsIdentifier()) { return false; } if (IsHexNumber(TokenData().Span)) { // Check if the number has the required number of digits. if (requiredLength != 0 && TokenData().Length != requiredLength) { return false; } SkipToken(); return true; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool TokenLongHexNumber(out long value) { if (!IsNumber() && !IsIdentifier()) { value = 0; return false; } // Try to parse again as a HEX int. // Since a parsing failure is very expensive, first check if the token // could be a hex value and reject it early if it cannot be. try { var data = TokenData(); if (!IsHexNumber(data.Span)) { value = 0; return false; } value = Convert.ToInt64(TokenString(), 16); return true; } catch (Exception) { value = 0; return false; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool TokenFloatNumber(out double value) { return double.TryParse(TokenStringData(), NumberStyles.Any, CultureInfo.InvariantCulture, out value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected string TokenString() { return current_.Data.ToString(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected ReadOnlySpan TokenStringData() { return current_.Data.Span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected ReadOnlyMemory TokenData() { return current_.Data; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void SkipToken() { previous_ = current_; current_ = lexer_.NextToken(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool ExpectAndSkipToken(params TokenKind[] kind) { if (kind.Contains(current_.Kind)) { SkipToken(); return true; } return false; } protected bool SkipOptionalToken(TokenKind kind) { if (current_.Kind == kind) { SkipToken(); return true; } return false; } protected bool SkipToToken(TokenKind kind) { while (!IsLineEnd()) { if (TokenIs(kind)) { return true; } SkipToken(); } return false; } protected bool SkipToAnyToken(params TokenKind[] tokens) { while (!IsLineEnd()) { if (IsAnyToken(tokens)) { return true; } SkipToken(); } return false; } protected bool SkipAfterToken(TokenKind kind) { while (!IsLineEnd()) { if (TokenIs(kind)) { SkipToken(); return true; } SkipToken(); } return false; } protected void SkipToLineEnd() { while (!IsLineEnd()) { SkipToken(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected void SkipToLineStart() { SkipToLineEnd(); SkipToken(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsEOF() { return current_.IsEOF(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsLineEnd() { return current_.IsLineEnd() || current_.IsEOF(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsDot() { return current_.Kind == TokenKind.Dot; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsComma() { return current_.Kind == TokenKind.Comma; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsColon() { return current_.Kind == TokenKind.Colon; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsLess() { return current_.Kind == TokenKind.Less; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsEqual() { return current_.Kind == TokenKind.Equal; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsStar() { return current_.Kind == TokenKind.Star; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsHash() { return current_.Kind == TokenKind.Hash; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsIdentifier() { return current_.Kind == TokenKind.Identifier; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsNumber() { return current_.Kind == TokenKind.Number; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool TokenIs(TokenKind kind) { return current_.Kind == kind; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool IsAnyToken(params TokenKind[] tokens) { return Array.IndexOf(tokens, current_.Kind) != -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool NextTokenIs(TokenKind kind) { return lexer_.PeekToken().Kind == kind; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected bool NextAfterTokenIs(TokenKind kind) { return lexer_.PeekToken(2).Kind == kind; } protected void SetTextRange(IRElement element, Token startToken, int adjustment = 0) { int distance = Math.Max(0, LocationDistance(startToken) - adjustment); element.SetTextRange(startToken.Location, distance); } protected void SetTextRange(IRElement element, Token startToken, Token endToken, int adjustment = 0) { int distance = Math.Max(0, endToken.Location.Offset - startToken.Location.Offset + endToken.Length - adjustment); element.SetTextRange(startToken.Location, distance); } protected void SetTextRange(IRElement element) { element.SetTextRange(current_.Location, current_.Length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private bool IsHexLetter(char c) { return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' || c == 'x' || c == 'X'; } private bool IsHexNumber(ReadOnlySpan span) { for (int i = 0; i < span.Length; i++) { if (!IsHexLetter(span[i])) { return false; } } return true; } } ================================================ FILE: src/ProfileExplorerCore/Parser/ParsingErrorHandler.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.Lexer; namespace ProfileExplorer.Core.Parser; public class ParsingErrorHandler : IRParsingErrorHandler { public ParsingErrorHandler() { ParsingErrors = new List(); } public bool ThrowOnError { get; set; } public IRSectionParser Parser { get; set; } public bool HadParsingErrors { get; set; } public List ParsingErrors { get; set; } public bool HandleError(TextLocation location, TokenKind expectedToken, Token actualToken, string message = "") { var builder = new StringBuilder(); if (!string.IsNullOrEmpty(message)) { builder.AppendLine(message); } builder.AppendLine($"Location: {location}"); builder.AppendLine($"Expected token: {expectedToken}"); builder.Append($"Actual token: {actualToken}"); if (ThrowOnError) { throw new InvalidOperationException($"IR parsing error:\n{builder}"); } ParsingErrors.Add(new IRParsingError(location, builder.ToString())); HadParsingErrors = true; return true; // Always continue parsing. } } ================================================ FILE: src/ProfileExplorerCore/Profile/CallTree/ProfileCallSite.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; namespace ProfileExplorer.Core.Profile.CallTree; public class ProfileCallSite : IEquatable { public ProfileCallSite(long rva) { Targets = new List<(ProfileCallTreeNode NodeId, TimeSpan Weight)>(); RVA = rva; Weight = TimeSpan.Zero; } public long RVA { get; set; } public TimeSpan Weight { get; set; } //? TODO: Consider using TinyList public List<(ProfileCallTreeNode Node, TimeSpan Weight)> Targets { get; set; } public List<(ProfileCallTreeNode Node, TimeSpan Weight)> SortedTargets { get { if (!HasSingleTarget) { Targets.Sort((a, b) => b.Weight.CompareTo(a.Weight)); } return Targets; } } public bool HasSingleTarget => Targets.Count == 1; public bool Equals(ProfileCallSite other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return RVA == other.RVA; } public static bool operator ==(ProfileCallSite left, ProfileCallSite right) { return Equals(left, right); } public static bool operator !=(ProfileCallSite left, ProfileCallSite right) { return !Equals(left, right); } public double ScaleWeight(TimeSpan weight) { return weight.Ticks / (double)Weight.Ticks; } public void AddTarget(ProfileCallTreeNode node, TimeSpan weight) { Weight += weight; // Total weight of targets. int index = -1; // Don't use FindIndex because it allocates a lambda on each invocation. for (int i = 0; i < Targets.Count; i++) { if (Targets[i].Node.Equals(node.Function)) { index = i; break; } } if (index != -1) { var span = CollectionsMarshal.AsSpan(Targets); span[index].Weight += weight; // Modify in-place per-target weight. } else { Targets.Add((node, weight)); } } public void MergeWith(ProfileCallSite otherCallSite) { Weight += otherCallSite.Weight; foreach (var target in otherCallSite.Targets) { AddTarget(target.Node, target.Weight); } } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((ProfileCallSite)obj); } public override int GetHashCode() { return RVA.GetHashCode(); } public override string ToString() { return $"RVA: {RVA}, Weight: {Weight.TotalMilliseconds}, Targets: {Targets.Count}"; } } ================================================ FILE: src/ProfileExplorerCore/Profile/CallTree/ProfileCallTree.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Threading; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.CallTree; public enum ProfileCallTreeNodeKind { Unset = 0, NativeUser = 1, NativeKernel = 2, Managed = 3 } public sealed class ProfileCallTree { private ConcurrentDictionary rootNodes_; private Dictionary> funcToNodesMap_; private Dictionary nodeIdMap_; private int nextNodeId_; public ProfileCallTree(int startId = 0) { nextNodeId_ = startId; InitializeReferenceMembers(); } public List RootNodes => rootNodes_.ToValueList(); public TimeSpan TotalRootNodesWeight { get { var sum = TimeSpan.Zero; foreach (var node in rootNodes_) { sum += node.Value.Weight; } return sum; } } public void UpdateCallTree(ref ProfileSample sample, ResolvedProfileStack resolvedStack) { // Build call tree. Note that the call tree methods themselves are thread-safe. bool isRootFrame = true; ProfileCallTreeNode prevNode = null; ResolvedProfileStackFrame prevFrame = null; var sampleWeight = sample.Weight; for (int k = resolvedStack.FrameCount - 1; k >= 0; k--) { var resolvedFrame = resolvedStack.StackFrames[k]; if (resolvedFrame.FrameRVA == 0 && resolvedFrame.FrameDetails.DebugInfo == null) { continue; } ProfileCallTreeNode node = null; if (isRootFrame) { node = AddRootNode(resolvedFrame.FrameDetails.DebugInfo, resolvedFrame.FrameDetails.Function); isRootFrame = false; } else { node = AddChildNode(prevNode, resolvedFrame.FrameDetails.DebugInfo, resolvedFrame.FrameDetails.Function); prevNode.AddCallSite(node, prevFrame.FrameRVA, sampleWeight); } node.AccumulateWeight(sampleWeight); node.AccumulateWeight(sampleWeight, TimeSpan.Zero, resolvedStack.Context.ThreadId); // Set the user/kernel-mode context of the function. if (node.Kind == ProfileCallTreeNodeKind.Unset) { if (resolvedFrame.FrameDetails.IsKernelCode) { node.Kind = ProfileCallTreeNodeKind.NativeKernel; } else if (resolvedFrame.FrameDetails.IsManagedCode) { node.Kind = ProfileCallTreeNodeKind.Managed; } else { node.Kind = ProfileCallTreeNodeKind.NativeUser; } } //node.RecordSample(sample, resolvedFrame); //? Remove prevNode = node; prevFrame = resolvedFrame; } // Last function on the stack gets the exclusive weight. if (prevNode != null) { prevNode.AccumulateExclusiveWeight(sampleWeight); prevNode.AccumulateWeight(TimeSpan.Zero, sampleWeight, resolvedStack.Context.ThreadId); } } private ProfileCallTreeNode AddRootNode(FunctionDebugInfo funcInfo, IRTextFunction function) { if (rootNodes_.TryGetValue(function, out var existingNode)) { return existingNode; } var node = rootNodes_.GetOrAdd(function, static (func, info) => new ProfileCallTreeNode(info, func), funcInfo); RegisterFunctionTreeNode(node); return node; } private ProfileCallTreeNode AddChildNode(ProfileCallTreeNode node, FunctionDebugInfo funcInfo, IRTextFunction function) { (var childNode, bool isNewNode) = node.AddChild(funcInfo, function); if (isNewNode) { RegisterFunctionTreeNode(childNode); } return childNode; } private void RegisterFunctionTreeNode(ProfileCallTreeNode node) { // Add an unique instance of the node for a function. node.Id = Interlocked.Increment(ref nextNodeId_); ref var nodeList = ref CollectionsMarshal.GetValueRefOrAddDefault(funcToNodesMap_, node.Function, out bool exists); if (!exists) { nodeList = new List(); } nodeList.Add(node); } public ProfileCallTreeNode FindNode(long nodeId) { // Build mapping on-demand. if (nodeIdMap_ == null) { if (nodeIdMap_ == null) { nodeIdMap_ = new Dictionary(funcToNodesMap_.Count); foreach (var list in funcToNodesMap_.Values) { foreach (var node in list) { nodeIdMap_[node.Id] = node; } } } } return nodeIdMap_.GetValueOrNull(nodeId); } public ProfileCallTreeNode FindMatchingNode(ProfileCallTreeNode queryNode) { // Find in the call tree node that corresponds to // a node from another instance of a call tree. if (queryNode.IsGroup) { return null; } if (!funcToNodesMap_.TryGetValue(queryNode.Function, out var nodeList)) { return null; } foreach (var node in nodeList) { if (ReferenceEquals(node, queryNode)) { return node; // Shortcut for same call tree instance. } // Since the IRTextFunctions remain stable across a session, // check the equivalence of the nodes by looking at the // function in each stack frame (parent) up to the root. var nodeA = node; var nodeB = queryNode; while (nodeA != null && nodeB != null) { if (!nodeA.Function.Equals(nodeB.Function)) { break; } nodeA = nodeA.Caller; nodeB = nodeB.Caller; } if (nodeA == null && nodeB == null) { return node; // Reached root from both nodes. } } return null; } public List GetCallTreeNodes(IRTextFunction function) { if (funcToNodesMap_.TryGetValue(function, out var nodeList)) { return nodeList; } return new List(); } public List GetSortedCallTreeNodes(IRTextFunction function) { var nodeList = GetCallTreeNodes(function); if (nodeList.Count < 2) { return nodeList; } // Make a copy of the list since it's shared with all other instances // of the node and it may be iterated on another thread, sorting may // modify the list which invalidates iteration and throws. var nodeListCopy = new List(nodeList); nodeListCopy.Sort((a, b) => b.Weight.CompareTo(a.Weight)); return nodeListCopy; } public ProfileCallTreeNode GetCombinedCallTreeNode(IRTextFunction function, ProfileCallTreeNode parentNode = null) { var nodes = GetSortedCallTreeNodes(function); return CombinedCallTreeNodesImpl(nodes, true, parentNode); } public static ProfileCallTreeNode CombinedCallTreeNodes(List nodes, bool combineLists = true) { var nodeListCopy = new List(nodes); nodeListCopy.Sort((a, b) => b.Weight.CompareTo(a.Weight)); return CombinedCallTreeNodesImpl(nodeListCopy, combineLists); } public static TimeSpan CombinedCallTreeNodesWeight(List nodes) { if (nodes.Count == 0) { return TimeSpan.Zero; } var combinedNode = CombinedCallTreeNodes(nodes, false); return combinedNode.Weight; } private static ProfileCallTreeNode CombinedCallTreeNodesImpl(List nodes, bool combineLists = true, ProfileCallTreeNode parentNode = null) { if (nodes == null || nodes.Count == 0) { return new ProfileCallTreeGroupNode(); } if (nodes.Count == 1) { return nodes[0]; } // Sort by weight so that parent nodes (more inclusive time) // get processed first and have the recursive instances ignored. var handledNodes = new HashSet(); var comparer = new ProfileCallTreeNodeComparer(); var childrenSet = new HashSet(comparer); var callersSet = new HashSet(comparer); var callSiteMap = new Dictionary(); var threadsMap = new Dictionary(); var weight = TimeSpan.Zero; var excWeight = TimeSpan.Zero; var kind = ProfileCallTreeNodeKind.Unset; foreach (var node in nodes) { // In case of recursive functions, the total time // should not be counted again for the recursive calls. // When the function is a callee, consider only the nodes that are actually being called // by the parent node - by default the list contains every node representing the function, // on all paths through the call tree. if (parentNode != null && !node.HasParent(parentNode, comparer)) { continue; } // If the node is being called by another // instance recursively which has its total time counted, // don't count the total time of this instance. bool countWeight = !NodeParentWasHandled(node, handledNodes); if (countWeight) { weight += node.Weight; handledNodes.Add(node); } excWeight += node.ExclusiveWeight; kind = node.Kind; if (!combineLists) { continue; } // Sum up per-thread weights. if (node.HasThreadWeights) { foreach (var pair in node.ThreadWeights) { threadsMap.AccumulateValue(pair.Key, countWeight ? pair.Value.Weight : TimeSpan.Zero, pair.Value.ExclusiveWeight); } } if (node.HasChildren) { foreach (var childNode in node.Children) { if (!childrenSet.TryGetValue(childNode, out var existingNode)) { existingNode = new ProfileCallTreeNode(childNode.FunctionDebugInfo, childNode.Function); existingNode.Id = childNode.Id; childrenSet.Add(existingNode); } existingNode.AccumulateWeight(childNode.Weight); existingNode.AccumulateExclusiveWeight(childNode.ExclusiveWeight); } } if (node.HasCallers) { void HandleCaller(ProfileCallTreeNode caller) { if (!callersSet.TryGetValue(caller, out var existingNode)) { existingNode = new ProfileCallTreeNode(caller.FunctionDebugInfo, caller.Function); existingNode.Id = caller.Id; callersSet.Add(existingNode); } existingNode.AccumulateWeight(caller.Weight); existingNode.AccumulateExclusiveWeight(caller.ExclusiveWeight); } if (node is ProfileCallTreeGroupNode groupNode) { foreach (var caller in groupNode.Callers) { HandleCaller(caller); } } else { HandleCaller(node.Caller); } } if (node.HasCallSites) { foreach (var pair in node.CallSites) { ref var callsite = ref CollectionsMarshal.GetValueRefOrAddDefault(callSiteMap, pair.Key, out bool exists); if (!exists) { callsite = new ProfileCallSite(pair.Key); } foreach (var target in pair.Value.Targets) { callsite.AddTarget(target.Node, target.Weight); } } } } return new ProfileCallTreeGroupNode(nodes[0].FunctionDebugInfo, nodes[0].Function, nodes, childrenSet.ToList(), callersSet.ToList(), callSiteMap, threadsMap) { Weight = weight, ExclusiveWeight = excWeight, Kind = kind }; } private static bool NodeParentWasHandled(ProfileCallTreeNode node, HashSet handledNodes) { if (!node.IsGroup) { var callerNode = node.Caller; while (callerNode != null) { if (handledNodes.Contains(callerNode)) { return true; } callerNode = callerNode.Caller; } } return false; } public TimeSpan GetCombinedCallTreeNodeWeight(IRTextFunction function) { var nodes = GetCallTreeNodes(function); if (nodes == null) { return TimeSpan.Zero; } var combinedNode = CombinedCallTreeNodesImpl(nodes, false); return combinedNode.Weight; } public List GetBacktrace(ProfileCallTreeNode node) { var list = new List(); // For multiple node groups there is no proper backtrace. if (node is ProfileCallTreeGroupNode groupNode && groupNode.Nodes.Count > 1) { return list; } while (node.HasCallers) { list.Add(node.Callers[0]); node = node.Callers[0]; } return list; } public List GetTopFunctions(ProfileCallTreeNode node) { return GetTopFunctionsAndModules(node).Functions; } public List GetTopModules(ProfileCallTreeNode node) { return GetTopFunctionsAndModules(node).Modules; } public (List Functions, List Modules) GetTopFunctionsAndModules(ProfileCallTreeNode node) { var moduleMap = new Dictionary(); var funcMap = new Dictionary(); if (node is ProfileCallTreeGroupNode groupNode) { foreach (var nestedNode in groupNode.Nodes) { CollectFunctionsAndModules(nestedNode, funcMap, moduleMap); } } else { CollectFunctionsAndModules(node, funcMap, moduleMap); } // In case of recursive functions, the total time // should not be counted again for the recursive calls. var handledNodes = new HashSet(); foreach (var collectedNode in funcMap.Values) { var collectedGroupNode = collectedNode as ProfileCallTreeGroupNode; if (collectedGroupNode.Nodes.Count == 1) { collectedGroupNode.Weight = collectedGroupNode.Nodes[0].Weight; collectedGroupNode.ExclusiveWeight = collectedGroupNode.Nodes[0].ExclusiveWeight; } else if (collectedGroupNode.Nodes.Count > 1) { collectedGroupNode.Nodes.Sort((a, b) => b.Weight.CompareTo(a.Weight)); handledNodes.Clear(); foreach (var instanceNode in collectedGroupNode.Nodes) { // If the node is being called by another // instance recursively which has its total time counted, // don't count the total time of this instance. bool countWeight = !NodeParentWasHandled(node, handledNodes); collectedGroupNode.ExclusiveWeight += instanceNode.ExclusiveWeight; if (countWeight) { collectedGroupNode.Weight += instanceNode.Weight; handledNodes.Add(instanceNode); } } } } // Compute time percentage per module. var moduleList = new List(moduleMap.Count); foreach (var module in moduleMap.Values) { module.Percentage = node.ScaleWeight(module.Weight); moduleList.Add(module); } moduleList.Sort((a, b) => b.Weight.CompareTo(a.Weight)); var funcList = funcMap.ToValueList(); funcList.Sort((a, b) => b.ExclusiveWeight.CompareTo(a.ExclusiveWeight)); return (funcList, moduleList); } private void CollectFunctionsAndModules(ProfileCallTreeNode node, Dictionary funcMap, Dictionary moduleMap) { // Combine all instances of a function under the node. ref var entry = ref CollectionsMarshal.GetValueRefOrAddDefault(funcMap, node.Function, out bool exists); if (!exists) { entry = new ProfileCallTreeGroupNode(node.FunctionDebugInfo, node.Function, node.Kind); } var groupEntry = (ProfileCallTreeGroupNode)entry; groupEntry.Nodes.Add(node); //groupEntry.AccumulateWeight(node.Weight); //groupEntry.AccumulateExclusiveWeight(node.ExclusiveWeight); // Collect time and functions per module. ref var moduleEntry = ref CollectionsMarshal.GetValueRefOrAddDefault(moduleMap, node.ModuleName, out bool moduleExists); if (!moduleExists) { moduleEntry = new ModuleProfileInfo(node.ModuleName); } moduleEntry.Weight += node.ExclusiveWeight; moduleEntry.Functions.Add(groupEntry); if (node.HasChildren) { foreach (var childNode in node.Children) { CollectFunctionsAndModules(childNode, funcMap, moduleMap); } } } public void MergeWith(ProfileCallTree otherTree) { // Recursively merge the common root nodes // and copy over any new root nodes. foreach (var rootNode in otherTree.rootNodes_) { if (rootNodes_.TryGetValue(rootNode.Key, out var existingRootNode)) { existingRootNode.MergeWith(rootNode.Value); } else { rootNodes_[rootNode.Key] = rootNode.Value; } } // Merge the other data structures. if (otherTree.funcToNodesMap_ != null) { funcToNodesMap_ ??= new Dictionary>(); var existingNodesSet = new HashSet(); foreach (var list in funcToNodesMap_.Values) { foreach (var node in list) { existingNodesSet.Add(node); } } foreach (var pair in otherTree.funcToNodesMap_) { ref var existingList = ref CollectionsMarshal.GetValueRefOrAddDefault(funcToNodesMap_, pair.Key, out bool exists); if (exists) { // A function present in both tree, add the nodes that are missing. foreach (var node in pair.Value) { if (!node.IsMergeNode() && !existingNodesSet.Contains(node)) { existingList.Add(node); } node.ClearIsMergedNode(); } } else { // A function present only in the other tree. existingList = pair.Value; } } } if (otherTree.nodeIdMap_ != null) { nodeIdMap_ ??= new Dictionary(); foreach (var pair in otherTree.nodeIdMap_) { nodeIdMap_[pair.Key] = pair.Value; } } } public string Print() { var builder = new StringBuilder(); foreach (var node in rootNodes_) { builder.AppendLine("Call tree root node"); builder.AppendLine("-----------------------"); node.Value.Print(builder); } return builder.ToString(); } public void VerifyCycles() { var nodeMap = new HashSet(); foreach (var node in rootNodes_) { nodeMap.Clear(); VerifyCycles(node.Value, nodeMap); } } private void VerifyCycles(ProfileCallTreeNode node, HashSet nodeMap) { if (!nodeMap.Add(node)) { Trace.WriteLine($"Found cycle in CallTree for node {node}"); Debug.Assert(false); return; } if (node.HasChildren) { foreach (var childNode in node.Children) { VerifyCycles(childNode, nodeMap); } } } public string PrintNodeInstances(string funcName, bool printStack = false) { var list = new List(); foreach (var pair in rootNodes_) { CollectNodeInstances(pair.Value, funcName, list); } list.Sort((a, b) => b.Weight.CompareTo(a.Weight)); var weight = TimeSpan.Zero; var excWeight = TimeSpan.Zero; foreach (var node in list) { weight += node.Weight; excWeight += node.ExclusiveWeight; } var sb = new StringBuilder(); sb.AppendLine($"Instances for {funcName}: {list.Count}"); sb.AppendLine( $" - Total weight: {weight} ({weight.TotalMilliseconds} ms), excl weight: {excWeight} ({excWeight.TotalMilliseconds} ms)"); foreach (var node in list) { sb.AppendLine( $" - Weight: {node.Weight} ({node.Weight.TotalMilliseconds} ms), excl weight: {node.ExclusiveWeight} ({node.ExclusiveWeight.TotalMilliseconds} ms), children: {(node.HasChildren ? node.Children.Count : 0)}"); weight += node.Weight; excWeight += node.ExclusiveWeight; if (printStack) { sb.AppendLine(" - Stack:"); var stackNode = node; int index = 0; while (stackNode != null) { sb.AppendLine($" {index}: {stackNode.FunctionName}"); stackNode = stackNode.Caller; index++; } sb.AppendLine($" ------------------------------"); } } return sb.ToString(); } public void CollectNodeInstances(ProfileCallTreeNode node, string funcName, List list) { if (node.FunctionName.Equals(funcName, StringComparison.Ordinal)) { list.Add(node); } if (node.HasChildren) { foreach (var child in node.Children) { CollectNodeInstances(child, funcName, list); } } } public override string ToString() { return $"Root nodes: {rootNodes_.Count}, Weight: {TotalRootNodesWeight}"; } private void InitializeReferenceMembers() { rootNodes_ ??= new ConcurrentDictionary(); funcToNodesMap_ ??= new Dictionary>(); } public void ResetTags() { foreach (var list in funcToNodesMap_.Values) { foreach (var node in list) { node.Tag = null; } } } public ProfileCallTreeNode FindRootNode(IRTextFunction func) { if (rootNodes_.TryGetValue(func, out var node)) { return node; } return null; } } ================================================ FILE: src/ProfileExplorerCore/Profile/CallTree/ProfileCallTreeNode.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Collections; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.CallTree; public class ProfileCallTreeNode : IEquatable { private static readonly object MergedNodeTag = new(); public int Id { get; set; } public IRTextFunction Function { get; set; } public ProfileCallTreeNodeKind Kind { get; set; } private TinyList children_; private ProfileCallTreeNode caller_; // Can't be serialized, reconstructed. public FunctionDebugInfo FunctionDebugInfo { get; set; } //? TODO: Replace Threads dict and CallSites with a TinyDictionary-like data struct //? like TinyList, also consider DictionarySlim instead of Dictionary from //? https://github.com/dotnet/corefxlab/blob/archive/src/Microsoft.Experimental.Collections/Microsoft/Collections/Extensions/DictionarySlim public Dictionary CallSites { get; set; } public Dictionary ThreadWeights { get; set; } public TimeSpan Weight { get; set; } public TimeSpan ExclusiveWeight { get; set; } public object Tag { get; set; } public virtual List Nodes => new() {this}; public IList Children => children_; public virtual List Callers => new() {caller_}; #if DEBUG public ProfileCallTreeNode Caller => !IsGroup ? caller_ : throw new InvalidOperationException("For group use Callers"); #else public ProfileCallTreeNode Caller => caller_; #endif public virtual bool IsGroup => false; public bool HasChildren => Children != null && Children.Count > 0; public virtual bool HasCallers => caller_ != null; public bool HasCallSites => CallSites != null && CallSites.Count > 0; public bool HasThreadWeights => ThreadWeights != null && ThreadWeights.Count > 0; public bool HasFunction => Function != null; public string FunctionName => Function.Name; public string ModuleName => Function.ModuleName; public double ScaleWeight(TimeSpan relativeWeigth) { return relativeWeigth.Ticks / (double)Weight.Ticks; } public (TimeSpan Weight, TimeSpan ExclusiveWeight) ChildrenWeight { get { var weight = TimeSpan.Zero; var exclusiveWeight = TimeSpan.Zero; if (!HasChildren) { return (weight, exclusiveWeight); } foreach (var child in Children) { weight += child.Weight; exclusiveWeight += child.ExclusiveWeight; } return (weight, exclusiveWeight); } } protected ProfileCallTreeNode() { } public ProfileCallTreeNode(FunctionDebugInfo funcInfo, IRTextFunction function, List children = null, ProfileCallTreeNode caller = null, Dictionary callSites = null, Dictionary threadWeights = null) { FunctionDebugInfo = funcInfo; Function = function; ThreadWeights = threadWeights ?? new Dictionary(); children_ = new TinyList(children); caller_ = caller; CallSites = callSites; } public void AccumulateWeight(TimeSpan weight) { Weight += weight; } public void AccumulateWeight(TimeSpan weight, TimeSpan exclusiveWeight, int threadId) { ThreadWeights.AccumulateValue(threadId, weight, exclusiveWeight); } public List<(int ThreadId, (TimeSpan Weight, TimeSpan ExclusiveWeight) Values)> SortedByWeightPerThreadWeights { get { var list = ThreadWeights.ToList(); list.Sort((a, b) => b.Item2.Weight.CompareTo(a.Item2.Weight)); return list; } } public List<(int ThreadId, (TimeSpan Weight, TimeSpan ExclusiveWeight) Values)> SortedByIdPerThreadWeights { get { var list = ThreadWeights.ToList(); list.Sort((a, b) => a.Item1.CompareTo(b.Item1)); return list; } } public void AccumulateExclusiveWeight(TimeSpan weight) { ExclusiveWeight += weight; } public (ProfileCallTreeNode, bool) AddChild(FunctionDebugInfo functionDebugInfo, IRTextFunction function) { return GetOrCreateChildNode(functionDebugInfo, function); } public bool HasChild(ProfileCallTreeNode node) { return children_.Contains(node); } public ProfileCallTreeNode FindChildNode(IRTextFunction function) { return children_.Find(node => node.Function == function); } internal void SetChildrenNoLock(List children) { // Used by ProfileCallTree.Deserialize. children_ = new TinyList(children); } internal void SetParent(ProfileCallTreeNode parentNode) { // Used by ProfileCallTree.Deserialize. caller_ = parentNode; } public bool HasParent(ProfileCallTreeNode parentNode, ProfileCallTreeNodeComparer comparer) { return caller_ != null && comparer.Equals(caller_, parentNode); } private (ProfileCallTreeNode, bool) GetOrCreateChildNode(FunctionDebugInfo functionDebugInfo, IRTextFunction function) { var childNode = FindExistingNode(functionDebugInfo, function); if (childNode != null) { return (childNode, false); } childNode = new ProfileCallTreeNode(functionDebugInfo, function, null, this); children_.Add(childNode); return (childNode, true); } public void AddCallSite(ProfileCallTreeNode childNode, long rva, TimeSpan weight) { CallSites ??= new Dictionary(); ref var callsite = ref CollectionsMarshal.GetValueRefOrAddDefault(CallSites, rva, out bool exists); if (!exists) { callsite = new ProfileCallSite(rva); } callsite.AddTarget(childNode, weight); } private ProfileCallTreeNode FindExistingNode(FunctionDebugInfo functionDebugInfo, IRTextFunction function) { for (int i = 0; i < children_.Count; i++) { var child = children_[i]; if (child.Equals(function)) { return child; } } return null; } public void MergeWith(ProfileCallTreeNode otherNode) { // Accumulate the weights and merge all data structures, // then recursively merge the common child nodes // and copy over any new child nodes. otherNode.Tag = MergedNodeTag; // Mark node as merged to be discarded later. Weight += otherNode.Weight; ExclusiveWeight += otherNode.ExclusiveWeight; if (otherNode.HasCallSites) { CallSites ??= new Dictionary(); foreach (var callSite in otherNode.CallSites) { ref var existingCallSite = ref CollectionsMarshal.GetValueRefOrAddDefault(CallSites, callSite.Key, out bool exists); if (!exists) { existingCallSite = callSite.Value; } else { existingCallSite.MergeWith(callSite.Value); } } } if (otherNode.HasThreadWeights) { ThreadWeights ??= new Dictionary(); foreach (var threadWeight in otherNode.ThreadWeights) { AccumulateWeight(threadWeight.Value.Weight, threadWeight.Value.ExclusiveWeight, threadWeight.Key); } } if (otherNode.HasChildren) { foreach (var child in otherNode.children_) { var existingChild = FindChildNode(child.Function); if (existingChild != null) { // Recursively merge child nodes. existingChild.MergeWith(child); } else { // Copy over the child from the other node. children_.Add(child); } } } } public bool IsMergeNode() { return Tag == MergedNodeTag; } public void ClearIsMergedNode() { Tag = null; } internal void Print(StringBuilder builder, int level = 0, bool caller = false) { builder.Append(new string(' ', level * 4)); builder.AppendLine($"{FunctionDebugInfo.Name}, RVA {FunctionDebugInfo.RVA}, Id {Id}"); builder.Append(new string(' ', level * 4)); builder.AppendLine($" weight {Weight.TotalMilliseconds}"); builder.Append(new string(' ', level * 4)); builder.AppendLine($" exc weight {ExclusiveWeight.TotalMilliseconds}"); builder.Append(new string(' ', level * 4)); builder.AppendLine($" callees: {(Children != null ? Children.Count : 0)}"); if (Children != null && !caller) { foreach (var child in Children) { child.Print(builder, level + 1); } } } public bool Equals(IRTextFunction function) { return Function.Equals(function); } public bool Equals(ProfileCallTreeNode other) { if (ReferenceEquals(null, other)) { return false; } // Note that this holds only for nodes // belonging to the same ProfileCallTree instance. return Id == other.Id; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((ProfileCallTreeNode)obj); } public override int GetHashCode() { return Id.GetHashCode(); } public static bool operator ==(ProfileCallTreeNode left, ProfileCallTreeNode right) { return Equals(left, right); } public static bool operator !=(ProfileCallTreeNode left, ProfileCallTreeNode right) { return !Equals(left, right); } public override string ToString() { return $"Name: {FunctionDebugInfo?.Name}\n" + $"RVA {FunctionDebugInfo.RVA}, Id {Id}\n" + $"Weight: {Weight}\n" + $"ExclusiveWeight: {ExclusiveWeight}\n" + $"Children: {Children?.Count ?? 0}\n" + $"CallSites: {CallSites?.Count ?? 0}"; } public ProfileCallTreeNode Clone() { return new ProfileCallTreeNode { Id = Id, Kind = Kind, Function = Function, FunctionDebugInfo = FunctionDebugInfo, Weight = Weight, ExclusiveWeight = ExclusiveWeight, children_ = children_, caller_ = caller_, CallSites = CallSites }; } } public sealed class ProfileCallTreeGroupNode : ProfileCallTreeNode { private List nodes_; private List callers_; public ProfileCallTreeGroupNode() { } public ProfileCallTreeGroupNode(FunctionDebugInfo funcInfo, IRTextFunction function, List nodes = null, List children = null, List callers = null, Dictionary callSites = null, Dictionary threadWeights = null) : base(funcInfo, function, children, null, callSites, threadWeights) { nodes_ = nodes ?? new List(); callers_ = callers ?? new List(); } public ProfileCallTreeGroupNode(FunctionDebugInfo funcInfo, IRTextFunction function, ProfileCallTreeNodeKind kind) : base(funcInfo, function) { nodes_ = new List(); Kind = kind; } public ProfileCallTreeGroupNode(ProfileCallTreeNode baseNode, TimeSpan weight) : this(baseNode.FunctionDebugInfo, baseNode.Function) { nodes_.Add(baseNode); Weight = weight; } public override bool IsGroup => true; public override List Nodes => nodes_; public override List Callers => callers_; public override bool HasCallers => callers_ != null && callers_.Count > 0; public override string ToString() { return $"{FunctionDebugInfo.Name}, RVA {FunctionDebugInfo.RVA}, Id {Id}, Nodes: {nodes_.Count}"; } } // Comparer used for the root nodes in order to ignore the ID part. public class ProfileCallTreeNodeComparer : IEqualityComparer { public bool Equals(ProfileCallTreeNode x, ProfileCallTreeNode y) { return x.Equals(y.Function); } public int GetHashCode(ProfileCallTreeNode obj) { return HashCode.Combine(obj.Function); } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/FunctionProfileData.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Data; public class FunctionProfileData { public FunctionProfileData() { InstructionWeight = new Dictionary(); SampleStartIndex = int.MaxValue; SampleEndIndex = int.MinValue; } public FunctionProfileData(FunctionDebugInfo debugInfo) : this() { FunctionDebugInfo = debugInfo; } public TimeSpan Weight { get; set; } public TimeSpan ExclusiveWeight { get; set; } public Dictionary InstructionWeight { get; set; } // Instr. offset mapping public Dictionary InstructionCounters { get; set; } public FunctionDebugInfo FunctionDebugInfo { get; set; } public int SampleStartIndex { get; set; } public int SampleEndIndex { get; set; } public bool HasPerformanceCounters => InstructionCounters is {Count: > 0}; public void MergeWith(FunctionProfileData otherData) { Weight += otherData.Weight; ExclusiveWeight += otherData.ExclusiveWeight; SampleStartIndex = Math.Min(SampleStartIndex, otherData.SampleStartIndex); SampleEndIndex = Math.Max(SampleEndIndex, otherData.SampleEndIndex); foreach (var pair in otherData.InstructionWeight) { ref var existingValue = ref CollectionsMarshal.GetValueRefOrAddDefault(InstructionWeight, pair.Key, out bool exists); existingValue += pair.Value; } if (otherData.HasPerformanceCounters) { InstructionCounters ??= new Dictionary(); foreach (var pair in otherData.InstructionCounters) { ref var existingValue = ref CollectionsMarshal.GetValueRefOrAddDefault(InstructionCounters, pair.Key, out bool exists); if (exists) { existingValue.Add(pair.Value); } else { existingValue = pair.Value; } } } } public static bool TryFindElementForOffset(AssemblyMetadataTag metadataTag, long offset, ICompilerIRInfo ir, out IRElement element) { var offsetData = ir.InstructionOffsetData; int multiplier = offsetData.InitialMultiplier; do { long candidateOffset = Math.Max(0, offset - multiplier * offsetData.OffsetAdjustIncrement); if (metadataTag.OffsetToElementMap.TryGetValue(candidateOffset, out element)) { return true; } ++multiplier; } while (multiplier * offsetData.OffsetAdjustIncrement < offsetData.MaxOffsetAdjust); return false; } public void AddCounterSample(long instrOffset, int perfCounterId, long value) { InstructionCounters ??= new Dictionary(); var counterSet = InstructionCounters.GetOrAddValue(instrOffset); counterSet.AddCounterSample(perfCounterId, value); } public void AddInstructionSample(long instrOffset, TimeSpan weight) { if (InstructionWeight.TryGetValue(instrOffset, out var currentWeight)) { InstructionWeight[instrOffset] = currentWeight + weight; } else { InstructionWeight[instrOffset] = weight; } } public double ScaleWeight(TimeSpan weight) { return weight.Ticks / (double)Weight.Ticks; } public FunctionProcessingResult Process(FunctionIR function, ICompilerIRInfo ir) { var metadataTag = function.GetTag(); bool hasInstrOffsetMetadata = metadataTag != null && metadataTag.OffsetToElementMap.Count > 0; if (!hasInstrOffsetMetadata) { return null; } var result = new FunctionProcessingResult(metadataTag.OffsetToElementMap.Count); foreach (var pair in InstructionWeight) { if (TryFindElementForOffset(metadataTag, pair.Key, ir, out var element)) { result.SampledElements.Add((element, pair.Value)); result.BlockSampledElementsMap.AccumulateValue(element.ParentBlock, pair.Value); } } if (HasPerformanceCounters) { foreach (var pair in InstructionCounters) { if (TryFindElementForOffset(metadataTag, pair.Key, ir, out var element)) { result.CounterElements.Add((element, pair.Value)); } result.FunctionCountersValue.Add(pair.Value); } } result.BlockSampledElements = result.BlockSampledElementsMap.ToList(); result.SortSampledElements(); return result; } public SourceLineProcessingResult ProcessSourceLines(IDebugInfoProvider debugInfo, ICompilerIRInfo ir, SourceStackFrame inlinee = null) { var result = new SourceLineProcessingResult(); int firstLine = int.MaxValue; int lastLine = int.MinValue; var offsetData = ir.InstructionOffsetData; var firstLineInfo = debugInfo.FindSourceLineByRVA(FunctionDebugInfo.RVA); if (!firstLineInfo.IsUnknown) { firstLine = firstLineInfo.Line; } var lastLineInfo = debugInfo.FindSourceLineByRVA(FunctionDebugInfo.EndRVA); if (!lastLineInfo.IsUnknown) { lastLine = lastLineInfo.Line; } foreach (var pair in InstructionWeight) { long rva = pair.Key + FunctionDebugInfo.RVA - offsetData.InitialMultiplier; var lineInfo = debugInfo.FindSourceLineByRVA(rva, inlinee != null); if (!lineInfo.IsUnknown) { int line = lineInfo.Line; if (inlinee != null) { // Map the instruction back to the function that got inlined // at the call site, if filtering by an inlinee is used. var matchingInlinee = lineInfo.FindSameFunctionInlinee(inlinee); if (matchingInlinee != null) { line = matchingInlinee.Line; } else { continue; // Don't count the instr. if not part of the inlinee. } } result.SourceLineWeight.AccumulateValue(line, pair.Value); firstLine = Math.Min(line, firstLine); lastLine = Math.Max(line, lastLine); } } if (HasPerformanceCounters) { foreach (var pair in InstructionCounters) { long rva = pair.Key + FunctionDebugInfo.RVA; var lineInfo = debugInfo.FindSourceLineByRVA(rva, inlinee != null); if (!lineInfo.IsUnknown) { int line = lineInfo.Line; if (inlinee != null) { // Map the instruction back to the function that got inlined // at the call site, if filtering by an inlinee is used. var matchingInlinee = lineInfo.FindSameFunctionInlinee(inlinee); if (matchingInlinee != null) { line = matchingInlinee.Line; } else { continue; // Don't count the instr. if not part of the inlinee. } } result.SourceLineCounters.AccumulateValue(line, pair.Value); firstLine = Math.Min(line, firstLine); lastLine = Math.Max(line, lastLine); } result.FunctionCountersValue.Add(pair.Value); } } result.FirstLineIndex = firstLine; result.LastLineIndex = lastLine; return result; } public PerformanceCounterValueSet ComputeFunctionTotalCounters() { var result = new PerformanceCounterValueSet(); if (HasPerformanceCounters) { foreach (var pair in InstructionCounters) { result.Add(pair.Value); } } return result; } public void Reset() { Weight = TimeSpan.Zero; ExclusiveWeight = TimeSpan.Zero; SampleStartIndex = int.MaxValue; SampleEndIndex = int.MinValue; InstructionWeight?.Clear(); InstructionCounters?.Clear(); } } public class FunctionProcessingResult { public FunctionProcessingResult(int capacity = 0) { SampledElements = new List<(IRElement, TimeSpan)>(capacity); BlockSampledElementsMap = new Dictionary(capacity); BlockSampledElements = new List<(BlockIR, TimeSpan)>(); CounterElements = new List<(IRElement, PerformanceCounterValueSet)>(capacity); FunctionCountersValue = new PerformanceCounterValueSet(); } public List<(IRElement, TimeSpan)> SampledElements { get; set; } public Dictionary BlockSampledElementsMap { get; set; } public List<(BlockIR, TimeSpan)> BlockSampledElements { get; set; } public List<(IRElement, PerformanceCounterValueSet)> CounterElements { get; set; } public List<(BlockIR, PerformanceCounterValueSet)> BlockCounterElements { get; set; } public PerformanceCounterValueSet FunctionCountersValue { get; set; } public double ScaleCounterValue(long value, PerformanceCounter counter) { long total = FunctionCountersValue.FindCounterValue(counter); return total > 0 ? value / (double)total : 0; } public void SortSampledElements() { BlockSampledElements.Sort((a, b) => b.Item2.CompareTo(a.Item2)); SampledElements.Sort((a, b) => b.Item2.CompareTo(a.Item2)); } public SampledElementsToLineMapping BuildSampledElementsToLineMapping(FunctionProfileData profile, ParsedIRTextSection parsedSection) { var elementMap = BuildElementToWeightMap(); var counterMap = BuildElementToCounterMap(); var instrToLineMap = new SampledElementsToLineMapping(); // Build groups of instructions mapping to the same source line, // with their associated sampled weight and perf. counters. foreach (var instr in parsedSection.Function.AllInstructions) { var tag = instr.GetTag(); if (tag != null) { var weight = elementMap.GetValueOr(instr, TimeSpan.Zero); var counters = counterMap.GetValueOrNull(instr); var list = instrToLineMap.SampledElements.GetOrAddValue(tag.Line); list.Add((instr, (weight, counters))); } } // Sort elements in each line group by text offset. foreach (var linePair in instrToLineMap.SampledElements) { linePair.Value.Sort((a, b) => a.Item1.TextLocation.CompareTo(b.Item1.TextLocation)); } return instrToLineMap; } public Dictionary BuildElementToWeightMap() { var map = new Dictionary(); foreach (var pair in SampledElements) { map[pair.Item1] = pair.Item2; } return map; } public Dictionary BuildElementToCounterMap() { var map = new Dictionary(); foreach (var pair in CounterElements) { map[pair.Item1] = pair.Item2; } return map; } // Mapping from a source line number to a list // of associated instructions and their weight and/or perf. counters. public record SampledElementsToLineMapping( Dictionary> SampledElements) { public SampledElementsToLineMapping() : this(new Dictionary>()) { } } } public class SourceLineProcessingResult { public SourceLineProcessingResult() { SourceLineWeight = new Dictionary(); SourceLineCounters = new Dictionary(); FunctionCountersValue = new PerformanceCounterValueSet(); } public Dictionary SourceLineWeight { get; set; } // Line number mapping public Dictionary SourceLineCounters { get; set; } // Line number mapping public PerformanceCounterValueSet FunctionCountersValue { get; set; } public List<(int LineNumber, TimeSpan Weight)> SourceLineWeightList => SourceLineWeight.ToList(); public int FirstLineIndex { get; set; } public int LastLineIndex { get; set; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/IProfileDataProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Threading.Tasks; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Profile.Data; public delegate void ProfileLoadProgressHandler(ProfileLoadProgress info); public delegate void ProcessListProgressHandler(ProcessListProgress info); public enum ModuleLoadState { Loaded, NotFound, Failed, LazyLoadPending // Binary will be downloaded on-demand when user views assembly } public enum ProfileLoadStage { TraceReading, BinaryLoading, SymbolLoading, TraceProcessing, PerfCounterProcessing, ComputeCallTree } public enum ProfileSessionKind { SystemWide, StartProcess, AttachToProcess } public interface IProfileDataProvider { Task LoadTraceAsync(RawProfileData rawProfile, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask = null); Task LoadTraceAsync(string tracePath, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask = null); } [ProtoContract(SkipConstructor = true)] public class ProcessSummary { public ProcessSummary(ProfileProcess process, TimeSpan weight) { Process = process; Weight = weight; } [ProtoMember(1)] public ProfileProcess Process { get; set; } [ProtoMember(2)] public TimeSpan Weight { get; set; } [ProtoMember(3)] public double WeightPercentage { get; set; } [ProtoMember(4)] public TimeSpan Duration { get; set; } [ProtoMember(5)] public double WeightPercentageExcludingIdle { get; set; } public override string ToString() { return $"{Process.Name} ({Weight})"; } } public class ProfileLoadProgress { public ProfileLoadProgress(ProfileLoadStage stage) { Stage = stage; } public ProfileLoadStage Stage { get; set; } public int Total { get; set; } public int Current { get; set; } public string Optional { get; set; } public override string ToString() { return $"{Stage}: {Current}/{Total} {Optional}"; } } public class ProcessListProgress { public int Total { get; set; } public int Current { get; set; } public List Processes { get; set; } public override string ToString() { return $"{Current}/{Total}"; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/IpToImageCache.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; namespace ProfileExplorer.Core.Profile.Data; public class IpToImageCache { private List images_; private long lowestBaseAddress_; public IpToImageCache(IEnumerable images, long lowestBaseAddress) { lowestBaseAddress_ = lowestBaseAddress; images_ = new List(images); images_.Sort(); } public static IpToImageCache Create(IEnumerable images) { long lowestAddr = long.MaxValue; foreach (var image in images) { lowestAddr = Math.Min(lowestAddr, image.BaseAddress); } return new IpToImageCache(images, lowestAddr); } public bool IsValidAddres(long ip) { return ip >= lowestBaseAddress_; } public ProfileImage Find(long ip) { Debug.Assert(IsValidAddres(ip)); return BinarySearch(images_, ip); } private ProfileImage BinarySearch(List ranges, long value) { int min = 0; int max = ranges.Count - 1; while (min <= max) { int mid = (min + max) / 2; var range = ranges[mid]; int comparison = range.CompareTo(value); if (comparison == 0) { return range; } if (comparison < 0) { min = mid + 1; } else { max = mid - 1; } } return null; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ManagedRawProfileData.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Profile.Data; public class ManagedRawProfileData { public Dictionary imageDebugInfo_; public Dictionary moduleDebugInfoMap_; public Dictionary moduleImageMap_; public Dictionary managedMethodIdMap_; public Dictionary managedMethodCodeMap_; public Dictionary managedMethodsMap_; public List managedMethods_; public List<(long ModuleId, ManagedMethodMapping Mapping)> patchedMappings_; public ManagedRawProfileData() { imageDebugInfo_ = new Dictionary(); moduleDebugInfoMap_ = new Dictionary(); moduleImageMap_ = new Dictionary(); managedMethods_ = new List(); managedMethodsMap_ = new Dictionary(); managedMethodCodeMap_ = new Dictionary(); managedMethodIdMap_ = new Dictionary(); patchedMappings_ = new List<(long ModuleId, ManagedMethodMapping Mapping)>(); } public void LoadingCompleted(int processId) { managedMethods_.Sort(); foreach (var debugInfo in imageDebugInfo_.Values) { debugInfo.LoadingCompleted(); } foreach (var (methodId, code) in managedMethodCodeMap_) { if (managedMethodIdMap_.TryGetValue(methodId, out var mapping) && moduleDebugInfoMap_.TryGetValue(mapping.ModuleId, out var debugInfo)) { debugInfo.AddMethodCode(code.Address, code); } } // A placeholder is created for cases where the method load event // is triggered before the module load one, try to assign the image now. foreach (var pair in patchedMappings_) { pair.Mapping.Image = moduleImageMap_.GetValueOrNull(pair.ModuleId); } patchedMappings_ = null; } [ProtoContract(SkipConstructor = true)] public class ManagedDataState { // list of DotNetDebugInfoProvider {id, file_name, arch} public Dictionary ImageDebugInfo; public Dictionary moduleDebugInfoMap_; public Dictionary managedMethodIdMap_; public Dictionary managedMethodsMap_; public List managedMethods_; } } [ProtoContract(SkipConstructor = true)] public class ManagedMethodMapping : IComparable, IComparable, IEquatable { public ManagedMethodMapping(FunctionDebugInfo functionDebugInfo, ProfileImage image, long moduleId, long ip, int size) { FunctionDebugInfo = functionDebugInfo; Image = image; ModuleId = moduleId; IP = ip; Size = size; } [ProtoMember(1)] public FunctionDebugInfo FunctionDebugInfo { get; } [ProtoMember(2)] public ProfileImage Image { get; set; } [ProtoMember(3)] public long ModuleId { get; } [ProtoMember(4)] public long IP { get; } [ProtoMember(5)] public int Size { get; } public int CompareTo(long value) { if (value < IP) { return 1; } if (value > IP + Size) { return -1; } return 0; } public int CompareTo(ManagedMethodMapping other) { return CompareTo(other.IP); } public bool Equals(ManagedMethodMapping other) { if (other == null) return false; return IP == other.IP; } public static ManagedMethodMapping BinarySearch(List ranges, long value) { int low = 0; int high = ranges.Count - 1; while (low <= high) { int mid = low + (high - low) / 2; var range = ranges[mid]; int result = range.CompareTo(value); if (result == 0) { return range; } if (result < 0) { low = mid + 1; } else { high = mid - 1; } } return null; } public override bool Equals(object obj) { return obj is ManagedMethodMapping other && Equals(other); } public override int GetHashCode() { return IP.GetHashCode(); } } public record ManagedMethodId(long MethodId, long ReJITId); ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ModuleProfileInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core.Profile.CallTree; namespace ProfileExplorer.Core.Profile.Data; public class ModuleProfileInfo { public ModuleProfileInfo() { } public ModuleProfileInfo(string name) { Name = name; Functions = new List(); } public string Name { get; set; } public double Percentage { get; set; } public TimeSpan Weight { get; set; } public List Functions { get; set; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/PerformanceCounters.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using ProtoBuf; namespace ProfileExplorer.Core.Profile.Data; [ProtoContract(SkipConstructor = true)] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PerformanceCounterValue : IEquatable { [ProtoMember(1)] public int CounterId { get; set; } [ProtoMember(2)] public long Value { get; set; } public PerformanceCounterValue(int counterId, long value = 0) { CounterId = counterId; Value = value; } public bool Equals(PerformanceCounterValue other) { return CounterId == other.CounterId && Value == other.Value; } public override bool Equals(object obj) { return obj is PerformanceCounterValue other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(CounterId, Value); } } [ProtoContract(SkipConstructor = true)] [ProtoInclude(100, typeof(PerformanceMetric))] public class PerformanceCounter { public PerformanceCounter() { } public PerformanceCounter(int id, string name, int frequency = 0) { Id = id; Name = name; Frequency = frequency; } public virtual bool IsMetric => false; [ProtoMember(2)] public int Index { get; set; } [ProtoMember(3)] public int Id { get; set; } [ProtoMember(4)] public string Name { get; set; } [ProtoMember(5)] public int Frequency { get; set; } } [ProtoContract(SkipConstructor = true)] public class PerformanceMetric : PerformanceCounter { public PerformanceMetric(int id, PerformanceMetricConfig config, PerformanceCounter baseCounter, PerformanceCounter relativeCounter) : base(id, config.Name) { Config = config; BaseCounter = baseCounter; RelativeCounter = relativeCounter; } [ProtoMember(1)] public PerformanceMetricConfig Config { get; set; } [ProtoMember(2)] public PerformanceCounter BaseCounter { get; set; } [ProtoMember(3)] public PerformanceCounter RelativeCounter { get; set; } public override bool IsMetric => true; public double ComputeMetric(PerformanceCounterValueSet counterValueSet, out long baseValue, out long relativeValue) { baseValue = counterValueSet.FindCounterValue(BaseCounter); relativeValue = counterValueSet.FindCounterValue(RelativeCounter); if (baseValue == 0) { return 0; } // Counters may not be accurate and the percentage can end up more than 100%. double result = relativeValue / (double)baseValue; return Config.IsPercentage ? Math.Min(result, 1) : result; } } // Groups a set of counters associated with a single instruction. // There is one PerformanceCounterValue for each counter type // that accumulates all instances of the raw events. [ProtoContract(SkipConstructor = true)] public class PerformanceCounterValueSet { public PerformanceCounterValueSet() { InitializeReferenceMembers(); } [ProtoMember(1)] public List Counters { get; set; } public int Count => Counters.Count; public long this[int perfCounterId] => FindCounterValue(perfCounterId); public void AddCounterSample(int perfCounterId, long value) { int index = Counters.FindIndex(item => item.CounterId == perfCounterId); var countersSpan = CollectionsMarshal.AsSpan(Counters); if (index != -1) { ref var counterRef = ref countersSpan[index]; counterRef.Value += value; } else { // Keep the list sorted so that it is in sync // with the sorted counter definition list. var counter = new PerformanceCounterValue(perfCounterId, value); int insertionIndex = 0; for (int i = 0; i < Counters.Count; i++, insertionIndex++) { if (Counters[i].CounterId >= perfCounterId) { break; } } Counters.Insert(insertionIndex, counter); } } public long FindCounterValue(int perfCounterId) { int index = Counters.FindIndex(item => item.CounterId == perfCounterId); return index != -1 ? Counters[index].Value : 0; } public long FindCounterValue(PerformanceCounter counter) { return FindCounterValue(counter.Id); } public void Add(PerformanceCounterValueSet other) { //? TODO: This assumes there are not many counters being collected, //? switch to dict if dozens get to be collected one day. foreach (var counter in other.Counters) { int index = Counters.FindIndex(item => item.CounterId == counter.CounterId); if (index != -1) { var countersSpan = CollectionsMarshal.AsSpan(Counters); ref var counterRef = ref countersSpan[index]; counterRef.Value += counter.Value; } else { Counters.Add(new PerformanceCounterValue(counter.CounterId, counter.Value)); } } } [ProtoAfterDeserialization] private void InitializeReferenceMembers() { Counters ??= new List(); } } public static class PerformanceCounterExtensions { public static PerformanceCounterValueSet AccumulateValue(this Dictionary dict, K key, PerformanceCounterValueSet value) { if (!dict.TryGetValue(key, out var currentValue)) { currentValue = new PerformanceCounterValueSet(); dict[key] = currentValue; } currentValue.Add(value); return currentValue; } } [ProtoContract(SkipConstructor = true)] public class PerformanceCounterConfig : IEquatable { public PerformanceCounterConfig(int id, string name, int defaultInterval, int minInterval, int maxInterval, bool isBuiltin) { Id = id; Name = name; Interval = defaultInterval; DefaultInterval = defaultInterval; MinInterval = minInterval; MaxInterval = maxInterval; IsBuiltin = isBuiltin; } [ProtoMember(1)] public bool IsEnabled { get; set; } [ProtoMember(2)] public bool IsBuiltin { get; set; } [ProtoMember(3)] public int Id { get; set; } [ProtoMember(4)] public string Name { get; set; } [ProtoMember(5)] public string Description { get; set; } [ProtoMember(6)] public int Interval { get; set; } [ProtoMember(7)] public int MinInterval { get; set; } [ProtoMember(8)] public int MaxInterval { get; set; } [ProtoMember(9)] public int DefaultInterval { get; set; } public bool Equals(PerformanceCounterConfig other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Id == other.Id && Name == other.Name; } public static bool operator ==(PerformanceCounterConfig left, PerformanceCounterConfig right) { return Equals(left, right); } public static bool operator !=(PerformanceCounterConfig left, PerformanceCounterConfig right) { return !Equals(left, right); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((PerformanceCounterConfig)obj); } public override int GetHashCode() { return HashCode.Combine(Id, Name); } } [ProtoContract(SkipConstructor = true)] public class PerformanceMetricConfig : IEquatable { public PerformanceMetricConfig(string name, string baseCounterName, string relativeCounterName, bool isPercentage, string description) { Name = name; BaseCounterName = baseCounterName; RelativeCounterName = relativeCounterName; Description = description; IsPercentage = isPercentage; IsEnabled = true; } [ProtoMember(1)] public string Name { get; set; } [ProtoMember(2)] public string BaseCounterName { get; set; } [ProtoMember(3)] public string RelativeCounterName { get; set; } [ProtoMember(4)] public string Description { get; set; } [ProtoMember(5)] public bool IsPercentage { get; set; } [ProtoMember(6)] public bool IsEnabled { get; set; } public bool Equals(PerformanceMetricConfig other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Name == other.Name && BaseCounterName == other.BaseCounterName && RelativeCounterName == other.RelativeCounterName; } public static bool operator ==(PerformanceMetricConfig left, PerformanceMetricConfig right) { return Equals(left, right); } public static bool operator !=(PerformanceMetricConfig left, PerformanceMetricConfig right) { return !Equals(left, right); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((PerformanceMetricConfig)obj); } public override int GetHashCode() { return HashCode.Combine(Name, BaseCounterName, RelativeCounterName, IsPercentage); } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ProcessSummaryBuilder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Data; public class ProcessSummaryBuilder { private RawProfileData profile_; private Dictionary processSamples_ = new(); private Dictionary procDuration_ = new(); private TimeSpan totalWeight_; public ProcessSummaryBuilder(RawProfileData profile) { profile_ = profile; } public void AddSample(ProfileSample sample) { var context = sample.GetContext(profile_); int processId = context.ProcessId; profile_.GetOrCreateProcess(processId); // Ensure process object exists. processSamples_.AccumulateValue(processId, sample.Weight); totalWeight_ += sample.Weight; // Modify in-place. ref var durationRef = ref CollectionsMarshal.GetValueRefOrAddDefault(procDuration_, processId, out bool found); if (!found) { durationRef.First = sample.Time; } durationRef.Last = sample.Time; } public void AddSample(TimeSpan sampleWeight, TimeSpan sampleTime, int processId) { profile_.GetOrCreateProcess(processId); // Ensure process object exists. processSamples_.AccumulateValue(processId, sampleWeight); totalWeight_ += sampleWeight; // Modify in-place. ref var durationRef = ref CollectionsMarshal.GetValueRefOrAddDefault(procDuration_, processId, out bool found); if (!found) { durationRef.First = sampleTime; } durationRef.Last = sampleTime; } public List MakeSummaries() { var list = new List(procDuration_.Count); // Calculate non-idle total weight for the excluding-idle percentage. long nonIdleWeightTicks = totalWeight_.Ticks; if (processSamples_.TryGetValue(ETW.ETWEventProcessor.KernelProcessId, out var idleWeight)) { nonIdleWeightTicks -= idleWeight.Ticks; } foreach (var pair in processSamples_) { var process = profile_.GetOrCreateProcess(pair.Key); double weightPercentage = totalWeight_.Ticks > 0 ? 100 * (double)pair.Value.Ticks / totalWeight_.Ticks : 0; double weightPercentageExcludingIdle; if (nonIdleWeightTicks > 0) { if (pair.Key == ETW.ETWEventProcessor.KernelProcessId) { // For the idle/kernel process, the excluding-idle percentage is not meaningful. // Set it equal to the overall weight percentage to avoid confusing values. weightPercentageExcludingIdle = weightPercentage; } else { weightPercentageExcludingIdle = 100 * (double)pair.Value.Ticks / nonIdleWeightTicks; } } else { weightPercentageExcludingIdle = 0; } var item = new ProcessSummary(process, pair.Value) { WeightPercentage = weightPercentage, WeightPercentageExcludingIdle = weightPercentageExcludingIdle }; list.Add(item); if (procDuration_.TryGetValue(pair.Key, out var duration)) { item.Duration = duration.Last - duration.First; } } return list; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ProfileData.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Data; public class ProfileData { public ProfileData(TimeSpan profileWeight, TimeSpan totalWeight) : this() { ProfileWeight = profileWeight; TotalWeight = totalWeight; } public ProfileData() { ProfileWeight = TimeSpan.Zero; FunctionProfiles = new Dictionary(); ModuleWeights = new Dictionary(); PerformanceCounters = new Dictionary(); ModuleCounters = new Dictionary(); Threads = new Dictionary(); Modules = new Dictionary(); Samples = new List<(ProfileSample, ResolvedProfileStack)>(); Events = new List<(PerformanceCounterEvent Sample, ResolvedProfileStack Stack)>(); ModuleDebugInfo = new Dictionary(); Filter = new ProfileSampleFilter(); } public TimeSpan ProfileWeight { get; set; } public TimeSpan TotalWeight { get; set; } public Dictionary FunctionProfiles { get; set; } public Dictionary ModuleWeights { get; set; } public Dictionary ModuleCounters { get; set; } public Dictionary PerformanceCounters { get; set; } public ProfileCallTree CallTree { get; set; } public ThreadSampleRanges ThreadSampleRanges { get; set; } public ProfileDataReport Report { get; set; } public List<(ProfileSample Sample, ResolvedProfileStack Stack)> Samples { get; set; } public List<(PerformanceCounterEvent Sample, ResolvedProfileStack Stack)> Events { get; set; } public ProfileProcess Process { get; set; } public Dictionary Threads { get; set; } public Dictionary Modules { get; set; } public Dictionary ModuleDebugInfo { get; set; } public ProfileSampleFilter Filter { get; set; } public List SortedPerformanceCounters { get { var list = PerformanceCounters.ToValueList(); list.Sort((a, b) => b.Id.CompareTo(a.Id)); return list; } } public List<(int ThreadId, TimeSpan Weight)> SortedThreadWeights { get { var list = new List<(int ThreadId, TimeSpan Weight)>(); var threadWeights = new Dictionary(); var sampleSpan = CollectionsMarshal.AsSpan(Samples); for (int i = 0; i < sampleSpan.Length; i++) { threadWeights.AccumulateValue(sampleSpan[i].Stack.Context.ThreadId, sampleSpan[i].Sample.Weight); } foreach ((int threadId, var weight) in threadWeights) { list.Add((threadId, weight)); } list.Sort((a, b) => b.Weight.CompareTo(a.Weight)); return list; } } public void RegisterModuleDebugInfo(string moduleName, IDebugInfoProvider provider) { ModuleDebugInfo[moduleName] = provider; } public void AddModuleSample(int moduleId, TimeSpan weight) { ModuleWeights.AccumulateValue(moduleId, weight); } public void AddModuleCounter(string moduleName, int perfCounterId, long value) { if (!ModuleCounters.TryGetValue(moduleName, out var counterSet)) { counterSet = new PerformanceCounterValueSet(); ModuleCounters[moduleName] = counterSet; } counterSet.AddCounterSample(perfCounterId, value); } public void RegisterPerformanceCounter(PerformanceCounter perfCounter) { perfCounter.Index = PerformanceCounters.Count; PerformanceCounters[perfCounter.Id] = perfCounter; } public PerformanceCounter GetPerformanceCounter(int id) { if (PerformanceCounters.TryGetValue(id, out var counter)) { return counter; } return null; } public PerformanceCounter FindPerformanceCounter(string name) { foreach (var pair in PerformanceCounters) { if (pair.Value.Name == name) { return pair.Value; } } return null; } public PerformanceMetric RegisterPerformanceMetric(int id, PerformanceMetricConfig config) { var baseCounter = FindPerformanceCounter(config.BaseCounterName); var relativeCounter = FindPerformanceCounter(config.RelativeCounterName); if (baseCounter != null && relativeCounter != null) { var metric = new PerformanceMetric(id, config, baseCounter, relativeCounter); PerformanceCounters[id] = metric; return metric; } return null; } public double ScaleFunctionWeight(TimeSpan weight) { return ProfileWeight.Ticks == 0 ? 0 : weight.Ticks / (double)ProfileWeight.Ticks; } public double ScaleModuleWeight(TimeSpan weight) { return TotalWeight.Ticks == 0 ? 0 : weight.Ticks / (double)TotalWeight.Ticks; } public FunctionProfileData GetFunctionProfile(IRTextFunction function) { return FunctionProfiles.TryGetValue(function, out var profile) ? profile : null; } public bool HasFunctionProfile(IRTextFunction function) { return GetFunctionProfile(function) != null; } public FunctionProfileData GetOrCreateFunctionProfile(IRTextFunction function, FunctionDebugInfo debugInfo) { ref var funcProfile = ref CollectionsMarshal.GetValueRefOrAddDefault(FunctionProfiles, function, out bool exists); if (!exists) { funcProfile = new FunctionProfileData(debugInfo); } return funcProfile; } public List<(IRTextFunction, FunctionProfileData)> GetSortedFunctions() { var list = FunctionProfiles.ToList(); list.Sort((a, b) => -a.Item2.ExclusiveWeight.CompareTo(b.Item2.ExclusiveWeight)); return list; } public void AddThreads(IEnumerable threads) { foreach (var thread in threads) { Threads[thread.ThreadId] = thread; } } public void AddModules(IEnumerable modules) { foreach (var module in modules) { Modules[module.Id] = module; } } public ProfileThread FindThread(int threadId) { if (Threads != null) { return Threads.GetValueOrNull(threadId); } return null; } public List FindModuleIds(Func matchCheck) { var ids = new List(); foreach (var module in Modules) { if (matchCheck(module.Value.ModuleName)) { ids.Add(module.Key); } } return ids; } public TimeSpan FindModulesWeight(Func matchCheck) { var ids = FindModuleIds(matchCheck); var weight = TimeSpan.Zero; foreach (int id in ids) { weight += ModuleWeights.GetValueOrDefault(id); } return weight; } public ProcessingResult FilterFunctionProfile(ProfileSampleFilter filter) { //? TODO: Split ProfileData into a part that has the samples and other info that doesn't change, //? while the rest is more like a processing result similar to FuncProfileData var currentProfile = new ProcessingResult { FunctionProfiles = FunctionProfiles, CallTree = CallTree, ModuleWeights = ModuleWeights, ProfileWeight = ProfileWeight, TotalWeight = TotalWeight, Filter = Filter }; CallTree?.ResetTags(); ModuleWeights = new Dictionary(); FunctionProfiles = new Dictionary(); ProfileWeight = TimeSpan.Zero; TotalWeight = TimeSpan.Zero; var profile = ComputeProfile(this, filter); ModuleWeights = profile.ModuleWeights; ProfileWeight = profile.ProfileWeight; TotalWeight = profile.TotalWeight; FunctionProfiles = profile.FunctionProfiles; CallTree = profile.CallTree; Filter = filter; return currentProfile; } public ProcessingResult RestorePreviousProfile(ProcessingResult previousProfile) { var currentProfile = new ProcessingResult { FunctionProfiles = FunctionProfiles, CallTree = CallTree, ModuleWeights = ModuleWeights, ProfileWeight = ProfileWeight, TotalWeight = TotalWeight, Filter = Filter }; ModuleWeights = previousProfile.ModuleWeights; ProfileWeight = previousProfile.ProfileWeight; TotalWeight = previousProfile.TotalWeight; FunctionProfiles = previousProfile.FunctionProfiles; CallTree = previousProfile.CallTree; Filter = previousProfile.Filter; return currentProfile; } public ProfileData ComputeProfile(ProfileData baseProfile, ProfileSampleFilter filter, bool computeCallTree = true, int maxChunks = int.MaxValue) { // Compute the call tree in parallel with the per-function profiles. var tasks = new List(); if (maxChunks == int.MaxValue) { // Use half the threads for each task. maxChunks = Math.Max(1, CoreSettingsProvider.GeneralSettings.CurrentCpuCoreLimit / 2); } var callTreeTask = Task.Run(() => { if (computeCallTree) { return CallTreeProcessor.Compute(baseProfile, filter, maxChunks); } return null; }); var funcProfileTask = Task.Run(() => { return FunctionProfileProcessor.Compute(baseProfile, filter, maxChunks); }); tasks.Add(callTreeTask); Task.WhenAll(tasks.ToArray()).Wait(); var profile = funcProfileTask.Result; profile.CallTree = callTreeTask.Result; return profile; } //? TODO: Port to ProfileSampleProcessor public ThreadSampleRanges ComputeThreadSampleRanges() { // Compute lists of contiguous range of samples running on the same thread, // used later to speed up the timeline slice computation and per-thread filtering. var threadSampleRanges = new Dictionary>(); int sampleIndex = 0; int prevThreadId = -1; int prevSampleIndex = -1; var sampleSpan = CollectionsMarshal.AsSpan(Samples); for (int i = 0; i < sampleSpan.Length; i++) { int threadId = sampleSpan[i].Stack.Context.ThreadId; if (threadId != prevThreadId) { if (prevThreadId != -1) { threadSampleRanges.GetOrAddValue(prevThreadId).Add(new ThreadSampleRange { StartIndex = prevSampleIndex, EndIndex = sampleIndex }); } prevThreadId = threadId; prevSampleIndex = sampleIndex; } sampleIndex++; } if (prevThreadId != -1) { threadSampleRanges.GetOrAddValue(prevThreadId).Add(new ThreadSampleRange { StartIndex = prevSampleIndex, EndIndex = sampleIndex }); } // Add an entry representing all threads, covering all samples. threadSampleRanges[-1] = new List { new() { StartIndex = 0, EndIndex = sampleIndex } }; ThreadSampleRanges = new ThreadSampleRanges(threadSampleRanges); return ThreadSampleRanges; } public class ProcessingResult { public ProfileSampleFilter Filter { get; set; } public Dictionary FunctionProfiles { get; set; } public ProfileCallTree CallTree { get; set; } public Dictionary ModuleWeights { get; set; } public TimeSpan ProfileWeight { get; set; } public TimeSpan TotalWeight { get; set; } public override string ToString() { return $"ProfileWeight: {ProfileWeight}, TotalWeight: {TotalWeight}, " + $"FunctionProfiles: {FunctionProfiles.Count}, CallTree: {CallTree}"; } } } // Represents a contiguous range of samples running on the same thread. public struct ThreadSampleRange { public int StartIndex; public int EndIndex; } // Represents a set of sample ranges for each thread. public class ThreadSampleRanges { public ThreadSampleRanges(Dictionary> ranges) { Ranges = ranges; } public Dictionary> Ranges { get; set; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ProfileDataReport.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Profile.Data; [ProtoContract(SkipConstructor = true)] public class ProfileDataReport : IEquatable { [ProtoMember(1)] private Dictionary moduleStatusMap_ = new(); [ProtoMember(2)] public ProfileTraceInfo TraceInfo { get; set; } [ProtoMember(3)] public List RunningProcesses { get; set; } [ProtoMember(4)] public ProfileProcess Process { get; set; } [ProtoMember(5)] public SymbolFileSourceSettings SymbolSettings { get; set; } [ProtoMember(6)] public ProfileRecordingSessionOptions RecordingSessionOptions { get; set; } // For recording mode public bool IsRecordingSession => RecordingSessionOptions != null; public bool IsStartProcessSession => RecordingSessionOptions is {SessionKind: ProfileSessionKind.StartProcess}; public bool IsAttachToProcessSession => RecordingSessionOptions is {SessionKind: ProfileSessionKind.AttachToProcess}; public List Modules => moduleStatusMap_.ToValueList(); public TimeSpan SamplingInterval { get { if (TraceInfo.SamplingInterval.Ticks > 0) { return TraceInfo.SamplingInterval; } if (RecordingSessionOptions != null) { return TimeSpan.FromMilliseconds(1.0 / RecordingSessionOptions.SamplingFrequency); } return TimeSpan.Zero; } } public bool Equals(ProfileDataReport other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Equals(RecordingSessionOptions, other.RecordingSessionOptions) && TraceInfo.HasSameTraceFilePath(other.TraceInfo); } public static bool operator ==(ProfileDataReport left, ProfileDataReport right) { return Equals(left, right); } public static bool operator !=(ProfileDataReport left, ProfileDataReport right) { return !Equals(left, right); } public void AddModuleInfo(BinaryFileDescriptor binaryInfo, BinaryFileSearchResult binaryFile, ModuleLoadState state) { lock (this) { var status = GetOrCreateModuleStatus(binaryInfo); status.BinaryFileInfo = binaryFile; status.State = state; } } public void AddDebugInfo(BinaryFileDescriptor binaryInfo, DebugFileSearchResult searchResult) { lock (this) { var status = GetOrCreateModuleStatus(binaryInfo); status.DebugInfoFile = searchResult; } } public ModuleStatus GetModuleStatus(string moduleName) { lock (this) { return Modules.Find( module => module.ImageFileInfo.ImageName.Equals(moduleName, StringComparison.OrdinalIgnoreCase)); } } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((ProfileDataReport)obj); } public override int GetHashCode() { return HashCode.Combine(RecordingSessionOptions); } public void Dump() { foreach (var pair in moduleStatusMap_) { Trace.WriteLine($"Module {pair.Value.ImageFileInfo.ImageName}"); Trace.WriteLine($" - state: {pair.Value.State}"); if (pair.Value.BinaryFileInfo != null) { Trace.WriteLine($" - found: {pair.Value.BinaryFileInfo.Found}"); Trace.WriteLine($" - path: {pair.Value.BinaryFileInfo.FilePath}"); Trace.WriteLine($" - details: {pair.Value.BinaryFileInfo.Details}"); } if (pair.Value.DebugInfoFile != null) { Trace.WriteLine($" - debug: {pair.Value.DebugInfoFile.Found}"); Trace.WriteLine($" - path: {pair.Value.DebugInfoFile.FilePath}"); Trace.WriteLine($" - details: {pair.Value.DebugInfoFile.Details}"); } } } public override string ToString() { return $"{TraceInfo.TraceFilePath}, {Process.Name}"; } private ModuleStatus GetOrCreateModuleStatus(BinaryFileDescriptor binaryInfo) { if (!moduleStatusMap_.TryGetValue(binaryInfo, out var status)) { status = new ModuleStatus(); status.ImageFileInfo = binaryInfo; moduleStatusMap_[binaryInfo] = status; } return status; } [ProtoContract(SkipConstructor = true)] public class ModuleStatus { [ProtoMember(1)] public ModuleLoadState State { get; set; } [ProtoMember(2)] public BinaryFileDescriptor ImageFileInfo { get; set; } // Info used for lookup. [ProtoMember(3)] public BinaryFileSearchResult BinaryFileInfo { get; set; } // Lookup result with local file. [ProtoMember(4)] public DebugFileSearchResult DebugInfoFile { get; set; } public bool HasBinaryLoaded => State == ModuleLoadState.Loaded; public bool HasDebugInfoLoaded => DebugInfoFile is {Found: true}; /// /// Returns true if binary is loaded OR if lazy loading is pending (binary can be loaded on-demand). /// Use this for UI display to avoid showing error icons when lazy loading is available. /// public bool IsBinaryAvailableOrPending => State == ModuleLoadState.Loaded || State == ModuleLoadState.LazyLoadPending; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ProfileModuleBuilder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Concurrent; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Data; public sealed class ProfileModuleBuilder : IDisposable { #if DEBUG private static volatile int FuncQueries; private static volatile int FuncFoundByAddress; private static volatile int FuncFoundByFuncAddress; private static volatile int FuncFoundByFuncAddressLocked; private static volatile int FuncCreated; #endif private ICompilerInfoProvider compilerInfo_; private IBinaryFileFinder binaryFileFinder_; private IDebugFileFinder debugFileFinder_; private IDebugInfoProviderFactory debugInfoProviderFactory_; private ICompilerIRInfo compilerIrInfo_; private INameProvider nameProvider_; private BinaryFileDescriptor binaryInfo_; private ConcurrentDictionary functionMap_; private ConcurrentDictionary loggedFuncAddresses_ = new(); private ProfileDataReport report_; private ReaderWriterLockSlim lock_; private SemaphoreSlim binaryLoadLock_; private SymbolFileSourceSettings symbolSettings_; private volatile bool disposed_; public ProfileModuleBuilder(ProfileDataReport report, ICompilerInfoProvider compilerInfoProvider) { report_ = report; compilerInfo_ = compilerInfoProvider; binaryFileFinder_ = compilerInfoProvider.BinaryFileFinder; debugFileFinder_ = compilerInfoProvider.DebugFileFinder; debugInfoProviderFactory_ = compilerInfoProvider.DebugInfoProviderFactory; compilerIrInfo_ = compilerInfoProvider.IR; nameProvider_ = compilerInfoProvider.NameProvider; functionMap_ = new ConcurrentDictionary(); lock_ = new ReaderWriterLockSlim(); binaryLoadLock_ = new SemaphoreSlim(1, 1); } public IRTextSummary Summary { get; set; } public ILoadedDocument ModuleDocument { get; set; } public IDebugInfoProvider DebugInfo { get; set; } public bool HasDebugInfo { get; set; } public bool Initialized { get; set; } public bool IsManaged { get; set; } public async Task Initialize(BinaryFileDescriptor binaryInfo, SymbolFileSourceSettings symbolSettings, IDebugInfoProvider debugInfo, bool skipBinaryDownload = false) { if (Initialized) { return true; } binaryInfo_ = binaryInfo; symbolSettings_ = symbolSettings; string imageName = binaryInfo.ImageName; DiagnosticLogger.LogInfo($"[ModuleInit] Starting initialization for module: {imageName} (skipBinaryDownload={skipBinaryDownload})"); DiagnosticLogger.LogInfo($"[ModuleInit] Binary info - Name: {binaryInfo.ImageName}, Path: {binaryInfo.ImagePath}, Architecture: {binaryInfo.Architecture}"); #if DEBUG Trace.WriteLine($"ModuleInfo init {imageName}"); #endif // LAZY BINARY LOADING: Skip binary download during trace loading. // Binaries are only needed for disassembly view, not for function name resolution. // They will be downloaded on-demand when user views assembly for a function. BinaryFileSearchResult binFile = null; if (skipBinaryDownload) { DiagnosticLogger.LogInfo($"[ModuleInit] Skipping binary download for {imageName} (lazy loading enabled)"); } else if (symbolSettings.SourceServerEnabled) { binFile = await FindBinaryFilePath(symbolSettings).ConfigureAwait(false); } else { DiagnosticLogger.LogInfo($"[ModuleInit] Skipping binary lookup for {imageName} - symbol server disabled"); } if (binFile == null || !binFile.Found) { if (skipBinaryDownload) { // Lazy loading: Binary will be downloaded on-demand. // Report as LazyLoadPending, not NotFound. DiagnosticLogger.LogInfo($"[ModuleInit] Binary lazy load pending for {imageName} - will download on-demand"); report_.AddModuleInfo(binaryInfo, binFile, ModuleLoadState.LazyLoadPending); } else if (binFile != null) { DiagnosticLogger.LogWarning($"[ModuleInit] Could not find local path for image {imageName}. Binary file missing."); Trace.TraceWarning($"Could not find local path for image {imageName}"); report_.AddModuleInfo(binaryInfo, binFile, ModuleLoadState.NotFound); } else { report_.AddModuleInfo(binaryInfo, binFile, ModuleLoadState.NotFound); } CreateDummyDocument(binaryInfo); return true; // Try to continue just with debug info. } DiagnosticLogger.LogInfo($"[ModuleInit] Found binary file for {imageName}: {binFile.FilePath}"); // Create a DisassemblerSectionLoader and LoadedDocument directly instead of calling through session bool isManagedImage = binFile.BinaryFile?.IsManagedImage ?? false; var loader = new DisassemblerSectionLoader(binFile.FilePath, compilerInfo_, debugInfo, false, isManagedImage); var loadedDoc = await CreateLoadedDocument(binFile.FilePath, binaryInfo.ImageName, loader).ConfigureAwait(false); if (loadedDoc == null) { DiagnosticLogger.LogError($"[ModuleInit] Failed to load document for image {imageName}"); Trace.TraceWarning($"Failed to load document for image {imageName}"); report_.AddModuleInfo(binaryInfo, binFile, ModuleLoadState.Failed); CreateDummyDocument(binaryInfo); return false; } DiagnosticLogger.LogInfo($"[ModuleInit] Successfully loaded document for image {imageName}"); loadedDoc.BinaryFile = BinaryFileSearchResult.Success(binFile.FilePath); loadedDoc.DebugInfo = debugInfo; #if DEBUG Trace.TraceWarning($" Loaded document for image {imageName}"); #endif report_.AddModuleInfo(binaryInfo, binFile, ModuleLoadState.Loaded); ModuleDocument = loadedDoc; Summary = loadedDoc.Summary; // .Net debug info is passed in by the client. IsManaged = binFile.BinaryFile != null && binFile.BinaryFile.IsManagedImage; if (IsManaged && debugInfo != null) { DiagnosticLogger.LogInfo($"[ModuleInit] Module {imageName} has managed debug info"); Trace.TraceInformation($" Has managed debug {imageName}"); DebugInfo = debugInfo; HasDebugInfo = true; loadedDoc.DebugInfo = debugInfo; } else if (IsManaged) { DiagnosticLogger.LogWarning($"[ModuleInit] Module {imageName} is managed but no debug info provided"); } else { DiagnosticLogger.LogInfo($"[ModuleInit] Module {imageName} is native (not managed)"); } #if DEBUG Trace.TraceInformation($"Initialized image {imageName}"); #endif DiagnosticLogger.LogInfo($"[ModuleInit] Module initialization completed for {imageName}. HasDebugInfo={HasDebugInfo}, IsManaged={IsManaged}"); Initialized = true; return true; } /// /// Loads the binary file on-demand for disassembly view. /// Call this when the user wants to view assembly for a function. /// public async Task EnsureBinaryLoaded() { // Check if disposed before attempting any operations if (disposed_) { return false; } // Already have a binary loaded - fast path check without lock if (ModuleDocument?.BinaryFile?.Found == true) { return true; } // Acquire the lock to ensure only one thread loads the binary // Check disposed again to avoid race with Dispose() if (disposed_) { return false; } try { await binaryLoadLock_.WaitAsync().ConfigureAwait(false); } catch (ObjectDisposedException) { // Semaphore was disposed between our check and WaitAsync return false; } try { // Double-check after acquiring lock - another thread may have loaded it if (ModuleDocument?.BinaryFile?.Found == true) { return true; } if (binaryInfo_ == null || symbolSettings_ == null) { return false; } string imageName = binaryInfo_.ImageName; DiagnosticLogger.LogInfo($"[LazyBinaryLoad] Loading binary on-demand for {imageName}"); // Clone settings with fresh timeout state for on-demand download. // The shared symbolSettings_ may have degraded/reduced timeouts from the PDB pre-download phase, // but the user is actively waiting for this binary so use generous timeout (BellwetherTimeoutSeconds = 60s). var downloadSettings = symbolSettings_.Clone(); downloadSettings.HadFirstSuccessfulNetworkRequest = true; DiagnosticLogger.LogInfo($"[LazyBinaryLoad] Cloned settings for {imageName}: " + $"EffectiveTimeout={downloadSettings.EffectiveTimeoutSeconds}s, " + $"BellwetherTimeout={downloadSettings.BellwetherTimeoutSeconds}s, " + $"HadFirstSuccess={downloadSettings.HadFirstSuccessfulNetworkRequest}, " + $"Degraded={downloadSettings.SymbolServerDegraded}, " + $"HadTimeout={downloadSettings.HadFirstTimeout}"); var binFile = await FindBinaryFilePath(downloadSettings).ConfigureAwait(false); if (binFile == null || !binFile.Found) { DiagnosticLogger.LogWarning($"[LazyBinaryLoad] Could not find binary for {imageName}"); // Update state from LazyLoadPending to NotFound so the UI shows the failure. report_.AddModuleInfo(binaryInfo_, binFile, ModuleLoadState.NotFound); return false; } DiagnosticLogger.LogInfo($"[LazyBinaryLoad] Found binary for {imageName}: {binFile.FilePath}"); DiagnosticLogger.LogInfo($"[LazyBinaryLoad] DebugInfo available: {DebugInfo != null}, compilerInfo available: {compilerInfo_ != null}"); if (DebugInfo == null) { DiagnosticLogger.LogError($"[LazyBinaryLoad] DebugInfo is null for {imageName} - disassembly will fail!"); } // Create the disassembler loader with the binary. // Pass preloadFunctions=false since we'll register functions manually. bool isManagedImage = binFile.BinaryFile?.IsManagedImage ?? false; var loader = new DisassemblerSectionLoader(binFile.FilePath, compilerInfo_, DebugInfo, false, isManagedImage); // Initialize the loader's document with our existing summary. // This is important because functions have already been added to Summary // during profile loading and we need to preserve those references. await Task.Run(async () => { await loader.LoadDocument(null).ConfigureAwait(false); }).ConfigureAwait(false); // Verify the disassembler was initialized bool disassemblerReady = loader.IsDisassemblerInitialized; DiagnosticLogger.LogInfo($"[LazyBinaryLoad] Disassembler initialized: {disassemblerReady}"); if (!disassemblerReady) { DiagnosticLogger.LogError($"[LazyBinaryLoad] Disassembler failed to initialize for {imageName}!"); } // Re-register all existing functions with the new loader so it knows about them. // The functions were already created via GetOrCreateFunction during profile loading. int registeredCount = 0; foreach (var kvp in functionMap_) { var (func, debugInfo) = kvp.Value; loader.RegisterFunction(func, debugInfo); registeredCount++; } DiagnosticLogger.LogInfo($"[LazyBinaryLoad] Registered {registeredCount} functions with loader for {imageName}"); // Update the existing document IN PLACE so the session state reference remains valid. // This is critical - creating a new document would break the reference that // MainWindowSession.LoadAndParseSection() holds. ModuleDocument.BinaryFile = BinaryFileSearchResult.Success(binFile.FilePath); ModuleDocument.DebugInfo = DebugInfo; // Dispose the old dummy loader and replace with the real one ModuleDocument.Loader?.Dispose(); ModuleDocument.Loader = loader; // Update the module load state in the report report_.AddModuleInfo(binaryInfo_, binFile, ModuleLoadState.Loaded); IsManaged = binFile.BinaryFile != null && binFile.BinaryFile.IsManagedImage; DiagnosticLogger.LogInfo($"[LazyBinaryLoad] Successfully loaded binary for {imageName}"); return true; } finally { binaryLoadLock_.Release(); } } public async Task InitializeDebugInfo(DebugFileSearchResult debugInfoFile) { string imageName = binaryInfo_?.ImageName ?? "Unknown"; DiagnosticLogger.LogInfo($"[DebugInfoInit] Initializing debug info for module {imageName}"); if (DebugInfo != null) { DiagnosticLogger.LogInfo($"[DebugInfoInit] Debug info already loaded for module {imageName}"); return HasDebugInfo; } ModuleDocument.DebugInfoFile = debugInfoFile; if (ModuleDocument.DebugInfoFile == null || !ModuleDocument.DebugInfoFile.Found) { DiagnosticLogger.LogWarning($"[DebugInfoInit] Debug info file not found for module {imageName}. DebugInfoFile={ModuleDocument.DebugInfoFile?.SymbolFile?.FileName ?? "null"}"); report_.AddDebugInfo(binaryInfo_, ModuleDocument.DebugInfoFile); return false; } DiagnosticLogger.LogInfo($"[DebugInfoInit] Found debug info file for module {imageName}: {ModuleDocument.DebugInfoFile.SymbolFile.FileName}"); DiagnosticLogger.LogInfo($"[DebugInfoInit] Debug file path: {ModuleDocument.DebugInfoFile.FilePath}"); DebugInfo = debugInfoProviderFactory_.CreateDebugInfoProvider(ModuleDocument.DebugInfoFile); HasDebugInfo = DebugInfo != null; if (HasDebugInfo) { // Also set on the document so GetOrCreateDebugInfoProvider can find it. ModuleDocument.DebugInfo = DebugInfo; DiagnosticLogger.LogInfo($"[DebugInfoInit] Successfully created debug info provider for module {imageName}"); if (ModuleDocument.Loader is DisassemblerSectionLoader disassemblerSectionLoader) { disassemblerSectionLoader.Initialize(DebugInfo); DiagnosticLogger.LogInfo($"[DebugInfoInit] Initialized disassembler with debug info for module {imageName}"); } } else { DiagnosticLogger.LogError($"[DebugInfoInit] Failed to create debug info provider for module {imageName}"); Trace.TraceWarning($"Failed to load debug info: {ModuleDocument.DebugInfoFile}"); } report_.AddDebugInfo(binaryInfo_, ModuleDocument.DebugInfoFile); return HasDebugInfo; } public async Task FindBinaryFilePath(SymbolFileSourceSettings settings) { // Use the symbol server to locate the image, // this will also attempt to download it if not found locally. return await binaryFileFinder_.FindBinaryFileAsync(binaryInfo_, settings).ConfigureAwait(false); } public (IRTextFunction Function, FunctionDebugInfo DebugInfo) GetOrCreateFunction(long funcAddress) { #if DEBUG Interlocked.Increment(ref FuncQueries); #endif bool shouldLog = loggedFuncAddresses_.TryAdd(funcAddress, true); // Returns true if newly added string moduleName = binaryInfo_?.ImageName ?? "Unknown"; // Try to get it form the concurrent dictionary first. if (functionMap_.TryGetValue(funcAddress, out var pair)) { #if DEBUG Interlocked.Increment(ref FuncFoundByAddress); #endif if (shouldLog) { DiagnosticLogger.LogInfo($"[FunctionResolution] Module: {moduleName}, Address: 0x{funcAddress:X}, Function: {pair.Item1.Name} (found in cache)"); } return pair; } // Find function outside lock to reduce contention. FunctionDebugInfo debugInfo = null; long funcStartAddress = funcAddress; if (HasDebugInfo) { // Search for the function at this RVA. debugInfo = DebugInfo.FindFunctionByRVA(funcAddress); if (debugInfo != null) { if (shouldLog) { DiagnosticLogger.LogInfo($"[FunctionResolution] Module: {moduleName}, Address: 0x{funcAddress:X}, Function: {debugInfo.Name} (resolved via debug info)"); } } else if (shouldLog) { DiagnosticLogger.LogWarning($"[FunctionResolution] Module: {moduleName}, Address: 0x{funcAddress:X}, Function: NOT_RESOLVED (debug info available but no symbol found)"); } } else if (shouldLog) { DiagnosticLogger.LogWarning($"[FunctionResolution] Module: {moduleName}, Address: 0x{funcAddress:X}, Function: NOT_RESOLVED (no debug info available)"); } if (debugInfo == null) { // Create a dummy debug entry for the missing function. string placeholderName = $"{funcAddress:X}"; debugInfo = new FunctionDebugInfo(placeholderName, funcAddress, 0); if (shouldLog) { DiagnosticLogger.LogWarning($"[FunctionResolution] Module: {moduleName}, Address: 0x{funcAddress:X}, Function: {placeholderName} (created placeholder)"); } } else { // Use the function start address from now on, this ensures // that a single instance of it is created. funcStartAddress = debugInfo.StartRVA; } // Check again under the write lock. if (functionMap_.TryGetValue(funcStartAddress, out pair)) { #if DEBUG Interlocked.Increment(ref FuncFoundByFuncAddress); #endif functionMap_.TryAdd(funcAddress, pair); return pair; } // Acquire write lock to create an entry for the function. lock_.EnterWriteLock(); // Check again under the write lock. if (functionMap_.TryGetValue(funcStartAddress, out pair)) { #if DEBUG Interlocked.Increment(ref FuncFoundByFuncAddressLocked); #endif lock_.ExitWriteLock(); return pair; } // Add the new function to the module and disassembler. var func = ModuleDocument.AddDummyFunction(debugInfo.Name); if (ModuleDocument.Loader is DisassemblerSectionLoader disassemblerSectionLoader) { disassemblerSectionLoader.RegisterFunction(func, debugInfo); } #if DEBUG Interlocked.Increment(ref FuncCreated); #endif // Cache RVA -> function mapping. pair = (func, debugInfo); if (funcStartAddress != funcAddress) { functionMap_.TryAdd(funcStartAddress, pair); } lock_.ExitWriteLock(); functionMap_.TryAdd(funcAddress, pair); return pair; } #if DEBUG public static void PrintStatistics() { Trace.WriteLine($"FuncQueries: {FuncQueries}"); Trace.WriteLine($"FuncFoundByAddress: {FuncFoundByAddress}"); Trace.WriteLine($"FuncFoundByFuncAddress: {FuncFoundByFuncAddress}"); Trace.WriteLine($"FuncFoundByFuncAddressLocked: {FuncFoundByFuncAddressLocked}"); Trace.WriteLine($"FuncCreated: {FuncCreated}"); } #endif private void CreateDummyDocument(BinaryFileDescriptor binaryInfo) { // Create a dummy document to represent the module, // AddPlaceholderFunction will populate it. ModuleDocument = LoadedDocument.CreateDummyDocument(binaryInfo.ImageName); Summary = ModuleDocument.Summary; // Set up lazy binary loading callback - this will be called when // user tries to view assembly/graph and binary hasn't been downloaded yet. ModuleDocument.EnsureBinaryLoaded = EnsureBinaryLoaded; } private async Task CreateLoadedDocument(string filePath, string modulePath, IRTextSectionLoader loader) { try { var result = await Task.Run(async () => { var result = new LoadedDocument(filePath, modulePath, Guid.NewGuid()); result.Loader = loader; result.Summary = await result.Loader.LoadDocument(null); return result; }); return result; } catch (Exception ex) { Trace.TraceError($"Failed to load document {filePath}: {ex}"); return null; } } public void Dispose() { disposed_ = true; lock_?.Dispose(); binaryLoadLock_?.Dispose(); } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/RawProfileData.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Collections; using ProfileExplorer.Core.Profile.ETW; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Profile.Data; [ProtoContract(SkipConstructor = true)] public class RawProfileData : IDisposable { private static ProfileContext tempContext_ = new(); private static ProfileStack tempStack_ = new(); // Per-thread caches to speed up lookups. [ThreadStatic] private static List<(int ProcessId, IpToImageCache Cache)> ipImageCache_; [ThreadStatic] private static ProfileImage lastIpImage_; [ThreadStatic] private static IpToImageCache globalIpImageCache_; /// /// Clears thread-local caches on the current thread /// public static void ClearThreadLocalCaches() { ipImageCache_ = null; lastIpImage_ = null; globalIpImageCache_ = null; } [ProtoMember(1)] private List samples_; [ProtoMember(2)] private Dictionary processes_; [ProtoMember(3)] private List threads_; [ProtoMember(4)] private List contexts_; [ProtoMember(5)] private List images_; [ProtoMember(6)] private List stacks_; [ProtoMember(7)] private List perfCounters_; [ProtoMember(8)] private CompressedSegmentedList perfCountersEvents_; [ProtoMember(9)] private ProfileTraceInfo traceInfo_; // Objects used only while building the profile. private Dictionary threadsMap_; private Dictionary contextsMap_; private Dictionary imagesMap_; private Dictionary> stacksMap_; private Dictionary> imageSymbols_; private HashSet stackData_; private Dictionary procManagedDataMap_; private Dictionary lastProcStacks_; private int lastProcId_; public RawProfileData(string tracePath, bool handlesDotNetEvents = false) { traceInfo_ = new ProfileTraceInfo(tracePath); contexts_ = new List(); contextsMap_ = new Dictionary(); images_ = new List(); imagesMap_ = new Dictionary(); processes_ = new Dictionary(); threads_ = new List(); threadsMap_ = new Dictionary(); stacks_ = new List(); stacksMap_ = new Dictionary>(); stackData_ = new HashSet(new StackComparer()); samples_ = new List(); perfCounters_ = new List(); imageSymbols_ = new Dictionary>(); if (handlesDotNetEvents) { procManagedDataMap_ = new Dictionary(); } } public ProfileTraceInfo TraceInfo => traceInfo_; public List Samples => samples_; public List Processes => processes_.ToValueList(); public List Threads => threads_; public List Images => images_; public CompressedSegmentedList PerformanceCountersEvents => perfCountersEvents_; public List PerformanceCounters => perfCounters_; public bool HasPerformanceCountersEvents => PerformanceCountersEvents is {Count: > 0}; public void Dispose() { perfCountersEvents_?.Dispose(); } public bool HasManagedMethods(int processId) { return procManagedDataMap_ != null && procManagedDataMap_.ContainsKey(processId); } public int ComputeSampleChunkLength(int chunks) { int chunkSize = Math.Max(1, samples_.Count / chunks); chunkSize = CompressedSegmentedList.RoundUpToSegmentLength(chunkSize); return Math.Min(chunkSize, samples_.Count); } public int ComputePerfCounterChunkLength(int chunks) { if (perfCountersEvents_ == null) { return 0; } int chunkSize = Math.Max(1, perfCountersEvents_.Count / chunks); chunkSize = CompressedSegmentedList.RoundUpToSegmentLength(chunkSize); return Math.Min(chunkSize, perfCountersEvents_.Count); } public void AddManagedMethodMapping(long moduleId, long methodId, long rejitId, FunctionDebugInfo functionDebugInfo, long ip, int size, int processId) { var (moduleDebugInfo, moduleImage) = GetModuleDebugInfo(processId, moduleId); var mapping = new ManagedMethodMapping(functionDebugInfo, moduleImage, moduleId, ip, size); var data = GetOrCreateManagedData(processId); data.managedMethods_.Add(mapping); if (moduleImage == null) { // A placeholder is created for cases where the method load event // is triggered before the module load one, add mapping to patch list // to have the image filled in later. data.patchedMappings_.Add((moduleId, mapping)); } //? TODO: MethodID is identical between opt levels, either split by level or use time like TraceEvent string initialName = functionDebugInfo.Name; //if (data.managedMethodsMap_.TryGetValue(initialName, out var other)) { // if (other.FunctionDebugInfo.HasOptimizationLevel && // !other.FunctionDebugInfo.Name.EndsWith(other.FunctionDebugInfo.OptimizationLevel)) { // other.FunctionDebugInfo.UpdateName($"{other.FunctionDebugInfo.Name}_{other.FunctionDebugInfo.OptimizationLevel}"); // } // if (functionDebugInfo.HasOptimizationLevel) { // functionDebugInfo.UpdateName($"{functionDebugInfo.Name}_{functionDebugInfo.OptimizationLevel}"); // } //} moduleDebugInfo.AddFunctionInfo(functionDebugInfo); data.managedMethodIdMap_[new ManagedMethodId(methodId, rejitId)] = mapping; data.managedMethodsMap_[initialName] = mapping; } public void AddManagedMethodCode(long functionId, int rejitId, int processId, long address, int codeSize, byte[] codeBytes) { var info = new DotNetDebugInfoProvider.MethodCode(address, codeSize, codeBytes); var data = GetOrCreateManagedData(processId); data.managedMethodCodeMap_[new ManagedMethodId(functionId, rejitId)] = info; } public void AddManagedMethodCallTarget(long functionId, int rejitId, int processId, long address, string name) { var data = GetOrCreateManagedData(processId); if (data.managedMethodCodeMap_.TryGetValue(new ManagedMethodId(functionId, rejitId), out var code)) { code.CallTargets.Add(new DotNetDebugInfoProvider.AddressNamePair(address, name)); } } public ManagedMethodMapping FindManagedMethodForIP(long ip, int processId) { var data = GetOrCreateManagedData(processId); return ManagedMethodMapping.BinarySearch(data.managedMethods_, ip); } public ManagedMethodMapping FindManagedMethod(long id, long rejitId, int processId) { var data = GetOrCreateManagedData(processId); return data.managedMethodIdMap_.GetValueOrNull(new ManagedMethodId(id, rejitId)); } public IDebugInfoProvider GetDebugInfoForManagedImage(ProfileImage image, int processId) { if (!HasManagedMethods(processId)) { return null; } var data = GetOrCreateManagedData(processId); return data.imageDebugInfo_?.GetValueOrNull(image); } public void AddDebugFileForImage(SymbolFileDescriptor symbolFile, long imageBase, int processId) { var procImageSymbols = imageSymbols_.GetOrAddValue(processId); procImageSymbols[imageBase] = symbolFile; } public SymbolFileDescriptor GetDebugFileForImage(ProfileImage image, int processId) { int originalProcessId = processId; // If the module is loaded in kernel address space, // look for the debug info entry in the kernel process. if (ETWEventProcessor.IsKernelAddress((ulong)image.BaseAddress, TraceInfo.PointerSize)) { processId = ETWEventProcessor.KernelProcessId; } var procImageSymbols = imageSymbols_.GetOrAddValue(processId); if (procImageSymbols == null) { return null; } var result = procImageSymbols.GetValueOrNull(image.BaseAddress); // Debug logging for missing symbol files - important system DLLs if (result == null && (image.ModuleName.Contains("ntdll", StringComparison.OrdinalIgnoreCase) || image.ModuleName.Contains("win32u", StringComparison.OrdinalIgnoreCase) || image.ModuleName.Contains("user32", StringComparison.OrdinalIgnoreCase) || image.ModuleName.Contains("kernel32", StringComparison.OrdinalIgnoreCase) || image.ModuleName.Contains("combase", StringComparison.OrdinalIgnoreCase))) { var availableBases = procImageSymbols.Keys.Take(20).Select(k => $"0x{k:X}"); string message = $"[SymbolLookup] {image.ModuleName} ImageID_DbgID not found! " + $"ProcessId={processId} (original={originalProcessId}), BaseAddress=0x{image.BaseAddress:X}. " + $"First 20 available bases: {string.Join(", ", availableBases)}"; // Log to both VS Output (Trace) and diagnostic file System.Diagnostics.Trace.WriteLine(message); Utilities.DiagnosticLogger.LogWarning(message); } return result; } public DotNetDebugInfoProvider GetOrAddManagedModuleDebugInfo(int processId, string moduleName, long moduleId, Machine architecture) { var data = GetOrCreateManagedData(processId); var proc = GetOrCreateProcess(processId); foreach (var image in proc.Images(this)) { //? TODO: Avoid linear search if (image.ModuleName.Equals(moduleName, StringComparison.OrdinalIgnoreCase)) { if (!data.imageDebugInfo_.TryGetValue(image, out var debugInfo)) { // A placeholder is created for cases where the method load event // is triggered before the module load one, use that provider. if (!data.moduleDebugInfoMap_.TryGetValue(moduleId, out debugInfo)) { debugInfo = new DotNetDebugInfoProvider(architecture); } else { debugInfo.UpdateArchitecture(architecture); foreach (var pair in data.patchedMappings_) { if (pair.ModuleId == moduleId) { pair.Mapping.Image = image; } } } data.imageDebugInfo_[image] = debugInfo; data.moduleDebugInfoMap_[moduleId] = debugInfo; data.moduleImageMap_[moduleId] = image; } return debugInfo; } } return null; } public (DotNetDebugInfoProvider, ProfileImage) GetModuleDebugInfo(int processId, long moduleId) { var data = GetOrCreateManagedData(processId); var debugInfo = data.moduleDebugInfoMap_.GetValueOrNull(moduleId); var image = data.moduleImageMap_.GetValueOrNull(moduleId); if (debugInfo == null) { // Module loaded event not triggered yet, create a placeholder for now. debugInfo = new DotNetDebugInfoProvider(Machine.Unknown); data.moduleDebugInfoMap_[moduleId] = debugInfo; } return (debugInfo, image); } public void LoadingCompleted() { // Free objects used only during trace event processing. stacksMap_ = null; contextsMap_ = null; imagesMap_ = null; threadsMap_ = null; stackData_ = null; lastProcStacks_ = null; // Wait for any compression tasks. perfCountersEvents_?.Wait(); } /// /// Adds an image directly to the images list and assigns it a sequential ID, /// bypassing deduplication. Safe to call after LoadingCompleted(). /// public void AddImageDirect(ProfileImage image) { if (imagesMap_ != null) { throw new InvalidOperationException( "AddImageDirect can only be called after LoadingCompleted() has been invoked."); } images_.Add(image); image.Id = images_.Count; } public void ManagedLoadingCompleted() { if (procManagedDataMap_ != null) { foreach (var pair in procManagedDataMap_) { pair.Value.LoadingCompleted(pair.Key); } } } public ProfileProcess GetOrCreateProcess(int id) { if (processes_.TryGetValue(id, out var process)) { return process; } return processes_.GetOrAddValue(id, () => new ProfileProcess(id)); } public void AddProcess(ProfileProcess process) { processes_[process.ProcessId] = process; } public int AddImage(ProfileImage image) { if (!imagesMap_.TryGetValue(image, out int existingImageId)) { images_.Add(image); int id = images_.Count; image.Id = id; imagesMap_[image] = id; existingImageId = id; } return existingImageId; } public ProfileImage FindImage(int id) { Debug.Assert(id > 0 && id <= images_.Count); return images_[id - 1]; } public ProfileImage FindImageByTimestamp(int timestamp) { foreach (var image in images_) { if (image.TimeStamp == timestamp) { return image; } } return null; } public int AddThread(ProfileThread thread) { if (!threadsMap_.TryGetValue(thread, out int existingThread)) { threads_.Add(thread); existingThread = threads_.Count; threadsMap_[thread] = threads_.Count; } return existingThread; } public ProfileThread FindThread(int id) { Debug.Assert(id > 0 && id <= threads_.Count); return threads_[id - 1]; } public int AddThreadToProcess(int processId, ProfileThread thread) { var proc = GetOrCreateProcess(processId); int result = AddThread(thread); proc.AddThread(result); return result; } public int AddImageToProcess(int processId, ProfileImage image) { var proc = GetOrCreateProcess(processId); int result = AddImage(image); proc.AddImage(result); return result; } public int AddSample(ProfileSample sample) { Debug.Assert(sample.ContextId != 0); samples_.Add(sample); return samples_.Count; } public bool TrySetSampleStack(int sampleId, int stackId, long frameIp, int contextId) { if (sampleId == 0) { return false; } if (samples_[sampleId - 1].ContextId == contextId && samples_[sampleId - 1].IP == frameIp) { SetSampleStack(sampleId, stackId, contextId); return true; } return false; } public void SetSampleStack(int sampleId, int stackId, int contextId) { // Change the stack ID in-place in the array. Debug.Assert(samples_[sampleId - 1].ContextId == contextId); CollectionsMarshal.AsSpan(samples_)[sampleId - 1].StackId = stackId; } public int AddPerformanceCounter(PerformanceCounter counter) { perfCounters_.Add(counter); return perfCounters_.Count; } public int AddPerformanceCounterEvent(PerformanceCounterEvent counterEvent) { Debug.Assert(counterEvent.ContextId != 0); perfCountersEvents_ ??= new CompressedSegmentedList(); perfCountersEvents_.Add(counterEvent); return perfCountersEvents_.Count; } public ProfileContext FindContext(int id) { Debug.Assert(id > 0 && id <= contexts_.Count); return contexts_[id - 1]; } public int AddStack(ProfileStack stack, ProfileContext context) { Debug.Assert(stack.ContextId != 0); Dictionary procStacks = null; if (lastProcId_ == context.ProcessId && lastProcStacks_ != null) { procStacks = lastProcStacks_; } else { if (!stacksMap_.TryGetValue(context.ProcessId, out procStacks)) { procStacks = new Dictionary(); stacksMap_[context.ProcessId] = procStacks; } lastProcId_ = context.ProcessId; lastProcStacks_ = procStacks; } if (!procStacks.TryGetValue(stack, out int existingStackId)) { // De-duplicate the stack frame pointer array, // since lots of samples have identical stacks. if (!stackData_.TryGetValue(stack.FramePointers, out long[] framePtrData)) { // Make a clone since the temporary stack uses a static array. framePtrData = stack.CloneFramePointers(); stackData_.Add(framePtrData); } var newStack = new ProfileStack(stack.ContextId, framePtrData); stacks_.Add(newStack); procStacks[newStack] = stacks_.Count; existingStackId = stacks_.Count; } else { Debug.Assert(stack == FindStack(existingStackId)); } stack.Discard(); return existingStackId; } public void ReplaceStackFramePointers(ProfileStack stack, long[] newFramePtrs, ProfileContext context) { if (stacksMap_.TryGetValue(context.ProcessId, out var procStacks)) { procStacks.Remove(stack); } stack.FramePointers = newFramePtrs; AddStack(stack, context); } public ProfileStack FindStack(int id) { Debug.Assert(id > 0 && id <= stacks_.Count); return stacks_[id - 1]; } public ProfileProcess FindProcess(string name, bool allowSubstring = false) { foreach (var process in processes_.Values) { if (process.Name == name) { return process; } } if (allowSubstring) { foreach (var process in processes_.Values) { if (process.Name.Contains(name)) { return process; } } } return null; } public ProfileProcess FindProcess(int processId) { return processes_.GetValueOrNull(processId); } public ProfileImage FindImage(ProfileProcess process, BinaryFileDescriptor info) { foreach (var image in process.Images(this)) { if (image.FilePath == info.ImageName && image.TimeStamp == info.TimeStamp && image.Checksum == info.Checksum) { return image; } } return null; } public ProfileImage FindImageForIP(long ip, ProfileContext context) { return FindImageForIP(ip, context.ProcessId); } public ProfileImage FindImageForIP(long ip, int processId) { // lastIpImage_ and ipImageCache_ are thread-local, // making this function thread-safe. if (lastIpImage_ != null && lastIpImage_.HasAddress(ip)) { return lastIpImage_; } ipImageCache_ ??= new List<(int ProcessId, IpToImageCache Cache)>(); IpToImageCache cache = null; foreach (var entry in ipImageCache_) { if (entry.ProcessId == processId) { cache = entry.Cache; break; } } if (cache == null) { var process = GetOrCreateProcess(processId); cache = IpToImageCache.Create(process.Images(this)); ipImageCache_.Add((processId, cache)); } if (!cache.IsValidAddres(ip)) { return null; } var result = cache.Find(ip); if (result != null) { lastIpImage_ = result; return result; } // Trace.WriteLine($"No image for ip {ip:X}"); return null; } public ProfileImage FindImageForIP(long ip) { if (globalIpImageCache_ == null) { // Per-thread, no locks needed. globalIpImageCache_ = IpToImageCache.Create(images_); } return globalIpImageCache_.Find(ip); } public List BuildProcessSummary() { var builder = new ProcessSummaryBuilder(this); foreach (var sample in samples_) { builder.AddSample(sample); } return builder.MakeSummaries(); } public void PrintProcess(int processId) { var proc = GetOrCreateProcess(processId); if (proc != null) { Trace.WriteLine($"Process {proc}"); foreach (var image in proc.Images(this)) { Trace.WriteLine($"Image: {image}"); if (HasManagedMethods(proc.ProcessId)) { var data = GetOrCreateManagedData(proc.ProcessId); Trace.WriteLine($" o methods: {data.managedMethods_.Count}"); Trace.WriteLine($" o hasDebug: {data.imageDebugInfo_ != null && data.imageDebugInfo_.ContainsKey(image)}"); } } } } public void PrintAllProcesses() { Trace.WriteLine($"Profile processes: {processes_.Count}"); foreach (var proc in processes_) { Trace.WriteLine($"- {proc}"); } } public void PrintPerfCounters(int processId) { if (perfCountersEvents_ == null) { return; } foreach (var sample in perfCountersEvents_) { var context = sample.GetContext(this); if (context.ProcessId == processId) { Trace.WriteLine($"{sample}"); } } } public void PrintSamples(int processId) { foreach (var sample in samples_) { var context = sample.GetContext(this); if (context.ProcessId == processId) { Trace.WriteLine($"{sample}"); } } } internal ProfileContext RentTempContext(int processId, int threadId, int processorNumber) { tempContext_.ProcessId = processId; tempContext_.ThreadId = threadId; tempContext_.ProcessorNumber = processorNumber; return tempContext_; } internal void ReturnContext(int contextId) { var context = FindContext(contextId); if (ReferenceEquals(context, tempContext_)) { tempContext_ = new ProfileContext(); } } internal int AddContext(ProfileContext context) { ref int existingContextId = ref CollectionsMarshal.GetValueRefOrAddDefault(contextsMap_, context, out bool exists); if (!exists) { contexts_.Add(context); existingContextId = contexts_.Count; } return existingContextId; } internal ProfileStack RentTemporaryStack(int frameCount, int contextId) { tempStack_.SetTempFramePointers(frameCount); tempStack_.ContextId = contextId; return tempStack_; } internal void ReturnStack(int stackId) { var stack = FindStack(stackId); if (ReferenceEquals(stack, tempStack_)) { tempStack_ = new ProfileStack(); } } private ManagedRawProfileData GetOrCreateManagedData(int processId) { if (!procManagedDataMap_.TryGetValue(processId, out var data)) { data = new ManagedRawProfileData(); procManagedDataMap_[processId] = data; } return data; } } public class StackComparer : IEqualityComparer { public bool Equals(long[] data1, long[] data2) { return AreEqual(data1, data2); } public int GetHashCode(long[] data) { return ComputeHashCode(data); } public static bool AreEqual(long[] data1, long[] data2) { if (data1.Length != data2.Length) { return false; } return data1.AsSpan().SequenceEqual(data2.AsSpan()); } public static int ComputeHashCode(long[] data) { HashCode hash = new(); hash.AddBytes(MemoryMarshal.AsBytes(data.AsSpan())); return hash.ToHashCode(); } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/RawProfileModel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Profile.Data; [ProtoContract(SkipConstructor = true)] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ProfileSample : IEquatable { [ProtoMember(1)] public long IP { get; set; } [ProtoMember(2)] public TimeSpan Time { get; set; } [ProtoMember(3)] public TimeSpan Weight { get; set; } [ProtoMember(4)] public int StackId { get; set; } [ProtoMember(5)] public int ContextId { get; set; } [ProtoMember(6)] public bool IsKernelCode { get; set; } public bool HasStack => StackId != 0; //public ProfileSample() {} public ProfileSample(long ip, TimeSpan time, TimeSpan weight, bool isKernelCode, int contextId) { IP = ip; Time = time; Weight = weight; StackId = 0; IsKernelCode = isKernelCode; ContextId = contextId; } public ProfileStack GetStack(RawProfileData profileData) { return StackId != 0 ? profileData.FindStack(StackId) : ProfileStack.Unknown; } public ProfileContext GetContext(RawProfileData profileData) { return profileData.FindContext(ContextId); } public bool Equals(ProfileSample other) { return IP == other.IP && Time == other.Time && Weight == other.Weight && StackId == other.StackId && ContextId == other.ContextId && IsKernelCode == other.IsKernelCode; } public override bool Equals(object obj) { return obj is ProfileSample other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(IP, Time, StackId, ContextId); } public static bool operator ==(ProfileSample left, ProfileSample right) { return Equals(left, right); } public static bool operator !=(ProfileSample left, ProfileSample right) { return !Equals(left, right); } public override string ToString() { return $"{IP:X}, Weight: {Weight.Ticks}, StackId: {StackId}"; } } [ProtoContract(SkipConstructor = true)] [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PerformanceCounterEvent : IEquatable { [ProtoMember(1)] public long IP { get; set; } [ProtoMember(2)] public TimeSpan Time { get; set; } [ProtoMember(3)] public int ContextId { get; set; } [ProtoMember(4)] public short CounterId; public PerformanceCounterEvent(long ip, TimeSpan time, int contextId, short counterId) { IP = ip; Time = time; ContextId = contextId; CounterId = counterId; } public ProfileContext GetContext(RawProfileData profileData) { return profileData.FindContext(ContextId); } public bool Equals(PerformanceCounterEvent other) { return Time == other.Time && IP == other.IP && ContextId == other.ContextId && CounterId == other.CounterId; } public override bool Equals(object obj) { return obj is PerformanceCounterEvent other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(Time, IP, ContextId, CounterId); } public override string ToString() { return $"PMC {CounterId}: {IP:X}, {Time}"; } } [ProtoContract(SkipConstructor = true)] public class ProfileStack : IEquatable { private const int MaxFrameNumber = 512; private static long[][] TempFrameArrays = new long[MaxFrameNumber + 1][]; public static readonly ProfileStack Unknown = new(); private object optionalData_; static ProfileStack() { // The frame ptr. array is being interned (unique instance) // later, use a pre-allocated array initially to reduce GC pressure. // Note: this also means creating ProfileStack must be single-threaded. for (int i = 0; i <= MaxFrameNumber; i++) { TempFrameArrays[i] = new long[i]; } } public ProfileStack() { FramePointers = null; ContextId = 0; } public ProfileStack(int contextId, int frameCount) { ContextId = contextId; FramePointers = RentArray(frameCount); } public ProfileStack(int contextId, long[] framePtrs) { ContextId = contextId; FramePointers = framePtrs; } [ProtoMember(1)] public long[] FramePointers { get; set; } [ProtoMember(2)] public int ContextId { get; set; } [ProtoMember(3)] public int UserModeTransitionIndex { get; set; } public bool IsUnknown => FramePointers == null; public int FrameCount => FramePointers.Length; public bool Equals(ProfileStack other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } // FramePointers is allocated using interning, ref. equality is sufficient. return ContextId == other.ContextId && UserModeTransitionIndex == other.UserModeTransitionIndex && FramePointers == other.FramePointers; } public static bool operator ==(ProfileStack left, ProfileStack right) { return Equals(left, right); } public static bool operator !=(ProfileStack left, ProfileStack right) { return !Equals(left, right); } public object GetOptionalData() { Interlocked.MemoryBarrier(); return optionalData_; } public void SetOptionalData(object value) { optionalData_ = value; Interlocked.MemoryBarrier(); } public long[] CloneFramePointers() { long[] clone = new long[FramePointers.Length]; FramePointers.CopyTo(clone, 0); return clone; } public void SetTempFramePointers(int frameCount) { FramePointers = RentArray(frameCount); } public ProfileImage FindImageForFrame(int frameIndex, RawProfileData profileData) { return profileData.FindImageForIP(FramePointers[frameIndex], profileData.FindContext(ContextId)); } public void Discard() { ReturnArray(FramePointers); } public override bool Equals(object obj) { return obj is ProfileStack other && Equals(other); } public override int GetHashCode() { int framePtrHash = StackComparer.ComputeHashCode(FramePointers); return HashCode.Combine(framePtrHash, ContextId); } public override string ToString() { return $"#{FrameCount}, ContextId: {ContextId}"; } private long[] RentArray(int frameCount) { // In most cases one of the pre-allocated temporary arrays can be used. long[] array; if (frameCount <= MaxFrameNumber) { array = TempFrameArrays[frameCount]; #if DEBUG Debug.Assert(array != null); TempFrameArrays[frameCount] = null; #endif } else { array = new long[frameCount]; } return array; } private void ReturnArray(long[] array) { #if DEBUG if (array.Length <= MaxFrameNumber) { TempFrameArrays[array.Length] = array; } #endif } } [ProtoContract(SkipConstructor = true)] public class ProfileTraceInfo { public ProfileTraceInfo(string tracePath = null) { TraceFilePath = tracePath; } [ProtoMember(1)] public DateTime ProfileStartTime { get; set; } [ProtoMember(2)] public DateTime ProfileEndTime { get; set; } [ProtoMember(3)] public int CpuCount { get; set; } [ProtoMember(4)] public int CpuSpeed { get; set; } [ProtoMember(5)] public int PointerSize { get; set; } [ProtoMember(6)] public int MemorySize { get; set; } [ProtoMember(7)] public string ComputerName { get; set; } [ProtoMember(8)] public string DomainName { get; set; } [ProtoMember(9)] public string TraceFilePath { get; set; } [ProtoMember(10)] public TimeSpan SamplingInterval { get; set; } [ProtoMember(11)] public int ImageLoadEventCount { get; set; } [ProtoMember(12)] public int ImageLoadWithTimestampCount { get; set; } [ProtoMember(13)] public int ImageIdEventCount { get; set; } [ProtoMember(14)] public int ImageIdDbgEventCount { get; set; } public bool Is64Bit => PointerSize == 8; public TimeSpan ProfileDuration => ProfileEndTime - ProfileStartTime; public bool HasImageIdEvents => ImageIdDbgEventCount > 0; /// /// True if trace has valid binary lookup info (timestamps for symbol server). /// public bool HasValidBinaryLookupInfo => ImageLoadWithTimestampCount > 0; public bool HasSameTraceFilePath(ProfileTraceInfo other) { if (!string.IsNullOrEmpty(TraceFilePath) && !string.IsNullOrEmpty(other.TraceFilePath)) { return string.Equals(TraceFilePath, other.TraceFilePath, StringComparison.OrdinalIgnoreCase); } return string.IsNullOrEmpty(TraceFilePath) && string.IsNullOrEmpty(other.TraceFilePath); } } [ProtoContract(SkipConstructor = true)] public sealed class ProfileContext : IEquatable { public ProfileContext() { } public ProfileContext(int processId, int threadId, int processorNumber) { ProcessId = processId; ThreadId = threadId; ProcessorNumber = processorNumber; } [ProtoMember(1)] public int ProcessId { get; set; } [ProtoMember(2)] public int ThreadId { get; set; } [ProtoMember(3)] public int ProcessorNumber { get; set; } public bool Equals(ProfileContext other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } return ProcessId == other.ProcessId && ThreadId == other.ThreadId && ProcessorNumber == other.ProcessorNumber; } public static bool operator ==(ProfileContext left, ProfileContext right) { return Equals(left, right); } public static bool operator !=(ProfileContext left, ProfileContext right) { return !Equals(left, right); } public ProfileProcess GetProcess(RawProfileData profileData) { return profileData.GetOrCreateProcess(ProcessId); } public ProfileThread GetThread(RawProfileData profileData) { return profileData.FindThread(ThreadId); } public override bool Equals(object other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } if (other.GetType() != GetType()) { return false; } return Equals((ProfileContext)other); } public override int GetHashCode() { return HashCode.Combine(ProcessId, ThreadId, ProcessorNumber); } public override string ToString() { return $"ProcessId: {ProcessId}, ThreadId: {ThreadId}, Processor: {ProcessorNumber}"; } } [ProtoContract(SkipConstructor = true)] public sealed class ProfileImage : IEquatable, IComparable { public ProfileImage() { } public ProfileImage(string filePath, string originalFileName, long baseAddress, long defaultBaseAddress, int size, int timeStamp, long checksum) { Size = size; FilePath = filePath != null ? string.Intern(filePath) : null; OriginalFileName = originalFileName != null ? string.Intern(originalFileName) : null; BaseAddress = baseAddress; DefaultBaseAddress = defaultBaseAddress; TimeStamp = timeStamp; Checksum = checksum; } [ProtoMember(1)] public int Id { get; set; } [ProtoMember(2)] public int Size { get; set; } [ProtoMember(3)] public long BaseAddress { get; set; } [ProtoMember(4)] public long DefaultBaseAddress { get; set; } [ProtoMember(5)] public string FilePath { get; set; } [ProtoMember(6)] public string OriginalFileName { get; set; } [ProtoMember(7)] public int TimeStamp { get; set; } [ProtoMember(8)] public long Checksum { get; set; } [ProtoMember(9)] public string CompanyName { get; set; } [ProtoMember(10)] public string FileDescription { get; set; } [ProtoMember(11)] public string ProductName { get; set; } public long BaseAddressEnd => BaseAddress + Size; public string ModuleName => Utilities.Utils.TryGetFileName(FilePath); /// /// Returns true if this appears to be a Microsoft binary based on version info from trace. /// Checks CompanyName, FileDescription, and ProductName fields. /// public bool IsMicrosoft => (!string.IsNullOrEmpty(CompanyName) && CompanyName.Contains("Microsoft", StringComparison.OrdinalIgnoreCase)) || (!string.IsNullOrEmpty(FileDescription) && FileDescription.Contains("Microsoft", StringComparison.OrdinalIgnoreCase)) || (!string.IsNullOrEmpty(ProductName) && ProductName.Contains("Microsoft", StringComparison.OrdinalIgnoreCase)); public int CompareTo(ProfileImage other) { if (BaseAddress < other.BaseAddress && BaseAddressEnd < other.BaseAddressEnd) { return -1; } if (BaseAddress > other.BaseAddress && BaseAddressEnd > other.BaseAddressEnd) { return 1; } return 0; } public bool Equals(ProfileImage other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } return Size == other.Size && FilePath == other.FilePath && Checksum == other.Checksum; } public static bool operator ==(ProfileImage left, ProfileImage right) { return Equals(left, right); } public static bool operator !=(ProfileImage left, ProfileImage right) { return !Equals(left, right); } public bool HasAddress(long ip) { return ip >= BaseAddress && ip < BaseAddress + Size; } public override int GetHashCode() { return HashCode.Combine(Size, FilePath, Checksum); } public override bool Equals(object other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } if (other.GetType() != GetType()) { return false; } return Equals((ProfileImage)other); } public int CompareTo(long value) { if (value < BaseAddress) { return 1; } if (value > BaseAddressEnd) { return -1; } return 0; } public override string ToString() { return $"ModuleName: {ModuleName}, FilePath: {FilePath}, Id: {Id}, Base: {BaseAddress:X}, DefaultBase: {DefaultBaseAddress:X} Size: {Size}, Checksum {Checksum:X}"; } } [ProtoContract(SkipConstructor = true)] public sealed class ProfileProcess : IEquatable { public ProfileProcess() { InitializeReferenceMembers(); } public ProfileProcess(int processId, int parentId, string name, string imageFileName, string commandLine) : this() { ProcessId = processId; ParentId = parentId; Name = name; ImageFileName = imageFileName; CommandLine = commandLine; } public ProfileProcess(int processId, string imageFileName = null) : this() { ProcessId = processId; ImageFileName = imageFileName; } [ProtoMember(1)] public int ProcessId { get; set; } [ProtoMember(2)] public int ParentId { get; set; } [ProtoMember(3)] public string Name { get; set; } [ProtoMember(4)] public string ImageFileName { get; set; } [ProtoMember(5)] public string CommandLine { get; set; } [ProtoMember(6)] public List ImageIds { get; set; } [ProtoMember(7)] public List ThreadIds { get; set; } [ProtoMember(8)] public DateTime StartTime { get; set; } [ProtoMember(9)] public bool IsWow64 { get; set; } // True if 32-bit process on 64-bit OS (WoW64) public bool Equals(ProfileProcess other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } return ProcessId == other.ProcessId && Name == other.Name; } public static bool operator ==(ProfileProcess left, ProfileProcess right) { return Equals(left, right); } public static bool operator !=(ProfileProcess left, ProfileProcess right) { return !Equals(left, right); } public IEnumerable Images(RawProfileData profileData) { foreach (int id in ImageIds) { yield return profileData.FindImage(id); } } public IEnumerable Threads(RawProfileData profileData) { foreach (int id in ThreadIds) { yield return profileData.FindThread(id); } } public ProfileThread FindThread(int threadId, RawProfileData profileData) { foreach (int id in ThreadIds) { var thread = profileData.FindThread(id); if (thread.ThreadId == threadId) { return thread; } } return null; } public void AddImage(int imageId) { if (!ImageIds.Contains(imageId)) { ImageIds.Add(imageId); } } public void AddThread(int threadId) { if (!ThreadIds.Contains(threadId)) { ThreadIds.Add(threadId); } } public override bool Equals(object other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } if (other.GetType() != GetType()) { return false; } return Equals((ProfileProcess)other); } public override int GetHashCode() { return HashCode.Combine(ProcessId, Name); } public override string ToString() { return $"{Name}, ImageFileName {ImageFileName}, ID: {ProcessId}, ParentID: {ParentId}, Images: {ImageIds.Count}, Threads: {ThreadIds.Count}"; } [ProtoAfterDeserialization] private void InitializeReferenceMembers() { ImageIds ??= new List(); ThreadIds ??= new List(); } } [ProtoContract(SkipConstructor = true)] public sealed class ProfileThread : IEquatable { public ProfileThread() { } public ProfileThread(int threadId, int processId, string name) { ThreadId = threadId; ProcessId = processId; Name = name; } [ProtoMember(1)] public int ThreadId { get; set; } [ProtoMember(2)] public int ProcessId { get; set; } [ProtoMember(3)] public string Name { get; set; } [ProtoMember(4)] public long Win32StartAddr { get; set; } public bool HasName => !string.IsNullOrEmpty(Name); public bool Equals(ProfileThread other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } return ThreadId == other.ThreadId && ProcessId == other.ProcessId; } public static bool operator ==(ProfileThread left, ProfileThread right) { return Equals(left, right); } public static bool operator !=(ProfileThread left, ProfileThread right) { return !Equals(left, right); } public override bool Equals(object other) { Debug.Assert(other != null); if (ReferenceEquals(this, other)) { return true; } if (other.GetType() != GetType()) { return false; } return Equals((ProfileThread)other); } public override int GetHashCode() { return HashCode.Combine(ThreadId, ProcessId); } public override string ToString() { return $"{ThreadId}, ProcessId: {ProcessId}, Name: {Name}"; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Data/ResolvedProfileStack.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.InteropServices; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.ETW; namespace ProfileExplorer.Core.Profile.Data; // Represents a resolved stack frame with details about the function and image it belongs to. // To reduce memory usage, the RVA field is stored in a derived class with the smallest possible size, // with the most common RVAs being values that fit in 16 or 32 bits. [StructLayout(LayoutKind.Sequential, Pack = 1)] public class ResolvedProfileStackFrame { public ResolvedProfileStackFrameDetails FrameDetails { get; set; } public virtual long FrameRVA { get; set; } public long FrameIP { get; set; } public ResolvedProfileStackFrame(long frameRva, ResolvedProfileStackFrameDetails frameDetails) { FrameRVA = frameRva; FrameDetails = frameDetails; } protected ResolvedProfileStackFrame(ResolvedProfileStackFrameDetails frameDetails) { FrameDetails = frameDetails; } public static ResolvedProfileStackFrame CreateStackFrame(long frameRVA, ResolvedProfileStackFrameDetails frameDetails) { // Pick a type of frame that has an RVA field just large enough // to hold the value, this reduces memory usage since most RVAs don't need 64 bits. if ((ulong)frameRVA <= 0xFFFF) { return new ResolvedProfileStackFrame16((ushort)frameRVA, frameDetails); } else if ((ulong)frameRVA <= 0xFFFFFFFF) { return new ResolvedProfileStackFrame32((uint)frameRVA, frameDetails); } return new ResolvedProfileStackFrame(frameRVA, frameDetails); } public bool IsUnknown => FrameDetails.IsUnknown; } // Stack frame with 16-bit RVA, used to reduce memory usage. [StructLayout(LayoutKind.Sequential, Pack = 1)] public class ResolvedProfileStackFrame16 : ResolvedProfileStackFrame { private ushort frameRva_; public override long FrameRVA { get => frameRva_; set => frameRva_ = (ushort)value; } public ResolvedProfileStackFrame16(ushort frameRva, ResolvedProfileStackFrameDetails frameDetails) : base(frameDetails) { frameRva_ = frameRva; } } // Stack frame with 32-bit RVA, used to reduce memory usage. [StructLayout(LayoutKind.Sequential, Pack = 1)] public class ResolvedProfileStackFrame32 : ResolvedProfileStackFrame { private uint frameRva_; public override long FrameRVA { get => frameRva_; set => frameRva_ = (ushort)value; } public ResolvedProfileStackFrame32(uint frameRva, ResolvedProfileStackFrameDetails frameDetails) : base(frameDetails) { frameRva_ = frameRva; } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public sealed class ResolvedProfileStack { // Used to deduplicate stack frames for the same function running in the same context. public static ConcurrentDictionary uniqueFrames_ = new(); // Stack frames with the same IP have a unique instance shared among all call stacks. public static ConcurrentDictionary frameInstances_ = new(); public static ConcurrentDictionary kernelFrameInstances_ = new(); /// /// Clears all static frame caches. Must be called before processing a new trace /// to prevent stale frame references from a previous session. /// public static void ResetCaches() { uniqueFrames_.Clear(); frameInstances_.Clear(); kernelFrameInstances_.Clear(); } public ResolvedProfileStack(int frameCount, ProfileContext context) { StackFrames = new List(frameCount); Context = context; } public List StackFrames { get; set; } public ProfileContext Context { get; set; } public int FrameCount => StackFrames.Count; public void AddFrame(IRTextFunction function, long frameIP, long frameRVA, int frameIndex, ResolvedProfileStackFrameKey frameDetails, ProfileStack stack, int pointerSize) { // Deduplicate the frame. var uniqueFrame = uniqueFrames_.GetOrAdd(frameDetails, CreateResolvedProfileStackFrameDetails, function); var rvaFrame = ResolvedProfileStackFrame.CreateStackFrame(frameRVA, uniqueFrame); rvaFrame.FrameIP = frameIP; // A stack frame IP can be called from both user and kernel mode code. uniqueFrame.IsKernelCode = frameIndex < stack.UserModeTransitionIndex; if (ETWEventProcessor.IsKernelAddress((ulong)frameIP, 8) && !uniqueFrame.IsKernelCode) { uniqueFrame.IsKernelCode = true; } var existingFrame = uniqueFrame.IsKernelCode ? kernelFrameInstances_.GetOrAdd(frameIP, rvaFrame) : frameInstances_.GetOrAdd(frameIP, rvaFrame); StackFrames.Add(existingFrame); } private static ResolvedProfileStackFrameDetails CreateResolvedProfileStackFrameDetails( ResolvedProfileStackFrameKey frameDetails, IRTextFunction function) { return new ResolvedProfileStackFrameDetails(frameDetails.DebugInfo, function, frameDetails.Image, frameDetails.IsManagedCode); } } [StructLayout(LayoutKind.Sequential, Pack = 1)] public sealed class ResolvedProfileStackFrameDetails : IEquatable { public static readonly ResolvedProfileStackFrameDetails Unknown = new(); public ResolvedProfileStackFrameDetails(FunctionDebugInfo debugInfo, IRTextFunction function, ProfileImage image, bool isManagedCode) { DebugInfo = debugInfo; Function = function; Image = image; IsManagedCode = isManagedCode; } private ResolvedProfileStackFrameDetails() { } public FunctionDebugInfo DebugInfo { get; set; } public IRTextFunction Function { get; set; } public ProfileImage Image { get; set; } public bool IsKernelCode { get; set; } public bool IsManagedCode { get; set; } public bool IsUnknown => Image == null; public static bool operator ==(ResolvedProfileStackFrameDetails left, ResolvedProfileStackFrameDetails right) { return Equals(left, right); } public static bool operator !=(ResolvedProfileStackFrameDetails left, ResolvedProfileStackFrameDetails right) { return !Equals(left, right); } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is ResolvedProfileStackFrameDetails other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(DebugInfo, Image, IsKernelCode, IsManagedCode); } public bool Equals(ResolvedProfileStackFrameDetails other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Equals(DebugInfo, other.DebugInfo) && Equals(Image, other.Image) && IsKernelCode == other.IsKernelCode && IsManagedCode == other.IsManagedCode; } } // Stack-allocated version of ResolvedProfileStackFrameDetails, used only // when adding a new stack frame to reduce GC pressure if it already exists. [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct ResolvedProfileStackFrameKey : IEquatable { public static readonly ResolvedProfileStackFrameKey Unknown = new(); public ResolvedProfileStackFrameKey(FunctionDebugInfo debugInfo, ProfileImage image, bool isManagedCode) { DebugInfo = debugInfo; Image = image; IsManagedCode = isManagedCode; } public ResolvedProfileStackFrameKey() { } public FunctionDebugInfo DebugInfo; public ProfileImage Image; public bool IsManagedCode; public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is ResolvedProfileStackFrameKey other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(DebugInfo, Image); } public bool Equals(ResolvedProfileStackFrameKey other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Equals(DebugInfo, other.DebugInfo) && Equals(Image, other.Image); } } ================================================ FILE: src/ProfileExplorerCore/Profile/ETW/ETWEventProcessor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Threading; using Microsoft.Diagnostics.Tracing; using Microsoft.Diagnostics.Tracing.Parsers; using Microsoft.Diagnostics.Tracing.Parsers.Clr; using Microsoft.Diagnostics.Tracing.Parsers.Kernel; using Microsoft.Diagnostics.Tracing.Parsers.Symbol; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.ETW; public sealed partial class ETWEventProcessor : IDisposable { public const int KernelProcessId = 0; private const double SamplingErrorMargin = 1.1; // 10% deviation from sampling interval allowed. private const int SampleReportingInterval = 20000; private const int MaxCoreCount = 4096; private ETWTraceEventSource source_; private string tracePath_; private bool isRealTime_; private bool handleDotNetEvents_; private int acceptedProcessId_; private bool handleChildProcesses_; private ProfilerNamedPipeServer pipeServer_; private List childAcceptedProcessIds_; private ProfileDataProviderOptions providerOptions_; private bool samplingIntervalSet_; private int samplingInterval100NS_; private double samplingIntervalMS_; private double samplingIntervalLimitMS_; public ETWEventProcessor(ETWTraceEventSource source, ProfileDataProviderOptions providerOptions, bool isRealTime = true, int acceptedProcessId = 0, bool handleChildProcesses = false, bool handleDotNetEvents = false, ProfilerNamedPipeServer pipeServer = null) { Trace.WriteLine($"ETWEventProcessor: ProcId {acceptedProcessId}, handleDotNet: {handleDotNetEvents}"); source_ = source; providerOptions_ = providerOptions; isRealTime_ = isRealTime; acceptedProcessId_ = acceptedProcessId; handleDotNetEvents_ = handleDotNetEvents; handleChildProcesses_ = handleChildProcesses; pipeServer_ = pipeServer; childAcceptedProcessIds_ = new List(); } public ETWEventProcessor(string tracePath, ProfileDataProviderOptions providerOptions, int acceptedProcessId = 0) { Debug.Assert(File.Exists(tracePath)); childAcceptedProcessIds_ = new List(); source_ = new ETWTraceEventSource(tracePath); tracePath_ = tracePath; providerOptions_ = providerOptions; acceptedProcessId_ = acceptedProcessId; } public void Dispose() { source_?.Dispose(); source_ = null; } public static bool IsKernelAddress(ulong ip, int pointerSize) { if (pointerSize == 4) { return ip >= 0x80000000; } return ip >= 0xFFFF000000000000; } private unsafe static string ReadWideString(ReadOnlySpan data, int offset = 0) { fixed (byte* dataPtr = data) { var sb = new StringBuilder(); while (offset < data.Length - 1) { byte first = dataPtr[offset]; byte second = dataPtr[offset + 1]; if (first == 0 && second == 0) { break; // Found string null terminator. } sb.Append((char)(first | second << 8)); offset += 2; } return sb.ToString(); } } public List BuildProcessSummary(ProcessListProgressHandler progressCallback, CancelableTask cancelableTask) { // Default 1ms sampling interval. UpdateSamplingInterval(SampleReportingInterval); // Use a dummy process summary to collect all the process info. var profile = new RawProfileData(tracePath_); var summaryBuilder = new ProcessSummaryBuilder(profile); int lastReportedSample = 0; int lastProcessListSample = 0; int nextProcessListSample = SampleReportingInterval * 10; int sampleId = 0; var lastProcessListReport = DateTime.UtcNow; if (isRealTime_) { profile.TraceInfo.ProfileStartTime = DateTime.Now; } ThreadPool.QueueUserWorkItem(state => { progressCallback(new ProcessListProgress()); }); // Enable building of a thead ID -> process ID table // that is used for circular traces to get the event process ID // when it is not set in the trace (-1). var kernel = new KernelTraceEventParser(source_, KernelTraceEventParser.ParserTrackingOptions.ThreadToProcess); if (!isRealTime_) { kernel.EventTraceHeader += data => { // If the trace has a known file name it's unlikely // to be using a circular buffer which needs the thread -> process ID table, // stop reading the entire trace early. if (data.LogFileName != "[multiple files]") { kernel = ReopenTrace(); } }; source_.Process(); } ProfileProcess HandleProcessEvent(ProcessTraceData data) { var profileProcess = profile.GetOrCreateProcess(data.ProcessID); profileProcess.ProcessId = data.ProcessID; profileProcess.ParentId = data.ParentID; // Process name is empty, extract it from the image name. profileProcess.Name = Utilities.Utils.TryGetFileNameWithoutExtension(data.ImageFileName); profileProcess.ImageFileName = data.ImageFileName; profileProcess.CommandLine = data.CommandLine; // Capture WoW64 flag - indicates 32-bit process on 64-bit OS // ProcessFlags.Wow64 = 2 profileProcess.IsWow64 = (data.Flags & ProcessFlags.Wow64) != 0; return profileProcess; } kernel.ProcessStartGroup += data => { HandleProcessEvent(data); }; // Traces with circular buffers don't have ProcessStart events, // extract this info from the ProcessDCStop events instead. kernel.ProcessEndGroup += data => { HandleProcessEvent(data); }; kernel.PerfInfoSample += data => { if (cancelableTask.IsCanceled) { source_.StopProcessing(); } // The thread ID -> process ID mapping is used internally. if (data.ProcessID < 0) { return; } sampleId++; var sampleWeight = TimeSpan.FromMilliseconds(samplingIntervalMS_); var sampleTime = TimeSpan.FromMilliseconds(data.TimeStampRelativeMSec); summaryBuilder.AddSample(sampleWeight, sampleTime, data.ProcessID); // Rebuild process list and update UI from time to time. if (sampleId - lastReportedSample >= SampleReportingInterval) { List processList = null; var currentTime = DateTime.UtcNow; if (sampleId - lastProcessListSample >= nextProcessListSample && (currentTime - lastProcessListReport).TotalMilliseconds > 1000) { // Rebuild the process list every few seconds. processList = summaryBuilder.MakeSummaries(); lastProcessListSample = sampleId; lastProcessListReport = currentTime; } if (progressCallback != null) { int current = (int)data.TimeStampRelativeMSec; // Copy since data gets reused. int total = (int)source_.SessionDuration.TotalMilliseconds; progressCallback(new ProcessListProgress { Total = total, Current = current, Processes = processList }); } lastReportedSample = sampleId; } }; // Go again over events and accumulate samples to build the process summary. source_.Process(); profile.Dispose(); return summaryBuilder.MakeSummaries(); } public RawProfileData ProcessEvents(ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask, bool isCircularBufferTrace = false) { UpdateSamplingInterval(SampleReportingInterval); ImageIDTraceData lastImageIdData = null; ProfileImage lastProfileImage = null; long lastProfileImageTime = 0; int imageLoadEventCount = 0; int imageLoadWithTimestampCount = 0; int imageIdEventCount = 0; int imageIdDbgEventCount = 0; // Info used to associate a sample with the last call stack running on a thread. var perThreadLastTimeMap = new Dictionary(); var perThreadLastSampleMap = new Dictionary(); var perThreadLastKernelStackMap = new Dictionary(); var perContextLastSampleMap = new Dictionary(); int lastReportedSample = 0; // Info used to handle compressed stack event var kernelStackKeyToPendingSamples = new Dictionary>(); var userStackKeyToPendingSamples = new Dictionary>(); var profile = new RawProfileData(tracePath_, handleDotNetEvents_); // Enable building of a thead ID -> process ID table // that is used for circular traces to get the event process ID // when it is not set in the trace (-1). var kernel = new KernelTraceEventParser(source_, KernelTraceEventParser.ParserTrackingOptions.ThreadToProcess); UpdateProgress(progressCallback, ProfileLoadStage.TraceReading, 0, 0); kernel.EventTraceHeader += data => { profile.TraceInfo.CpuSpeed = data.CPUSpeed; profile.TraceInfo.ProfileStartTime = data.StartTime; profile.TraceInfo.ProfileEndTime = data.EndTime; // If the trace has a known file name it's unlikely // to be using a circular buffer which needs the thread -> process ID table, // stop reading the entire trace early. if (!isRealTime_ && data.LogFileName != "[multiple files]") { kernel = ReopenTrace(); } }; if (!isRealTime_) { // Process the trace in case it's using circular buffers // to build the thread -> process ID table. source_.Process(); } // For ETL file, the image timestamp (needed to find a binary on a symbol server) // can show up in the ImageID event instead the usual Kernel.ImageGroup. var symbolParser = new SymbolTraceEventParser(source_); symbolParser.ImageID += data => { // The image timestamp often is part of this event when reading an ETL file. // A correct timestamp is needed to locate and download the image. if (lastProfileImage != null && lastProfileImageTime == data.TimeStampQPC) { lastProfileImage.OriginalFileName = data.OriginalFileName; if (lastProfileImage.TimeStamp == 0) { lastProfileImage.TimeStamp = data.TimeDateStamp; } // Prefer ImageSize from ImageID (PE header value from merge) over the kernel // ImageGroup value (mapped view size which can have extra slack pages). if (data.ImageSize > 0) { lastProfileImage.Size = (int)data.ImageSize; } } else { // The ImageGroup event should show up later in the stream. lastImageIdData = (ImageIDTraceData)data.Clone(); imageIdEventCount++; } }; symbolParser.ImageIDDbgID_RSDS += data => { imageIdDbgEventCount++; if (IsAcceptedProcess(data.ProcessID)) { #if DEBUG Trace.WriteLine($"PDB signature: imageBase: {(long)data.ImageBase}, file: {data.PdbFileName}, age: {data.Age}, guid: {data.GuidSig}, timestamp: {data.TimeStamp}"); #endif var symbolFile = new SymbolFileDescriptor(data.PdbFileName, data.GuidSig, data.Age); profile.AddDebugFileForImage(symbolFile, (long)data.ImageBase, data.ProcessID); } }; // FileVersion events contain version resource info including CompanyName symbolParser.ImageIDFileVersion += data => { // Find the image by timestamp and update its version info var image = profile.FindImageByTimestamp(data.TimeDateStamp); if (image != null) { image.CompanyName = data.CompanyName; image.FileDescription = data.FileDescription; image.ProductName = data.ProductName; } }; // Start of main ETW event handlers. kernel.ProcessStartGroup += data => { var proc = new ProfileProcess(data.ProcessID, data.ParentID, data.ProcessName, data.ImageFileName, data.CommandLine); profile.AddProcess(proc); #if DEBUG Trace.WriteLine($"ProcessStartGroup: {proc}"); #endif // If parent is one of the accepted processes, accept the child too. if (handleChildProcesses_ && IsAcceptedProcess(data.ParentID)) { //Trace.WriteLine($"=> Accept child {data.ProcessID} of {data.ParentID}"); childAcceptedProcessIds_.Add(data.ProcessID); } }; // Traces with circular buffers don't have ProcessStart events, // extract this info from the ProcessDCStop events instead. kernel.ProcessGroup += data => { var proc = profile.GetOrCreateProcess(data.ProcessID); proc.ProcessId = data.ProcessID; proc.ParentId = data.ParentID; // Process name is empty, extract it from the image name. proc.Name = Utilities.Utils.TryGetFileNameWithoutExtension(data.ImageFileName); proc.ImageFileName = data.ImageFileName; proc.CommandLine = data.CommandLine; #if DEBUG Trace.WriteLine($"ProcessGroup {data.Opcode}: {proc}"); #endif // If parent is one of the accepted processes, accept the child too. if (handleChildProcesses_ && IsAcceptedProcess(data.ParentID)) { //Trace.WriteLine($"=> Accept child {data.ProcessID} of {data.ParentID}"); childAcceptedProcessIds_.Add(data.ProcessID); } }; kernel.ImageGroup += data => { imageLoadEventCount++; string originalName = null; int timeStamp = data.TimeDateStamp; int imageSize = data.ImageSize; bool sawImageId = false; if (lastImageIdData != null && lastImageIdData.TimeStampQPC == data.TimeStampQPC) { // The ImageID event showed up earlier in the stream. sawImageId = true; originalName = lastImageIdData.OriginalFileName; if (timeStamp == 0) { timeStamp = lastImageIdData.TimeDateStamp; } // Prefer the ImageSize from the ImageID event over the kernel ImageGroup event. // The kernel reports the mapped view size which can exceed the PE SizeOfImage // by a few slack pages. The ImageID event's ImageSize comes from reading the // actual PE file during trace merge, so it matches the PE header and is the // correct value for symbol server lookups (TimeDateStamp+SizeOfImage key). if (lastImageIdData.ImageSize > 0) { imageSize = (int)lastImageIdData.ImageSize; } } else if (isRealTime_) { // In a capture session, the image is on the local machine, // so just take the info out of the binary. var imageInfo = PEBinaryInfoProvider.GetBinaryFileInfo(data.FileName); if (imageInfo != null) { timeStamp = imageInfo.TimeStamp; } } #if DEBUG //Trace.WriteLine($"ImageGroup: imageBase: {(long)data.ImageBase}, file: {data.FileName}, timestamp: {timeStamp}, checksum: {data.ImageChecksum}"); #endif var image = new ProfileImage(data.FileName, originalName, (long)data.ImageBase, (long)data.DefaultBase, imageSize, timeStamp, data.ImageChecksum); if (timeStamp != 0) { imageLoadWithTimestampCount++; } int imageId = profile.AddImageToProcess(data.ProcessID, image); if (!sawImageId) { // The ImageID event may show up later in the stream. lastProfileImage = profile.FindImage(imageId); lastProfileImageTime = data.TimeStampQPC; } else { lastProfileImage = null; } }; kernel.ThreadStartGroup += data => { if (cancelableTask != null && cancelableTask.IsCanceled) { source_.StopProcessing(); } var thread = new ProfileThread(data.ThreadID, data.ProcessID, data.ThreadName); thread.Win32StartAddr = (long)data.Win32StartAddr; profile.AddThreadToProcess(data.ProcessID, thread); }; kernel.ThreadSetName += data => { if (IsAcceptedProcess(data.ProcessID)) { var proc = profile.GetOrCreateProcess(data.ProcessID); var thread = proc.FindThread(data.ThreadID, profile); if (thread != null) { thread.Name = data.ThreadName; } } }; kernel.SystemConfigCPU += data => { profile.TraceInfo.PointerSize = data.PointerSize; profile.TraceInfo.CpuCount = data.NumberOfProcessors; profile.TraceInfo.ComputerName = data.ComputerName; profile.TraceInfo.DomainName = data.DomainName; profile.TraceInfo.MemorySize = data.MemSize; }; kernel.StackWalkStack += data => { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } bool isKernelStack = data.FrameCount > 0 && IsKernelAddress(data.InstructionPointer(data.FrameCount - 1), data.PointerSize); bool isKernelStackStart = data.FrameCount > 0 && IsKernelAddress(data.InstructionPointer(0), data.PointerSize); #if DEBUG // if (data.FrameCount > 0) { // Trace.WriteLine("-----------------------------------"); // Trace.WriteLine($"Stack {data.InstructionPointer(0):X}, timestamp {data.EventTimeStampRelativeMSec}, TS {data.EventTimeStampQPC}, thread {data.ThreadID}"); // Trace.WriteLine($" kernel {isKernelStack}, kernelStart {isKernelStackStart}"); // } //Trace.WriteLine($"User stack {data.InstructionPointer(0):X}, proc {data.ProcessID}, name {data.ProcessName}, TS {data.EventTimeStampQPC}"); #endif var context = profile.RentTempContext(data.ProcessID, data.ThreadID, data.ProcessorNumber); int contextId = profile.AddContext(context); int frameCount = data.FrameCount; ProfileStack kstack = null; if (!isKernelStack && !isKernelStackStart) { // This is a user mode stack, check if before it an associated // kernel mode stack was recorded - if so, merge the two stacks. ref var lastKernelStack = ref CollectionsMarshal.GetValueRefOrAddDefault(perThreadLastKernelStackMap, data.ThreadID, out bool exists); if (exists && lastKernelStack.StackId != 0 && lastKernelStack.Timestamp == data.EventTimeStampQPC) { #if DEBUG //Trace.WriteLine($" Found matching KernelStack {lastKernelStack.StackId} at {lastKernelStack.Timestamp} on CPU {data.ProcessorNumber}"); #endif // Append at the end of the kernel stack, marking a user -> kernel mode transition. kstack = profile.FindStack(lastKernelStack.StackId); int kstackFrameCount = kstack.FrameCount; long[] frames = new long[kstack.FrameCount + data.FrameCount]; kstack.FramePointers.CopyTo(frames, 0); #if DEBUG //Trace.WriteLine($" kernel mode end IP: {frames[kstackFrameCount - 1]:X}"); //Trace.WriteLine($" user mode start IP: {data.InstructionPointer(0):X}"); #endif for (int i = 0; i < frameCount; i++) { frames[kstackFrameCount + i] = (long)data.InstructionPointer(i); } profile.ReplaceStackFramePointers(kstack, frames, context); kstack.UserModeTransitionIndex = kstackFrameCount; // Frames after index are user mode. lastKernelStack = (0, 0); // Clear the last kernel stack. } } if (kstack == null) { // This is either a kernel mode stack, or a user mode stack with no associated kernel mode stack. var stack = profile.RentTemporaryStack(frameCount, contextId); // Copy data from event to the temp. stack pointer array. // Slightly faster to copy the entire array as a whole. unsafe { var ptr = (void*)((IntPtr)(void*)data.DataStart + 16); int bytes = data.PointerSize * frameCount; var span = new Span(ptr, bytes); fixed (long* destPtr = stack.FramePointers) { var destSpan = new Span(destPtr, bytes); span.CopyTo(destSpan); } } int stackId = profile.AddStack(stack, context); // Try to associate with a previous sample from the same context. int sampleId = perThreadLastSampleMap.GetValueOrDefault(data.ThreadID); long frameIp = (long)data.InstructionPointer(0); //? TODO: Check more than the last sample? if (!profile.TrySetSampleStack(sampleId, stackId, frameIp, contextId)) { #if DEBUG //Trace.WriteLine($"Couldn't set stack {stackId} for sample {sampleId}"); #endif } if (isKernelStack) { #if DEBUG //Trace.WriteLine($" register KernelStack {stackId} on CPU {data.ProcessorNumber}"); #endif perThreadLastKernelStackMap[data.ThreadID] = (stackId, data.EventTimeStampQPC); } } profile.ReturnContext(contextId); }; kernel.StackWalkStackKeyKernel += data => { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } var context = profile.RentTempContext(data.ProcessID, data.ThreadID, data.ProcessorNumber); int contextId = profile.AddContext(context); int sampleId = perThreadLastSampleMap.GetValueOrDefault(data.ThreadID); var triggeringEventTimestamp = TimeSpan.FromMilliseconds(data.EventTimeStampRelativeMSec); // Check if the last sample on the core did not trigger this stack collection if (sampleId == 0 || profile.Samples[sampleId - 1].Time != triggeringEventTimestamp) { // Check if the last sample from the context did not trigger this stack collection if (!perContextLastSampleMap.TryGetValue(contextId, out sampleId) || profile.Samples[sampleId - 1].Time != triggeringEventTimestamp) { // We don't know what sample this stack belongs to so we won't collect it return; } } // Add the sample id to our list of pending samples for this stack key so when the definition comes along we can add the stack to our profile if (kernelStackKeyToPendingSamples.TryGetValue(data.StackKey, out var pendingSamples)) { pendingSamples.Add(sampleId); } else { kernelStackKeyToPendingSamples.Add(data.StackKey, new List {sampleId}); } profile.ReturnContext(contextId); }; kernel.StackWalkStackKeyUser += delegate(StackWalkRefTraceData data) { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } var context = profile.RentTempContext(data.ProcessID, data.ThreadID, data.ProcessorNumber); int contextId = profile.AddContext(context); int sampleId = perThreadLastSampleMap.GetValueOrDefault(data.ThreadID); var triggeringEventTimestamp = TimeSpan.FromMilliseconds(data.EventTimeStampRelativeMSec); // Check if the last sample on the core did not trigger this stack collection if (sampleId == 0 || profile.Samples[sampleId - 1].Time != triggeringEventTimestamp) { // Check if the last sample from the context did not trigger this stack collection if (!perContextLastSampleMap.TryGetValue(contextId, out sampleId) || profile.Samples[sampleId - 1].Time != triggeringEventTimestamp) { // We don't know what sample this stack belongs to so we won't collect it return; } } // Add the sample id to our list of pending samples for this stack key so when the definition comes along we can add the stack to our profile if (userStackKeyToPendingSamples.TryGetValue(data.StackKey, out var pendingSamples)) { pendingSamples.Add(sampleId); } else { userStackKeyToPendingSamples.Add(data.StackKey, new List {sampleId}); } profile.ReturnContext(contextId); }; kernel.AddCallbackForEvents(delegate(StackWalkDefTraceData data) { if (data.FrameCount == 0 || userStackKeyToPendingSamples.Count == 0 && kernelStackKeyToPendingSamples.Count == 0) { return; // Ignore data that won't fulfill any pending samples } bool isKernelAddress = IsKernelAddress(data.InstructionPointer(0), data.PointerSize); List pendingSamples; if (isKernelAddress && !kernelStackKeyToPendingSamples.TryGetValue(data.StackKey, out pendingSamples)) { return; } if (!userStackKeyToPendingSamples.TryGetValue(data.StackKey, out pendingSamples)) { return; } foreach (int sampleId in pendingSamples) { var sample = profile.Samples[sampleId - 1]; // Check if we already have part of the stack for this sample if (sample.StackId == 0) { var profileStack = profile.RentTemporaryStack(data.FrameCount, sample.ContextId); // Copy data from event to the temp. stack pointer array. // Slightly faster to copy the entire array as a whole. unsafe { var ptr = (void*)((IntPtr)(void*)data.DataStart + 8); int bytes = data.PointerSize * data.FrameCount; var span = new Span(ptr, bytes); fixed (long* destPtr = profileStack.FramePointers) { var destSpan = new Span(destPtr, bytes); span.CopyTo(destSpan); } } int stackId = profile.AddStack(profileStack, profile.FindContext(sample.ContextId)); profile.SetSampleStack(sampleId, stackId, sample.ContextId); } else if (isKernelAddress) { var profileStack = profile.FindStack(sample.StackId); int ustackFrameCount = profileStack.FrameCount; int kstackFrameCount = data.FrameCount; long[] frames = new long[kstackFrameCount + ustackFrameCount]; profileStack.FramePointers.CopyTo(frames, kstackFrameCount); for (int i = 0; i < kstackFrameCount; i++) { frames[i] = (long)data.InstructionPointer(i); } var context = profile.FindContext(sample.ContextId); profile.ReplaceStackFramePointers(profileStack, frames, context); profileStack.UserModeTransitionIndex = kstackFrameCount; // Frames after kernel stack are user mode. } else { var profileStack = profile.FindStack(sample.StackId); int ustackFrameCount = data.FrameCount; int kstackFrameCount = profileStack.FrameCount; long[] frames = new long[kstackFrameCount + ustackFrameCount]; profileStack.FramePointers.CopyTo(frames, 0); for (int i = 0; i < ustackFrameCount; i++) { frames[i + kstackFrameCount] = (long)data.InstructionPointer(i); } var context = profile.FindContext(sample.ContextId); profile.ReplaceStackFramePointers(profileStack, frames, context); profileStack.UserModeTransitionIndex = kstackFrameCount; // Frames after kernel stack are user mode. } } if (isKernelAddress) { kernelStackKeyToPendingSamples.Remove(data.StackKey); } else { userStackKeyToPendingSamples.Remove(data.StackKey); } }); void HandlePerfInfoCollection(SampledProfileIntervalTraceData data, RawProfileData profile) { if (data.SampleSource == 0) { UpdateSamplingInterval(data.NewInterval); profile.TraceInfo.SamplingInterval = TimeSpan.FromMilliseconds(samplingIntervalMS_); samplingIntervalSet_ = true; } else { // The description of a PMC event. var dataSpan = data.EventData().AsSpan(); string name = ReadWideString(dataSpan, 12); var counterInfo = new PerformanceCounter(data.SampleSource, name, data.NewInterval); profile.AddPerformanceCounter(counterInfo); } } kernel.PerfInfoCollectionStart += data => HandlePerfInfoCollection( data, profile); // I haven't really seen us recieve this event - was it just a mistake? kernel.PerfInfoCollectionEnd += data => HandlePerfInfoCollection(data, profile); kernel.PerfInfoSetInterval += data => { if (data.SampleSource == 0 && !samplingIntervalSet_) { UpdateSamplingInterval(data.OldInterval); profile.TraceInfo.SamplingInterval = TimeSpan.FromMilliseconds(samplingIntervalMS_); samplingIntervalSet_ = true; } }; kernel.PerfInfoSample += data => { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } // If the time since the last sample is greater than the sampling interval + some error margin, // it likely means that some samples were lost, use the sampling interval as the weight. int cpu = data.ProcessorNumber; double timestamp = data.TimeStampRelativeMSec; ref double perThreadLastTime = ref CollectionsMarshal.GetValueRefOrAddDefault(perThreadLastTimeMap, data.ThreadID, out bool exists); double weight = timestamp - perThreadLastTime; if (weight > samplingIntervalLimitMS_) { weight = samplingIntervalMS_; } perThreadLastTime = timestamp; // Skip unknown process. if (data.ProcessID < 0) { return; } // Skip idle thread on non-kernel code. bool isKernelCode = data.ExecutingDPC || data.ExecutingISR; if (data.ThreadID == 0 && !isKernelCode) { return; } // Save sample. var context = profile.RentTempContext(data.ProcessID, data.ThreadID, cpu); int contextId = profile.AddContext(context); var sample = new ProfileSample((long)data.InstructionPointer, TimeSpan.FromMilliseconds(timestamp), TimeSpan.FromMilliseconds(weight), isKernelCode, contextId); int sampleId = profile.AddSample(sample); profile.ReturnContext(contextId); // Trace.WriteLine($"Sample {sampleId}, timestamp {timestamp}, IP {data.InstructionPointer:X} kernel {isKernelCode}, CPU {cpu}, thread {data.ThreadID}"); // Remember the sample, to be matched later with a call stack. perThreadLastSampleMap[data.ThreadID] = sampleId; perContextLastSampleMap[contextId] = sampleId; // Report progress. if (progressCallback != null && sampleId - lastReportedSample >= SampleReportingInterval) { if (cancelableTask != null && cancelableTask.IsCanceled) { source_.StopProcessing(); } if (!isRealTime_) { int current = (int)data.TimeStampRelativeMSec; // Copy since data gets reused. int total = (int)source_.SessionDuration.TotalMilliseconds; UpdateProgress(progressCallback, ProfileLoadStage.TraceReading, total, current); } else { UpdateProgress(progressCallback, ProfileLoadStage.TraceReading, sampleId, sampleId); } lastReportedSample = sampleId; } }; if (providerOptions_.IncludePerformanceCounters) { Trace.WriteLine("Enable PMC event handling"); kernel.PerfInfoPMCSample += data => { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } var context = profile.RentTempContext(data.ProcessID, data.ThreadID, data.ProcessorNumber); int contextId = profile.AddContext(context); double timestamp = data.TimeStampRelativeMSec; var counterEvent = new PerformanceCounterEvent((long)data.InstructionPointer, TimeSpan.FromMilliseconds(timestamp), contextId, (short)data.ProfileSource); profile.AddPerformanceCounterEvent(counterEvent); profile.ReturnContext(contextId); }; } if (handleDotNetEvents_) { ProcessDotNetEvents(profile, cancelableTask); } // Go over all ETW events, which will call the registered handlers. try { Trace.WriteLine("Start processing ETW events"); var sw = Stopwatch.StartNew(); if (isRealTime_) { profile.TraceInfo.ProfileStartTime = DateTime.Now; } UpdateProgress(progressCallback, ProfileLoadStage.TraceReading, 0, 0); source_.Process(); if (isRealTime_) { profile.TraceInfo.ProfileEndTime = DateTime.Now; } sw.Stop(); Trace.WriteLine($"Done processing ETW events: {sw}, {sw.ElapsedMilliseconds} ms"); } catch (Exception ex) { Trace.TraceError($"Failed to process ETW events: {ex.Message}"); } Trace.WriteLine("ETW events summary"); Trace.WriteLine($" - samples: {profile.Samples.Count}"); Trace.WriteLine($" - pmc events: {profile.PerformanceCountersEvents?.Count}"); Trace.WriteLine($" - ImageLoad events: {imageLoadEventCount} ({imageLoadWithTimestampCount} with valid timestamp)"); Trace.WriteLine($" - ImageID events: {imageIdEventCount}"); Trace.WriteLine($" - ImageID DbgID (RSDS) events: {imageIdDbgEventCount}"); // Store event counts for later use (symbol loading warnings) profile.TraceInfo.ImageLoadEventCount = imageLoadEventCount; profile.TraceInfo.ImageLoadWithTimestampCount = imageLoadWithTimestampCount; profile.TraceInfo.ImageIdEventCount = imageIdEventCount; profile.TraceInfo.ImageIdDbgEventCount = imageIdDbgEventCount; // Log summary to diagnostic log DiagnosticLogger.LogInfo($"[TraceLoad] Event counts: ImageLoad={imageLoadEventCount} ({imageLoadWithTimestampCount} with timestamp), " + $"ImageID={imageIdEventCount}, ImageID_DbgID={imageIdDbgEventCount}"); // Warn if trace lacks ImageID events - symbol resolution will likely fail if (imageIdDbgEventCount == 0) { DiagnosticLogger.LogWarning("[TraceLoad] Trace has no ImageID DbgID (RSDS) events - PDB GUID/Age info is missing. " + "Symbol resolution will likely fail. Consider re-capturing with ImageID events enabled."); } else if (imageIdDbgEventCount < profile.Images.Count / 2) { DiagnosticLogger.LogWarning($"[TraceLoad] Trace has only {imageIdDbgEventCount} ImageID DbgID events for {profile.Images.Count} images. " + "Some symbols may not resolve correctly."); } // Free temporary data structures. profile.LoadingCompleted(); if (handleDotNetEvents_) { profile.ManagedLoadingCompleted(); } #if DEBUG profile.PrintAllProcesses(); #endif #if false GC.Collect(); GC.WaitForPendingFinalizers(); long memory2 = GC.GetTotalMemory(true); Trace.WriteLine($"Memory diff: {(memory2 - memory) / (1024 * 1024):F2}, MB"); Trace.Flush(); #endif return profile; } private KernelTraceEventParser ReopenTrace() { // Stop processing the current trace, close it // and create a new one with kernel event provider. source_.StopProcessing(); source_.Dispose(); source_ = new ETWTraceEventSource(tracePath_); return new KernelTraceEventParser(source_, KernelTraceEventParser.ParserTrackingOptions.ThreadToProcess); } private void UpdateSamplingInterval(int value) { samplingInterval100NS_ = value; samplingIntervalMS_ = (double)samplingInterval100NS_ / 10000; samplingIntervalLimitMS_ = samplingIntervalMS_ * SamplingErrorMargin; } private void UpdateProgress(ProfileLoadProgressHandler callback, ProfileLoadStage stage, int total, int current, string optional = null) { if (callback != null) { callback(new ProfileLoadProgress(stage) { Total = total, Current = current, Optional = optional }); } } private string ToOptimizationLevel(OptimizationTier tier) { return tier switch { OptimizationTier.MinOptJitted => "MinOptJitted", OptimizationTier.Optimized => "Optimized", OptimizationTier.OptimizedTier1 => "OptimizedTier1", OptimizationTier.PreJIT => "PreJIT", OptimizationTier.QuickJitted => "QuickJitted", OptimizationTier.ReadyToRun => "ReadyToRun", _ => null }; } private bool IsAcceptedProcess(int processID) { if (acceptedProcessId_ == 0) { return true; // No filtering. } if (processID == acceptedProcessId_ || processID == 0) { // Always accept the System process. return true; } return childAcceptedProcessIds_.Contains(processID); } } ================================================ FILE: src/ProfileExplorerCore/Profile/ETW/ETWEventProcessorManaged.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Diagnostics; using System.Reflection.PortableExecutable; using System.Threading.Tasks; using Microsoft.Diagnostics.Tracing.Parsers.Clr; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.ETW; public sealed partial class ETWEventProcessor { private void ProcessDotNetEvents(RawProfileData profile, CancelableTask cancelableTask) { if (pipeServer_ != null) { pipeServer_.FunctionCodeReceived += (functionId, rejitId, processId, address, codeSize, codeBytes) => { #if DEBUG Trace.WriteLine($"PipeServer_OnFunctionCodeReceived: {functionId}, {rejitId}, {address}, {codeSize}"); #endif profile.AddManagedMethodCode(functionId, rejitId, processId, address, codeSize, codeBytes); }; pipeServer_.FunctionCallTargetsReceived += (functionId, rejitId, processId, address, name) => { #if DEBUG Trace.WriteLine($"PipeServer_OnFunctionCallTargetsReceived: {functionId}, {rejitId}, {address}, {name}"); #endif profile.AddManagedMethodCallTarget(functionId, rejitId, processId, address, name); }; Task.Run(() => { // Receive messages from the pipe client with the managed method code. Trace.WriteLine("Start .NET pipe server communication"); pipeServer_.StartReceiving(cancelableTask.Token); }); } //source_.Clr.GCStart += data => { // Trace.WriteLine($"GCStart: {data}"); // double timestamp = data.TimeStampRelativeMSec; // var counterEvent = new PerformanceCounterEvent(0, // TimeSpan.FromMilliseconds(timestamp), // 1, (short)(1)); // profile.AddPerformanceCounterEvent(counterEvent); //}; //source_.Clr.GCStop += data => { // Trace.WriteLine($"GCStop: {data}"); // double timestamp = data.TimeStampRelativeMSec; // var counterEvent = new PerformanceCounterEvent(0, // TimeSpan.FromMilliseconds(timestamp), // 1, (short)(0)); // profile.AddPerformanceCounterEvent(counterEvent); //}; source_.Clr.LoaderModuleLoad += data => { ProcessLoaderModuleLoad(data, profile); }; source_.Clr.MethodLoadVerbose += data => { ProcessDotNetMethodLoad(data, profile, cancelableTask); }; source_.Clr.MethodILToNativeMap += data => { ProcessDotNetILToNativeMap(data, profile); }; // Needed when attaching to a running process to get info // about modules/methods loaded before the ETW session started. var rundownParser = new ClrRundownTraceEventParser(source_); rundownParser.LoaderModuleDCStart += data => { ProcessLoaderModuleLoad(data, profile, true); }; //rundownParser.LoaderModuleDCStop += data => { // ProcessLoaderModuleLoad(data, profile, true); //}; rundownParser.MethodDCStartVerbose += data => { ProcessDotNetMethodLoad(data, profile, cancelableTask, true); }; //rundownParser.MethodDCStopVerbose += data => { // ProcessDotNetMethodLoad(data, profile, true); //}; rundownParser.MethodILToNativeMapDCStart += data => { ProcessDotNetILToNativeMap(data, profile, true); }; //rundownParser.MethodILToNativeMapDCStop += data => { // ProcessDotNetILToNativeMap(data, profile, true); //}; } private void ProcessLoaderModuleLoad(ModuleLoadUnloadTraceData data, RawProfileData profile, bool rundown = false) { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } #if DEBUG Trace.WriteLine($"=> R-{rundown} Managed module {data.ModuleID}, {data.ModuleILFileName} in proc {data.ProcessID}"); #endif var runtimeArch = Machine.Amd64; string moduleName = data.ModuleILFileName; var moduleDebugInfo = profile.GetOrAddManagedModuleDebugInfo(data.ProcessID, moduleName, data.ModuleID, runtimeArch); if (moduleDebugInfo != null) { moduleDebugInfo.ManagedSymbolFile = FromModuleLoad(data); #if DEBUG Trace.WriteLine($"Set managed symbol {moduleDebugInfo.ManagedSymbolFile}"); #endif } } private void ProcessDotNetILToNativeMap(MethodILToNativeMapTraceData data, RawProfileData profile, bool rundown = false) { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } #if DEBUG Trace.WriteLine( $"=> R-{rundown} ILMap token: {data.MethodID}, entries: {data.CountOfMapEntries}, ProcessID: {data.ProcessID}, name: {data.ProcessName}"); #endif var methodMapping = profile.FindManagedMethod(data.MethodID, data.ReJITID, data.ProcessID); if (methodMapping == null) { return; } var ilOffsets = new List<(int ILOffset, int NativeOffset)>(data.CountOfMapEntries); for (int i = 0; i < data.CountOfMapEntries; i++) { ilOffsets.Add((data.ILOffset(i), data.NativeOffset(i))); } var (debugInfo, _) = profile.GetModuleDebugInfo(data.ProcessID, methodMapping.ModuleId); if (debugInfo != null) { debugInfo.AddMethodILToNativeMap(methodMapping.FunctionDebugInfo, ilOffsets); } } private void ProcessDotNetMethodLoad(MethodLoadUnloadVerboseTraceData data, RawProfileData profile, CancelableTask cancelableTask, bool rundown = false) { if (!IsAcceptedProcess(data.ProcessID)) { return; // Ignore events from other processes. } if (rundown) { if (pipeServer_ != null && !cancelableTask.IsCanceled) { #if DEBUG Trace.WriteLine($"Request {data.MethodStartAddress:x}: {data.MethodSignature}"); #endif if (!pipeServer_.RequestFunctionCode((long)data.MethodStartAddress, data.MethodID, (int)data.ReJITID, data.ProcessID)) { Trace.WriteLine($"Failed to request rundown method {data.MethodStartAddress:x}"); } } } #if DEBUG Trace.WriteLine( $"=> R-{rundown} Load at {data.MethodStartAddress}: {data.MethodNamespace}.{data.MethodName}, {data.MethodSignature},ProcessID: {data.ProcessID}, name: {data.ProcessName}"); Trace.WriteLine( $" id/token: {data.MethodID}/{data.MethodToken}, opts: {data.OptimizationTier}, size: {data.MethodSize}"); #endif string funcName = $"{data.MethodNamespace}.{data.MethodName}"; var funcInfo = new FunctionDebugInfo(funcName, (long)data.MethodStartAddress, (uint)data.MethodSize, (short)data.OptimizationTier, data.MethodToken, (short)data.ReJITID); profile.AddManagedMethodMapping(data.ModuleID, data.MethodID, data.ReJITID, funcInfo, (long)data.MethodStartAddress, data.MethodSize, data.ProcessID); } private SymbolFileDescriptor FromModuleLoad(ModuleLoadUnloadTraceData data) { return new SymbolFileDescriptor(data.ManagedPdbBuildPath, data.ManagedPdbSignature, data.ManagedPdbAge); } } ================================================ FILE: src/ProfileExplorerCore/Profile/ETW/ETWProfileDataProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.ETW; // Event delegates for session callbacks public delegate Task SetupNewSessionHandler(ILoadedDocument mainDocument, List otherDocuments, ProfileData profileData); public delegate Task StartNewSessionHandler(string sessionName, SessionKind sessionKind, ICompilerInfoProvider compilerInfo); public sealed class ETWProfileDataProvider : IProfileDataProvider, IDisposable { private const int IMAGE_LOCK_COUNT = 64; private const int PROGRESS_UPDATE_INTERVAL = 2048; // Progress UI update after pow2 N samples. #if DEBUG // For collecting statistics on stack frame resolution. private volatile static int UnresolvedStackCount; private volatile static int ResolvedStackCount; private Dictionary> perModuleSampleStatsMap_; #endif // Per-thread caching of the previously handled image // and module builder, with hotspots many samples have the same. [ThreadStatic] private static ProfileImage prevImage_; [ThreadStatic] private static ProfileModuleBuilder prevProfileModuleBuilder_; private ProfileDataProviderOptions options_; private ProfileDataReport report_; private ICompilerInfoProvider compilerInfoProvider_; private ProfileData profileData_; private Machine defaultArchitecture_ = Machine.Amd64; // Default to x64, updated from trace PointerSize private object lockObject_; private object[] imageLocks_; private ConcurrentDictionary imageModuleMap_; private HashSet rejectedDebugModules_; private int currentSampleIndex_; // Synthetic module for samples whose instruction pointers don't map to any // known module loaded in the process. This can be dynamically generated code // (e.g., LUA JIT, Java JIT), code from unloaded modules, or other unmapped regions. private const string UnknownModuleName = "[Unknown Module]"; // Synthetic IP layout: [base bit48] [PID 16-bit] [TID 32-bit]. // Chosen arbitrarily, just with constraint of being between // max user VA and IsKernelAddress threshold. See `IsKernelAddress` // in ETWEventProcessor.cs and https://learn.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/virtual-address-spaces private const ulong SyntheticIpBase = 0x0001_0000_0000_0000UL; // ProcessId (and ThreadId) is a DWORD (32-bit unsigned) // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocessid // though with only 16 bits here, as a full 32-bit PID << 32 (in `MakeSyntheticIp`) // can flow into kernel addr range. private const ulong ProcessIdMask = 0xFFFFUL; private sealed class UnknownModuleState(ProfileImage image, ProfileData profileData, int processId) { private readonly object lock_ = new(); private readonly ConcurrentDictionary threadFunctions_ = new(); private readonly ProfileData profileData_ = profileData; private readonly int processId_ = processId; private readonly ILoadedDocument document_ = LoadedDocument.CreateDummyDocument(UnknownModuleName); public ProfileImage Image { get; } = image; public ILoadedDocument Document => document_; /// /// Gets or creates a synthetic function for samples with unmapped IPs /// on a specific thread. /// public (IRTextFunction Function, FunctionDebugInfo DebugInfo) GetOrCreateThreadFunction(int threadId) { // Lock-free fast path for threads we've already seen (IRTextFunction Function, FunctionDebugInfo DebugInfo) existing; if (threadFunctions_.TryGetValue(threadId, out existing)) { return existing; } // Serialize creation to ensure AddDummyFunction is called exactly once per threadId lock (lock_) { // Check again, in case another thread *just* created the entry since we checked previously if (threadFunctions_.TryGetValue(threadId, out existing)) { return existing; } ProfileThread thread = profileData_.FindThread(threadId); string startModule = ResolveStartModule(thread); string funcName = FormatFuncName(threadId, thread?.Name, startModule); // RVA = threadId so FunctionDebugInfo.IsUnknown (RVA==0 && Size==0) is false. // Id = processId_ so FunctionDebugInfo.Equals differentiates across processes // (Id is normally MethodToken for managed code, repurposed here for dedup keying). FunctionDebugInfo debugInfo = new FunctionDebugInfo(funcName, threadId, 1, id: processId_); IRTextFunction func = document_.AddDummyFunction(funcName); (IRTextFunction func, FunctionDebugInfo debugInfo) result = (func, debugInfo); threadFunctions_[threadId] = result; return result; } } /// /// Resolves the module containing the thread's Win32 start address. /// private string ResolveStartModule(ProfileThread thread) { if (thread == null || thread.Win32StartAddr == 0) { return null; } foreach (var module in profileData_.Modules.Values) { if (module.HasAddress(thread.Win32StartAddr)) { return module.ModuleName; } } return null; } /// /// Formats function as [JIT ThreadName (ThreadId) StartModule]. /// private static string FormatFuncName(int threadId, string threadName, string startModule) { // Examples: [JIT WorkerThread (1234) lua51.dll], [JIT Thread 1234] if (!string.IsNullOrEmpty(threadName)) { return string.IsNullOrEmpty(startModule) ? $"[JIT {threadName} ({threadId})]" : $"[JIT {threadName} ({threadId}) {startModule}]"; } return string.IsNullOrEmpty(startModule) ? $"[JIT Thread {threadId}]" : $"[JIT Thread {threadId} {startModule}]"; } } private readonly ConcurrentDictionary unknownModules_ = new(); // Events for session lifecycle callbacks public event SetupNewSessionHandler SetupNewSessionRequested; public event StartNewSessionHandler StartNewSessionRequested; public ETWProfileDataProvider() { profileData_ = new ProfileData(); // Data structs used for module loading. lockObject_ = new object(); imageModuleMap_ = new ConcurrentDictionary(); rejectedDebugModules_ = new HashSet(); imageLocks_ = new object[IMAGE_LOCK_COUNT]; for (int i = 0; i < imageLocks_.Length; i++) { imageLocks_[i] = new object(); } // Clear static caches from any previous trace load to prevent // stale frame/function references leaking across sessions. ResolvedProfileStack.ResetCaches(); } public static async Task> FindTraceProcesses(string tracePath, ProfileDataProviderOptions options, ProcessListProgressHandler progressCallback, CancelableTask cancelableTask) { try { using var eventProcessor = new ETWEventProcessor(tracePath, options); return await Task.Run(() => eventProcessor.BuildProcessSummary(progressCallback, cancelableTask)); } catch (Exception ex) { Trace.WriteLine($"Failed to open ETL file {tracePath}: {ex.Message}"); return null; } } public void Dispose() { // NOTE: Do NOT dispose ProfileModuleBuilder instances here! // They need to remain alive for dynamic on-demand binary loading // (e.g., when user views assembly after trace is loaded). // ProfileModuleBuilder instances should live as long as the profile data is being used. } public async Task LoadTraceAsync(string tracePath, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { Trace.WriteLine($"LoadTraceAsync(file): Starting trace loading from file: {tracePath}"); Trace.WriteLine($"LoadTraceAsync(file): Process IDs: [{string.Join(", ", processIds)}]"); try { UpdateProgress(progressCallback, ProfileLoadStage.TraceReading, 0, 0); Trace.WriteLine($"LoadTraceAsync(file): Creating ETW event processor"); var rawProfile = await Task.Run(() => { int acceptedProcessId = processIds.Count == 1 ? processIds[0] : 0; symbolSettings.InsertSymbolPath(tracePath); // Include the trace path in the symbol search path. if (symbolSettings.IncludeSymbolSubdirectories) { symbolSettings.ExpandSymbolPathsSubdirectories([".pdb"]); } Trace.WriteLine($"LoadTraceAsync(file): Starting ETW event processing for process {acceptedProcessId}"); using var eventProcessor = new ETWEventProcessor(tracePath, options, acceptedProcessId); var result = eventProcessor.ProcessEvents(progressCallback, cancelableTask); Trace.WriteLine($"LoadTraceAsync(file): ETW event processing completed, found {result?.Samples?.Count ?? 0} samples"); return result; }); if (rawProfile == null) { Trace.WriteLine($"LoadTraceAsync(file): ERROR - ETW event processing returned null"); return null; } var mainProcess = rawProfile.FindProcess(processIds[0]); if (mainProcess == null) { Trace.WriteLine($"LoadTraceAsync(file): ERROR - Failed to find main process id {processIds[0]} in trace"); Trace.WriteLine($"LoadTraceAsync(file): Available processes: [{string.Join(", ", rawProfile.Processes.Select(p => p.ProcessId))}]"); return null; } Trace.WriteLine($"LoadTraceAsync(file): Found main process {processIds[0]}: {mainProcess.ImageFileName}"); Trace.WriteLine($"LoadTraceAsync(file): Calling LoadTraceAsync with raw profile"); var result = await LoadTraceAsync(rawProfile, processIds, options, symbolSettings, report, progressCallback, cancelableTask); Trace.WriteLine($"LoadTraceAsync(file): LoadTraceAsync completed, disposing raw profile"); rawProfile.Dispose(); Trace.WriteLine($"LoadTraceAsync(file): Returning {(result != null ? "success" : "failure")}"); return result; } catch (Exception ex) { Trace.WriteLine($"LoadTraceAsync(file): EXCEPTION: {ex.GetType().Name}: {ex.Message}"); Trace.WriteLine($"LoadTraceAsync(file): Stack trace: {ex.StackTrace}"); if (ex.InnerException != null) { Trace.WriteLine($"LoadTraceAsync(file): Inner exception: {ex.InnerException.GetType().Name}: {ex.InnerException.Message}"); } return null; } } public async Task LoadTraceAsync(RawProfileData rawProfile, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { Trace.WriteLine($"LoadTraceAsync: Starting profile loading for {processIds.Count} processes"); try { // Fill in report details. var mainProcess = rawProfile.FindProcess(processIds[0]); if (mainProcess == null) { Trace.WriteLine($"LoadTraceAsync: ERROR - Main process {processIds[0]} not found in raw profile"); return null; } Trace.WriteLine($"LoadTraceAsync: Found main process {processIds[0]}: {mainProcess.ImageFileName}"); report_ = report; report_.Process = mainProcess; report.TraceInfo = rawProfile.TraceInfo; int mainProcessId = mainProcess.ProcessId; // Save process and thread info. profileData_.Process = mainProcess; options_ = options; foreach (int procId in processIds) { var proc = rawProfile.FindProcess(procId); if (proc != null) { Trace.WriteLine($"LoadTraceAsync: Adding threads for process {procId}: {proc.Threads(rawProfile).Count()} threads"); profileData_.AddThreads(proc.Threads(rawProfile)); } else { Trace.WriteLine($"LoadTraceAsync: WARNING - Process {procId} not found in raw profile"); } } // Save all modules to include the ones loaded in the kernel only, // which would show up in stack traces if kernel samples are enabled. int moduleCount = rawProfile.Images.Count(); Trace.WriteLine($"LoadTraceAsync: Adding {moduleCount} modules from raw profile"); profileData_.AddModules(rawProfile.Images); // Pre-create synthetic [Unknown Module] state for each profiled process. // This must happen before parallel sample processing begins, since // RawProfileData.AddImageDirect is not thread-safe. foreach (int procId in processIds) { PreCreateUnknownModule(rawProfile, procId); } string imageName = Utilities.Utils.TryGetFileNameWithoutExtension(mainProcess.ImageFileName); Trace.WriteLine($"LoadTraceAsync: Main image name: {imageName}"); if (options.HasBinarySearchPaths) { Trace.WriteLine($"LoadTraceAsync: Adding {options.BinarySearchPaths.Count} binary search paths"); symbolSettings.InsertSymbolPaths(options.BinarySearchPaths); } // The entire ETW processing must be done on the same thread. Trace.WriteLine($"LoadTraceAsync: Starting main processing task"); bool result = await Task.Run(async () => { try { // Start getting the function address data while the trace is loading. var totalSw = Stopwatch.StartNew(); UpdateProgress(progressCallback, ProfileLoadStage.TraceReading, 0, 0); Trace.WriteLine($"LoadTraceAsync: Task.Run started, beginning binary/debug file loading"); // Start getting the function address data while the trace is loading. if (cancelableTask is {IsCanceled: true}) { Trace.WriteLine($"LoadTraceAsync: Cancellation requested before binary loading"); return false; } #if DEBUG rawProfile.PrintProcess(mainProcessId); //profile.PrintSamples(mainProcessId); #endif // Preload binaries and debug files, downloading them concurrently if needed. Trace.WriteLine($"LoadTraceAsync: Starting LoadBinaryAndDebugFiles"); await LoadBinaryAndDebugFiles(rawProfile, mainProcess, imageName, symbolSettings, progressCallback, cancelableTask); Trace.WriteLine($"LoadTraceAsync: Completed LoadBinaryAndDebugFiles"); if (cancelableTask is {IsCanceled: true}) { Trace.WriteLine($"LoadTraceAsync: Cancellation requested after binary loading"); return false; } // Start main processing part, resolving stack frames, // mapping IPs/RVAs to functions using the debug info. UpdateProgress(progressCallback, ProfileLoadStage.TraceProcessing, rawProfile.Samples.Count, 0); var processingSw = Stopwatch.StartNew(); Trace.WriteLine($"LoadTraceAsync: Starting sample processing for {rawProfile.Samples.Count} samples"); // Split sample processing in multiple chunks, each done by another thread. int chunks = CoreSettingsProvider.GeneralSettings.CurrentCpuCoreLimit; #if DEBUG chunks = 1; #endif int chunkSize = rawProfile.ComputeSampleChunkLength(chunks); int sampleCount = rawProfile.Samples.Count; Trace.WriteLine($"LoadTraceAsync: Using {chunks} threads, chunk size: {chunkSize}"); var tasks = new List>>(); var taskScheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, chunks); var taskFactory = new TaskFactory(taskScheduler.ConcurrentScheduler); // Process the raw samples and stacks by resolving stack frame symbols // and creating the function profiles. for (int k = 0; k < chunks; k++) { int start = Math.Min(k * chunkSize, sampleCount); int end = k == chunks - 1 ? sampleCount : Math.Min((k + 1) * chunkSize, sampleCount); Trace.WriteLine($"LoadTraceAsync: Creating task {k} for samples {start}-{end}"); tasks.Add(taskFactory.StartNew(async () => { var chunkSamples = await ProcessSamplesChunk(rawProfile, start, end, processIds, options.IncludeKernelEvents, symbolSettings, progressCallback, cancelableTask, chunks).ConfigureAwait(false); return chunkSamples; }).Unwrap()); } Trace.WriteLine($"LoadTraceAsync: Waiting for {tasks.Count} sample processing tasks"); await Task.WhenAll(tasks.ToArray()); Trace.WriteLine($"LoadTraceAsync: Done processing samples in {processingSw.Elapsed}"); if (cancelableTask is {IsCanceled: true}) { Trace.WriteLine($"LoadTraceAsync: Cancellation requested after sample processing"); return false; } // Collect samples from tasks. Trace.WriteLine($"LoadTraceAsync: Collecting chunk samples"); CollectChunkSamples(tasks); // Create the per-function profile and call tree. UpdateProgress(progressCallback, ProfileLoadStage.ComputeCallTree, 0, rawProfile.Samples.Count); var callTreeSw = Stopwatch.StartNew(); Trace.WriteLine($"LoadTraceAsync: Computing thread sample ranges and function profile"); profileData_.ComputeThreadSampleRanges(); profileData_.FilterFunctionProfile(new ProfileSampleFilter()); Trace.WriteLine( $"LoadTraceAsync: Done compute func profile/call tree in {callTreeSw.Elapsed}, {callTreeSw.ElapsedMilliseconds} ms"); Trace.WriteLine( $"LoadTraceAsync: Done processing trace in {processingSw.Elapsed}, {processingSw.ElapsedMilliseconds} ms"); // If the trace has registered PMU counters (from PerfInfoCollectionEnd events) // but no PerfInfoPMCSample events, the PMU counters were used as sampling sources // rather than as separate counting events. Create synthetic counter events from // the regular samples, similar to how samples without stacks get a synthetic // single-frame stack (see ProcessSamplesChunk). if (!rawProfile.HasPerformanceCountersEvents && rawProfile.PerformanceCounters.Count > 0) { Trace.WriteLine($"LoadTraceAsync: Generating synthetic PMC events from {rawProfile.Samples.Count} samples " + $"for {rawProfile.PerformanceCounters.Count} PMU sampling source counter(s)"); foreach (var sample in rawProfile.Samples) { foreach (var counter in rawProfile.PerformanceCounters) { var counterEvent = new PerformanceCounterEvent( sample.IP, sample.Time, sample.ContextId, (short)counter.Id); rawProfile.AddPerformanceCounterEvent(counterEvent); } } } // Process performance counters. if (rawProfile.HasPerformanceCountersEvents) { Trace.WriteLine($"LoadTraceAsync: Processing {rawProfile.PerformanceCountersEvents.Count} performance counter events"); ProcessPerformanceCounters(rawProfile, processIds, symbolSettings, progressCallback, cancelableTask); } else { Trace.WriteLine($"LoadTraceAsync: No performance counter events to process"); } #if DEBUG // PrintSampleStatistics(); #endif Trace.WriteLine($"LoadTraceAsync: Done loading profile in {totalSw.Elapsed}"); return true; } catch (Exception ex) { Trace.WriteLine($"LoadTraceAsync: EXCEPTION in Task.Run: {ex.GetType().Name}: {ex.Message}"); Trace.WriteLine($"LoadTraceAsync: Stack trace: {ex.StackTrace}"); throw; // Re-throw to be caught by outer try-catch } }); if (cancelableTask is {IsCanceled: true}) { Trace.WriteLine($"LoadTraceAsync: Cancellation requested after main processing task"); return null; } // Setup session documents. if (result) { Trace.WriteLine($"LoadTraceAsync: Main processing succeeded, setting up session documents"); var exeDocument = FindSessionDocuments(imageName, out var otherDocuments); if (exeDocument == null) { Trace.WriteLine($"LoadTraceAsync: WARNING - Failed to find main EXE document for {imageName}"); exeDocument = new LoadedDocument(string.Empty, string.Empty, Guid.Empty); exeDocument.Summary = new IRTextSummary(string.Empty); } else { Trace.WriteLine($"LoadTraceAsync: Using exe document {exeDocument.ModuleName} with {otherDocuments.Count} other documents"); } Trace.WriteLine($"LoadTraceAsync: Calling SetupNewSessionRequested event"); await (SetupNewSessionRequested?.Invoke(exeDocument, otherDocuments, profileData_) ?? Task.CompletedTask); Trace.WriteLine($"LoadTraceAsync: Completed SetupNewSessionRequested event"); } else { Trace.WriteLine($"LoadTraceAsync: ERROR - Main processing task returned false (failed)"); } if (cancelableTask is {IsCanceled: true}) { Trace.WriteLine($"LoadTraceAsync: Cancellation requested after session setup"); return null; } Trace.WriteLine($"LoadTraceAsync: Returning {(result ? "success" : "failure")}"); return result ? profileData_ : null; } catch (Exception ex) { Trace.TraceError($"LoadTraceAsync: TOP-LEVEL EXCEPTION: {ex.GetType().Name}: {ex.Message}"); Trace.WriteLine($"LoadTraceAsync: Exception details - Type: {ex.GetType().FullName}"); Trace.WriteLine($"LoadTraceAsync: Exception source: {ex.Source}"); Trace.WriteLine($"LoadTraceAsync: Stack trace: {ex.StackTrace}"); if (ex.InnerException != null) { Trace.WriteLine($"LoadTraceAsync: Inner exception: {ex.InnerException.GetType().Name}: {ex.InnerException.Message}"); Trace.WriteLine($"LoadTraceAsync: Inner exception stack: {ex.InnerException.StackTrace}"); } Trace.Flush(); return null; } } private void CollectChunkSamples(List>> tasks) { var samples = new List<(ProfileSample, ResolvedProfileStack)>[tasks.Count]; for (int k = 0; k < tasks.Count; k++) { samples[k] = tasks[k].Result; } // Preallocate merged samples list. int totalSamples = 0; foreach (var chunkSamples in samples) { totalSamples += chunkSamples.Count; } profileData_.Samples.EnsureCapacity(totalSamples); // Merge the samples from all chunks and sort them by time. foreach (var chunkSamples in samples) { profileData_.Samples.AddRange(chunkSamples); } if (profileData_.Samples != null) { profileData_.Samples.Sort((a, b) => a.Sample.Time.CompareTo(b.Sample.Time)); } else { // Make an empty list to keep other parts happy. profileData_.Samples = []; } } private async Task> ProcessSamplesChunk(RawProfileData rawProfile, int start, int end, List processIds, bool includeKernelEvents, SymbolFileSourceSettings symbolSettings, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask, int chunks) { // Clear thread-local caches to prevent stale data from previous trace loads prevImage_ = null; prevProfileModuleBuilder_ = null; RawProfileData.ClearThreadLocalCaches(); var totalWeight = TimeSpan.Zero; var profileWeight = TimeSpan.Zero; var samples = new List<(ProfileSample Sample, ResolvedProfileStack Stack)>(end - start + 1); int sampleIndex = 0; var chunkSw = Stopwatch.StartNew(); int stackResolutionCount = 0; int kernelSamplesSkipped = 0; int otherProcessSamplesSkipped = 0; Trace.WriteLine($"ProcessSamplesChunk: Processing chunk {start}-{end} ({end - start} samples) on thread {Thread.CurrentThread.ManagedThreadId}"); for (int i = start; i < end; i++) { var sample = rawProfile.Samples[i]; // Update progress every pow2 N samples. if ((++sampleIndex & PROGRESS_UPDATE_INTERVAL - 1) == 0) { if (cancelableTask is {IsCanceled: true}) { Trace.WriteLine($"ProcessSamplesChunk: Cancellation requested at sample {sampleIndex}"); return samples; } // Calculate global progress more accurately - each chunk processes start+sampleIndex samples int globalProgress = start + sampleIndex; var elapsed = chunkSw.Elapsed; var samplesPerSecond = sampleIndex / Math.Max(elapsed.TotalSeconds, 0.001); var progressInfo = $"Thread {Thread.CurrentThread.ManagedThreadId}: {samplesPerSecond:F0} samples/sec, {stackResolutionCount} stacks resolved"; UpdateProgress(progressCallback, ProfileLoadStage.TraceProcessing, rawProfile.Samples.Count, globalProgress, progressInfo); } if (!includeKernelEvents && sample.IsKernelCode) { kernelSamplesSkipped++; continue; } // Ignore other processes. var context = sample.GetContext(rawProfile); if (!processIds.Contains(context.ProcessId)) { otherProcessSamplesSkipped++; continue; } // Count time for each sample. var stack = sample.GetStack(rawProfile); ResolvedProfileStack resolvedStack = null; // Count time in the profile image. totalWeight += sample.Weight; profileWeight += sample.Weight; // If no stack is associated, use a dummy stack that has // a single frame with the sample IP, which is sufficient // to count the sample in the proper function as exclusive time. if (stack.IsUnknown) { stack = new ProfileStack { ContextId = sample.ContextId, //? TODO: Avoid allocating a new array for each sample. FramePointers = new long[1] {sample.IP} }; } // Process each stack frame to map it to a module:function // using the debug info. A stack is resolved only once, future // occurrences use the cached version. resolvedStack = stack.GetOptionalData() as ResolvedProfileStack; if (resolvedStack == null) { #if DEBUG Interlocked.Increment(ref UnresolvedStackCount); #endif stackResolutionCount++; resolvedStack = await ProcessUnresolvedStackAsync(stack, context, rawProfile, symbolSettings).ConfigureAwait(false); stack.SetOptionalData(resolvedStack); // Cache resolved stack. } else { #if DEBUG Interlocked.Increment(ref ResolvedStackCount); #endif } #if DEBUG RecordSampleStatistics(resolvedStack); #endif samples.Add((sample, resolvedStack)); } var finalElapsed = chunkSw.Elapsed; Trace.WriteLine($"ProcessSamplesChunk: Completed chunk {start}-{end} in {finalElapsed.TotalSeconds:F2}s, " + $"processed {samples.Count} samples, resolved {stackResolutionCount} stacks, " + $"skipped {kernelSamplesSkipped} kernel + {otherProcessSamplesSkipped} other process samples"); lock (lockObject_) { profileData_.TotalWeight += totalWeight; profileData_.ProfileWeight += profileWeight; } return samples; } private async Task ProcessUnresolvedStackAsync(ProfileStack stack, ProfileContext context, RawProfileData rawProfile, SymbolFileSourceSettings symbolSettings) { var sw = Stopwatch.StartNew(); var resolvedStack = new ResolvedProfileStack(stack.FrameCount, context); long[] stackFrames = stack.FramePointers; bool isManagedCode = false; int frameIndex = 0; int pointerSize = rawProfile.TraceInfo.PointerSize; int kernelFrames = 0; int managedFrames = 0; int unknownFrames = 0; int resolvedFrames = 0; bool prevFrameWasUnknownJit = false; //? TODO: Stacks with >256 frames are truncated, inclusive time computation is not right then //? for ex it never gets to main. Easy example is a quicksort impl for (; frameIndex < stackFrames.Length; frameIndex++) { long frameIp = stackFrames[frameIndex]; ProfileImage frameImage = null; isManagedCode = false; if (ETWEventProcessor.IsKernelAddress((ulong)frameIp, pointerSize)) { kernelFrames++; frameImage = rawProfile.FindImageForIP(frameIp, ETWEventProcessor.KernelProcessId); } else { frameImage = rawProfile.FindImageForIP(frameIp, context.ProcessId); } if (frameImage == null) { // Check if it's a .NET method, the JITted code may not mapped to any module. if (rawProfile.HasManagedMethods(context.ProcessId)) { var managedFunc = rawProfile.FindManagedMethodForIP(frameIp, context.ProcessId); if (managedFunc != null) { frameImage = managedFunc.Image; isManagedCode = true; managedFrames++; } } if (frameImage == null) { unknownFrames++; // for case when some kernel address used without a named corresponding module, // we should not label it as JIT immediately if (ETWEventProcessor.IsKernelAddress((ulong)frameIp, pointerSize)) { resolvedStack.AddFrame(null, frameIp, 0, frameIndex, ResolvedProfileStackFrameKey.Unknown, stack, pointerSize); prevFrameWasUnknownJit = false; continue; } // IP doesn't map to any known module (e.g., JITted). Attribute // to a synthetic per-thread JIT function, but collapse consecutive // unknown frames to avoid self-recursive chains in the call tree if (!prevFrameWasUnknownJit) { UnknownModuleState? unknownState = GetUnknownModule(context.ProcessId); if (unknownState != null) { (IRTextFunction function, FunctionDebugInfo debugInfo) = unknownState.GetOrCreateThreadFunction(context.ThreadId); ResolvedProfileStackFrameKey unknownFrame = new ResolvedProfileStackFrameKey(debugInfo, unknownState.Image, false); // Use a synthetic IP keyed by thread ID to prevent cache collisions // in ResolvedProfileStack.frameInstances_ when multiple threads // share the same unmapped IP long syntheticIp = MakeSyntheticIp(context.ProcessId, context.ThreadId); resolvedStack.AddFrame(function, syntheticIp, debugInfo.RVA, frameIndex, unknownFrame, stack, pointerSize); prevFrameWasUnknownJit = true; continue; } // Fallback when no synthetic module state for this process resolvedStack.AddFrame(null, frameIp, 0, frameIndex, ResolvedProfileStackFrameKey.Unknown, stack, pointerSize); continue; } // Consecutive unknown frame after a named JIT frame -- skip // to avoid self-recursive chains in the call tree. continue; } } // Try to resolve the frame using the lists of processes/images and debug info. long frameRva = 0; ProfileModuleBuilder profileModuleBuilder = null; var moduleStartTime = sw.Elapsed; profileModuleBuilder = await GetModuleBuilderAsync(rawProfile, frameImage, context.ProcessId, symbolSettings).ConfigureAwait(false); var moduleEndTime = sw.Elapsed; if (profileModuleBuilder == null) { unknownFrames++; resolvedStack.AddFrame(null, frameIp, 0, frameIndex, ResolvedProfileStackFrameKey.Unknown, stack, pointerSize); prevFrameWasUnknownJit = false; continue; } // Track significant module builder delays var moduleTime = (moduleEndTime - moduleStartTime).TotalMilliseconds; if (moduleTime > 10) { // Log delays > 10ms Trace.WriteLine($"Slow module builder for {frameImage.ModuleName}: {moduleTime:F1}ms"); } if (isManagedCode) { frameRva = frameIp; } else { frameRva = frameIp - frameImage.BaseAddress; } // Find the function the sample belongs to. var funcStartTime = sw.Elapsed; var funcPair = profileModuleBuilder.GetOrCreateFunction(frameRva); var funcEndTime = sw.Elapsed; // Track significant function lookup delays var funcTime = (funcEndTime - funcStartTime).TotalMilliseconds; if (funcTime > 10) { // Log delays > 10ms Trace.WriteLine($"Slow function lookup in {frameImage.ModuleName} at RVA 0x{frameRva:X}: {funcTime:F1}ms"); } // Create the function profile data, with the merged weight of all instances // of the func. across all call stacks. var resolvedFrame = new ResolvedProfileStackFrameKey(funcPair.DebugInfo, frameImage, profileModuleBuilder.IsManaged); resolvedStack.AddFrame(funcPair.Function, frameIp, frameRva, frameIndex, resolvedFrame, stack, pointerSize); resolvedFrames++; prevFrameWasUnknownJit = false; // Known frame breaks unknown frame run. } var totalTime = sw.Elapsed; // Log slow stack resolutions for debugging if (totalTime.TotalMilliseconds > 50) { // Log stacks taking > 50ms Trace.WriteLine($"Slow stack resolution: {totalTime.TotalMilliseconds:F1}ms for {stackFrames.Length} frames " + $"(resolved: {resolvedFrames}, unknown: {unknownFrames}, managed: {managedFrames}, kernel: {kernelFrames})"); } return resolvedStack; } private ProfileImage unknownModuleImage_; /// /// Pre-creates the synthetic [Unknown Module] for a process. Must be called /// before parallel sample processing begins. /// private void PreCreateUnknownModule(RawProfileData rawProfile, int processId) { // Share a single image across all processes to match how real modules // are deduplicated by AddImage. if (unknownModuleImage_ == null) { unknownModuleImage_ = new ProfileImage( filePath: UnknownModuleName, originalFileName: UnknownModuleName, baseAddress: 0, defaultBaseAddress: 0, size: 0, timeStamp: 0, checksum: 0); // Use AddImageDirect since LoadingCompleted() has already freed imagesMap_. rawProfile.AddImageDirect(unknownModuleImage_); profileData_.Modules[unknownModuleImage_.Id] = unknownModuleImage_; } var state = new UnknownModuleState(unknownModuleImage_, profileData_, processId); unknownModules_[processId] = state; Trace.WriteLine($"Pre-created synthetic {UnknownModuleName} for process {processId}, ImageId={unknownModuleImage_.Id}"); } /// /// Gets the pre-created synthetic module state for a process. /// Returns null if PreCreateUnknownModule was not called for this process. /// private UnknownModuleState? GetUnknownModule(int processId) { return unknownModules_.GetValueOrDefault(processId); } /// /// Creates a synthetic IP that is unique per (processId, threadId). /// Uses made up x64 address that shouldn't naturally be seen in traces, /// that stays below the IsKernelAddress threshold. /// private static long MakeSyntheticIp(int processId, int threadId) { ulong pid = (ulong)processId & ProcessIdMask; ulong tid = (uint)threadId; return unchecked((long)(SyntheticIpBase | (pid << 32) | tid)); } private ILoadedDocument FindSessionDocuments(string imageName, out List otherDocuments) { ILoadedDocument exeDocument = null; otherDocuments = new List(); foreach (ProfileModuleBuilder module in imageModuleMap_.Values) { var moduleDoc = module.ModuleDocument; if (moduleDoc == null) { continue; } if (Utilities.Utils.IsExecutableFile(moduleDoc.BinaryFile?.FilePath)) { if (exeDocument == null) { exeDocument = module.ModuleDocument; } else if (moduleDoc.ModuleName.Contains(imageName, StringComparison.OrdinalIgnoreCase)) { // Pick the better match EXE. otherDocuments.Add(exeDocument); exeDocument = module.ModuleDocument; continue; } } otherDocuments.Add(moduleDoc); if (module.DebugInfo != null) { // Used after profiling completes to unload debug info and free memory. profileData_.RegisterModuleDebugInfo(moduleDoc.ModuleName, module.DebugInfo); } } // Include synthetic [Unknown Module] documents so the UI can // navigate to JIT functions via FindLoadedDocument. foreach (var state in unknownModules_.Values) { otherDocuments.Add(state.Document); } return exeDocument; } private void UpdateProgress(ProfileLoadProgressHandler callback, ProfileLoadStage stage, int total, int current, string optional = null) { if (callback != null) { callback(new ProfileLoadProgress(stage) { Total = total, Current = current, Optional = optional }); } } private List<(ProfileImage Image, int SampleCount)> CollectTopModules(RawProfileData rawProfile, ProfileProcess mainProcess) { var moduleMap = new Dictionary(); int pointerSize = rawProfile.TraceInfo.PointerSize; var sampleRefs = CollectionsMarshal.AsSpan(rawProfile.Samples); var timer = Stopwatch.StartNew(); int index = 0; int totalSamplesProcessed = 0; int mainProcessSamples = 0; int samplesWithStacks = 0; int samplesWithoutStacks = 0; Trace.WriteLine($"TOP_MODULES_DEBUG: Starting top modules collection for process {mainProcess.ProcessId} ({mainProcess.ImageFileName})"); Trace.WriteLine($"TOP_MODULES_DEBUG: Total samples in trace: {rawProfile.Samples.Count}"); foreach (ref var sample in sampleRefs) { totalSamplesProcessed++; var context = sample.GetContext(rawProfile); if (context.ProcessId != mainProcess.ProcessId) { continue; } mainProcessSamples++; var stack = sample.GetStack(rawProfile); if (stack.IsUnknown) { // Even if no stack is available, count the sample IP itself for module identification // This allows us to load debug files for function name resolution even without stacks ProfileImage frameImage = null; if (ETWEventProcessor.IsKernelAddress((ulong)sample.IP, pointerSize)) { frameImage = rawProfile.FindImageForIP(sample.IP, ETWEventProcessor.KernelProcessId); } else { frameImage = rawProfile.FindImageForIP(sample.IP, context.ProcessId); } if (frameImage != null) { moduleMap.AccumulateValue(frameImage, 1); } samplesWithoutStacks++; continue; } samplesWithStacks++; foreach (long frame in stack.FramePointers) { ProfileImage frameImage = null; if (ETWEventProcessor.IsKernelAddress((ulong)frame, pointerSize)) { frameImage = rawProfile.FindImageForIP(frame, ETWEventProcessor.KernelProcessId); } else { frameImage = rawProfile.FindImageForIP(frame, context.ProcessId); } if (frameImage != null) { moduleMap.AccumulateValue(frameImage, 1); } } // Stop collecting after a couple seconds, it's good enough // for an approximated set of used modules. if ((++index & PROGRESS_UPDATE_INTERVAL - 1) == 0 && timer.ElapsedMilliseconds > 1000) { Trace.WriteLine($"TOP_MODULES_DEBUG: Early termination after {timer.ElapsedMilliseconds}ms at sample {totalSamplesProcessed}"); break; } } var moduleList = moduleMap.ToList(); moduleList.Sort((a, b) => b.Item2.CompareTo(a.Item2)); Trace.WriteLine($"TOP_MODULES_DEBUG: Collection completed in {timer.Elapsed}"); Trace.WriteLine($"TOP_MODULES_DEBUG: Processed {totalSamplesProcessed} total samples"); Trace.WriteLine($"TOP_MODULES_DEBUG: Found {mainProcessSamples} samples for main process {mainProcess.ProcessId}"); Trace.WriteLine($"TOP_MODULES_DEBUG: Found {samplesWithStacks} samples with valid stacks"); Trace.WriteLine($"TOP_MODULES_DEBUG: Found {samplesWithoutStacks} samples without stacks (using sample IP for module identification)"); Trace.WriteLine($"TOP_MODULES_DEBUG: Collected {moduleMap.Count} unique modules"); Trace.WriteLine($"TOP_MODULES_DEBUG: Top 20 modules by sample count:"); for (int i = 0; i < Math.Min(20, moduleList.Count); i++) { var module = moduleList[i]; Trace.WriteLine($"TOP_MODULES_DEBUG: {i + 1}. {module.Item1.ModuleName}: {module.Item2} samples (path: {module.Item1.FilePath})"); } Trace.WriteLine("TOP_MODULES_DEBUG: ====================================="); #if DEBUG Trace.WriteLine($"Collected top modules: {timer.Elapsed}, modules: {moduleMap.Count}"); foreach (var pair in moduleList) { Trace.WriteLine($" - {pair.Item1.ModuleName}: {pair.Item2}"); } Trace.WriteLine("-------------------------------------"); #endif return moduleList; } private async Task LoadBinaryAndDebugFiles(RawProfileData rawProfile, ProfileProcess mainProcess, string mainImageName, SymbolFileSourceSettings symbolSettings, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { var loadStartTime = Stopwatch.StartNew(); DiagnosticLogger.LogInfo($"[SymbolLoading] === Starting LoadBinaryAndDebugFiles for process {mainProcess.ImageFileName} ==="); var imageList = mainProcess.Images(rawProfile).ToList(); var kernelProc = rawProfile.FindProcess(ETWEventProcessor.KernelProcessId); if (kernelProc != null) { imageList.AddRange(kernelProc.Images(rawProfile)); } int imageLimit = imageList.Count; DiagnosticLogger.LogInfo($"[SymbolLoading] Total images to process: {imageLimit} (including kernel modules: {kernelProc != null})"); // Find the modules with samples, sorted by sample count. // Used to skip loading of insignificant modules with few samples. var topModules = CollectTopModules(rawProfile, mainProcess); int moduleSampleCutOff = 0; if (symbolSettings.SkipLowSampleModules) { moduleSampleCutOff = (int)(symbolSettings.LowSampleModuleCutoff * rawProfile.Samples.Count); } DiagnosticLogger.LogInfo($"[SymbolLoading] Module filtering: SkipLowSampleModules={symbolSettings.SkipLowSampleModules}, " + $"Cutoff={moduleSampleCutOff} ({symbolSettings.LowSampleModuleCutoff:P1} of {rawProfile.Samples.Count} samples), " + $"TopModulesCount={topModules.Count}"); // Log symbol server configuration for diagnostics DiagnosticLogger.LogInfo($"[SymbolLoading] Symbol server enabled: {symbolSettings.SourceServerEnabled}"); DiagnosticLogger.LogInfo($"[SymbolLoading] Symbol paths: {string.Join("; ", symbolSettings.SymbolPaths)}"); DiagnosticLogger.LogInfo($"[SymbolLoading] Initial timeout: {symbolSettings.EffectiveTimeoutSeconds}s (Bellwether: {symbolSettings.BellwetherTimeoutSeconds}s, Normal: {symbolSettings.SymbolServerTimeoutSeconds}s, Degraded: {symbolSettings.DegradedTimeoutSeconds}s)"); Trace.WriteLine($"BINARY_FILTER_DEBUG: Sample cutoff calculation: {symbolSettings.LowSampleModuleCutoff} * {rawProfile.Samples.Count} = {moduleSampleCutOff}"); Trace.WriteLine($"BINARY_FILTER_DEBUG: Skip low sample modules: {symbolSettings.SkipLowSampleModules}"); Trace.WriteLine($"BINARY_FILTER_DEBUG: Starting PDB filtering for {imageLimit} total modules"); // PDB task list for parallel downloads var pdbTaskList = new Task[imageLimit]; // Sanity check: Do we have ImageID DbgID events (PDB GUID/Age)? // Without GUID/Age, PDB symbol server lookup is IMPOSSIBLE - the server requires GUID+Age. // The GUID comes from the trace's ImageID DbgID events, NOT from downloading binaries. // The pragmatic solution is to skip symbol server entirely and use local symbols only. // This matches WPA's behavior which requires ImageID events for symbol server lookup. if (!rawProfile.TraceInfo.HasImageIdEvents) { DiagnosticLogger.LogWarning("[SymbolLoading] Trace has no ImageID DbgID events (PDB GUID/Age missing). " + "Symbol server lookups require GUID+Age. Disabling symbol server. " + "Using local symbols only. Consider re-capturing with 'wpr -start CPU'."); symbolSettings.SourceServerEnabled = false; } // Bellwether test: try to download the ntoskrnl PDB first to check symbol server health // Use 30s timeout for first connection (warmup), then reduce to 10s for subsequent downloads if (symbolSettings.BellwetherTestEnabled && symbolSettings.SourceServerEnabled) { await PerformBellwetherTest(imageList, rawProfile, symbolSettings); } // LAZY BINARY LOADING: Skip upfront binary downloads entirely. // Binaries are only needed for disassembly view, not for function name resolution. // Function names come from PDB files, which use GUID/Age from ImageID events in trace. // Binaries will be downloaded on-demand when user views assembly for a function. // This dramatically speeds up trace loading (from minutes to seconds). DiagnosticLogger.LogInfo("[SymbolLoading] Skipping upfront binary downloads (lazy loading enabled). " + "Binaries will be downloaded on-demand when viewing assembly."); // Determine the compiler target from trace metadata instead of binaries. // PointerSize tells us if it's a 64-bit or 32-bit OS. // Note: Individual processes can be 32-bit (WoW64) on 64-bit OS. // We default to the OS architecture here; per-module architecture is inferred // from path (SysWOW64 = 32-bit) or determined when the binary is loaded on-demand. var irMode = IRMode.Default; if (rawProfile.TraceInfo.PointerSize == 8) { // 64-bit system - could be x64 or ARM64, but x64 is far more common // TODO: Could potentially detect ARM64 from other trace metadata if needed irMode = IRMode.x86_64; defaultArchitecture_ = Machine.Amd64; DiagnosticLogger.LogInfo("[SymbolLoading] Detected 64-bit OS from trace metadata (PointerSize=8)"); } else if (rawProfile.TraceInfo.PointerSize == 4) { irMode = IRMode.x86_64; // x86 is supported under x86_64 mode defaultArchitecture_ = Machine.I386; DiagnosticLogger.LogInfo("[SymbolLoading] Detected 32-bit OS from trace metadata (PointerSize=4)"); } else { DiagnosticLogger.LogWarning($"[SymbolLoading] Unknown pointer size {rawProfile.TraceInfo.PointerSize}, defaulting to x86_64"); irMode = IRMode.x86_64; defaultArchitecture_ = Machine.Amd64; } Trace.WriteLine($"Binary download skipped (lazy loading) - architecture detected from trace: {irMode}"); compilerInfoProvider_ = new ASMCompilerInfoProvider(irMode); await (StartNewSessionRequested?.Invoke(mainImageName, SessionKind.FileSession, compilerInfoProvider_) ?? Task.CompletedTask); // Locate the needed debug files, in parallel. This will download them // from the symbol server if not yet on local machine and enabled. int pdbCount = 0; var pdbTaskSemaphore = new SemaphoreSlim(12); var pdbSw = Stopwatch.StartNew(); // Skip PDB symbol server lookups if disabled (e.g., no ImageID events in trace) if (!symbolSettings.SourceServerEnabled) { DiagnosticLogger.LogInfo("[SymbolLoading] Symbol server disabled - skipping PDB downloads. " + "Will search local paths only."); } DiagnosticLogger.LogInfo($"[SymbolLoading] Starting PDB/symbol file search for {imageLimit} images. Sample cutoff: {moduleSampleCutOff}"); // Log top modules from sample analysis (with Microsoft flag from trace FileVersion events) DiagnosticLogger.LogInfo($"[SymbolLoading] Top 10 modules by sample count:"); for (int t = 0; t < Math.Min(10, topModules.Count); t++) { var tm = topModules[t]; string msTag = tm.Item1.IsMicrosoft ? " [Microsoft]" : ""; DiagnosticLogger.LogInfo($"[SymbolLoading] {t+1}. {tm.Item1.ModuleName}: {tm.SampleCount} samples{msTag}"); } Trace.WriteLine($"DEBUG_FILTER_DEBUG: Starting debug file search for {imageLimit} modules. Low sample cutoff: {moduleSampleCutOff}"); for (int i = 0; i < imageLimit; i++) { if (cancelableTask is {IsCanceled: true}) { DiagnosticLogger.LogInfo($"[SymbolLoading] PDB loading cancelled at image {i}/{imageLimit}"); return; } // Apply module filtering (same logic that was used for binary filtering) if (!IsAcceptedModule(imageList[i])) { Trace.WriteLine($"DEBUG_FILTER_DEBUG: Debug file search SKIPPED - Module rejected by binary name allowlist: {imageList[i].ModuleName} (path: {imageList[i].FilePath})"); rejectedDebugModules_.Add(imageList[i]); continue; } int moduleIndex = topModules.FindIndex(pair => pair.Item1 == imageList[i]); bool acceptModule = moduleIndex >= 0 && topModules[moduleIndex].SampleCount > moduleSampleCutOff; if (!acceptModule) { if (moduleIndex < 0) { Trace.WriteLine($"DEBUG_FILTER_DEBUG: Debug file search SKIPPED - Module not in top modules list: {imageList[i].ModuleName} (path: {imageList[i].FilePath})"); } else { long sampleCount = topModules[moduleIndex].SampleCount; Trace.WriteLine($"DEBUG_FILTER_DEBUG: Debug file search SKIPPED - Module sample count too low: {imageList[i].ModuleName} (samples: {sampleCount}, cutoff: {moduleSampleCutOff})"); } rejectedDebugModules_.Add(imageList[i]); continue; } // With lazy binary loading, we use ETL symbol file descriptors (ImageID events) for PDB lookup. // This contains GUID/Age which is required for symbol server lookup. var symbolFile = rawProfile.GetDebugFileForImage(imageList[i], mainProcess.ProcessId); if (symbolFile == null) { // No ImageID_DbgID event for this module - can't download PDB without GUID/Age string msTag = imageList[i].IsMicrosoft ? " [Microsoft]" : ""; DiagnosticLogger.LogWarning($"[SymbolLoading] No PDB info (ImageID_DbgID event) for {imageList[i].ModuleName}{msTag} at base 0x{imageList[i].BaseAddress:X} - skipping PDB download"); continue; } if (symbolFile != null) { if (symbolSettings.IsRejectedSymbolFile(symbolFile)) { // Log all rejected symbol files - negative cache from previous failed downloads string msTag = imageList[i].IsMicrosoft ? " [Microsoft]" : ""; DiagnosticLogger.LogWarning($"[SymbolLoading] REJECTED: {imageList[i].ModuleName}{msTag} symbol file in negative cache: {symbolFile.FileName} (ID: {symbolFile.Id})"); Trace.WriteLine($"DEBUG_FILTER_DEBUG: Debug file search SKIPPED - Symbol file previously rejected: {imageList[i].ModuleName} (symbol: {symbolFile})"); rejectedDebugModules_.Add(imageList[i]); continue; } pdbCount++; Trace.WriteLine($"DEBUG_FILTER_DEBUG: Debug file search STARTED - Using ETL symbol file descriptor: {imageList[i].ModuleName} (symbol: {symbolFile})"); var taskSymbolFile = symbolFile; pdbTaskList[i] = Task.Run(async () => { await pdbTaskSemaphore.WaitAsync(); DebugFileSearchResult result; Task downloadTask = null; try { // Apply manual timeout since TraceEvent's ServerTimeout doesn't work reliably int timeoutSeconds = symbolSettings.EffectiveTimeoutSeconds > 0 ? symbolSettings.EffectiveTimeoutSeconds : 10; using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds)); downloadTask = compilerInfoProvider_.DebugFileFinder.FindDebugInfoFileAsync(taskSymbolFile, symbolSettings); var timeoutTask = Task.Delay(Timeout.Infinite, cts.Token); var completedTask = await Task.WhenAny(downloadTask, timeoutTask).ConfigureAwait(false); if (completedTask == downloadTask) { result = await downloadTask.ConfigureAwait(false); } else { DiagnosticLogger.LogWarning($"[SymbolSearch] TIMEOUT after {timeoutSeconds}s for {taskSymbolFile.FileName}"); result = DebugFileSearchResult.Failure(taskSymbolFile, $"Timeout after {timeoutSeconds}s"); // Track timeout as a failure, but DON'T cache it (transient failure) symbolSettings.RejectSymbolFile(taskSymbolFile, SymbolFileRejectionReason.NetworkTimeout, $"Timeout after {timeoutSeconds}s"); // After first timeout, reduce timeout for subsequent downloads if (!symbolSettings.HadFirstTimeout) { symbolSettings.HadFirstTimeout = true; DiagnosticLogger.LogInfo($"[SymbolSearch] First timeout detected - reducing timeout from {timeoutSeconds}s to {symbolSettings.SymbolServerTimeoutSeconds}s for remaining downloads"); } } } catch (OperationCanceledException) { result = DebugFileSearchResult.Failure(taskSymbolFile, "Cancelled"); } finally { // Wait for the underlying download to actually complete before releasing semaphore. if (downloadTask != null && !downloadTask.IsCompleted) { try { await downloadTask.ConfigureAwait(false); } catch { // Ignore errors from the orphaned task } } pdbTaskSemaphore.Release(); } return result; }); } else { // No symbol file descriptor in ETL - this module won't have symbols // until user clicks on a function (lazy binary loading will try then) Trace.WriteLine($"DEBUG_FILTER_DEBUG: Debug file search SKIPPED - No symbol file descriptor in ETL: {imageList[i].ModuleName} (path: {imageList[i].FilePath})"); } } int pdbTasksStarted = pdbTaskList.Count(t => t != null); DiagnosticLogger.LogInfo($"[SymbolLoading] PDB download phase: Started {pdbTasksStarted} download tasks for {pdbCount} eligible modules"); // Wait for ALL PDB tasks to complete in parallel before processing results. // Report progress incrementally as tasks complete (not just at the end). var activePdbTasks = pdbTaskList.Where(t => t != null).ToArray(); if (activePdbTasks.Length > 0) { DiagnosticLogger.LogInfo($"[SymbolLoading] Waiting for {activePdbTasks.Length} PDB downloads to complete in parallel..."); // Track completions and report progress incrementally int pdbCompletedCount = 0; int pdbTotalTasks = activePdbTasks.Length; // Start a progress monitoring task that reports progress every 500ms var pdbProgressCts = new CancellationTokenSource(); var pdbProgressTask = Task.Run(async () => { int lastReported = -1; while (!pdbProgressCts.Token.IsCancellationRequested) { int current = Volatile.Read(ref pdbCompletedCount); if (current != lastReported) { UpdateProgress(progressCallback, ProfileLoadStage.SymbolLoading, pdbTotalTasks, current, "PDB downloads"); lastReported = current; } try { await Task.Delay(500, pdbProgressCts.Token).ConfigureAwait(false); } catch (OperationCanceledException) { break; } } }); // Attach completion tracking to each task var pdbTrackingTasks = activePdbTasks.Select(task => task.ContinueWith(_ => Interlocked.Increment(ref pdbCompletedCount), TaskContinuationOptions.ExecuteSynchronously) ).ToArray(); // Wait for all downloads to complete await Task.WhenAll(activePdbTasks).ConfigureAwait(false); // Stop progress monitoring pdbProgressCts.Cancel(); try { await pdbProgressTask.ConfigureAwait(false); } catch { } DiagnosticLogger.LogInfo($"[SymbolLoading] All PDB downloads completed in {pdbSw.Elapsed.TotalSeconds:F1}s"); } // Note: Don't reset progress here - we're about to process results which is fast // UpdateProgress is called per-module in the loop below int pdbsFound = 0; int pdbsProcessed = 0; // Process results (tasks already completed, so this is fast) for (int i = 0; i < imageLimit; i++) { if (cancelableTask is {IsCanceled: true}) { DiagnosticLogger.LogInfo($"[SymbolLoading] PDB download cancelled at image {i}/{imageLimit}"); return; } // Always update progress even for skipped modules UpdateProgress(progressCallback, ProfileLoadStage.SymbolLoading, imageLimit, i, imageList[i].ModuleName); if (pdbTaskList[i] != null) { pdbsProcessed++; var pdbTaskStart = Stopwatch.StartNew(); var pdbPath = await pdbTaskList[i].ConfigureAwait(false); var pdbTaskDuration = pdbTaskStart.Elapsed; // Log slow PDB lookups (> 2 seconds) if (pdbTaskDuration.TotalSeconds > 2) { DiagnosticLogger.LogWarning($"[SymbolLoading] Slow PDB lookup ({pdbTaskDuration.TotalSeconds:F1}s): {imageList[i].ModuleName} - Found: {pdbPath.Found}"); } if (pdbPath.Found) { pdbsFound++; } } } var totalPdbTime = pdbSw.Elapsed; DiagnosticLogger.LogInfo($"[SymbolLoading] PDB download complete: {pdbsFound}/{pdbsProcessed} found in {totalPdbTime.TotalSeconds:F1}s"); DiagnosticLogger.LogInfo($"[SymbolLoading] === LoadBinaryAndDebugFiles completed in {loadStartTime.Elapsed.TotalSeconds:F1}s ==="); // Report completion (current=total means 100%) UpdateProgress(progressCallback, ProfileLoadStage.SymbolLoading, imageLimit, imageLimit); Trace.WriteLine($"PDB download time: {totalPdbTime}"); } private async Task CreateModuleBuilderAsync(ProfileImage image, RawProfileData rawProfile, int processId, SymbolFileSourceSettings symbolSettings) { var totalSw = Stopwatch.StartNew(); var imageModule = new ProfileModuleBuilder(report_, compilerInfoProvider_); IDebugInfoProvider imageDebugInfo = null; Trace.WriteLine($"CreateModuleBuilderAsync: Starting for module {image.ModuleName}"); // Time spent on initial setup var initSw = Stopwatch.StartNew(); if (IsAcceptedModule(image)) { imageDebugInfo = rawProfile.GetDebugInfoForManagedImage(image, processId); if (imageDebugInfo != null) { imageDebugInfo.SymbolSettings = symbolSettings; Trace.WriteLine($"CreateModuleBuilderAsync: Found managed debug info for {image.ModuleName}"); } } var initTime = initSw.Elapsed; // Time spent on module initialization var moduleInitSw = Stopwatch.StartNew(); Trace.WriteLine($"CreateModuleBuilderAsync: Calling Initialize for {image.ModuleName}"); try { // LAZY BINARY LOADING: Skip binary download during trace loading. // Binaries will be downloaded on-demand when user views assembly. bool moduleInitialized = await imageModule.Initialize(FromProfileImage(image, rawProfile, processId), symbolSettings, imageDebugInfo, skipBinaryDownload: true).ConfigureAwait(false); var moduleInitTime = moduleInitSw.Elapsed; Trace.WriteLine($"CreateModuleBuilderAsync: Initialize completed for {image.ModuleName}, result: {moduleInitialized}"); if (moduleInitialized) { // If binary couldn't be found, try to initialize using // the PDB signature from the trace file. if (rejectedDebugModules_.Contains(image)) { #if DEBUG Trace.WriteLine($"CreateModuleBuilderAsync: Skipped rejected module {image.ModuleName}"); #endif return imageModule; } // Time spent on debug info file lookup. // Always try to find PDB - it may be cached locally from the initial download phase. var debugFileSw = Stopwatch.StartNew(); var debugInfoFile = await GetDebugInfoFile(imageModule.ModuleDocument.BinaryFile, image, rawProfile, processId, symbolSettings); var debugFileTime = debugFileSw.Elapsed; // Time spent on debug info initialization var debugInitSw = Stopwatch.StartNew(); bool debugInitialized = false; if (debugInfoFile != null) { Trace.WriteLine($"CreateModuleBuilderAsync: Initializing debug info for {image.ModuleName}"); debugInitialized = await imageModule.InitializeDebugInfo(debugInfoFile).ConfigureAwait(false); Trace.WriteLine($"CreateModuleBuilderAsync: Debug info initialization for {image.ModuleName}, result: {debugInitialized}"); } else { Trace.WriteLine($"CreateModuleBuilderAsync: No debug info file found for {image.ModuleName}"); } var debugInitTime = debugInitSw.Elapsed; if (debugInfoFile != null && !debugInitialized) { Trace.TraceWarning($"CreateModuleBuilderAsync: Failed to load debug debugInfo for image: {image.FilePath}"); } var totalTime = totalSw.Elapsed; // Log modules that take significant time to create if (totalTime.TotalMilliseconds > 100) { // Log modules taking > 100ms Trace.WriteLine($"CreateModuleBuilderAsync: Slow module creation for {image.ModuleName}: {totalTime.TotalMilliseconds:F1}ms total " + $"(init: {initTime.TotalMilliseconds:F1}ms, module: {moduleInitTime.TotalMilliseconds:F1}ms, " + $"debugFile: {debugFileTime.TotalMilliseconds:F1}ms, debugInit: {debugInitTime.TotalMilliseconds:F1}ms)"); } } else { var totalTime = totalSw.Elapsed; Trace.WriteLine($"CreateModuleBuilderAsync: Module initialization failed for {image.ModuleName} after {totalTime.TotalMilliseconds:F1}ms"); } Trace.WriteLine($"CreateModuleBuilderAsync: Completed for module {image.ModuleName}"); return imageModule; } catch (Exception ex) { Trace.WriteLine($"CreateModuleBuilderAsync: EXCEPTION for module {image.ModuleName}: {ex.GetType().Name}: {ex.Message}"); Trace.WriteLine($"CreateModuleBuilderAsync: Stack trace: {ex.StackTrace}"); throw; } } private async Task GetDebugInfoFile(BinaryFileSearchResult binaryFile, ProfileImage image, RawProfileData rawProfile, int processId, SymbolFileSourceSettings symbolSettings) { if (binaryFile is {Found: true}) { return await compilerInfoProvider_.DebugFileFinder.FindDebugInfoFileAsync(binaryFile.FilePath, symbolSettings); } else { // Try to use ETL info if binary not available. var symbolFile = rawProfile.GetDebugFileForImage(image, processId); if (symbolFile != null) { return await compilerInfoProvider_.DebugFileFinder.FindDebugInfoFileAsync(symbolFile, symbolSettings); } } return null; } private bool IsAcceptedModule(ProfileImage image) { if (!options_.HasBinaryNameAllowedList) { Trace.WriteLine($"BINARY_FILTER_DEBUG: Module PASSED binary name allowlist check - No allowlist defined: {image.ModuleName} (path: {image.FilePath})"); return true; } Trace.WriteLine($"BINARY_FILTER_DEBUG: Checking binary name allowlist for module: {image.ModuleName} (path: {image.FilePath})"); Trace.WriteLine($"BINARY_FILTER_DEBUG: Binary name allowlist contents: [{string.Join(", ", options_.BinaryNameAllowedList)}]"); foreach (string file in options_.BinaryNameAllowedList) { string fileName = Utilities.Utils.TryGetFileNameWithoutExtension(file); Trace.WriteLine($"BINARY_FILTER_DEBUG: Comparing '{image.ModuleName}' against allowlist entry '{fileName}' (original: '{file}')"); if (fileName.Equals(image.ModuleName, StringComparison.OrdinalIgnoreCase)) { Trace.WriteLine($"BINARY_FILTER_DEBUG: Module PASSED binary name allowlist check - Matched '{fileName}': {image.ModuleName}"); return true; } } Trace.WriteLine($"BINARY_FILTER_DEBUG: Module FAILED binary name allowlist check - Not found in allowlist: {image.ModuleName} (path: {image.FilePath})"); return false; } private async Task GetModuleBuilderAsync(RawProfileData rawProfile, ProfileImage queryImage, int processId, SymbolFileSourceSettings symbolSettings) { // prevImage_/prevModule_ are TLS variables since this is called from multiple threads. if (queryImage == prevImage_) { return prevProfileModuleBuilder_; } if (!imageModuleMap_.TryGetValue(queryImage.Id, out var imageModule)) { // TODO: Why not lock on queryImage? lock (imageLocks_[queryImage.Id % IMAGE_LOCK_COUNT]) { if (imageModuleMap_.TryGetValue(queryImage.Id, out imageModule)) { prevImage_ = queryImage; prevProfileModuleBuilder_ = imageModule; return imageModule; } } // Create the module builder outside the lock to avoid blocking other threads imageModule = await CreateModuleBuilderAsync(queryImage, rawProfile, processId, symbolSettings).ConfigureAwait(false); // Add to the cache. If another thread already added a module, use that one instead // to ensure all threads share the same (hopefully initialized) instance. if (!imageModuleMap_.TryAdd(queryImage.Id, imageModule)) { // Another thread won the race - use their module instead imageModule = imageModuleMap_[queryImage.Id]; } } prevImage_ = queryImage; prevProfileModuleBuilder_ = imageModule; return imageModule; } private ProfileModuleBuilder GetModuleBuilder(RawProfileData rawProfile, ProfileImage queryImage, int processId, SymbolFileSourceSettings symbolSettings) { // prevImage_/prevModule_ are TLS variables since this is called from multiple threads. if (queryImage == prevImage_) { return prevProfileModuleBuilder_; } if (!imageModuleMap_.TryGetValue(queryImage.Id, out var imageModule)) { // TODO: Why not lock on queryImage? lock (imageLocks_[queryImage.Id % IMAGE_LOCK_COUNT]) { if (imageModuleMap_.TryGetValue(queryImage.Id, out imageModule)) { return imageModule; } // Fall back to sync version with deadlock risk - this is for compatibility imageModule = CreateModuleBuilderAsync(queryImage, rawProfile, processId, symbolSettings).ConfigureAwait(false).GetAwaiter().GetResult(); imageModuleMap_.TryAdd(queryImage.Id, imageModule); } } prevImage_ = queryImage; prevProfileModuleBuilder_ = imageModule; return imageModule; } private void ProcessPerformanceCounters(RawProfileData rawProfile, List processIds, SymbolFileSourceSettings symbolSettings, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { // Register the counters found in the trace. foreach (var counter in rawProfile.PerformanceCounters) { profileData_.RegisterPerformanceCounter(counter); } // Try to register the metrics. int metricIndex = 1000; int index = 0; foreach (var metric in options_.PerformanceMetrics) { if (metric.IsEnabled) { profileData_.RegisterPerformanceMetric(metricIndex++, metric); } } //? TODO: Parallel //? TODO: Use ref foreach currentSampleIndex_ = 0; Trace.WriteLine($"Start process PMC at {DateTime.Now}"); var sw = Stopwatch.StartNew(); foreach (var counter in rawProfile.PerformanceCountersEvents) { if ((++index & PROGRESS_UPDATE_INTERVAL - 1) == 0) { // Update progress every 128K samples. if (cancelableTask is {IsCanceled: true}) { break; } UpdateProgress(progressCallback, ProfileLoadStage.PerfCounterProcessing, rawProfile.PerformanceCountersEvents.Count, index); } var context = counter.GetContext(rawProfile); if (!processIds.Contains(context.ProcessId)) { continue; } int managedBaseAddress = 0; var frameImage = rawProfile.FindImageForIP(counter.IP, context); if (frameImage == null) { if (rawProfile.HasManagedMethods(context.ProcessId)) { var managedFunc = rawProfile.FindManagedMethodForIP(counter.IP, context.ProcessId); if (managedFunc != null) { frameImage = managedFunc.Image; managedBaseAddress = 1; } } // If real module and managed method lookup both fail, attribute to synthetic "Unknown" to preserve counts if (frameImage == null) { frameImage = GetUnknownModule(context.ProcessId)?.Image; } } if (frameImage != null) { profileData_.AddModuleCounter(frameImage.ModuleName, counter.CounterId, 1); var profileModuleBuilder = GetModuleBuilder(rawProfile, frameImage, context.ProcessId, symbolSettings); if (profileModuleBuilder == null) { continue; } if (!profileModuleBuilder.HasDebugInfo) { continue; } long frameRva = managedBaseAddress != 0 ? counter.IP : counter.IP - frameImage.BaseAddress; var funcPair = profileModuleBuilder.GetOrCreateFunction(frameRva); long funcRva = funcPair.DebugInfo.RVA; long offset = frameRva - funcRva; var profile = profileData_.GetOrCreateFunctionProfile(funcPair.Function, funcPair.DebugInfo); profile.AddCounterSample(offset, counter.CounterId, 1); } // profileData_.Events.Add((counter, null)); } Trace.WriteLine($"Done process PMC in {sw.Elapsed}"); } private BinaryFileDescriptor FromProfileImage(ProfileImage image, RawProfileData rawProfile, int processId) { // Architecture detection: Use process's IsWow64 flag from ETW ProcessStart events. // ProcessFlags.Wow64 indicates a 32-bit process running on 64-bit Windows. var architecture = defaultArchitecture_; // For kernel modules, use OS architecture (kernel is always native) if (!ETWEventProcessor.IsKernelAddress((ulong)image.BaseAddress, rawProfile.TraceInfo.PointerSize)) { // User-mode module: check if the process is WoW64 (32-bit on 64-bit) var process = rawProfile.FindProcess(processId); if (process != null && process.IsWow64) { architecture = Machine.I386; } } return new BinaryFileDescriptor { ImageName = image.ModuleName, ImagePath = image.FilePath, Architecture = architecture, Checksum = image.Checksum, TimeStamp = image.TimeStamp, ImageSize = image.Size }; } /// /// Performs a "bellwether" test by attempting to download the ntoskrnl PDB (the Windows kernel symbols). /// If this fails, it indicates the symbol server is unavailable or slow, and we should /// reduce timeouts to avoid wasting time on failed downloads. /// private async Task PerformBellwetherTest(List imageList, RawProfileData rawProfile, SymbolFileSourceSettings symbolSettings) { // Find ntoskrnl.exe in the image list - it's always present in ETW traces var bellwetherImage = imageList.FirstOrDefault(img => img.ModuleName.Equals("ntoskrnl.exe", StringComparison.OrdinalIgnoreCase)); if (bellwetherImage == null) { // Try ntdll.dll as fallback bellwetherImage = imageList.FirstOrDefault(img => img.ModuleName.Equals("ntdll.dll", StringComparison.OrdinalIgnoreCase)); } if (bellwetherImage == null) { DiagnosticLogger.LogInfo("[BellwetherTest] No bellwether image found (ntoskrnl.exe or ntdll.dll), skipping test"); return; } // Get the PDB info for the bellwether image from the trace's ImageID DbgID events. // ntoskrnl is a kernel module, so use KernelProcessId. var symbolFile = rawProfile.GetDebugFileForImage(bellwetherImage, ETWEventProcessor.KernelProcessId); if (symbolFile == null) { DiagnosticLogger.LogWarning($"[BellwetherTest] No PDB info (ImageID DbgID event) for {bellwetherImage.ModuleName}, skipping test"); return; } var sw = Stopwatch.StartNew(); // Use EffectiveTimeoutSeconds which is PreAuthTimeoutSeconds (10 min) until auth is validated. // This allows time for the user to interact with the auth dialog without timing out. int timeoutSeconds = symbolSettings.EffectiveTimeoutSeconds; // Log symbol server configuration DiagnosticLogger.LogInfo($"[BellwetherTest] Symbol paths configured: {string.Join("; ", symbolSettings.SymbolPaths)}"); DiagnosticLogger.LogInfo($"[BellwetherTest] Testing symbol server health with {symbolFile.FileName} PDB (timeout: {timeoutSeconds}s, pre-auth: {!symbolSettings.HadFirstSuccessfulNetworkRequest})"); DiagnosticLogger.LogInfo($"[BellwetherTest] PDB GUID: {symbolFile.Id}, Age: {symbolFile.Age}"); try { using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeoutSeconds)); // Run the synchronous PDB lookup in a background task with timeout var downloadTask = Task.Run(() => PDBDebugInfoProvider.LocateDebugInfoFile(symbolFile, symbolSettings), cts.Token); var timeoutTask = Task.Delay(Timeout.Infinite, cts.Token); var completedTask = await Task.WhenAny(downloadTask, timeoutTask).ConfigureAwait(false); if (completedTask == downloadTask) { var result = await downloadTask.ConfigureAwait(false); var elapsedMs = sw.ElapsedMilliseconds; if (result.Found) { // Check if this was a cache hit (very fast response, < 500ms) // A real network download would take longer bool likelyCacheHit = elapsedMs < 500; string cacheNote = likelyCacheHit ? " (likely from local cache - not a true network test)" : ""; DiagnosticLogger.LogInfo($"[BellwetherTest] SUCCESS: {symbolFile.FileName} PDB found at {result.FilePath} in {sw.Elapsed.TotalSeconds:F1}s{cacheNote}"); if (likelyCacheHit) { // Cache hit doesn't prove network works - the first REAL network request will be the true bellwether DiagnosticLogger.LogInfo("[BellwetherTest] Fast response suggests local cache hit. Network connectivity not verified."); DiagnosticLogger.LogInfo("[BellwetherTest] First real network request will determine timeout strategy."); // Don't change any flags - first real network request will set HadFirstTimeout or HadFirstSuccessfulNetworkRequest } else { // Actual network download succeeded - THIS is the real bellwether, network is verified DiagnosticLogger.LogInfo("[BellwetherTest] Network download verified (took real network time). Symbol server is healthy."); symbolSettings.HadFirstSuccessfulNetworkRequest = true; } symbolSettings.SymbolServerDegraded = false; } else { // PDB not found on symbol server - this is expected for some builds // Mark as degraded so we use shorter timeouts for other PDBs DiagnosticLogger.LogWarning($"[BellwetherTest] FAILED: {symbolFile.FileName} PDB not found on symbol server ({sw.Elapsed.TotalSeconds:F1}s) - " + $"Symbols may not be available for this build. Using reduced timeout ({symbolSettings.DegradedTimeoutSeconds}s)"); symbolSettings.SymbolServerDegraded = true; } } else { // Timeout - symbol server is slow or unreachable DiagnosticLogger.LogWarning($"[BellwetherTest] TIMEOUT: {symbolFile.FileName} PDB timed out after {timeoutSeconds}s - " + $"Symbol server may be slow or unreachable. Using reduced timeout ({symbolSettings.DegradedTimeoutSeconds}s)"); symbolSettings.SymbolServerDegraded = true; } } catch (OperationCanceledException) { DiagnosticLogger.LogWarning($"[BellwetherTest] TIMEOUT: {symbolFile.FileName} PDB timed out after {timeoutSeconds}s - Using reduced timeout"); symbolSettings.SymbolServerDegraded = true; } catch (Exception ex) { DiagnosticLogger.LogWarning($"[BellwetherTest] ERROR: {symbolFile.FileName} PDB failed with exception: {ex.Message} - Using reduced timeout"); symbolSettings.SymbolServerDegraded = true; } if (symbolSettings.SymbolServerDegraded) { DiagnosticLogger.LogWarning($"[BellwetherTest] Symbol server marked as DEGRADED - using {symbolSettings.DegradedTimeoutSeconds}s timeout instead of {symbolSettings.SymbolServerTimeoutSeconds}s"); } else { DiagnosticLogger.LogInfo($"[BellwetherTest] Using initial timeout: {symbolSettings.EffectiveTimeoutSeconds}s (will reduce to {symbolSettings.SymbolServerTimeoutSeconds}s after first timeout)"); } } #if DEBUG private void RecordSampleStatistics(ResolvedProfileStack resolvedStack) { // Record statistics about the most common RVAs with exclusive samples. if (resolvedStack.FrameCount <= 0) return; lock (lockObject_) { perModuleSampleStatsMap_ ??= new(); var topFrame = resolvedStack.StackFrames[0]; if (topFrame.FrameDetails.Image == null) { return; } var moduleStats = perModuleSampleStatsMap_.GetOrAddValue(topFrame.FrameDetails.Image); if (!moduleStats.TryGetValue(topFrame.FrameRVA, out var rvaStats)) { rvaStats = (topFrame.FrameDetails.DebugInfo, 1); moduleStats[topFrame.FrameRVA] = rvaStats; } else { rvaStats.SampleCount++; moduleStats[topFrame.FrameRVA] = rvaStats; } } } private void PrintSampleStatistics() { lock (lockObject_) { if (perModuleSampleStatsMap_ == null) { return; } Trace.WriteLine("Per-module RVA sample stats"); foreach (var moduleStats in perModuleSampleStatsMap_) { Trace.WriteLine($"--------------\n{moduleStats.Key.ModuleName}:"); var rvaStats = moduleStats.Value.ToList(); rvaStats.Sort((a, b) => b.Item2.SampleCount.CompareTo(a.Item2.SampleCount)); foreach (var (rva, sampleStats) in rvaStats) { Trace.WriteLine($" - RVA {rva:X}: {sampleStats.SampleCount} samples, func: {sampleStats.Info.Name}"); } } } } #endif } ================================================ FILE: src/ProfileExplorerCore/Profile/ETW/ETWRecordingSession.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Diagnostics.NETCore.Client; using Microsoft.Diagnostics.Tracing; using Microsoft.Diagnostics.Tracing.Parsers; using Microsoft.Diagnostics.Tracing.Parsers.Clr; using Microsoft.Diagnostics.Tracing.Session; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.Utils; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.ETW; public sealed class ETWRecordingSession : IDisposable { private static readonly string ProfilerPath = "ProfileExplorerProfiler.dll"; private static readonly string ProfilerGuid = "{805A308B-061C-47F3-9B30-F785C3186E81}"; private TraceEventSession session_; private DiagnosticsClient diagClient_; private ProfilerNamedPipeServer pipeServer_; private ProfileRecordingSessionOptions options_; private ProfileDataProviderOptions providerOptions_; private ProfileLoadProgressHandler progressCallback_; private DateTime lastEventTime_; private string sessionName_; private string profilerPath_; public ETWRecordingSession(ProfileDataProviderOptions providerOptions, string sessionName = null) { Debug.Assert(!RequiresElevation); options_ = providerOptions.RecordingSessionOptions; providerOptions_ = providerOptions; if (options_.RecordPerformanceCounters) { // To record CPU perf. counters, a kernel session is needed. sessionName_ = KernelTraceEventParser.KernelSessionName; } else { sessionName_ = sessionName ?? $"PEX-ETW-{Guid.NewGuid()}"; } } public static bool RequiresElevation => TraceEventSession.IsElevated() != true; public static List BuiltinPerformanceCounters { get { var list = new List(); try { var counters = TraceEventProfileSources.GetInfo(); foreach (var counter in counters) { // Filter out the Timer. if (counter.Value.ID == 0) { continue; } list.Add(new PerformanceCounterConfig(counter.Value.ID, counter.Value.Name, counter.Value.Interval, counter.Value.MinInterval, counter.Value.MaxInterval, true)); } } catch (Exception ex) { Trace.TraceError($"Failed to get CPU perf counters: {ex.Message}"); } return list; } } public static List BuiltinPerformanceMetrics { get { //? TODO: Configurable list var list = new List(); list.Add(new PerformanceMetricConfig("DCacheMiss", "DcacheAccesses", "DcacheMisses", true, "Data cache miss percentage")); list.Add( new PerformanceMetricConfig("ICacheMiss", "ICFetch", "ICMiss", true, "Instruction cache miss percentage")); list.Add(new PerformanceMetricConfig("MispredBr", "BranchInstructions", "BranchMispredictions", true, "Branch misprediction percentage")); list.Add(new PerformanceMetricConfig("CPI", "InstructionRetired", "UnhaltedCoreCycles", false, "Clockticks per Instructions retired rate")); return list; } } public void Dispose() { StopSession(); } public Task StartRecording(ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { int acceptedProcessId = 0; Process profiledProcess = null; WindowsThreadSuspender threadSuspender = null; var sessionStarted = new ManualResetEvent(false); // The entire ETW processing must be done on the same thread. // Start a task that runs the ETW session and captures the events. RawProfileData profile = null; var eventTask = Task.Run(() => { try { if (!CreateSession(cancelableTask)) { return null; } // Start the profiled application. switch (options_.SessionKind) { case ProfileSessionKind.StartProcess: { (profiledProcess, acceptedProcessId) = StartProfiledApplication(); if (profiledProcess == null) { sessionStarted.Set(); // Unblock waiting task below. return null; } // Start task that waits for the process to exit, // which will stop the ETW session. CreateApplicationExitTask(profiledProcess, cancelableTask); // Suspend the application before the session starts, // then resume it once everything is set up. try { threadSuspender = new WindowsThreadSuspender(acceptedProcessId); } catch (Exception ex) { Trace.TraceError( $"Failed to suspend application threads {options_.ApplicationPath}: {ex.Message}\n{ex.StackTrace}"); } break; } case ProfileSessionKind.SystemWide: { // ETW sessions are system-wide by default. break; } case ProfileSessionKind.AttachToProcess: { try { profiledProcess = Process.GetProcessById(acceptedProcessId); acceptedProcessId = options_.TargetProcessId; } catch (Exception ex) { Trace.WriteLine($"Failed to attach to process {options_.TargetProcessId}"); StopSession(); return null; } if (options_.ProfileDotNet && options_.RecordDotNetAssembly) { if (!AttachProfiler(acceptedProcessId)) { StopSession(); return null; } } // Start task that waits for the process to exit, // which will stop the ETW session. //? TODO: Doesns't work for attached process! CreateApplicationExitTask(profiledProcess, cancelableTask); break; } default: { throw new NotImplementedException(); } } var capturedEvents = KernelTraceEventParser.Keywords.ImageLoad | KernelTraceEventParser.Keywords.Process | KernelTraceEventParser.Keywords.Thread | //KernelTraceEventParser.Keywords.ContextSwitch | //KernelTraceEventParser.Keywords.DiskIO | //KernelTraceEventParser.Keywords.DiskFileIO | //KernelTraceEventParser.Keywords.DiskIOInit | //KernelTraceEventParser.Keywords.FileIO | //KernelTraceEventParser.Keywords.FileIOInit | KernelTraceEventParser.Keywords.Profile; if (options_.RecordPerformanceCounters && options_.PerformanceCounters.Count > 0) { // Enable the CPU perf. counters to collect. capturedEvents |= KernelTraceEventParser.Keywords.PMCProfile; EnablePerformanceCounters(); session_.EnableKernelProvider(capturedEvents, capturedEvents); // With stack sampling. } else { session_.EnableKernelProvider(capturedEvents, capturedEvents); // With stack sampling. session_.EnableProvider(SymbolTraceEventParser.ProviderGuid); } if (options_.ProfileDotNet) { session_.EnableProvider( ClrTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)(ClrTraceEventParser.Keywords.Jit | ClrTraceEventParser.Keywords.JittedMethodILToNativeMap | ClrTraceEventParser.Keywords.GC | ClrTraceEventParser.Keywords.Loader)); if (options_.SessionKind == ProfileSessionKind.AttachToProcess) { // Needed when attaching to a running .net app. Trace.WriteLine("Enable ClrRundownTraceEventParser"); session_.EnableProvider( ClrRundownTraceEventParser.ProviderGuid, TraceEventLevel.Verbose, (ulong)(ClrRundownTraceEventParser.Keywords.Jit | ClrRundownTraceEventParser.Keywords.JittedMethodILToNativeMap | ClrRundownTraceEventParser.Keywords.Loader | ClrRundownTraceEventParser.Keywords.StartEnumeration)); } } // Start the ETW session. using var eventProcessor = new ETWEventProcessor(session_.Source, providerOptions_, true, acceptedProcessId, options_.ProfileChildProcesses, options_.ProfileDotNet, pipeServer_); sessionStarted.Set(); progressCallback_ = progressCallback; lastEventTime_ = DateTime.MinValue; return eventProcessor.ProcessEvents(SessionProgressHandler, cancelableTask); } catch (Exception ex) { Trace.TraceError($"Failed ETW event capture: {ex.Message}\n{ex.StackTrace}"); threadSuspender?.Dispose(); // This resume all profiled app threads. sessionStarted.Set(); // Unblock waiting task below. return null; } finally { StopSession(); profiledProcess?.Dispose(); profiledProcess = null; } }); // Start a task that waits for the ETW session task to complete. return Task.Run(() => { try { // Wait until the ETW session task starts. while (!cancelableTask.IsCanceled && !sessionStarted.WaitOne(100)) { } // Resume all profiled app threads and start waiting for it to close, // then wait for ETW session to complete. threadSuspender?.Dispose(); profile = eventTask.Result; } catch (Exception ex) { Trace.TraceError($"Failed ETW event capture: {ex.Message}\n{ex.StackTrace}"); threadSuspender?.Dispose(); // This resume all profiled app threads. } finally { StopSession(); profiledProcess?.Dispose(); profiledProcess = null; } return profile; }); } private void SessionProgressHandler(ProfileLoadProgress info) { // Record the last time samples were processed, this is used in // CreateApplicationExitTask to keep the ETW session running after the app exits, // but ETW events for the app are still incoming. lastEventTime_ = DateTime.UtcNow; progressCallback_?.Invoke(info); } private void EnablePerformanceCounters() { var enabledCounters = options_.EnabledPerformanceCounters; if (enabledCounters.Count == 0) { return; } int[] counterIds = new int[enabledCounters.Count]; int[] frequencyCounts = new int[enabledCounters.Count]; int index = 0; foreach (var counter in enabledCounters) { counterIds[index] = counter.Id; frequencyCounts[index] = counter.Interval; index++; Trace.WriteLine($"Enabling counter {counter.Name}"); } TraceEventProfileSources.Set(counterIds, frequencyCounts); } private bool CreateSession(CancelableTask cancelableTask) { if (options_.ProfileDotNet) { profilerPath_ = Path.Combine(AppContext.BaseDirectory, ProfilerPath); if (options_.RecordDotNetAssembly) { try { Trace.WriteLine("Start .NET profiler named pipe server"); pipeServer_ = new ProfilerNamedPipeServer(); } catch (Exception ex) { Trace.TraceError($"Failed to start named pipe: {ex.Message}\n{ex.StackTrace}"); StopSession(); return false; } } } // Start a new in-memory session. try { Debug.Assert(session_ == null); session_ = new TraceEventSession(sessionName_); session_.BufferSizeMB = Math.Max(session_.BufferSizeMB, 128); session_.CpuSampleIntervalMSec = 1000.0f / options_.SamplingFrequency; Trace.WriteLine("Started ETW session:"); Trace.WriteLine($" Buffer size: {session_.BufferSizeMB} MB"); Trace.WriteLine($" Sampling freq: {session_.CpuSampleIntervalMSec} ms / {options_.SamplingFrequency}"); Trace.Flush(); return true; } catch (Exception ex) { Trace.TraceError($"Failed to start ETW capture session: {ex.Message}\n{ex.StackTrace}"); StopSession(); return false; } } private (Process, int) StartProfiledApplication() { try { var procInfo = new ProcessStartInfo(options_.ApplicationPath) { Arguments = options_.ApplicationArguments, WorkingDirectory = options_.HasWorkingDirectory ? options_.WorkingDirectory : Utilities.Utils.TryGetDirectoryName(options_.ApplicationPath), //? The Process object must have the UseShellExecute property set to false in order to use environment variables //UseShellExecute = true, Verb = "runas" //RedirectStandardError = false, //RedirectStandardOutput = true }; if (options_.ProfileDotNet && options_.RecordDotNetAssembly) { if (!SetupStartupDotNetProfiler(procInfo)) { Trace.TraceError("Failed to setup managed profiler"); return (null, 0); } } if (options_.EnableEnvironmentVars) { foreach (var pair in options_.EnvironmentVariables) { procInfo.EnvironmentVariables[pair.Value] = pair.Variable; } } var process = new Process {StartInfo = procInfo, EnableRaisingEvents = true}; process.Start(); Trace.WriteLine($"Started process {options_.ApplicationPath}"); return (process, process.Id); } catch (Exception ex) { Trace.TraceError( $"Failed to start profiled application {options_.ApplicationPath}: {ex.Message}\n{ex.StackTrace}"); } return (null, 0); } private bool SetupStartupDotNetProfiler(ProcessStartInfo procInfo) { procInfo.EnvironmentVariables["CORECLR_ENABLE_PROFILING"] = "1"; procInfo.EnvironmentVariables["CORECLR_PROFILER"] = ProfilerGuid; procInfo.EnvironmentVariables["CORECLR_PROFILER_PATH"] = profilerPath_; Trace.WriteLine($"Using managed profiler {profilerPath_}"); return true; } private bool AttachProfiler(int processId) { try { Trace.WriteLine($"Attaching managed profiler to proc {processId}: {profilerPath_}"); byte[] profilerArgs = Array.Empty(); diagClient_ = new DiagnosticsClient(processId); diagClient_.AttachProfiler(TimeSpan.FromSeconds(10), Guid.Parse(ProfilerGuid), profilerPath_, profilerArgs); } catch (Exception ex) { Trace.TraceError($"Failed to attach profiler to process {processId}: {ex.Message}"); return false; } return true; } private void DetachProfiler() { if (pipeServer_ == null) { return; } // Request .NET profiler detach. pipeServer_.EndSession(); pipeServer_.Stop(); pipeServer_ = null; diagClient_ = null; } private void CreateApplicationExitTask(Process process, CancelableTask task) { Task.Run(() => { try { while (!task.IsCanceled && !task.IsCompleted) { if (process.WaitForExit(100)) { break; } } // Once the app exits, wait until no more ETW events are arriving // to be processed, then stop the session. int waitCount = 0; while (!task.IsCanceled) { // If no events arrived yet at all, wait a while longer. if (lastEventTime_ == DateTime.MinValue) { Thread.Sleep(500); if (waitCount++ > 10) break; } else { var timeSinceLastSample = DateTime.UtcNow - lastEventTime_; if (timeSinceLastSample.TotalMilliseconds > 1000) { break; } Thread.Sleep(100); } } StopSession(); } catch (Exception ex) { Trace.TraceError( $"Failed to wait for profiled application exit {options_.ApplicationPath}: {ex.Message}\n{ex.StackTrace}"); } }); } private void StopSession() { if (session_ != null) { try { session_.Stop(); session_.Dispose(); // Stop profiler named pipe after no more write requests are made. DetachProfiler(); } catch (Exception ex) { Trace.TraceError($"Failed to stop ETW session: {ex.Message}"); } session_ = null; } } } ================================================ FILE: src/ProfileExplorerCore/Profile/ETW/ProfilerNamedPipeServer.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Threading; using ProfileExplorer.Core.Profile.Utils; namespace ProfileExplorer.Core.Profile.ETW; public class ProfilerNamedPipeServer : IDisposable { public delegate void FunctionCallTargetsReceivedDelegate(long functionId, int rejitId, int processId, long address, string name); public delegate void FunctionCodeReceivedDelegate(long functionId, int rejitId, int processId, long address, int codeSize, byte[] codeBytes); public const string PipeName = "PEXProfilerPipe"; private NamedPipeServer instance_; public ProfilerNamedPipeServer() { instance_ = new NamedPipeServer(PipeName); } public void Dispose() { if (instance_ != null) { Stop(); } } public event FunctionCodeReceivedDelegate FunctionCodeReceived; public event FunctionCallTargetsReceivedDelegate FunctionCallTargetsReceived; public bool StartReceiving(CancellationToken cancellationToken) { try { Trace.WriteLine("Start pipe reading thread"); instance_.ReceiveMessages((header, body) => { if (cancellationToken.IsCancellationRequested) { Trace.WriteLine($"Canceled {Environment.CurrentManagedThreadId}"); return; } switch ((MessageKind)header.Kind) { case MessageKind.FunctionCode: { var message = MemoryMarshal.Cast(body)[0]; byte[] code = body.AsSpan().Slice(28, message.CodeSize).ToArray(); FunctionCodeReceived?.Invoke(message.FunctionId, message.ReJITId, message.ProcessId, message.Address, message.CodeSize, code); break; } case MessageKind.FunctionCallTarget: { var message = MemoryMarshal.Cast(body)[0]; var nameBytes = body.AsSpan().Slice(28, message.NameLength); // Don't include the null terminator. if (nameBytes[^1] == 0) { nameBytes = nameBytes.Slice(0, nameBytes.Length - 1); } string name = Encoding.UTF8.GetString(nameBytes); FunctionCallTargetsReceived?.Invoke(message.FunctionId, message.ReJITId, message.ProcessId, message.Address, name); break; } } }, cancellationToken); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to receive messages: {ex}"); return false; } } public bool EndSession() { try { instance_.SendMessage((int)MessageKind.EndSession); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to send message: {ex}"); return false; } } public bool RequestFunctionCode(long address, long functionId, int rejitId, int processId) { try { var message = new RequestFunctionCodeMessage { FunctionId = functionId, ReJITId = rejitId, Address = address, ProcessId = processId }; instance_.SendMessage((int)MessageKind.RequestFunctionCode, message); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to send message: {ex}"); return false; } } public void Stop() { instance_.Dispose(); instance_ = null; } private enum MessageKind { StartSession, EndSession, FunctionCode, FunctionCallTarget, RequestFunctionCode } [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct FunctionCodeMessage { public long FunctionId; // 0 public long Address; // 8 public int ReJITId; // 16 public int ProcessId; // 20 public int CodeSize; // 24 // Code bytes start here at offset 28. } [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct FunctionCallTargetMessage { public long FunctionId; // 0 public long Address; // 8 public int ReJITId; // 16 public int ProcessId; // 20 public int NameLength; // 20 // UTF-8 name bytes start here at offset 28. } [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct RequestFunctionCodeMessage { public long FunctionId; // 0 public long Address; // 8 public int ReJITId; // 16 public int ProcessId; // 20 } } ================================================ FILE: src/ProfileExplorerCore/Profile/Processing/CallTreeProcessor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Threading.Tasks; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.Core.Profile.Processing; public sealed class CallTreeProcessor : ProfileSampleProcessor { private List chunks_; private int maxChunks_; public CallTreeProcessor(int maxChunks) { chunks_ = new List(); maxChunks_ = maxChunks; } public ProfileCallTree CallTree { get; set; } = new(); public static ProfileCallTree Compute(ProfileData profile, ProfileSampleFilter filter, int maxChunks = int.MaxValue) { var funcProcessor = new CallTreeProcessor(maxChunks); funcProcessor.ProcessSampleChunk(profile, filter, maxChunks); return funcProcessor.CallTree; } protected override void ProcessSample(ref ProfileSample sample, ResolvedProfileStack stack, int sampleIndex, object chunkData) { var callTree = (ProfileCallTree)chunkData; callTree.UpdateCallTree(ref sample, stack); } protected override object InitializeChunk(int k, int samplesPerChunk) { // Partition the node IDs into namespaces based on the chunk // of samples they are created from - this ensures that each // call tree will usue unique node IDs when compared to other call trees. int startNodeId = k * (int.MaxValue / (maxChunks_ + 1)); var chunk = new ProfileCallTree(startNodeId); lock (chunks_) { chunks_.Add(chunk); } return chunk; } protected override void Complete() { lock (chunks_) { // Multi-threaded merging of partial call trees. while (chunks_.Count > 1) { int step = Math.Min(chunks_.Count, 2); // Trace.WriteLine($"=> Merging {chunks_.Count} chunks, step {step}"); var tasks = new Task[chunks_.Count / step]; var newChunks = new List(chunks_.Count / step); for (int i = 0; i < chunks_.Count / step; i++) { int iCopy = i; newChunks.Add(chunks_[iCopy * step]); tasks[i] = Task.Run(() => { for (int k = 1; k < step; k++) { chunks_[iCopy * step].MergeWith(chunks_[iCopy * step + k]); } }); } Task.WaitAll(tasks); // Handle any chunks that were not paired during the parallel phase. // With a step of 2 this can happen only in the first round. if (chunks_.Count % step != 0) { int lastHandledIndex = chunks_.Count / step * step; for (int i = lastHandledIndex; i < chunks_.Count; i++) { chunks_[0].MergeWith(chunks_[i]); } } chunks_ = newChunks; } CallTree = chunks_[0]; #if DEBUG CallTree.VerifyCycles(); #endif } } } ================================================ FILE: src/ProfileExplorerCore/Profile/Processing/FunctionProfileProcessor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Processing; public sealed class FunctionProfileProcessor : ProfileSampleProcessor { private ProfileSampleFilter filter_; private List> filterStackFuncts_; private List chunks_; private FunctionProfileProcessor(ProfileSampleFilter filter) { filter_ = filter; chunks_ = new List(); if (filter_ != null && filter_.FunctionInstances is {Count: > 0}) { // Compute once the list of functions on the path // from call tree root to the function instance node. filterStackFuncts_ = new List>(); foreach (var instance in filter_.FunctionInstances) { if (instance is ProfileCallTreeGroupNode groupNode) { foreach (var node in groupNode.Nodes) { AddInstanceFilter(node); } } else { AddInstanceFilter(instance); } } } } public ProfileData Profile { get; } = new(); private void AddInstanceFilter(ProfileCallTreeNode node) { var stackFuncts = new List(); while (node != null) { stackFuncts.Add(node.Function); node = node.Caller; } stackFuncts.Reverse(); filterStackFuncts_.Add(stackFuncts); } public static ProfileData Compute(ProfileData profile, ProfileSampleFilter filter, int maxChunks = int.MaxValue) { var funcProcessor = new FunctionProfileProcessor(filter); funcProcessor.ProcessSampleChunk(profile, filter, maxChunks); return funcProcessor.Profile; } protected override object InitializeChunk(int k, int samplesPerChunk) { var chunk = new ChunkData(); lock (chunks_) { chunks_.Add(chunk); } return chunk; } protected override void ProcessSample(ref ProfileSample sample, ResolvedProfileStack stack, int sampleIndex, object chunkData) { if (filterStackFuncts_ != null) { // Filtering of functions to a single instance is enabled, // accept only samples that have the instance path nodes // as a prefix of the call stack, this accounts for total weight. if (stack.FrameCount < filterStackFuncts_.Count) { return; } bool foundMatch = false; foreach (var stackFuncts in filterStackFuncts_) { // Check if instance path nodes are a prefix of the call stack. if (stack.FrameCount < stackFuncts.Count) { continue; } bool isMatch = true; for (int i = 0; i < stackFuncts.Count; i++) { if (stackFuncts[i] != stack.StackFrames[stack.FrameCount - i - 1].FrameDetails.Function) { isMatch = false; break; } } if (isMatch) { foundMatch = true; break; } } if (!foundMatch) { return; } } var data = (ChunkData)chunkData; data.TotalWeight += sample.Weight; data.ProfileWeight += sample.Weight; bool isTopFrame = true; data.StackModules.Clear(); data.StackFunctions.Clear(); foreach (var resolvedFrame in stack.StackFrames) { if (resolvedFrame.IsUnknown) { continue; } var frameDetails = resolvedFrame.FrameDetails; if (isTopFrame && data.StackModules.Add(frameDetails.Image.Id)) { data.ModuleWeights.AccumulateValue(frameDetails.Image.Id, sample.Weight); } long funcRva = frameDetails.DebugInfo.RVA; long frameRva = resolvedFrame.FrameRVA; var textFunction = frameDetails.Function; ref var funcProfile = ref CollectionsMarshal.GetValueRefOrAddDefault(data.FunctionProfiles, frameDetails.Function, out bool exists); if (!exists) { funcProfile = new FunctionProfileData(frameDetails.DebugInfo); } long offset = frameRva - funcRva; // Don't count the inclusive time for recursive functions multiple times. if (data.StackFunctions.Add(textFunction)) { funcProfile.AddInstructionSample(offset, sample.Weight); funcProfile.Weight += sample.Weight; // Set sample range covered by function. funcProfile.SampleStartIndex = Math.Min(funcProfile.SampleStartIndex, sampleIndex); funcProfile.SampleEndIndex = Math.Max(funcProfile.SampleEndIndex, sampleIndex); } // Count the exclusive time for the top frame function. if (isTopFrame) { funcProfile.ExclusiveWeight += sample.Weight; } isTopFrame = false; } } protected override void CompleteChunk(int k, object chunkData) { var data = (ChunkData)chunkData; lock (Profile) { Profile.TotalWeight += data.TotalWeight; Profile.ProfileWeight += data.ProfileWeight; foreach ((int moduleId, var weight) in data.ModuleWeights) { Profile.AddModuleSample(moduleId, weight); } } } protected override void Complete() { lock (chunks_) { while (chunks_.Count > 1) { int step = Math.Min(chunks_.Count, 2); // Trace.WriteLine($"=> Merging {chunks_.Count} chunks, step {step}"); var tasks = new Task[chunks_.Count / step]; var newChunks = new List(chunks_.Count / step); for (int i = 0; i < chunks_.Count / step; i++) { int iCopy = i; newChunks.Add(chunks_[iCopy * step]); tasks[i] = Task.Run(() => { for (int k = 1; k < step; k++) { var destChunk = chunks_[iCopy * step]; var sourceChunk = chunks_[iCopy * step + k]; MergeChuncks(destChunk, sourceChunk); } }); } Task.WaitAll(tasks); // Handle any chuncks that were not paired during the parallel phase. // With a step of 2 this can happen only in the first round. if (chunks_.Count % step != 0) { int lastHandledIndex = chunks_.Count / step * step; for (int i = lastHandledIndex; i < chunks_.Count; i++) { MergeChuncks(chunks_[0], chunks_[i]); } } chunks_ = newChunks; } lock (Profile) { Profile.FunctionProfiles = chunks_[0].FunctionProfiles; } } } private static void MergeChuncks(ChunkData destChunk, ChunkData sourceChunk) { foreach (var pair in sourceChunk.FunctionProfiles) { ref var existingValue = ref CollectionsMarshal.GetValueRefOrAddDefault(destChunk.FunctionProfiles, pair.Key, out bool exists); if (exists) { existingValue.MergeWith(pair.Value); } else { // Copy over func. profile if missing. existingValue = pair.Value; } } } private class ChunkData { public HashSet StackModules = new(); public HashSet StackFunctions = new(); public Dictionary ModuleWeights = new(); public Dictionary FunctionProfiles = new(); public TimeSpan TotalWeight = TimeSpan.Zero; public TimeSpan ProfileWeight = TimeSpan.Zero; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Processing/FunctionSamplesProcessor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Diagnostics; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.Timeline; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Processing; public sealed class FunctionSamplesProcessor : ProfileSampleProcessor { private const int AllThreadsKey = -1; private Dictionary> threadListMap_; private List chunks_; private ProfileCallTreeNode node_; public FunctionSamplesProcessor(ProfileCallTreeNode node) { node_ = node; chunks_ = new List(); } public static Dictionary> Compute(ProfileCallTreeNode node, ProfileData profile, ProfileSampleFilter filter, int maxChunks = int.MaxValue) { // Compute the list of samples associated with the function, // for each thread it was executed on. var funcProcessor = new FunctionSamplesProcessor(node); funcProcessor.ProcessSampleChunk(profile, filter, maxChunks); return funcProcessor.threadListMap_; } protected override object InitializeChunk(int k, int samplesPerChunk) { var chunk = new ChunkData(); lock (chunks_) { chunks_.Add(chunk); } return chunk; } protected override void ProcessSample(ref ProfileSample sample, ResolvedProfileStack stack, int sampleIndex, object chunkData) { var data = (ChunkData)chunkData; var currentNode = node_; bool match = false; for (int k = 0; k < stack.StackFrames.Count; k++) { if (currentNode == null || currentNode.IsGroup) { // Mismatch along the call path leading to the function. match = false; break; } var stackFrame = stack.StackFrames[k]; if (stackFrame.IsUnknown) { continue; } if (stackFrame.FrameDetails.Function.Equals(currentNode.Function)) { // Continue checking if the callers show up on the stack trace // to make the search context-sensitive. match = true; currentNode = currentNode.Caller; } else if (match) { // Mismatch along the call path leading to the function. match = false; break; } } if (match) { var threadList = data.ThreadListMap.GetOrAddValue(stack.Context.ThreadId); var index = new SampleIndex(sampleIndex, sample.Time); threadList.Add(index); data.AllThreadsList.Add(index); } } protected override void Complete() { lock (chunks_) { // Compute the sample list size for each thread // across all chunks to pre-allocate memory. var countMap = new Dictionary(); var chunkThreadListMap = new Dictionary>>(); foreach (var chunk in chunks_) { foreach (var pair in chunk.ThreadListMap) { countMap.AccumulateValue(pair.Key, pair.Value.Count); if (pair.Value.Count > 0) { chunkThreadListMap.GetOrAddValue(pair.Key).Add(pair.Value); } } } // Pre-allocate memory for the merged per-thread sample lists. threadListMap_ = new Dictionary>(countMap.Count); foreach (var pair in countMap) { threadListMap_[pair.Key] = new List(pair.Value); } // The per-thread sample lists are already sorted, // now put them in the correct order across all chunks. foreach (var chunkList in chunkThreadListMap.Values) { chunkList.Sort((a, b) => a[0].Index.CompareTo(b[0].Index)); } var map = new Dictionary(); // Merge the per-thread sample lists. foreach (var pair in chunkThreadListMap) { var threadList = threadListMap_[pair.Key]; var chunkLists = pair.Value; foreach (var list in chunkLists) { threadList.AddRange(list); } for (int i = 1; i < threadList.Count; i++) { int dist = threadList[i].Index - threadList[i - 1].Index; map.AccumulateValue(dist, 1); } #if DEBUG // Validate sample ordering. for (int i = 1; i < chunkLists.Count; i++) { Debug.Assert(chunkLists[i][0].Index > chunkLists[i - 1][^1].Index); } #endif } } } private class ChunkData { public List AllThreadsList; public Dictionary> ThreadListMap; public ChunkData() { AllThreadsList = new List(); ThreadListMap = new Dictionary>(); ThreadListMap[AllThreadsKey] = AllThreadsList; } } } ================================================ FILE: src/ProfileExplorerCore/Profile/Processing/FunctionsForSamplesProcessor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.Core.Profile.Processing; public sealed class FunctionsForSamplesProcessor : ProfileSampleProcessor { private HashSet functionSet_; private List chunks_; public FunctionsForSamplesProcessor() { chunks_ = new List(); } public static HashSet Compute(ProfileSampleFilter filter, ProfileData profile, int maxChunks = int.MaxValue) { // Compute the list of functions covered by the samples // on the specified thread or all threads. var funcProcessor = new FunctionsForSamplesProcessor(); funcProcessor.ProcessSampleChunk(profile, filter, maxChunks); return funcProcessor.functionSet_; } protected override object InitializeChunk(int k, int samplesPerChunk) { var chunk = new ChunkData(); lock (chunks_) { chunks_.Add(chunk); } return chunk; } protected override void ProcessSample(ref ProfileSample sample, ResolvedProfileStack stack, int sampleIndex, object chunkData) { var data = (ChunkData)chunkData; foreach (var stackFrame in stack.StackFrames) { if (!stackFrame.IsUnknown) { data.functionSet_.Add(stackFrame.FrameDetails.Function); } } } protected override void Complete() { // Compute the sample list size for each thread // across all chunks to pre-allocate memory. int count = 0; foreach (var chunk in chunks_) { count += chunk.functionSet_.Count; } functionSet_ = new HashSet(count); // Merge the per-thread sample lists. foreach (var chunk in chunks_) { foreach (var func in chunk.functionSet_) { functionSet_.Add(func); } } } private class ChunkData { public HashSet functionSet_ = new(1024); } } ================================================ FILE: src/ProfileExplorerCore/Profile/Processing/ProfileSampleFilter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Threading.Tasks; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Timeline; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Processing; public class ProfileSampleFilter : IEquatable { public ProfileSampleFilter() { } public ProfileSampleFilter(ProfileCallTreeNode instance) { AddInstance(instance); } public ProfileSampleFilter(int threadId) { AddThread(threadId); } public SampleTimeRangeInfo TimeRange { get; set; } public List ThreadIds { get; set; } public List FunctionInstances { get; set; } public bool HasThreadFilter => ThreadIds is {Count: > 0}; public bool HasInstanceFilter => FunctionInstances is {Count: > 0}; public bool IncludesAll => TimeRange == null && !HasThreadFilter && !HasInstanceFilter; public bool Equals(ProfileSampleFilter other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(TimeRange, other.TimeRange) && ThreadIds.AreEqual(other.ThreadIds) && FunctionInstances.AreEqual(other.FunctionInstances); } public ProfileSampleFilter AddInstance(ProfileCallTreeNode instance) { FunctionInstances ??= new List(); FunctionInstances.Add(instance); return this; } public bool IncludesInstance(ProfileCallTreeNode node) { return HasInstanceFilter && FunctionInstances.Contains(node); } public void RemoveInstance(ProfileCallTreeNode instance) { FunctionInstances?.Remove(instance); } public void ClearInstances() { FunctionInstances?.Clear(); } public ProfileSampleFilter AddThread(int threadId) { ThreadIds ??= new List(); ThreadIds.Add(threadId); return this; } public bool IncludesThread(int threadId) { return HasThreadFilter && ThreadIds.Contains(threadId); } public void RemoveThread(int threadId) { ThreadIds?.Remove(threadId); } public void ClearThreads() { ThreadIds?.Clear(); } public ProfileSampleFilter Clone() { var clone = new ProfileSampleFilter(); clone.TimeRange = TimeRange; clone.ThreadIds = ThreadIds.CloneList(); clone.FunctionInstances = FunctionInstances.CloneList(); return clone; } public ProfileSampleFilter CloneForCallTarget(IRTextFunction targetFunc) { var targetFilter = Clone(); if (HasInstanceFilter) { targetFilter.ClearInstances(); foreach (var instance in FunctionInstances) { // Try to add the instance node that is a child // of the current instance in the profile filter. var targetInstance = instance.FindChildNode(targetFunc); if (targetInstance != null) { targetFilter.AddInstance(targetInstance); } } } return targetFilter; } public static bool operator ==(ProfileSampleFilter left, ProfileSampleFilter right) { return Equals(left, right); } public static bool operator !=(ProfileSampleFilter left, ProfileSampleFilter right) { return !Equals(left, right); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((ProfileSampleFilter)obj); } public override int GetHashCode() { return HashCode.Combine(TimeRange, ThreadIds, FunctionInstances); } public override string ToString() { string text = $"TimeRange: {TimeRange}, HasInstanceFilter: {HasInstanceFilter}, HasThreadFilter: {HasThreadFilter}"; if (HasInstanceFilter) { foreach (var item in FunctionInstances) { text += $"\n - instance: {item.FunctionName}"; } } if (HasThreadFilter) { foreach (int item in ThreadIds) { text += $"\n - thread: {item}"; } } return text; } } public class ProfileFilterState { public ProfileFilterState(ProfileSampleFilter filter = null) { Filter = filter ?? new ProfileSampleFilter(); } public bool HasAnyFilter => HasThreadFilter || HasFilter; public ProfileSampleFilter Filter { get; set; } public bool HasFilter { get; set; } public TimeSpan FilteredTime { get; set; } public bool HasThreadFilter { get; set; } public string ThreadFilterText { get; set; } public Func RemoveThreadFilter { get; set; } public Func RemoveTimeRangeFilter { get; set; } public Func RemoveAllFilters { get; set; } } ================================================ FILE: src/ProfileExplorerCore/Profile/Processing/ProfileSampleProcessor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Threading.Tasks; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Profile.Processing; // Provides support for running an analysis over samples, with filtering, // in parallel, by splitting the samples into multiple chunks, each // processed on a different thread. public abstract class ProfileSampleProcessor { protected virtual int DefaultThreadCount => CoreSettingsProvider.GeneralSettings.CurrentCpuCoreLimit; protected virtual object InitializeChunk(int k, int samplesPerChunk) { return null; } protected abstract void ProcessSample(ref ProfileSample sample, ResolvedProfileStack stack, int sampleIndex, object chunkData); protected virtual void CompleteChunk(int k, object chunkData) { } protected virtual void Complete() { } protected void ProcessSampleChunk(ProfileData profile, ProfileSampleFilter filter, int maxChunks = int.MaxValue) { int sampleStartIndex = filter.TimeRange?.StartSampleIndex ?? 0; int sampleEndIndex = filter.TimeRange?.EndSampleIndex ?? profile.Samples.Count; //Trace.WriteLine($"ProfileSampleProcessor: Sample range: {sampleStartIndex} - {sampleEndIndex}"); int sampleCount = sampleEndIndex - sampleStartIndex; int chunks = Math.Min(maxChunks, DefaultThreadCount); //Trace.WriteLine($"ProfileSampleProcessor: Using {chunks} chunks"); //var sw = Stopwatch.StartNew(); int chunkSize = sampleCount / chunks; var taskScheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, chunks); var taskFactory = new TaskFactory(taskScheduler.ConcurrentScheduler); var tasks = new List(); for (int k = 0; k < chunks; k++) { int start = Math.Min(sampleStartIndex + k * chunkSize, sampleEndIndex); int end = k == chunks - 1 ? sampleEndIndex : Math.Min(sampleStartIndex + (k + 1) * chunkSize, sampleEndIndex); // If a single thread is selected, only process the samples for that thread // by going through the thread sample ranges. var ranges = profile.ThreadSampleRanges.Ranges[-1]; if (filter.HasThreadFilter && filter.ThreadIds.Count == 1) { ranges = profile.ThreadSampleRanges.Ranges[filter.ThreadIds[0]]; // Trace.WriteLine($"Filter single thread with {ranges.Count} ranges"); } int kCopy = k; // Pass value copy. tasks.Add(taskFactory.StartNew(() => { int samplesPerChunk = (int)Math.Ceiling((double)sampleCount / chunks); object chunkData = InitializeChunk(kCopy, samplesPerChunk); // Find the ranges of samples that overlap with the filter time range. int startRangeIndex = 0; int endRangeIndex = ranges.Count - 1; while (startRangeIndex < ranges.Count && ranges[startRangeIndex].EndIndex < start) { startRangeIndex++; } while (endRangeIndex > 0 && ranges[endRangeIndex].StartIndex > end) { endRangeIndex--; } // Walk each sample in the range and update the function profile. bool hasThreadFilter = filter.HasThreadFilter; var sampleSpan = CollectionsMarshal.AsSpan(profile.Samples); for (int k = startRangeIndex; k <= endRangeIndex; k++) { var range = ranges[k]; int startIndex = Math.Max(start, range.StartIndex); int endIndex = Math.Min(end, range.EndIndex); for (int i = startIndex; i < endIndex; i++) { ref var stack = ref sampleSpan[i].Stack; if (hasThreadFilter && !filter.ThreadIds.Contains(stack.Context.ThreadId)) { continue; } ref var sample = ref sampleSpan[i].Sample; ProcessSample(ref sample, stack, i, chunkData); } } CompleteChunk(kCopy, chunkData); })); } Task.WhenAll(tasks.ToArray()).Wait(); Complete(); //sw.Stop(); //Trace.WriteLine($"ProfileSampleProcessor: Time {sw.ElapsedMilliseconds} ms"); //Trace.Flush(); } } ================================================ FILE: src/ProfileExplorerCore/Profile/Timeline/ActivityView.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace ProfileExplorer.Core.Profile.Timeline; public record SampleTimeRangeInfo( TimeSpan StartTime, TimeSpan EndTime, int StartSampleIndex, int EndSampleIndex, int ThreadId); public record struct SampleTimePointInfo(TimeSpan Time, int SampleIndex, int ThreadId); //? TODO: Use SampleIndex in SampleTimePointInfo/Range public record struct SampleIndex(int Index, TimeSpan Time); ================================================ FILE: src/ProfileExplorerCore/Profile/Utils/DummySectionLoader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; namespace ProfileExplorer.Core.Profile.Utils; public sealed class DummySectionLoader : IRTextSectionLoader { public async override Task LoadDocument(ProgressInfoHandler progressHandler) { return null; } public override string GetDocumentOutputText() { return ""; } public override byte[] GetDocumentTextBytes() { return null; } public override ParsedIRTextSection LoadSection(IRTextSection section) { return null; } public override string GetSectionText(IRTextSection section) { return ""; } public override ReadOnlyMemory GetSectionTextSpan(IRTextSection section) { return ReadOnlyMemory.Empty; } public override string GetSectionOutputText(IRPassOutput output) { return ""; } public override ReadOnlyMemory GetSectionPassOutputTextSpan(IRPassOutput output) { return ReadOnlyMemory.Empty; } public override List GetSectionPassOutputTextLines(IRPassOutput output) { return new List(); } public override string GetRawSectionText(IRTextSection section) { return ""; } public override string GetRawSectionPassOutput(IRPassOutput output) { return ""; } public override ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section) { return ReadOnlyMemory.Empty; } public override ReadOnlyMemory GetRawSectionPassOutputSpan(IRPassOutput output) { return ReadOnlyMemory.Empty; } protected override void Dispose(bool disposing) { } } ================================================ FILE: src/ProfileExplorerCore/Profile/Utils/NamedPipeServer.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Runtime.InteropServices; using System.Security.AccessControl; using System.Security.Principal; using System.Threading; namespace ProfileExplorer.Core.Profile.Utils; public class NamedPipeServer : IDisposable { public delegate void MessageReceivedDelegate(PipeMessageHeader messageHeader, byte[] messageBody); private static readonly int HeaderSize = Marshal.SizeOf(); private NamedPipeServerStream pipeStream_; private BinaryReader reader_; private BinaryWriter writer_; private bool connected_; private bool connectionTimeout_; public NamedPipeServer(string pipeName) { // Allow non-admins to connect to the pipe. var securityIdentifier = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null); var pipeSecurity = new PipeSecurity(); pipeSecurity.AddAccessRule(new PipeAccessRule(securityIdentifier, PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow)); pipeStream_ = NamedPipeServerStreamAcl.Create(pipeName, PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 0, 0, pipeSecurity); } public void Dispose() { if (connected_) { reader_?.Dispose(); writer_?.Dispose(); if (pipeStream_.IsConnected) { pipeStream_.Disconnect(); } } pipeStream_.Dispose(); } public void ReceiveMessages(MessageReceivedDelegate action, CancellationToken cancellationToken) { if (!Connect()) { throw new Exception("Failed to connect to pipe"); } byte[] buffer = new byte[HeaderSize]; while (pipeStream_.IsConnected && !cancellationToken.IsCancellationRequested) { int bytesRead = reader_.Read(buffer); if (bytesRead == 0) { break; } if (bytesRead != HeaderSize) { throw new Exception($"Invalid message header, read {bytesRead} vs expected {HeaderSize}"); } var header = MemoryMarshal.Cast(buffer)[0]; byte[] bodyBuffer = null; if (header.Size > HeaderSize) { int messageSize = header.Size - HeaderSize; bodyBuffer = new byte[messageSize]; bytesRead = reader_.Read(bodyBuffer); if (bytesRead != messageSize) { throw new Exception($"Invalid message body, read {bytesRead} vs expected {messageSize}"); } } action(header, bodyBuffer); } } public void SendMessage(int kind) { if (!Connect()) { throw new Exception("Failed to connect to pipe"); } SendMessageHeader(kind, 0); } public void SendMessage(int kind, T data) where T : struct { if (!Connect()) { throw new Exception("Failed to connect to pipe"); } int dataSize = Marshal.SizeOf(); SendMessageHeader(kind, dataSize); if (dataSize > 0) { var bodySpan = MemoryMarshal.Cast(MemoryMarshal.CreateSpan(ref data, 1)); writer_.Write(bodySpan); } } public void Flush() { writer_.Flush(); } private void SendMessageHeader(int kind, int bodySize) { var header = new PipeMessageHeader {Kind = kind, Size = HeaderSize + bodySize}; var headerSpan = MemoryMarshal.Cast(MemoryMarshal.CreateSpan(ref header, 1)); writer_.Write(headerSpan); } private bool Connect(int timeoutMs = 10000) { if (connected_) { return true; } if (connectionTimeout_) { return false; // Failed to connect previously, don't try again. } lock (this) { if (connected_) { return true; } try { // Wait for a connection for a certain amount of time. var result = pipeStream_.BeginWaitForConnection(e => { }, null); if (result.AsyncWaitHandle.WaitOne(timeoutMs)) { Trace.WriteLine("Connected to pipe"); pipeStream_.EndWaitForConnection(result); reader_ = new BinaryReader(pipeStream_); writer_ = new BinaryWriter(pipeStream_); connected_ = true; } else { Trace.WriteLine("Pipe connection timeout"); connected_ = false; connectionTimeout_ = true; } } catch (Exception ex) { Trace.WriteLine($"Failed to connect to pipe: {ex}"); connected_ = false; } } return connected_; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct PipeMessageHeader { public int Kind; public int Size; // sizeof(PipeMessageHeader) + additional data public override string ToString() { return $"Message Kind: {Kind}, Size: {Size}"; } } } ================================================ FILE: src/ProfileExplorerCore/Profile/Utils/ThreadSuspender.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.ConstrainedExecution; using System.Runtime.InteropServices; using Microsoft.Win32.SafeHandles; namespace ProfileExplorer.Core.Profile.Utils; // Copied from ClrMD. class WindowsThreadSuspender : CriticalFinalizerObject, IDisposable { private readonly object _sync = new(); private readonly int _pid; private volatile int[] _suspendedThreads; public WindowsThreadSuspender(int pid) { _pid = pid; _suspendedThreads = SuspendThreads(); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~WindowsThreadSuspender() { Dispose(false); } private int[] SuspendThreads() { bool permissionFailure = false; var suspendedThreads = new HashSet(); // A thread may create more threads while we are in the process of walking the list. We will keep looping through // the thread list over and over until we find that we haven't found any new threads to suspend. try { int originalCount; do { originalCount = suspendedThreads.Count; Process process; try { process = Process.GetProcessById(_pid); } catch (ArgumentException e) { throw new InvalidOperationException($"Unable to inspect process {_pid:x}.", e); } foreach (ProcessThread thread in process.Threads) { if (thread != null) { if (suspendedThreads.Contains(thread.Id)) continue; using var threadHandle = Interop.OpenThread(Interop.ThreadAccess.SUSPEND_RESUME, false, (uint)thread.Id); if (threadHandle.IsInvalid || Interop.SuspendThread(threadHandle.DangerousGetHandle()) == -1) { permissionFailure = true; continue; } suspendedThreads.Add(thread.Id); } } } while (originalCount != suspendedThreads.Count); // If we fail to suspend any thread then we didn't have permission. We'll throw an exception in that case. If // we fail to suspend a few of the threads we'll treat that as non-fatal. if (permissionFailure && suspendedThreads.Count == 0) throw new InvalidOperationException($"Unable to suspend threads of process {_pid:x}."); int[] result = suspendedThreads.ToArray(); suspendedThreads = null; return result; } finally { if (suspendedThreads != null) ResumeThreads(suspendedThreads); } } private void ResumeThreads(IEnumerable suspendedThreads) { foreach (int threadId in suspendedThreads) { using var threadHandle = Interop.OpenThread(Interop.ThreadAccess.SUSPEND_RESUME, false, (uint)threadId); if (threadHandle.IsInvalid || Interop.ResumeThread(threadHandle.DangerousGetHandle()) == -1) { // If we fail to resume a thread we are in a bit of trouble because the target process is likely in a bad // state. This shouldn't ever happen, but if it does there's nothing we can do about it. We'll log an event // here but we won't throw an exception for a few reasons: // 1. We really never expect this to happen. Why would we be able to suspend a thread but not resume it? // 2. We want to finish resuming threads. // 3. There's nothing the caller can really do about it. Trace.WriteLine($"Failed to resume thread id:{threadId:id} in pid:{_pid:x}."); } } } private void Dispose(bool _) { lock (_sync) { if (_suspendedThreads != null) { int[] suspendedThreads = _suspendedThreads; _suspendedThreads = null; ResumeThreads(suspendedThreads); } } } public static class Interop { public enum ThreadAccess { SUSPEND_RESUME = 0x0002, THREAD_ALL_ACCESS = 0x1F03FF } private const string Kernel32LibraryName = "kernel32.dll"; [DllImport(Kernel32LibraryName)] private static extern bool GetThreadContext(IntPtr hThread, IntPtr lpContext); [DllImport(Kernel32LibraryName, SetLastError = true)] internal static extern SafeWin32Handle OpenThread(ThreadAccess dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwThreadId); [DllImport(Kernel32LibraryName, SetLastError = true)] internal static extern int SuspendThread(IntPtr hThread); [DllImport(Kernel32LibraryName, SetLastError = true)] internal static extern int ResumeThread(IntPtr hThread); public sealed class SafeWin32Handle : SafeHandleZeroOrMinusOneIsInvalid { public SafeWin32Handle() : base(true) { } public SafeWin32Handle(IntPtr handle) : this(handle, true) { } public SafeWin32Handle(IntPtr handle, bool ownsHandle) : base(ownsHandle) { SetHandle(handle); } [DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CloseHandle(IntPtr handle); protected override bool ReleaseHandle() { return CloseHandle(handle); } } } } ================================================ FILE: src/ProfileExplorerCore/ProfileExplorerCore.csproj ================================================  net8.0 enable enable true ..\external\Microsoft.Diagnostics.Tracing.TraceEvent.SymbolsAuthentication.dll ================================================ FILE: src/ProfileExplorerCore/Providers/CompilerIRKind.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.Core.Providers; /// /// Defines the different compiler IR types supported by Profile Explorer. /// public enum CompilerIRKind { /// /// Assembly/machine code IR /// ASM, /// /// LLVM Intermediate Representation /// LLVM } ================================================ FILE: src/ProfileExplorerCore/Providers/IBinaryFileFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.Core.Providers; public interface IBinaryFileFinder { Task FindBinaryFileAsync(BinaryFileDescriptor binaryFile, SymbolFileSourceSettings settings = null); } ================================================ FILE: src/ProfileExplorerCore/Providers/ICompilerInfoProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProtoBuf; namespace ProfileExplorer.Core.Providers; public interface ICompilerInfoProvider { string CompilerIRName { get; } CompilerIRKind CompilerIRKind { get; } string CompilerDisplayName { get; } string DefaultSyntaxHighlightingFile { get; } string OpenFileFilter { get; } string OpenDebugFileFilter { get; } ICompilerIRInfo IR { get; } INameProvider NameProvider { get; } IBinaryFileFinder BinaryFileFinder { get; } IDebugFileFinder DebugFileFinder { get; } IDebugInfoProviderFactory DebugInfoProviderFactory { get; } IDiffFilterProvider DiffFilterProvider { get; } Task AnalyzeLoadedFunction(FunctionIR function, IRTextSection section, ILoadedDocument loadedDoc, FunctionDebugInfo funcDebugInfo = null); } [ProtoContract] public class BinaryFileSearchResult { public static BinaryFileSearchResult None = new(); [ProtoMember(1)] public bool Found { get; set; } [ProtoMember(2)] public BinaryFileDescriptor BinaryFile { get; set; } [ProtoMember(3)] public string FilePath { get; set; } [ProtoMember(4)] public string Details { get; set; } [ProtoMember(5)] public bool IsApproximateMatch { get; set; } public static BinaryFileSearchResult Success(BinaryFileDescriptor file, string filePath, string details = null) { return new BinaryFileSearchResult {Found = true, BinaryFile = file, FilePath = filePath, Details = details}; } public static BinaryFileSearchResult Success(string filePath) { if (File.Exists(filePath)) { var info = PEBinaryInfoProvider.GetBinaryFileInfo(filePath); return new BinaryFileSearchResult {Found = true, BinaryFile = info, FilePath = filePath}; } return new BinaryFileSearchResult {Found = false, BinaryFile = null, FilePath = filePath}; } public static BinaryFileSearchResult ApproximateSuccess(BinaryFileDescriptor file, string filePath, string details = null) { return new BinaryFileSearchResult {Found = true, BinaryFile = file, FilePath = filePath, Details = details, IsApproximateMatch = true}; } public static BinaryFileSearchResult Failure(BinaryFileDescriptor file, string details) { return new BinaryFileSearchResult {BinaryFile = file, Details = details}; } public override string ToString() { return FilePath; } } [ProtoContract] public class DebugFileSearchResult { public static DebugFileSearchResult None = new(); [ProtoMember(1)] public bool Found { get; set; } [ProtoMember(2)] public SymbolFileDescriptor SymbolFile { get; set; } [ProtoMember(3)] public string FilePath { get; set; } [ProtoMember(4)] public string Details { get; set; } public static DebugFileSearchResult Success(SymbolFileDescriptor symbolFile, string filePath, string details = null) { return new DebugFileSearchResult {Found = true, SymbolFile = symbolFile, FilePath = filePath, Details = details}; } public static DebugFileSearchResult Success(string filePath) { return Success(new SymbolFileDescriptor(Path.GetFileName(filePath)), filePath); } public static DebugFileSearchResult Failure(SymbolFileDescriptor symbolFile, string details) { return new DebugFileSearchResult {SymbolFile = symbolFile, Details = details}; } public override string ToString() { return FilePath; } } ================================================ FILE: src/ProfileExplorerCore/Providers/IDebugFileFinder.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.Core.Providers; public interface IDebugFileFinder { Task FindDebugInfoFileAsync(string imagePath, SymbolFileSourceSettings settings = null); Task FindDebugInfoFileAsync(SymbolFileDescriptor symbolFile, SymbolFileSourceSettings settings = null); } ================================================ FILE: src/ProfileExplorerCore/Providers/IDebugInfoProviderFactory.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Session; namespace ProfileExplorer.Core.Providers; public interface IDebugInfoProviderFactory { IDebugInfoProvider CreateDebugInfoProvider(DebugFileSearchResult debugFile); IDebugInfoProvider GetOrCreateDebugInfoProvider(IRTextFunction function, ILoadedDocument loadedDoc); } ================================================ FILE: src/ProfileExplorerCore/Providers/INameProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; namespace ProfileExplorer.Core.Providers; public delegate string FunctionNameFormatter(string name); [Flags] public enum FunctionNameDemanglingOptions { Default = 0, OnlyName = 1 << 0, NoReturnType = 1 << 1, NoSpecialKeywords = 1 << 2 } public interface INameProvider { bool IsDemanglingSupported { get; } bool IsDemanglingEnabled { get; } FunctionNameDemanglingOptions GlobalDemanglingOptions { get; } string GetSectionName(IRTextSection section, bool includeNumber = true); string GetFunctionName(IRTextFunction function); string DemangleFunctionName(IRTextFunction function, FunctionNameDemanglingOptions options = FunctionNameDemanglingOptions.Default); string DemangleFunctionName(string name, FunctionNameDemanglingOptions options); string FormatFunctionName(IRTextFunction function); string FormatFunctionName(string name); void SettingsChanged(); //? TODO: GetBlockName } ================================================ FILE: src/ProfileExplorerCore/SectionReaderBase.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.IO; using System.Linq.Expressions; using System.Runtime.CompilerServices; using System.Text; namespace ProfileExplorer.Core; public abstract class SectionReaderBase : IRSectionReader, IDisposable { public static readonly long MAX_PRELOADED_FILE_SIZE = 256 * 1024 * 1024; // 256 MB private static readonly int STREAM_BUFFER_SIZE = 16 * 1024; private static readonly int MAX_LINE_LENGTH = 2000; private StreamReader dataReader_; private Stream dataStream_; private long dataStreamSize_; private Encoding dataStreamEncoding_; private bool expectSectionHeaders_; private object lockObject_; private Dictionary functionMap_; private int lineIndex_; private IRPassOutput optionalOutput_; private bool optionalOutputNeeded_; private string preloadedData_; private int prevLineCount_; private string[] prevLines_; private string currentLine_; private long nextInitialOffset_; private bool hasPreprocessedLines_; private bool hasMetadataLines_; private IRTextSummary summary_; private long textOffset_; private long previousOffset_; public SectionReaderBase(string filePath, bool expectSectionHeaders = true) { expectSectionHeaders_ = expectSectionHeaders; dataStreamSize_ = new FileInfo(filePath).Length; if (dataStreamSize_ < MAX_PRELOADED_FILE_SIZE) { dataStream_ = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var textStream = new StreamReader(dataStream_); preloadedData_ = textStream.ReadToEnd(); dataStream_.Seek(0, SeekOrigin.Begin); } else { dataStream_ = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); } Initialize(); } public SectionReaderBase(byte[] textData, bool expectSectionHeaders = true) { expectSectionHeaders_ = expectSectionHeaders; dataStream_ = new MemoryStream(textData); dataStreamSize_ = textData.Length; Initialize(); } // Main function for reading the text source and producing a summary // with all functions and their sections. public IRTextSummary GenerateSummary(ProgressInfoHandler progressHandler, SectionTextHandler sectionTextHandler) { var summary = GenerateSummaryImpl(progressHandler, sectionTextHandler); if (summary.Functions.Count == 0 && expectSectionHeaders_) { // Try parsing again, but without looking for section headers. // Useful when handling a single section copy-pasted from somewhere. expectSectionHeaders_ = false; dataStream_.Seek(0, SeekOrigin.Begin); dataReader_.DiscardBufferedData(); ResetSummaryState(); summary = GenerateSummaryImpl(progressHandler, sectionTextHandler); } return summary; } public string GetSectionText(IRTextSection section) { if (section.Output == null) { throw new NullReferenceException(); } return GetPassOutputText(section.Output, false); } public ReadOnlyMemory GetSectionTextSpan(IRTextSection section) { if (section.Output == null) { throw new NullReferenceException(); } return GetPassOutputTextSpan(section.Output); } public List GetSectionTextLines(IRTextSection section) { if (section.Output == null) { throw new NullReferenceException(); } return GetPassOutputTextLines(section.Output, false); } public string GetPassOutputText(IRPassOutput output) { return GetPassOutputText(output, true); } public ReadOnlyMemory GetPassOutputTextSpan(IRPassOutput output) { if (output == null) { throw new NullReferenceException(); } if (!output.HasPreprocessedLines) { // Fast path that avoids reading text line by line. return GetRawPassOutputTextSpan(output, false); } string text = GetPassOutputText(output, false); return text.AsMemory(); } public List GetPassOutputTextLines(IRPassOutput output) { return GetPassOutputTextLines(output, true); } public string GetRawSectionText(IRTextSection section) { if (section.Output == null) { throw new NullReferenceException(); } return GetRawPassOutputText(section.Output, false); } public ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section) { if (section.Output == null) { throw new NullReferenceException(); } return GetRawPassOutputTextSpan(section.Output, false); } public string GetRawPassOutputText(IRPassOutput output) { return GetRawPassOutputText(output, true); } public ReadOnlyMemory GetRawPassOutputTextSpan(IRPassOutput output) { return GetRawPassOutputTextSpan(output, true); } public byte[] GetDocumentTextData() { lock (lockObject_) { dataStream_.Seek(0, SeekOrigin.Begin); var encoding = DetectUTF8Encoding(dataStream_, Encoding.ASCII); using var binaryReader = new BinaryReader(dataStream_, encoding, true); return binaryReader.ReadBytes((int)dataStream_.Length); } } // Methods to be implemented by an IR reader implementation. protected abstract bool IsSectionStart(string line); protected abstract bool SectionStartIsFunctionStart(string line); protected abstract bool IsFunctionStart(string line); protected abstract bool IsFunctionEnd(string line); protected abstract bool IsBlockStart(string line); protected abstract string ExtractSectionName(string line); protected abstract string ExtractFunctionName(string line); protected abstract string PreprocessLine(string line); protected abstract bool ShouldSkipOutputLine(string line); protected abstract bool IsMetadataLine(string line); protected abstract bool FunctionEndIsFunctionStart(string line); protected void MarkPreprocessedLine(int line) { hasPreprocessedLines_ = true; } protected string NextLine() { return NextLine(dataReader_, true); } protected string NextLine(TextReader reader, bool recordPreviousLines) { previousOffset_ = textOffset_; string line = reader.ReadLine(); if (line == null) { return null; } line = PreprocessLine(line); if (recordPreviousLines) { RecordPreviousLine(line); } if (reader == dataReader_) { textOffset_ = ComputeTextOffset(dataReader_); } else { textOffset_ = ((SpanStringReader)reader).Position; } return line; } protected string PreviousLine(int offset) { return offset < prevLineCount_ ? prevLines_[offset] : null; } protected void RecordPreviousLine(string line) { for (int i = prevLines_.Length - 1; i >= 1; i--) { prevLines_[i] = prevLines_[i - 1]; } prevLines_[0] = line; prevLineCount_++; } protected long TextOffset() { return textOffset_; } private Encoding DetectUTF8Encoding(Stream stream, Encoding defaultEncoding) { // Check if the stream uses UTF8, otherwise fall back // to a default encoding (ASCII) which is much faster to read. Encoding encoding = new UTF8Encoding(true); byte[] preamble = encoding.GetPreamble(); if (stream.Length < preamble.Length) { return defaultEncoding; } long position = stream.Position; Span buffer = stackalloc byte[preamble.Length]; stream.Read(buffer); for (int i = 0; i < preamble.Length; i++) { if (buffer[i] != preamble[i]) { encoding = defaultEncoding; break; } } stream.Position = position; return encoding; } private void Initialize() { dataStreamEncoding_ = DetectUTF8Encoding(dataStream_, Encoding.ASCII); dataReader_ = new StreamReader(dataStream_, dataStreamEncoding_, false, STREAM_BUFFER_SIZE); prevLines_ = new string[3]; summary_ = new IRTextSummary(); functionMap_ = new Dictionary(); lockObject_ = new object(); } private void ResetSummaryState() { optionalOutput_ = null; optionalOutputNeeded_ = false; hasPreprocessedLines_ = false; hasMetadataLines_ = false; prevLineCount_ = 0; lineIndex_ = 0; } private IRTextSummary GenerateSummaryImpl(ProgressInfoHandler progressHandler, SectionTextHandler sectionTextHandler) { // Scan the document once to find the section boundaries, // any before/after text associated with the sections // and build the function -> sections hierarchy. ResetAdditionalOutput(); IRTextSection previousSection = null; var updateProgress = () => { if (progressHandler != null) { var info = new SectionReaderProgressInfo(TextOffset(), dataStreamSize_); progressHandler(this, info); } }; var section = FindNextSection(sectionTextHandler); updateProgress(); while (section != null) { summary_.AddSection(section); if (previousSection != null) { previousSection.OutputAfter = GetAdditionalOutput(); } section.OutputBefore = GetAdditionalOutput(); ResetAdditionalOutput(); previousSection = section; section = FindNextSection(sectionTextHandler); updateProgress(); } if (previousSection != null) { previousSection.OutputAfter = GetAdditionalOutput(); } return summary_; } private IRTextFunction GetOrCreateFunction(string name) { if (functionMap_.TryGetValue(name, out var textFunc)) { return textFunc; } textFunc = new IRTextFunction(name); summary_.AddFunction(textFunc); functionMap_.Add(name, textFunc); return textFunc; } private string GetPassOutputText(IRPassOutput output, bool isOptionalOutput) { if (output == null) { return ""; } if (!output.HasPreprocessedLines) { // Fast path that avoids reading text line by line. return GetRawPassOutputText(output, isOptionalOutput); } // If the file was preloaded in memory, create a new stream // to allow parallel loading of text. if (preloadedData_ != null) { using var streamReader = CreatePreloadedDataReader(output); return ReadPassOutputText(streamReader, output, isOptionalOutput); } lock (lockObject_) { return ReadPassOutputText(dataReader_, output, isOptionalOutput); } } private List GetPassOutputTextLines(IRPassOutput output, bool isOptionalOutput) { if (output == null) { return new List(); } // If the file was preloaded in memory, create a new stream // to allow parallel loading of text. if (preloadedData_ != null) { using var streamReader = CreatePreloadedDataReader(output); return ReadPassOutputTextLines(streamReader, output, isOptionalOutput); } lock (lockObject_) { return ReadPassOutputTextLines(dataReader_, output, isOptionalOutput); } } private SpanStringReader CreatePreloadedDataReader(IRPassOutput output) { return new SpanStringReader(preloadedData_, (int)output.Size, (int)output.DataStartOffset); } private string GetRawPassOutputText(IRPassOutput output, bool isOptionalOutput) { if (output == null) { return ""; } if (preloadedData_ != null) { // For some use cases, such as text search on the whole document, // it is much faster to use the unfiltered text and avoid reading // the text line by line to form the final string. var span = preloadedData_.AsMemory((int)output.DataStartOffset, (int)output.Size); return span.ToString(); } lock (lockObject_) { return ReadPassOutputText(dataReader_, output, isOptionalOutput); } } private ReadOnlyMemory GetRawPassOutputTextSpan(IRPassOutput output, bool isOptionalOutput) { if (output == null) { return ReadOnlyMemory.Empty; } if (preloadedData_ != null) { // For some use cases, such as text search on the whole document, // it is much faster to use the unfiltered text and avoid reading // the text line by line to form the final string. return preloadedData_.AsMemory((int)output.DataStartOffset, (int)output.Size); } lock (lockObject_) { string text = ReadPassOutputText(dataReader_, output, isOptionalOutput); return text.AsMemory(); } } private string ReadPassOutputText(StreamReader reader, IRPassOutput output, bool isOptionalOutput) { reader.BaseStream.Position = output.DataStartOffset; reader.DiscardBufferedData(); return ReadPassOutputText((TextReader)reader, output, isOptionalOutput); } private string ReadPassOutputText(TextReader reader, IRPassOutput output, bool isOptionalOutput) { var builder = new StringBuilder((int)output.Size); for (int i = output.StartLine; i <= output.EndLine; i++) { string line = NextLine(reader, false); if (isOptionalOutput && ShouldSkipOutputLine(line)) { continue; } // Skip over metadata lines, they are not supposed to be part of the IR // and are already saved in the LineMetadata table of the IRTextSection. if (IsMetadataLine(line)) { continue; } if (line.Length > MAX_LINE_LENGTH) { line = line.Substring(0, MAX_LINE_LENGTH); } builder.AppendLine(line); } return builder.ToString(); } private List ReadPassOutputTextLines(StreamReader reader, IRPassOutput output, bool isOptionalOutput) { reader.BaseStream.Position = output.DataStartOffset; reader.DiscardBufferedData(); return ReadPassOutputTextLines((TextReader)reader, output, isOptionalOutput); } private List ReadPassOutputTextLines(TextReader reader, IRPassOutput output, bool isOptionalOutput) { var list = new List(output.LineCount); for (int i = output.StartLine; i <= output.EndLine; i++) { string line = NextLine(reader, false); if (isOptionalOutput && ShouldSkipOutputLine(line)) { continue; } if (line.Length > MAX_LINE_LENGTH) { line = line.Substring(0, MAX_LINE_LENGTH); } list.Add(line); } return list; } private void AddOptionalOutputLine(string line, long initialOffset) { if (optionalOutput_ == null) { // Start a new optional section. long offset = TextOffset(); optionalOutput_ = new IRPassOutput(initialOffset, offset, lineIndex_, lineIndex_); optionalOutputNeeded_ = false; } optionalOutput_.DataEndOffset = TextOffset(); optionalOutput_.EndLine = lineIndex_; if (!string.IsNullOrWhiteSpace(line)) { optionalOutputNeeded_ = true; if (IsMetadataLine(line)) { hasMetadataLines_ = true; } } } private IRPassOutput GetAdditionalOutput() { if (optionalOutput_ != null && optionalOutputNeeded_) { optionalOutput_.HasPreprocessedLines = hasPreprocessedLines_ || hasMetadataLines_; return optionalOutput_; } return null; } private void ResetAdditionalOutput() { optionalOutput_ = null; hasPreprocessedLines_ = false; hasMetadataLines_ = false; } private IRTextSection FindNextSection(SectionTextHandler sectionTextHandler) { prevLineCount_ = 0; while (true) { long initialOffset = nextInitialOffset_; if (currentLine_ == null || !IsFunctionEnd(currentLine_) || !FunctionEndIsFunctionStart(currentLine_)) { currentLine_ = NextLine(); } if (currentLine_ == null) { break; } // Each section is expected to start with a name, // followed by an ASCII "currentLine_", which is searched for here, // unless the client indicates that the name may be missing. bool hasSectionName = true; if (!IsSectionStart(currentLine_)) { if (!expectSectionHeaders_ && (IsFunctionStart(currentLine_) || IsBlockStart(currentLine_))) { hasSectionName = false; } else { // Skip over currentLine_. AddOptionalOutputLine(currentLine_, initialOffset); lineIndex_++; continue; } } string funcName = string.Empty; if (SectionStartIsFunctionStart(currentLine_)) { funcName = ExtractFunctionName(currentLine_); hasSectionName = false; } // Collect the text lines if the client wants to process // the text while first reading the document. List sectionLines = null; if (sectionTextHandler != null) { sectionLines = new List(); } // Go back and find the name of the section. // If the current line is both a section and a function start (e.g. ASM 'func:'), // exclude the header from the section body output so tests see only the body. bool isFuncStartLine = SectionStartIsFunctionStart(currentLine_); int sectionStartLine = lineIndex_ + ((hasSectionName || isFuncStartLine) ? 1 : 0); int sectionEndLine = 0; string sectionName = hasSectionName ? ExtractSectionName(currentLine_) : string.Empty; // Find the end of the section and extract the function name. long startOffset = (hasSectionName || isFuncStartLine) ? TextOffset() : previousOffset_; long endOffset = startOffset; int blockCount = 0; // A section can have metadata associated with the previous line. Dictionary lineMetadata = null; int metadataLines = 0; while (true) { currentLine_ = NextLine(); if (currentLine_ == null) { sectionEndLine = lineIndex_ + 1; endOffset = TextOffset(); break; } if (sectionTextHandler != null) { if (!IsFunctionEnd(currentLine_) || !FunctionEndIsFunctionStart(currentLine_)) { // Add current line as part of section body. Header line was never added because // population starts only after advancing past the section/function start line. sectionLines.Add(currentLine_); } } if (string.IsNullOrEmpty(funcName) && IsFunctionStart(currentLine_)) { // Extract function name. funcName = ExtractFunctionName(currentLine_); } else if (IsFunctionEnd(currentLine_)) { // Found function end. endOffset = FunctionEndIsFunctionStart(currentLine_) ? previousOffset_ : TextOffset(); sectionEndLine = lineIndex_ + 1; nextInitialOffset_ = endOffset; break; } else if (IsBlockStart(currentLine_)) { blockCount++; } else if (IsMetadataLine(currentLine_)) { // Add line - metadata mapping to auxiliary table. lineMetadata ??= new Dictionary(); lineMetadata[lineIndex_ - sectionStartLine - metadataLines] = currentLine_; metadataLines++; } currentLine_ = null; lineIndex_++; } sectionEndLine = Math.Max(sectionEndLine, sectionStartLine); int lines = sectionEndLine - sectionStartLine; // Ignore empty sections. if (lines == 0) { lineIndex_++; continue; } // Create the a new section and its corresponding function, if needed. var output = new IRPassOutput(startOffset, endOffset, sectionStartLine, sectionEndLine) { HasPreprocessedLines = hasPreprocessedLines_ || lineMetadata != null }; var textFunc = GetOrCreateFunction(funcName); var section = new IRTextSection(textFunc, sectionName, output, blockCount); textFunc.AddSection(section); // Notify client a new section has been read. if (sectionTextHandler != null) { sectionTextHandler(this, new SectionReaderText(output, sectionLines)); } // Attach any metadata lines. if (lineMetadata != null) { section.LineMetadata = lineMetadata; section.CompressLineMetadata(); } return section; } return null; } private long ComputeTextOffset(StreamReader reader) { // This is a hack needed to get the proper offset in the stream, see // https://stackoverflow.com/questions/5404267/streamreader-and-seeking // Dynamic code generation is used as an efficient way of reading out the private fields. var fields = StreamReaderFields.Read(reader); // The number of bytes the remaining chars use in the original encoding. int numBytesLeft = reader.CurrentEncoding.GetByteCount(fields.CharBuffer, fields.CharPos, fields.CharLen - fields.CharPos); // For variable-byte encodings, deal with partial chars at the end of the buffer int numFragments = 0; if (fields.ByteLen > 0 && !reader.CurrentEncoding.IsSingleByte) { if (reader.CurrentEncoding.CodePage == 65001) { // UTF-8 byte byteCountMask = 0; while (fields.ByteBuffer[fields.ByteLen - numFragments - 1] >> 6 == 2 ) // if the byte is "10xx xxxx", it's a continuation-byte { byteCountMask |= (byte)(1 << ++numFragments ); // count bytes & build the "complete char" mask } if (fields.ByteBuffer[fields.ByteLen - numFragments - 1] >> 6 == 3 ) // if the byte is "11xx xxxx", it starts a multi-byte char. { byteCountMask |= (byte)(1 << ++numFragments ); // count bytes & build the "complete char" mask } // see if we found as many bytes as the leading-byte says to expect if (numFragments > 1 && fields.ByteBuffer[fields.ByteLen - numFragments] >> 7 - numFragments == byteCountMask) { numFragments = 0; // no partial-char in the byte-buffer to account for } } else if (reader.CurrentEncoding.CodePage == 1200) { // UTF-16LE if (fields.ByteBuffer[fields.ByteLen - 1] >= 0xd8) // high-surrogate { numFragments = 2; // account for the partial character } } else if (reader.CurrentEncoding.CodePage == 1201) { // UTF-16BE if (fields.ByteBuffer[fields.ByteLen - 2] >= 0xd8) // high-surrogate { numFragments = 2; // account for the partial character } } } return reader.BaseStream.Position - numBytesLeft - numFragments; } // Helper to quickly read a couple of private fields of a StreamReader // in order to compute the proper offset in the stream. // This is much faster (up to 10x) than using reflection to get to each field, // which was the main bottleneck in reading text files. // https://tyrrrz.me/blog/expression-trees private class StreamReaderFields { private static Action callback_; public char[] CharBuffer; public int CharPos; public int CharLen; public byte[] ByteBuffer; public int ByteLen; static StreamReaderFields() { // Create and compile to IL a function that reads the private fields // from a StreamReader and saves the values. var inputParam = Expression.Parameter(typeof(StreamReader)); var outputParam = Expression.Parameter(typeof(StreamReaderFields)); var block = Expression.Block( Expression.Assign(Expression.Field(outputParam, "CharBuffer"), Expression.Field(inputParam, "_charBuffer")), Expression.Assign(Expression.Field(outputParam, "CharPos"), Expression.Field(inputParam, "_charPos")), Expression.Assign(Expression.Field(outputParam, "CharLen"), Expression.Field(inputParam, "_charLen")), Expression.Assign(Expression.Field(outputParam, "ByteBuffer"), Expression.Field(inputParam, "_byteBuffer")), Expression.Assign(Expression.Field(outputParam, "ByteLen"), Expression.Field(inputParam, "_byteLen")) ); callback_ = Expression.Lambda> (block, inputParam, outputParam).Compile(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static StreamReaderFields Read(StreamReader reader) { var readerFields = new StreamReaderFields(); callback_(reader, readerFields); return readerFields; } } // Simple TextReader that can be used with a span or a substring. private class SpanStringReader : TextReader { private ReadOnlyMemory data_; private int position_; private int endPosition_; public SpanStringReader(ReadOnlyMemory value, int length, int position = 0) { data_ = value; endPosition_ = position + length; position_ = position; } public SpanStringReader(ReadOnlyMemory value, int position = 0) : this(value, value.Length, position) { } public SpanStringReader(string value, int length, int position = 0) { data_ = value.AsMemory(); endPosition_ = position + length; position_ = position; } public SpanStringReader(string value, int position = 0) : this(value, value.Length, position) { } public int Position => position_; public override int Read() { if (position_ == endPosition_) { return -1; } return data_.Span[position_++]; } public override int Peek() { if (position_ == endPosition_) { return -1; } return data_.Span[position_]; } } #region IDisposable Support private bool disposed_; protected void Dispose(bool disposing) { if (!disposed_) { dataReader_?.Dispose(); dataStream_?.Dispose(); dataReader_ = null; dataStream_ = null; preloadedData_ = null; disposed_ = true; } } ~SectionReaderBase() { Dispose(false); } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } #endregion } ================================================ FILE: src/ProfileExplorerCore/Session/BaseSession.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Metadata; using System.Threading.Tasks; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.ETW; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; using static System.Collections.Specialized.BitVector32; namespace ProfileExplorer.Core.Session; public enum SessionKind { Default = 0, FileSession = 1, DebugSession = 2 } public class BaseSession : ISession { private ICompilerInfoProvider compilerInfo_; private ProfileData profileData_; private List documents_; public ICompilerInfoProvider CompilerInfo => compilerInfo_; public ProfileData ProfileData => profileData_; public IReadOnlyList Documents => documents_; public BaseSession() { profileData_ = null; documents_ = new List(); } public async Task LoadProfileData(string profileFilePath, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { using var provider = new ETWProfileDataProvider(); provider.SetupNewSessionRequested += OnSetupNewSessionRequested; provider.StartNewSessionRequested += OnStartNewSessionRequested; var result = await provider.LoadTraceAsync(profileFilePath, processIds, options, symbolSettings, report, progressCallback, cancelableTask); if (result != null) { result.Report = report; profileData_ = result; UnloadProfilingDebugInfo(); } return result != null; } private async Task OnStartNewSessionRequested(string sessionName, SessionKind sessionKind, ICompilerInfoProvider compilerInfo) { compilerInfo_ = compilerInfo; } private async Task OnSetupNewSessionRequested(ILoadedDocument mainDocument, List otherDocuments, ProfileData profileData) { documents_.Add(mainDocument); documents_.AddRange(otherDocuments); } public async Task LoadAndParseSection(IRTextSection section) { var summary = section.ParentFunction.ParentSummary; var docInfo = FindLoadedDocument(section); // This shouldn't happen if document was loaded properly... if (docInfo == null || docInfo.Loader == null) { Trace.WriteLine($"Failed LoadAndParseSection for function {section.ParentFunction.Name}"); return null; } var parsedSection = docInfo.Loader.LoadSection(section); if (parsedSection != null && parsedSection.Function != null) { var funcDebugInfo = ProfileData?.GetFunctionProfile(section.ParentFunction)?.FunctionDebugInfo; var loadedDoc = FindLoadedDocument(section.ParentFunction); await compilerInfo_.AnalyzeLoadedFunction(parsedSection.Function, section, loadedDoc, funcDebugInfo); return parsedSection; } string placeholderText = "Could not find function code"; var dummyFunc = new FunctionIR(section.ParentFunction.Name); return new ParsedIRTextSection(section, placeholderText.AsMemory(), dummyFunc) { LoadFailed = true }; } private ILoadedDocument FindLoadedDocument(IRTextSection section) { var summary = section.ParentFunction.ParentSummary; return documents_.Find(item => item.Summary == summary); } private ILoadedDocument FindLoadedDocument(IRTextFunction func) { var summary = func.ParentSummary; return documents_.Find(item => item.Summary == summary); } private void UnloadProfilingDebugInfo() { if (ProfileData == null) { return; } // Free memory used by the debug info by unloading any objects // such as the PDB DIA reader using COM. Task.Run(() => { foreach ((string module, var debugInfo) in ProfileData.ModuleDebugInfo) { debugInfo.Unload(); } }); } } ================================================ FILE: src/ProfileExplorerCore/Session/ILoadedDocument.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Session; /// /// Delegate for lazy binary loading. Called when binary is needed but not yet loaded. /// public delegate Task EnsureBinaryLoadedDelegate(); public interface ILoadedDocument : IDisposable { Guid Id { get; set; } string ModuleName { get; set; } string FilePath { get; set; } BinaryFileSearchResult BinaryFile { get; set; } DebugFileSearchResult DebugInfoFile { get; set; } SymbolFileDescriptor SymbolFileInfo { get; set; } IRTextSectionLoader Loader { get; set; } IRTextSummary Summary { get; set; } IDebugInfoProvider DebugInfo { get; set; } bool IsDummyDocument { get; } bool DebugInfoFileExists { get; } bool BinaryFileExists { get; } bool HasSymbolFileInfo { get; } string FileName { get; } /// /// Callback for lazy binary loading. Set by ProfileModuleBuilder during profiling. /// Call this before accessing assembly/disassembly to ensure binary is downloaded. /// EnsureBinaryLoadedDelegate EnsureBinaryLoaded { get; set; } public event EventHandler DocumentChanged; public void SetupDocumentWatcher(); public void ChangeDocumentWatcherState(bool enabled); public void AddDummyFunctions(List funcNames); IRTextFunction AddDummyFunction(string name); void SaveSectionState(object stateObject, IRTextSection section); object LoadSectionState(IRTextSection section); ILoadedDocumentState SerializeDocument(); } ================================================ FILE: src/ProfileExplorerCore/Session/ILoadedDocumentState.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Providers; namespace ProfileExplorer.Core.Session; public interface ILoadedDocumentState { Guid Id { get; set; } string ModuleName { get; set; } string FilePath { get; set; } BinaryFileSearchResult BinaryFile { get; set; } DebugFileSearchResult DebugInfoFile { get; set; } byte[] DocumentText { get; set; } List> SectionStates { get; set; } List FunctionNames { get; set; } } ================================================ FILE: src/ProfileExplorerCore/Session/ISession.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Reflection.Metadata; using System.Threading.Tasks; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.Core.Session; public interface ISession { ICompilerInfoProvider CompilerInfo { get; } ProfileData ProfileData { get; } IReadOnlyList Documents { get; } Task LoadProfileData(string profileFilePath, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask); Task LoadAndParseSection(IRTextSection section); } ================================================ FILE: src/ProfileExplorerCore/Session/LoadedDocument.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.Utils; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Session; [ProtoContract] public class LoadedDocumentState : ILoadedDocumentState { [ProtoMember(1)] public Guid Id { get; set; } [ProtoMember(2)] public string ModuleName { get; set; } [ProtoMember(3)] public string FilePath { get; set; } [ProtoMember(4)] public BinaryFileSearchResult BinaryFile { get; set; } [ProtoMember(5)] public DebugFileSearchResult DebugInfoFile { get; set; } [ProtoMember(6)] public byte[] DocumentText { get; set; } [ProtoMember(7)] public List> SectionStates { get; set; } [ProtoMember(8)] public List FunctionNames { get; set; } public LoadedDocumentState() { SectionStates = new List>(); FunctionNames = new List(); } public LoadedDocumentState(Guid id) : this() { Id = id; } } public class LoadedDocument : ILoadedDocument { public Dictionary SectionStates; private FileSystemWatcher documentWatcher_; private IRTextSummary summary_; private bool disposed_; public LoadedDocument(string filePath, string modulePath, Guid id) { FilePath = filePath; ModuleName = Utils.TryGetFileName(modulePath ?? filePath); Id = id; SectionStates = new Dictionary(); } public Guid Id { get; set; } public string ModuleName { get; set; } public string FilePath { get; set; } public BinaryFileSearchResult BinaryFile { get; set; } public DebugFileSearchResult DebugInfoFile { get; set; } public SymbolFileDescriptor SymbolFileInfo { get; set; } public IRTextSectionLoader Loader { get; set; } public IRTextSummary Summary { get => summary_; set { summary_ = value; if (summary_ != null) { summary_.Id = Id; summary_.SetModuleName(ModuleName); } } } public IDebugInfoProvider DebugInfo { get; set; } // Used for managed binaries. public bool IsDummyDocument => Loader is DummySectionLoader; public bool DebugInfoFileExists => DebugInfoFile is {Found: true}; public bool BinaryFileExists => BinaryFile is {Found: true}; public bool HasSymbolFileInfo => SymbolFileInfo != null; public string FileName => Utils.TryGetFileName(FilePath); public EnsureBinaryLoadedDelegate EnsureBinaryLoaded { get; set; } public event EventHandler DocumentChanged; public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public static LoadedDocument CreateDummyDocument(string name) { return CreateDummyDocument(name, Guid.NewGuid()); } public static LoadedDocument CreateDummyDocument(string name, Guid id) { var doc = new LoadedDocument(name, name, id); doc.Summary = new IRTextSummary(name); doc.Loader = new DummySectionLoader(); // Placeholder used to prevent null pointers. return doc; } public IRTextFunction AddDummyFunction(string name) { var func = new IRTextFunction(name); func.ParentSummary = summary_; var section = new IRTextSection(func, func.Name, IRPassOutput.Empty); func.AddSection(section); summary_.AddFunction(func); summary_.AddSection(section); return func; } public void AddDummyFunctions(List funcNames) { foreach (string name in funcNames) { if (summary_.FindFunction(name) == null) { AddDummyFunction(name); } } } public void SaveSectionState(object stateObject, IRTextSection section) { SectionStates[section] = stateObject; } public object LoadSectionState(IRTextSection section) { return SectionStates.TryGetValue(section, out object stateObject) ? stateObject : null; } public void SetupDocumentWatcher() { try { string fileDir = Path.GetDirectoryName(FilePath); string fileName = Path.GetFileName(FilePath); documentWatcher_ = new FileSystemWatcher(fileDir, fileName); documentWatcher_.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size; documentWatcher_.Changed += DocumentWatcher_Changed; } catch (Exception ex) { Trace.TraceError($"Failed to setup document watcher for file {FilePath}: {ex.Message}"); documentWatcher_ = null; } } public void ChangeDocumentWatcherState(bool enabled) { if (documentWatcher_ != null) { documentWatcher_.EnableRaisingEvents = enabled; } } public virtual ILoadedDocumentState SerializeDocument() { var state = new LoadedDocumentState(Id) { ModuleName = ModuleName, FilePath = FilePath, BinaryFile = BinaryFile, DebugInfoFile = DebugInfoFile, DocumentText = Loader.GetDocumentTextBytes() }; foreach (var sectionState in SectionStates) { state.SectionStates.Add(new Tuple(sectionState.Key.Id, sectionState.Value as byte[])); } // Used by profiling to represent missing binaries. foreach (var func in summary_.Functions) { state.FunctionNames.Add(func.Name); } return state; } private void DocumentWatcher_Changed(object sender, FileSystemEventArgs e) { if (e.ChangeType != WatcherChangeTypes.Changed) { return; } DocumentChanged?.Invoke(this, EventArgs.Empty); } protected virtual void Dispose(bool disposing) { if (!disposed_) { if (disposing) { documentWatcher_?.Dispose(); } Loader?.Dispose(); Loader = null; Summary = null; documentWatcher_ = null; disposed_ = true; } } ~LoadedDocument() { Dispose(false); } } ================================================ FILE: src/ProfileExplorerCore/Session/StateSerializer.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.IR; using ProtoBuf; using ProtoBuf.Meta; namespace ProfileExplorer.Core.Session; public static class StateSerializer { public static readonly int subtypeIdStep_ = 100; public static int nextSubtypeId_; private static bool isInitialized_; private static readonly object initLock_ = new object(); static StateSerializer() { Initialize(); } public static void Initialize() { lock (initLock_) { if (!isInitialized_) { RuntimeTypeModel.Default.InternStrings = true; isInitialized_ = true; } } } public static void RegisterSurrogate() { RegisterSurrogate(typeof(T1), typeof(T2)); } public static void RegisterSurrogate(Type realType, Type surrogateType) { var model = RuntimeTypeModel.Default; model.Add(surrogateType); model.Add(realType, false).SetSurrogate(surrogateType); } public static void RegisterDerivedClass(int id = 0) { RegisterDerivedClass(typeof(T1), typeof(T2), id); } public static void RegisterDerivedClass(Type derivedType, Type baseType, int id = 0) { var model = RuntimeTypeModel.Default; if (id == 0) { nextSubtypeId_ += subtypeIdStep_; id = nextSubtypeId_; } model.Add(baseType, false).AddSubType(id, derivedType); } public static byte[] Serialize(T state, FunctionIR function = null) where T : class { using var stream = new MemoryStream(); Serializer.Serialize(stream, state); return stream.ToArray(); } public static bool Serialize(string filePath, T state, FunctionIR function = null) where T : class { using var stream = new FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite); Serializer.Serialize(stream, state); return true; } public static T Deserialize(byte[] data, FunctionIR function) where T : class { var value = Deserialize(data); if (value != null) { PatchIRElementObjects(value, function); return value; } return null; } public static T Deserialize(byte[] data) where T : class { if (data == null) { return null; } var stream = new MemoryStream(data); return Serializer.Deserialize(stream); } public static T Deserialize(string filePath) where T : class { using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); return Serializer.Deserialize(stream); } public static T Deserialize(object data, FunctionIR function) where T : class { return Deserialize((byte[])data, function); } public static T Deserialize(object data) where T : class { return Deserialize((byte[])data); } public static void PatchIRElementObjects(object value, FunctionIR function) { if (value == null) { return; } if (value is IRElementReference elementRef) { elementRef.Value = function.GetElementWithId(elementRef.Id); return; } if (!value.GetType().GetTypeInfo().IsClass) { return; // Don't walk primitive types. } if (value is IList list) { foreach (object item in list) { PatchIRElementObjects(item, function); } } else if (value is IDictionary dict) { foreach (object item in dict.Keys) { PatchIRElementObjects(item, function); } foreach (object item in dict.Values) { PatchIRElementObjects(item, function); } } else { var fields = value.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); foreach (var field in fields) { PatchIRElementObjects(field.GetValue(value), function); } } } } ================================================ FILE: src/ProfileExplorerCore/Settings/DiffSettings.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.ComponentModel; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Session; using ProtoBuf; namespace ProfileExplorer.Core.Settings; [ProtoContract(SkipConstructor = true)] public class DiffSettings : SettingsBase { public DiffSettings() { Reset(); } [ProtoMember(1)][OptionValue(true)] public bool IdentifyMinorDiffs { get; set; } [ProtoMember(2)][OptionValue(true)] public bool FilterInsignificantDiffs { get; set; } [ProtoMember(3)][OptionValue(true)] public bool ManyDiffsMarkWholeLine { get; set; } [ProtoMember(4)][OptionValue(60)] public int ManyDiffsModificationPercentage { get; set; } [ProtoMember(5)][OptionValue(75)] public int ManyDiffsInsertionPercentage { get; set; } [ProtoMember(6)][OptionValue(DiffImplementationKind.Internal)] [DefaultValue(DiffImplementationKind.Internal)] public DiffImplementationKind DiffImplementation { get; set; } [ProtoMember(7)][OptionValue(true)] public bool FilterTempVariableNames { get; set; } [ProtoMember(8)][OptionValue(true)] public bool FilterSSADefNumbers { get; set; } [ProtoMember(9)][OptionValue(true)] public bool ShowInsertions { get; set; } [ProtoMember(10)][OptionValue(true)] public bool ShowDeletions { get; set; } [ProtoMember(11)][OptionValue(true)] public bool ShowModifications { get; set; } [ProtoMember(12)][OptionValue(true)] public bool ShowMinorModifications { get; set; } [ProtoMember(13)] [OptionValue("")] public string ExternalDiffAppPath { get; set; } public bool ShowAnyChanges => ShowInsertions || ShowDeletions || ShowModifications || ShowMinorModifications; public override void Reset() { ResetAllOptions(this); } public virtual DiffSettings Clone() { byte[] serialized = StateSerializer.Serialize(this); return StateSerializer.Deserialize(serialized); } public bool HasDiffHandlingChanges(DiffSettings other) { return other.IdentifyMinorDiffs != IdentifyMinorDiffs || other.FilterInsignificantDiffs != FilterInsignificantDiffs || other.FilterTempVariableNames != FilterTempVariableNames || other.FilterSSADefNumbers != FilterSSADefNumbers || other.ManyDiffsMarkWholeLine != ManyDiffsMarkWholeLine || other.ManyDiffsInsertionPercentage != ManyDiffsInsertionPercentage || other.ManyDiffsModificationPercentage != ManyDiffsModificationPercentage || other.DiffImplementation != DiffImplementation || other.ShowInsertions != ShowInsertions || other.ShowDeletions != ShowDeletions || other.ShowModifications != ShowModifications || other.ShowMinorModifications != ShowMinorModifications; } public override bool Equals(object obj) { return AreOptionsEqual(this, obj); } [ProtoAfterDeserialization] private void AfterDeserialization() { if (!ShowAnyChanges) { ShowInsertions = true; ShowDeletions = true; ShowModifications = true; ShowMinorModifications = true; } } public override string ToString() { return PrintOptions(this); } } ================================================ FILE: src/ProfileExplorerCore/Settings/GeneralSettings.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Settings; [ProtoContract(SkipConstructor = true)] public class GeneralSettings : SettingsBase { private static int MinCpuCoreLimit = 1; private static int MaxCpuCoreLimit = 16; private static readonly double MinZoomAmount = 0.5; private static readonly double MaxZoomAmount = 2; private static readonly double ZoomStep = 0.05; public static readonly double DefaultCpuCoreLimit = 0.75; // Under a Remote Desktop session, disable animations // even if enabled otherwise by the user. private static readonly bool GlobalDisableAnimations = NativeMethods.IsRemoteDesktopSession(); public GeneralSettings() { Reset(); } [ProtoMember(1)][OptionValue(false)] public bool DisableHardwareRendering { get; set; } [ProtoMember(2)][OptionValue(true)] public bool CheckForUpdates { get; set; } [ProtoMember(3)][OptionValue(1.0)] public double WindowScaling { get; set; } [ProtoMember(4)][OptionValue(0)] public int ThemeIndex { get; set; } [ProtoMember(5)][OptionValue(0.75)] public double CpuCoreLimit { get; set; } [ProtoMember(6)][OptionValue(false)] public bool DisableAnimations { get; set; } public int CurrentCpuCoreLimit => (int)Math.Clamp(Math.Floor(CpuCoreLimit * Environment.ProcessorCount), MinCpuCoreLimit, MaxCpuCoreLimit); public bool UseAnimations => !DisableAnimations && !GlobalDisableAnimations; public override void Reset() { ResetAllOptions(this); } public double ZoomInWindow() { WindowScaling = Math.Clamp(WindowScaling + ZoomStep, MinZoomAmount, MaxZoomAmount); return WindowScaling; } public double ZoomOutWindow() { WindowScaling = Math.Clamp(WindowScaling - ZoomStep, MinZoomAmount, MaxZoomAmount); return WindowScaling; } public double ResetWindowZoom() { WindowScaling = 1.0; return WindowScaling; } public GeneralSettings Clone() { byte[] serialized = StateSerializer.Serialize(this); return StateSerializer.Deserialize(serialized); } public override bool Equals(object obj) { return AreOptionsEqual(this, obj); } public override string ToString() { return PrintOptions(this); } } ================================================ FILE: src/ProfileExplorerCore/Settings/ISettingsProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Providers; namespace ProfileExplorer.Core.Settings; /// /// Interface for providing access to application settings. /// This allows the UI project to override default settings used by the Core project. /// public interface ISettingsProvider { SymbolFileSourceSettings SymbolSettings { get; } ProfileDataProviderOptions ProfileOptions { get; } SectionSettings SectionSettings { get; } DiffSettings DiffSettings { get; } GeneralSettings GeneralSettings { get; } } ================================================ FILE: src/ProfileExplorerCore/Settings/ISettingsTypeConverter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; namespace ProfileExplorer.Core.Settings; /// /// Interface for custom type converters used in settings serialization/deserialization. /// Allows registration of type-specific conversion logic for complex types. /// public interface ISettingsTypeConverter { /// /// Gets the target type this converter handles. /// Type TargetType { get; } /// /// Converts a string value to the target type. /// /// The string representation of the value. /// The converted value of the target type. object ConvertFromString(string stringValue); /// /// Converts an array of string values to an array of the target type. /// /// The array of string representations. /// An array of converted values of the target type. Array ConvertFromStringArray(string[] stringArray); } ================================================ FILE: src/ProfileExplorerCore/Settings/ProfileDataProviderOptions.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Settings; [ProtoContract(SkipConstructor = true)] public class ProfileDataProviderOptions : SettingsBase { public ProfileDataProviderOptions() { Reset(); } [ProtoMember(1)][OptionValue(false)] public bool BinarySearchPathsEnabled { get; set; } [ProtoMember(2)][OptionValue(false)] public bool BinaryNameAllowedListEnabled { get; set; } [ProtoMember(3)][OptionValue(true)] public bool DownloadBinaryFiles { get; set; } [ProtoMember(4)][OptionValue()] public List BinarySearchPaths { get; set; } [ProtoMember(5)][OptionValue()] public List BinaryNameAllowedList { get; set; } [ProtoMember(6)][OptionValue(false)] public bool MarkInlinedFunctions { get; set; } [ProtoMember(7)][OptionValue(true)] public bool IncludeKernelEvents { get; set; } [ProtoMember(8)][OptionValue(true)] public bool IncludePerformanceCounters { get; set; } [ProtoMember(9)][OptionValue()] public ProfileRecordingSessionOptions RecordingSessionOptions { get; set; } [ProtoMember(10)][OptionValue()] public List PerformanceMetrics { get; set; } [ProtoMember(11)][OptionValue()] public List PreviousRecordingSessions { get; set; } [ProtoMember(12)][OptionValue()] public List PreviousLoadedSessions { get; set; } public bool HasBinaryNameAllowedList => BinaryNameAllowedListEnabled && BinaryNameAllowedList.Count > 0; public bool HasBinarySearchPaths => BinarySearchPathsEnabled && BinarySearchPaths.Count > 0; public override void Reset() { ResetAllOptions(this); } public bool AddPerformanceMetric(PerformanceMetricConfig config) { if (!PerformanceMetrics.Contains(config)) { PerformanceMetrics.Add(config); return true; } return false; } public bool HasBinaryPath(string path) { path = Utils.TryGetDirectoryName(path).ToLowerInvariant(); return BinarySearchPaths.Find(item => item.ToLowerInvariant() == path) != null; } public void InsertBinaryPath(string path) { if (string.IsNullOrEmpty(path) || HasBinaryPath(path)) { return; } path = Utils.TryGetDirectoryName(path); if (!string.IsNullOrEmpty(path)) { BinarySearchPaths.Insert(0, path); } } public ProfileDataProviderOptions Clone() { byte[] serialized = StateSerializer.Serialize(this); return StateSerializer.Deserialize(serialized); } public override bool Equals(object obj) { return AreOptionsEqual(this, obj); } public override string ToString() { return PrintOptions(this); } [ProtoAfterDeserialization] private void InitializeReferenceMembers() { InitializeReferenceOptions(this); } } ================================================ FILE: src/ProfileExplorerCore/Settings/ProfileOptions.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.IO; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Session; using ProtoBuf; namespace ProfileExplorer.Core.Settings; [ProtoContract(SkipConstructor = true)] public class ProfileRecordingSessionOptions : SettingsBase, IEquatable { public const int DefaultSamplingFrequency = 4000; public const int MaximumSamplingFrequency = 8000; public ProfileRecordingSessionOptions() { Reset(); } [ProtoMember(1)][OptionValue(ProfileSessionKind.StartProcess)] public ProfileSessionKind SessionKind { get; set; } [ProtoMember(2)][OptionValue("")] public string ApplicationPath { get; set; } [ProtoMember(3)][OptionValue("")] public string ApplicationArguments { get; set; } [ProtoMember(4)][OptionValue("")] public string WorkingDirectory { get; set; } [ProtoMember(5)][OptionValue(4000)] // 4 kHz, Xperf default is 1 kHz. public int SamplingFrequency { get; set; } [ProtoMember(6)][OptionValue(false)] public bool ProfileDotNet { get; set; } [ProtoMember(7)][OptionValue(false)] public bool ProfileChildProcesses { get; set; } [ProtoMember(8)][OptionValue(false)] public bool RecordPerformanceCounters { get; set; } [ProtoMember(9)][OptionValue(false)] public bool EnableEnvironmentVars { get; set; } [ProtoMember(10)][OptionValue()] public List<(string Variable, string Value)> EnvironmentVariables { get; set; } [ProtoMember(11)][OptionValue()] public List PerformanceCounters { get; set; } [ProtoMember(12)][OptionValue("")] public string Title { get; set; } [ProtoMember(13)][OptionValue(0)] public int TargetProcessId { get; set; } [ProtoMember(14)][OptionValue(false)] public bool RecordDotNetAssembly { get; set; } public List EnabledPerformanceCounters => PerformanceCounters.FindAll(c => c.IsEnabled); public bool HasWorkingDirectory => Directory.Exists(WorkingDirectory); public bool HasTitle => !string.IsNullOrEmpty(Title); public bool Equals(ProfileRecordingSessionOptions other) { return AreOptionsEqual(this, other); } public static bool operator ==(ProfileRecordingSessionOptions left, ProfileRecordingSessionOptions right) { return Equals(left, right); } public static bool operator !=(ProfileRecordingSessionOptions left, ProfileRecordingSessionOptions right) { return !Equals(left, right); } public override void Reset() { ResetAllOptions(this); } public bool AddPerformanceCounter(PerformanceCounterConfig config) { if (!PerformanceCounters.Contains(config)) { PerformanceCounters.Add(config); return true; } return false; } public ProfileRecordingSessionOptions Clone() { byte[] serialized = StateSerializer.Serialize(this); return StateSerializer.Deserialize(serialized); } public override bool Equals(object obj) { return AreOptionsEqual(this, obj); } public override string ToString() { return PrintOptions(this); } [ProtoAfterDeserialization] private void InitializeReferenceMembers() { InitializeReferenceOptions(this); } } ================================================ FILE: src/ProfileExplorerCore/Settings/SectionSettings.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Providers; using ProtoBuf; namespace ProfileExplorer.Core.Settings; /// /// Core section settings with properties needed by the Core project. /// This is a minimal implementation that can be overridden by UI-specific settings. /// [ProtoContract(SkipConstructor = true)] public class SectionSettings : SettingsBase { public SectionSettings() { Reset(); } // Properties needed by Core project public virtual bool ShowDemangledNames { get; set; } = true; public virtual FunctionNameDemanglingOptions DemanglingOptions { get; set; } = FunctionNameDemanglingOptions.Default; public override void Reset() { ShowDemangledNames = true; DemanglingOptions = FunctionNameDemanglingOptions.Default; } public virtual SectionSettings Clone() { return new SectionSettings { ShowDemangledNames = this.ShowDemangledNames, DemanglingOptions = this.DemanglingOptions }; } public override bool Equals(object obj) { if (obj is SectionSettings other) { return ShowDemangledNames == other.ShowDemangledNames && DemanglingOptions == other.DemanglingOptions; } return false; } public override string ToString() { return $"ShowDemangledNames: {ShowDemangledNames}, DemanglingOptions: {DemanglingOptions}"; } } ================================================ FILE: src/ProfileExplorerCore/Settings/SettingsBase.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Text; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Settings; // A typical settings class should: // - should inherit from SettingsBase and be marked with ProtoContract. // - have a constructor that calls Reset() and is skipped by ProtoBuf. // - have a ProtoMember for each setting with an OptionValue default value. // - have a ProtoAfterDeserialization method that initializes reference members. // - have a Reset method that calls ResetAllOptions. // - have an Equals method that calls AreSettingsOptionsEqual. // // Type handling registry for custom type conversion public static class SettingsTypeRegistry { private static readonly Dictionary _converters = new(); /// /// Registers a type converter for use in settings serialization/deserialization. /// /// The type converter to register. public static void RegisterConverter(ISettingsTypeConverter converter) { if (converter == null) throw new ArgumentNullException(nameof(converter)); _converters[converter.TargetType] = converter; } /// /// Gets a registered converter for the specified type. /// /// The type to get a converter for. /// The registered converter, or null if none is registered. internal static ISettingsTypeConverter GetConverter(Type type) { _converters.TryGetValue(type, out var converter); return converter; } /// /// Clears all registered converters. Primarily for testing purposes. /// public static void ClearConverters() { _converters.Clear(); } } // - have a ToString method that calls PrintOptions. // - have a Clone method that serializes and deserializes the object. // // Example: // [ProtoContract(SkipConstructor = true)] // public class ExampleSettings : SettingsBase { // [ProtoMember(1), OptionValue("Default Value")] // public string SomeSetting { get; set; } // // public ExampleSettings() { // Reset(); // } // // public override void Reset() { // InitializeReferenceMembers(); // ResetAllOptions(this); // } // // [ProtoAfterDeserialization] // private void InitializeReferenceMembers() { // // Initialize reference members here. // } // // public override bool Equals(object obj) { // return AreSettingsOptionsEqual(this, obj); // } // // public override string ToString() { // return PrintOptions(this); // } // // public ExampleSettings Clone() { // byte[] serialized = StateSerializer.Serialize(this); // return StateSerializer.Deserialize(serialized); // } // } // A unique identifier for an option value, combines the class name // with the ProtoBuf ProtoMember Id tag, which should remain stable // across versions of the app. public record OptionValueId(string ClassName, int MemberId); // Attribute to specify the default value of an option. [AttributeUsage(AttributeTargets.All)] public class OptionValueAttribute : Attribute { public OptionValueAttribute() { // Create new object of type, calling default constructor. CreateNewInstance = true; } public OptionValueAttribute(object value) { // Set value to the primitive value passed in. Value = value; } public object Value { get; set; } public bool CreateNewInstance { get; set; } } public class SettingsBase { private static void EmptyVisitOptionAction(object settings, PropertyInfo property, OptionValueAttribute optionAttr, OptionValueId optionId) { } private static void EmptyVisitSettingsAction(object settings, int level) { } private static void EmptyVisitNestedSettingsAction(object nestedSettings, PropertyInfo property, bool isCollection) { } public virtual void Reset() { } public static HashSet CollectOptionMembers(object settings) { var set = new HashSet(); CollectOptionMembers(settings, set); return set; } public static void CollectOptionMembers(object settings, HashSet set) { var type = settings.GetType(); var visited = new HashSet(); CollectOptionMembers(type, set, visited); } private static ProtoIncludeAttribute FindMatchingProtoInclude(Type baseType, Type derivedType) { foreach (var attr in baseType.GetCustomAttributes()) { if (attr.KnownType == derivedType) { return attr; } } return null; } public static void ResetAllOptions(object settings, Type type = null, bool resetNestedSettings = true, bool resetToNew = true) { var visited = new HashSet(); WalkSettingsOptions(settings, (obj, property, optionAttr, optionId) => { // Trace.WriteLine($"Resetting property {property.Name}, type {type.Name}: {optionAttr.Value}"); if (optionAttr != null) { SetOptionValue(property, obj, optionAttr); return true; } if (resetNestedSettings && property.GetValue(obj) is SettingsBase nestedSettings) { nestedSettings.Reset(); } else if (resetToNew) { if (property.GetValue(obj) is IList list) { list.Clear(); } else if (property.GetValue(obj) is IDictionary dict) { dict.Clear(); } else if (property.GetSetMethod() != null) { object newObject = Activator.CreateInstance(property.PropertyType); property.SetValue(obj, newObject); } } return true; }, EmptyVisitSettingsAction, EmptyVisitSettingsAction, EmptyVisitNestedSettingsAction, false, false, type, visited); } private static void SetOptionValue(PropertyInfo property, object obj, OptionValueAttribute optionAttr) { if (property.GetSetMethod() == null) return; if (optionAttr.CreateNewInstance) { property.SetValue(obj, Activator.CreateInstance(property.PropertyType)); } else if (optionAttr.Value != null) { if (optionAttr.Value.GetType() == property.PropertyType) { property.SetValue(obj, optionAttr.Value); } else if (optionAttr.Value.GetType().IsPrimitive) { object convertedValue = Convert.ChangeType(optionAttr.Value, property.PropertyType); property.SetValue(obj, convertedValue); } else if (optionAttr.Value is string strValue) { // Try to find a registered converter for this type var converter = SettingsTypeRegistry.GetConverter(property.PropertyType); if (converter != null) { object convertedValue = converter.ConvertFromString(strValue); property.SetValue(obj, convertedValue); } else { throw new InvalidOperationException($"Type {property.PropertyType.Name} not handled - no converter registered"); } } else if (optionAttr.Value is string[] strArray) { // Try to find a registered converter for this type var converter = SettingsTypeRegistry.GetConverter(property.PropertyType.GetElementType() ?? property.PropertyType); if (converter != null) { Array convertedArray = converter.ConvertFromStringArray(strArray); property.SetValue(obj, convertedArray); } else { throw new InvalidOperationException($"Type {property.PropertyType.Name} not handled - no converter registered"); } } else { throw new InvalidOperationException("Type not handled"); } } } public static void InitializeAllNewOptions(object settings, HashSet knownOptions) { var visited = new HashSet(); WalkSettingsOptions(settings, (obj, property, optionAttr, optionId) => { // Initialize only missing properties. if (optionAttr != null && knownOptions != null && !knownOptions.Contains(optionId)) { // Trace.WriteLine($"Setting missing property {property.Name}, type {type.Name}: {optionAttr.Value}"); SetOptionValue(property, obj, optionAttr); } return true; }, EmptyVisitSettingsAction, EmptyVisitSettingsAction, EmptyVisitNestedSettingsAction, true, true, null, visited); } public static void InitializeReferenceOptions(object settings) { var visited = new HashSet(); WalkSettingsOptions(settings, (obj, property, optionAttr, optionId) => { if (!property.GetType().IsValueType && property.GetValue(obj) == null && (optionAttr == null || optionAttr.CreateNewInstance) && property.GetSetMethod() != null) { // Initialize all reference properties with an instance. object newObject = Activator.CreateInstance(property.PropertyType); property.SetValue(obj, newObject); } return true; }, EmptyVisitSettingsAction, EmptyVisitSettingsAction, EmptyVisitNestedSettingsAction, false, true, null, visited); } public static string PrintOptions(object settings, Type type = null, bool includeBaseClass = true) { var visited = new HashSet(); var sb = new StringBuilder(); int currentLevel = 0; if (type != null) { Debug.Assert(type.IsAssignableFrom(settings.GetType())); } else { type = settings.GetType(); } WalkSettingsOptions(settings, (obj, property, optionAttr, optionId) => { object value = property.GetValue(obj); if (value is SettingsBase) { return true; // Printed as sub-section. } sb.Append(' ', currentLevel * 4); sb.Append($"{property.Name}: {value}"); if (optionAttr != null && optionAttr.Value != null) { if (value != null && AreValuesEqual(value, optionAttr.Value)) { sb.Append($" (default \u2713)"); } else { sb.Append($" (default {optionAttr.Value})"); } } sb.AppendLine(); return true; }, (settings, level) => { sb.Append(' ', currentLevel * 4); sb.AppendLine($"{settings.GetType().Name}:"); currentLevel = level; }, (settings, level) => { sb.Append(' ', currentLevel * 4); sb.AppendLine("--------------------------------------"); currentLevel = level; }, (nestedSettings, property, isCollection) => { //? TODO: Pretty-print list/dict }, true, includeBaseClass, type, visited); return sb.ToString(); } private static bool AreValuesEqual(object a, object b, bool compareNestedSettings = false) { if (ReferenceEquals(a, b)) { return true; } else if (a == null || b == null) { return false; } switch ((a, b)) { case (double da, double db): { return Math.Abs(da - db) < double.Epsilon; break; } case (float fa, float fb): { return Math.Abs(fa - fb) < float.Epsilon; break; } case (double da, int ib): { return Math.Abs(da - ib) < double.Epsilon; break; } case (float fa, int ib): { return Math.Abs(fa - ib) < float.Epsilon; break; } case (string sa, string sb): { return sa.Equals(sb, StringComparison.Ordinal); } case (SettingsBase settingsA, SettingsBase settingsB): { if (compareNestedSettings) { // If Equals was overridden use it, otherwise // recursively compare each property in nested settings. var equals = settingsA.GetType().GetMethod("Equals"); if (equals == null || equals.DeclaringType != settingsA.GetType()) { return AreOptionsEqual(settingsA, settingsB, null, false, compareNestedSettings); } } return settingsA.Equals(settingsB); } case (IList listA, IList listB): { // Compare each element of the collection. return listA.AreEqual(listB); } case (IDictionary dictA, IDictionary dictB): { // Compare each element of the collection. return dictA.AreEqual(dictB); } case (IEnumerable enumA, IEnumerable enumB): { // Compare each element of the collection. var iterA = enumA.GetEnumerator(); var iterB = enumB.GetEnumerator(); bool hasA = iterA.MoveNext(); bool hasB = iterB.MoveNext(); while (hasA && hasB) { if (!Equals(iterA.Current, iterB.Current)) { return false; } hasA = iterA.MoveNext(); hasB = iterB.MoveNext(); if (!hasA && !hasB) { return true; } } return false; } default: { return a.Equals(b); } } } public static bool AreOptionsEqual(object settingsA, object settingsB, Type type = null, bool compareBaseClass = false, bool compareNestedSettings = true) { if (settingsA == null || settingsB == null || settingsA.GetType() != settingsB.GetType()) { return false; } else if (ReferenceEquals(settingsA, settingsB)) { return true; } if (type != null) { Debug.Assert(type.IsAssignableFrom(settingsA.GetType())); } else { type = settingsA.GetType(); } var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; if (!compareBaseClass) { flags |= BindingFlags.DeclaredOnly; } foreach (var property in type.GetProperties(flags)) { object valueA = property.GetValue(settingsA); object valueB = property.GetValue(settingsB); if (!AreValuesEqual(valueA, valueB, compareNestedSettings)) { return false; } } return true; } private static bool WalkSettingsOptions(object settings, VisitOptionAction optionAction, VisitSettingsAction beginVisitSettingsAction, VisitSettingsAction endVisitSettingsAction, VisitNestedSettingsAction beginNestedSettingsAction, bool visitedNestedSettings, bool visitBaseClass, Type type, HashSet visited, int level = 0) { if (settings == null || !visited.Add(settings)) { return true; // Avoid cycles in the object graph. } if (type != null) { Debug.Assert(type.IsAssignableFrom(settings.GetType())); } else { type = settings.GetType(); } var contractAttr = type.GetCustomAttribute(); if (contractAttr == null) { return true; } beginVisitSettingsAction?.Invoke(settings, level); var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; if (!visitBaseClass) { // When resetting don't consider properties from the base class. flags |= BindingFlags.DeclaredOnly; } foreach (var property in type.GetProperties(flags)) { var protoAttr = property.GetCustomAttribute(); if (protoAttr == null) continue; // Check if there is a default option value attribute attached. var optionAttr = property.GetCustomAttribute(); bool propertyIsSettings = property.PropertyType.BaseType == typeof(SettingsBase); if (optionAttr != null) { var optionId = MakeOptionId(property, type, contractAttr, protoAttr); if (!optionAction(settings, property, optionAttr, optionId)) { return false; } } else { if (!optionAction(settings, property, null, null)) { return false; } } if (!visitedNestedSettings) { continue; // When resetting don't handle base class and nested settings. } // Recursively go over nested settings. if (propertyIsSettings) { object value = property.GetValue(settings); if (value is SettingsBase nestedSettings) { beginNestedSettingsAction?.Invoke(nestedSettings, property, false); WalkSettingsOptions(nestedSettings, optionAction, beginVisitSettingsAction, endVisitSettingsAction, beginNestedSettingsAction, visitedNestedSettings, visitBaseClass, null, visited, level + 1); } } else if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) { if (IsSettingsBaseGenericType(property) && property.GetValue(settings) is IEnumerable enumValue) { beginNestedSettingsAction?.Invoke(enumValue, property, true); foreach (object nestedValue in enumValue) { if (nestedValue is SettingsBase nestedSettings) { WalkSettingsOptions(nestedSettings, optionAction, beginVisitSettingsAction, endVisitSettingsAction, beginNestedSettingsAction, visitedNestedSettings, visitBaseClass, null, visited, level + 1); } } } } else if (property.PropertyType.IsGenericType && property.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) { if (IsSettingsBaseGenericType(property) && property.GetValue(settings) is IDictionary dictValue) { beginNestedSettingsAction?.Invoke(dictValue, property, true); foreach (DictionaryEntry kvp in dictValue) { if (kvp.Key is SettingsBase keySettings) { WalkSettingsOptions(keySettings, optionAction, beginVisitSettingsAction, endVisitSettingsAction, beginNestedSettingsAction, visitedNestedSettings, visitBaseClass, null, visited, level + 1); } if (kvp.Value is SettingsBase valueSettings) { WalkSettingsOptions(valueSettings, optionAction, beginVisitSettingsAction, endVisitSettingsAction, beginNestedSettingsAction, visitedNestedSettings, visitBaseClass, null, visited, level + 1); } } } } } endVisitSettingsAction?.Invoke(settings, Math.Max(0, level - 1)); return true; } private static bool IsSettingsBaseGenericType(PropertyInfo property) { foreach (var genericType in property.PropertyType.GenericTypeArguments) { if (genericType.BaseType == typeof(SettingsBase)) { return true; } } return false; } private static void CollectOptionMembers(Type type, HashSet set, HashSet visited) { if (!visited.Add(type)) { return; // Avoid cycles in the type graph. } var contractAttr = type.GetCustomAttribute(); if (contractAttr == null) return; foreach (var property in type.GetProperties()) { var protoAttr = property.GetCustomAttribute(); if (protoAttr == null) continue; var optionId = MakeOptionId(property, type, contractAttr, protoAttr); set.Add(optionId); if (property.PropertyType.BaseType == typeof(SettingsBase)) { CollectOptionMembers(property.PropertyType, set, visited); } else if (property.PropertyType.IsGenericType && (property.PropertyType.GetGenericTypeDefinition() == typeof(List<>) || property.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>))) { // Go over generic types of in List and Dictionary. foreach (var genericType in property.PropertyType.GenericTypeArguments) { if (genericType.BaseType == typeof(SettingsBase)) { CollectOptionMembers(genericType, set, visited); } } } } } private static OptionValueId MakeOptionId(PropertyInfo property, Type type, ProtoContractAttribute contractAttr, ProtoMemberAttribute protoAttr) { string className = !string.IsNullOrEmpty(contractAttr.Name) ? contractAttr.Name : type.Name; int id = protoAttr.Tag; if (property.DeclaringType != type) { // Members from base classes have an Id that is at an offset // defined by a ProtoInclude attribute. Find the ProtoInclude that corresponds // to this derived type. var protoIncludeAttr = FindMatchingProtoInclude(property.DeclaringType, type); if (protoIncludeAttr != null) { id += protoIncludeAttr.Tag; } } var optionId = new OptionValueId(className, id); return optionId; } private delegate bool VisitOptionAction(object settings, PropertyInfo property, OptionValueAttribute optionAttr, OptionValueId optionId); private delegate void VisitSettingsAction(object settings, int level); private delegate void VisitNestedSettingsAction(object nestedSettings, PropertyInfo property, bool isCollection); } ================================================ FILE: src/ProfileExplorerCore/Settings/SymbolFileSourceSettings.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.Core.Settings; public enum SymbolFileRejectionReason { Unknown = 0, // Unknown/legacy PermanentNotFound, // 404 - safe to cache (3 days) InvalidFormat, // Parse error - safe to cache NetworkTimeout, // Transient - DON'T cache AuthenticationFailure, // Transient - DON'T cache ServerError // 5xx - transient - DON'T cache } [ProtoContract(SkipConstructor = true)] public class SymbolFileSourceSettings : SettingsBase { private const string DefaultPrivateSymbolServer = @"https://symweb.azurefd.net"; private const string DefaultPublicSymbolServer = @"https://msdl.microsoft.com/download/symbols"; private const string DefaultSymbolCachePath = @"C:\Symbols"; private const string DefaultEnvironmentVarSymbolPath = @"_NT_SYMBOL_PATH"; public const double DefaultLowSampleModuleCutoff = 0.002; // 0.2% public SymbolFileSourceSettings() { Reset(); } public static string DefaultCacheDirectoryPath => Path.Combine(Path.GetTempPath(), "ProfileExplorer", "symcache"); [ProtoMember(1)][OptionValue()] public List SymbolPaths { get; set; } [ProtoMember(2)][OptionValue(true)] public bool SourceServerEnabled { get; set; } [ProtoMember(3)][OptionValue(false)] public bool AuthorizationTokenEnabled { get; set; } [ProtoMember(4)][OptionValue("")] public string AuthorizationToken { get; set; } [ProtoMember(5)][OptionValue(false)] public bool UseEnvironmentVarSymbolPaths { get; set; } [ProtoMember(6)][OptionValue(true)] public bool SkipLowSampleModules { get; set; } [ProtoMember(7)][OptionValue("")] public string AuthorizationUser { get; set; } [ProtoMember(8)][OptionValue()] public HashSet RejectedBinaryFiles { get; set; } [ProtoMember(9)][OptionValue()] public HashSet RejectedSymbolFiles { get; set; } [ProtoMember(10)][OptionValue(true)] public bool RejectPreviouslyFailedFiles { get; set; } [ProtoMember(11)][OptionValue(true)] public bool IncludeSymbolSubdirectories { get; set; } [ProtoMember(12)][OptionValue(true)] public bool CacheSymbolFiles { get; set; } [ProtoMember(13)][OptionValue("")] public string CustomSymbolCacheDirectory { get; set; } [ProtoMember(14)][OptionValue(0.002)] // 0.2% public double LowSampleModuleCutoff { get; set; } [ProtoMember(15)][OptionValue(true)] public bool CompanyFilterEnabled { get; set; } [ProtoMember(16)][OptionValue()] public List CompanyFilterStrings { get; set; } [ProtoMember(17)][OptionValue(30)] // 30 seconds normal timeout (after auth validated) public int SymbolServerTimeoutSeconds { get; set; } [ProtoMember(18)][OptionValue(true)] public bool BellwetherTestEnabled { get; set; } [ProtoMember(19)][OptionValue(60)] // 60 seconds for bellwether/initial requests (after auth validated) public int BellwetherTimeoutSeconds { get; set; } [ProtoMember(20)][OptionValue(10)] // 10 seconds when symbol server is degraded public int DegradedTimeoutSeconds { get; set; } [ProtoMember(24)][OptionValue(600)] // 10 minutes pre-auth timeout (user may need to interact with auth dialog) public int PreAuthTimeoutSeconds { get; set; } [ProtoMember(21)][OptionValue(true)] public bool WindowsPathFilterEnabled { get; set; } [ProtoMember(22)] public DateTime RejectedFilesCacheTime { get; set; } [ProtoMember(23)][OptionValue(3)] // 3 days default expiration public int RejectedFilesCacheExpirationDays { get; set; } [ProtoMember(25)][OptionValue(true)] public bool AllowApproximateBinaryMatch { get; set; } public bool HasAuthorizationToken => AuthorizationTokenEnabled && !string.IsNullOrEmpty(AuthorizationToken); public bool HasCompanyFilter => CompanyFilterEnabled; // Runtime state - not persisted. Set when bellwether test fails. public bool SymbolServerDegraded { get; set; } // Runtime state - tracks if we've had our first successful network request. // Used to know when to reduce timeout from initial 30s to normal 10s. public bool HadFirstSuccessfulNetworkRequest { get; set; } // Runtime state - tracks if we've had any timeout, triggering reduced timeout. public bool HadFirstTimeout { get; set; } // Runtime state - tracks if primary (private) server auth failed. // When true, subsequent downloads skip primary and go directly to secondary (public) server. public bool PrimaryServerAuthFailed { get; set; } // Runtime state - tracks if primary server has been verified working. // When true, we know primary server works and should be used. public bool PrimaryServerVerified { get; set; } // Runtime state - session-level tracking for negative cache safety checks. // These are NOT persisted and reset on each session. public int SessionSymbolSearchCount { get; set; } public int SessionSymbolFailureCount { get; set; } public int SessionSymbolSuccessCount { get; set; } /// /// Returns the effective timeout based on current state: /// - If auth not yet validated: use PreAuthTimeoutSeconds (600s/10min) to allow for interactive auth /// - If degraded (bellwether failed): use DegradedTimeoutSeconds (10s) /// - If we've had a timeout: use SymbolServerTimeoutSeconds (30s) /// - Otherwise (initial post-auth state): use BellwetherTimeoutSeconds (60s) /// public int EffectiveTimeoutSeconds { get { // Before auth is validated, use very long timeout to allow for interactive auth dialog // The user might not see the auth dialog immediately, so we give them 10 minutes if (!HadFirstSuccessfulNetworkRequest && !SymbolServerDegraded) { return PreAuthTimeoutSeconds; } if (SymbolServerDegraded) { return DegradedTimeoutSeconds; } if (HadFirstTimeout) { return SymbolServerTimeoutSeconds; } // Auth validated, no timeouts yet - use generous initial timeout return BellwetherTimeoutSeconds; } } /// /// Returns the effective company filter strings. Uses "Microsoft" as default if enabled but list is empty. /// public IReadOnlyList EffectiveCompanyFilterStrings { get { if (CompanyFilterStrings?.Count > 0) { return CompanyFilterStrings; } // Default to "Microsoft" when filter is enabled but no custom strings specified return CompanyFilterEnabled ? new[] { "Microsoft" } : Array.Empty(); } } public string SymbolCacheDirectoryPath => !string.IsNullOrEmpty(CustomSymbolCacheDirectory) ? CustomSymbolCacheDirectory : DefaultCacheDirectoryPath; public long SymbolCacheDirectorySizeMB => Utils.ComputeDirectorySize(SymbolCacheDirectoryPath) / (1024 * 1024); public string EnvironmentVarSymbolPath { get { try { return Environment.GetEnvironmentVariable(DefaultEnvironmentVarSymbolPath); } catch (Exception ex) { Trace.WriteLine($"Failed to read symbol env var: {ex.Message}"); return null; } } } public void ClearSymbolFileCache() { try { if (Directory.Exists(SymbolCacheDirectoryPath)) { Directory.Delete(SymbolCacheDirectoryPath, true); } } catch (Exception ex) { Trace.WriteLine($"Failed to empty cache dir {SymbolCacheDirectoryPath}: {ex.Message}"); } } public void AddSymbolServer(bool usePrivateServer) { string symbolServer = usePrivateServer ? DefaultPrivateSymbolServer : DefaultPublicSymbolServer; string path = $"srv*{DefaultSymbolCachePath}*{symbolServer}"; if (!SymbolPaths.Contains(path)) { SymbolPaths.Add(path); } } public bool HasSymbolPath(string path) { path = Utils.TryGetDirectoryName(path).ToLowerInvariant(); return SymbolPaths.Find(item => item.ToLowerInvariant() == path) != null; } public void InsertSymbolPath(string path) { if (string.IsNullOrEmpty(path)) { return; } foreach (string p in path.Split(";")) { string dir = Utils.TryGetDirectoryName(p); if (!string.IsNullOrEmpty(dir) && !HasSymbolPath(dir)) { SymbolPaths.Insert(0, dir); // Prepend path. } } } public void InsertSymbolPaths(IEnumerable paths) { foreach (string path in paths) { InsertSymbolPath(path); } } public SymbolFileSourceSettings WithSymbolPaths(params string[] paths) { var options = Clone(); foreach (string path in paths) { options.InsertSymbolPath(path); } return options; } public bool IsRejectedBinaryFile(BinaryFileDescriptor file) { bool isRejected = RejectPreviouslyFailedFiles && RejectedBinaryFiles.Contains(file); if (isRejected) { Trace.WriteLine($"BINARY_FILTER_DEBUG: Binary file REJECTED - Previously failed: {file?.ImageName} (path: {file?.ImagePath})"); } return isRejected; } public bool IsRejectedSymbolFile(SymbolFileDescriptor file) { bool isRejected = RejectPreviouslyFailedFiles && RejectedSymbolFiles.Contains(file); if (isRejected) { Trace.WriteLine($"DEBUG_FILTER_DEBUG: Symbol file REJECTED - Previously failed: {file?.FileName} (ID: {file?.Id}, Age: {file?.Age})"); } return isRejected; } /// /// Checks if a rejection reason represents a transient failure that should NOT be cached. /// Transient failures include auth failures, timeouts, and server errors. /// private bool IsTransientFailure(SymbolFileRejectionReason reason) { return reason == SymbolFileRejectionReason.AuthenticationFailure || reason == SymbolFileRejectionReason.NetworkTimeout || reason == SymbolFileRejectionReason.ServerError || reason == SymbolFileRejectionReason.Unknown; // Treat unknown conservatively - don't cache } /// /// Classifies a search failure based on the search log to determine if it should be cached. /// Used by both PDB and binary rejection to distinguish transient failures (timeout, auth, server errors) /// from permanent failures (404 not found). /// public SymbolFileRejectionReason ClassifySearchFailure(string searchLog) { if (DetectPrimaryServerAuthFailure(searchLog)) { return SymbolFileRejectionReason.AuthenticationFailure; } if (!string.IsNullOrEmpty(searchLog) && (searchLog.Contains("500") || searchLog.Contains("503") || searchLog.Contains("Internal Server Error", StringComparison.OrdinalIgnoreCase))) { return SymbolFileRejectionReason.ServerError; } if (!string.IsNullOrEmpty(searchLog) && (searchLog.Contains("timeout", StringComparison.OrdinalIgnoreCase) || searchLog.Contains("timed out", StringComparison.OrdinalIgnoreCase))) { return SymbolFileRejectionReason.NetworkTimeout; } if (string.IsNullOrEmpty(searchLog) || searchLog.Contains("404") || searchLog.Contains("not found", StringComparison.OrdinalIgnoreCase)) { return SymbolFileRejectionReason.PermanentNotFound; } return SymbolFileRejectionReason.Unknown; } /// /// Detects if the search log indicates a primary symbol server (symweb) authentication failure. /// public static bool DetectPrimaryServerAuthFailure(string searchLog) { if (string.IsNullOrEmpty(searchLog)) { return false; } if (!searchLog.Contains("symweb", StringComparison.OrdinalIgnoreCase)) { return false; } var authFailurePatterns = new[] { @"\b401\b", // 401 at word boundary (not in hex GUIDs like A3401B) @"\b403\b", // 403 at word boundary "Unauthorized", // HTTP 401 description "Forbidden" // HTTP 403 description }; foreach (var pattern in authFailurePatterns) { if (pattern.StartsWith(@"\b")) { if (Regex.IsMatch(searchLog, pattern)) { return true; } } else { if (searchLog.Contains(pattern, StringComparison.OrdinalIgnoreCase)) { return true; } } } return false; } /// /// Checks if a symbol file exists in the local symbol cache directories. /// Searches all paths from _NT_SYMBOL_PATH including structured (foo.pdb/GUID/foo.pdb) and flat directories. /// private bool IsSymbolFileInLocalCache(SymbolFileDescriptor file) { if (file == null || string.IsNullOrEmpty(file.FileName)) { return false; } // Check all symbol paths configured foreach (string path in SymbolPaths) { if (string.IsNullOrEmpty(path)) continue; // Skip symbol server entries (srv*) if (path.StartsWith("srv*", StringComparison.OrdinalIgnoreCase)) { // Extract local cache path from srv*C:\Symbols*https://... var parts = path.Split('*'); if (parts.Length >= 2) { string localCachePath = parts[1]; if (CheckSymbolFileInDirectory(localCachePath, file)) { return true; } } continue; } // Check regular directory paths if (CheckSymbolFileInDirectory(path, file)) { return true; } } // Check environment variable symbol paths if enabled if (UseEnvironmentVarSymbolPaths && !string.IsNullOrEmpty(EnvironmentVarSymbolPath)) { foreach (string path in EnvironmentVarSymbolPath.Split(';')) { if (string.IsNullOrEmpty(path)) continue; if (path.StartsWith("srv*", StringComparison.OrdinalIgnoreCase)) { var parts = path.Split('*'); if (parts.Length >= 2) { string localCachePath = parts[1]; if (CheckSymbolFileInDirectory(localCachePath, file)) { return true; } } } else if (CheckSymbolFileInDirectory(path, file)) { return true; } } } return false; } /// /// Checks if a symbol file exists in a specific directory, looking for both structured /// symbol server format (foo.pdb/GUID/foo.pdb) and flat format (foo.pdb). /// private bool CheckSymbolFileInDirectory(string directory, SymbolFileDescriptor file) { if (!Directory.Exists(directory)) { return false; } try { // Check structured symbol server format: basePath\fileName\GUID\fileName string structuredPath = Path.Combine(directory, file.FileName, file.Id.ToString("N").ToUpperInvariant(), file.FileName); if (File.Exists(structuredPath)) { DiagnosticLogger.LogInfo($"[NegativeCache] Found symbol file in local cache (structured): {structuredPath}"); return true; } // Check flat format: basePath\fileName string flatPath = Path.Combine(directory, file.FileName); if (File.Exists(flatPath)) { DiagnosticLogger.LogInfo($"[NegativeCache] Found symbol file in local cache (flat): {flatPath}"); return true; } } catch (Exception ex) { Trace.WriteLine($"[NegativeCache] Error checking symbol file in {directory}: {ex.Message}"); } return false; } /// /// Session-level safety check: If we have a suspicious failure rate (>80% failures with at least 10 searches), /// something is systematically wrong (network down, auth broken, etc.) and we should NOT add to negative cache. /// This prevents mass rejection when there's an infrastructure issue. /// private bool ShouldSkipNegativeCachingDueToSuspiciousFailureRate() { const int MinSearchCount = 10; const double MaxFailureRate = 0.80; // 80% if (SessionSymbolSearchCount < MinSearchCount) { return false; // Not enough data yet } double failureRate = (double)SessionSymbolFailureCount / SessionSymbolSearchCount; if (failureRate > MaxFailureRate) { DiagnosticLogger.LogWarning($"[NegativeCache] Suspicious failure rate detected: {SessionSymbolFailureCount}/{SessionSymbolSearchCount} ({failureRate:P0}) - Disabling negative caching for this session"); return true; } return false; } public bool RejectBinaryFile(BinaryFileDescriptor file, SymbolFileRejectionReason reason = SymbolFileRejectionReason.Unknown, string searchLog = null) { if (!RejectPreviouslyFailedFiles) return false; // Same safeguards as RejectSymbolFile: don't cache transient failures. if (IsTransientFailure(reason)) { DiagnosticLogger.LogInfo($"[NegativeCache] Skipping transient binary failure: {file.ImageName} - {reason}"); return false; } if (PrimaryServerAuthFailed) { DiagnosticLogger.LogWarning($"[NegativeCache] Auth failure detected - skipping binary rejection for {file.ImageName}"); return false; } if (ShouldSkipNegativeCachingDueToSuspiciousFailureRate()) { DiagnosticLogger.LogWarning($"[NegativeCache] Suspicious failure rate - skipping binary rejection"); return false; } RejectedBinaryFiles.Add(file); if (RejectedFilesCacheTime == default) { RejectedFilesCacheTime = DateTime.UtcNow; } DiagnosticLogger.LogInfo($"[NegativeCache] Added binary: {file.ImageName} - Reason: {reason}"); return true; } /// /// Attempts to add a symbol file to the negative cache (list of previously failed symbols). /// Includes multiple safeguards to prevent caching transient failures: /// - Skips transient failures (auth, timeout, server errors) /// - Skips if auth failure detected this session /// - Skips if file exists in local cache /// - Skips if suspicious failure rate detected (>80%) /// Returns true if the file was added to negative cache, false if rejected or skipped. /// public bool RejectSymbolFile(SymbolFileDescriptor file, SymbolFileRejectionReason reason = SymbolFileRejectionReason.Unknown, string searchLog = null) { if (!RejectPreviouslyFailedFiles) return false; // SAFEGUARD 1: Skip transient failures if (IsTransientFailure(reason)) { DiagnosticLogger.LogInfo($"[NegativeCache] Skipping transient failure: {file.FileName} - {reason}"); return false; } // SAFEGUARD 2: Check if auth failure detected this session if (PrimaryServerAuthFailed) { DiagnosticLogger.LogWarning($"[NegativeCache] Auth failure detected - rejecting rejection for {file.FileName}"); return false; } // SAFEGUARD 3: Check if file exists in local cache if (IsSymbolFileInLocalCache(file)) { DiagnosticLogger.LogInfo($"[NegativeCache] Symbol exists in local cache: {file.FileName}"); return false; } // SAFEGUARD 4: Session-level safety check - suspicious failure rate if (ShouldSkipNegativeCachingDueToSuspiciousFailureRate()) { DiagnosticLogger.LogWarning($"[NegativeCache] Suspicious failure rate - skipping ALL negative caching"); return false; } // All checks passed - safe to add to negative cache RejectedSymbolFiles.Add(file); if (RejectedFilesCacheTime == default) { RejectedFilesCacheTime = DateTime.UtcNow; } DiagnosticLogger.LogInfo($"[NegativeCache] Added: {file.FileName} - Reason: {reason}"); return true; } public void ClearRejectedFiles() { RejectedSymbolFiles.Clear(); RejectedBinaryFiles.Clear(); } /// /// Checks if a file path is in a Windows/Microsoft directory (likely Microsoft binary). /// Used as a heuristic when PE version info isn't available yet. /// public static bool IsWindowsSystemPath(string filePath) { if (string.IsNullOrEmpty(filePath)) { return false; } // Common Windows system paths that contain Microsoft binaries string windowsDir = Environment.GetFolderPath(Environment.SpecialFolder.Windows); string systemRoot = Environment.GetEnvironmentVariable("SystemRoot") ?? @"C:\Windows"; string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles); return filePath.StartsWith(windowsDir, StringComparison.OrdinalIgnoreCase) || filePath.StartsWith(systemRoot, StringComparison.OrdinalIgnoreCase) || filePath.StartsWith(@"C:\Windows", StringComparison.OrdinalIgnoreCase) || filePath.StartsWith(@"\SystemRoot", StringComparison.OrdinalIgnoreCase) || filePath.Contains(@"\Windows\System32\", StringComparison.OrdinalIgnoreCase) || filePath.Contains(@"\Windows\SysWOW64\", StringComparison.OrdinalIgnoreCase) || filePath.Contains(@"\Windows\WinSxS\", StringComparison.OrdinalIgnoreCase) || // WindowsApps contains Microsoft Store apps and system components filePath.Contains(@"\WindowsApps\", StringComparison.OrdinalIgnoreCase) || filePath.Contains(@"\Program Files\WindowsApps\", StringComparison.OrdinalIgnoreCase) || // Device paths from ETW traces (e.g., \Device\HarddiskVolume2\Windows\...) (filePath.StartsWith(@"\Device\", StringComparison.OrdinalIgnoreCase) && (filePath.Contains(@"\Windows\", StringComparison.OrdinalIgnoreCase) || filePath.Contains(@"\WindowsApps\", StringComparison.OrdinalIgnoreCase))) || // Microsoft.* and CoreMessaging* DLLs are typically Microsoft binaries regardless of path System.IO.Path.GetFileName(filePath).StartsWith("Microsoft.", StringComparison.OrdinalIgnoreCase) || System.IO.Path.GetFileName(filePath).StartsWith("CoreMessaging", StringComparison.OrdinalIgnoreCase); } public void ExpandSymbolPathsSubdirectories(string[] symbolExtensions) { // For symbol paths that are local directories, add any subdirectory // that also contains symbols to the path list, otherwise the symbol reader // will not find them since it doesn't search rerursively. var symbolPathSet = new HashSet(); foreach (string path in SymbolPaths) { symbolPathSet.Add(path); if (path.StartsWith("srv*", StringComparison.OrdinalIgnoreCase)) { continue; // Skip over symbol servers. } //? TODO: Option for max level BuildSymbolsDirectoriesSet(path, symbolPathSet, symbolExtensions, 0, 3); } SymbolPaths = symbolPathSet.ToList(); } private void BuildSymbolsDirectoriesSet(string path, HashSet symbolDirs, string[] symbolExtensions, int level = 0, int maxLevel = 0) { if (!Directory.Exists(path) || level > maxLevel) { return; } try { if (level == 0) { // Check the drive type for the top-level directory // and accept only local paths (exclude mapped network paths). var driveInfo = new DriveInfo(path); if (driveInfo.DriveType != DriveType.Fixed) { return; } } foreach (string file in Directory.EnumerateFileSystemEntries(path)) { if (File.GetAttributes(file).HasFlag(FileAttributes.Directory)) { BuildSymbolsDirectoriesSet(file, symbolDirs, symbolExtensions, level + 1, maxLevel); } else if (level > 0) { // Top-level directory already included in set, // check files only for subdirectories. string extension = Path.GetExtension(file); foreach (string symbolExt in symbolExtensions) { if (extension.Equals(symbolExt, StringComparison.OrdinalIgnoreCase)) { symbolDirs.Add(path); break; } } } } } catch (Exception ex) { Trace.WriteLine($"Failed to expand symbols dir set: {ex.Message}"); } } public static bool ShouldUsePrivateSymbolPath() { // Try to detect running as a domain-joined or AAD-joined account, // which should have access to a private, internal symbol server. // Based on https://stackoverflow.com/questions/926227/how-to-detect-if-machine-is-joined-to-domain // try { // string domain = IPGlobalProperties.GetIPGlobalProperties().DomainName; // // if (domain != null && // domain.Contains("DOMANIN_NAME", StringComparison.OrdinalIgnoreCase)) { // Trace.WriteLine("Set symbol path for domain-joined machine"); // return true; // } // } // catch (Exception ex) { // } try { string pcszTenantId = null; IntPtr ptrJoinInfo = IntPtr.Zero; IntPtr ptrUserInfo = IntPtr.Zero; IntPtr ptrJoinCertificate = IntPtr.Zero; var joinInfo = new NetAPI32.DSREG_JOIN_INFO(); NetAPI32.NetFreeAadJoinInformation(IntPtr.Zero); int retValue = NetAPI32.NetGetAadJoinInformation(pcszTenantId, out ptrJoinInfo); if (retValue == 0) { var ptrJoinInfoObject = new NetAPI32.DSREG_JOIN_INFO(); joinInfo = (NetAPI32.DSREG_JOIN_INFO)Marshal.PtrToStructure(ptrJoinInfo, (Type)ptrJoinInfoObject.GetType()); if (joinInfo.JoinUserEmail.Contains("@microsoft.com", StringComparison.OrdinalIgnoreCase) || joinInfo.TenantDisplayName.Contains("microsoft", StringComparison.OrdinalIgnoreCase)) { Trace.WriteLine("Set symbol path for AAD-joined machine"); return true; } } } catch (Exception ex) { } Trace.WriteLine("Set symbol path for non-domain-joined machine"); return false; } public override void Reset() { InitializeReferenceMembers(); ResetAllOptions(this); if (ShouldUsePrivateSymbolPath()) { AddSymbolServer(usePrivateServer: true); } AddSymbolServer(usePrivateServer: false); // Default company filter to "Microsoft" since the tool is primarily for Microsoft code. // Users can modify this in the UI settings. if (CompanyFilterStrings.Count == 0) { CompanyFilterStrings.Add("Microsoft"); } } public SymbolFileSourceSettings Clone() { byte[] serialized = StateSerializer.Serialize(this); return StateSerializer.Deserialize(serialized); } [ProtoAfterDeserialization] private void InitializeReferenceMembers() { InitializeReferenceOptions(this); // Migrate old settings: ensure negative caching is enabled by default. // Old settings may have this as false before the feature was fully implemented. if (!RejectPreviouslyFailedFiles) { RejectPreviouslyFailedFiles = true; } // Check if rejected files cache has expired (default 3 days). // This allows retrying symbols that may have become available. int expirationDays = RejectedFilesCacheExpirationDays > 0 ? RejectedFilesCacheExpirationDays : 3; if (RejectedFilesCacheTime != default && DateTime.UtcNow - RejectedFilesCacheTime > TimeSpan.FromDays(expirationDays)) { Trace.WriteLine($"[SymbolSettings] Rejected files cache expired (>{expirationDays} days old), clearing {RejectedBinaryFiles?.Count ?? 0} binaries and {RejectedSymbolFiles?.Count ?? 0} symbols"); ClearRejectedFiles(); RejectedFilesCacheTime = DateTime.UtcNow; } // TODO: TEMPORARY - clear negative cache for testing. Remove this after testing. // Trace.WriteLine($"[SymbolSettings] TEMP: Clearing negative cache for testing ({RejectedBinaryFiles?.Count ?? 0} binaries, {RejectedSymbolFiles?.Count ?? 0} symbols)"); // ClearRejectedFiles(); // RejectedFilesCacheTime = DateTime.UtcNow; } public override bool Equals(object obj) { return AreOptionsEqual(this, obj); } public override string ToString() { return PrintOptions(this); } private class NetAPI32 { [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern void NetFreeAadJoinInformation( IntPtr pJoinInfo); [DllImport("netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int NetGetAadJoinInformation( string pcszTenantId, out IntPtr ppJoinInfo); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct DSREG_JOIN_INFO { public int joinType; public IntPtr pJoinCertificate; [MarshalAs(UnmanagedType.LPWStr)] public string DeviceId; [MarshalAs(UnmanagedType.LPWStr)] public string IdpDomain; [MarshalAs(UnmanagedType.LPWStr)] public string TenantId; [MarshalAs(UnmanagedType.LPWStr)] public string JoinUserEmail; [MarshalAs(UnmanagedType.LPWStr)] public string TenantDisplayName; [MarshalAs(UnmanagedType.LPWStr)] public string MdmEnrollmentUrl; [MarshalAs(UnmanagedType.LPWStr)] public string MdmTermsOfUseUrl; [MarshalAs(UnmanagedType.LPWStr)] public string MdmComplianceUrl; [MarshalAs(UnmanagedType.LPWStr)] public string UserSettingSyncUrl; public IntPtr pUserInfo; } } } ================================================ FILE: src/ProfileExplorerCore/SourceParser/SourceCodeParser.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security; using ProfileExplorer.Core.SourceParser; namespace ProfileExplorer.Core.SourceParser; public enum SourceCodeLanguage { Cpp, CSharp, Rust } public class SourceCodeParser { private const int ParsingTimeoutSeconds = 3; private SourceCodeLanguage language_; public SourceCodeParser(SourceCodeLanguage language = SourceCodeLanguage.Cpp) { language_ = language; } [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter-cpp.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr tree_sitter_cpp(); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter-c-sharp.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr tree_sitter_c_sharp(); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter-rust.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr tree_sitter_rust(); private TSLanguage InitializeParserLanguage(SourceCodeLanguage language) { switch (language) { case SourceCodeLanguage.Cpp: return new TSLanguage(tree_sitter_cpp()); case SourceCodeLanguage.CSharp: return new TSLanguage(tree_sitter_c_sharp()); case SourceCodeLanguage.Rust: return new TSLanguage(tree_sitter_rust()); default: throw new InvalidOperationException(); } } public SourceSyntaxTree Parse(ReadOnlyMemory text) { return Parse(text.ToString()); } public SourceSyntaxTree Parse(string text) { SourceSyntaxTree tree = null; try { // Initialize parser. using var parser = new TSParser(); parser.set_timeout_micros((ulong)TimeSpan.FromSeconds(ParsingTimeoutSeconds).TotalMicroseconds); using var language = InitializeParserLanguage(language_); parser.set_language(language); // Try to parse the text. using var parsedTree = parser.parse_string(null, text); if (parsedTree == null) { Trace.WriteLine($"Failed to parse the source code text using tree-sitter."); return null; } // Walked the parse tree and build a reduced syntax tree // of the main statement and expression nodes. tree = new SourceSyntaxTree(); using var cursor = new TSCursor(parsedTree.root_node(), language); foreach (var node in WalkTreeNodes(cursor)) { // #if DEBUG // int so = (int)cursor.current_node().start_offset(); // int eo = (int)cursor.current_node().end_offset(); // int sl = (int)cursor.current_node().start_point().row + 1; // int el = (int)cursor.current_node().end_point().row + 1; // var type = node.type(); // var sym = node.symbol(); // Trace.WriteLine($" - node type is {type}, startL {sl}, endL {el}"); // #endif bool accepted = true; var nodeKind = SourceSyntaxNodeKind.Other; switch (node.type()) { case "if_statement": case "if_expression": { // Rust nodeKind = SourceSyntaxNodeKind.If; break; } case "condition_clause": { nodeKind = SourceSyntaxNodeKind.Condition; break; } case "else_clause": { nodeKind = SourceSyntaxNodeKind.Else; break; } case "for_statement": case "for_range_loop": case "for_each_statement": // C# case "for_expression": { // Rust nodeKind = SourceSyntaxNodeKind.Loop; break; } case "while_statement": case "do_statement": { nodeKind = SourceSyntaxNodeKind.Loop; break; } case "switch_statement": case "match_expression": { // Rust nodeKind = SourceSyntaxNodeKind.Switch; break; } case "case_statement": case "switch_section": // C# case "match_arm": { // Rust nodeKind = SourceSyntaxNodeKind.SwitchCase; break; } case "compound_statement": case "block": { // C# nodeKind = SourceSyntaxNodeKind.Compound; break; } case "function_definition": case "method_declaration": // C# case "local_function_statement": // C# case "function_item": { // Rust nodeKind = SourceSyntaxNodeKind.Function; break; } case "call_expression": case "macro_invocation": { // Rust nodeKind = SourceSyntaxNodeKind.Call; break; } case "translation_unit": case "source_file": { // Rust nodeKind = SourceSyntaxNodeKind.Root; break; } default: { accepted = false; break; } } if (tree.RootNode == null || accepted) { var treeNode = tree.GetOrCreateNode(node.id.ToInt64()); int startOffset = (int)cursor.current_node().start_offset(); int endOffset = (int)cursor.current_node().end_offset(); int startLine = (int)cursor.current_node().start_point().row + 1; int endLine = (int)cursor.current_node().end_point().row + 1; treeNode.Kind = nodeKind; treeNode.Start = new TextLocation(startOffset, startLine, 0); treeNode.End = new TextLocation(endOffset, endLine, 0); if (tree.RootNode == null) { tree.RootNode = treeNode; } else if (nodeKind == SourceSyntaxNodeKind.Function) { // Add all functions to the root node even if inide a class, // to make it easier to find a function by line. tree.RootNode.AddChild(treeNode); } else { // Because not all nodes are created in the reduce syntax tree, // look up for first ancestor node that is added and use it as parent. var parentNode = node.parent(); while (parentNode.id != IntPtr.Zero) { var parentTreeNode = tree.GetNode(parentNode.id.ToInt64()); if (parentTreeNode != null) { parentTreeNode.AddChild(treeNode); break; } parentNode = parentNode.parent(); } } } } } catch (Exception ex) { Trace.WriteLine($"Exception parsing the source code text using tree-sitter: {ex.Message}"); } return tree; } private IEnumerable WalkTreeNodes(TSCursor rootNode) { // Preorder traversal of the syntax tree, without using recursion. var cursor = rootNode; bool reachedRoot = false; while (!reachedRoot) { yield return cursor.current_node(); if (cursor.current_node().child_count() > 0 && cursor.goto_first_child()) { continue; } if (cursor.current_node().next_sibling().id != IntPtr.Zero && cursor.goto_next_sibling()) { continue; } bool retracting = true; while (retracting) { if (!cursor.goto_parent()) { retracting = false; reachedRoot = true; } if (cursor.current_node().next_sibling().id != IntPtr.Zero && cursor.goto_next_sibling()) { retracting = false; } } } } } ================================================ FILE: src/ProfileExplorerCore/SourceParser/SourceSyntaxTree.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; namespace ProfileExplorer.Core.SourceParser; public enum SourceSyntaxNodeKind { Root, Function, If, Else, ElseIf, Loop, Switch, SwitchCase, Compound, Condition, Call, Other } public class SourceSyntaxNode { public SourceSyntaxNode(SourceSyntaxNodeKind kind = SourceSyntaxNodeKind.Other) { Kind = kind; } public SourceSyntaxNodeKind Kind { get; set; } public SourceSyntaxNode ParentNode { get; set; } public List ChildNodes { get; set; } public TextLocation Start { get; set; } public TextLocation End { get; set; } public object Tag { get; set; } public int Length => End.Offset - Start.Offset; public bool SpansMultipleLines => End.Line != Start.Line; public bool HasChildren => ChildNodes is {Count: > 0}; public void AddChild(SourceSyntaxNode node) { ChildNodes ??= new List(); ChildNodes.Add(node); node.ParentNode = this; } public SourceSyntaxNode GetChildOfKind(SourceSyntaxNodeKind kind) { if (ChildNodes != null) { foreach (var child in ChildNodes) { if (child.Kind == kind) { return child; } } } return null; } public string GetText(ReadOnlyMemory text) { if (text.Length > 0 && End.Offset < text.Length) { return text.Slice(Start.Offset, Length).ToString(); } return null; } public void WalkNodes(Func action, SourceSyntaxNodeKind kindFilter = SourceSyntaxNodeKind.Other) { WalkNodes(this, action, kindFilter); } private bool WalkNodes(SourceSyntaxNode node, Func action, SourceSyntaxNodeKind kindFilter = SourceSyntaxNodeKind.Other, int depth = 0) { // Do a pre-order traversal of the tree. if (node.Kind == kindFilter || kindFilter == SourceSyntaxNodeKind.Other) { if (!action(node, depth)) { return false; } } if (node.HasChildren) { foreach (var childNode in node.ChildNodes) { if (!WalkNodes(childNode, action, kindFilter, depth + 1)) { return false; } } } return true; } public string Print() { var sb = new StringBuilder(); Print(sb, 0); return sb.ToString(); } public void Print(StringBuilder sb, int level) { sb.Append(new string('\t', level)); sb.AppendLine($"Kind: {Kind}, Start: {Start}, End: {End}"); if (ChildNodes != null) { foreach (var child in ChildNodes) { child.Print(sb, level + 1); } } } } public class SourceSyntaxTree { private Dictionary nodeMap_; public SourceSyntaxTree() { nodeMap_ = new Dictionary(); } public SourceSyntaxNode RootNode { get; set; } public SourceSyntaxNode GetOrCreateNode(long id) { if (!nodeMap_.TryGetValue(id, out var node)) { node = new SourceSyntaxNode(); nodeMap_[id] = node; } return node; } public SourceSyntaxNode GetNode(long id) { return nodeMap_.GetValueOrDefault(id); } public SourceSyntaxNode FindFunctionNode(int startLine) { if (RootNode is not {HasChildren: true}) { return null; } foreach (var node in RootNode.ChildNodes) { if (node.Kind == SourceSyntaxNodeKind.Function) { if (Math.Abs(node.Start.Line - startLine) <= 1) { return node; } // Check the compound node of the function, // the start line in debug info is usually this line. var childNode = node.GetChildOfKind(SourceSyntaxNodeKind.Compound); if (childNode != null && Math.Abs(childNode.Start.Line - startLine) <= 1) { return node; } } } return null; } public string Print() { var sb = new StringBuilder(); RootNode?.Print(sb, 0); return sb.ToString(); } } ================================================ FILE: src/ProfileExplorerCore/SourceParser/TreeSitter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. ////////////////////////////////////////////////////////////////////////////// // // Module Name: // binding.cs // // Abstract: // Wrapper for GitHub Tree-Sitter Library. // using System; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Security; namespace ProfileExplorer.Core.SourceParser; public enum TSInputEncoding { TSInputEncodingUTF8, TSInputEncodingUTF16 } public enum TSSymbolType { TSSymbolTypeRegular, TSSymbolTypeAnonymous, TSSymbolTypeAuxiliary } public enum TSLogType { TSLogTypeParse, TSLogTypeLex } public enum TSQuantifier { TSQuantifierZero = 0, // must match the array initialization value TSQuantifierZeroOrOne, TSQuantifierZeroOrMore, TSQuantifierOne, TSQuantifierOneOrMore } public enum TSQueryPredicateStepType { TSQueryPredicateStepTypeDone, TSQueryPredicateStepTypeCapture, TSQueryPredicateStepTypeString } public enum TSQueryError { TSQueryErrorNone = 0, TSQueryErrorSyntax, TSQueryErrorNodeType, TSQueryErrorField, TSQueryErrorCapture, TSQueryErrorStructure, TSQueryErrorLanguage } [StructLayout(LayoutKind.Sequential)] public struct TSPoint { public uint row; public uint column; public TSPoint(uint row, uint column) { this.row = row; this.column = column; } } [StructLayout(LayoutKind.Sequential)] public struct TSRange { public TSPoint start_point; public TSPoint end_point; public uint start_byte; public uint end_byte; } [StructLayout(LayoutKind.Sequential)] public struct TSInputEdit { public uint start_byte; public uint old_end_byte; public uint new_end_byte; public TSPoint start_point; public TSPoint old_end_point; public TSPoint new_end_point; } [StructLayout(LayoutKind.Sequential)] public struct TSQueryCapture { public TSNode node; public uint index; } [StructLayout(LayoutKind.Sequential)] public struct TSQueryMatch { public uint id; public ushort pattern_index; public ushort capture_count; public IntPtr captures; } [StructLayout(LayoutKind.Sequential)] public struct TSQueryPredicateStep { public TSQueryPredicateStepType type; public uint value_id; } public delegate void TSLogger(TSLogType logType, string message); /********************/ /* Section - Parser */ /********************/ public sealed class TSParser : IDisposable { public TSParser() { Ptr = ts_parser_new(); } private IntPtr Ptr { get; set; } public void Dispose() { if (Ptr != IntPtr.Zero) { ts_parser_delete(Ptr); Ptr = IntPtr.Zero; } } public bool set_language(TSLanguage language) { return ts_parser_set_language(Ptr, language.Ptr); } public TSLanguage language() { IntPtr ptr = ts_parser_language(Ptr); return ptr != IntPtr.Zero ? new TSLanguage(ptr) : null; } public bool set_included_ranges(TSRange[] ranges) { return ts_parser_set_included_ranges(Ptr, ranges, (uint)ranges.Length); } public TSRange[] included_ranges() { uint length; return ts_parser_included_ranges(Ptr, out length); } public TSTree parse_string(TSTree oldTree, string input) { IntPtr ptr = ts_parser_parse_string_encoding(Ptr, oldTree != null ? oldTree.Ptr : IntPtr.Zero, input, (uint)input.Length * 2, TSInputEncoding.TSInputEncodingUTF16); return ptr != IntPtr.Zero ? new TSTree(ptr) : null; } public void reset() { ts_parser_reset(Ptr); } public void set_timeout_micros(ulong timeout) { ts_parser_set_timeout_micros(Ptr, timeout); } public ulong timeout_micros() { return ts_parser_timeout_micros(Ptr); } public void set_logger(TSLogger logger) { var code = new _TSLoggerCode(logger); var data = new _TSLoggerData {Log = logger != null ? new TSLogCallback(code.LogCallback) : null}; ts_parser_set_logger(Ptr, data); } [StructLayout(LayoutKind.Sequential)] private struct _TSLoggerData { private IntPtr Payload; internal TSLogCallback Log; } [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void TSLogCallback(IntPtr payload, TSLogType logType, [MarshalAs(UnmanagedType.LPUTF8Str)] string message); private class _TSLoggerCode { private TSLogger logger; internal _TSLoggerCode(TSLogger logger) { this.logger = logger; } internal void LogCallback(IntPtr payload, TSLogType logType, string message) { logger(logType, message); } } #region PInvoke [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter-cpp.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr tree_sitter_cpp(); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter-c-sharp.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr tree_sitter_c_sharp(); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter-rust.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr tree_sitter_rust(); /** * Create a new parser. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_parser_new(); /** * Delete the parser, freeing all of the memory that it used. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_parser_delete(IntPtr parser); /** * Set the language that the parser should use for parsing. * * Returns a boolean indicating whether or not the language was successfully * assigned. True means assignment succeeded. False means there was a version * mismatch: the language was generated with an incompatible version of the * Tree-sitter CLI. Check the language's version using `ts_language_version` * and compare it to this library's `TREE_SITTER_LANGUAGE_VERSION` and * `TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION` constants. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] private static extern bool ts_parser_set_language(IntPtr parser, IntPtr language); /** * Get the parser's current language. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_parser_language(IntPtr parser); /** * Set the ranges of text that the parser should include when parsing. * * By default, the parser will always include entire documents. This function * allows you to parse only a *portion* of a document but still return a syntax * tree whose ranges match up with the document as a whole. You can also pass * multiple disjoint ranges. * * The second and third parameters specify the location and length of an array * of ranges. The parser does *not* take ownership of these ranges; it copies * the data, so it doesn't matter how these ranges are allocated. * * If `length` is zero, then the entire document will be parsed. Otherwise, * the given ranges must be ordered from earliest to latest in the document, * and they must not overlap. That is, the following must hold for all * `i` < `length - 1`: ranges[i].end_byte <= ranges[i + 1].start_byte * * If this requirement is not satisfied, the operation will fail, the ranges * will not be assigned, and this function will return `false`. On success, * this function returns `true` */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] //[return: MarshalAs(UnmanagedType.I1)] private static extern bool ts_parser_set_included_ranges(IntPtr parser, [In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] TSRange[] ranges, uint length); /** * Get the ranges of text that the parser will include when parsing. * * The returned pointer is owned by the parser. The caller should not free it * or write to it. The length of the array will be written to the given * `length` pointer. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] private static extern TSRange[] ts_parser_included_ranges(IntPtr parser, out uint length); /** * Use the parser to parse some source code stored in one contiguous buffer. * The first two parameters are the same as in the `ts_parser_parse` function * above. The second two parameters indicate the location of the buffer and its * length in bytes. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_parser_parse_string(IntPtr parser, IntPtr oldTree, [MarshalAs(UnmanagedType.LPUTF8Str)] string input, uint length); /** * Use the parser to parse some source code stored in one contiguous buffer. * The first two parameters are the same as in the `ts_parser_parse` function * above. The second two parameters indicate the location of the buffer and its * length in bytes. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] //private static extern IntPtr ts_parser_parse_string_encoding(IntPtr parser, IntPtr oldTree, [MarshalAs(UnmanagedType.LPUTF8Str)] string input, uint length, TSInputEncoding encoding); private static extern IntPtr ts_parser_parse_string_encoding(IntPtr parser, IntPtr oldTree, [MarshalAs(UnmanagedType.LPWStr)] string input, uint length, TSInputEncoding encoding); /** * Instruct the parser to start the next parse from the beginning. * * If the parser previously failed because of a timeout or a cancellation, then * by default, it will resume where it left off on the next call to * `ts_parser_parse` or other parsing functions. If you don't want to resume, * and instead intend to use this parser to parse some other document, you must * call `ts_parser_reset` first. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_parser_reset(IntPtr parser); /** * Set the maximum duration in microseconds that parsing should be allowed to * take before halting. * * If parsing takes longer than this, it will halt early, returning NULL. * See `ts_parser_parse` for more information. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_parser_set_timeout_micros(IntPtr parser, ulong timeout); /** * Get the duration in microseconds that parsing is allowed to take. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern ulong ts_parser_timeout_micros(IntPtr parser); /** * Set the parser's current cancellation flag pointer. * * If a non-null pointer is assigned, then the parser will periodically read * from this pointer during parsing. If it reads a non-zero value, it will * halt early, returning NULL. See `ts_parser_parse` for more information. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_parser_set_cancellation_flag(IntPtr parser, ref IntPtr flag); /** * Get the parser's current cancellation flag pointer. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_parser_cancellation_flag(IntPtr parser); /** * Set the logger that a parser should use during parsing. * * The parser does not take ownership over the logger payload. If a logger was * previously assigned, the caller is responsible for releasing any memory * owned by the previous logger. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_parser_set_logger(IntPtr parser, _TSLoggerData logger); #endregion } /******************/ /* Section - Tree */ /******************/ public sealed class TSTree : IDisposable { public TSTree(IntPtr ptr) { Ptr = ptr; } internal IntPtr Ptr { get; private set; } public void Dispose() { if (Ptr != IntPtr.Zero) { ts_tree_delete(Ptr); Ptr = IntPtr.Zero; } } public TSTree copy() { IntPtr ptr = ts_tree_copy(Ptr); return ptr != IntPtr.Zero ? new TSTree(ptr) : null; } public TSNode root_node() { return ts_tree_root_node(Ptr); } public TSNode root_node_with_offset(uint offsetBytes, TSPoint offsetPoint) { return ts_tree_root_node_with_offset(Ptr, offsetBytes, offsetPoint); } public TSLanguage language() { IntPtr ptr = ts_tree_language(Ptr); return ptr != IntPtr.Zero ? new TSLanguage(ptr) : null; } public void edit(TSInputEdit edit) { ts_tree_edit(Ptr, ref edit); } #region PInvoke /** * Create a shallow copy of the syntax tree. This is very fast. * * You need to copy a syntax tree in order to use it on more than one thread at * a time, as syntax trees are not thread safe. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_tree_copy(IntPtr tree); /** * Delete the syntax tree, freeing all of the memory that it used. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_tree_delete(IntPtr tree); /** * Get the root node of the syntax tree. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_tree_root_node(IntPtr tree); /** * Get the root node of the syntax tree, but with its position * shifted forward by the given offset. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_tree_root_node_with_offset(IntPtr tree, uint offsetBytes, TSPoint offsetPoint); /** * Get the language that was used to parse the syntax tree. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_tree_language(IntPtr tree); /** * Get the array of included ranges that was used to parse the syntax tree. * * The returned pointer must be freed by the caller. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_tree_included_ranges(IntPtr tree, out uint length); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_tree_included_ranges_free(IntPtr ranges); /** * Edit the syntax tree to keep it in sync with source code that has been * edited. * * You must describe the edit both in terms of byte offsets and in terms of * (row, column) coordinates. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_tree_edit(IntPtr tree, ref TSInputEdit edit); /** * Compare an old edited syntax tree to a new syntax tree representing the same * document, returning an array of ranges whose syntactic structure has changed. * * For this to work correctly, the old syntax tree must have been edited such * that its ranges match up to the new tree. Generally, you'll want to call * this function right after calling one of the `ts_parser_parse` functions. * You need to pass the old tree that was passed to parse, as well as the new * tree that was returned from that function. * * The returned array is allocated using `malloc` and the caller is responsible * for freeing it using `free`. The length of the array will be written to the * given `length` pointer. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_tree_get_changed_ranges(IntPtr old_tree, IntPtr new_tree, out uint length); #endregion } /******************/ /* Section - Node */ /******************/ [StructLayout(LayoutKind.Sequential)] public struct TSNode { private uint context0; private uint context1; private uint context2; private uint context3; public IntPtr id; private IntPtr tree; public void clear() { id = IntPtr.Zero; tree = IntPtr.Zero; } public bool is_zero() { return id == IntPtr.Zero && tree == IntPtr.Zero; } public string type() { return Marshal.PtrToStringAnsi(ts_node_type(this)); } public string type(TSLanguage lang) { return lang.symbol_name(symbol()); } public ushort symbol() { return ts_node_symbol(this); } public uint start_offset() { return ts_node_start_byte(this) / sizeof(ushort); } public TSPoint start_point() { var pt = ts_node_start_point(this); return new TSPoint(pt.row, pt.column / sizeof(ushort)); } public uint end_offset() { return ts_node_end_byte(this) / sizeof(ushort); } public TSPoint end_point() { var pt = ts_node_end_point(this); return new TSPoint(pt.row, pt.column / sizeof(ushort)); } public string to_string() { IntPtr dat = ts_node_string(this); string str = Marshal.PtrToStringAnsi(dat); ts_node_string_free(dat); return str; } public bool is_null() { return ts_node_is_null(this); } public bool is_named() { return ts_node_is_named(this); } public bool is_missing() { return ts_node_is_missing(this); } public bool is_extra() { return ts_node_is_extra(this); } public bool has_changes() { return ts_node_has_changes(this); } public bool has_error() { return ts_node_has_error(this); } public TSNode parent() { return ts_node_parent(this); } public TSNode child(uint index) { return ts_node_child(this, index); } public IntPtr field_name_for_child(uint index) { return ts_node_field_name_for_child(this, index); } public uint child_count() { return ts_node_child_count(this); } public TSNode named_child(uint index) { return ts_node_named_child(this, index); } public uint named_child_count() { return ts_node_named_child_count(this); } public TSNode child_by_field_name(string field_name) { return ts_node_child_by_field_name(this, field_name, (uint)field_name.Length); } public TSNode child_by_field_id(ushort fieldId) { return ts_node_child_by_field_id(this, fieldId); } public TSNode next_sibling() { return ts_node_next_sibling(this); } public TSNode prev_sibling() { return ts_node_prev_sibling(this); } public TSNode next_named_sibling() { return ts_node_next_named_sibling(this); } public TSNode prev_named_sibling() { return ts_node_prev_named_sibling(this); } public TSNode first_child_for_offset(uint offset) { return ts_node_first_child_for_byte(this, offset * sizeof(ushort)); } public TSNode first_named_child_for_offset(uint offset) { return ts_node_first_named_child_for_byte(this, offset * sizeof(ushort)); } public TSNode descendant_for_offset_range(uint start, uint end) { return ts_node_descendant_for_byte_range(this, start * sizeof(ushort), end * sizeof(ushort)); } public TSNode descendant_for_point_range(TSPoint start, TSPoint end) { return ts_node_descendant_for_point_range(this, start, end); } public TSNode named_descendant_for_offset_range(uint start, uint end) { return ts_node_named_descendant_for_byte_range(this, start * sizeof(ushort), end * sizeof(ushort)); } public TSNode named_descendant_for_point_range(TSPoint start, TSPoint end) { return ts_node_named_descendant_for_point_range(this, start, end); } public bool eq(TSNode other) { return ts_node_eq(this, other); } public string text(string data) { uint beg = start_offset(); uint end = end_offset(); return data.Substring((int)beg, (int)(end - beg)); } #region PInvoke /** * Get the node's type as a null-terminated string. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_node_type(TSNode node); /** * Get the node's type as a numerical id. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern ushort ts_node_symbol(TSNode node); /** * Get the node's start byte. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_node_start_byte(TSNode node); /** * Get the node's start position in terms of rows and columns. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSPoint ts_node_start_point(TSNode node); /** * Get the node's end byte. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_node_end_byte(TSNode node); /** * Get the node's end position in terms of rows and columns. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSPoint ts_node_end_point(TSNode node); /** * Get an S-expression representing the node as a string. * * This string is allocated with `malloc` and the caller is responsible for * freeing it using `free`. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_node_string(TSNode node); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_node_string_free(IntPtr str); /** * Check if the node is null. Functions like `ts_node_child` and * `ts_node_next_sibling` will return a null node to indicate that no such node * was found. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_is_null(TSNode node); /** * Check if the node is *named*. Named nodes correspond to named rules in the * grammar, whereas *anonymous* nodes correspond to string literals in the * grammar. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_is_named(TSNode node); /** * Check if the node is *missing*. Missing nodes are inserted by the parser in * order to recover from certain kinds of syntax errors. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_is_missing(TSNode node); /** * Check if the node is *extra*. Extra nodes represent things like comments, * which are not required the grammar, but can appear anywhere. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_is_extra(TSNode node); /** * Check if a syntax node has been edited. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_has_changes(TSNode node); /** * Check if the node is a syntax error or contains any syntax errors. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_has_error(TSNode node); /** * Get the node's immediate parent. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_parent(TSNode node); /** * Get the node's child at the given index, where zero represents the first * child. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_child(TSNode node, uint index); /** * Get the field name for node's child at the given index, where zero represents * the first child. Returns NULL, if no field is found. */ [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_node_field_name_for_child(TSNode node, uint index); /** * Get the node's number of children. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_node_child_count(TSNode node); /** * Get the node's number of *named* children. * * See also `ts_node_is_named`. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_named_child(TSNode node, uint index); /** * Get the node's number of *named* children. * * See also `ts_node_is_named`. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_node_named_child_count(TSNode node); /** * Get the node's child with the given numerical field id. * * You can convert a field name to an id using the * `ts_language_field_id_for_name` function. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_child_by_field_name(TSNode self, [MarshalAs(UnmanagedType.LPUTF8Str)] string field_name, uint field_name_length); /** * Get the node's child with the given numerical field id. * * You can convert a field name to an id using the * `ts_language_field_id_for_name` function. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_child_by_field_id(TSNode self, ushort fieldId); /** * Get the node's next / previous sibling. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_next_sibling(TSNode self); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_prev_sibling(TSNode self); /** * Get the node's next / previous *named* sibling. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_next_named_sibling(TSNode self); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_prev_named_sibling(TSNode self); /** * Get the node's first child that extends beyond the given byte offset. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_first_child_for_byte(TSNode self, uint byteOffset); /** * Get the node's first named child that extends beyond the given byte offset. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_first_named_child_for_byte(TSNode self, uint byteOffset); /** * Get the smallest node within this node that spans the given range of bytes * or (row, column) positions. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_descendant_for_byte_range(TSNode self, uint startByte, uint endByte); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_descendant_for_point_range(TSNode self, TSPoint startPoint, TSPoint endPoint); /** * Get the smallest named node within this node that spans the given range of * bytes or (row, column) positions. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_named_descendant_for_byte_range(TSNode self, uint startByte, uint endByte); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_node_named_descendant_for_point_range(TSNode self, TSPoint startPoint, TSPoint endPoint); /** * Check if two nodes are identical. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_node_eq(TSNode node1, TSNode node2); #endregion } /************************/ /* Section - TreeCursor */ /************************/ public sealed class TSCursor : IDisposable { private IntPtr Ptr; private TSTreeCursor cursor; public TSCursor(TSTreeCursor cursor, TSLanguage lang) { this.cursor = cursor; this.lang = lang; Ptr = new IntPtr(1); } public TSCursor(TSNode node, TSLanguage lang) { cursor = ts_tree_cursor_new(node); this.lang = lang; Ptr = new IntPtr(1); } public TSLanguage lang { get; private set; } public void Dispose() { if (Ptr != IntPtr.Zero) { ts_tree_cursor_delete(ref cursor); Ptr = IntPtr.Zero; } } public void reset(TSNode node) { ts_tree_cursor_reset(ref cursor, node); } public TSNode current_node() { return ts_tree_cursor_current_node(ref cursor); } public string current_field() { return lang.fields[current_field_id()]; } public string current_symbol() { ushort symbol = ts_tree_cursor_current_node(ref cursor).symbol(); return symbol != ushort.MaxValue ? lang.symbols[symbol] : "ERROR"; } public ushort current_field_id() { return ts_tree_cursor_current_field_id(ref cursor); } public bool goto_parent() { return ts_tree_cursor_goto_parent(ref cursor); } public bool goto_next_sibling() { return ts_tree_cursor_goto_next_sibling(ref cursor); } public bool goto_first_child() { return ts_tree_cursor_goto_first_child(ref cursor); } public long goto_first_child_for_offset(uint offset) { return ts_tree_cursor_goto_first_child_for_byte(ref cursor, offset * sizeof(ushort)); } public long goto_first_child_for_point(TSPoint point) { return ts_tree_cursor_goto_first_child_for_point(ref cursor, point); } public TSCursor copy() { return new TSCursor(ts_tree_cursor_copy(ref cursor), lang); } [StructLayout(LayoutKind.Sequential)] public struct TSTreeCursor { private IntPtr Tree; private IntPtr Id; private uint Context0; private uint Context1; } #region PInvoke /** * Create a new tree cursor starting from the given node. * * A tree cursor allows you to walk a syntax tree more efficiently than is * possible using the `TSNode` functions. It is a mutable object that is always * on a certain syntax node, and can be moved imperatively to different nodes. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSTreeCursor ts_tree_cursor_new(TSNode node); /** * Delete a tree cursor, freeing all of the memory that it used. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_tree_cursor_delete(ref TSTreeCursor cursor); /** * Re-initialize a tree cursor to start at a different node. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_tree_cursor_reset(ref TSTreeCursor cursor, TSNode node); /** * Get the tree cursor's current node. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSNode ts_tree_cursor_current_node(ref TSTreeCursor cursor); /** * Get the field name of the tree cursor's current node. * * This returns `NULL` if the current node doesn't have a field. * See also `ts_node_child_by_field_name`. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_tree_cursor_current_field_name(ref TSTreeCursor cursor); /** * Get the field id of the tree cursor's current node. * * This returns zero if the current node doesn't have a field. * See also `ts_node_child_by_field_id`, `ts_language_field_id_for_name`. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern ushort ts_tree_cursor_current_field_id(ref TSTreeCursor cursor); /** * Move the cursor to the parent of its current node. * * This returns `true` if the cursor successfully moved, and returns `false` * if there was no parent node (the cursor was already on the root node). */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_tree_cursor_goto_parent(ref TSTreeCursor cursor); /** * Move the cursor to the next sibling of its current node. * * This returns `true` if the cursor successfully moved, and returns `false` * if there was no next sibling node. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_tree_cursor_goto_next_sibling(ref TSTreeCursor cursor); /** * Move the cursor to the first child of its current node. * * This returns `true` if the cursor successfully moved, and returns `false` * if there were no children. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_tree_cursor_goto_first_child(ref TSTreeCursor cursor); /** * Move the cursor to the first child of its current node that extends beyond * the given byte offset or point. * * This returns the index of the child node if one was found, and returns -1 * if no such child was found. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern long ts_tree_cursor_goto_first_child_for_byte(ref TSTreeCursor cursor, uint byteOffset); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern long ts_tree_cursor_goto_first_child_for_point(ref TSTreeCursor cursor, TSPoint point); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSTreeCursor ts_tree_cursor_copy(ref TSTreeCursor cursor); #endregion } /*******************/ /* Section - Query */ /*******************/ public sealed class TSQuery : IDisposable { public TSQuery(IntPtr ptr) { Ptr = ptr; } internal IntPtr Ptr { get; private set; } public void Dispose() { if (Ptr != IntPtr.Zero) { ts_query_delete(Ptr); Ptr = IntPtr.Zero; } } public uint pattern_count() { return ts_query_pattern_count(Ptr); } public uint capture_count() { return ts_query_capture_count(Ptr); } public uint string_count() { return ts_query_string_count(Ptr); } public uint start_offset_for_pattern(uint patternIndex) { return ts_query_start_byte_for_pattern(Ptr, patternIndex) / sizeof(ushort); } public IntPtr predicates_for_pattern(uint patternIndex, out uint length) { return ts_query_predicates_for_pattern(Ptr, patternIndex, out length); } public bool is_pattern_rooted(uint patternIndex) { return ts_query_is_pattern_rooted(Ptr, patternIndex); } public bool is_pattern_non_local(uint patternIndex) { return ts_query_is_pattern_non_local(Ptr, patternIndex); } public bool is_pattern_guaranteed_at_offset(uint offset) { return ts_query_is_pattern_guaranteed_at_step(Ptr, offset / sizeof(ushort)); } public string capture_name_for_id(uint id, out uint length) { return Marshal.PtrToStringAnsi(ts_query_capture_name_for_id(Ptr, id, out length)); } public TSQuantifier capture_quantifier_for_id(uint patternId, uint captureId) { return ts_query_capture_quantifier_for_id(Ptr, patternId, captureId); } public string string_value_for_id(uint id, out uint length) { return Marshal.PtrToStringAnsi(ts_query_string_value_for_id(Ptr, id, out length)); } public void disable_capture(string captureName) { ts_query_disable_capture(Ptr, captureName, (uint)captureName.Length); } public void disable_pattern(uint patternIndex) { ts_query_disable_pattern(Ptr, patternIndex); } #region PInvoke [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_delete(IntPtr query); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_query_pattern_count(IntPtr query); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_query_capture_count(IntPtr query); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_query_string_count(IntPtr query); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_query_start_byte_for_pattern(IntPtr query, uint patternIndex); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_query_predicates_for_pattern(IntPtr query, uint patternIndex, out uint length); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_query_is_pattern_rooted(IntPtr query, uint patternIndex); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_query_is_pattern_non_local(IntPtr query, uint patternIndex); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_query_is_pattern_guaranteed_at_step(IntPtr query, uint byteOffset); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_query_capture_name_for_id(IntPtr query, uint id, out uint length); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSQuantifier ts_query_capture_quantifier_for_id(IntPtr query, uint patternId, uint captureId); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_query_string_value_for_id(IntPtr query, uint id, out uint length); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_disable_capture(IntPtr query, [MarshalAs(UnmanagedType.LPUTF8Str)] string captureName, uint captureNameLength); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_disable_pattern(IntPtr query, uint patternIndex); #endregion } public sealed class TSQueryCursor : IDisposable { private TSQueryCursor(IntPtr ptr) { Ptr = ptr; } public TSQueryCursor() { Ptr = ts_query_cursor_new(); } private IntPtr Ptr { get; set; } public void Dispose() { if (Ptr != IntPtr.Zero) { ts_query_cursor_delete(Ptr); Ptr = IntPtr.Zero; } } public void exec(TSQuery query, TSNode node) { ts_query_cursor_exec(Ptr, query.Ptr, node); } public bool did_exceed_match_limit() { return ts_query_cursor_did_exceed_match_limit(Ptr); } public uint match_limit() { return ts_query_cursor_match_limit(Ptr); } public void set_match_limit(uint limit) { ts_query_cursor_set_match_limit(Ptr, limit); } public void set_range(uint start, uint end) { ts_query_cursor_set_byte_range(Ptr, start * sizeof(ushort), end * sizeof(ushort)); } public void set_point_range(TSPoint start, TSPoint end) { ts_query_cursor_set_point_range(Ptr, start, end); } public bool next_match(out TSQueryMatch match, out TSQueryCapture[] captures) { captures = null; if (ts_query_cursor_next_match(Ptr, out match)) { if (match.capture_count > 0) { captures = new TSQueryCapture [match.capture_count]; for (ushort i = 0; i < match.capture_count; i++) { IntPtr intPtr = match.captures + Marshal.SizeOf(typeof(TSQueryCapture)) * i; captures[i] = Marshal.PtrToStructure(intPtr); } } return true; } return false; } public void remove_match(uint id) { ts_query_cursor_remove_match(Ptr, id); } public bool next_capture(out TSQueryMatch match, out uint index) { return ts_query_cursor_next_capture(Ptr, out match, out index); } #region PInvoke [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_query_cursor_new(); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_cursor_delete(IntPtr cursor); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_cursor_exec(IntPtr cursor, IntPtr query, TSNode node); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_query_cursor_did_exceed_match_limit(IntPtr cursor); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_query_cursor_match_limit(IntPtr cursor); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_cursor_set_match_limit(IntPtr cursor, uint limit); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_cursor_set_byte_range(IntPtr cursor, uint start_byte, uint end_byte); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_cursor_set_point_range(IntPtr cursor, TSPoint start_point, TSPoint end_point); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_query_cursor_next_match(IntPtr cursor, out TSQueryMatch match); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern void ts_query_cursor_remove_match(IntPtr cursor, uint id); [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern bool ts_query_cursor_next_capture(IntPtr cursor, out TSQueryMatch match, out uint capture_index); #endregion } /**********************/ /* Section - Language */ /**********************/ public sealed class TSLanguage : IDisposable { public string[] symbols; public string[] fields; public Dictionary fieldIds; public TSLanguage(IntPtr ptr) { Ptr = ptr; symbols = new string[symbol_count() + 1]; for (ushort i = 0; i < symbols.Length; i++) { symbols[i] = Marshal.PtrToStringAnsi(ts_language_symbol_name(Ptr, i)); } fields = new string[field_count() + 1]; fieldIds = new Dictionary((int)field_count() + 1); for (ushort i = 0; i < fields.Length; i++) { fields[i] = Marshal.PtrToStringAnsi(ts_language_field_name_for_id(Ptr, i)); if (fields[i] != null) { fieldIds.Add(fields[i], i); // TODO: check for dupes, and throw if found } } #if false for (int i = 0; i < symbols.Length; i++) { for (int j = 0; j < i; j++) { Debug.Assert(symbols[i] != symbols[j]); } } for (int i = 0; i < fields.Length; i++) { for (int j = 0; j < i; j++) { Debug.Assert(fields[i] != fields[j]); } } #endif } internal IntPtr Ptr { get; private set; } public void Dispose() { if (Ptr != IntPtr.Zero) { //ts_query_cursor_delete(Ptr); Ptr = IntPtr.Zero; } } public TSQuery query_new(string source, out uint error_offset, out TSQueryError error_type) { IntPtr ptr = ts_query_new(Ptr, source, (uint)source.Length, out error_offset, out error_type); return ptr != IntPtr.Zero ? new TSQuery(ptr) : null; } public uint symbol_count() { return ts_language_symbol_count(Ptr); } public string symbol_name(ushort symbol) { return symbol != ushort.MaxValue ? symbols[symbol] : "ERROR"; } public ushort symbol_for_name(string str, bool is_named) { return ts_language_symbol_for_name(Ptr, str, (uint)str.Length, is_named); } public uint field_count() { return ts_language_field_count(Ptr); } public string field_name_for_id(ushort fieldId) { return fields[fieldId]; } public ushort field_id_for_name(string str) { return ts_language_field_id_for_name(Ptr, str, (uint)str.Length); } public TSSymbolType symbol_type(ushort symbol) { return ts_language_symbol_type(Ptr, symbol); } #region PInvoke /** * Create a new query from a string containing one or more S-expression * patterns. The query is associated with a particular language, and can * only be run on syntax nodes parsed with that language. * * If all of the given patterns are valid, this returns a `TSQuery`. * If a pattern is invalid, this returns `NULL`, and provides two pieces * of information about the problem: * 1. The byte offset of the error is written to the `error_offset` parameter. * 2. The type of error is written to the `error_type` parameter. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_query_new(IntPtr language, [MarshalAs(UnmanagedType.LPUTF8Str)] string source, uint source_len, out uint error_offset, out TSQueryError error_type); /** * Get the number of distinct node types in the language. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_language_symbol_count(IntPtr language); /** * Get a node type string for the given numerical id. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_language_symbol_name(IntPtr language, ushort symbol); /** * Get the numerical id for the given node type string. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern ushort ts_language_symbol_for_name(IntPtr language, [MarshalAs(UnmanagedType.LPUTF8Str)] string str, uint length, bool is_named); /** * Get the number of distinct field names in the language. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_language_field_count(IntPtr language); /** * Get the field name string for the given numerical id. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ts_language_field_name_for_id(IntPtr language, ushort fieldId); /** * Get the numerical id for the given field name string. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern ushort ts_language_field_id_for_name(IntPtr language, [MarshalAs(UnmanagedType.LPUTF8Str)] string str, uint length); /** * Check whether the given node type id belongs to named nodes, anonymous nodes, * or a hidden nodes. * * See also `ts_node_is_named`. Hidden nodes are never returned from the API. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern TSSymbolType ts_language_symbol_type(IntPtr language, ushort symbol); /** * Get the ABI version number for this language. This version number is used * to ensure that languages were generated by a compatible version of * Tree-sitter. * * See also `ts_parser_set_language`. */ [SuppressUnmanagedCodeSecurity] [DllImport("tree-sitter.dll", CallingConvention = CallingConvention.Cdecl)] private static extern uint ts_language_version(IntPtr language); #endregion } ================================================ FILE: src/ProfileExplorerCore/TextLocation.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Runtime.CompilerServices; namespace ProfileExplorer.Core; public struct TextLocation : IComparable { public int Offset { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } public int Line { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } public int Column { [MethodImpl(MethodImplOptions.AggressiveInlining)] get; [MethodImpl(MethodImplOptions.AggressiveInlining)] set; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public TextLocation(int offset, int line, int column) { Offset = offset; Line = line; Column = column; } public override string ToString() { return $"offset: {Offset}, line: {Line}"; } public override bool Equals(object obj) { return obj is TextLocation location && Offset == location.Offset && Line == location.Line && Column == location.Column; } public override int GetHashCode() { return HashCode.Combine(Offset, Line); } public int CompareTo(TextLocation other) { return Offset.CompareTo(other.Offset); } public static bool operator ==(TextLocation a, TextLocation b) { return a.Equals(b); } public static bool operator !=(TextLocation a, TextLocation b) { return !a.Equals(b); } public static bool operator <(TextLocation left, TextLocation right) { return left.CompareTo(right) < 0; } public static bool operator >(TextLocation left, TextLocation right) { return left.CompareTo(right) > 0; } public static bool operator <=(TextLocation left, TextLocation right) { return left.CompareTo(right) <= 0; } public static bool operator >=(TextLocation left, TextLocation right) { return left.CompareTo(right) >= 0; } } ================================================ FILE: src/ProfileExplorerCore/Utilities/BindableObject.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.ComponentModel; using System.Runtime.CompilerServices; namespace ProfileExplorer.Core.Utilities; // Shorter way to have property notifications for data-binding. // Based on code from https://www.danrigby.com/2012/04/01/inotifypropertychanged-the-net-4-5-way-revisited/ public class BindableObject : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetAndNotify(ref T storage, T value, [CallerMemberName] string propertyName = null) { if (Equals(storage, value)) { return false; } storage = value; NotifyPropertyChanged(propertyName); return true; } protected void Notify(string propertyName) { NotifyPropertyChanged(propertyName); } } ================================================ FILE: src/ProfileExplorerCore/Utilities/CancelableTask.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Threading; using System.Threading.Tasks; namespace ProfileExplorer.Core.Utilities; public static class WaitHandleExtensions { public static Task AsTask(this WaitHandle handle) { return AsTask(handle, Timeout.InfiniteTimeSpan); } public static Task AsTask(this WaitHandle handle, TimeSpan timeout) { var taskSource = new TaskCompletionSource(); var registration = ThreadPool.RegisterWaitForSingleObject(handle, (state, timedOut) => { var localTaskSource = (TaskCompletionSource)state; if (timedOut) localTaskSource.TrySetCanceled(); else localTaskSource.TrySetResult(null); }, taskSource, timeout, true); taskSource.Task.ContinueWith((_, state) => ((RegisteredWaitHandle)state).Unregister(null), registration, TaskScheduler.Default); return taskSource.Task; } } public class CancelableTask : IDisposable { private CancellationToken cancelToken_; private ManualResetEvent taskCompletedEvent_; private CancellationTokenSource tokenSource_; private bool disposed_; private bool completeOnCancel_; public CancelableTask(bool completeOnCancel = true) { taskCompletedEvent_ = new ManualResetEvent(false); tokenSource_ = new CancellationTokenSource(); cancelToken_ = tokenSource_.Token; completeOnCancel_ = completeOnCancel; //Debug.WriteLine($"+ Create task {ObjectTracker.Track(this)}"); //Debug.WriteLine($"{Environment.StackTrace}\n-------------------------------------------\n"); } public CancellationToken Token => cancelToken_; public bool IsCanceled => cancelToken_.IsCancellationRequested; public bool IsCompleted => !IsCanceled && taskCompletedEvent_.WaitOne(0); public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } ~CancelableTask() { Dispose(false); } public void WaitToComplete() { //Debug.WriteLine($"+ Wait to complete task {ObjectTracker.Track(this)}"); //Debug.WriteLine($"{Environment.StackTrace}\n-------------------------------------------\n"); if (disposed_) { return; } taskCompletedEvent_.WaitOne(); } public async Task WaitToCompleteAsync() { //Debug.WriteLine($"+ Wait to complete task {ObjectTracker.Track(this)}"); //Debug.WriteLine($"{Environment.StackTrace}\n-------------------------------------------\n"); return await WaitToCompleteAsync(TimeSpan.FromMilliseconds(int.MaxValue - 1)); } public bool WaitToComplete(TimeSpan timeout) { if (disposed_) { return false; } return taskCompletedEvent_.WaitOne(timeout); } private async Task WaitToCompleteAsync(TimeSpan timeout) { //Debug.WriteLine($"+ Wait to complete task {ObjectTracker.Track(this)}"); //Debug.WriteLine($"{Environment.StackTrace}\n-------------------------------------------\n"); if (disposed_) { return false; } try { await taskCompletedEvent_.AsTask(timeout); return true; } catch (TaskCanceledException ex) { // Triggered when timing out. return false; } } public void Complete() { //Debug.WriteLine($"+ Complete task {ObjectTracker.Track(this)}"); //Debug.WriteLine($"{Environment.StackTrace}\n-------------------------------------------\n"); if (disposed_) { return; } taskCompletedEvent_.Set(); } public void Cancel() { //Debug.WriteLine($"+ Cancel task {ObjectTracker.Track(this)}"); //Debug.WriteLine($"{Environment.StackTrace}\n-------------------------------------------\n"); if (disposed_) { return; } tokenSource_.Cancel(); if (completeOnCancel_) { taskCompletedEvent_.Set(); } } private void Dispose(bool disposing) { if (!disposed_) { taskCompletedEvent_.Set(); // May not be marked as completed yet. tokenSource_.Dispose(); taskCompletedEvent_.Dispose(); disposed_ = true; } } } ================================================ FILE: src/ProfileExplorerCore/Utilities/CancelableTaskInstance.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Threading.Tasks; namespace ProfileExplorer.Core.Utilities; // Manages a unique running instance of a CancelableTask. public class CancelableTaskInstance : IDisposable { public delegate void CancelableTaskDelegate(CancelableTask task); private CancelableTask taskInstance_; private CancelableTaskDelegate registerAction_; private CancelableTaskDelegate unregisterAction_; private object lockObject_ = new(); private bool completeOnCancel_; public CancelableTaskInstance(bool completeOnCancel = true, CancelableTaskDelegate registerAction = null, CancelableTaskDelegate unregisterAction = null) { completeOnCancel_ = completeOnCancel; registerAction_ = registerAction; unregisterAction_ = unregisterAction; } public CancelableTask CurrentInstance { get { lock (lockObject_) { if (taskInstance_ == null) { throw new InvalidOperationException("No task instance running!"); } return taskInstance_; } } } public void Dispose() { taskInstance_?.Dispose(); } public CancelableTask CreateTask() { lock (lockObject_) { if (taskInstance_ != null) { // Cancel running task without blocking. CancelTask(); } taskInstance_ = new CancelableTask(completeOnCancel_); registerAction_?.Invoke(taskInstance_); return taskInstance_; } } public async Task CancelCurrentAndCreateTaskAsync() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; } if (task != null) { await CancelTaskAndWaitAsync(task); } lock (lockObject_) { // Check that nothing else changed the current task // before replacing it. if (taskInstance_ == task) { taskInstance_ = new CancelableTask(completeOnCancel_); registerAction_?.Invoke(taskInstance_); } return taskInstance_; } } public CancelableTask CancelCurrentAndCreateTask() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; } if (task != null) { CancelTask(task); } lock (lockObject_) { // Check that nothing else changed the current task // before replacing it. if (taskInstance_ == task) { taskInstance_ = new CancelableTask(completeOnCancel_); registerAction_?.Invoke(taskInstance_); } return taskInstance_; } } public async Task WaitAndCreateTaskAsync() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; } if (task != null) { await task.WaitToCompleteAsync(); } lock (lockObject_) { // Check that nothing else changed the current task // before replacing it. if (taskInstance_ == task) { taskInstance_ = new CancelableTask(completeOnCancel_); registerAction_?.Invoke(taskInstance_); } return taskInstance_; } } public void CancelTask() { lock (lockObject_) { if (taskInstance_ == null) { return; } var canceledTask = taskInstance_; taskInstance_ = null; // Cancel the task and wait for it to complete without blocking. canceledTask.Cancel(); unregisterAction_?.Invoke(canceledTask); } } public void CancelTaskAndWait() { lock (lockObject_) { if (taskInstance_ == null) { return; } var canceledTask = taskInstance_; taskInstance_ = null; CancelTask(canceledTask); } } private void CancelTask(CancelableTask canceledTask) { // Cancel the task and wait for it to complete. canceledTask.Cancel(); canceledTask.WaitToComplete(); unregisterAction_?.Invoke(canceledTask); } public async Task CancelTaskAndWaitAsync() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; taskInstance_ = null; } if (task != null) { await CancelTaskAndWaitAsync(task); } } public void CompleteTask(CancelableTask task) { lock (lockObject_) { if (task != taskInstance_) { return; // A canceled task, ignore it. } if (taskInstance_ != null) { unregisterAction_?.Invoke(taskInstance_); taskInstance_.Complete(); taskInstance_.Dispose(); taskInstance_ = null; } } } public void CompleteTask() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; } if (task != null) { CompleteTask(task); } } public void WaitForTask() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; } if (task != null) { task.WaitToComplete(); } } public async Task WaitForTaskAsync() { CancelableTask task = null; lock (lockObject_) { task = taskInstance_; } if (task != null) { await task.WaitToCompleteAsync(); } } private async Task CancelTaskAndWaitAsync(CancelableTask canceledTask) { // Cancel the task and wait for it to complete. canceledTask.Cancel(); unregisterAction_?.Invoke(canceledTask); await canceledTask.WaitToCompleteAsync(); } } ================================================ FILE: src/ProfileExplorerCore/Utilities/CollectionExtensionMethods.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.IR; namespace ProfileExplorer.Core.Utilities; public static class CollectionExtensionMethods { public static List CloneList(this List list) { if (list == null) { return null; } return list.ConvertAll(item => item); } public static bool AreEqual(this List list, List other) { if (ReferenceEquals(list, other)) { return true; } else if (list == null || other == null || list.Count != other.Count) { return false; } return list.SequenceEqual(other); } public static bool AreEqual(this IList list, IList other) { if (ReferenceEquals(list, other)) { return true; } else if (list == null || other == null || list.Count != other.Count) { return false; } for (int i = 0; i < list.Count; i++) { if (!Equals(list[i], other[i])) { return false; } } return true; } public static Dictionary CloneDictionary( this Dictionary dict) { if (dict == null) { return null; } var newDict = new Dictionary(dict.Count); foreach (var item in dict) { newDict.Add(item.Key, item.Value); } return newDict; } public static HashSet CloneHashSet(this HashSet hashSet) { if (hashSet == null) { return null; } var newHashSet = new HashSet(hashSet.Count); foreach (var item in hashSet) { newHashSet.Add(item); } return newHashSet; } public static HashSet ToHashSet(this List list) { var hashSet = new HashSet(list.Count); list.ForEach(item => hashSet.Add(item)); return hashSet; } public static HashSet ToHashSet(this List list, Func action) where TIn : class where TOut : class { var hashSet = new HashSet(list.Count); list.ForEach(item => hashSet.Add(action(item))); return hashSet; } public static List ToList(this HashSet hashSet) { var list = new List(hashSet.Count); foreach (var item in hashSet) { list.Add(item); } return list; } public static List ToList(this HashSet hashSet, Func action) { var list = new List(hashSet.Count); foreach (var item in hashSet) { list.Add(action(item)); } return list; } public static List<(K, V)> ToList(this IDictionary dict) { var list = new List<(K, V)>(dict.Count); foreach (var item in dict) { list.Add((item.Key, item.Value)); } return list; } public static List ToKeyList(this IDictionary dict) { var list = new List(dict.Count); foreach (var item in dict) { list.Add(item.Key); } return list; } public static List ToValueList(this IDictionary dict) { var list = new List(dict.Count); foreach (var item in dict) { list.Add(item.Value); } return list; } public static List> ToList(this Dictionary dict) where K1 : IRElement where K2 : IRElementReference { var list = new List>(dict.Count); foreach (var item in dict) { list.Add(new Tuple((K2)item.Key, item.Value)); } return list; } public static Dictionary ToDictionary(this List> list) { var dict = new Dictionary(list.Count); foreach (var item in list) { dict.Add(item.Item1, item.Item2); } return dict; } public static Dictionary ToDictionary(this List> list) where K1 : IRElementReference where K2 : IRElement { var dict = new Dictionary(list.Count); foreach (var item in list) { if (item.Item1 != null) { dict.Add((K2)item.Item1, item.Item2); } } return dict; } public static bool AreEqual(this Dictionary first, Dictionary second) { if (first == second) return true; if (first == null || second == null) return false; if (first.Count != second.Count) return false; var valueComparer = EqualityComparer.Default; foreach (var kvp in first) { if (!second.TryGetValue(kvp.Key, out var value2)) return false; if (!valueComparer.Equals(kvp.Value, value2)) return false; } return true; } public static bool AreEqual(this IDictionary first, IDictionary second) { if (first == second) return true; if (first == null || second == null) return false; if (first.Count != second.Count) return false; foreach (DictionaryEntry kvp in first) { if (!second.Contains(kvp.Key)) return false; if (!Equals(kvp.Value, second[kvp.Key])) return false; } return true; } public static bool AreEqual(this HashSet first, HashSet second) { if (first == second) return true; if (first == null || second == null) return false; if (first.Count != second.Count) return false; var valueComparer = EqualityComparer.Default; foreach (var value in first) { if (!second.TryGetValue(value, out var value2)) return false; if (!valueComparer.Equals(value, value2)) return false; } return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void AccumulateValue(this Dictionary dict, K key, int value) { ref int currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); currentValue += value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void AccumulateValue(this Dictionary dict, K key, long value) { ref long currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); currentValue += value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void AccumulateValue(this Dictionary dict, K key, TimeSpan value) { ref var currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); // The TimeSpan + operator does an overflow check that is not relevant // (and an exception undesirable), avoid it for some speedup. long sum = currentValue.Ticks + value.Ticks; var newValue = TimeSpan.FromTicks(sum); currentValue = newValue; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void AccumulateValue(this Dictionary dict, K key, TimeSpan value1, TimeSpan value2) { ref var currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); // The TimeSpan + operator does an overflow check that is not relevant // (and an exception undesirable), avoid it for some speedup. long sum1 = currentValue.Item1.Ticks + value1.Ticks; long sum2 = currentValue.Item2.Ticks + value2.Ticks; var newValue1 = TimeSpan.FromTicks(sum1); var newValue2 = TimeSpan.FromTicks(sum2); currentValue.Item1 = newValue1; currentValue.Item2 = newValue2; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int CollectMaxValue(this Dictionary dict, K key, int value) { ref int currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); if (exists) { if (value > currentValue) { currentValue = value; return value; } return currentValue; } currentValue = value; return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double CollectMaxValue(this Dictionary dict, K key, double value) { ref double currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); if (exists) { if (value > currentValue) { currentValue = value; return value; } return currentValue; } currentValue = value; return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TimeSpan CollectMaxValue(this Dictionary dict, K key, TimeSpan value) { ref var currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); if (exists) { if (value > currentValue) { currentValue = value; return value; } return currentValue; } currentValue = value; return value; } } ================================================ FILE: src/ProfileExplorerCore/Utilities/CompressionUtils.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Security.Cryptography; using System.Text; using System.Text.Json; namespace ProfileExplorer.Core.Utilities; public static class CompressionUtils { public static byte[] Compress(byte[] data, CompressionLevel level = CompressionLevel.Fastest) { using var uncompressedStream = new MemoryStream(data); using var compressedStream = new MemoryStream(); using var compressorStream = new BrotliStream(compressedStream, level, true); compressorStream.Write(data, 0, data.Length); compressorStream.Close(); return compressedStream.ToArray(); } public static byte[] CompressString(string text, CompressionLevel level = CompressionLevel.Fastest) { return Compress(Encoding.UTF8.GetBytes(text), level); } public static byte[] Decompress(byte[] data) { var compressedStream = new MemoryStream(data); using var decompressorStream = new BrotliStream(compressedStream, CompressionMode.Decompress); // The compression ratio is about 5x, preallocate this much. using var decompressedStream = new MemoryStream(data.Length * 5); decompressorStream.CopyTo(decompressedStream); byte[] decompressedBytes = decompressedStream.ToArray(); return decompressedBytes; } public static string DecompressString(byte[] data) { return Encoding.UTF8.GetString(Decompress(data)); } public static byte[] CreateSHA256(byte[] data) { using var sha = SHA256.Create(); return sha.ComputeHash(data); } public static byte[] CreateSHA256(string text) { return CreateSHA256(Encoding.UTF8.GetBytes(text)); } public static byte[] CreateSHA256(List byteList) { int outputSize = 0; foreach (byte[] item in byteList) { outputSize += item.Length + 1; } byte[] output = new byte[outputSize]; int position = 0; foreach (byte[] item in byteList) { Array.Copy(item, 0, output, position, item.Length); position += item.Length; output[position] = 0xFF; // Use a separator so that "ab cde" and "abc de" are distinct. position++; } using var sha = SHA256.Create(); return sha.ComputeHash(output); } } public class CompressedString : IEquatable { private byte[] data_; private int hash_; public CompressedString(ReadOnlySpan span, CompressionLevel level = CompressionLevel.Fastest) { data_ = CompressionUtils.Compress(Encoding.UTF8.GetBytes(span.ToArray()), level); hash_ = 0; } public CompressedString(string value, CompressionLevel level = CompressionLevel.Fastest) { data_ = CompressionUtils.Compress(Encoding.UTF8.GetBytes(value), level); hash_ = data_.GetHashCode(); } public int Size => data_.Length; public byte[] UniqueId => CompressionUtils.CreateSHA256(data_); public bool Equals(CompressedString other) { return Equals((object)other); } public static bool operator ==(CompressedString left, CompressedString right) { return left.Equals(right); } public static bool operator !=(CompressedString left, CompressedString right) { return !(left == right); } public override bool Equals(object obj) { return obj is CompressedString other && GetHashCode() == other.GetHashCode() && data_.Equals(other.data_); } public override int GetHashCode() { if (hash_ == 0) { hash_ = data_.GetHashCode(); } return hash_; } public override string ToString() { return CompressionUtils.DecompressString(data_); } } public class CompressedObject where T : class { private byte[] data_; private T value_; private object lockObject_; public CompressedObject(T value) { value_ = value; lockObject_ = new object(); } public void Compress() { lock (lockObject_) { if (value_ == null) { return; // Compressed already. } using var stream = new MemoryStream(); JsonSerializer.Serialize(stream, value_); byte[] serializedData = stream.ToArray(); data_ = CompressionUtils.Compress(serializedData); value_ = null; } } public T GetValue() { lock (lockObject_) { if (value_ != null) { return value_; } // Decompress on-demand. byte[] serializedData = CompressionUtils.Decompress(data_); using var stream = new MemoryStream(serializedData); value_ = JsonSerializer.Deserialize(stream); data_ = null; return value_; } } } ================================================ FILE: src/ProfileExplorerCore/Utilities/CoreSettingsProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.Core.Utilities; /// /// Default implementation of ISettingsProvider that provides hardcoded default settings. /// public class DefaultSettingsProvider : ISettingsProvider { private static readonly SymbolFileSourceSettings _symbolSettings = new SymbolFileSourceSettings(); private static readonly ProfileDataProviderOptions _profileOptions = new ProfileDataProviderOptions(); private static readonly SectionSettings _sectionSettings = new SectionSettings(); private static readonly DiffSettings _diffSettings = new DiffSettings(); private static readonly GeneralSettings _generalSettings = new GeneralSettings(); public SymbolFileSourceSettings SymbolSettings => _symbolSettings.Clone(); public ProfileDataProviderOptions ProfileOptions => _profileOptions; public SectionSettings SectionSettings => _sectionSettings; public DiffSettings DiffSettings => _diffSettings.Clone(); public GeneralSettings GeneralSettings => _generalSettings; } public static class CoreSettingsProvider { private static ISettingsProvider _provider = new DefaultSettingsProvider(); /// /// Sets the settings provider to use. This allows the UI project to override default settings. /// /// The settings provider to use, or null to reset to default. public static void SetProvider(ISettingsProvider provider) { _provider = provider ?? new DefaultSettingsProvider(); } public static SymbolFileSourceSettings SymbolSettings => _provider.SymbolSettings; public static ProfileDataProviderOptions ProfileOptions => _provider.ProfileOptions; public static SectionSettings SectionSettings => _provider.SectionSettings; public static DiffSettings DiffSettings => _provider.DiffSettings; public static GeneralSettings GeneralSettings => _provider.GeneralSettings; } ================================================ FILE: src/ProfileExplorerCore/Utilities/DebugObjectId.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace ProfileExplorer.Core.Utilities; // Used to create an unique ID for an object, to be used // for tracking in log files. public static class ObjectTracker { private static ConditionalWeakTable DebugTaskId = new(); public static DebugObjectId Track(object value) { if (value == null) { return new DebugObjectId(); } return DebugTaskId.GetValue(value, obj => new DebugObjectId(obj)); } public class DebugObjectId { private static Dictionary PrefixNumbers = new(); private static object LockObject = new(); public DebugObjectId() { Id = ""; } public DebugObjectId(object value) { string typeName = value.GetType().Name.ToLower(); string prefix = typeName.Substring(0, Math.Min(12, typeName.Length)); int number = 1; lock (LockObject) { if (PrefixNumbers.TryGetValue(prefix, out number)) { ++number; PrefixNumbers[prefix] = number; } else { PrefixNumbers[prefix] = number; } } Id = $"{prefix}-{number}"; } public string Id { get; set; } public override string ToString() { return Id; } } } ================================================ FILE: src/ProfileExplorerCore/Utilities/DiagnosticLogger.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Diagnostics; using System.IO; using System.Threading; using Microsoft.Extensions.Logging; namespace ProfileExplorer.Core.Utilities; /// /// Diagnostic logger that writes to a file that can be easily retrieved by users. /// This is specifically designed for debugging issues that don't reproduce locally /// and need to be sent back by users. /// /// Logging is controlled by the PROFILE_EXPLORER_DEBUG environment variable. /// Set to "1", "true", "on", or "enabled" to enable diagnostic logging. /// Defaults to disabled for performance and privacy. /// public static class DiagnosticLogger { private static readonly object lockObject_ = new(); private static ILogger logger_; private static string logFilePath_; private static readonly ConcurrentQueue recentMessages_ = new(); private static readonly int MaxRecentMessages = 1000; private static bool initialized_ = false; private static readonly Lazy isEnabled_ = new Lazy(CheckIfEnabled); /// /// Check if diagnostic logging is enabled via environment variable /// private static bool CheckIfEnabled() { string envValue = Environment.GetEnvironmentVariable("PROFILE_EXPLORER_DEBUG"); if (string.IsNullOrEmpty(envValue)) { return false; } envValue = envValue.Trim().ToLowerInvariant(); return envValue == "1" || envValue == "true" || envValue == "on" || envValue == "enabled"; } /// /// Gets whether diagnostic logging is enabled /// public static bool IsEnabled => isEnabled_.Value; /// /// Ensure the diagnostic logger is initialized /// private static void EnsureInitialized() { if (!IsEnabled) { return; // Don't initialize if logging is disabled } if (!initialized_) { lock (lockObject_) { if (!initialized_ && IsEnabled) { Initialize(); initialized_ = true; } } } } /// /// Initialize the diagnostic logger with a file in the user's temp directory /// private static void Initialize() { try { // Create log file in user's temp directory with timestamp string tempDir = Path.GetTempPath(); string timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss"); string processId = Process.GetCurrentProcess().Id.ToString(); logFilePath_ = Path.Combine(tempDir, $"ProfileExplorer_Diagnostic_{timestamp}_{processId}.log"); // Create a simple file logger var loggerFactory = LoggerFactory.Create(builder => { builder.AddProvider(new FileLoggerProvider(logFilePath_)); builder.SetMinimumLevel(LogLevel.Debug); }); logger_ = loggerFactory.CreateLogger("Diagnostic"); // Log startup info directly to avoid circular calls during initialization LogMessageDirect(LogLevel.Information, "=== Profile Explorer Diagnostic Log Started ==="); LogMessageDirect(LogLevel.Information, $"Diagnostic logging enabled via PROFILE_EXPLORER_DEBUG environment variable"); LogMessageDirect(LogLevel.Information, $"Process ID: {processId}"); LogMessageDirect(LogLevel.Information, $"Working Directory: {Environment.CurrentDirectory}"); LogMessageDirect(LogLevel.Information, $"Machine Name: {Environment.MachineName}"); LogMessageDirect(LogLevel.Information, $"User: {Environment.UserName}"); LogMessageDirect(LogLevel.Information, $"OS Version: {Environment.OSVersion}"); LogMessageDirect(LogLevel.Information, $"CLR Version: {Environment.Version}"); LogMessageDirect(LogLevel.Information, $"Log File: {logFilePath_}"); LogMessageDirect(LogLevel.Information, "================================================="); } catch (Exception ex) { // Fallback to trace if file logging fails Trace.TraceError($"Failed to initialize DiagnosticLogger: {ex.Message}"); } } /// /// Get the path to the current diagnostic log file /// Returns null if logging is disabled /// public static string LogFilePath { get { if (!IsEnabled) { return null; } EnsureInitialized(); return logFilePath_; } } /// /// Log debug information /// public static void LogDebug(string message) { if (!IsEnabled) return; LogMessage(LogLevel.Debug, message); } /// /// Log informational message /// public static void LogInfo(string message) { if (!IsEnabled) return; LogMessage(LogLevel.Information, message); } /// /// Log warning message /// public static void LogWarning(string message) { if (!IsEnabled) return; LogMessage(LogLevel.Warning, message); } /// /// Log error message /// public static void LogError(string message) { if (!IsEnabled) return; LogMessage(LogLevel.Error, message); } /// /// Log error with exception /// public static void LogError(string message, Exception ex) { if (!IsEnabled) return; LogMessage(LogLevel.Error, $"{message}\nException: {ex}"); } private static void LogMessage(LogLevel level, string message) { try { EnsureInitialized(); LogMessageDirect(level, message); } catch { // Silently ignore logging errors to avoid cascading failures } } /// /// Log message directly without initialization check - used during initialization only /// private static void LogMessageDirect(LogLevel level, string message) { try { lock (lockObject_) { // Add to recent messages queue string timestampedMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{level}] {message}"; recentMessages_.Enqueue(timestampedMessage); // Maintain queue size while (recentMessages_.Count > MaxRecentMessages) { recentMessages_.TryDequeue(out _); } // Log to file if available logger_?.Log(level, message); // Also log to trace for debugging switch (level) { case LogLevel.Error: Trace.TraceError(message); break; case LogLevel.Warning: Trace.TraceWarning(message); break; default: Trace.TraceInformation(message); break; } } } catch { // Silently ignore logging errors to avoid cascading failures } } /// /// Get recent log messages (useful for displaying in UI) /// Returns empty array if logging is disabled /// public static string[] GetRecentMessages() { if (!IsEnabled) { return new string[0]; } EnsureInitialized(); return recentMessages_.ToArray(); } /// /// Open the log file in the default text editor /// public static void OpenLogFile() { if (!IsEnabled) { return; } try { EnsureInitialized(); if (File.Exists(logFilePath_)) { Process.Start(new ProcessStartInfo(logFilePath_) { UseShellExecute = true }); } } catch (Exception ex) { Trace.TraceError($"Failed to open log file: {ex.Message}"); } } /// /// Copy log file path to clipboard /// public static void CopyLogFilePathToClipboard() { if (!IsEnabled) { return; } try { EnsureInitialized(); // Just trace the path since we don't have clipboard access in core library Trace.TraceInformation($"Diagnostic log path: {logFilePath_}"); } catch { // Ignore errors } } /// /// Show message to user about where to find the diagnostic log /// This method is UI-framework agnostic and returns the log file path /// public static void ShowLogFileLocation() { if (!IsEnabled) { return; } try { EnsureInitialized(); // Open the file location in Windows Explorer if (File.Exists(logFilePath_)) { System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{logFilePath_}\""); } else { // If file doesn't exist, open the directory string directory = Path.GetDirectoryName(logFilePath_) ?? Path.GetTempPath(); System.Diagnostics.Process.Start("explorer.exe", directory); } LogInfo("User accessed diagnostic log file location"); } catch (Exception ex) { Trace.TraceError($"Failed to show log file location: {ex.Message}"); } } /// /// Get diagnostic log file information /// public static string GetLogFileInfo() { if (!IsEnabled) { return "Diagnostic logging is disabled. Set PROFILE_EXPLORER_DEBUG environment variable to '1', 'true', 'on', or 'enabled' to enable logging."; } EnsureInitialized(); if (File.Exists(logFilePath_)) { var info = new FileInfo(logFilePath_); return $"Diagnostic log file location:\n{logFilePath_}\n\nFile size: {info.Length:N0} bytes\nLast modified: {info.LastWriteTime}"; } else { return $"Diagnostic log file not found at:\n{logFilePath_}"; } } /// /// Simple file logger provider for writing to a single file /// private class FileLoggerProvider : ILoggerProvider { private readonly string filePath_; private readonly object writeLock_ = new(); public FileLoggerProvider(string filePath) { filePath_ = filePath; } public ILogger CreateLogger(string categoryName) { return new FileLogger(filePath_, categoryName, writeLock_); } public void Dispose() { } private class FileLogger : ILogger { private readonly string filePath_; private readonly string categoryName_; private readonly object writeLock_; public FileLogger(string filePath, string categoryName, object writeLock) { filePath_ = filePath; categoryName_ = categoryName; writeLock_ = writeLock; } public IDisposable BeginScope(TState state) => null; public bool IsEnabled(LogLevel logLevel) => true; public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) { try { string message = formatter(state, exception); string logLine = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} [{logLevel}] [{categoryName_}] {message}"; if (exception != null) { logLine += $"\n{exception}"; } lock (writeLock_) { File.AppendAllText(filePath_, logLine + Environment.NewLine); } } catch { // Ignore file write errors } } } } } ================================================ FILE: src/ProfileExplorerCore/Utilities/ExtensionMethods.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Text; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; namespace ProfileExplorer.Core.Utilities; public static class ExtensionMethods { private static readonly string[] NewLineStrings = {"\r\n", "\r", "\n"}; public static string Indent(this string value, int spaces) { string whitespace = new(' ', spaces); string valueNoCr = value.Replace("\r\n", "\n", StringComparison.Ordinal); return valueNoCr.Replace("\n", $"{Environment.NewLine}{whitespace}", StringComparison.Ordinal); } public static V GetOrAddValue(this Dictionary dict, K key) where V : new() { ref var currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); if (!exists) { currentValue = new V(); } return currentValue; } public static V GetOrAddValue(this Dictionary dict, K key, V defaultValue) where V : new() { ref var currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); if (!exists) { currentValue = defaultValue; } return currentValue; } public static V GetOrAddValue(this Dictionary dict, K key, Func newValueFunc) where V : class { ref var currentValue = ref CollectionsMarshal.GetValueRefOrAddDefault(dict, key, out bool exists); if (!exists) { currentValue = newValueFunc(); } return currentValue; } public static V GetValueOrNull(this Dictionary dict, K key) where V : class { if (dict.TryGetValue(key, out var currentValue)) { return currentValue; } return null; } public static V GetValueOr(this Dictionary dict, K key, V defaultValue) { if (dict.TryGetValue(key, out var currentValue)) { return currentValue; } return defaultValue; } public static string[] NewLineSeparators(this string value) { return NewLineStrings; } public static string[] SplitLines(this string value) { return value.Split(NewLineStrings, StringSplitOptions.None); } public static string[] SplitLinesRemoveEmpty(this string value) { return value.Split(NewLineStrings, StringSplitOptions.RemoveEmptyEntries); } public static int CountLines(this string value) { if (string.IsNullOrEmpty(value)) { return 0; } int lines = 0; int len = value.Length; for (int i = 0; i < len; i++) { char c = value[i]; if (c == '\r') { lines++; // Treat CRLF as a single newline. if (i + 1 < len && value[i + 1] == '\n') { i++; } } else if (c == '\n') { lines++; } } // If the last character wasn't a newline, account for the final line. if (len > 0) { char last = value[len - 1]; if (last != '\n' && last != '\r') { lines++; } } return lines; } private static readonly char[] NewLineChars = { '\r', '\n' }; private static ConcurrentDictionary percentageStringCache_ = new(); private static ConcurrentDictionary nanosecondsTimeStringCache_ = new(); private static ConcurrentDictionary microsecondTimeStringCache_ = new(); private static ConcurrentDictionary millisecondsTimeStringCache_ = new(); private static ConcurrentDictionary secondsTimeStringCache_ = new(); public static string RemoveChars(this string value, params char[] charList) { if (string.IsNullOrEmpty(value)) { return value; } var sb = new StringBuilder(value.Length); foreach (char c in value) { if (Array.IndexOf(charList, c) == -1) { sb.Append(c); } } return sb.ToString(); } public static string RemoveNewLines(this string value) { return value.RemoveChars(NewLineChars); } public static string TrimToLength(this string text, int maxLength) { if (text.Length <= maxLength) { return text; } return $"{text.Substring(0, maxLength)}.."; } public static List AllIndexesOf(this string text, string value) { if (string.IsNullOrEmpty(value)) { return new List(); } var offsetList = new List(32); int offset = text.IndexOf(value, StringComparison.InvariantCulture); while (offset != -1 && offset < text.Length) { offsetList.Add(offset); offset += value.Length; offset = text.IndexOf(value, offset, StringComparison.InvariantCulture); } return offsetList; } public static string AsTrimmedPercentageString(this double value, int digits = 2, string suffix = "%") { return AsPercentageString(value, digits, true, suffix); } public static string AsPercentageString(this double value, int digits = 2, bool trim = false, string suffix = "%") { var entry = new PercentageString(value, digits, trim, suffix); if (percentageStringCache_.TryGetValue(entry, out string percentageString)) { return percentageString; } value = Math.Round(value * 100, digits); if (value == 0 && trim) { percentageStringCache_.TryAdd(entry, ""); return ""; } percentageString = digits switch { 1 => $"{value:0.0}{suffix}", 2 => $"{value:0.00}{suffix}", _ => string.Format("{0:0." + new string('0', digits) + "}", value) + suffix }; percentageStringCache_.TryAdd(entry, percentageString); return percentageString; } public static string AsNanosecondsString(this TimeSpan value, int digits = 2, string suffix = " ns") { var entry = new TimeString(value, digits, suffix); if (nanosecondsTimeStringCache_.TryGetValue(entry, out string timeString)) { return timeString; } double roundedValue = value.TotalNanoseconds.TruncateToDigits(digits); timeString = string.Format("{0:N" + Math.Abs(digits) + "}", roundedValue) + suffix; nanosecondsTimeStringCache_.TryAdd(entry, timeString); return timeString; } public static string AsMicrosecondString(this TimeSpan value, int digits = 2, string suffix = " µs") { var entry = new TimeString(value, digits, suffix); if (microsecondTimeStringCache_.TryGetValue(entry, out string timeString)) { return timeString; } double roundedValue = value.TotalMicroseconds.TruncateToDigits(digits); timeString = string.Format("{0:N" + Math.Abs(digits) + "}", roundedValue) + suffix; microsecondTimeStringCache_.TryAdd(entry, timeString); return timeString; } public static string AsMillisecondsString(this TimeSpan value, int digits = 2, string suffix = " ms") { var entry = new TimeString(value, digits, suffix); if (millisecondsTimeStringCache_.TryGetValue(entry, out string timeString)) { return timeString; } double roundedValue = value.TotalMilliseconds.TruncateToDigits(digits); timeString = string.Format("{0:N" + Math.Abs(digits) + "}", roundedValue) + suffix; millisecondsTimeStringCache_.TryAdd(entry, timeString); return timeString; } public static string AsSecondsString(this TimeSpan value, int digits = 2, string suffix = " s") { var entry = new TimeString(value, digits, suffix); if (secondsTimeStringCache_.TryGetValue(entry, out string timeString)) { return timeString; } double roundedValue = value.TotalSeconds.TruncateToDigits(digits); timeString = string.Format("{0:N" + Math.Abs(digits) + "}", roundedValue) + suffix; secondsTimeStringCache_.TryAdd(entry, timeString); return timeString; } public static string AsTimeString(this TimeSpan value, int digits = 2) { return AsTimeString(value, value, digits); } public static string AsTimeString(this TimeSpan value, TimeSpan totalValue, int digits = 2) { if (value.Ticks == 0) { return "0"; } if (totalValue.TotalMinutes >= 60) { return value.ToString("h\\:mm\\:ss"); } if (totalValue.TotalMinutes >= 10) { return value.ToString("mm\\:ss"); } if (totalValue.TotalSeconds >= 60) { return $"{value.Minutes}:{value.Seconds:D2}"; } if (totalValue.TotalSeconds >= 10) { return value.ToString("ss"); } if (totalValue.TotalSeconds >= 1) { return $"{value.Seconds}"; } double roundedValue = value.TotalMilliseconds.TruncateToDigits(digits); return string.Format("{0:N" + Math.Abs(digits) + "}", roundedValue) + " ms"; } public static string AsTimeStringWithMilliseconds(this TimeSpan value, int digits = 2) { return AsTimeStringWithMilliseconds(value, value, digits); } public static string AsTimeStringWithMilliseconds(this TimeSpan value, TimeSpan totalValue, int digits = 2) { if (value.Ticks == 0) { return "0"; } if (totalValue.TotalMinutes >= 60) { return value.ToString("h\\:mm\\:ss\\.fff"); } if (totalValue.TotalMinutes >= 10) { return value.ToString("mm\\:ss\\.fff"); } if (totalValue.TotalSeconds >= 60) { return $"{value.Minutes}:{value:ss\\.fff}"; } if (totalValue.TotalSeconds >= 10) { return value.ToString("ss\\.fff"); } if (totalValue.TotalSeconds >= 1) { return $"{value.Seconds}{value:\\.fff}"; } double roundedValue = value.TotalMilliseconds.TruncateToDigits(digits); return string.Format("{0:N" + Math.Abs(digits) + "}", roundedValue) + " ms"; } public static double TruncateToDigits(this double value, int digits) { double factor = Math.Pow(10, digits); value *= factor; value = Math.Truncate(value); return value / factor; } public static string FormatFunctionName(this ProfileCallTreeNode node, FunctionNameFormatter nameFormatter, int maxLength = int.MaxValue) { return FormatName(node.FunctionName, nameFormatter, maxLength); } public static string FormatModuleName(this ProfileCallTreeNode node, FunctionNameFormatter nameFormatter, int maxLength = int.MaxValue) { return FormatName(node.ModuleName, nameFormatter, maxLength); } public static string FormatFunctionName(this IRTextFunction func, ISession session, int maxLength = int.MaxValue) { return FormatName(func.Name, session.CompilerInfo.NameProvider.FormatFunctionName, maxLength); } public static string FormatFunctionName(this IRTextSection section, ISession session, int maxLength = int.MaxValue) { return FormatName(section.ParentFunction.Name, session.CompilerInfo.NameProvider.FormatFunctionName, maxLength); } public static string FormatFunctionName(this string name, ISession session, int maxLength = int.MaxValue) { return FormatName(name, session.CompilerInfo.NameProvider.FormatFunctionName, maxLength); } public static string FormatFunctionName(this ProfileCallTreeNode node, ISession session, int maxLength = int.MaxValue) { return FormatName(node.FunctionName, session.CompilerInfo.NameProvider.FormatFunctionName, maxLength); } private static string FormatName(string name, FunctionNameFormatter nameFormatter, int maxLength) { if (string.IsNullOrEmpty(name)) { return name; } name = nameFormatter != null ? nameFormatter(name) : name; if (name.Length > maxLength) { if (maxLength > 3) { name = $"{name.Substring(0, maxLength - 3)}..."; } else { name = name.Substring(0, maxLength); } } return name; } public static int GetStableHashCode(this string str) { unchecked { int hash1 = 5381; int hash2 = hash1; for (int i = 0; i < str.Length && str[i] != '\0'; i += 2) { hash1 = (hash1 << 5) + hash1 ^ str[i]; if (i == str.Length - 1 || str[i + 1] == '\0') break; hash2 = (hash2 << 5) + hash2 ^ str[i + 1]; } return hash1 + hash2 * 1566083941; } } // Cache percentage and time value to string conversion result // to reduce GC pressure when rendering. private record PercentageString(double value, int digits, bool trim, string suffix); private record TimeString(TimeSpan value, int digits, string suffix); } ================================================ FILE: src/ProfileExplorerCore/Utilities/JsonUtils.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Text; using System.Text.Json; using System.Text.Json.Serialization; namespace ProfileExplorer.Core.Utilities; public class StringInterningConverter : JsonConverter { public override string Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { return string.Intern(reader.GetString()); } public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) { writer.WriteStringValue(value); } } public static class JsonUtils { private static readonly List customConverters = new List(); /// /// Registers a custom JSON converter that will be added to all JsonSerializerOptions. /// /// The custom converter to register public static void RegisterConverter(JsonConverter converter) { if (converter != null && !customConverters.Contains(converter)) { customConverters.Add(converter); } } /// /// Unregisters a custom JSON converter. /// /// The converter to unregister public static void UnregisterConverter(JsonConverter converter) { customConverters.Remove(converter); } /// /// Clears all registered custom converters. /// public static void ClearCustomConverters() { customConverters.Clear(); } public static JsonSerializerOptions GetJsonOptions() { var options = new JsonSerializerOptions { WriteIndented = true, PropertyNameCaseInsensitive = true, IgnoreReadOnlyProperties = true }; // Add built-in converters options.Converters.Add(new StringInterningConverter()); options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)); // Add any registered custom converters foreach (var converter in customConverters) { options.Converters.Add(converter); } return options; } public static bool SerializeToFile(T data, string path) { try { var options = GetJsonOptions(); using var stream = File.OpenWrite(path); JsonSerializer.Serialize(stream, data, options); return true; } catch (Exception ex) { Trace.TraceError($"Failed to save JSON file: {ex.Message}"); return false; } } public static string Serialize(T data) { try { var options = GetJsonOptions(); return JsonSerializer.Serialize(data, options); } catch (Exception ex) { Trace.TraceError($"Failed to save JSON: {ex.Message}"); return null; } } public static byte[] SerializeToBytes(T data) { string text = Serialize(data); return text != null ? Encoding.UTF8.GetBytes(text) : null; } public static bool DeserializeFromFile(string path, out T data) where T : class { try { var options = GetJsonOptions(); using var stream = File.OpenRead(path); data = JsonSerializer.Deserialize(stream, options); return true; } catch (Exception ex) { Trace.TraceError($"Failed to load JSON file: {ex.Message}"); data = default(T); return false; } } public static bool Deserialize(string text, out T data) where T : class { try { var options = GetJsonOptions(); data = JsonSerializer.Deserialize(text, options); return true; } catch (Exception ex) { Trace.TraceError($"Failed to load JSON: {ex.Message}"); data = default(T); return false; } } public static bool DeserializeFromBytes(byte[] textData, out T data) where T : class { return Deserialize(Encoding.UTF8.GetString(textData), out data); } } ================================================ FILE: src/ProfileExplorerCore/Utilities/NativeMethods.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Runtime.InteropServices; using System.Security; using System.Text; namespace ProfileExplorer.Core.Utilities; public static class NativeMethods { // C++ function name demangling [Flags] public enum UnDecorateFlags { UNDNAME_COMPLETE = 0x0000, // Enable full undecoration UNDNAME_NO_LEADING_UNDERSCORES = 0x0001, // Remove leading underscores from MS extended keywords UNDNAME_NO_MS_KEYWORDS = 0x0002, // Disable expansion of MS extended keywords UNDNAME_NO_FUNCTION_RETURNS = 0x0004, // Disable expansion of return type for primary declaration UNDNAME_NO_ALLOCATION_MODEL = 0x0008, // Disable expansion of the declaration model UNDNAME_NO_ALLOCATION_LANGUAGE = 0x0010, // Disable expansion of the declaration language specifier UNDNAME_NO_MS_THISTYPE = 0x0020, // NYI Disable expansion of MS keywords on the 'this' type for primary declaration UNDNAME_NO_CV_THISTYPE = 0x0040, // NYI Disable expansion of CV modifiers on the 'this' type for primary declaration UNDNAME_NO_THISTYPE = 0x0060, // Disable all modifiers on the 'this' type UNDNAME_NO_ACCESS_SPECIFIERS = 0x0080, // Disable expansion of access specifiers for members UNDNAME_NO_THROW_SIGNATURES = 0x0100, // Disable expansion of 'throw-signatures' for functions and pointers to functions UNDNAME_NO_MEMBER_TYPE = 0x0200, // Disable expansion of 'static' or 'virtual'ness of members UNDNAME_NO_RETURN_UDT_MODEL = 0x0400, // Disable expansion of MS model for UDT returns UNDNAME_32_BIT_DECODE = 0x0800, // Undecorate 32-bit decorated names UNDNAME_NAME_ONLY = 0x1000, // Crack only the name for primary declaration; // return just [scope::]name. Does expand template params UNDNAME_NO_ARGUMENTS = 0x2000, // Don't undecorate arguments to function UNDNAME_NO_SPECIAL_SYMS = 0x4000 // Don't undecorate special names (v-table, vcall, vector xxx, metatype, etc) } public const uint TOPMOST_FLAGS = SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOSENDCHANGING; public const uint SYMOPT_DEBUG = 0x80000000; public const uint SYMOPT_EXACT_SYMBOLS = 0x00000400; private const int MAX_PATH = 260; private const uint SWP_NOSIZE = 0x0001; private const uint SWP_NOMOVE = 0x0002; private const uint SWP_NOZORDER = 0x0004; private const uint SWP_NOREDRAW = 0x0008; private const uint SWP_NOACTIVATE = 0x0010; private const uint SWP_FRAMECHANGED = 0x0020; /* The frame changed: send WM_NCCALCSIZE */ private const uint SWP_SHOWWINDOW = 0x0040; private const uint SWP_HIDEWINDOW = 0x0080; private const uint SWP_NOCOPYBITS = 0x0100; private const uint SWP_NOOWNERZORDER = 0x0200; /* Don’t do owner Z ordering */ private const uint SWP_NOSENDCHANGING = 0x0400; /* Don’t send WM_WINDOWPOSCHANGING */ public const int WM_MOUSEHWHEEL = 0x020E; public static readonly IntPtr HWND_TOPMOST = new(-1); public static readonly IntPtr HWND_NOTOPMOST = new(-2); public static readonly IntPtr HWND_TOP = new(0); public static readonly IntPtr HWND_BOTTOM = new(1); [SuppressUnmanagedCodeSecurity] [DllImport("user32.dll")] public static extern uint GetDoubleClickTime(); [SuppressUnmanagedCodeSecurity] [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [SuppressUnmanagedCodeSecurity] [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, SetLastError = false)] public static extern bool PathFindOnPath([In][Out] StringBuilder pszFile, [In] string[] ppszOtherDirs); [SuppressUnmanagedCodeSecurity] [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); [SuppressUnmanagedCodeSecurity] [DllImport("dbghelp.dll", SetLastError = true, PreserveSig = true)] public static extern int UnDecorateSymbolName( [In][MarshalAs(UnmanagedType.LPStr)] string DecoratedName, [Out] StringBuilder UnDecoratedName, [In][MarshalAs(UnmanagedType.U4)] int UndecoratedLength, [In][MarshalAs(UnmanagedType.U4)] UnDecorateFlags Flags); public static string GetFullPathFromWindows(string exeName) { var sb = new StringBuilder(exeName, MAX_PATH); return PathFindOnPath(sb, null) ? sb.ToString() : null; } public static int HIWORD(IntPtr ptr) { unchecked { if (Environment.Is64BitOperatingSystem) { long val64 = ptr.ToInt64(); return (short)(val64 >> 16 & 0xFFFF); } int val32 = ptr.ToInt32(); return (short)(val32 >> 16 & 0xFFFF); } } [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)] private static extern int GetSystemMetrics(int nIndex); public static bool IsRemoteDesktopSession() { return (GetSystemMetrics(0x1000) & 1) != 0; } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } } ================================================ FILE: src/ProfileExplorerCore/Utilities/Optional.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; namespace ProfileExplorer.Core.Utilities; public struct Optional : IEquatable> { private T value_; public bool HasValue { get; private set; } public T Value { get { Debug.Assert(HasValue); return value_; } set { value_ = value; HasValue = true; } } public Optional(T value) { value_ = value; HasValue = true; } public static explicit operator T(Optional optional) { return optional.Value; } public static implicit operator Optional(T value) { return new Optional(value); } public override bool Equals(object obj) { if (obj is Optional) { return Equals((Optional)obj); } return false; } public bool Equals(Optional other) { if (HasValue && other.HasValue) { return Equals(value_, other.value_); } return HasValue == other.HasValue; } public override int GetHashCode() { return HashCode.Combine(value_, HasValue); } } ================================================ FILE: src/ProfileExplorerCore/Utilities/SourceFileMapper.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.IO; namespace ProfileExplorer.Core; public class SourceFileMapper { private readonly Dictionary sourcePathMap_; private readonly Dictionary sourceFileCache_; private readonly object lockObject_ = new(); public SourceFileMapper(Dictionary sourcePathMap = null) { sourcePathMap_ = sourcePathMap; sourcePathMap_ ??= new Dictionary(); // Saved across sessions. sourceFileCache_ = new Dictionary(); // Active per session. } public Dictionary SourceMap => sourcePathMap_; public string Map(string sourceFile, Func lookup = null) { if (string.IsNullOrEmpty(sourceFile)) { return null; } lock (lockObject_) { if (TryLookupInMap(sourceFile, out string result)) { return result; } if (lookup == null) { return null; } result = lookup(); if (result != null) { UpdateMap(sourceFile, result); } return result; } } public void Reset() { lock (lockObject_) { sourcePathMap_.Clear(); sourcePathMap_.Clear(); } } private bool TryLookupInMap(string sourceFile, out string result) { // Check the direct mapping cache first. if (sourceFileCache_.TryGetValue(sourceFile, out result)) { return true; } // Use the past directory mappings to build the equivalent // local path for the source file. int index = sourceFile.LastIndexOf(Path.DirectorySeparatorChar); while (index > 0) { if (sourcePathMap_.TryGetValue(sourceFile.Substring(0, index), out string mappedDirectory)) { result = Path.Combine(mappedDirectory, sourceFile.Substring(index + 1)); return true; } index = sourceFile.LastIndexOf(Path.DirectorySeparatorChar, index - 1); } result = null; return false; } public void UpdateMap(string originalPath, string mappedPath) { if (string.IsNullOrEmpty(originalPath) || string.IsNullOrEmpty(mappedPath)) { return; } sourceFileCache_[originalPath] = mappedPath; // Try to create a mapping between the directory paths, // to be used later with another source file part of the same // directory structure. int prevOriginalPath = originalPath.Length; int prevMappedPath = mappedPath.Length; int originalPathIndex = originalPath.LastIndexOf(Path.DirectorySeparatorChar); int mappedPathIndex = mappedPath.LastIndexOf(Path.DirectorySeparatorChar); while (originalPathIndex > 0 && mappedPathIndex > 0) { // Stop once there is a mismatch in directory names. // Use a case-insensitive compare for Windows paths. if (!originalPath.Substring(originalPathIndex, prevOriginalPath - originalPathIndex).Equals( mappedPath.Substring(mappedPathIndex, prevMappedPath - mappedPathIndex), StringComparison.OrdinalIgnoreCase)) { return; } sourcePathMap_[originalPath.Substring(0, originalPathIndex)] = mappedPath.Substring(0, mappedPathIndex); prevOriginalPath = originalPathIndex; prevMappedPath = mappedPathIndex; originalPathIndex = originalPath.LastIndexOf(Path.DirectorySeparatorChar, prevOriginalPath - 1); mappedPathIndex = mappedPath.LastIndexOf(Path.DirectorySeparatorChar, prevMappedPath - 1); } } } ================================================ FILE: src/ProfileExplorerCore/Utilities/Utils.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Xml; using Microsoft.Win32; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.Core.Utilities; public static class Utils { private static readonly TaskFactory TaskFactoryInstance = new(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default); private static readonly string HTML_COPY_HEADER = "Version:0.9\r\n" + "StartHTML:{0:0000000000}\r\n" + "EndHTML:{1:0000000000}\r\n" + "StartFragment:{2:0000000000}\r\n" + "EndFragment:{3:0000000000}\r\n"; private static readonly string HTML_COPY_START = "\r\n" + "\r\n" + ""; private static readonly string HTML_COPY_END = "\r\n" + "\r\n" + ""; public static TResult RunSync(Func> func) { return TaskFactoryInstance.StartNew>(func). Unwrap().GetAwaiter().GetResult(); } public static void RunSync(Func func) { TaskFactoryInstance.StartNew(func).Unwrap().GetAwaiter().GetResult(); } //? TODO: This should be part of the IR NameProvider public static string MakeBlockDescription(BlockIR block) { if (block == null) { return ""; } if (block.HasLabel && !string.IsNullOrEmpty(block.Label.Name)) { return $"B{block.Number} ({block.Label.Name})"; } return $"B{block.Number}"; } //? TODO: This should be part of the IR NameProvider public static string MakeElementDescription(IRElement element) { switch (element) { case BlockIR block: return MakeBlockDescription(block); case InstructionIR instr: { var builder = new StringBuilder(); bool needsComma = false; if (instr.Destinations.Count > 0) { foreach (var destOp in instr.Destinations) { if (needsComma) { builder.Append(", "); } else { needsComma = true; } builder.Append(MakeElementDescription(destOp)); } builder.Append(" = "); } builder.Append($"{instr.OpcodeText} "); needsComma = false; foreach (var sourceOp in instr.Sources) { if (needsComma) { builder.Append(", "); } else { needsComma = true; } builder.Append(MakeElementDescription(sourceOp)); } return builder.ToString(); } case OperandIR op: { string text = GetSymbolName(op); switch (op.Kind) { case OperandKind.Address: case OperandKind.LabelAddress: { text = $"&{text}"; break; } case OperandKind.Indirection: { text = $"[{MakeElementDescription(op.IndirectionBaseValue)}]"; break; } case OperandKind.IntConstant: { text = op.IntValue.ToString(); break; } case OperandKind.FloatConstant: { text = op.FloatValue.ToString(); break; } } var ssaTag = op.GetTag(); if (ssaTag != null) { text += $"<{ssaTag.DefinitionId}>"; } return text; } default: return element.ToString(); } } //? TODO: This should be part of the IR NameProvider public static string GetSymbolName(OperandIR op) { if (op.HasName) { return op.NameValue.ToString(); } return ""; } public static void Swap(ref T a, ref T b) { var temp = a; a = b; b = temp; } public static string GetAutoSaveFilePath() { string AUTO_SAVE_TEMP_FILE = "autosave.pex"; return Path.Combine(Path.GetTempPath(), AUTO_SAVE_TEMP_FILE); } public static bool TryDeleteFile(string path) { if (!File.Exists(path)) { return false; } try { File.Delete(path); } catch (Exception ex) { Trace.WriteLine($"Failed to delete {path}: {ex.Message}"); return false; } return true; } public static string TryGetFileName(string path) { try { if (string.IsNullOrEmpty(path)) { return ""; } return Path.GetFileName(path); } catch (Exception ex) { return ""; } } public static string TryGetFileNameWithoutExtension(string path) { try { if (string.IsNullOrEmpty(path)) { return ""; } return Path.GetFileNameWithoutExtension(path); } catch (Exception ex) { return ""; } } public static string TryGetDirectoryName(string path) { try { if (string.IsNullOrEmpty(path)) { return ""; } if (!Directory.Exists(path)) { path = Path.GetDirectoryName(path); } // Remove \ at the end. if (path.EndsWith(Path.DirectorySeparatorChar) || path.EndsWith(Path.AltDirectorySeparatorChar)) { path = path.Substring(0, path.Length - 1); } return path; } catch (Exception ex) { return ""; } } public static string CleanupPath(string path) { if (string.IsNullOrEmpty(path)) { return path; } path = path.Trim(); if (path.Length >= 2 && path[0] == '"' && path[^1] == '"') { path = path.Substring(1, path.Length - 2); } return path; } public static bool OpenExternalFile(string path, bool checkFileExists = true) { if (checkFileExists && !File.Exists(path)) { return false; } try { var psi = new ProcessStartInfo(path) { UseShellExecute = true }; Process.Start(psi); return true; } catch (Exception ex) { Trace.TraceError($"Failed to open file: {path}, exception {ex.Message}"); return false; } } public static bool OpenURL(string path) { return OpenExternalFile(path, false); } public static bool ExecuteTool(string path, string args, CancelableTask cancelableTask = null, Dictionary envVariables = null) { return ExecuteToolWithOutput(path, args, cancelableTask, envVariables) != null; } public static string ExecuteToolWithOutput(string path, string args, CancelableTask cancelableTask = null, Dictionary envVariables = null) { if (!File.Exists(path)) { return null; } Trace.TraceInformation($"Executing tool {path} with args {args}"); var outputText = new StringBuilder(); var procInfo = new ProcessStartInfo(path) { Arguments = args, UseShellExecute = false, CreateNoWindow = true, RedirectStandardError = false, RedirectStandardOutput = true }; if (envVariables != null) { foreach (var pair in envVariables) { procInfo.EnvironmentVariables[pair.Key] = pair.Value; } } try { using var process = new Process {StartInfo = procInfo, EnableRaisingEvents = true}; process.OutputDataReceived += (sender, e) => { outputText.AppendLine(e.Data); }; process.Start(); process.BeginOutputReadLine(); do { process.WaitForExit(100); if (cancelableTask != null && cancelableTask.IsCanceled) { Trace.TraceWarning($"Task {ObjectTracker.Track(cancelableTask)}: Canceled"); process.Kill(); return null; } } while (!process.HasExited); process.CancelOutputRead(); if (process.ExitCode != 0) { Trace.TraceError($"Task {ObjectTracker.Track(cancelableTask)}: Failed with error code: {process.ExitCode}"); Trace.TraceError($" Output:\n{outputText}"); return null; } } catch (Exception ex) { Trace.TraceError($"Task {ObjectTracker.Track(cancelableTask)}: Failed with exception: {ex.Message}"); return null; } return outputText.ToString(); } public static string DetectMSVCPath() { // https://devblogs.microsoft.com/cppblog/finding-the-visual-c-compiler-tools-in-visual-studio-2017/ string vswherePath = @"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"; string vswhereArgs = @"-latest -prerelease -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath"; vswherePath = Environment.ExpandEnvironmentVariables(vswherePath); try { string vsPath = ExecuteToolWithOutput(vswherePath, vswhereArgs); if (string.IsNullOrEmpty(vsPath)) { Trace.TraceError("Failed to run vswhere"); return null; } vsPath = vsPath.SplitLinesRemoveEmpty().First(); string msvcPathInfo = Path.Combine(vsPath, @"VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt"); string msvcVersion = File.ReadLines(msvcPathInfo).First(); return Path.Combine(vsPath, @"VC\Tools\MSVC", msvcVersion, @"bin\HostX64\x64"); } catch (Exception ex) { Trace.TraceError($"Failed to find MSVC path: {ex.Message}"); } return null; } public static DebugFileSearchResult LocateDebugInfoFile(string imagePath, string extension) { try { if (!File.Exists(imagePath)) { return DebugFileSearchResult.None; } string path = Path.GetDirectoryName(imagePath); string imageName = Path.GetFileNameWithoutExtension(imagePath); string pdbPath = Path.Combine(path, imageName) + extension; if (File.Exists(pdbPath)) { return DebugFileSearchResult.Success(pdbPath); } } catch (Exception ex) { Trace.TraceError($"Failed to find debug file for {imagePath}: {ex.Message}"); } return DebugFileSearchResult.None; } public static bool IsBinaryFile(string filePath) { return FileHasExtension(filePath, ".exe") || FileHasExtension(filePath, ".dll") || FileHasExtension(filePath, ".sys"); } public static bool IsExecutableFile(string filePath) { return FileHasExtension(filePath, ".exe"); } public static bool FileHasExtension(string filePath, string extension) { if (string.IsNullOrEmpty(filePath)) { return false; } try { extension = extension.ToLowerInvariant(); if (!extension.StartsWith(".")) { extension = $".{extension}"; } return Path.GetExtension(filePath).ToLowerInvariant() == extension; } catch (Exception ex) { Trace.TraceError($"Failed FileHasExtension for {filePath}: {ex}"); return false; } } public static string GetFileExtension(string filePath) { if (string.IsNullOrEmpty(filePath)) { return ""; } try { return Path.GetExtension(filePath); } catch (Exception ex) { Trace.TraceError($"Failed GetFileExtension for {filePath}: {ex}"); return ""; } } public static long ComputeDirectorySize(string path, bool recursive = false) { try { if (!Directory.Exists(path)) { return 0; } long total = 0; foreach (string file in Directory.EnumerateFileSystemEntries(path)) { if (!File.GetAttributes(file).HasFlag(FileAttributes.Directory)) { total += new FileInfo(file).Length; } else if (recursive) { total += ComputeDirectorySize(file, true); } } return total; } catch { return 0; } } public static void OpenExplorerAtFile(string path) { if (!File.Exists(path) && !Directory.Exists(path)) { return; } try { Process.Start("explorer.exe", "/select, " + path); } catch (Exception ex) { Trace.WriteLine($"Failed to start explorer.exe for {path}: {ex.Message}"); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static double SnapToPixels(double value) { return Math.Round(value); } private static bool IsOptionsUpdateEvent(string sourceName) { return sourceName != "Button" && sourceName != "ToggleButton" && sourceName != "TextBox" && sourceName != "TextBoxView" && sourceName != "TextBlock"; } public static string ConvertHtmlToClipboardFormat(string html) { var encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); byte[] data = Array.Empty(); byte[] header = encoding.GetBytes(string.Format(HTML_COPY_HEADER, 0, 1, 2, 3)); data = data.Concat(header).ToArray(); int startHtml = data.Length; data = data.Concat(encoding.GetBytes(HTML_COPY_START)).ToArray(); int startFragment = data.Length; data = data.Concat(encoding.GetBytes(html)).ToArray(); int endFragment = data.Length; data = data.Concat(encoding.GetBytes(HTML_COPY_END)).ToArray(); int endHtml = data.Length; byte[] newHeader = encoding.GetBytes( string.Format(HTML_COPY_HEADER, startHtml, endHtml, startFragment, endFragment)); Array.Copy(newHeader, data, startHtml); return encoding.GetString(data); } public static string RemovePathQuotes(string text) { if (string.IsNullOrEmpty(text)) { return text; } return text.Trim('\"'); } public struct KeyCharInfo { public bool IsLetter; public char Letter; public bool IsShift; public bool IsControl; public bool IsAlt; } } ================================================ FILE: src/ProfileExplorerCoreTests/ASMIRSectionReaderTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core; using ProfileExplorer.Core.Compilers.ASM; namespace ProfileExplorer.CoreTests; [TestClass] public class ASMIRSectionReaderTests { [TestMethod] public void GenerateSummary_CreatesOneTextInfoPerSection() { string data = @"x264_plane_copy_c: str lr,[sp] x264_frame_init_lowres: sub sp,sp,#0x40 "; byte[] bytes = Encoding.UTF8.GetBytes(data); var (_, capturedText, _1) = GenerateSummaryFor(bytes); Assert.AreEqual(2, capturedText.Count); Assert.AreEqual(1, capturedText[0].TextLines.Count); Assert.AreEqual(" str lr,[sp]", capturedText[0].TextLines[0]); Assert.AreEqual(1, capturedText[1].TextLines.Count); Assert.AreEqual(" sub sp,sp,#0x40", capturedText[1].TextLines[0]); } [TestMethod] public void GenerateSummary_GivesNPlus1ProgressUpdates() { string data = @"x264_plane_copy_c: str lr,[sp] x264_frame_init_lowres: sub sp,sp,#0x40 "; byte[] bytes = Encoding.UTF8.GetBytes(data); var (_, _1, capturedProgressInfo) = GenerateSummaryFor(bytes); // 1 progress for each section + 1 "done" Assert.AreEqual(3, capturedProgressInfo.Count); // processed all bytes Assert.AreEqual(bytes.Length, capturedProgressInfo[2].BytesProcessed); foreach (var info in capturedProgressInfo) { Assert.AreEqual(bytes.Length, info.TotalBytes); } } [TestMethod] public void GenerateSummary_CreatesCorrectIROutputForFunctions() { string data = @"x264_plane_copy_c: str lr,[sp] x264_frame_init_lowres: sub sp,sp,#0x40 "; byte[] bytes = Encoding.UTF8.GetBytes(data); var (summary, _, _1) = GenerateSummaryFor(bytes); Assert.AreEqual(2, summary.Functions.Count); Action verifyFunctionBody = (f, expected) => { int start = (int)f.Sections[0].Output.DataStartOffset; int size = (int)f.Sections[0].Output.Size; Assert.AreEqual(expected, Encoding.UTF8.GetString(bytes, start, size)); }; var copy = summary.Functions.Find(f => f.Name == "x264_plane_copy_c"); Assert.IsNotNull(copy); Assert.AreEqual(1, copy.SectionCount); verifyFunctionBody(copy, " str lr,[sp]\r\n"); var init = summary.Functions.Find(f => f.Name == "x264_frame_init_lowres"); Assert.IsNotNull(init); Assert.AreEqual(1, init.SectionCount); verifyFunctionBody(init, " sub sp,sp,#0x40\r\n"); } private (IRTextSummary, List, List) GenerateSummaryFor(byte[] input) { var reader = new ASMIRSectionReader(input, true); var capturedText = new List(); var capturedProgressInfo = new List(); var summary = reader.GenerateSummary((reader, info) => { capturedProgressInfo.Add(info); }, (reader, text) => { capturedText.Add(text); }); return (summary, capturedText, capturedProgressInfo); } } ================================================ FILE: src/ProfileExplorerCoreTests/CompressedSegmentedListTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core.Collections; namespace ProfileExplorer.CoreTests; public struct TestObject { public int a, b, c, d; public static int Counter; public static TestObject Create() { var result = new TestObject { a = Counter, b = Counter + 1, c = Counter + 2, d = Counter + 3 }; Counter += 4; return result; } } public struct TestGuidObject { public Guid a, b; public static TestGuidObject Create() { var result = new TestGuidObject { a = Guid.NewGuid(), b = Guid.NewGuid() }; return result; } } [TestClass] public class CompressedSegmentedListTests { [TestMethod] public void TestAdd() { var list = new CompressedSegmentedList(); int count = 100000; TestObject.Counter = 0; for (int i = 0; i < count; i++) { list.Add(TestObject.Create()); } Assert.AreEqual(list.Count, count); int counter = 0; for (int i = 0; i < 10000; i++) { var item = list[i]; Assert.AreEqual(item.a, counter); Assert.AreEqual(item.b, counter + 1); Assert.AreEqual(item.c, counter + 2); Assert.AreEqual(item.d, counter + 3); counter += 4; } } [TestMethod] public void TestEnumerator() { var list = new CompressedSegmentedList(); int count = 100000; TestObject.Counter = 0; for (int i = 0; i < count; i++) { list.Add(TestObject.Create()); } int counter = 0; foreach (var item in list) { Assert.AreEqual(item.a, counter); Assert.AreEqual(item.b, counter + 1); Assert.AreEqual(item.c, counter + 2); Assert.AreEqual(item.d, counter + 3); counter += 4; } } [TestMethod] public void TestContains() { var list = new CompressedSegmentedList(); int count = 10000; TestObject.Counter = 0; for (int i = 0; i < count; i++) { list.Add(TestObject.Create()); } TestObject.Counter = 0; for (int i = 0; i < count; i++) { Assert.IsTrue(list.Contains(TestObject.Create())); } } [TestMethod] public void TestIndexOf() { var list = new CompressedSegmentedList(); int count = 10000; TestObject.Counter = 0; for (int i = 0; i < count; i++) { list.Add(TestObject.Create()); } TestObject.Counter = 0; for (int i = 0; i < count; i++) { Assert.AreEqual(i, list.IndexOf(TestObject.Create())); } } [TestMethod] public void TestHuge() { var list = new CompressedSegmentedList(); int count = 1000000; TestObject.Counter = 0; for (int i = 0; i < count; i++) { list.Add(TestObject.Create()); } int counter = 0; foreach (var item in list) { Assert.AreEqual(item.a, counter); Assert.AreEqual(item.b, counter + 1); Assert.AreEqual(item.c, counter + 2); Assert.AreEqual(item.d, counter + 3); counter += 4; } } [TestMethod] public void TestRandom() { var list = new CompressedSegmentedList(); int count = 1000000; TestObject.Counter = 0; var checkList = new List(); var orderList = new List(); for (int i = 0; i < count; i++) { var obj = TestObject.Create(); list.Add(obj); checkList.Add(obj); orderList.Add(i); } var random = new Random(31); orderList = orderList.OrderBy(x => random.Next()).ToList(); for (int i = 0; i < count; i++) { int index = orderList[i]; var item = list[index]; var checkItem = checkList[index]; Assert.AreEqual(item.a, checkItem.a); Assert.AreEqual(item.b, checkItem.b); Assert.AreEqual(item.c, checkItem.c); Assert.AreEqual(item.d, checkItem.d); } } [TestMethod] public void TestPrefetch() { var list = new CompressedSegmentedList(true, true, 10); int count = 1000000; TestObject.Counter = 0; for (int i = 0; i < count; i++) { list.Add(TestObject.Create()); } int counter = 0; foreach (var item in list) { Assert.AreEqual(item.a, counter); Assert.AreEqual(item.b, counter + 1); Assert.AreEqual(item.c, counter + 2); Assert.AreEqual(item.d, counter + 3); counter += 4; } } [TestMethod] public void TestGuid() { var list = new CompressedSegmentedList(); int count = 1000000; var checkList = new List(); var orderList = new List(); for (int i = 0; i < count; i++) { var obj = TestGuidObject.Create(); list.Add(obj); checkList.Add(obj); orderList.Add(i); } var random = new Random(31); //orderList = orderList.OrderBy(x => random.Next()).ToList(); for (int i = 0; i < count; i++) { int index = orderList[i]; var item = list[index]; var checkItem = checkList[index]; Assert.AreEqual(item.a, checkItem.a); Assert.AreEqual(item.b, checkItem.b); } } [TestMethod] public void TestGuidRandom() { var list = new CompressedSegmentedList(); int count = 1000000; var checkList = new List(); var orderList = new List(); for (int i = 0; i < count; i++) { var obj = TestGuidObject.Create(); list.Add(obj); checkList.Add(obj); orderList.Add(i); } var random = new Random(31); orderList = orderList.OrderBy(x => random.Next()).ToList(); for (int i = 0; i < count; i++) { int index = orderList[i]; var item = list[index]; var checkItem = checkList[index]; Assert.AreEqual(item.a, checkItem.a); Assert.AreEqual(item.b, checkItem.b); } } } ================================================ FILE: src/ProfileExplorerCoreTests/ETWUnmappedFrameResolutionTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.ETW; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.CoreTests; /// /// Verifies that samples from dynamically generated code /// (LUA JIT, Java JIT, etc.) whose IPs don't map to any loaded module are /// properly attributed rather than silently dropped. /// /// Integration tests exercise the actual ETWProfileDataProvider code path. /// Processor tests verify FunctionProfileProcessor and FunctionsForSamplesProcessor /// handle the resulting frames correctly (these processors are not covered by /// the existing SyntheticProfileTests in the UI test project). /// [TestClass] public class ETWUnmappedFrameResolutionTests { private static readonly BindingFlags NonPublic = BindingFlags.Instance | BindingFlags.NonPublic; #region Integration tests — actual ETWProfileDataProvider code path [TestMethod] public async Task ProcessUnresolvedStack_UnmappedIP_CreatesAttributedFrame() { var (rawProfile, process, context) = CreateRawProfile(1000, 2000, "test.exe", "WorkerThread"); rawProfile.AddImageToProcess(1000, new ProfileImage("test.exe", "test.exe", 0x10000, 0x10000, 0x1000, 0, 0)); rawProfile.LoadingCompleted(); var provider = CreateProvider(); GetProfileData(provider).AddThreads(process.Threads(rawProfile)); InvokePreCreateUnknownModule(provider, rawProfile, 1000); var stack = new ProfileStack { ContextId = 1, FramePointers = new long[] { 0xAAAAAA } }; var resolved = await InvokeProcessUnresolvedStack(provider, stack, context, rawProfile); Assert.AreEqual(1, resolved.FrameCount); var frame = resolved.StackFrames[0]; Assert.IsFalse(frame.IsUnknown, "Unmapped IP should produce an attributed frame, not Unknown"); Assert.IsNotNull(frame.FrameDetails.Image); Assert.IsNotNull(frame.FrameDetails.Function); StringAssert.Contains(frame.FrameDetails.Function.Name, "JIT"); } [TestMethod] public async Task ProcessUnresolvedStack_MixedStack_BothFramesAttributed() { var (rawProfile, process, context) = CreateRawProfile(1001, 2001, "mixed.exe", null); rawProfile.AddImageToProcess(1001, new ProfileImage("mixed.exe", "mixed.exe", 0x10000, 0x10000, 0x10000, 0, 0)); rawProfile.LoadingCompleted(); var provider = CreateProvider(); GetProfileData(provider).AddThreads(process.Threads(rawProfile)); InvokePreCreateUnknownModule(provider, rawProfile, 1001); // Frame 0 (leaf): unmapped. Frame 1 (root): inside mixed.exe. var stack = new ProfileStack { ContextId = 1, FramePointers = new long[] { 0xCCCCCC, 0x10500 } }; var resolved = await InvokeProcessUnresolvedStack(provider, stack, context, rawProfile); Assert.AreEqual(2, resolved.FrameCount); Assert.IsFalse(resolved.StackFrames[0].IsUnknown, "Unmapped frame should not be Unknown"); Assert.IsFalse(resolved.StackFrames[1].IsUnknown, "Mapped frame should not be Unknown"); Assert.AreEqual("mixed.exe", resolved.StackFrames[1].FrameDetails.Image.ModuleName); } [TestMethod] public async Task ProcessUnresolvedStack_ConsecutiveUnmappedIPs_CollapsedToOneFrame() { var (rawProfile, process, context) = CreateRawProfile(1002, 2002, "collapse.exe", null); rawProfile.AddImageToProcess(1002, new ProfileImage("collapse.exe", "collapse.exe", 0x90000, 0x90000, 0x10000, 0, 0)); rawProfile.LoadingCompleted(); var provider = CreateProvider(); GetProfileData(provider).AddThreads(process.Threads(rawProfile)); InvokePreCreateUnknownModule(provider, rawProfile, 1002); // 3 consecutive unmapped IPs followed by a known frame. var stack = new ProfileStack { ContextId = 1, FramePointers = new long[] { 0xBB0001, 0xBB0002, 0xBB0003, 0x90500 } }; var resolved = await InvokeProcessUnresolvedStack(provider, stack, context, rawProfile); // Consecutive unmapped frames should be collapsed to 1 JIT frame + 1 known frame = 2 total Assert.AreEqual(2, resolved.FrameCount, "3 consecutive unmapped IPs should collapse to 1 JIT frame"); StringAssert.Contains(resolved.StackFrames[0].FrameDetails.Function.Name, "JIT"); Assert.AreEqual("collapse.exe", resolved.StackFrames[1].FrameDetails.Image.ModuleName); } [TestMethod] public async Task ProcessUnresolvedStack_KernelUnmappedIP_RoutedToUnknownNotJit() { var (rawProfile, process, context) = CreateRawProfile(1003, 2003, "kernel.exe", null); rawProfile.LoadingCompleted(); var provider = CreateProvider(); GetProfileData(provider).AddThreads(process.Threads(rawProfile)); InvokePreCreateUnknownModule(provider, rawProfile, 1003); // Kernel-range IP that doesn't map to any module. var stack = new ProfileStack { ContextId = 1, FramePointers = new long[] { unchecked((long)0xFFFFF80012340000UL) } }; var resolved = await InvokeProcessUnresolvedStack(provider, stack, context, rawProfile); Assert.AreEqual(1, resolved.FrameCount); Assert.IsTrue(resolved.StackFrames[0].IsUnknown, "Unmapped kernel IP should be Unknown, not attributed as JIT"); } [TestMethod] public async Task ProcessUnresolvedStack_NoPreCreate_FallsBackToUnknown() { var (rawProfile, process, context) = CreateRawProfile(1004, 2004, "fallback.exe", null); rawProfile.LoadingCompleted(); var provider = CreateProvider(); GetProfileData(provider).AddThreads(process.Threads(rawProfile)); // Deliberately NOT calling InvokePreCreateUnknownModule. var stack = new ProfileStack { ContextId = 1, FramePointers = new long[] { 0xDD0001 } }; var resolved = await InvokeProcessUnresolvedStack(provider, stack, context, rawProfile); Assert.AreEqual(1, resolved.FrameCount); Assert.IsTrue(resolved.StackFrames[0].IsUnknown, "Without pre-created module, unmapped IP should fall back to Unknown"); } [TestMethod] public void PreCreateUnknownModule_ProducesConsistentState() { var rawProfile = new RawProfileData("test.etl"); rawProfile.TraceInfo.PointerSize = 8; rawProfile.GetOrCreateProcess(3000); rawProfile.LoadingCompleted(); var provider = CreateProvider(); InvokePreCreateUnknownModule(provider, rawProfile, 3000); var getModule = typeof(ETWProfileDataProvider).GetMethod("GetUnknownModule", NonPublic); var state = getModule.Invoke(provider, new object[] { 3000 }); Assert.IsNotNull(state, "Pre-created module should be retrievable"); } [TestMethod] public void GetOrCreateThreadFunction_PerThreadIsolation() { var rawProfile = new RawProfileData("test.etl"); rawProfile.TraceInfo.PointerSize = 8; rawProfile.GetOrCreateProcess(3001); rawProfile.LoadingCompleted(); var provider = CreateProvider(); var profileData = GetProfileData(provider); for (int t = 0; t < 5; t++) profileData.Threads[4000 + t] = new ProfileThread(4000 + t, 3001, $"Worker{t}"); InvokePreCreateUnknownModule(provider, rawProfile, 3001); var getModule = typeof(ETWProfileDataProvider).GetMethod("GetUnknownModule", NonPublic); var unknownState = getModule.Invoke(provider, new object[] { 3001 }); var getFunc = unknownState.GetType().GetMethod("GetOrCreateThreadFunction"); var results = new ConcurrentBag<(int Tid, string Name)>(); var tasks = new List(); for (int round = 0; round < 10; round++) for (int t = 0; t < 5; t++) { int tid = 4000 + t; tasks.Add(Task.Run(() => { var r = ((IRTextFunction, FunctionDebugInfo))getFunc.Invoke( unknownState, new object[] { tid }); results.Add((tid, r.Item1.Name)); })); } Task.WaitAll(tasks.ToArray()); Assert.AreEqual(5, results.Select(r => r.Name).Distinct().Count(), "Each thread should get a distinct function"); foreach (var g in results.GroupBy(r => r.Tid)) Assert.AreEqual(1, g.Select(r => r.Name).Distinct().Count(), $"Thread {g.Key} should always return the same function"); } #endregion #region Processor tests — FunctionProfileProcessor / FunctionsForSamplesProcessor [TestMethod] public void FunctionProfileProcessor_ExclusiveWeightGoesToLeafNotCaller() { // Core bug: before the fix, Unknown leaf frames were skipped and // ExclusiveWeight was mis-attributed to the deepest known caller. var profileData = new ProfileData(); var unknownImage = CreateUnknownModuleImage(); profileData.Modules[RealImage.Id] = RealImage; profileData.Modules[unknownImage.Id] = unknownImage; var mainFunc = new IRTextFunction("main"); var mainInfo = new FunctionDebugInfo("main", 0x100, 64); var unknownFunc = new IRTextFunction("[JIT Thread 500]"); var unknownInfo = new FunctionDebugInfo("[JIT Thread 500]", 500, 1); for (int i = 0; i < 2; i++) { var stack = new ProfileStack(contextId: 1, framePtrs: new long[2]); var resolved = new ResolvedProfileStack(2, new ProfileContext(100, 500, 0)); resolved.AddFrame(unknownFunc, 0x50000 + i, unknownInfo.RVA, 0, new ResolvedProfileStackFrameKey(unknownInfo, unknownImage, false), stack, 8); resolved.AddFrame(mainFunc, 0x51100 + i, mainInfo.RVA, 1, new ResolvedProfileStackFrameKey(mainInfo, RealImage, false), stack, 8); profileData.Samples.Add(( new ProfileSample(0x50000 + i, TimeSpan.FromMilliseconds(i * 10), TimeSpan.FromMilliseconds(10), false, 0), resolved)); } profileData.ComputeThreadSampleRanges(); var result = FunctionProfileProcessor.Compute(profileData, new ProfileSampleFilter()); Assert.AreEqual(TimeSpan.FromMilliseconds(20), result.FunctionProfiles[unknownFunc].ExclusiveWeight, "Leaf (JIT) should get exclusive weight"); Assert.AreEqual(TimeSpan.Zero, result.FunctionProfiles[mainFunc].ExclusiveWeight, "Caller (main) should NOT get exclusive weight — it's not the leaf"); Assert.AreEqual(TimeSpan.FromMilliseconds(20), result.FunctionProfiles[mainFunc].Weight, "Caller (main) should get inclusive weight"); } [TestMethod] public void FunctionProfileProcessor_AllUnmappedStack_WeightPreserved() { var profileData = new ProfileData(); var unknownImage = CreateUnknownModuleImage(); profileData.Modules[unknownImage.Id] = unknownImage; var unknownFunc = new IRTextFunction("[JIT Thread 600]"); var unknownInfo = new FunctionDebugInfo("[JIT Thread 600]", 600, 1); var stack = new ProfileStack(contextId: 1, framePtrs: new long[1]); var resolved = new ResolvedProfileStack(1, new ProfileContext(100, 600, 0)); resolved.AddFrame(unknownFunc, 0xCA01, unknownInfo.RVA, 0, new ResolvedProfileStackFrameKey(unknownInfo, unknownImage, false), stack, 8); profileData.Samples.Add(( new ProfileSample(0xCA01, TimeSpan.Zero, TimeSpan.FromMilliseconds(5), false, 0), resolved)); profileData.ComputeThreadSampleRanges(); var result = FunctionProfileProcessor.Compute(profileData, new ProfileSampleFilter()); Assert.AreEqual(TimeSpan.FromMilliseconds(5), result.ProfileWeight, "Profile weight must include unmapped-code-only samples"); Assert.AreEqual(TimeSpan.FromMilliseconds(5), result.FunctionProfiles[unknownFunc].ExclusiveWeight); } [TestMethod] public void FunctionsForSamplesProcessor_IncludesUnmappedCodeFunctions() { var profileData = new ProfileData(); var unknownImage = CreateUnknownModuleImage(); profileData.Modules[unknownImage.Id] = unknownImage; var unknownFunc = new IRTextFunction("[JIT Thread 800]"); var unknownInfo = new FunctionDebugInfo("[JIT Thread 800]", 800, 1); var stack = new ProfileStack(contextId: 1, framePtrs: new long[1]); var resolved = new ResolvedProfileStack(1, new ProfileContext(100, 800, 0)); resolved.AddFrame(unknownFunc, 0xBA01, unknownInfo.RVA, 0, new ResolvedProfileStackFrameKey(unknownInfo, unknownImage, false), stack, 8); profileData.Samples.Add(( new ProfileSample(0xBA01, TimeSpan.Zero, TimeSpan.FromMilliseconds(1), false, 0), resolved)); profileData.ComputeThreadSampleRanges(); Assert.IsTrue( FunctionsForSamplesProcessor.Compute(new ProfileSampleFilter(), profileData).Contains(unknownFunc), "Unmapped code function must appear in the function set"); } #endregion #region Helpers private static readonly ProfileImage RealImage = new("app.exe", "app.exe", 0x1000, 0x1000, 0x100000, 0, 0xABCDEF) { Id = 1 }; private static ProfileImage CreateUnknownModuleImage() => new("[Unknown Module]", "[Unknown Module]", 0, 0, 0, 0, 0) { Id = 9999 }; private static (RawProfileData, ProfileProcess, ProfileContext) CreateRawProfile( int processId, int threadId, string processName, string threadName) { var rawProfile = new RawProfileData("synthetic.etl"); rawProfile.TraceInfo.PointerSize = 8; var process = rawProfile.GetOrCreateProcess(processId); process.Name = processName; process.ImageFileName = processName; rawProfile.AddThreadToProcess(processId, new ProfileThread(threadId, processId, threadName)); var context = new ProfileContext(processId, threadId, 0); typeof(RawProfileData).GetMethod("AddContext", NonPublic)! .Invoke(rawProfile, new object[] { context }); return (rawProfile, process, context); } private static ETWProfileDataProvider CreateProvider() { var provider = new ETWProfileDataProvider(); SetField(provider, "report_", new ProfileDataReport()); SetField(provider, "options_", new ProfileDataProviderOptions()); SetField(provider, "compilerInfoProvider_", new ASMCompilerInfoProvider(IRMode.x86_64)); return provider; } private static ProfileData GetProfileData(ETWProfileDataProvider provider) => (ProfileData)typeof(ETWProfileDataProvider).GetField("profileData_", NonPublic)!.GetValue(provider)!; private static async Task InvokeProcessUnresolvedStack( ETWProfileDataProvider provider, ProfileStack stack, ProfileContext context, RawProfileData rawProfile) => await (Task)typeof(ETWProfileDataProvider) .GetMethod("ProcessUnresolvedStackAsync", NonPublic)! .Invoke(provider, new object[] { stack, context, rawProfile, new SymbolFileSourceSettings() })!; private static void InvokePreCreateUnknownModule(ETWProfileDataProvider provider, RawProfileData rawProfile, int processId) => typeof(ETWProfileDataProvider).GetMethod("PreCreateUnknownModule", NonPublic)! .Invoke(provider, new object[] { rawProfile, processId }); private static void SetField(object obj, string name, object value) => typeof(ETWProfileDataProvider).GetField(name, NonPublic)!.SetValue(obj, value); #endregion } ================================================ FILE: src/ProfileExplorerCoreTests/EndToEndWorkflowTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.ETW; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.CoreTests; /// /// End-to-end workflow tests for Profile Explorer functionality. /// /// These tests validate the complete pipeline from trace loading to assembly analysis by comparing /// extracted data against known baselines. Four types of baselines are validated: /// /// 1. Process Baselines: CPU usage, duration, and process information /// 2. Module Baselines: Time spent per module/DLL /// 3. Function Baselines: Performance data per function /// 4. Assembly Baselines: Assembly/disassembly text for specific binary-function pairs /// /// ADDING NEW TEST CASES: /// /// 1. Add test case name to TestCases list /// 2. (Optional) Add process ID to TestCaseProcessIds if known /// 3. (Optional) Configure assembly baselines in TestCaseAssemblyBaselines /// 4. Create TestData// directory with: /// - Traces/ subdirectory containing ETW trace files /// - Binaries/ subdirectory containing executable/library files /// - Symbols/ subdirectory containing PDB symbol files /// 5. Run GenerateBaseline_ForTestCase (remove [Ignore] attribute) to create baselines /// 6. Re-enable [Ignore] attribute and run TestEndToEndWorkflow_ForTestCase /// /// ADDING ASSEMBLY BASELINES: /// /// Assembly baselines capture the disassembly text for specific functions, which helps detect /// when compiler optimizations or code changes affect the generated assembly. To add new ones: /// /// 1. Add (binary name, function name) pairs to TestCaseAssemblyBaselines for your test case: /// { "MyTestCase", new List<(string, string)> { /// ("MyApp.exe", "main"), /// ("MyLibrary.dll", "CriticalFunction") /// } /// } /// /// 2. Run GenerateBaseline to create assembly__baseline.csv files /// 3. Each CSV contains function names and their complete assembly text /// /// BASELINE FILE STRUCTURE: /// /// TestData// /// ├── processes_baseline.csv (process CPU usage data) /// ├── modules_baseline.csv (module timing data) /// ├── functions__baseline.csv (function performance per module) /// └── assembly__baseline.csv (assembly text per binary) /// /// Example assembly baseline entry: /// FunctionName,AssemblyText /// "main","push rbp\nmov rbp,rsp\nsub rsp,20h\n..." /// /// MAINTENANCE: /// /// - Baselines may need regeneration when: /// * Compiler versions change /// * Build configurations change /// * Code optimizations are modified /// * Symbol resolution improves /// /// - Use GenerateBaseline_ForTestCase to update baselines after intentional changes /// - Review baseline diffs carefully to ensure changes are expected /// [TestClass] public class EndToEndWorkflowTests { /// /// List of test cases to run. Add new test case names here to include them in testing. /// Each test case should have corresponding directories in TestData/Traces/, TestData/Binaries/, and TestData/Symbols/. /// /// The test infrastructure validates multiple types of baselines: /// - Process baselines: CPU usage and process information /// - Module baselines: Time spent per module/DLL /// - Function baselines: Performance data per function /// - Assembly baselines: Assembly/disassembly text for specific binary-function pairs /// /// Assembly baselines are configured in TestCaseAssemblyBaselines and only generated for explicitly /// specified (binary, function) pairs to avoid creating excessive baseline files. /// private static readonly List TestCases = new List { "MsoTrace" // Add new test case names here, e.g.: // "WebBrowserTrace", // "GameEngineTrace", // "DatabaseTrace" }; /// /// Optional: Process IDs for each test case. If not specified, the test will show available processes. /// private static readonly Dictionary TestCaseProcessIds = new Dictionary { { "MsoTrace", 34376 } // Add process IDs for specific test cases if known, e.g.: // { "WebBrowserTrace", 12345 }, // { "GameEngineTrace", 67890 } }; /// /// Configuration for assembly baseline generation. Each test case maps to a list of (binary name, function name) pairs /// for which assembly/disassembly text should be retrieved and baselined. /// /// To add assembly baselines for a new test case: /// 1. Add the test case name as a key in this dictionary /// 2. Provide a list of (binary, function) tuples for the functions you want to baseline /// 3. Run the GenerateBaseline test to create the baseline CSV files /// 4. The test will create assembly_.csv files in the TestData// directory /// /// Example: /// { "MyTestCase", new List<(string, string)> { /// ("MyApp.exe", "main"), /// ("MyLibrary.dll", "ImportantFunction"), /// ("MyLibrary.dll", "AnotherFunction") /// } /// } /// private static readonly Dictionary> TestCaseAssemblyBaselines = new Dictionary> { { "MsoTrace", new List<(string, string)> { ("Mso20win32client.dll", "Mso::Experiment::EcsNS::Private::SortByParameterGroups") // Add more (binary, function) pairs here as needed: // ("Mso20win32client.dll", "AnotherFunction"), // ("OtherBinary.dll", "SomeFunction") } } // Add assembly baseline configurations for other test cases here, e.g.: // { "WebBrowserTrace", new List<(string, string)> { // ("browser.exe", "RenderPage"), // ("engine.dll", "ProcessHTML") // } // } }; /// /// Data structure representing a process baseline entry /// public class ProcessBaselineEntry { public string Name { get; set; } public double WeightPercentage { get; set; } public double DurationMs { get; set; } public int ProcessId { get; set; } public string CommandLine { get; set; } } /// /// Data structure representing a module baseline entry /// public class ModuleBaselineEntry { public string Name { get; set; } public double WeightPercentage { get; set; } public double TimeMs { get; set; } } /// /// Data structure representing a function baseline entry /// public class FunctionBaselineEntry { public string Name { get; set; } public string Address { get; set; } public string Module { get; set; } public double SelfTimePercentage { get; set; } public double SelfTimeMs { get; set; } public double TotalTimePercentage { get; set; } public double TotalTimeMs { get; set; } } /// /// Data structure representing an assembly baseline entry for a specific binary and function pair. /// Contains the assembly/disassembly text that should be consistent across test runs. /// public class AssemblyBaselineEntry { public string BinaryName { get; set; } public string FunctionName { get; set; } public string AssemblyText { get; set; } } [DataTestMethod] [DynamicData(nameof(GetTestCaseData), DynamicDataSourceType.Method)] public async Task TestEndToEndWorkflow_ForTestCase(string testCaseName) { Console.WriteLine($"\n=== Running End-to-End Workflow Test for: {testCaseName} ==="); // Execute common workflow steps var (processBaselineData, moduleBaselineData, functionBaselineData, assemblyBaselineData) = await ExecuteCommonWorkflowSteps(testCaseName); // Step 7: Compare with baselines Console.WriteLine($"\n=== Step 7: Baseline Validation ==="); var baselineDir = GetBaselineDirectory(testCaseName); var processBaselinePath = Path.Combine(baselineDir, "processes_baseline.csv"); var moduleBaselinePath = Path.Combine(baselineDir, "modules_baseline.csv"); bool baselinesExist = File.Exists(processBaselinePath) && File.Exists(moduleBaselinePath); // Check if function baseline files exist for all modules if (baselinesExist) { foreach (var moduleName in functionBaselineData.Keys) { var functionBaselinePath = Path.Combine(baselineDir, $"functions_{SanitizeFileName(moduleName)}_baseline.csv"); if (!File.Exists(functionBaselinePath)) { baselinesExist = false; break; } } } // Check if assembly baseline files exist for all binaries if (baselinesExist) { foreach (var binaryName in assemblyBaselineData.Keys) { var assemblyBaselinePath = Path.Combine(baselineDir, $"assembly_{SanitizeFileName(binaryName)}_baseline.csv"); if (!File.Exists(assemblyBaselinePath)) { baselinesExist = false; break; } } } if (baselinesExist) { // Save current results to temporary CSV files in system temp directory var tempDir = Path.Combine(Path.GetTempPath(), "ProfileExplorerTests", $"Baseline_{testCaseName}_{Guid.NewGuid():N}"); Directory.CreateDirectory(tempDir); try { var currentProcessFile = Path.Combine(tempDir, "processes_baseline.csv"); var currentModulesFile = Path.Combine(tempDir, "modules_baseline.csv"); SaveProcessBaseline(processBaselineData, currentProcessFile); SaveModuleBaseline(moduleBaselineData, currentModulesFile); // Save function baselines grouped by module foreach (var moduleGroup in functionBaselineData) { var currentFunctionFile = Path.Combine(tempDir, $"functions_{SanitizeFileName(moduleGroup.Key)}_baseline.csv"); SaveFunctionBaseline(moduleGroup.Value, currentFunctionFile); } // Save assembly baselines grouped by binary foreach (var binaryGroup in assemblyBaselineData) { var currentAssemblyFile = Path.Combine(tempDir, $"assembly_{SanitizeFileName(binaryGroup.Key)}_baseline.csv"); SaveAssemblyBaseline(binaryGroup.Value, currentAssemblyFile); } // Compare CSV files directly CompareBaselineFiles(baselineDir, tempDir, testCaseName); Console.WriteLine($"✓ All baselines match for test case '{testCaseName}'"); } finally { // Clean up temporary files if (Directory.Exists(tempDir)) { Directory.Delete(tempDir, true); } } } else { Assert.Inconclusive($"Baselines not found for test case '{testCaseName}'. Run the GenerateBaseline test first to create them."); } Console.WriteLine($"\n✓ Workflow completed successfully for test case '{testCaseName}'"); } /// /// Test method to generate or regenerate baseline CSV files for a test case. /// This should be run whenever you need to create new baselines or update existing ones. /// [Ignore] // Remove to save baselines [DataTestMethod] [DynamicData(nameof(GetTestCaseData), DynamicDataSourceType.Method)] public async Task GenerateBaseline_ForTestCase(string testCaseName) { Console.WriteLine($"\n=== Generating Baselines for: {testCaseName} ==="); // Execute common workflow steps var (processBaselineData, moduleBaselineData, functionBaselineData, assemblyBaselineData) = await ExecuteCommonWorkflowSteps(testCaseName); // Step 7: Save baselines to TestData folder Console.WriteLine($"\n=== Step 7: Saving Baselines ==="); var baselineDir = GetBaselineDirectory(testCaseName); Directory.CreateDirectory(baselineDir); var processBaselinePath = Path.Combine(baselineDir, "processes_baseline.csv"); var moduleBaselinePath = Path.Combine(baselineDir, "modules_baseline.csv"); SaveProcessBaseline(processBaselineData, processBaselinePath); SaveModuleBaseline(moduleBaselineData, moduleBaselinePath); // Save function baselines for each module var totalFunctions = 0; foreach (var moduleEntry in functionBaselineData) { var moduleName = moduleEntry.Key; var functions = moduleEntry.Value; var functionBaselinePath = Path.Combine(baselineDir, $"functions_{SanitizeFileName(moduleName)}_baseline.csv"); SaveFunctionBaseline(functions, functionBaselinePath); totalFunctions += functions.Count; Console.WriteLine($" - Functions for {moduleName}: {functions.Count} entries -> {functionBaselinePath}"); } // Save assembly baselines for each binary var totalAssemblyFunctions = 0; foreach (var binaryEntry in assemblyBaselineData) { var binaryName = binaryEntry.Key; var assemblyFunctions = binaryEntry.Value; var assemblyBaselinePath = Path.Combine(baselineDir, $"assembly_{SanitizeFileName(binaryName)}_baseline.csv"); SaveAssemblyBaseline(assemblyFunctions, assemblyBaselinePath); totalAssemblyFunctions += assemblyFunctions.Count; Console.WriteLine($" - Assembly for {binaryName}: {assemblyFunctions.Count} functions -> {assemblyBaselinePath}"); } Console.WriteLine($"✓ Baselines saved to TestData folder for test case '{testCaseName}'"); Console.WriteLine($" - Processes: {processBaselineData.Count} entries -> {processBaselinePath}"); Console.WriteLine($" - Modules: {moduleBaselineData.Count} entries -> {moduleBaselinePath}"); Console.WriteLine($" - Functions: {totalFunctions} entries across {functionBaselineData.Count} modules"); Console.WriteLine($" - Assembly: {totalAssemblyFunctions} functions across {assemblyBaselineData.Count} binaries"); Console.WriteLine($"\n✓ Baseline generation completed successfully for test case '{testCaseName}'"); } /// /// Executes the common workflow steps (1-5) shared by both test methods /// private async Task<(List processBaselineData, List moduleBaselineData, Dictionary> functionBaselineData, Dictionary> assemblyBaselineData)> ExecuteCommonWorkflowSteps(string testCaseName) { // Get test case information var testCase = TestDataHelper.GetTestCase(testCaseName); if (!testCase.IsValid) { Assert.Inconclusive($"Test case '{testCaseName}' is not valid:\n{testCase.GetSummary()}"); } var options = new ProfileDataProviderOptions(); var cancelableTask = new CancelableTask(); // Step 1: Load list of processes from trace Console.WriteLine("=== Step 1: Loading process list from trace ==="); var processList = await ETWProfileDataProvider.FindTraceProcesses( testCase.TracePath, options, progress => { Console.WriteLine($"Process discovery: {progress.Current}/{progress.Total}"); }, cancelableTask); Assert.IsNotNull(processList, "Failed to load process list from trace"); Assert.IsTrue(processList.Count > 0, "No processes found in trace"); // Extract process baseline data var processBaselineData = ExtractProcessBaselineData(processList); // Determine target process ID int targetProcessId; if (TestCaseProcessIds.TryGetValue(testCaseName, out targetProcessId)) { var targetProcess = processList.FirstOrDefault(p => p.Process.ProcessId == targetProcessId); if (targetProcess == null) { Console.WriteLine($"WARNING: Configured process ID {targetProcessId} not found in trace."); Console.WriteLine($"Available process IDs: {string.Join(", ", processList.Select(p => p.Process.ProcessId))}"); Assert.Inconclusive($"Target process ID {targetProcessId} not found in trace for test case '{testCaseName}'"); } } else { // Use the process with the highest weight var sortedProcesses = processList.OrderByDescending(p => p.Weight).ToList(); targetProcessId = sortedProcesses.First().Process.ProcessId; Console.WriteLine($"No specific process ID configured for '{testCaseName}', using process with highest weight: {targetProcessId}"); } // Step 2: Configure symbol settings Console.WriteLine($"\n=== Step 2: Configuring symbol settings ==="); var symbolSettings = new SymbolFileSourceSettings(); symbolSettings.SymbolPaths.Clear(); // Clear any default paths symbolSettings.InsertSymbolPath(testCase.BinariesPath); // Add our binaries directory symbolSettings.InsertSymbolPath(testCase.SymbolsPath); // Add our symbols directory symbolSettings.SourceServerEnabled = false; // Disable symbol servers symbolSettings.UseEnvironmentVarSymbolPaths = false; // Disable environment symbol paths Console.WriteLine($"Symbol paths configured: {string.Join("; ", symbolSettings.SymbolPaths)}"); Console.WriteLine($"Available PDB files: {testCase.PdbFiles.Count}"); foreach (var pdb in testCase.PdbFiles) { Console.WriteLine($" - {Path.GetFileName(pdb)}"); } // Step 3: Load trace data for the target process Console.WriteLine($"\n=== Step 3: Loading trace data for process {targetProcessId} ==="); var session = new BaseSession(); var processIds = new List { targetProcessId }; var report = new ProfileDataReport(); bool loadResult = await session.LoadProfileData( testCase.TracePath, processIds, options, symbolSettings, report, progress => { Console.WriteLine($"Data processing: {progress.Stage} - {progress.Current}/{progress.Total} {progress.Optional}"); }, cancelableTask); Assert.IsTrue(loadResult, "Failed to load profile data"); var profileData = session.ProfileData; Assert.IsNotNull(profileData, "Profile data is null after successful load"); Console.WriteLine("Data processing completed successfully"); // Step 4: Get module baseline data Console.WriteLine($"\n=== Step 4: Extracting Module Information ==="); var moduleBaselineData = ExtractModuleBaselineData(profileData); // Step 5: Get function baseline data Console.WriteLine($"\n=== Step 5: Extracting Function Information ==="); var functionBaselineData = ExtractFunctionBaselineData(profileData); // Step 6: Get assembly baseline data Console.WriteLine($"\n=== Step 6: Extracting Assembly Information ==="); var assemblyBaselineData = await ExtractAssemblyBaselineData(session, testCaseName); return (processBaselineData, moduleBaselineData, functionBaselineData, assemblyBaselineData); } /// /// Gets the baseline directory path in the source TestData folder /// private string GetBaselineDirectory(string testCaseName) { // Get the source TestData directory, not the runtime one var testProjectDir = Path.GetDirectoryName(typeof(EndToEndWorkflowTests).Assembly.Location); var sourceTestDataDir = Path.GetFullPath(Path.Combine(testProjectDir!, "..", "..", "..", "TestData")); return Path.Combine(sourceTestDataDir, testCaseName); } /// /// Sanitizes a filename by removing invalid characters /// private string SanitizeFileName(string fileName) { var invalidChars = Path.GetInvalidFileNameChars(); return string.Join("_", fileName.Split(invalidChars, StringSplitOptions.RemoveEmptyEntries)); } /// /// Extracts process baseline data from the process list /// private List ExtractProcessBaselineData(List processList) { var sortedProcesses = processList.OrderByDescending(p => p.Weight).ToList(); var baselineData = new List(); foreach (var process in sortedProcesses) { baselineData.Add(new ProcessBaselineEntry { Name = process.Process.Name ?? "Unknown", WeightPercentage = process.WeightPercentage, DurationMs = process.Duration.TotalMilliseconds, ProcessId = process.Process.ProcessId, CommandLine = process.Process.CommandLine ?? "N/A" }); } return baselineData; } /// /// Extracts module baseline data from the profile data /// private List ExtractModuleBaselineData(ProfileData profileData) { var moduleInfoList = new List(); foreach (var moduleKvp in profileData.Modules) { var moduleId = moduleKvp.Key; var module = moduleKvp.Value; var moduleName = module.ModuleName ?? $"Module_{moduleId}"; // Get weight for this module TimeSpan moduleWeight = TimeSpan.Zero; if (profileData.ModuleWeights.TryGetValue(moduleId, out var weight)) { moduleWeight = weight; } // Skip modules with zero time if (moduleWeight.TotalMilliseconds <= 0) { continue; } // Calculate percentage double weightPercentage = profileData.ScaleModuleWeight(moduleWeight) * 100; double timeMs = moduleWeight.TotalMilliseconds; moduleInfoList.Add(new ModuleBaselineEntry { Name = moduleName, WeightPercentage = weightPercentage, TimeMs = timeMs }); } // Sort by descending weight percentage return moduleInfoList.OrderByDescending(m => m.WeightPercentage).ToList(); } /// /// Extracts function baseline data from the profile data using call tree, grouped by module /// private Dictionary> ExtractFunctionBaselineData(ProfileData profileData) { var functionsByModule = new Dictionary>(); if (profileData.CallTree == null) { return functionsByModule; } // Get all functions from the call tree by collecting from all root nodes var allFunctionNodes = new List(); foreach (var rootNode in profileData.CallTree.RootNodes) { var functions = profileData.CallTree.GetTopFunctions(rootNode); allFunctionNodes.AddRange(functions); } // Group by function to avoid duplicates and combine weights var functionGroups = allFunctionNodes .GroupBy(node => node.Function) .ToList(); foreach (var group in functionGroups) { var function = group.Key; if (function == null) continue; // Sum up weights from all instances of this function var totalWeight = TimeSpan.Zero; var totalExclusiveWeight = TimeSpan.Zero; var firstNode = group.First(); foreach (var node in group) { totalWeight += node.Weight; totalExclusiveWeight += node.ExclusiveWeight; } // Skip functions with zero self time if (totalExclusiveWeight.TotalMilliseconds <= 0) { continue; } // Calculate percentages double selfTimePercentage = profileData.ScaleFunctionWeight(totalExclusiveWeight) * 100; double totalTimePercentage = profileData.ScaleFunctionWeight(totalWeight) * 100; var functionEntry = new FunctionBaselineEntry { Name = function.Name ?? "Unknown", Address = firstNode.FunctionDebugInfo?.RVA.ToString("X") ?? "Unknown", Module = function.ModuleName ?? "Unknown", SelfTimePercentage = selfTimePercentage, SelfTimeMs = totalExclusiveWeight.TotalMilliseconds, TotalTimePercentage = totalTimePercentage, TotalTimeMs = totalWeight.TotalMilliseconds }; // Group by module var moduleName = functionEntry.Module; if (!functionsByModule.ContainsKey(moduleName)) { functionsByModule[moduleName] = new List(); } functionsByModule[moduleName].Add(functionEntry); } // Sort functions within each module by descending self time percentage foreach (var moduleEntry in functionsByModule) { moduleEntry.Value.Sort((a, b) => b.SelfTimePercentage.CompareTo(a.SelfTimePercentage)); } return functionsByModule; } /// /// Extracts assembly baseline data for configured binary and function pairs from the session. /// Returns a dictionary grouped by binary name, where each entry contains the assembly text for functions in that binary. /// private async Task>> ExtractAssemblyBaselineData(ISession session, string testCaseName) { var assemblyByBinary = new Dictionary>(); // Check if this test case has assembly baseline configuration if (!TestCaseAssemblyBaselines.TryGetValue(testCaseName, out var binaryFunctionPairs)) { Console.WriteLine($"No assembly baseline configuration found for test case '{testCaseName}'"); return assemblyByBinary; } Console.WriteLine($"Processing {binaryFunctionPairs.Count} assembly baseline pairs for test case '{testCaseName}'"); foreach (var (binaryName, functionName) in binaryFunctionPairs) { Console.WriteLine($" - Retrieving assembly for {binaryName}::{functionName}"); try { var section = await GetSectionForFunction(session, binaryName, functionName); if (section == null) { Console.WriteLine($" WARNING: Could not find section for {binaryName}::{functionName}"); continue; } var parsedSection = await session.LoadAndParseSection(section); if (parsedSection?.Text == null) { Console.WriteLine($" WARNING: Could not parse section or get assembly text for {binaryName}::{functionName}"); continue; } var assemblyEntry = new AssemblyBaselineEntry { BinaryName = binaryName, FunctionName = functionName, AssemblyText = parsedSection.Text.ToString() }; // Group by binary if (!assemblyByBinary.ContainsKey(binaryName)) { assemblyByBinary[binaryName] = new List(); } assemblyByBinary[binaryName].Add(assemblyEntry); Console.WriteLine($" ✓ Retrieved {parsedSection.Text.Length} characters of assembly text"); } catch (Exception ex) { Console.WriteLine($" ERROR: Failed to retrieve assembly for {binaryName}::{functionName}: {ex.Message}"); // Continue processing other pairs instead of failing the entire test } } // Sort functions within each binary alphabetically for consistent ordering foreach (var binaryEntry in assemblyByBinary) { binaryEntry.Value.Sort((a, b) => string.Compare(a.FunctionName, b.FunctionName, StringComparison.OrdinalIgnoreCase)); } Console.WriteLine($"Successfully extracted assembly data for {assemblyByBinary.Values.Sum(list => list.Count)} functions across {assemblyByBinary.Count} binaries"); return assemblyByBinary; } /// /// Saves process baseline data to CSV file /// private void SaveProcessBaseline(List data, string filePath) { var csv = new StringBuilder(); csv.AppendLine("Name,WeightPercentage,DurationMs,ProcessId,CommandLine"); foreach (var entry in data.OrderByDescending(x => x.WeightPercentage).ThenBy(x => x.Name)) { csv.AppendLine($"\"{EscapeCsvValue(entry.Name)}\"," + $"{entry.WeightPercentage.ToString("F4", CultureInfo.InvariantCulture)}," + $"{entry.DurationMs.ToString("F4", CultureInfo.InvariantCulture)}," + $"{entry.ProcessId}," + $"\"{EscapeCsvValue(entry.CommandLine)}\""); } File.WriteAllText(filePath, csv.ToString()); } /// /// Saves module baseline data to CSV file /// private void SaveModuleBaseline(List data, string filePath) { var csv = new StringBuilder(); csv.AppendLine("Name,WeightPercentage,TimeMs"); foreach (var entry in data.OrderByDescending(x => x.TimeMs).ThenBy(x => x.Name)) { csv.AppendLine($"\"{EscapeCsvValue(entry.Name)}\"," + $"{entry.WeightPercentage.ToString("F4", CultureInfo.InvariantCulture)}," + $"{entry.TimeMs.ToString("F4", CultureInfo.InvariantCulture)}"); } File.WriteAllText(filePath, csv.ToString()); } /// /// Saves function baseline data to CSV file /// private void SaveFunctionBaseline(List data, string filePath) { var csv = new StringBuilder(); csv.AppendLine("Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs"); foreach (var entry in data.OrderByDescending(x => x.SelfTimeMs).ThenBy(x => x.Name)) { csv.AppendLine($"\"{EscapeCsvValue(entry.Name)}\"," + $"\"{EscapeCsvValue(entry.Address)}\"," + $"\"{EscapeCsvValue(entry.Module)}\"," + $"{entry.SelfTimePercentage.ToString("F4", CultureInfo.InvariantCulture)}," + $"{entry.SelfTimeMs.ToString("F4", CultureInfo.InvariantCulture)}," + $"{entry.TotalTimePercentage.ToString("F4", CultureInfo.InvariantCulture)}," + $"{entry.TotalTimeMs.ToString("F4", CultureInfo.InvariantCulture)}"); } File.WriteAllText(filePath, csv.ToString()); } /// /// Saves assembly baseline data to CSV file for a specific binary. /// Each row contains the function name and its complete assembly/disassembly text. /// private void SaveAssemblyBaseline(List data, string filePath) { var csv = new StringBuilder(); csv.AppendLine("FunctionName,AssemblyText"); foreach (var entry in data.OrderBy(x => x.FunctionName)) { csv.AppendLine($"\"{EscapeCsvValue(entry.FunctionName)}\"," + $"\"{EscapeCsvValue(entry.AssemblyText)}\""); } File.WriteAllText(filePath, csv.ToString()); } /// /// Loads assembly baseline data from CSV file for debugging or manual inspection purposes. /// private List LoadAssemblyBaseline(string filePath, string binaryName) { var entries = new List(); if (!File.Exists(filePath)) { return entries; } var lines = File.ReadAllLines(filePath); if (lines.Length <= 1) { // Skip header or empty files return entries; } for (int i = 1; i < lines.Length; i++) { // Skip header line var line = lines[i]; if (string.IsNullOrWhiteSpace(line)) continue; // Simple CSV parsing - assumes properly escaped values var parts = ParseCsvLine(line); if (parts.Count >= 2) { entries.Add(new AssemblyBaselineEntry { BinaryName = binaryName, FunctionName = UnescapeCsvValue(parts[0]), AssemblyText = UnescapeCsvValue(parts[1]) }); } } return entries; } /// /// Simple CSV line parser that handles quoted values /// private List ParseCsvLine(string line) { var parts = new List(); var current = new StringBuilder(); bool inQuotes = false; for (int i = 0; i < line.Length; i++) { char c = line[i]; if (c == '"') { if (inQuotes && i + 1 < line.Length && line[i + 1] == '"') { // Double quote escape current.Append('"'); i++; // Skip next quote } else { inQuotes = !inQuotes; } } else if (c == ',' && !inQuotes) { parts.Add(current.ToString()); current.Clear(); } else { current.Append(c); } } parts.Add(current.ToString()); return parts; } /// /// Unescapes CSV values by handling double quotes /// private string UnescapeCsvValue(string value) { if (string.IsNullOrEmpty(value)) return ""; return value.Replace("\"\"", "\""); } /// /// Compares current process data with baseline /// private void CompareBaselineFiles(string baselineDir, string tempDir, string testCaseName) { // Get all baseline CSV files var baselineFiles = Directory.GetFiles(baselineDir, "*_baseline.csv"); foreach (var baselineFile in baselineFiles) { var fileName = Path.GetFileName(baselineFile); var currentFile = Path.Combine(tempDir, fileName); if (!File.Exists(currentFile)) { Assert.Fail($"Current results file not found: {fileName}"); } var baselineContent = File.ReadAllText(baselineFile); var currentContent = File.ReadAllText(currentFile); if (baselineContent != currentContent) { var fileType = GetFileTypeFromName(fileName); Assert.Fail($"Baseline mismatch in {fileType} for test case '{testCaseName}'. " + $"File: {fileName}\n" + $"Expected content length: {baselineContent.Length}\n" + $"Actual content length: {currentContent.Length}\n" + $"First difference at character: {FindFirstDifference(baselineContent, currentContent)}"); } } } private async Task GetSectionForFunction(ISession session, string targetModuleName, string targetFunctionName) { // Assume you have: string targetModuleName, string targetFunctionName // And you have loaded: List summaries (one per module/binary) List summaries = session.Documents .Select(doc => doc.Summary) .Where(summary => summary != null) .ToList(); foreach (var summary in summaries) { // Match the module/binary name (case-insensitive) if (!string.Equals(summary.ModuleName, targetModuleName, StringComparison.OrdinalIgnoreCase)) continue; // Find the function by name (case-insensitive, adjust matching as needed) var function = summary.Functions .FirstOrDefault(f => session.CompilerInfo.NameProvider.FormatFunctionName(f).Contains(targetFunctionName)); if (function != null && function.SectionCount > 0) { // Use the first section (or select a specific one if needed) return function.Sections[0]; } } return null; } private string GetFileTypeFromName(string fileName) { if (fileName.StartsWith("processes_")) return "processes"; if (fileName.StartsWith("modules_")) return "modules"; if (fileName.StartsWith("functions_")) return "functions"; if (fileName.StartsWith("assembly_")) return "assembly"; return "unknown"; } private int FindFirstDifference(string expected, string actual) { int minLength = Math.Min(expected.Length, actual.Length); for (int i = 0; i < minLength; i++) { if (expected[i] != actual[i]) { return i; } } return minLength; // Difference is in length } /// /// Helper method to escape CSV values /// private string EscapeCsvValue(string value) { if (string.IsNullOrEmpty(value)) return ""; return value.Replace("\"", "\"\""); } /// /// Provides test case data for parameterized tests. /// /// Test case data for MSTest DataTestMethod public static IEnumerable GetTestCaseData() { foreach (var testCase in TestCases) { yield return new object[] { testCase }; } } } ================================================ FILE: src/ProfileExplorerCoreTests/ExtensionMethodsTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.CoreTests; [TestClass] public class ExtensionMethodsTests { [TestMethod] public void CountLines_EmptyString_ReturnsZero() { string emptyString = ""; int result = emptyString.CountLines(); Assert.AreEqual(0, result); } [TestMethod] public void CountLines_SingleLineString_ReturnsOne() { string singleLineString = "This is a single line."; int result = singleLineString.CountLines(); Assert.AreEqual(1, result); } [TestMethod] public void CountLines_MultiLineString_ReturnsCorrectCount() { string multiLineString = "Line 1\nLine 2\nLine 3"; int result = multiLineString.CountLines(); Assert.AreEqual(3, result); } [TestMethod] public void CountLines_MultiLineString_ReturnsCorrectCount2() { string multiLineString = "Line 1\r\nLine 2\nLine 3\rLine4"; int result = multiLineString.CountLines(); Assert.AreEqual(4, result); } [TestMethod] public void CountLines_MultiLineString_ReturnsCorrectCount3() { string multiLineString = "Line 1\r\nLine 2\nLine 3\r\nLine4"; int result = multiLineString.CountLines(); Assert.AreEqual(4, result); } [TestMethod] public void CountLines_MultiLineString_ReturnsCorrectCount4() { string multiLineString = "Line 1\r\nLine 2\nLine 3\rLine4\n\rLine6"; int result = multiLineString.CountLines(); Assert.AreEqual(6, result); } } ================================================ FILE: src/ProfileExplorerCoreTests/FileFormat/FileArchiveTest.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core.FileFormat; namespace ProfileExplorer.CoreTests.FileFormat; [TestClass] public class FileArchiveTest { private const string InPath = @"testFiles"; private const string OutPath = @"outTestFiles"; private const string ResultPath = @"resultTestFiles"; [TestInitialize] public void Initialize() { Directory.CreateDirectory(InPath); Directory.CreateDirectory(OutPath); Directory.CreateDirectory(ResultPath); } [TestCleanup] public void Cleanup() { RecursiveDelete(new DirectoryInfo(InPath)); RecursiveDelete(new DirectoryInfo(OutPath)); RecursiveDelete(new DirectoryInfo(ResultPath)); } [TestMethod] public async Task TestCreateAsync() { string path = $@"{ResultPath}\archive.zip"; using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); Assert.IsTrue(new FileInfo(path).Length > 0); } [TestMethod] public async Task TestAddFileAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileAsync(file1)); Assert.IsTrue(await archive.AddFileAsync(file2)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\file2.txt")); } [TestMethod] public async Task TestAddFileStreamAsync() { string path = $@"{ResultPath}\archive.zip"; var stream = CreateTestStream(1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileStreamAsync(stream, @"file1.txt")); Assert.IsTrue(await archive.AddFileAsync(file2)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsTrue(AreFilesEqual(stream, $@"{OutPath}\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\file2.txt")); } [TestMethod] public async Task TestAddDirectoryAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddDirectoryAsync(InPath)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\file2.txt")); } [TestMethod] public async Task TestAddDirectoryWithSubdirsAsync() { string path = $@"{ResultPath}\archive.zip"; Directory.CreateDirectory($@"{InPath}\subdir"); string file1 = CreateTestFile($@"{InPath}\subdir\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\subdir\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 1023); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddDirectoryAsync(InPath, true, searchPattern: "*", optionalDirectory: "clientSubdir")); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\clientSubdir\subdir\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\clientSubdir\subdir\file2.txt")); Assert.IsTrue(AreFilesEqual(file3, $@"{OutPath}\clientSubdir\file3.txt")); } [TestMethod] public async Task TestAddDirectoryWithoutSubdirsAsync() { string path = $@"{ResultPath}\archive.zip"; Directory.CreateDirectory($@"{InPath}\subdir"); string file1 = CreateTestFile($@"{InPath}\subdir\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\subdir\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 1023); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddDirectoryAsync(InPath, false)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsFalse(AreFilesEqual(file1, $@"{OutPath}\subdir\file1.txt")); Assert.IsFalse(AreFilesEqual(file2, $@"{OutPath}\subdir\file2.txt")); Assert.IsTrue(AreFilesEqual(file3, $@"{OutPath}\file3.txt")); } [TestMethod] public async Task TestAddDirectoryFilteringAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.dat", 4095); string file3 = CreateTestFile($@"{InPath}\file3.dat", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddDirectoryAsync(InPath, false, searchPattern: "*.dat")); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsFalse(AreFilesEqual(file1, $@"{OutPath}\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\file2.dat")); Assert.IsTrue(AreFilesEqual(file3, $@"{OutPath}\file3.dat")); } [TestMethod] public async Task TestLoadAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileAsync(file1)); Assert.IsTrue(await archive.AddFileAsync(file2)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); Assert.IsTrue(loadedArchive.FileCount == 2); Assert.IsNotNull(loadedArchive.Files.Find(entry => entry.Name == "file1.txt")); Assert.IsNotNull(loadedArchive.Files.Find(entry => entry.Name == "file2.txt")); } [TestMethod] public async Task TestExtractFileToDirectoryAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileAsync(file1)); Assert.IsTrue(await archive.AddFileAsync(file2)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); Assert.IsTrue(await loadedArchive.ExtractFileToDirectoryAsync("file1.txt", OutPath)); Assert.IsTrue(await loadedArchive.ExtractFileToDirectoryAsync("file2.txt", OutPath)); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\file2.txt")); } [TestMethod] public async Task TestExtractAllToDirectoryAsync() { string path = $@"{ResultPath}\archive.zip"; Directory.CreateDirectory($@"{InPath}\subdir"); string file1 = CreateTestFile($@"{InPath}\subdir\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\subdir\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 1023); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddDirectoryAsync(InPath, false)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); await FileArchive.ExtractAllToDirectoryAsync(path, OutPath); Assert.IsFalse(AreFilesEqual(file1, $@"{OutPath}\subdir\file1.txt")); Assert.IsFalse(AreFilesEqual(file2, $@"{OutPath}\subdir\file2.txt")); Assert.IsTrue(AreFilesEqual(file3, $@"{OutPath}\file3.txt")); } [TestMethod] public async Task TestExtractFileToStreamAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); await FileArchive.CreateFromFileAsync(file1, path, CompressionLevel.Fastest); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); Assert.IsTrue(loadedArchive.FileCount == 1); using var outStream = await loadedArchive.ExtractFileToMemoryAsync("file1.txt"); Assert.IsNotNull(outStream); Assert.IsTrue(AreFilesEqual(outStream, file1)); } [TestMethod] public async Task TestCreateFromFileAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); await FileArchive.CreateFromFileAsync(file1, path, CompressionLevel.Fastest); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\file1.txt")); } [TestMethod] public async Task TestCreateFromStreamAsync() { string path = $@"{ResultPath}\archive.zip"; var stream = CreateTestStream(1023); await FileArchive.CreateFromStreamAsync(stream, "file1.txt", path, CompressionLevel.Fastest); Assert.IsTrue(File.Exists(path)); ZipFile.ExtractToDirectory(path, OutPath); Assert.IsTrue(AreFilesEqual(stream, $@"{OutPath}\file1.txt")); } [TestMethod] public async Task TestGetFilesOfKind() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileAsync(file1, 123, null, false)); Assert.IsTrue(await archive.AddFileAsync(file2, 456, null, false)); Assert.IsTrue(await archive.AddFileAsync(file3, 123, null, false)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); Assert.IsTrue(loadedArchive.FileCount == 3); Assert.IsTrue(loadedArchive.HasFilesOfKind(123)); Assert.IsTrue(loadedArchive.HasFilesOfKind(456)); Assert.IsTrue(loadedArchive.FindFilesOfKind(123).Count() == 2); Assert.IsTrue(loadedArchive.FindFilesOfKind(456).Count() == 1); } [TestMethod] public async Task TestFindFilesInDirectory() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileAsync(file1, 123, "foo", false)); Assert.IsTrue(await archive.AddFileAsync(file2, 456, "bar", false)); Assert.IsTrue(await archive.AddFileAsync(file3, 123, "foobar", false)); Assert.IsTrue(await archive.AddFileAsync(file1, 123, "foo\\bar", false)); Assert.IsTrue(await archive.AddFileAsync(file2, 456, "foo\\bar", false)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); var result1 = loadedArchive.FindFilesInDirectory("bar"); Assert.IsTrue(result1.Count() == 1); Assert.IsTrue(result1.Count(entry => entry.ArchivePath == "bar\\file2.txt") == 1); var result2 = loadedArchive.FindFilesInDirectory("foo"); Assert.IsTrue(result2.Count() == 3); Assert.IsTrue(result2.Count(entry => entry.ArchivePath == "foo\\file1.txt") == 1); Assert.IsTrue(result2.Count(entry => entry.ArchivePath == "foo\\bar\\file1.txt") == 1); Assert.IsTrue(result2.Count(entry => entry.ArchivePath == "foo\\bar\\file2.txt") == 1); var result3 = loadedArchive.FindFilesInDirectory("foo\\bar"); Assert.IsTrue(result3.Count() == 2); Assert.IsTrue(result3.Count(entry => entry.ArchivePath == "foo\\bar\\file1.txt") == 1); Assert.IsTrue(result3.Count(entry => entry.ArchivePath == "foo\\bar\\file2.txt") == 1); await loadedArchive.ExtractFilesToDirectoryAsync(result3, OutPath); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\foo\bar\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\foo\bar\file2.txt")); } [TestMethod] public async Task TestExtractAllFilesOfKindToDirectoryAsync() { string path = $@"{ResultPath}\archive.zip"; string file1 = CreateTestFile($@"{InPath}\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 4095); using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); Assert.IsTrue(await archive.AddFileAsync(file1, 123, null, false)); Assert.IsTrue(await archive.AddFileAsync(file2, 456, null, false)); Assert.IsTrue(await archive.AddFileAsync(file3, 456, "foo", false)); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); await loadedArchive.ExtractAllFilesOfKindToDirectoryAsync(456, OutPath); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\file2.txt")); Assert.IsTrue(AreFilesEqual(file3, $@"{OutPath}\foo\file3.txt")); } [TestMethod] public async Task TestOptionalData() { string path = $@"{ResultPath}\archive.zip"; using var archive = await FileArchive.CreateAsync(path, CompressionLevel.Fastest); var data = new ExtraData() { Value1 = 123, Value2 = 456, Value3 = "foo" }; archive.SetOptionalData(data); Assert.IsTrue(await archive.SaveAsync()); Assert.IsTrue(File.Exists(path)); using var loadedArchive = await FileArchive.LoadAsync(path); Assert.IsNotNull(loadedArchive); Assert.IsTrue(loadedArchive.HasOptionalData); var loadedData = loadedArchive.GetOptionalData(); Assert.IsTrue(loadedData.Value1 == 123); Assert.IsTrue(loadedData.Value2 == 456); Assert.IsTrue(loadedData.Value3 == "foo"); } [TestMethod] public async Task TestPlainZipFile() { string path = $@"{ResultPath}\archive.zip"; Directory.CreateDirectory($@"{InPath}\subdir"); string file1 = CreateTestFile($@"{InPath}\subdir\file1.txt", 1023); string file2 = CreateTestFile($@"{InPath}\subdir\file2.txt", 4095); string file3 = CreateTestFile($@"{InPath}\file3.txt", 1023); // Create zip file without included header, // extracting files should still work. ZipFile.CreateFromDirectory(InPath, path, CompressionLevel.Fastest, false); Assert.IsTrue(File.Exists(path)); await FileArchive.ExtractAllToDirectoryAsync(path, OutPath); Assert.IsTrue(AreFilesEqual(file1, $@"{OutPath}\subdir\file1.txt")); Assert.IsTrue(AreFilesEqual(file2, $@"{OutPath}\subdir\file2.txt")); Assert.IsTrue(AreFilesEqual(file3, $@"{OutPath}\file3.txt")); } private MemoryStream CreateTestStream(int size) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); var rand = new Random(21); for (int i = 0; i < size; i++) { writer.Write((char)rand.Next(127)); } writer.Flush(); stream.Flush(); stream.Position = 0; return stream; } private string CreateTestFile(string name, int size) { using var fileStream = new FileStream(name, FileMode.Create); using var stream = CreateTestStream(size); stream.CopyTo(fileStream); fileStream.Flush(); fileStream.Close(); return name; } private static void RecursiveDelete(DirectoryInfo baseDir) { if (!baseDir.Exists) return; foreach (var dir in baseDir.EnumerateDirectories()) { RecursiveDelete(dir); } baseDir.Delete(true); } private static bool AreFilesEqual(string fileA, string fileB) { try { byte[] data1 = File.ReadAllBytes(fileA); byte[] data2 = File.ReadAllBytes(fileB); return data1.SequenceEqual(data2); } catch { return false; } } private static bool AreFilesEqual(Stream stream, string fileB) { try { byte[] data1 = new byte[stream.Length]; stream.Position = 0; stream.Read(data1, 0, (int)stream.Length); byte[] data2 = File.ReadAllBytes(fileB); return data1.SequenceEqual(data2); } catch { return false; } } private class ExtraData { public int Value1 { get; set; } public int Value2 { get; set; } public string Value3 { get; set; } } } ================================================ FILE: src/ProfileExplorerCoreTests/ProfileExplorerCoreTests.csproj ================================================  net8.0 false AnyCPU default ProfilerExplorerCoreTests ================================================ FILE: src/ProfileExplorerCoreTests/SourceFileMapperTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core; namespace ProfileExplorer.CoreTests; [TestClass] public class SourceFileMapperTests { [TestMethod] public void Map_FirstTime_ReturnsResultFromLookup() { var mapper = new SourceFileMapper(); bool called = false; const string expectedResult = @"c:\mapped\path\to\file.txt"; Assert.AreEqual(expectedResult, mapper.Map(@"c:\path\to\file.txt", () => { called = true; return expectedResult; })); Assert.IsTrue(called); } [TestMethod] public void Map_SecondTimeForSamePath_DoesNotUseLookup() { var mapper = new SourceFileMapper(); const string expectedResult = @"c:\mapped\path\to\file.txt"; const string source = @"c:\path\to\file.txt"; // prime it mapper.Map(source, () => expectedResult); Assert.AreEqual(expectedResult, mapper.Map(source, () => { Assert.Fail(); return ""; })); } [TestMethod] public void OtherFilesInTheSameDirectoryDontUseLookup() { var mapper = new SourceFileMapper(); const string source = @"c:\path\to\file.txt"; const string sourceInSameDir = @"c:\path\to\otherFile.txt"; // prime it mapper.Map(source, () => @"c:\mapped\path\to\file.txt"); const string expectedResult = @"c:\mapped\path\to\otherFile.txt"; Assert.AreEqual(expectedResult, mapper.Map(sourceInSameDir, () => { Assert.Fail(); return ""; })); } [TestMethod] public void OtherFilesWithTheSamePrefixAreMapped() { string file1 = @"c:\path\to\file.txt"; string file2 = @"c:\path\for\other\file.txt"; string mappedFile1 = @"c:\mapped\to\file.txt"; string mappedFile2 = @"c:\mapped\for\other\file.txt"; var mapper = new SourceFileMapper(); // prime it mapper.Map(file1, () => mappedFile1); Assert.AreEqual(mappedFile2, mapper.Map(file2, () => { Assert.Fail(); return ""; })); } [TestMethod] public void OtherFilesWithDeeperHierarchyAreMatched() { string file1 = @"c:\path\to\file.txt"; string file2 = @"c:\path\to\deeper\file.txt"; string mappedFile1 = @"c:\mapped\to\file.txt"; string mappedFile2 = @"c:\mapped\to\deeper\file.txt"; var mapper = new SourceFileMapper(); // prime it mapper.Map(file1, () => mappedFile1); Assert.AreEqual(mappedFile2, mapper.Map(file2, () => { Assert.Fail(); return ""; })); } [TestMethod] public void ResultIsNullWhenLookupIsCanceled() { var mapper = new SourceFileMapper(); Assert.IsNull(mapper.Map(@"c:\path\to\file.txt", () => null)); } [TestMethod] public void Map_FirstTime_NetworkPath() { var mapper = new SourceFileMapper(); bool called = false; const string expectedResult = @"\\network\path\file.txt"; Assert.AreEqual(expectedResult, mapper.Map(@"\\network\path\file.txt", () => { called = true; return expectedResult; })); Assert.IsTrue(called); } [TestMethod] public void Map_FirstTime_NetworkPath_SamePrefix() { const string file1 = @"\\network\to\file.txt"; const string file2 = @"\\network\for\file2.txt"; string mappedFile1 = @"c:\mapped\to\file.txt"; string mappedFile2 = @"c:\mapped\for\file2.txt"; var mapper = new SourceFileMapper(); // prime it mapper.Map(file1, () => mappedFile1); Assert.AreEqual(mappedFile2, mapper.Map(file2, () => { Assert.Fail(); return ""; })); } } ================================================ FILE: src/ProfileExplorerCoreTests/SparseBitVectorTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Linq; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core.Collections; namespace ProfileExplorer.CoreTests; [TestClass] public class SparseBitVectorTests { [TestMethod] public void NodeSetGetBits() { var v = new SparseBitvector.Node(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { v[i] = i % 2 != 0; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { Assert.AreEqual(v[i], i % 2 != 0); } for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { v[i] = true; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { Assert.IsTrue(v[i]); } for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { v[i] = false; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { Assert.IsFalse(v[i]); } } [TestMethod] public void NodeBitCount() { var v = new SparseBitvector.Node(); Assert.AreEqual(v.SetBitCount, 0); Assert.IsFalse(v.HasBitsSet); v[0] = true; Assert.AreEqual(v.SetBitCount, 1); Assert.IsTrue(v.HasBitsSet); v[0] = true; v[3] = true; v[64] = true; v[91] = true; v[150] = true; v[201] = true; v[255] = true; Assert.AreEqual(v.SetBitCount, 7); Assert.IsTrue(v.HasBitsSet); v.ResetAllBits(); Assert.AreEqual(v.SetBitCount, 0); Assert.IsFalse(v.HasBitsSet); for (int i = 0; i < SparseBitvector.Node.BitsPerNode; i++) { Assert.IsFalse(v[i]); } } [TestMethod] public void SetGetBits() { var v = new SparseBitvector(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { v[i] = true; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { Assert.AreEqual(v[i], true); } Assert.AreEqual(v.SetBitCount, SparseBitvector.Node.BitsPerNode * 10); Assert.IsTrue(v.HasBitsSet); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { v[i] = false; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { Assert.AreEqual(v[i], false); } Assert.AreEqual(v.SetBitCount, 0); Assert.IsFalse(v.HasBitsSet); } [TestMethod] public void SetGetBitsAlternate() { var v = new SparseBitvector(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { v[i] = i % 2 == 0; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { Assert.AreEqual(v[i], i % 2 == 0); } Assert.AreEqual(v.SetBitCount, SparseBitvector.Node.BitsPerNode * 10 / 2); Assert.IsTrue(v.HasBitsSet); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { v[i] = i % 2 != 0; } for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { Assert.AreEqual(v[i], i % 2 != 0); } Assert.AreEqual(v.SetBitCount, SparseBitvector.Node.BitsPerNode * 10 / 2); Assert.IsTrue(v.HasBitsSet); } [TestMethod] public void SetGetBitsReverseAlternate() { var v = new SparseBitvector(); int set = 0; for (int i = SparseBitvector.Node.BitsPerNode * 10; i >= 0; i--) { v[i] = i % 2 == 0; set += i % 2 == 0 ? 1 : 0; } for (int i = SparseBitvector.Node.BitsPerNode * 10; i >= 0; i--) { Assert.AreEqual(v[i], i % 2 == 0); } Assert.AreEqual(v.SetBitCount, set); Assert.IsTrue(v.HasBitsSet); } [TestMethod] public void SetGetBitsRandom() { int n = SparseBitvector.Node.BitsPerNode * 100; foreach (int seed in new[] {7, 13, 31, 51, 123}) { var r = new Random(seed); int[] indices = Enumerable.Range(0, n).OrderBy(i => r.Next()).ToArray(); var v = new SparseBitvector(); for (int i = 0; i < n; i++) { v[indices[i]] = true; } for (int i = 0; i < n; i++) { Assert.AreEqual(v[indices[i]], true); } for (int i = 0; i < n; i++) { Assert.AreEqual(v[i], true); } Assert.AreEqual(v.SetBitCount, n); Assert.IsTrue(v.HasBitsSet); indices = Enumerable.Range(0, n).OrderBy(i => r.Next()).ToArray(); for (int i = 0; i < n; i++) { v[indices[i]] = false; } for (int i = 0; i < n; i++) { Assert.AreEqual(v[i], false); } for (int i = 0; i < n; i++) { Assert.AreEqual(v[indices[i]], false); } Assert.AreEqual(v.SetBitCount, 0); Assert.IsFalse(v.HasBitsSet); } } [TestMethod] public void SetGetBitsRandomAlternate() { int n = SparseBitvector.Node.BitsPerNode * 100; foreach (int seed in new[] {7, 13, 31, 51, 123}) { var r = new Random(seed); int[] indices = Enumerable.Range(0, n).OrderBy(i => r.Next()).ToArray(); var v = new SparseBitvector(); for (int i = 0; i < n; i++) { v[indices[i]] = i % 2 == 0; } for (int i = 0; i < n; i++) { Assert.AreEqual(v[indices[i]], i % 2 == 0); } } } [TestMethod] public void And() { var v = new SparseBitvector(); var v2 = new SparseBitvector(); var v3 = new SparseBitvector(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { v[i] = i % 2 == 0; v2[i] = i % 2 == 0; v3[i] = i % 2 != 0; } v2.And(v); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { Assert.AreEqual(v2[i], i % 2 == 0); } v3.And(v); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i++) { Assert.AreEqual(v3[i], false); } } [TestMethod] public void And2() { var v = new SparseBitvector(); var v2 = new SparseBitvector(); var v3 = new SparseBitvector(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i += 64) { SetFromInt(v, 0xABCDEFABCDEFABCD, i); SetFromInt(v2, 0xF0F0F0F0F0F0F0F0, i); SetFromInt(v3, 0xA0C0E0A0C0E0A0C0, i); } v.And(v2); Assert.AreEqual(v, v3); } [TestMethod] public void And3() { foreach (int step in new[] {2, 3, 4}) { var v = new SparseBitvector(); var v2 = new SparseBitvector(); var v3 = new SparseBitvector(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i += 64) { SetFromInt(v, 0xABCDEFABCDEFABCD, i); } for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i += 64 * step) { SetFromInt(v2, 0xF0F0F0F0F0F0F0F0, i); SetFromInt(v3, 0xA0C0E0A0C0E0A0C0, i); } v.And(v2); Assert.AreEqual(v, v3); } foreach (int step in new[] {2, 3, 4}) { var v = new SparseBitvector(); var v2 = new SparseBitvector(); var v3 = new SparseBitvector(); for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i += 64 * step) { SetFromInt(v, 0xABCDEFABCDEFABCD, i); SetFromInt(v3, 0xA0C0E0A0C0E0A0C0, i); } for (int i = 0; i < SparseBitvector.Node.BitsPerNode * 10; i += 64) { SetFromInt(v2, 0xF0F0F0F0F0F0F0F0, i); } v.And(v2); Assert.AreEqual(v, v3); } } private void SetFromInt(SparseBitvector bv, ulong value, int startIndex = 0) { for (int i = 0; i < 64; i++) { bv[startIndex + i] = (value & 1ul << i) != 0; } } } ================================================ FILE: src/ProfileExplorerCoreTests/StringTrieTests.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using Microsoft.VisualStudio.TestTools.UnitTesting; using ProfileExplorer.Core.Collections; namespace ProfileExplorer.CoreTests; [TestClass] public class StringTrieTests { [TestMethod] public void StringValueTest() { var trie = new StringTrie(); var values = new Dictionary { {"abc", "123"}, {"def", "456"}, {"abcd", "234"}, {"abce", "235"}, {"abcr", "236"}, {"abcdef", "124"}, {"abcdet", "125"}, {"dxyz", "126"}, {"dexyz", "127"} }; trie.Build(values); foreach (var pair in values) { bool found = trie.TryGetValue(pair.Key, out string outValue); Assert.IsTrue(found); Assert.AreEqual(outValue, pair.Value); } } [TestMethod] public void StringEnumTest() { var trie = new StringTrie(); var values = new Dictionary { {"abc", TestEnum.Value2}, {"def", TestEnum.Value2}, {"abcd", TestEnum.Value2}, {"abce", TestEnum.Value2}, {"abcr", TestEnum.Value2}, {"abcdef", TestEnum.Value2}, {"abcdet", TestEnum.Value2}, {"dxyz", TestEnum.Value2}, {"dexyz", TestEnum.Value2} }; trie.Build(values); foreach (var pair in values) { bool found = trie.TryGetValue(pair.Key, out var outValue); Assert.IsTrue(found); Assert.AreEqual(outValue, pair.Value); } } [TestMethod] public void RandomStringEnumTest() { for (int length = 1; length < 102; length += 20) { var trie = new StringTrie(); var values = new Dictionary(); var random = new Random(31); for (int i = 0; i < 1000; i++) { string key = GenerateRandomString(length, random); var value = GenerateRandomEnum(random); values[key] = value; } trie.Build(values); foreach (var pair in values) { bool found = trie.TryGetValue(pair.Key, out var outValue); Assert.IsTrue(found); Assert.AreEqual(outValue, pair.Value); } } } private string GenerateRandomString(int length, Random random) { string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; char[] stringChars = new char[length]; for (int i = 0; i < stringChars.Length; i++) { stringChars[i] = chars[random.Next(chars.Length)]; } return new string(stringChars); } private T GenerateRandomEnum(Random random) where T : Enum { var values = Enum.GetValues(typeof(T)); return (T)values.GetValue(random.Next(values.Length)); } private enum TestEnum { Value1, Value2, Value3 } } ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/assembly_Mso20win32client.dll_baseline.csv ================================================ FunctionName,AssemblyText "Mso::Experiment::EcsNS::Private::SortByParameterGroups","180032C3C: mov qword ptr [rsp + 0x18], rbx 180032C41: push rbp 180032C42: push rsi 180032C43: push rdi 180032C44: push r12 180032C46: push r13 180032C48: push r14 180032C4A: push r15 180032C4C: lea rbp, [rsp - 0x27] 180032C51: sub rsp, 0xc0 180032C58: mov rax, qword ptr [rip + 0x81fda1] 180032C5F: xor rax, rsp 180032C62: mov qword ptr [rbp + 0x17], rax 180032C66: mov rdi, rdx 180032C69: mov qword ptr [rbp - 0x59], rdx 180032C6D: xor r12d, r12d 180032C70: cmp qword ptr [rdx], r12 180032C73: je 0x180032f19 180032C79: mov r15, qword ptr [rcx] 180032C7C: mov rsi, qword ptr [rcx + 8] 180032C80: mov qword ptr [rbp - 0x49], rsi 180032C84: cmp r15, rsi 180032C87: je 0x180032f19 180032C8D: mov qword ptr [rbp - 0x69], r12 180032C91: mov qword ptr [rbp - 0x61], r12 180032C95: mov ecx, 0x50 180032C9A: call void * __ptr64 __cdecl std::_Allocate<16,struct std::_Default_allocate_traits>(unsigned __int64) 180032C9F: mov qword ptr [rax], rax 180032CA2: mov qword ptr [rax + 8], rax 180032CA6: mov qword ptr [rax + 0x10], rax 180032CAA: mov word ptr [rax + 0x18], 0x101 180032CB0: mov qword ptr [rbp - 0x69], rax 180032CB4: mov r13, qword ptr [r15] 180032CB7: mov rax, qword ptr [r15 + 8] 180032CBB: mov qword ptr [rbp - 0x51], rax 180032CBF: cmp r13, rax 180032CC2: je 0x180032f5b 180032CC8: mov rdx, r13 180032CCB: lea rcx, [rbp - 9] 180032CCF: call __cdecl std::basic_string,class std::allocator >::basic_string,class std::allocator >(class std::basic_string,class std::allocator > const & __ptr64) __ptr64 180032CD4: lea r9, [rbp - 9] 180032CD8: mov r11, qword ptr [rbp - 9] 180032CDC: cmp qword ptr [rbp + 0xf], 7 180032CE1: cmova r9, r11 180032CE5: lea rcx, [rbp - 9] 180032CE9: cmova rcx, r11 180032CED: mov rax, qword ptr [rbp + 7] 180032CF1: lea r8, [rcx + rax*2] 180032CF5: lea rdx, [rbp - 9] 180032CF9: cmova rdx, r11 180032CFD: mov rax, qword ptr [rip + 0x58b674] 180032D04: mov qword ptr [rsp + 0x20], rax 180032D09: lea rcx, [rbp - 0x41] 180032D0D: call class std::_String_iterator > > __cdecl std::transform > >,class std::_String_iterator > >,int (__cdecl*)(int)>(class std::_String_iterator > >,class std::_String_iterator > >,class std::_String_iterator > >,int (__cdecl*)(int)) 180032D12: mov rax, qword ptr [rdi] 180032D15: mov rbx, qword ptr [rax + 0x18] 180032D19: mov rbx, qword ptr [rbx] 180032D1C: mov rax, qword ptr [rdi] 180032D1F: cmp rbx, qword ptr [rax + 0x18] 180032D23: je 0x180032f40 180032D29: lea r14, [rbx + 0x20] 180032D2D: xorps xmm0, xmm0 180032D30: movups xmmword ptr [rbp - 0x29], xmm0 180032D34: mov qword ptr [rbp - 0x19], r12 180032D38: mov qword ptr [rbp - 0x11], r12 180032D3C: mov rdi, qword ptr [r14 + 0x10] 180032D40: cmp qword ptr [r14 + 0x18], 7 180032D45: jbe 0x180032d4a 180032D47: mov r14, qword ptr [r14] 180032D4A: movabs rax, 0x7ffffffffffffffe 180032D54: cmp rdi, rax 180032D57: ja 0x180032f03 180032D5D: cmp rdi, 7 180032D61: jbe 0x180032d9c 180032D63: mov rsi, rdi 180032D66: or rsi, 7 180032D6A: cmp rsi, rax 180032D6D: ja 0x180032f11 180032D73: mov eax, 0xa 180032D78: cmp rsi, rax 180032D7B: cmovb rsi, rax 180032D7F: lea rcx, [rsi + 1] 180032D83: movabs rax, 0x7fffffffffffffff 180032D8D: cmp rcx, rax 180032D90: jbe 0x180032e7a 180032D96: call void __cdecl std::_Throw_bad_array_new_length(void) 180032D9B: int3 180032D9C: mov qword ptr [rbp - 0x19], rdi 180032DA0: mov edx, 7 180032DA5: mov qword ptr [rbp - 0x11], rdx 180032DA9: movups xmm0, xmmword ptr [r14] 180032DAD: movups xmmword ptr [rbp - 0x29], xmm0 180032DB1: lea r14, [rbp - 0x29] 180032DB5: movq rcx, xmm0 180032DBA: lea rax, [rbp - 0x29] 180032DBE: cmp rdx, 7 180032DC2: cmova rax, rcx 180032DC6: lea r12, [rax + rdi*2] 180032DCA: lea rsi, [rbp - 0x29] 180032DCE: cmova rsi, rcx 180032DD2: cmp rsi, r12 180032DD5: je 0x180032dfd 180032DD7: sub r14, rsi 180032DDA: movzx ecx, word ptr [rsi] 180032DDD: call qword ptr [rip + 0x58b595] 180032DE3: mov word ptr [rsi + r14], ax 180032DE8: add rsi, 2 180032DEC: cmp rsi, r12 180032DEF: jne 0x180032dda 180032DF1: mov rdx, qword ptr [rbp - 0x11] 180032DF5: mov rdi, qword ptr [rbp - 0x19] 180032DF9: mov rcx, qword ptr [rbp - 0x29] 180032DFD: lea rax, [rbp - 9] 180032E01: cmp qword ptr [rbp + 0xf], 7 180032E06: cmova rax, qword ptr [rbp - 9] 180032E0B: lea r9, [rbp - 0x29] 180032E0F: cmp rdx, 7 180032E13: cmova r9, rcx 180032E17: xor r12d, r12d 180032E1A: cmp rdi, qword ptr [rbp + 7] 180032E1E: je 0x18003300c 180032E24: cmp rdx, 7 180032E28: jbe 0x180032e43 180032E2A: lea rax, [rdx*2 + 2] 180032E32: mov rdx, rcx 180032E35: cmp rax, 0x1000 180032E3B: jae 0x180032e62 180032E3D: call qword ptr [rip + 0x58b3ad] 180032E43: mov rcx, qword ptr [rbx + 0x10] 180032E47: cmp byte ptr [rcx + 0x19], r12b 180032E4B: jne 0x180032feb 180032E51: call struct std::_Tree_node,class std::allocator > > >,void * __ptr64> * __ptr64 __cdecl std::_Tree_val,class std::allocator > > > > >::_Min(struct std::_Tree_node,class std::allocator > > >,void * __ptr64> * __ptr64) 180032E56: mov rbx, rax 180032E59: mov rdi, qword ptr [rbp - 0x59] 180032E5D: jmp 0x180032D1C 180032E62: mov rcx, qword ptr [rcx - 8] 180032E66: sub rdx, rcx 180032E69: lea rax, [rdx - 8] 180032E6D: cmp rax, 0x1f 180032E71: jbe 0x180032e3d 180032E73: call qword ptr [rip + 0x58b397] 180032E79: int3 180032E7A: add rcx, rcx 180032E7D: je 0x180032fe3 180032E83: cmp rcx, 0x1000 180032E8A: jb 0x180032ef1 180032E8C: lea rax, [rcx + 0x27] 180032E90: cmp rax, rcx 180032E93: jbe 0x180032d96 180032E99: mov rcx, rax 180032E9C: call void __cdecl std::_Hash_vec > >,struct std::_Iterator_base0> > >::_Assign_grow(unsigned __int64,class std::_List_unchecked_const_iterator > >,struct std::_Iterator_base0>) __ptr64 180032EA1: mov rcx, rax 180032EA4: test rax, rax 180032EA7: je 0x180032e73 180032EA9: add rax, 0x27 180032EAD: and rax, 0xffffffffffffffe0 180032EB1: mov qword ptr [rax - 8], rcx 180032EB5: mov qword ptr [rbp - 0x29], rax 180032EB9: mov qword ptr [rbp - 0x19], rdi 180032EBD: mov qword ptr [rbp - 0x11], rsi 180032EC1: lea r8, [rdi*2 + 2] 180032EC9: mov rdx, r14 180032ECC: mov rcx, rax 180032ECF: call memcpy 180032ED4: lea r14, [rbp - 0x29] 180032ED8: mov rcx, qword ptr [rbp - 0x29] 180032EDC: mov rdx, qword ptr [rbp - 0x11] 180032EE0: cmp rdx, 7 180032EE4: cmova r14, rcx 180032EE8: mov rdi, qword ptr [rbp - 0x19] 180032EEC: jmp 0x180032DBA 180032EF1: call qword ptr [rip + 0x58b2f1] 180032EF7: test rax, rax 180032EFA: jne 0x180032eb5 180032EFC: call qword ptr [rip + 0x58ab2e] 180032F02: int3 180032F03: lea rcx, [rip + 0x706a2e] 180032F0A: call qword ptr [rip + 0x58ab50] 180032F10: int3 180032F11: mov rsi, rax 180032F14: jmp 0x180032D7F 180032F19: mov rcx, qword ptr [rbp + 0x17] 180032F1D: xor rcx, rsp 180032F20: call __security_check_cookie 180032F25: mov rbx, qword ptr [rsp + 0x110] 180032F2D: add rsp, 0xc0 180032F34: pop r15 180032F36: pop r14 180032F38: pop r13 180032F3A: pop r12 180032F3C: pop rdi 180032F3D: pop rsi 180032F3E: pop rbp 180032F3F: ret 180032F40: lea rcx, [rbp - 9] 180032F44: call __cdecl Mso::Collections::KeyValue,class std::allocator >,enum Mso::Authentication::FederationProvider::ConfigurationProviderCode>::~KeyValue,class std::allocator >,enum Mso::Authentication::FederationProvider::ConfigurationProviderCode>(void) __ptr64 180032F49: add r13, 0x20 180032F4D: cmp r13, qword ptr [rbp - 0x51] 180032F51: jne 0x180032cc8 180032F57: mov rsi, qword ptr [rbp - 0x49] 180032F5B: cmp qword ptr [rbp - 0x61], r12 180032F5F: jbe 0x180032f9d 180032F61: mov rdi, qword ptr [rdi] 180032F64: mov rbx, qword ptr [rdi + 8] 180032F68: cmp rbx, qword ptr [rdi + 0x10] 180032F6C: je 0x180032fd2 180032F6E: mov qword ptr [rbx], r12 180032F71: mov qword ptr [rbx + 8], r12 180032F75: call __cdecl std::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > >::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > >(class std::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > const & __ptr64) __ptr64 180032F7A: mov qword ptr [rbx], rax 180032F7D: mov rcx, qword ptr [rbp - 0x69] 180032F81: mov qword ptr [rbx], rcx 180032F84: mov qword ptr [rbp - 0x69], rax 180032F88: mov rcx, qword ptr [rbx + 8] 180032F8C: mov rax, qword ptr [rbp - 0x61] 180032F90: mov qword ptr [rbx + 8], rax 180032F94: mov qword ptr [rbp - 0x61], rcx 180032F98: add qword ptr [rdi + 8], 0x10 180032F9D: mov r8, qword ptr [rbp - 0x69] 180032FA1: mov r8, qword ptr [r8 + 8] 180032FA5: lea rdx, [rbp - 0x69] 180032FA9: lea rcx, [rbp - 0x69] 180032FAD: call void __cdecl std::_Tree_val,class std::allocator > const ,class Mso::AnyType> > >::_Erase_tree,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> > >(class std::allocator,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> > & __ptr64,struct std::_Tree_node,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> * __ptr64) __ptr64 180032FB2: mov rcx, qword ptr [rbp - 0x69] 180032FB6: call qword ptr [rip + 0x58b234] 180032FBC: add r15, 0x18 180032FC0: cmp r15, rsi 180032FC3: je 0x180032f19 180032FC9: mov rdi, qword ptr [rbp - 0x59] 180032FCD: jmp 0x180032C8D 180032FD2: lea r8, [rbp - 0x69] 180032FD6: mov rdx, rbx 180032FD9: mov rcx, rdi 180032FDC: call class std::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > * __ptr64 __cdecl std::vector,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > >,class std::allocator,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > > >::_Emplace_reallocate,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > >(class std::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > * __ptr64 const,class std::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > && __ptr64) __ptr64 180032FE1: jmp 0x180032F9D 180032FE3: mov rax, r12 180032FE6: jmp 0x180032EB5 180032FEB: mov rax, qword ptr [rbx + 8] 180032FEF: cmp byte ptr [rax + 0x19], r12b 180032FF3: jne 0x180032e56 180032FF9: cmp rbx, qword ptr [rax + 0x10] 180032FFD: jne 0x180032e56 180033003: mov rbx, rax 180033006: mov rax, qword ptr [rax + 8] 18003300A: jmp 0x180032FEF 18003300C: test rdi, rdi 18003300F: je 0x180033030 180033011: mov r8, rdi 180033014: mov rdx, rax 180033017: mov rcx, r9 18003301A: call wmemcmp 18003301F: test eax, eax 180033021: je 0x180033030 180033023: mov rdx, qword ptr [rbp - 0x11] 180033027: mov rcx, qword ptr [rbp - 0x29] 18003302B: jmp 0x180032E24 180033030: lea r9, [rbx + 0x40] 180033034: lea r8, [rbx + 0x20] 180033038: lea rdx, [rbp - 0x39] 18003303C: lea rcx, [rbp - 0x69] 180033040: call struct std::pair,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> * __ptr64,bool> __cdecl std::_Tree,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> >,0> >::_Emplace,class std::allocator > const & __ptr64,class Mso::AnyType & __ptr64>(class std::basic_string,class std::allocator > const & __ptr64,class Mso::AnyType & __ptr64) __ptr64 180033045: mov rdi, qword ptr [rbp - 0x59] 180033049: mov rcx, qword ptr [rdi] 18003304C: add rcx, 0x18 180033050: mov rdx, rbx 180033053: call int __cdecl Mso::Experiment::ABConfigsCollection::MergeGroupedFeature(class std::map,class std::allocator >,class Mso::AnyType,struct std::less,class std::allocator > >,class std::allocator,class std::allocator > const ,class Mso::AnyType> > > const & __ptr64,enum Mso::Experiment::ConfigSource const & __ptr64,bool) __ptr64 180033058: mov rdx, rax 18003305B: call void __cdecl std::_Tree_node,class std::allocator > const ,class Mso::AnyType>,void * __ptr64>::_Freenode,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> > >(class std::allocator,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> > & __ptr64,struct std::_Tree_node,class std::allocator > const ,class Mso::AnyType>,void * __ptr64> * __ptr64) 180033060: lea rcx, [rbp - 0x29] 180033064: call __cdecl Mso::Collections::KeyValue,class std::allocator >,enum Mso::Authentication::FederationProvider::ConfigurationProviderCode>::~KeyValue,class std::allocator >,enum Mso::Authentication::FederationProvider::ConfigurationProviderCode>(void) __ptr64 180033069: jmp 0x180032F40 " ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_AppvIsvSubsystems64.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1AF75","1AF75","AppvIsvSubsystems64.dll",0.0820,7.9926,0.0820,7.9926 "1AFB2","1AFB2","AppvIsvSubsystems64.dll",0.0614,5.9865,0.0614,5.9865 "F88A","F88A","AppvIsvSubsystems64.dll",0.0513,4.9944,0.1373,13.3821 "C5F80","C5F80","AppvIsvSubsystems64.dll",0.0510,4.9680,0.0510,4.9680 "1F978","1F978","AppvIsvSubsystems64.dll",0.0411,4.0019,0.0411,4.0019 "7370F","7370F","AppvIsvSubsystems64.dll",0.0411,4.0000,0.0411,4.0000 "C0CC5","C0CC5","AppvIsvSubsystems64.dll",0.0409,3.9863,0.0409,3.9863 "BEA86","BEA86","AppvIsvSubsystems64.dll",0.0406,3.9556,0.0406,3.9556 "B1E43","B1E43","AppvIsvSubsystems64.dll",0.0378,3.6810,0.0378,3.6810 "D4365","D4365","AppvIsvSubsystems64.dll",0.0374,3.6473,0.0374,3.6473 "1AF9F","1AF9F","AppvIsvSubsystems64.dll",0.0342,3.3349,0.0342,3.3349 "7B672","7B672","AppvIsvSubsystems64.dll",0.0327,3.1819,0.0327,3.1819 "B63EF","B63EF","AppvIsvSubsystems64.dll",0.0327,3.1814,1.3710,133.5787 "C00FA","C00FA","AppvIsvSubsystems64.dll",0.0310,3.0163,0.0310,3.0163 "B63F3","B63F3","AppvIsvSubsystems64.dll",0.0309,3.0123,0.0309,3.0123 "CA74E","CA74E","AppvIsvSubsystems64.dll",0.0308,3.0042,0.5853,57.0237 "B695B","B695B","AppvIsvSubsystems64.dll",0.0308,3.0010,0.0308,3.0010 "C0161","C0161","AppvIsvSubsystems64.dll",0.0308,2.9984,0.0308,2.9984 "BEAB4","BEAB4","AppvIsvSubsystems64.dll",0.0308,2.9968,0.0308,2.9968 "BEAF7","BEAF7","AppvIsvSubsystems64.dll",0.0307,2.9919,0.0307,2.9919 "C0CFD","C0CFD","AppvIsvSubsystems64.dll",0.0307,2.9872,0.0307,2.9872 "C5D7C","C5D7C","AppvIsvSubsystems64.dll",0.0281,2.7377,0.0281,2.7377 "C9363","C9363","AppvIsvSubsystems64.dll",0.0270,2.6265,5.9545,580.1548 "1F9E2","1F9E2","AppvIsvSubsystems64.dll",0.0266,2.5873,0.0266,2.5873 "D4367","D4367","AppvIsvSubsystems64.dll",0.0243,2.3683,0.0243,2.3683 "B1E40","B1E40","AppvIsvSubsystems64.dll",0.0220,2.1442,0.0220,2.1442 "C2454","C2454","AppvIsvSubsystems64.dll",0.0213,2.0711,0.0213,2.0711 "CC4A7","CC4A7","AppvIsvSubsystems64.dll",0.0208,2.0302,0.0208,2.0302 "D1A75","D1A75","AppvIsvSubsystems64.dll",0.0206,2.0090,3.9387,383.7497 "CA5FC","CA5FC","AppvIsvSubsystems64.dll",0.0206,2.0043,3.3097,322.4655 "BEF8F","BEF8F","AppvIsvSubsystems64.dll",0.0206,2.0034,0.0206,2.0034 "CD68C","CD68C","AppvIsvSubsystems64.dll",0.0205,2.0012,0.0205,2.0012 "F8A7","F8A7","AppvIsvSubsystems64.dll",0.0205,2.0004,0.2182,21.2638 "1AFA7","1AFA7","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "38EA8","38EA8","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "6695F","6695F","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "746E3","746E3","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "9E97E","9E97E","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "ADB09","ADB09","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "ADBA6","ADBA6","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "B69C2","B69C2","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "B6A9C","B6A9C","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "BEB1F","BEB1F","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "BEBF9","BEBF9","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "BF2BB","BF2BB","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "C0F0B","C0F0B","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "C5D55","C5D55","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "C5D6F","C5D6F","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "CC05C","CC05C","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "D240F","D240F","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "D242E","D242E","AppvIsvSubsystems64.dll",0.0205,2.0000,0.0205,2.0000 "9E93F","9E93F","AppvIsvSubsystems64.dll",0.0205,1.9965,0.0205,1.9965 "F884","F884","AppvIsvSubsystems64.dll",0.0205,1.9939,0.0205,1.9939 "B2F20","B2F20","AppvIsvSubsystems64.dll",0.0204,1.9912,0.0204,1.9912 "F880","F880","AppvIsvSubsystems64.dll",0.0204,1.9907,0.0204,1.9907 "C2668","C2668","AppvIsvSubsystems64.dll",0.0204,1.9876,0.2495,24.3121 "9BA88","9BA88","AppvIsvSubsystems64.dll",0.0203,1.9779,0.0203,1.9779 "B6A94","B6A94","AppvIsvSubsystems64.dll",0.0203,1.9753,0.0742,7.2246 "BDCBD","BDCBD","AppvIsvSubsystems64.dll",0.0202,1.9715,0.0202,1.9715 "B23F8","B23F8","AppvIsvSubsystems64.dll",0.0200,1.9530,0.0200,1.9530 "27D0F","27D0F","AppvIsvSubsystems64.dll",0.0192,1.8680,0.0192,1.8680 "9E8F0","9E8F0","AppvIsvSubsystems64.dll",0.0188,1.8300,0.0188,1.8300 "D4443","D4443","AppvIsvSubsystems64.dll",0.0181,1.7664,0.0181,1.7664 "D43CC","D43CC","AppvIsvSubsystems64.dll",0.0171,1.6628,0.0171,1.6628 "7B691","7B691","AppvIsvSubsystems64.dll",0.0168,1.6367,0.0168,1.6367 "D0FEA","D0FEA","AppvIsvSubsystems64.dll",0.0158,1.5416,0.0158,1.5416 "6E070","6E070","AppvIsvSubsystems64.dll",0.0148,1.4373,0.0148,1.4373 "74344","74344","AppvIsvSubsystems64.dll",0.0146,1.4243,0.0255,2.4817 "C5563","C5563","AppvIsvSubsystems64.dll",0.0144,1.3987,0.0144,1.3987 "C46F9","C46F9","AppvIsvSubsystems64.dll",0.0140,1.3603,0.0140,1.3603 "C6622","C6622","AppvIsvSubsystems64.dll",0.0139,1.3544,0.3064,29.8574 "AB77D","AB77D","AppvIsvSubsystems64.dll",0.0130,1.2649,0.0130,1.2649 "74329","74329","AppvIsvSubsystems64.dll",0.0128,1.2500,0.0128,1.2500 "BEC23","BEC23","AppvIsvSubsystems64.dll",0.0119,1.1628,0.0119,1.1628 "BF085","BF085","AppvIsvSubsystems64.dll",0.0113,1.1058,0.0113,1.1058 "C46F7","C46F7","AppvIsvSubsystems64.dll",0.0108,1.0530,0.0108,1.0530 "BE120","BE120","AppvIsvSubsystems64.dll",0.0107,1.0401,0.0107,1.0401 "D4379","D4379","AppvIsvSubsystems64.dll",0.0106,1.0356,0.0106,1.0356 "C8842","C8842","AppvIsvSubsystems64.dll",0.0105,1.0224,0.0105,1.0224 "B5F39","B5F39","AppvIsvSubsystems64.dll",0.0104,1.0156,0.0104,1.0156 "C575F","C575F","AppvIsvSubsystems64.dll",0.0104,1.0113,0.0104,1.0113 "BF0F8","BF0F8","AppvIsvSubsystems64.dll",0.0104,1.0110,0.0104,1.0110 "CD6F6","CD6F6","AppvIsvSubsystems64.dll",0.0104,1.0099,0.0104,1.0099 "C5DE4","C5DE4","AppvIsvSubsystems64.dll",0.0103,1.0079,0.0103,1.0079 "CCB21","CCB21","AppvIsvSubsystems64.dll",0.0103,1.0079,0.0103,1.0079 "229D9","229D9","AppvIsvSubsystems64.dll",0.0103,1.0074,0.0103,1.0074 "D9500","D9500","AppvIsvSubsystems64.dll",0.0103,1.0074,0.0103,1.0074 "B2020","B2020","AppvIsvSubsystems64.dll",0.0103,1.0065,0.0103,1.0065 "C5DA3","C5DA3","AppvIsvSubsystems64.dll",0.0103,1.0059,0.0103,1.0059 "73506","73506","AppvIsvSubsystems64.dll",0.0103,1.0048,0.0103,1.0048 "ADB40","ADB40","AppvIsvSubsystems64.dll",0.0103,1.0033,0.0103,1.0033 "BEAED","BEAED","AppvIsvSubsystems64.dll",0.0103,1.0022,0.0103,1.0022 "1F96F","1F96F","AppvIsvSubsystems64.dll",0.0103,1.0020,0.0103,1.0020 "C9EFB","C9EFB","AppvIsvSubsystems64.dll",0.0103,1.0019,0.3470,33.8054 "CAB4F","CAB4F","AppvIsvSubsystems64.dll",0.0103,1.0015,0.0103,1.0015 "C64E5","C64E5","AppvIsvSubsystems64.dll",0.0103,1.0005,0.0103,1.0005 "BEB74","BEB74","AppvIsvSubsystems64.dll",0.0103,0.9999,0.0103,0.9999 "B6AB5","B6AB5","AppvIsvSubsystems64.dll",0.0103,0.9995,0.0208,2.0274 "1AFA4","1AFA4","AppvIsvSubsystems64.dll",0.0103,0.9994,0.0103,0.9994 "9E956","9E956","AppvIsvSubsystems64.dll",0.0103,0.9989,0.0103,0.9989 "C850","C850","AppvIsvSubsystems64.dll",0.0103,0.9988,0.0103,0.9988 "C070E","C070E","AppvIsvSubsystems64.dll",0.0103,0.9987,0.0103,0.9987 "B6094","B6094","AppvIsvSubsystems64.dll",0.0102,0.9985,0.0102,0.9985 "BEED4","BEED4","AppvIsvSubsystems64.dll",0.0102,0.9984,0.0102,0.9984 "BF119","BF119","AppvIsvSubsystems64.dll",0.0102,0.9983,0.0102,0.9983 "C5413","C5413","AppvIsvSubsystems64.dll",0.0102,0.9982,0.0102,0.9982 "B2033","B2033","AppvIsvSubsystems64.dll",0.0102,0.9981,0.0102,0.9981 "B892D","B892D","AppvIsvSubsystems64.dll",0.0102,0.9979,0.0102,0.9979 "BDC65","BDC65","AppvIsvSubsystems64.dll",0.0102,0.9978,0.0102,0.9978 "C87D8","C87D8","AppvIsvSubsystems64.dll",0.0102,0.9976,0.0102,0.9976 "CC156","CC156","AppvIsvSubsystems64.dll",0.0102,0.9970,0.0102,0.9970 "B34C0","B34C0","AppvIsvSubsystems64.dll",0.0102,0.9968,0.0102,0.9968 "C552B","C552B","AppvIsvSubsystems64.dll",0.0102,0.9968,0.0102,0.9968 "B6962","B6962","AppvIsvSubsystems64.dll",0.0102,0.9965,0.0102,0.9965 "84A92","84A92","AppvIsvSubsystems64.dll",0.0102,0.9963,0.0102,0.9963 "C6025","C6025","AppvIsvSubsystems64.dll",0.0102,0.9961,0.0102,0.9961 "C8D88","C8D88","AppvIsvSubsystems64.dll",0.0102,0.9960,0.0102,0.9960 "B693F","B693F","AppvIsvSubsystems64.dll",0.0102,0.9956,0.0102,0.9956 "C5CFC","C5CFC","AppvIsvSubsystems64.dll",0.0102,0.9956,0.0102,0.9956 "86FC","86FC","AppvIsvSubsystems64.dll",0.0102,0.9952,0.0102,0.9952 "B605E","B605E","AppvIsvSubsystems64.dll",0.0102,0.9951,0.0102,0.9951 "B2127","B2127","AppvIsvSubsystems64.dll",0.0102,0.9949,0.0102,0.9949 "B2F80","B2F80","AppvIsvSubsystems64.dll",0.0102,0.9949,0.0102,0.9949 "C5F79","C5F79","AppvIsvSubsystems64.dll",0.0102,0.9948,0.0102,0.9948 "CD596","CD596","AppvIsvSubsystems64.dll",0.0102,0.9945,0.0102,0.9945 "B307F","B307F","AppvIsvSubsystems64.dll",0.0102,0.9943,0.0102,0.9943 "B92F2","B92F2","AppvIsvSubsystems64.dll",0.0102,0.9943,0.0102,0.9943 "C3E7E","C3E7E","AppvIsvSubsystems64.dll",0.0102,0.9943,0.0102,0.9943 "C8D3F","C8D3F","AppvIsvSubsystems64.dll",0.0102,0.9940,0.0102,0.9940 "70160","70160","AppvIsvSubsystems64.dll",0.0102,0.9939,0.0102,0.9939 "C0702","C0702","AppvIsvSubsystems64.dll",0.0102,0.9939,0.0102,0.9939 "B659B","B659B","AppvIsvSubsystems64.dll",0.0102,0.9938,9.7850,953.3591 "BF2F6","BF2F6","AppvIsvSubsystems64.dll",0.0102,0.9938,0.0102,0.9938 "CA4C5","CA4C5","AppvIsvSubsystems64.dll",0.0102,0.9936,0.0102,0.9936 "74798","74798","AppvIsvSubsystems64.dll",0.0102,0.9931,0.0102,0.9931 "74496","74496","AppvIsvSubsystems64.dll",0.0102,0.9930,0.0102,0.9930 "CA66C","CA66C","AppvIsvSubsystems64.dll",0.0102,0.9930,0.3309,32.2412 "3AAA","3AAA","AppvIsvSubsystems64.dll",0.0102,0.9928,0.0102,0.9928 "71840","71840","AppvIsvSubsystems64.dll",0.0102,0.9928,0.0102,0.9928 "C8848","C8848","AppvIsvSubsystems64.dll",0.0102,0.9927,0.3919,38.1855 "CA385","CA385","AppvIsvSubsystems64.dll",0.0102,0.9927,0.0102,0.9927 "C4961","C4961","AppvIsvSubsystems64.dll",0.0102,0.9925,0.0102,0.9925 "C9419","C9419","AppvIsvSubsystems64.dll",0.0102,0.9922,0.0102,0.9922 "C3786","C3786","AppvIsvSubsystems64.dll",0.0102,0.9920,0.0102,0.9920 "BF1B2","BF1B2","AppvIsvSubsystems64.dll",0.0102,0.9913,0.0102,0.9913 "812BC","812BC","AppvIsvSubsystems64.dll",0.0102,0.9912,0.1404,13.6816 "1B4C1","1B4C1","AppvIsvSubsystems64.dll",0.0102,0.9907,0.0102,0.9907 "B20A2","B20A2","AppvIsvSubsystems64.dll",0.0102,0.9907,0.0102,0.9907 "B3340","B3340","AppvIsvSubsystems64.dll",0.0102,0.9907,0.0102,0.9907 "CA380","CA380","AppvIsvSubsystems64.dll",0.0102,0.9904,0.0102,0.9904 "7B658","7B658","AppvIsvSubsystems64.dll",0.0102,0.9901,0.0102,0.9901 "D9509","D9509","AppvIsvSubsystems64.dll",0.0102,0.9897,0.0102,0.9897 "9E9EE","9E9EE","AppvIsvSubsystems64.dll",0.0102,0.9896,0.0102,0.9896 "CD504","CD504","AppvIsvSubsystems64.dll",0.0102,0.9895,0.0102,0.9895 "B6016","B6016","AppvIsvSubsystems64.dll",0.0101,0.9888,0.0101,0.9888 "BEA5B","BEA5B","AppvIsvSubsystems64.dll",0.0101,0.9885,0.0101,0.9885 "C0EAD","C0EAD","AppvIsvSubsystems64.dll",0.0101,0.9884,0.0101,0.9884 "5074","5074","AppvIsvSubsystems64.dll",0.0101,0.9880,0.0101,0.9880 "ADB81","ADB81","AppvIsvSubsystems64.dll",0.0101,0.9879,0.0101,0.9879 "CCC6F","CCC6F","AppvIsvSubsystems64.dll",0.0101,0.9877,0.0101,0.9877 "D1A34","D1A34","AppvIsvSubsystems64.dll",0.0101,0.9870,0.0101,0.9870 "CC6EC","CC6EC","AppvIsvSubsystems64.dll",0.0101,0.9856,0.0101,0.9856 "B6A7C","B6A7C","AppvIsvSubsystems64.dll",0.0101,0.9855,0.0101,0.9855 "B4FAF","B4FAF","AppvIsvSubsystems64.dll",0.0101,0.9853,0.0101,0.9853 "6D040","6D040","AppvIsvSubsystems64.dll",0.0101,0.9825,0.0101,0.9825 "1F964","1F964","AppvIsvSubsystems64.dll",0.0101,0.9817,0.0101,0.9817 "C0111","C0111","AppvIsvSubsystems64.dll",0.0101,0.9810,0.0101,0.9810 "B5134","B5134","AppvIsvSubsystems64.dll",0.0101,0.9804,0.0101,0.9804 "84A90","84A90","AppvIsvSubsystems64.dll",0.0101,0.9800,0.0101,0.9800 "C5F86","C5F86","AppvIsvSubsystems64.dll",0.0101,0.9800,0.0101,0.9800 "ADB4A","ADB4A","AppvIsvSubsystems64.dll",0.0100,0.9791,0.0100,0.9791 "86F9","86F9","AppvIsvSubsystems64.dll",0.0099,0.9691,0.0099,0.9691 "BF0D4","BF0D4","AppvIsvSubsystems64.dll",0.0099,0.9599,0.0099,0.9599 "BF0BE","BF0BE","AppvIsvSubsystems64.dll",0.0098,0.9508,0.0098,0.9508 "CD5C9","CD5C9","AppvIsvSubsystems64.dll",0.0095,0.9249,0.0095,0.9249 "C9052","C9052","AppvIsvSubsystems64.dll",0.0093,0.9027,0.0093,0.9027 "ADB53","ADB53","AppvIsvSubsystems64.dll",0.0092,0.8951,0.0092,0.8951 "71351","71351","AppvIsvSubsystems64.dll",0.0083,0.8070,0.0083,0.8070 "84FF8","84FF8","AppvIsvSubsystems64.dll",0.0081,0.7849,0.0081,0.7849 "74E98","74E98","AppvIsvSubsystems64.dll",0.0064,0.6257,0.0064,0.6257 "DB20","DB20","AppvIsvSubsystems64.dll",0.0063,0.6101,0.0063,0.6101 "C820","C820","AppvIsvSubsystems64.dll",0.0043,0.4178,0.0043,0.4178 "C5D15","C5D15","AppvIsvSubsystems64.dll",0.0024,0.2311,0.0024,0.2311 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_C2R64.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "45508","45508","C2R64.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_CI.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2CD14","2CD14","CI.dll",0.0311,3.0293,0.0311,3.0293 "10767","10767","CI.dll",0.0310,3.0244,0.0310,3.0244 "106C5","106C5","CI.dll",0.0309,3.0060,0.0309,3.0060 "F874","F874","CI.dll",0.0307,2.9915,0.0307,2.9915 "FFD1","FFD1","CI.dll",0.0306,2.9858,0.0306,2.9858 "104D6","104D6","CI.dll",0.0248,2.4146,0.0248,2.4146 "40B5","40B5","CI.dll",0.0208,2.0256,0.0208,2.0256 "107EB","107EB","CI.dll",0.0207,2.0207,0.0207,2.0207 "108EB","108EB","CI.dll",0.0207,2.0148,0.0207,2.0148 "108DE","108DE","CI.dll",0.0206,2.0087,0.0206,2.0087 "10850","10850","CI.dll",0.0206,2.0081,0.0206,2.0081 "106D3","106D3","CI.dll",0.0206,2.0068,0.0206,2.0068 "1011F","1011F","CI.dll",0.0206,2.0033,0.0206,2.0033 "1092D","1092D","CI.dll",0.0206,2.0030,0.0206,2.0030 "F6AF","F6AF","CI.dll",0.0205,2.0018,0.0205,2.0018 "FE3E","FE3E","CI.dll",0.0205,2.0010,0.0205,2.0010 "FEF0","FEF0","CI.dll",0.0205,2.0009,0.0205,2.0009 "10755","10755","CI.dll",0.0205,2.0006,0.0205,2.0006 "106AA","106AA","CI.dll",0.0205,2.0004,0.0205,2.0004 "12B1C","12B1C","CI.dll",0.0205,2.0000,0.0205,2.0000 "13355","13355","CI.dll",0.0205,2.0000,0.0205,2.0000 "133C2","133C2","CI.dll",0.0205,2.0000,0.0205,2.0000 "3C65","3C65","CI.dll",0.0205,2.0000,0.0205,2.0000 "40C0","40C0","CI.dll",0.0205,2.0000,0.0205,2.0000 "9164D","9164D","CI.dll",0.0205,2.0000,0.0205,2.0000 "1085B","1085B","CI.dll",0.0205,1.9996,0.0205,1.9996 "FE15","FE15","CI.dll",0.0205,1.9992,0.0205,1.9992 "106C2","106C2","CI.dll",0.0205,1.9987,0.0205,1.9987 "107A1","107A1","CI.dll",0.0205,1.9984,0.0205,1.9984 "108BC","108BC","CI.dll",0.0205,1.9980,0.0205,1.9980 "1077C","1077C","CI.dll",0.0205,1.9979,0.0205,1.9979 "10919","10919","CI.dll",0.0205,1.9973,0.0205,1.9973 "FE59","FE59","CI.dll",0.0205,1.9963,0.0205,1.9963 "FA47","FA47","CI.dll",0.0205,1.9955,0.0205,1.9955 "1044B","1044B","CI.dll",0.0205,1.9949,0.0205,1.9949 "107FC","107FC","CI.dll",0.0205,1.9935,0.0205,1.9935 "10916","10916","CI.dll",0.0204,1.9905,0.0204,1.9905 "10932","10932","CI.dll",0.0204,1.9894,0.0204,1.9894 "10924","10924","CI.dll",0.0204,1.9841,0.0204,1.9841 "FA01","FA01","CI.dll",0.0202,1.9685,0.0202,1.9685 "FBD6","FBD6","CI.dll",0.0172,1.6721,0.0172,1.6721 "10855","10855","CI.dll",0.0167,1.6286,0.0167,1.6286 "6EA7F","6EA7F","CI.dll",0.0159,1.5519,0.0159,1.5519 "584A4","584A4","CI.dll",0.0147,1.4296,0.0147,1.4296 "10861","10861","CI.dll",0.0139,1.3577,0.0139,1.3577 "6FDC6","6FDC6","CI.dll",0.0135,1.3130,0.0135,1.3130 "13549","13549","CI.dll",0.0112,1.0960,0.0112,1.0960 "8F370","8F370","CI.dll",0.0106,1.0365,0.0106,1.0365 "10461","10461","CI.dll",0.0106,1.0298,0.0106,1.0298 "10758","10758","CI.dll",0.0105,1.0231,0.0105,1.0231 "40BC","40BC","CI.dll",0.0105,1.0224,0.0105,1.0224 "107E3","107E3","CI.dll",0.0105,1.0203,0.0105,1.0203 "10908","10908","CI.dll",0.0105,1.0192,0.0105,1.0192 "12542","12542","CI.dll",0.0105,1.0186,0.0105,1.0186 "12508","12508","CI.dll",0.0104,1.0144,0.0104,1.0144 "FD5B","FD5B","CI.dll",0.0104,1.0137,0.0104,1.0137 "108C7","108C7","CI.dll",0.0104,1.0127,0.0104,1.0127 "FEB5","FEB5","CI.dll",0.0104,1.0111,0.0104,1.0111 "1371B","1371B","CI.dll",0.0104,1.0106,0.0104,1.0106 "FB01","FB01","CI.dll",0.0103,1.0082,0.0103,1.0082 "12632","12632","CI.dll",0.0103,1.0080,0.0103,1.0080 "131D3","131D3","CI.dll",0.0103,1.0074,0.0103,1.0074 "10271","10271","CI.dll",0.0103,1.0073,0.0103,1.0073 "12340","12340","CI.dll",0.0103,1.0059,0.0103,1.0059 "FFB7","FFB7","CI.dll",0.0103,1.0059,0.0103,1.0059 "10841","10841","CI.dll",0.0103,1.0057,0.0103,1.0057 "13403","13403","CI.dll",0.0103,1.0057,0.0103,1.0057 "FCE8","FCE8","CI.dll",0.0103,1.0052,0.0103,1.0052 "1003A","1003A","CI.dll",0.0103,1.0051,0.0103,1.0051 "107CE","107CE","CI.dll",0.0103,1.0051,0.0103,1.0051 "1370F","1370F","CI.dll",0.0103,1.0048,0.0103,1.0048 "1326C","1326C","CI.dll",0.0103,1.0046,0.0103,1.0046 "12061","12061","CI.dll",0.0103,1.0041,0.0103,1.0041 "40B0","40B0","CI.dll",0.0103,1.0041,0.0103,1.0041 "40D9","40D9","CI.dll",0.0103,1.0030,0.0103,1.0030 "11F65","11F65","CI.dll",0.0103,1.0028,0.0103,1.0028 "40D5","40D5","CI.dll",0.0103,1.0028,0.0103,1.0028 "1002F","1002F","CI.dll",0.0103,1.0027,0.0103,1.0027 "13601","13601","CI.dll",0.0103,1.0026,0.0103,1.0026 "138D6","138D6","CI.dll",0.0103,1.0026,0.0103,1.0026 "109C3","109C3","CI.dll",0.0103,1.0025,0.0103,1.0025 "F6A1","F6A1","CI.dll",0.0103,1.0024,0.0103,1.0024 "FF4A","FF4A","CI.dll",0.0103,1.0024,0.0103,1.0024 "10675","10675","CI.dll",0.0103,1.0023,0.0103,1.0023 "FC1A","FC1A","CI.dll",0.0103,1.0022,0.0103,1.0022 "FF79","FF79","CI.dll",0.0103,1.0022,0.0103,1.0022 "107D7","107D7","CI.dll",0.0103,1.0020,0.0103,1.0020 "91954","91954","CI.dll",0.0103,1.0020,0.0103,1.0020 "107A7","107A7","CI.dll",0.0103,1.0018,0.0103,1.0018 "1084A","1084A","CI.dll",0.0103,1.0018,0.0103,1.0018 "FBB0","FBB0","CI.dll",0.0103,1.0018,0.0103,1.0018 "106C0","106C0","CI.dll",0.0103,1.0015,0.0103,1.0015 "107E8","107E8","CI.dll",0.0103,1.0015,0.0103,1.0015 "108BF","108BF","CI.dll",0.0103,1.0015,0.0103,1.0015 "107AD","107AD","CI.dll",0.0103,1.0014,0.0103,1.0014 "107C4","107C4","CI.dll",0.0103,1.0014,0.0103,1.0014 "F882","F882","CI.dll",0.0103,1.0013,0.0103,1.0013 "1005F","1005F","CI.dll",0.0103,1.0012,0.0103,1.0012 "10113","10113","CI.dll",0.0103,1.0012,0.0103,1.0012 "1016E","1016E","CI.dll",0.0103,1.0007,0.0103,1.0007 "10771","10771","CI.dll",0.0103,1.0007,0.0103,1.0007 "10798","10798","CI.dll",0.0103,1.0007,0.0103,1.0007 "2C544","2C544","CI.dll",0.0103,1.0007,0.0103,1.0007 "106A4","106A4","CI.dll",0.0103,1.0005,0.0103,1.0005 "106FF","106FF","CI.dll",0.0103,1.0005,0.0103,1.0005 "1093C","1093C","CI.dll",0.0103,1.0005,0.0103,1.0005 "10954","10954","CI.dll",0.0103,1.0005,0.0103,1.0005 "FC4A","FC4A","CI.dll",0.0103,1.0004,0.0103,1.0004 "131ED","131ED","CI.dll",0.0103,1.0003,0.0103,1.0003 "FAC0","FAC0","CI.dll",0.0103,1.0003,0.0103,1.0003 "1070F","1070F","CI.dll",0.0103,1.0002,0.0103,1.0002 "100A9","100A9","CI.dll",0.0103,1.0001,0.0103,1.0001 "109B3","109B3","CI.dll",0.0103,1.0000,0.0103,1.0000 "FFE9","FFE9","CI.dll",0.0103,1.0000,0.0103,1.0000 "FF86","FF86","CI.dll",0.0103,0.9999,0.0103,0.9999 "103F0","103F0","CI.dll",0.0103,0.9997,0.0103,0.9997 "106B8","106B8","CI.dll",0.0103,0.9995,0.0103,0.9995 "106E6","106E6","CI.dll",0.0103,0.9994,0.0103,0.9994 "FA55","FA55","CI.dll",0.0103,0.9992,0.0103,0.9992 "FE8E","FE8E","CI.dll",0.0103,0.9992,0.0103,0.9992 "FFA1","FFA1","CI.dll",0.0103,0.9992,0.0103,0.9992 "106F7","106F7","CI.dll",0.0103,0.9990,0.0103,0.9990 "FB85","FB85","CI.dll",0.0103,0.9989,0.0103,0.9989 "FD9F","FD9F","CI.dll",0.0103,0.9989,0.0103,0.9989 "10705","10705","CI.dll",0.0103,0.9988,0.0103,0.9988 "105E9","105E9","CI.dll",0.0103,0.9987,0.0103,0.9987 "107E6","107E6","CI.dll",0.0103,0.9987,0.0103,0.9987 "108B1","108B1","CI.dll",0.0103,0.9987,0.0103,0.9987 "109D1","109D1","CI.dll",0.0103,0.9987,0.0103,0.9987 "1087D","1087D","CI.dll",0.0102,0.9985,0.0102,0.9985 "1071F","1071F","CI.dll",0.0102,0.9984,0.0102,0.9984 "1088B","1088B","CI.dll",0.0102,0.9984,0.0102,0.9984 "10910","10910","CI.dll",0.0102,0.9984,0.0102,0.9984 "1012D","1012D","CI.dll",0.0102,0.9983,0.0102,0.9983 "1014D","1014D","CI.dll",0.0102,0.9983,0.0102,0.9983 "107DD","107DD","CI.dll",0.0102,0.9983,0.0102,0.9983 "1088D","1088D","CI.dll",0.0102,0.9981,0.0102,0.9981 "FD2B","FD2B","CI.dll",0.0102,0.9981,0.0102,0.9981 "FE7C","FE7C","CI.dll",0.0102,0.9977,0.0102,0.9977 "4139","4139","CI.dll",0.0102,0.9976,0.0102,0.9976 "FFBD","FFBD","CI.dll",0.0102,0.9976,0.0102,0.9976 "F9BF","F9BF","CI.dll",0.0102,0.9974,0.0102,0.9974 "FF1B","FF1B","CI.dll",0.0102,0.9974,0.0102,0.9974 "10960","10960","CI.dll",0.0102,0.9973,0.0102,0.9973 "1092A","1092A","CI.dll",0.0102,0.9972,0.0102,0.9972 "1023F","1023F","CI.dll",0.0102,0.9969,0.0102,0.9969 "F758","F758","CI.dll",0.0102,0.9968,0.0102,0.9968 "13343","13343","CI.dll",0.0102,0.9966,0.0102,0.9966 "FDAD","FDAD","CI.dll",0.0102,0.9965,0.0102,0.9965 "10101","10101","CI.dll",0.0102,0.9964,0.0102,0.9964 "10730","10730","CI.dll",0.0102,0.9964,0.0102,0.9964 "10690","10690","CI.dll",0.0102,0.9961,0.0102,0.9961 "10793","10793","CI.dll",0.0102,0.9961,0.0102,0.9961 "10714","10714","CI.dll",0.0102,0.9958,0.0102,0.9958 "FB34","FB34","CI.dll",0.0102,0.9958,0.0102,0.9958 "FEEB","FEEB","CI.dll",0.0102,0.9956,0.0102,0.9956 "1046D","1046D","CI.dll",0.0102,0.9951,0.0102,0.9951 "106FA","106FA","CI.dll",0.0102,0.9951,0.0102,0.9951 "FBCC","FBCC","CI.dll",0.0102,0.9951,0.0102,0.9951 "10947","10947","CI.dll",0.0102,0.9950,0.0102,0.9950 "106D0","106D0","CI.dll",0.0102,0.9949,0.0102,0.9949 "106E9","106E9","CI.dll",0.0102,0.9945,0.0102,0.9945 "FD7E","FD7E","CI.dll",0.0102,0.9945,0.0102,0.9945 "F959","F959","CI.dll",0.0102,0.9943,0.0102,0.9943 "10805","10805","CI.dll",0.0102,0.9939,0.0102,0.9939 "F96A","F96A","CI.dll",0.0102,0.9936,0.0102,0.9936 "FE69","FE69","CI.dll",0.0102,0.9936,0.0102,0.9936 "FA9D","FA9D","CI.dll",0.0102,0.9934,0.0102,0.9934 "108AE","108AE","CI.dll",0.0102,0.9930,0.0102,0.9930 "10746","10746","CI.dll",0.0102,0.9928,0.0102,0.9928 "10484","10484","CI.dll",0.0102,0.9926,0.0102,0.9926 "102D1","102D1","CI.dll",0.0102,0.9921,0.0102,0.9921 "10763","10763","CI.dll",0.0102,0.9920,0.0102,0.9920 "172B","172B","CI.dll",0.0102,0.9912,0.0102,0.9912 "FF21","FF21","CI.dll",0.0102,0.9910,0.0102,0.9910 "1086A","1086A","CI.dll",0.0102,0.9901,0.0102,0.9901 "108CD","108CD","CI.dll",0.0102,0.9898,0.0102,0.9898 "10255","10255","CI.dll",0.0101,0.9879,0.0101,0.9879 "10711","10711","CI.dll",0.0101,0.9871,0.0101,0.9871 "12518","12518","CI.dll",0.0101,0.9868,0.0101,0.9868 "106D8","106D8","CI.dll",0.0101,0.9866,0.0101,0.9866 "FD1F","FD1F","CI.dll",0.0101,0.9863,0.0101,0.9863 "106D5","106D5","CI.dll",0.0101,0.9830,0.0101,0.9830 "F974","F974","CI.dll",0.0101,0.9825,0.0101,0.9825 "10327","10327","CI.dll",0.0101,0.9822,0.0101,0.9822 "1003D","1003D","CI.dll",0.0100,0.9754,0.0100,0.9754 "10568","10568","CI.dll",0.0075,0.7309,0.0075,0.7309 "10881","10881","CI.dll",0.0066,0.6421,0.0066,0.6421 "FFDB","FFDB","CI.dll",0.0062,0.6081,0.0062,0.6081 "133F1","133F1","CI.dll",0.0061,0.5974,0.0061,0.5974 "40E0","40E0","CI.dll",0.0054,0.5225,0.0054,0.5225 "106EB","106EB","CI.dll",0.0046,0.4480,0.0046,0.4480 "131F9","131F9","CI.dll",0.0040,0.3919,0.0040,0.3919 "F743","F743","CI.dll",0.0040,0.3887,0.0040,0.3887 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_CoreMessaging.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "62608","62608","CoreMessaging.dll",0.0205,2.0000,0.0205,2.0000 "6E100","6E100","CoreMessaging.dll",0.0205,2.0000,0.0205,2.0000 "9F7D","9F7D","CoreMessaging.dll",0.0205,2.0000,0.0205,2.0000 "1E340","1E340","CoreMessaging.dll",0.0104,1.0134,0.0104,1.0134 "1E3FB","1E3FB","CoreMessaging.dll",0.0101,0.9845,0.0101,0.9845 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_DWrite.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "74EA3","74EA3","DWrite.dll",0.0215,2.0907,0.0215,2.0907 "C3F95","C3F95","DWrite.dll",0.0213,2.0791,0.0213,2.0791 "8241","8241","DWrite.dll",0.0205,2.0022,0.0205,2.0022 "5AB3E","5AB3E","DWrite.dll",0.0205,2.0000,0.0205,2.0000 "45C1E","45C1E","DWrite.dll",0.0169,1.6458,0.0169,1.6458 "A5BC9","A5BC9","DWrite.dll",0.0156,1.5226,0.0156,1.5226 "5FD69","5FD69","DWrite.dll",0.0154,1.5040,0.0154,1.5040 "22F33","22F33","DWrite.dll",0.0148,1.4406,0.0148,1.4406 "60CB9","60CB9","DWrite.dll",0.0145,1.4110,0.0145,1.4110 "3D8E8","3D8E8","DWrite.dll",0.0137,1.3344,0.0137,1.3344 "517F8","517F8","DWrite.dll",0.0115,1.1234,0.0115,1.1234 "97C90","97C90","DWrite.dll",0.0114,1.1074,0.0114,1.1074 "5A895","5A895","DWrite.dll",0.0110,1.0755,0.0110,1.0755 "CD776","CD776","DWrite.dll",0.0108,1.0514,0.0108,1.0514 "97DEE","97DEE","DWrite.dll",0.0106,1.0356,0.0106,1.0356 "59BFF","59BFF","DWrite.dll",0.0105,1.0231,0.0105,1.0231 "3CF88","3CF88","DWrite.dll",0.0104,1.0125,0.0104,1.0125 "84A9C","84A9C","DWrite.dll",0.0104,1.0100,0.0104,1.0100 "22EFC","22EFC","DWrite.dll",0.0103,1.0072,0.0103,1.0072 "F3E64","F3E64","DWrite.dll",0.0103,1.0066,0.0103,1.0066 "4487B","4487B","DWrite.dll",0.0103,1.0037,0.0103,1.0037 "4B236","4B236","DWrite.dll",0.0103,1.0034,0.0103,1.0034 "D7C06","D7C06","DWrite.dll",0.0103,1.0029,0.0103,1.0029 "10C22C","10C22C","DWrite.dll",0.0103,1.0015,0.0103,1.0015 "4A97A","4A97A","DWrite.dll",0.0103,1.0015,0.0103,1.0015 "D4440","D4440","DWrite.dll",0.0103,1.0015,0.0103,1.0015 "17573","17573","DWrite.dll",0.0103,1.0013,0.0103,1.0013 "84A7E","84A7E","DWrite.dll",0.0103,1.0013,0.0103,1.0013 "214A1","214A1","DWrite.dll",0.0103,1.0000,0.0103,1.0000 "1F573","1F573","DWrite.dll",0.0102,0.9979,0.0102,0.9979 "2089C","2089C","DWrite.dll",0.0102,0.9971,0.0102,0.9971 "D499D","D499D","DWrite.dll",0.0102,0.9971,0.0102,0.9971 "FCD8C","FCD8C","DWrite.dll",0.0102,0.9959,0.0102,0.9959 "60CBF","60CBF","DWrite.dll",0.0102,0.9956,0.0102,0.9956 "84BE2","84BE2","DWrite.dll",0.0102,0.9930,0.0102,0.9930 "B6C2F","B6C2F","DWrite.dll",0.0102,0.9920,0.0102,0.9920 "2002F","2002F","DWrite.dll",0.0101,0.9863,0.0101,0.9863 "22A1E","22A1E","DWrite.dll",0.0100,0.9771,0.0100,0.9771 "8476D","8476D","DWrite.dll",0.0096,0.9387,0.0096,0.9387 "44F6E","44F6E","DWrite.dll",0.0089,0.8629,0.0089,0.8629 "5439D","5439D","DWrite.dll",0.0085,0.8248,0.0085,0.8248 "66247","66247","DWrite.dll",0.0072,0.7016,0.0072,0.7016 "977CB","977CB","DWrite.dll",0.0056,0.5458,0.0056,0.5458 "99A60","99A60","DWrite.dll",0.0039,0.3757,0.0039,0.3757 "960C0","960C0","DWrite.dll",0.0031,0.3058,0.0031,0.3058 "6B022","6B022","DWrite.dll",0.0031,0.3029,0.0031,0.3029 "A5BC3","A5BC3","DWrite.dll",0.0027,0.2625,0.0027,0.2625 "9CF44","9CF44","DWrite.dll",0.0014,0.1398,0.0014,0.1398 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_EMSMDB32.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "4FF91","4FF91","EMSMDB32.DLL",0.0206,2.0028,0.0206,2.0028 "169330","169330","EMSMDB32.DLL",0.0205,2.0000,0.0205,2.0000 "8BDCD","8BDCD","EMSMDB32.DLL",0.0203,1.9783,0.0203,1.9783 "28F1C0","28F1C0","EMSMDB32.DLL",0.0107,1.0383,0.0107,1.0383 "2CC1A0","2CC1A0","EMSMDB32.DLL",0.0101,0.9848,0.0101,0.9848 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_FLTMGR.SYS_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "B718","B718","FLTMGR.SYS",0.0292,2.8449,0.0292,2.8449 "1DD39","1DD39","FLTMGR.SYS",0.0221,2.1558,0.0221,2.1558 "1D4D9","1D4D9","FLTMGR.SYS",0.0205,2.0000,0.0205,2.0000 "4987","4987","FLTMGR.SYS",0.0205,2.0000,0.0205,2.0000 "538F9","538F9","FLTMGR.SYS",0.0205,2.0000,0.0205,2.0000 "B700","B700","FLTMGR.SYS",0.0205,2.0000,0.0205,2.0000 "84E5","84E5","FLTMGR.SYS",0.0178,1.7331,0.0178,1.7331 "4860","4860","FLTMGR.SYS",0.0171,1.6670,0.0171,1.6670 "46CA","46CA","FLTMGR.SYS",0.0147,1.4279,0.0147,1.4279 "55B96","55B96","FLTMGR.SYS",0.0144,1.4053,0.0144,1.4053 "5CD7","5CD7","FLTMGR.SYS",0.0110,1.0707,0.0110,1.0707 "1541C","1541C","FLTMGR.SYS",0.0107,1.0385,0.0107,1.0385 "55626","55626","FLTMGR.SYS",0.0106,1.0339,0.0106,1.0339 "15419","15419","FLTMGR.SYS",0.0104,1.0155,0.0104,1.0155 "7D85","7D85","FLTMGR.SYS",0.0104,1.0128,0.0104,1.0128 "1E238","1E238","FLTMGR.SYS",0.0102,0.9971,0.0102,0.9971 "1D8D5","1D8D5","FLTMGR.SYS",0.0101,0.9804,0.0101,0.9804 "18439","18439","FLTMGR.SYS",0.0086,0.8345,0.0086,0.8345 "85E1","85E1","FLTMGR.SYS",0.0074,0.7196,0.0074,0.7196 "84F0","84F0","FLTMGR.SYS",0.0066,0.6399,0.0066,0.6399 "85B0","85B0","FLTMGR.SYS",0.0063,0.6154,0.0063,0.6154 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_FlightSettings.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "3D048","3D048","FlightSettings.dll",0.0219,2.1378,0.0219,2.1378 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_IPHLPAPI.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "7C2A","7C2A","IPHLPAPI.DLL",0.0102,0.9897,0.0102,0.9897 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_KernelBase.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "B8F70","B8F70","KernelBase.dll",0.0576,5.6111,0.0576,5.6111 "3CEB0","3CEB0","KernelBase.dll",0.0561,5.4674,0.0561,5.4674 "4D2B0","4D2B0","KernelBase.dll",0.0456,4.4431,0.0456,4.4431 "63B9B","63B9B","KernelBase.dll",0.0411,4.0000,0.0411,4.0000 "69A8","69A8","KernelBase.dll",0.0356,3.4651,0.0356,3.4651 "5F6D0","5F6D0","KernelBase.dll",0.0310,3.0215,0.0310,3.0215 "73C1","73C1","KernelBase.dll",0.0308,3.0008,0.0308,3.0008 "3CB13","3CB13","KernelBase.dll",0.0308,2.9967,0.0308,2.9967 "9A7B0","9A7B0","KernelBase.dll",0.0308,2.9967,0.0308,2.9967 "73FB","73FB","KernelBase.dll",0.0307,2.9886,0.0307,2.9886 "3E008","3E008","KernelBase.dll",0.0307,2.9871,0.0307,2.9871 "7409","7409","KernelBase.dll",0.0306,2.9804,0.0306,2.9804 "C5C90","C5C90","KernelBase.dll",0.0295,2.8767,0.0295,2.8767 "6BF5","6BF5","KernelBase.dll",0.0283,2.7578,0.0283,2.7578 "FA110","FA110","KernelBase.dll",0.0271,2.6384,0.0271,2.6384 "3DFD1","3DFD1","KernelBase.dll",0.0220,2.1393,0.0220,2.1393 "3CEBC","3CEBC","KernelBase.dll",0.0206,2.0093,0.0206,2.0093 "11529","11529","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "37180","37180","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "3BA5E","3BA5E","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "3CB7E","3CB7E","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "3CE99","3CE99","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "3CF6E","3CF6E","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "3DF33","3DF33","KernelBase.dll",0.0205,2.0000,0.1334,12.9928 "3E02C","3E02C","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "63589","63589","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "6983","6983","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "746C","746C","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "8A35","8A35","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "C363","C363","KernelBase.dll",0.0205,2.0000,0.0205,2.0000 "3E052","3E052","KernelBase.dll",0.0205,1.9986,0.0205,1.9986 "B8650","B8650","KernelBase.dll",0.0205,1.9976,0.0205,1.9976 "3E038","3E038","KernelBase.dll",0.0205,1.9956,0.0205,1.9956 "5FC07","5FC07","KernelBase.dll",0.0204,1.9884,0.0204,1.9884 "3E099","3E099","KernelBase.dll",0.0203,1.9752,0.0203,1.9752 "61856","61856","KernelBase.dll",0.0203,1.9749,0.0203,1.9749 "8A55","8A55","KernelBase.dll",0.0201,1.9621,0.0201,1.9621 "C30B0","C30B0","KernelBase.dll",0.0189,1.8421,0.0189,1.8421 "3CB48","3CB48","KernelBase.dll",0.0163,1.5835,0.0163,1.5835 "3CE52","3CE52","KernelBase.dll",0.0156,1.5238,0.0156,1.5238 "37B10","37B10","KernelBase.dll",0.0155,1.5097,0.0155,1.5097 "60F95","60F95","KernelBase.dll",0.0146,1.4230,0.0146,1.4230 "3E0A3","3E0A3","KernelBase.dll",0.0142,1.3851,0.0142,1.3851 "57EA3","57EA3","KernelBase.dll",0.0136,1.3220,0.0136,1.3220 "ABB80","ABB80","KernelBase.dll",0.0127,1.2395,0.0127,1.2395 "73F7","73F7","KernelBase.dll",0.0121,1.1787,0.0121,1.1787 "1336AA","1336AA","KernelBase.dll",0.0115,1.1212,0.0115,1.1212 "3E16D","3E16D","KernelBase.dll",0.0108,1.0480,0.0108,1.0480 "1FFE0","1FFE0","KernelBase.dll",0.0107,1.0396,0.0107,1.0396 "5AF40","5AF40","KernelBase.dll",0.0105,1.0185,0.0105,1.0185 "A1A0","A1A0","KernelBase.dll",0.0104,1.0092,0.0104,1.0092 "2EC90","2EC90","KernelBase.dll",0.0103,1.0056,0.0103,1.0056 "7439","7439","KernelBase.dll",0.0103,1.0041,0.0103,1.0041 "73CB","73CB","KernelBase.dll",0.0103,1.0028,0.0103,1.0028 "3DFAE","3DFAE","KernelBase.dll",0.0103,1.0024,0.0103,1.0024 "3CE93","3CE93","KernelBase.dll",0.0103,1.0022,0.0103,1.0022 "371D7","371D7","KernelBase.dll",0.0103,1.0021,0.0103,1.0021 "19C4B8","19C4B8","KernelBase.dll",0.0103,1.0010,0.0103,1.0010 "84E02","84E02","KernelBase.dll",0.0103,1.0004,0.0103,1.0004 "57EB8","57EB8","KernelBase.dll",0.0103,1.0000,0.0103,1.0000 "738B","738B","KernelBase.dll",0.0103,0.9994,0.0103,0.9994 "3F978","3F978","KernelBase.dll",0.0103,0.9989,0.0103,0.9989 "3DF46","3DF46","KernelBase.dll",0.0102,0.9985,0.0102,0.9985 "3CA8F","3CA8F","KernelBase.dll",0.0102,0.9980,0.0102,0.9980 "5D306","5D306","KernelBase.dll",0.0102,0.9977,0.0102,0.9977 "3B870","3B870","KernelBase.dll",0.0102,0.9976,0.0102,0.9976 "D6200","D6200","KernelBase.dll",0.0102,0.9976,0.0102,0.9976 "3E0AE","3E0AE","KernelBase.dll",0.0102,0.9971,0.0102,0.9971 "1AA8C","1AA8C","KernelBase.dll",0.0102,0.9970,0.0102,0.9970 "8A61","8A61","KernelBase.dll",0.0102,0.9966,0.0102,0.9966 "3DE2D","3DE2D","KernelBase.dll",0.0102,0.9960,0.0102,0.9960 "60EB8","60EB8","KernelBase.dll",0.0102,0.9958,0.0102,0.9958 "3EC93","3EC93","KernelBase.dll",0.0102,0.9956,0.0102,0.9956 "4D33C","4D33C","KernelBase.dll",0.0102,0.9953,0.0102,0.9953 "631B7","631B7","KernelBase.dll",0.0102,0.9953,0.0102,0.9953 "C2A0","C2A0","KernelBase.dll",0.0102,0.9951,0.0102,0.9951 "194DD7","194DD7","KernelBase.dll",0.0102,0.9942,0.0102,0.9942 "4DFCC","4DFCC","KernelBase.dll",0.0102,0.9939,0.0102,0.9939 "3CEC5","3CEC5","KernelBase.dll",0.0102,0.9938,0.0102,0.9938 "C1B70","C1B70","KernelBase.dll",0.0102,0.9933,0.0102,0.9933 "3E065","3E065","KernelBase.dll",0.0102,0.9930,0.0102,0.9930 "5EB6F","5EB6F","KernelBase.dll",0.0102,0.9930,0.0102,0.9930 "134C3","134C3","KernelBase.dll",0.0102,0.9926,0.0102,0.9926 "CC4F0","CC4F0","KernelBase.dll",0.0102,0.9925,0.0102,0.9925 "4EC59","4EC59","KernelBase.dll",0.0102,0.9924,0.0102,0.9924 "3E09C","3E09C","KernelBase.dll",0.0102,0.9915,0.0102,0.9915 "60FFA","60FFA","KernelBase.dll",0.0102,0.9914,0.0102,0.9914 "3CB17","3CB17","KernelBase.dll",0.0102,0.9912,0.0102,0.9912 "84E31","84E31","KernelBase.dll",0.0102,0.9912,0.0102,0.9912 "7449","7449","KernelBase.dll",0.0102,0.9906,0.0102,0.9906 "103430","103430","KernelBase.dll",0.0102,0.9896,0.0102,0.9896 "1345CE","1345CE","KernelBase.dll",0.0102,0.9891,0.0102,0.9891 "AD170","AD170","KernelBase.dll",0.0101,0.9870,0.0101,0.9870 "631B0","631B0","KernelBase.dll",0.0101,0.9856,0.0101,0.9856 "A521F","A521F","KernelBase.dll",0.0101,0.9840,0.0101,0.9840 "3CA0B","3CA0B","KernelBase.dll",0.0101,0.9837,0.0101,0.9837 "C78C0","C78C0","KernelBase.dll",0.0101,0.9830,0.0101,0.9830 "3E0A5","3E0A5","KernelBase.dll",0.0100,0.9759,0.0100,0.9759 "43470","43470","KernelBase.dll",0.0100,0.9709,0.0100,0.9709 "3CF72","3CF72","KernelBase.dll",0.0100,0.9705,0.0100,0.9705 "87FFF","87FFF","KernelBase.dll",0.0096,0.9400,0.0096,0.9400 "1AA32","1AA32","KernelBase.dll",0.0073,0.7088,0.0073,0.7088 "84DF0","84DF0","KernelBase.dll",0.0056,0.5440,0.0056,0.5440 "56970","56970","KernelBase.dll",0.0050,0.4909,0.0050,0.4909 "3CDBB","3CDBB","KernelBase.dll",0.0042,0.4136,0.0042,0.4136 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_MSO.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "3F723","3F723","MSO.DLL",0.0270,2.6319,0.0270,2.6319 "191DE","191DE","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "197A80","197A80","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "1F9F0","1F9F0","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "3F1F0","3F1F0","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "443FC","443FC","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "6A172","6A172","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "87F00C","87F00C","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "C41F1","C41F1","MSO.DLL",0.0205,2.0000,0.0205,2.0000 "15701","15701","MSO.DLL",0.0205,1.9981,0.0205,1.9981 "3F6D9","3F6D9","MSO.DLL",0.0198,1.9300,0.0198,1.9300 "80E83","80E83","MSO.DLL",0.0120,1.1687,0.0120,1.1687 "81751","81751","MSO.DLL",0.0117,1.1381,0.0117,1.1381 "3F6B8","3F6B8","MSO.DLL",0.0108,1.0561,0.0108,1.0561 "12D543D","12D543D","MSO.DLL",0.0105,1.0228,0.0105,1.0228 "1840E0","1840E0","MSO.DLL",0.0103,0.9994,0.0103,0.9994 "EC7E0","EC7E0","MSO.DLL",0.0102,0.9976,0.0102,0.9976 "89460","89460","MSO.DLL",0.0102,0.9904,0.0102,0.9904 "933C0","933C0","MSO.DLL",0.0101,0.9827,0.0101,0.9827 "693376","693376","MSO.DLL",0.0100,0.9758,0.0100,0.9758 "114A10","114A10","MSO.DLL",0.0091,0.8875,0.0091,0.8875 "44ADE2","44ADE2","MSO.DLL",0.0091,0.8850,0.0091,0.8850 "D1A50","D1A50","MSO.DLL",0.0080,0.7772,0.0080,0.7772 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_MSOARIA.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "8F5D","8F5D","MSOARIA.DLL",0.0514,5.0066,0.0514,5.0066 "120CAE","120CAE","MSOARIA.DLL",0.0416,4.0559,0.0416,4.0559 "8947D","8947D","MSOARIA.DLL",0.0308,3.0036,0.0308,3.0036 "120C8B","120C8B","MSOARIA.DLL",0.0305,2.9706,0.0305,2.9706 "EF441","EF441","MSOARIA.DLL",0.0278,2.7062,0.0278,2.7062 "6951","6951","MSOARIA.DLL",0.0205,2.0004,0.0205,2.0004 "11C8E","11C8E","MSOARIA.DLL",0.0205,2.0000,0.0205,2.0000 "1217B6","1217B6","MSOARIA.DLL",0.0205,2.0000,0.0205,2.0000 "1218B9","1218B9","MSOARIA.DLL",0.0205,2.0000,0.0205,2.0000 "85EA3","85EA3","MSOARIA.DLL",0.0205,2.0000,0.0205,2.0000 "89AEE","89AEE","MSOARIA.DLL",0.0205,2.0000,0.0205,2.0000 "12196C","12196C","MSOARIA.DLL",0.0204,1.9919,0.0204,1.9919 "121956","121956","MSOARIA.DLL",0.0204,1.9887,0.0204,1.9887 "12191E","12191E","MSOARIA.DLL",0.0204,1.9883,0.0204,1.9883 "121982","121982","MSOARIA.DLL",0.0204,1.9879,0.0204,1.9879 "88436","88436","MSOARIA.DLL",0.0203,1.9827,0.0203,1.9827 "9D2FB","9D2FB","MSOARIA.DLL",0.0179,1.7402,0.0179,1.7402 "3BAA3","3BAA3","MSOARIA.DLL",0.0125,1.2211,0.0125,1.2211 "1234CD","1234CD","MSOARIA.DLL",0.0112,1.0930,0.0112,1.0930 "768E","768E","MSOARIA.DLL",0.0103,1.0056,0.0103,1.0056 "E7A6","E7A6","MSOARIA.DLL",0.0103,1.0044,0.0103,1.0044 "395A1","395A1","MSOARIA.DLL",0.0103,1.0043,0.0103,1.0043 "7C1C3","7C1C3","MSOARIA.DLL",0.0103,1.0038,0.0103,1.0038 "120C37","120C37","MSOARIA.DLL",0.0103,1.0033,0.0103,1.0033 "9BC63","9BC63","MSOARIA.DLL",0.0103,1.0033,0.0103,1.0033 "8A94","8A94","MSOARIA.DLL",0.0103,1.0030,0.0103,1.0030 "1235E6","1235E6","MSOARIA.DLL",0.0103,1.0028,0.0103,1.0028 "E26B","E26B","MSOARIA.DLL",0.0103,1.0021,0.0103,1.0021 "120B0A","120B0A","MSOARIA.DLL",0.0103,1.0014,0.0103,1.0014 "123578","123578","MSOARIA.DLL",0.0103,1.0014,0.0103,1.0014 "8A6BC","8A6BC","MSOARIA.DLL",0.0103,1.0012,0.0103,1.0012 "6260E","6260E","MSOARIA.DLL",0.0103,1.0011,0.0103,1.0011 "6C650","6C650","MSOARIA.DLL",0.0103,1.0010,0.0103,1.0010 "E5F9","E5F9","MSOARIA.DLL",0.0103,1.0010,0.0103,1.0010 "9E3C0","9E3C0","MSOARIA.DLL",0.0103,1.0004,0.0103,1.0004 "144A0","144A0","MSOARIA.DLL",0.0103,1.0002,0.0103,1.0002 "13706","13706","MSOARIA.DLL",0.0103,0.9997,0.0103,0.9997 "2FCF0","2FCF0","MSOARIA.DLL",0.0103,0.9996,0.0103,0.9996 "3B3C9","3B3C9","MSOARIA.DLL",0.0103,0.9991,0.0103,0.9991 "348CB","348CB","MSOARIA.DLL",0.0103,0.9987,0.0103,0.9987 "120C9B","120C9B","MSOARIA.DLL",0.0102,0.9981,0.0102,0.9981 "61A39","61A39","MSOARIA.DLL",0.0102,0.9979,0.0102,0.9979 "13718","13718","MSOARIA.DLL",0.0102,0.9978,0.0102,0.9978 "61B9F","61B9F","MSOARIA.DLL",0.0102,0.9974,0.0102,0.9974 "F5455","F5455","MSOARIA.DLL",0.0102,0.9974,0.0102,0.9974 "12178A","12178A","MSOARIA.DLL",0.0102,0.9966,0.0102,0.9966 "62FBD","62FBD","MSOARIA.DLL",0.0102,0.9962,0.0102,0.9962 "969C4","969C4","MSOARIA.DLL",0.0102,0.9958,0.0102,0.9958 "121A9E","121A9E","MSOARIA.DLL",0.0102,0.9957,0.0102,0.9957 "396D8","396D8","MSOARIA.DLL",0.0102,0.9955,0.0102,0.9955 "13A59","13A59","MSOARIA.DLL",0.0102,0.9949,0.0102,0.9949 "3976E","3976E","MSOARIA.DLL",0.0102,0.9949,0.0102,0.9949 "894A4","894A4","MSOARIA.DLL",0.0102,0.9948,0.0170,1.6522 "121913","121913","MSOARIA.DLL",0.0102,0.9945,0.0102,0.9945 "74DB","74DB","MSOARIA.DLL",0.0102,0.9943,0.0307,2.9943 "7C158","7C158","MSOARIA.DLL",0.0102,0.9915,0.0102,0.9915 "13A60","13A60","MSOARIA.DLL",0.0102,0.9913,0.0102,0.9913 "7D01F","7D01F","MSOARIA.DLL",0.0102,0.9910,0.0102,0.9910 "120C2C","120C2C","MSOARIA.DLL",0.0102,0.9909,0.0102,0.9909 "120C16","120C16","MSOARIA.DLL",0.0102,0.9907,0.0102,0.9907 "40197","40197","MSOARIA.DLL",0.0102,0.9902,0.0102,0.9902 "827CA","827CA","MSOARIA.DLL",0.0102,0.9900,0.0102,0.9900 "37629","37629","MSOARIA.DLL",0.0102,0.9891,0.0102,0.9891 "121938","121938","MSOARIA.DLL",0.0101,0.9883,0.0101,0.9883 "8D4F","8D4F","MSOARIA.DLL",0.0101,0.9883,0.0101,0.9883 "120C30","120C30","MSOARIA.DLL",0.0101,0.9880,0.0101,0.9880 "121910","121910","MSOARIA.DLL",0.0101,0.9844,0.0101,0.9844 "16BF1","16BF1","MSOARIA.DLL",0.0100,0.9788,0.0100,0.9788 "7D032","7D032","MSOARIA.DLL",0.0069,0.6764,0.0069,0.6764 "85B27","85B27","MSOARIA.DLL",0.0067,0.6574,0.0067,0.6574 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_MSPST32.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "81114","81114","MSPST32.DLL",0.0205,2.0000,0.0205,2.0000 "8B28B","8B28B","MSPST32.DLL",0.0205,2.0000,0.0205,2.0000 "100DE","100DE","MSPST32.DLL",0.0204,1.9884,0.0204,1.9884 "19D4F5","19D4F5","MSPST32.DLL",0.0178,1.7340,0.0178,1.7340 "A8FA5","A8FA5","MSPST32.DLL",0.0137,1.3391,0.0137,1.3391 "7CB78","7CB78","MSPST32.DLL",0.0126,1.2324,0.0126,1.2324 "A8E6E","A8E6E","MSPST32.DLL",0.0114,1.1144,0.0114,1.1144 "44AC0","44AC0","MSPST32.DLL",0.0110,1.0673,0.0110,1.0673 "A2810","A2810","MSPST32.DLL",0.0103,1.0084,0.0103,1.0084 "19D4CD","19D4CD","MSPST32.DLL",0.0090,0.8809,0.0090,0.8809 "261A3","261A3","MSPST32.DLL",0.0034,0.3305,0.0034,0.3305 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_MSPTLS.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "520FE","520FE","MSPTLS.DLL",0.0309,3.0086,0.0309,3.0086 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_MicrosoftAccountWAMExtension.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "39B0","39B0","MicrosoftAccountWAMExtension.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Mso20win32client.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "?SortByParameterGroups@Private@EcsNS@Experiment@Mso@@YAXAEAV?$vector@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@V?$allocator@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@2@@std@@AEBV?$shared_ptr@UFeatureConfigs@Experiment@Mso@@@6@@Z","32C3C","Mso20win32client.dll",0.5132,49.9990,1.7549,170.9838 "??$ReplaceRulePointerInMap@V?$unordered_map@KU?$pair@V?$vector@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@V?$allocator@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@@2@@std@@W4UlsColumns@Telemetry@Mso@@@std@@U?$hash@K@2@U?$equal_to@K@2@V?$allocator@U?$pair@$$CBKU?$pair@V?$vector@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@V?$allocator@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@@2@@std@@W4UlsColumns@Telemetry@Mso@@@std@@@std@@@2@@std@@@Telemetry@Mso@@YAXAEAV?$unordered_map@KU?$pair@V?$vector@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@V?$allocator@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@@2@@std@@W4UlsColumns@Telemetry@Mso@@@std@@U?$hash@K@2@U?$equal_to@K@2@V?$allocator@U?$pair@$$CBKU?$pair@V?$vector@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@V?$allocator@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@@2@@std@@W4UlsColumns@Telemetry@Mso@@@std@@@std@@@2@@std@@AEBV?$shared_ptr@UIRule@Telemetry@Mso@@@3@@Z","37D50","Mso20win32client.dll",0.1276,12.4347,0.1276,12.4347 "inflate_fast_chunk_","F10E0","Mso20win32client.dll",0.1241,12.0864,0.1282,12.4937 "?ReadNext@?$JsonReader@_W@Json@Mso@@UEAA?AW4Enum@ParseState@23@XZ","1C8160","Mso20win32client.dll",0.0785,7.6481,0.0990,9.6482 "?GetSharedName@RuleParser@Telemetry@Mso@@QEAAJAEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@_KAEAV?$shared_ptr@_W@5@@Z","364F4","Mso20win32client.dll",0.0686,6.6868,0.1843,17.9522 "??$CheckField@D@StructuredTraceValidator@Logging@Mso@@AEAAXPEBD@Z","35910","Mso20win32client.dll",0.0635,6.1852,0.1148,11.1823 "??$escape_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@@YA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@AEBV01@@Z","2C3A0","Mso20win32client.dll",0.0549,5.3510,0.0653,6.3601 "?Free@Memory@Mso@@YAXPEAX@Z","29390","Mso20win32client.dll",0.0548,5.3414,0.2194,21.3759 "wmemcmp","36740","Mso20win32client.dll",0.0492,4.7929,0.0492,4.7929 "??$find@X@?$_Hash@V?$_Umap_traits@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$tuple@V?$shared_ptr@VABConfig@Experiment@Mso@@@std@@V?$optional@V?$shared_ptr@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@std@@@2@@2@V?$_Uhash_compare@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@U?$hash@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@U?$equal_to@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@2@V?$allocator@U?$pair@$$CBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$tuple@V?$shared_ptr@VABConfig@Experiment@Mso@@@std@@V?$optional@V?$shared_ptr@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@std@@@2@@2@@std@@@2@$0A@@std@@@std@@QEAA?AV?$_List_iterator@V?$_List_val@U?$_List_simple_types@U?$pair@$$CBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$tuple@V?$shared_ptr@VABConfig@Experiment@Mso@@@std@@V?$optional@V?$shared_ptr@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@std@@@2@@2@@std@@@std@@@std@@@1@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@1@@Z","40270","Mso20win32client.dll",0.0483,4.7033,0.0483,4.7033 "??$emplace@AEBV?$shared_ptr@_W@std@@@?$vector@V?$shared_ptr@_W@std@@V?$allocator@V?$shared_ptr@_W@std@@@2@@std@@QEAA?AV?$_Vector_iterator@V?$_Vector_val@U?$_Simple_types@V?$shared_ptr@_W@std@@@std@@@std@@@1@V?$_Vector_const_iterator@V?$_Vector_val@U?$_Simple_types@V?$shared_ptr@_W@std@@@std@@@std@@@1@AEBV?$shared_ptr@_W@1@@Z","37950","Mso20win32client.dll",0.0459,4.4725,0.0459,4.4725 "GetBaseFlightName","42670","Mso20win32client.dll",0.0401,3.9052,0.0401,3.9052 "??0StringWriter@Unicode@Json@Mso@@QEAA@W4PrettyPrint@23@@Z","1B04A4","Mso20win32client.dll",0.0316,3.0825,0.0437,4.2529 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@QEBD@Z","DDAC","Mso20win32client.dll",0.0309,3.0074,0.0309,3.0074 "??1?$KeyValue@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@W4ConfigurationProviderCode@FederationProvider@Authentication@Mso@@@Collections@Mso@@QEAA@XZ","2A8B0","Mso20win32client.dll",0.0308,3.0033,0.1128,10.9938 "??0?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAA@QEB_W@Z","34F20","Mso20win32client.dll",0.0308,3.0018,0.0471,4.5937 "?reset@?$_Optional_destruct_base@VResult@System@Office@@$0A@@std@@QEAAXXZ","17A6A4","Mso20win32client.dll",0.0308,3.0014,0.0308,3.0014 "?CompleteStringLiteral@?$Json_StringParser@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@details@Json@Mso@@MEAA_N_WAEAUToken@?$Json_Parser@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@234@@Z","2EDE0","Mso20win32client.dll",0.0308,3.0008,0.0411,4.0003 "?HrEscape@CMsoUrlSimple@@CAJPEB_WHW4MsoUrlCreateFlags@@PEA_WPEAH@Z","4B5A0","Mso20win32client.dll",0.0308,2.9981,0.0308,2.9981 "?append@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV12@QEBD_K@Z","25124","Mso20win32client.dll",0.0307,2.9950,0.0614,5.9850 "??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@AEBV10@QEBD@Z","1082D4","Mso20win32client.dll",0.0293,2.8522,0.0528,5.1411 "??R?$_Func_class@W4UlsColumns@Telemetry@Mso@@KW4Category@Logging@3@W4InternalSeverity@53@@std@@QEBA?AW4UlsColumns@Telemetry@Mso@@KW4Category@Logging@4@W4InternalSeverity@64@@Z","3116F8","Mso20win32client.dll",0.0283,2.7590,0.0283,2.7590 "?IsTraceThrottled@SampledDiagnosticsThrottler@Diagnostics@Mso@@UEAA_NAEBUTraceHeader@Logging@3@@Z","22720","Mso20win32client.dll",0.0253,2.4661,0.0253,2.4661 "?Lock@?$TLocker@V?$Lockable@V?$AlwaysInit@VCritSecBase@Mso@@@Mso@@VZeroOrOneThreaded@2@@Mso@@VZeroOrOneThreaded@2@@Mso@@QEAAXXZ","25508","Mso20win32client.dll",0.0245,2.3834,0.0961,9.3665 "?MsoShouldTrace@Logging@Mso@@YA_NKW4Category@12@W4Severity@12@W4DataCategories@12@@Z","23800","Mso20win32client.dll",0.0245,2.3834,0.0800,7.7969 "?MsoRgwchIndex@@YAPEB_WPEB_WHH@Z","4AEE0","Mso20win32client.dll",0.0235,2.2907,0.0235,2.2907 "??$T_ReplaceWchWithWchSubstr@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@DString@Mso@@YAXAEAV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@_W1HH@Z","147720","Mso20win32client.dll",0.0224,2.1844,0.0224,2.1844 "?AdjustBarrier@CBaseWorkObject@@QEAAXKPEAUAdjustBarrierInOut@1@@Z","EAA10","Mso20win32client.dll",0.0211,2.0558,0.0512,4.9916 "?GetCategoryName@Logging@Mso@@YAPEB_WW4Category@12@@Z","210F0","Mso20win32client.dll",0.0210,2.0501,0.0210,2.0501 "?ReadAttributeValues@AttributeHelper@Telemetry@Mso@@QEAAJPEAUAttributeValues@23@I@Z","43B74","Mso20win32client.dll",0.0210,2.0466,0.0239,2.3315 "?WriteEscapedString@?$TWriter@_W@Json@Mso@@AEAAXAEBV?$basic_string_view@_WU?$char_traits@_W@std@@@std@@@Z","162234","Mso20win32client.dll",0.0207,2.0159,0.0602,5.8634 "??$make_unique@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@AEBV12@$0A@@std@@YA?AV?$unique_ptr@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@U?$default_delete@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@0@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@0@@Z","26620","Mso20win32client.dll",0.0207,2.0120,0.0412,4.0128 "??1?$unique_ptr@V_Value@details@Json@Mso@@U?$default_delete@V_Value@details@Json@Mso@@@std@@@std@@QEAA@XZ","2917C","Mso20win32client.dll",0.0206,2.0077,0.0652,6.3558 "??$From@PEB_W@TelemetryValue@Telemetry@Mso@@SA?AV012@AEBQEB_W_N@Z","B87D0","Mso20win32client.dll",0.0206,2.0040,0.0717,6.9886 "?LogStructuredTraceTag@ReentrantLoggerDecorator@Logging@Mso@@UEAAXAEBUTraceHeader@23@PEB_WAEBUIStructuredTrace@23@@Z","368C0","Mso20win32client.dll",0.0205,2.0002,2.6265,255.9017 "?push_back@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAAX_W@Z","2D770","Mso20win32client.dll",0.0205,2.0001,0.0360,3.5080 "??$InvokeCallback@V?$StateTracker@UITimerObject@Async@Mso@@VCurrentTimerObjectHolder@Details@23@@Async@Mso@@@?$CallbackObjectBase@UITimerObject@Async@Mso@@VCurrentTimerObjectHolder@Details@23@@Async@Mso@@IEAAXXZ","F9FC","Mso20win32client.dll",0.0205,2.0000,4.2085,410.0356 "??0?$DataField@E@Telemetry@Mso@@QEAA@PEBD$$QEAEW4DataClassifications@Logging@2@@Z","158AC","Mso20win32client.dll",0.0205,2.0000,0.0529,5.1568 "?Accept@Activity@System@Office@@CAXAEBV123@AEAUIDataFieldVisitor@Telemetry@Mso@@@Z","107A00","Mso20win32client.dll",0.0205,2.0000,0.1532,14.9247 "?Accept@CopiedEventContract@Details@Telemetry@Mso@@UEBAXAEAUIDataFieldVisitor@34@@Z","18C510","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?CheckTraceAndThrottle@SampledDiagnosticsThrottler@Diagnostics@Mso@@UEAA_NAEBUTraceHeader@Logging@3@@Z","AF200","Mso20win32client.dll",0.0205,2.0000,0.0309,3.0074 "?Detach@Activity@Telemetry@Mso@@QEAA?AV?$TCntPtr@UIDetachedActivity@Telemetry@Mso@@@3@XZ","13DD0","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?DoPostXmlParseCleanup@Rule@Telemetry@Mso@@UEAAXXZ","FA630","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?GetConfigurationFromDefaultAndCacheIfApplicable@ConfigurationManager@Configuration@Storage@@AEBAXW4ConfigurationId@23@AEAUConfigurationEntry@23@@Z","41F24","Mso20win32client.dll",0.0205,2.0000,0.0561,5.4630 "?GetUlsColumnFlags@ULSRuleSelector@Telemetry@Mso@@QEBA?AW4UlsColumns@23@KW4Category@Logging@3@W4InternalSeverity@63@@Z","13315C","Mso20win32client.dll",0.0205,2.0000,0.0488,4.7590 "?HandleStarts@RuleParseHelper_V@Telemetry@Mso@@IEAAJAEAVXmlReaderHelper@23@@Z","19BE50","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?HasStreamDataToWrite@SendRequestHelper@Http@Mso@@QEBA_NXZ","2412E4","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?InvokeInCallbackContext@Async@Mso@@YAX$$QEAV?$Functor@$$A6AXXZ@2@PEAVIDispatchQueue@12@PEAUIIdleDispatchQueue@Details@12@_N@Z","BF40","Mso20win32client.dll",0.0205,2.0000,22.1882,2161.8240 "?lock@_Mutex_base@std@@QEAAXXZ","41EA0","Mso20win32client.dll",0.0205,2.0000,0.0514,5.0061 "?LogStructuredTraceTag@Logger@Logging@Mso@@UEAAXAEBUTraceHeader@23@PEB_WAEBUIStructuredTrace@23@@Z","36FE0","Mso20win32client.dll",0.0205,2.0000,0.8584,83.6343 "?MsoCchCanonicalizePath@@YAHPEA_WH@Z","3D180","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?PostSelfToOwner@CWorkerQueue@@UEAAXH@Z","EBF60","Mso20win32client.dll",0.0205,2.0000,0.0312,3.0426 "?Release@?$UnknownObject@USimpleNoQuery@RefCountStrategy@Mso@@U?$IFunctor@XAEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@3@@Mso@@UEAAKXZ","EB2B0","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?StartsWith@StringAscii@Mso@@SA_NPEB_WH0H@Z","3B348","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?TryDecode@?$TBase64Decoder@D@Base64@Mso@@UEAA_NAEBV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z","2480C0","Mso20win32client.dll",0.0205,2.0000,0.0205,2.0000 "?NotifyNewConfigsAvailable@ABConfigsCollection@Experiment@Mso@@QEAAIW4ConfigSource@23@AEBV?$shared_ptr@UFeatureConfigs@Experiment@Mso@@@std@@_NPEAUIConfigContext@23@@Z","5EB58","Mso20win32client.dll",0.0205,1.9995,0.2463,23.9966 "?_Min@?$_Tree_val@U?$_Tree_simple_types@U?$pair@$$CB_KV?$map@_KUCluster@Syzygy@@U?$less@_K@std@@V?$allocator@U?$pair@$$CB_KUCluster@Syzygy@@@std@@@4@@std@@@std@@@std@@@std@@SAPEAU?$_Tree_node@U?$pair@$$CB_KV?$map@_KUCluster@Syzygy@@U?$less@_K@std@@V?$allocator@U?$pair@$$CB_KUCluster@Syzygy@@@std@@@4@@std@@@std@@PEAX@2@PEAU32@@Z","A8E4","Mso20win32client.dll",0.0205,1.9989,0.0205,1.9989 "??0TelemetryValue@Telemetry@Mso@@QEAA@$$QEAV012@@Z","29900","Mso20win32client.dll",0.0204,1.9917,0.0204,1.9917 "MsoWchToUpperLid","B3B80","Mso20win32client.dll",0.0203,1.9800,0.0203,1.9800 "??1?$unique_ptr@UISingleDataField@Telemetry@Mso@@U?$default_delete@UISingleDataField@Telemetry@Mso@@@std@@@std@@QEAA@XZ","2DB2C","Mso20win32client.dll",0.0201,1.9578,0.0201,1.9578 "?_Fnv1a_append_bytes@std@@YA_K_KQEBE_K@Z","46670","Mso20win32client.dll",0.0199,1.9379,0.0199,1.9379 "?ReceiveEvent@CompositeEventSink@Telemetry@Mso@@QEAAXAEBUTelemetryEvent@23@@Z","23FE4","Mso20win32client.dll",0.0195,1.8964,2.0234,197.1442 "inflate","EF000","Mso20win32client.dll",0.0188,1.8299,0.1428,13.9163 "?AllocateEx@Memory@Mso@@YAPEAX_KK@Z","259E0","Mso20win32client.dll",0.0182,1.7763,0.1648,16.0590 "?IsNameOrEndObjectAllowed@?$TWriter@D@Json@Mso@@QEBA_NXZ","1621E0","Mso20win32client.dll",0.0171,1.6702,0.0171,1.6702 "?Accept@SingleDataFieldCollection@Telemetry@Mso@@UEBAXAEAUIDataFieldVisitor@23@@Z","11660","Mso20win32client.dll",0.0170,1.6590,0.1683,16.3990 "??0MathEnabledEventField@Telemetry@Mso@@QEAA@AEBV012@@Z","2AA50","Mso20win32client.dll",0.0159,1.5453,0.0159,1.5453 "??$_Allocate@$0BA@U_Default_allocate_traits@std@@@std@@YAPEAX_K@Z","2CED0","Mso20win32client.dll",0.0155,1.5079,0.4446,43.3172 "?TryGetInt64@?$JsonReader@_W@Json@Mso@@UEBA?AV?$optional@_J@std@@XZ","134610","Mso20win32client.dll",0.0152,1.4847,0.0255,2.4837 "__chkstk","1F7820","Mso20win32client.dll",0.0150,1.4630,0.0150,1.4630 "?ParseIntWz@@YAHPEB_WPEAH_N@Z","31094","Mso20win32client.dll",0.0148,1.4382,0.0148,1.4382 "?GetFieldName@FieldProperties@Telemetry@Mso@@QEBAPEB_WE@Z","BA68C","Mso20win32client.dll",0.0145,1.4175,0.0145,1.4175 "?GetFolder@ShellFolderCache@ShellFolder@Mso@@QEAA?AW4CopyStatus@123@IPEA_WI@Z","F395C","Mso20win32client.dll",0.0144,1.4000,0.0349,3.4000 "?LogTrace@TraceCollector@Diagnostics@Mso@@UEAAXAEBV?$DiagnosticLog_t@V?$DiagnosticsStringBuilder@D$0EAA@@Diagnostics@Mso@@VDiagnosticLogSerializer@23@@23@@Z","245E0","Mso20win32client.dll",0.0137,1.3390,0.1573,15.3307 "?HandleColumn@RuleParseHelper_V@Telemetry@Mso@@IEAAJAEAVXmlReaderHelper@23@@Z","433D0","Mso20win32client.dll",0.0137,1.3325,0.3013,29.3597 "?AddInput@FilterRule@Telemetry@Mso@@UEAA_NPEBURoutingInfo@23@@Z","14F080","Mso20win32client.dll",0.0136,1.3218,0.0136,1.3218 "?ImplementXmlHandler@RuleParseHelper_V@Telemetry@Mso@@IEAAJAEAVXmlReaderHelper@23@PEAUXmlHandlerInfo@23@I_N@Z","43080","Mso20win32client.dll",0.0131,1.2783,0.6616,64.4579 "??$GetOptimizedValue@_N@ABConfigsCollection@Experiment@Mso@@QEAA_NAEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@AEB_NAEBUScopeEvaluator@AB@2@AEBU?$pair@$$CBE$$CB_N@4@_N@Z","41FDC","Mso20win32client.dll",0.0131,1.2747,0.0872,8.4942 "??_M@YAXPEAX_K1P6AX0@Z@Z","1C6630","Mso20win32client.dll",0.0129,1.2560,0.0129,1.2560 "?ValidateEvent@Details@Telemetry@Mso@@YA?AW4EventValidationError@123@AEBUEventName@23@AEBV?$shared_ptr@UEventContract@Telemetry@Mso@@@std@@AEBUEventFlags@23@AEBUIDataField@23@W4ContentType@23@@Z","106F6C","Mso20win32client.dll",0.0127,1.2372,0.0401,3.9054 "?append@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEAAAEAV12@QEB_W_K@Z","38F74","Mso20win32client.dll",0.0121,1.1751,0.0599,5.8319 "??1?$SimpleRefCountMemoryGuard@VInstance@Lithium@Storage@@UMakeAllocator@Mso@@@Mso@@QEAA@XZ","15C418","Mso20win32client.dll",0.0120,1.1704,0.0120,1.1704 "?CbHashSize@CNGHashObj@Mso@@UEBAKXZ","184C30","Mso20win32client.dll",0.0110,1.0707,0.0110,1.0707 "??$AppendJsonString@D$0A@@?$DiagnosticsStringBuilder@D$0EAA@@Diagnostics@Mso@@QEAA_NPEBDV?$optional@_K@std@@@Z","1347C4","Mso20win32client.dll",0.0110,1.0673,0.0110,1.0673 "?GetMsoMemHeap@Memory@Mso@@YAPEAUIMsoMemHeap@@XZ","157C90","Mso20win32client.dll",0.0109,1.0616,0.0109,1.0616 "?now@HighPrecisionSteadyClock@Chrono@Storage@@YA?AV?$time_point@Usteady_clock@chrono@std@@V?$duration@_JU?$ratio@$00$0DLJKMKAA@@std@@@23@@chrono@std@@XZ","226610","Mso20win32client.dll",0.0108,1.0554,0.0217,2.1108 "??$_Construct_from_iter@PEADPEAD_K@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@AEAAXPEADQEAD_K@Z","579F0","Mso20win32client.dll",0.0107,1.0432,0.0210,2.0426 "?CreateFromTelemetryEvent@EventPropertiesFactory@AriaEventSink@Mso@@QEAA?AV?$optional@UEventProperties@AriaApi@Telemetry@Mso@@@std@@AEBUTelemetryEvent@Telemetry@3@_NAEBV?$optional@USampleRate@Sampling@Telemetry@Mso@@@5@AEBV?$optional@W4SamplingPolicy@Telemetry@Mso@@@5@@Z","16F664","Mso20win32client.dll",0.0106,1.0348,0.4484,43.6835 "?WriteRawChars@?$TWriter@_W@Json@Mso@@AEAAXAEBV?$basic_string_view@_WU?$char_traits@_W@std@@@std@@@Z","16239C","Mso20win32client.dll",0.0105,1.0220,0.0208,2.0218 "??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@AEBV01@@Z","22ACC","Mso20win32client.dll",0.0104,1.0132,0.0254,2.4709 "??1CBaseWorkObject@@UEAA@XZ","EB080","Mso20win32client.dll",0.0104,1.0093,0.0104,1.0093 "?ValidateEventContract@DataFieldValidator@Details@Telemetry@Mso@@QEAAXAEBUEventContract@34@@Z","1077A0","Mso20win32client.dll",0.0104,1.0092,0.0104,1.0092 "?IsGlobalEnvironment@FederationInfo@FederationProvider@Authentication@Mso@@CA_NAEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z","331C30","Mso20win32client.dll",0.0103,1.0082,0.0103,1.0082 "??$_Try_emplace@AEB_K$$V@?$_Hash@V?$_Umap_traits@_KIV?$_Uhash_compare@_KU?$hash@_K@std@@U?$equal_to@_K@2@@std@@V?$allocator@U?$pair@$$CB_KI@std@@@2@$0A@@std@@@std@@IEAA?AU?$pair@PEAU?$_List_node@U?$pair@$$CB_KI@std@@PEAX@std@@_N@1@AEB_K@Z","AF578","Mso20win32client.dll",0.0103,1.0074,0.0103,1.0074 "??$AppendJsonKey@D$0A@@?$DiagnosticsStringBuilder@D$0EAA@@Diagnostics@Mso@@QEAA_NPEBDAEBV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z","22260","Mso20win32client.dll",0.0103,1.0057,0.0103,1.0057 "?EvaluateGroupedFeatureGates@ABConfigsCollection@Experiment@Mso@@AEBAXAEBV?$shared_ptr@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@std@@AEBV?$shared_ptr@VABConfig@Experiment@Mso@@@5@@Z","41CB4","Mso20win32client.dll",0.0103,1.0056,0.0206,2.0065 "?ForEachLoggingDependency@Rule@Telemetry@Mso@@UEBAXAEBV?$FunctorRef@$$A6AXAEBURoutingInfo@Telemetry@Mso@@@Z@3@@Z","B9650","Mso20win32client.dll",0.0103,1.0054,0.0205,1.9978 "?IsLabMachine@BuildInfo@Experiment@Mso@@UEAA_N_N@Z","159050","Mso20win32client.dll",0.0103,1.0053,0.0103,1.0053 "MsoWzLowerCore","53560","Mso20win32client.dll",0.0103,1.0051,0.0103,1.0051 "?WriteBool@StringWriter@Unicode@Json@Mso@@UEAA_N_N@Z","1C89F0","Mso20win32client.dll",0.0103,1.0048,0.0103,1.0048 "?map_fields@_Object@details@Json@Mso@@AEAAXXZ","261C0","Mso20win32client.dll",0.0103,1.0033,0.0103,1.0033 "?ForEachMatchingRule@ULSRuleSelector@Telemetry@Mso@@UEBAXKW4Category@Logging@3@W4InternalSeverity@53@V?$function@$$A6AXAEBV?$shared_ptr@UIRule@Telemetry@Mso@@@std@@@Z@std@@@Z","B8400","Mso20win32client.dll",0.0103,1.0027,0.3053,29.7443 "??$_Try_emplace@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@$$V@?$_Hash@V?$_Umap_traits@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$unique_ptr@UAggregation@Telemetry@Mso@@U?$default_delete@UAggregation@Telemetry@Mso@@@std@@@2@V?$_Uhash_compare@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$hash@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@U?$equal_to@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$unique_ptr@UAggregation@Telemetry@Mso@@U?$default_delete@UAggregation@Telemetry@Mso@@@std@@@2@@std@@@2@$0A@@std@@@std@@IEAA?AU?$pair@PEAU?$_List_node@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@V?$unique_ptr@UAggregation@Telemetry@Mso@@U?$default_delete@UAggregation@Telemetry@Mso@@@std@@@2@@std@@PEAX@std@@_N@1@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z","25604","Mso20win32client.dll",0.0103,1.0025,0.0103,1.0025 "??0TelemetryEventParams@Telemetry@Mso@@QEAA@$$QEAV012@@Z","61764","Mso20win32client.dll",0.0103,1.0025,0.0103,1.0025 "?Release@?$TRefCountedImpl@UILogWriter@Logging@Mso@@@Mso@@UEBAXXZ","D300","Mso20win32client.dll",0.0103,1.0025,0.0103,1.0025 "?_Tidy_deallocate@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEAAXXZ","29590","Mso20win32client.dll",0.0103,1.0023,0.0308,3.0041 "?PassEventViaRoutingInfo@RuleImplementor@Telemetry@Mso@@SAXPEAUIRuleImplementor@23@PEAV?$vector@URoutingInfo@Telemetry@Mso@@V?$allocator@URoutingInfo@Telemetry@Mso@@@std@@@std@@AEAUEventID@23@AEBUITelemetryEvent@23@I@Z","B9CF8","Mso20win32client.dll",0.0103,1.0022,0.2403,23.4147 "?GetCurrentCorrelation@CorrelationManager@Logging@Mso@@YA?AU_GUID@@XZ","20474","Mso20win32client.dll",0.0103,1.0021,0.0103,1.0021 "?SerializeLog@DiagnosticLogSerializer@Diagnostics@Mso@@SA_NAEAV?$DiagnosticsStringBuilder@D$0EAA@@23@AEBV?$DiagnosticLog_t@V?$DiagnosticsStringBuilder@D$0EAA@@Diagnostics@Mso@@VDiagnosticLogSerializer@23@@23@@Z","20BDC","Mso20win32client.dll",0.0103,1.0020,0.0452,4.4013 "?GetHashedName@Experiment@Mso@@YA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@PEB_W@Z","42530","Mso20win32client.dll",0.0103,1.0019,0.0504,4.9071 "?SubmitEventProcessingItemIdempotent@UlsDataCollector@Telemetry@Mso@@AEAA_NPEQ123@_NP6AAEAVIDispatchQueue@Async@3@XZ@Z","1F544","Mso20win32client.dll",0.0103,1.0018,0.0103,1.0018 "?_Delete_this@?$_Ref_count_obj2@VRulesFetchRequestExecutor@RulesFetch@Mso@@@std@@EEAAXXZ","37B00","Mso20win32client.dll",0.0103,1.0012,0.0103,1.0012 "?CastToType@MathEnabledEventField@Telemetry@Mso@@QEBAJW4FieldType@23@PEAV123@@Z","29D2C","Mso20win32client.dll",0.0103,1.0010,0.0615,5.9956 "??$?4JV?$TCntPtr@UKey@Registry@Mso@@@Mso@@$0A@@?$tuple@AEAJAEAV?$TCntPtr@UKey@Registry@Mso@@@Mso@@@std@@QEAAAEAV01@$$QEAU?$pair@JV?$TCntPtr@UKey@Registry@Mso@@@Mso@@@1@@Z","C3B58","Mso20win32client.dll",0.0103,1.0009,1.7755,172.9905 "?AllocateEx@Throw@Memory@Mso@@YAPEAX_KK@Z","27BC0","Mso20win32client.dll",0.0103,1.0008,0.0205,1.9956 "MsoSzToWz","3E460","Mso20win32client.dll",0.0103,1.0007,0.0210,2.0487 "??0ScopeHolder@ActivityScope@Mso@@QEAA@KPEB_WAEBV?$shared_ptr@UIMsoLoggingScope@ActivityScope@Mso@@@std@@_NW4Severity@Logging@2@@Z","338850","Mso20win32client.dll",0.0103,1.0003,0.0103,1.0003 "??1?$MemHeapPtr@PEAD$0A@@Mso@@QEAA@XZ","B7D28","Mso20win32client.dll",0.0103,1.0002,0.0308,3.0031 "??$_Integer_to_chars@_K@std@@YA?AUto_chars_result@0@PEADQEAD_KH@Z","1C33D8","Mso20win32client.dll",0.0103,1.0000,0.0103,1.0000 "?EnsureGroupExists@Rule@Telemetry@Mso@@QEAAPEAURuleResultSet@23@I@Z","28964","Mso20win32client.dll",0.0103,1.0000,0.0204,1.9867 "?ProcessParserData@RuleManager@Telemetry@Mso@@MEAAJAEBV?$TCntPtr@UIXmlReader@@@3@@Z","1EEB90","Mso20win32client.dll",0.0103,1.0000,0.9768,95.1659 "?RegQueryWz@DString@Mso@@YAJAEAV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@PEAUHKEY__@@PEB_W@Z","34C8A0","Mso20win32client.dll",0.0103,0.9999,0.0305,2.9745 "??$count@X@?$_Hash@V?$_Uset_traits@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$_Uhash_compare@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@U?$hash@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@U?$equal_to@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@2@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@$0A@@std@@@std@@QEBA_KAEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@1@@Z","5F684","Mso20win32client.dll",0.0103,0.9997,0.0103,0.9997 "?GetABConfigFromConfigName@ABConfigsCollection@Experiment@Mso@@AEBA?AV?$tuple@V?$shared_ptr@VABConfig@Experiment@Mso@@@std@@V?$optional@V?$shared_ptr@V?$vector@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$allocator@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@std@@@std@@@2@@std@@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@5@@Z","4000C","Mso20win32client.dll",0.0103,0.9996,0.0691,6.7356 "?NextCharacter@?$Json_StringParser@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@details@Json@Mso@@MEAA_WXZ","2ECD0","Mso20win32client.dll",0.0103,0.9995,0.0103,0.9995 "?Remove@?$LRUCache@PEBU_orkey@@V?$TCntPtr@UKey@Registry@Mso@@@Mso@@$0CA@@Collections@Mso@@QEAAXAEBQEBU_orkey@@@Z","C2A68","Mso20win32client.dll",0.0103,0.9994,0.0513,5.0021 "??4value@Json@Mso@@QEAAAEAV012@AEBV012@@Z","15B320","Mso20win32client.dll",0.0103,0.9993,0.0715,6.9673 "??$CrashIfIncorrectType@PEBD@TelemetryValue@Telemetry@Mso@@AEBAXXZ","13F3C0","Mso20win32client.dll",0.0103,0.9992,0.0103,0.9992 "?index@_Object@details@Json@Mso@@UEAAAEAVvalue@34@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z","28BE0","Mso20win32client.dll",0.0103,0.9992,0.0735,7.1595 "?WriteString@StringWriter@Unicode@Json@Mso@@UEAA_NPEB_W@Z","1C8BF0","Mso20win32client.dll",0.0103,0.9988,0.0704,6.8622 "?_Check_rehash_required_1@?$_Hash@V?$_Umap_traits@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$shared_ptr@VIPersistentStore@Mso@@@2@V?$_Uhash_compare@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@U?$hash@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@U?$equal_to@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@2@@2@V?$allocator@U?$pair@$$CBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@V?$shared_ptr@VIPersistentStore@Mso@@@2@@std@@@2@$0A@@std@@@std@@IEBA_NXZ","A2E8","Mso20win32client.dll",0.0103,0.9987,0.0103,0.9987 "?_ParseValue@?$Json_Parser@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@details@Json@Mso@@AEAA?AV?$unique_ptr@V_Value@details@Json@Mso@@U?$default_delete@V_Value@details@Json@Mso@@@std@@@std@@AEAUToken@1234@@Z","30330","Mso20win32client.dll",0.0102,0.9984,0.4651,45.3131 "__security_check_cookie","1C6610","Mso20win32client.dll",0.0102,0.9980,0.0102,0.9980 "?HrUnescape@CMsoUrlSimple@@AEBAJPEB_WHPEA_WPEAHW4MsoUrlDisplayFormFlags@@@Z","4BAC0","Mso20win32client.dll",0.0102,0.9980,0.0102,0.9980 "??$FNVHash@_K$0?DEANGDBLHLNNNMNL@$0BAAAAAAABLD@@Details@Hash@Mso@@YA_KPEBE_K_K@Z","75ADC","Mso20win32client.dll",0.0102,0.9979,0.0102,0.9979 "?AppendExportabilityInfo@EventPropertiesFactory@AriaEventSink@Mso@@CAXAEBUTelemetryEvent@Telemetry@3@AEAUEventProperties@AriaApi@53@@Z","16640C","Mso20win32client.dll",0.0102,0.9979,0.0102,0.9979 "?GetUserIdSpaceByCIDUserId@AlwaysOnMetadataProvider@Telemetry@Mso@@KA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@5@@Z","B3624","Mso20win32client.dll",0.0102,0.9970,0.0102,0.9970 "?HrSetFromUserRgwch@CMsoUrlSimple@@UEAAJPEB_WHKPEBUIMsoUrl@@W4MsoUrlCreateFlags@@@Z","394C0","Mso20win32client.dll",0.0102,0.9970,0.1555,15.1514 "?TakeInput@FilterRule@Telemetry@Mso@@UEAAXAEAUEventID@23@AEBUITelemetryEvent@23@I@Z","BA960","Mso20win32client.dll",0.0102,0.9966,0.1371,13.3619 "??$CrashIfIncorrectType@PEB_W@TelemetryValue@Telemetry@Mso@@AEBAXXZ","2A9E0","Mso20win32client.dll",0.0102,0.9955,0.0102,0.9955 "??4?$TypeErasedIterator@V?$shared_ptr@UIRule@Telemetry@Mso@@@std@@@Telemetry@Mso@@QEAAAEAV012@AEBV012@@Z","B8F50","Mso20win32client.dll",0.0102,0.9955,0.0102,0.9955 "?_Decref@_Ref_count_base@std@@QEAAXXZ","37A50","Mso20win32client.dll",0.0102,0.9953,0.0692,6.7461 "?Crack@CMsoUrlSimple@@IEBAXXZ","4E1A0","Mso20win32client.dll",0.0102,0.9951,0.0337,3.2858 "MsoMultiByteToWideChar","3E940","Mso20win32client.dll",0.0102,0.9945,0.0723,7.0410 "?GetEventOverrides@TelemetryNamespaceTreeNode@Telemetry@Mso@@QEBA?AV?$optional@VTelemetryEventOverrides@Telemetry@Mso@@@std@@AEBUEventName@23@_K@Z","DA50","Mso20win32client.dll",0.0102,0.9943,0.0612,5.9648 "?TakeInput@Rule@Telemetry@Mso@@UEAAXAEAUEventID@23@AEBUITelemetryEvent@23@I@Z","B9B80","Mso20win32client.dll",0.0102,0.9943,0.2172,21.1589 "??$_Emplace_reallocate@VTelemetryField@Telemetry@Mso@@@?$vector@VTelemetryField@Telemetry@Mso@@V?$allocator@VTelemetryField@Telemetry@Mso@@@std@@@std@@AEAAPEAVTelemetryField@Telemetry@Mso@@QEAV234@$$QEAV234@@Z","2A704","Mso20win32client.dll",0.0102,0.9940,0.0281,2.7414 "?AppendTime@?$DiagnosticsStringBuilder@D$0EAA@@Diagnostics@Mso@@QEAA_NAEBU_SYSTEMTIME@@W4DateEncoding@23@@Z","211C0","Mso20win32client.dll",0.0102,0.9938,0.0102,0.9938 "?Accept@Consent@System@Office@@CAXAEBV123@AEAUIDataFieldVisitor@Telemetry@Mso@@@Z","175230","Mso20win32client.dll",0.0102,0.9935,0.0718,6.9909 "??$T_ReleaseBuffer@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@DString@Mso@@YAXAEAV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z","2F044","Mso20win32client.dll",0.0102,0.9931,0.0102,0.9931 "?TryGetInt32@?$JsonReader@_W@Json@Mso@@UEBA?AV?$optional@H@std@@XZ","134590","Mso20win32client.dll",0.0102,0.9927,0.0357,3.4764 "??$_Emplace@AEBUEventID@Telemetry@Mso@@@?$_Tree@V?$_Tset_traits@UEventID@Telemetry@Mso@@V?$LessFunctor@UEventID@Telemetry@Mso@@@Memory@3@V?$allocator@UEventID@Telemetry@Mso@@@std@@$0A@@std@@@std@@IEAA?AU?$pair@PEAU?$_Tree_node@UEventID@Telemetry@Mso@@PEAX@std@@_N@1@AEBUEventID@Telemetry@Mso@@@Z","12E388","Mso20win32client.dll",0.0102,0.9924,0.0102,0.9924 "?AddRef@?$RefCountedObject@VISystemMemoryMapper@SharedMemory@Disco@@$$V@Mso@@UEBAXXZ","16E0B0","Mso20win32client.dll",0.0102,0.9915,0.0102,0.9915 "?EmplaceBack@StructuredTraceReader@Telemetry@Mso@@AEAAXPEBD$$QEAVTelemetryValue@23@@Z","350B0","Mso20win32client.dll",0.0102,0.9907,0.0409,3.9821 "??$WriteStructuredObject@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@StructuredTraceJsonSerializer@Logging@Mso@@AEAAXAEBU?$ClassifiedStructuredObject@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Diagnostics@2@@Z","3E038","Mso20win32client.dll",0.0102,0.9899,0.0271,2.6412 "?HrSetFromCanonicalUrlWithGrfurl@CMsoUrlSimple@@QEAAJPEB_WKPEBUIMsoUrl@@W4MsoUrlCreateFlags@@@Z","3AC60","Mso20win32client.dll",0.0102,0.9899,0.0236,2.2969 "?Clear@?$TCntPtr@UILogWriter@Logging@Mso@@@Mso@@QEAAXXZ","29364","Mso20win32client.dll",0.0101,0.9886,0.0306,2.9783 "??$Make@UKey@Registry@Mso@@U123@AEAPEAUHKEY__@@_N@Mso@@YA?AV?$TCntPtr@UKey@Registry@Mso@@@0@AEAPEAUHKEY__@@$$QEA_N@Z","55EE1C","Mso20win32client.dll",0.0101,0.9879,0.0304,2.9637 "??$_Find_lower_bound@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@?$_Tree@V?$_Tmap_traits@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VTelemetryNamespaceTreeNode@Telemetry@Mso@@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VTelemetryNamespaceTreeNode@Telemetry@Mso@@@std@@@2@$0A@@std@@@std@@IEBA?AU?$_Tree_find_result@PEAU?$_Tree_node@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VTelemetryNamespaceTreeNode@Telemetry@Mso@@@std@@PEAX@std@@@1@AEBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@1@@Z","DC48","Mso20win32client.dll",0.0101,0.9877,0.0203,1.9815 "_Smtx_unlock_shared","1C72A8","Mso20win32client.dll",0.0101,0.9876,0.0101,0.9876 "?HrClone@CMsoUrlSimple@@MEBAJPEAPEAUIMsoUrl@@@Z","3B5D0","Mso20win32client.dll",0.0101,0.9876,0.0101,0.9876 "??$_Free_non_head@V?$allocator@U?$_List_node@U?$pair@$$CBW4RequestSettings@Http@Mso@@V?$TCntPtr@UIRefCounted@Mso@@@3@@std@@PEAX@std@@@std@@@?$_List_node@U?$pair@$$CBW4RequestSettings@Http@Mso@@V?$TCntPtr@UIRefCounted@Mso@@@3@@std@@PEAX@std@@SAXAEAV?$allocator@U?$_List_node@U?$pair@$$CBW4RequestSettings@Http@Mso@@V?$TCntPtr@UIRefCounted@Mso@@@3@@std@@PEAX@std@@@1@PEAU01@@Z","1619BC","Mso20win32client.dll",0.0101,0.9872,0.0101,0.9872 "?_Tidy@?$vector@VMathEnabledEventField@Telemetry@Mso@@V?$allocator@VMathEnabledEventField@Telemetry@Mso@@@std@@@std@@AEAAXXZ","2B2A8","Mso20win32client.dll",0.0101,0.9867,0.0204,1.9879 "??1?$SimpleRefCountMemoryGuard@VStringWriter@Unicode@Json@Mso@@UMakeAllocator@4@@Mso@@QEAA@XZ","1C3214","Mso20win32client.dll",0.0101,0.9797,0.0101,0.9797 "?MsoWzToSzSimpleInPlace@@YAHPEA_W@Z","241590","Mso20win32client.dll",0.0100,0.9785,0.0201,1.9570 "??1?$_Hash@V?$_Umap_traits@U?$pair@W4Category@Logging@Mso@@W4InternalSeverity@23@@std@@V?$vector@GV?$allocator@G@std@@@2@V?$_Uhash_compare@U?$pair@W4Category@Logging@Mso@@W4InternalSeverity@23@@std@@U?$hash@U?$pair@W4Category@Logging@Mso@@W4InternalSeverity@23@@std@@@2@U?$equal_to@U?$pair@W4Category@Logging@Mso@@W4InternalSeverity@23@@std@@@2@@2@V?$allocator@U?$pair@$$CBU?$pair@W4Category@Logging@Mso@@W4InternalSeverity@23@@std@@V?$vector@GV?$allocator@G@std@@@2@@std@@@2@$0A@@std@@@std@@QEAA@XZ","BF344","Mso20win32client.dll",0.0100,0.9750,0.0235,2.2937 "??R?$_Func_class@_NKW4Category@Logging@Mso@@W4InternalSeverity@23@@std@@QEBA_NKW4Category@Logging@Mso@@W4InternalSeverity@34@@Z","2A4CBC","Mso20win32client.dll",0.0100,0.9706,0.0199,1.9412 "?WriteDiagnosticLog@SizeLimitedlogFileCollection@Diagnostics@Mso@@UEAAXV?$basic_string_view@DU?$char_traits@D@std@@@std@@@Z","156AE0","Mso20win32client.dll",0.0099,0.9657,0.0467,4.5457 "??$make_unique@$$BY0A@UColumnProperties@Telemetry@Mso@@$0A@@std@@YA?AV?$unique_ptr@$$BY0A@UColumnProperties@Telemetry@Mso@@U?$default_delete@$$BY0A@UColumnProperties@Telemetry@Mso@@@std@@@0@_K@Z","279CC","Mso20win32client.dll",0.0099,0.9621,0.0185,1.8013 "??$transform@V?$_String_iterator@V?$_String_val@U?$_Simple_types@_W@std@@@std@@@std@@V12@P6AHH@Z@std@@YA?AV?$_String_iterator@V?$_String_val@U?$_Simple_types@_W@std@@@std@@@0@V10@0V10@P6AHH@Z@Z","5F610","Mso20win32client.dll",0.0099,0.9606,0.0201,1.9562 "?MsoEnumValueW@@YAJPEBU_msoreg@@KPEA_WPEAK22PEAE2@Z","49D50","Mso20win32client.dll",0.0095,0.9254,0.0908,8.8483 "??1?$Result@X@Storage@@UEAA@XZ","22FAF0","Mso20win32client.dll",0.0092,0.8994,0.0092,0.8994 "??C?$optional@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@std@@QEBAPEBV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@1@XZ","15564","Mso20win32client.dll",0.0092,0.8917,0.0092,0.8917 "??0ColumnProperties@Telemetry@Mso@@QEAA@XZ","27AA0","Mso20win32client.dll",0.0086,0.8392,0.0086,0.8392 "?AddGroupSource@GrouperRule@Telemetry@Mso@@QEAA_NPEBURoutingInfo@23@@Z","F8C80","Mso20win32client.dll",0.0073,0.7094,0.0073,0.7094 "??$AppendJsonString@_W$0A@@?$DiagnosticsStringBuilder@D$0EAA@@Diagnostics@Mso@@QEAA_NPEB_WV?$optional@_K@std@@@Z","220D4","Mso20win32client.dll",0.0068,0.6641,0.0068,0.6641 "?Visit@StructuredTraceSerializer@Diagnostics@Mso@@UEAAXAEBU?$ClassifiedStructuredObject@V?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@23@@Z","202F0","Mso20win32client.dll",0.0068,0.6622,0.0068,0.6622 "?SampleEvent@Sampling@Telemetry@Mso@@YA?AV?$optional@V?$tuple@W4SamplingPolicy@Telemetry@Mso@@USampleRate@Sampling@23@@std@@@std@@V?$optional@USampleRate@Sampling@Telemetry@Mso@@@5@AEBV?$optional@VEventSamplingMetadata@Telemetry@Mso@@@5@AEBUEventFlags@23@AEBUSamplingMetadata@123@@Z","84C0","Mso20win32client.dll",0.0068,0.6579,0.0390,3.8006 "??$CopyAndSet@PEBD@TelemetryValue@Telemetry@Mso@@AEAAXAEBQEBD@Z","12B390","Mso20win32client.dll",0.0063,0.6129,0.0063,0.6129 "??OMathEnabledEventField@Telemetry@Mso@@QEBA?AV012@AEBV012@@Z","129654","Mso20win32client.dll",0.0059,0.5763,0.0059,0.5763 "?substr@?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@QEBA?AV12@_K0@Z","336F8","Mso20win32client.dll",0.0059,0.5713,0.0263,2.5653 "?Delete@AnyType@Mso@@AEAAXXZ","2883C","Mso20win32client.dll",0.0049,0.4810,0.0049,0.4810 "?ReadNextAttribute@XmlReaderHelper@Telemetry@Mso@@QEAAJXZ","4338C","Mso20win32client.dll",0.0029,0.2849,0.0029,0.2849 "??$_Insert_range_unchecked@V?$_List_unchecked_const_iterator@V?$_List_val@U?$_List_simple_types@U?$pair@$$CBVEventSamplingMetadata@Telemetry@Mso@@USampleRate@Sampling@23@@std@@@std@@@std@@U_Iterator_base0@2@@std@@V12@@?$_Hash@V?$_Umap_traits@VEventSamplingMetadata@Telemetry@Mso@@USampleRate@Sampling@23@V?$_Uhash_compare@VEventSamplingMetadata@Telemetry@Mso@@U?$hash@VEventSamplingMetadata@Telemetry@Mso@@@std@@U?$equal_to@VEventSamplingMetadata@Telemetry@Mso@@@5@@std@@V?$allocator@U?$pair@$$CBVEventSamplingMetadata@Telemetry@Mso@@USampleRate@Sampling@23@@std@@@7@$0A@@std@@@std@@IEAAXV?$_List_unchecked_const_iterator@V?$_List_val@U?$_List_simple_types@U?$pair@$$CBVEventSamplingMetadata@Telemetry@Mso@@USampleRate@Sampling@23@@std@@@std@@@std@@U_Iterator_base0@2@@1@V21@@Z","2D4AC","Mso20win32client.dll",0.0017,0.1628,0.0222,2.1613 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Mso30win32client.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1D4EB6","1D4EB6","Mso30win32client.dll",0.1345,13.1051,0.1345,13.1051 "1D4EDE","1D4EDE","Mso30win32client.dll",0.1010,9.8378,0.1010,9.8378 "1D4EB2","1D4EB2","Mso30win32client.dll",0.0856,8.3373,0.0856,8.3373 "1D4DFA","1D4DFA","Mso30win32client.dll",0.0652,6.3520,0.0652,6.3520 "1D4E61","1D4E61","Mso30win32client.dll",0.0617,6.0119,0.0617,6.0119 "1D4F2D","1D4F2D","Mso30win32client.dll",0.0512,4.9837,0.0512,4.9837 "1D4E20","1D4E20","Mso30win32client.dll",0.0511,4.9787,0.0511,4.9787 "1D4EFC","1D4EFC","Mso30win32client.dll",0.0488,4.7571,0.0488,4.7571 "18A6B","18A6B","Mso30win32client.dll",0.0424,4.1268,0.0424,4.1268 "1D4E27","1D4E27","Mso30win32client.dll",0.0413,4.0191,0.0413,4.0191 "1D4E37","1D4E37","Mso30win32client.dll",0.0402,3.9195,0.0402,3.9195 "1D4ECD","1D4ECD","Mso30win32client.dll",0.0355,3.4549,0.0355,3.4549 "1D4EF4","1D4EF4","Mso30win32client.dll",0.0350,3.4107,0.0350,3.4107 "21DD27","21DD27","Mso30win32client.dll",0.0342,3.3308,0.0342,3.3308 "21DDD4","21DDD4","Mso30win32client.dll",0.0308,3.0045,0.0308,3.0045 "1D4F17","1D4F17","Mso30win32client.dll",0.0308,3.0041,0.0308,3.0041 "1DA1B0","1DA1B0","Mso30win32client.dll",0.0308,2.9997,0.0308,2.9997 "21DD56","21DD56","Mso30win32client.dll",0.0306,2.9858,0.0306,2.9858 "A54B","A54B","Mso30win32client.dll",0.0306,2.9801,0.0306,2.9801 "1D4EC8","1D4EC8","Mso30win32client.dll",0.0304,2.9663,0.0304,2.9663 "21DDDF","21DDDF","Mso30win32client.dll",0.0268,2.6128,0.0268,2.6128 "1D4E0F","1D4E0F","Mso30win32client.dll",0.0243,2.3655,0.0243,2.3655 "1D4E2B","1D4E2B","Mso30win32client.dll",0.0230,2.2415,0.0230,2.2415 "1D46F8","1D46F8","Mso30win32client.dll",0.0213,2.0730,0.0213,2.0730 "21DD5B","21DD5B","Mso30win32client.dll",0.0209,2.0336,0.0209,2.0336 "27E26D","27E26D","Mso30win32client.dll",0.0208,2.0313,0.0208,2.0313 "1D4E8B","1D4E8B","Mso30win32client.dll",0.0208,2.0290,0.0208,2.0290 "CEB1","CEB1","Mso30win32client.dll",0.0206,2.0033,0.0206,2.0033 "21DD0E","21DD0E","Mso30win32client.dll",0.0205,2.0022,0.0205,2.0022 "1D4EE3","1D4EE3","Mso30win32client.dll",0.0205,2.0021,0.0205,2.0021 "10F6BE","10F6BE","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "17C999","17C999","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "17CEE","17CEE","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "18A05","18A05","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "18A7A","18A7A","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "1D0FF5","1D0FF5","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "1D41D4","1D41D4","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "1D4B18","1D4B18","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "1E047A","1E047A","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "25FD20","25FD20","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "35804","35804","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "383E40","383E40","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "3C104","3C104","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "3E9C5E","3E9C5E","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "41E2F","41E2F","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "41E35","41E35","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "479D50","479D50","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "4AF34","4AF34","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "4E8B8","4E8B8","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "52595C","52595C","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "57E7C","57E7C","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "8199EE","8199EE","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "9034D","9034D","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "96C3C","96C3C","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "F583D","F583D","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "F5E30","F5E30","Mso30win32client.dll",0.0205,2.0000,0.0205,2.0000 "1D4E70","1D4E70","Mso30win32client.dll",0.0205,1.9987,0.0205,1.9987 "45C7B0","45C7B0","Mso30win32client.dll",0.0205,1.9963,0.0205,1.9963 "1D4F26","1D4F26","Mso30win32client.dll",0.0205,1.9958,0.0205,1.9958 "6E29","6E29","Mso30win32client.dll",0.0205,1.9930,0.0205,1.9930 "1D4DF6","1D4DF6","Mso30win32client.dll",0.0203,1.9819,0.0203,1.9819 "1D4EA9","1D4EA9","Mso30win32client.dll",0.0203,1.9775,0.0203,1.9775 "1D79F2","1D79F2","Mso30win32client.dll",0.0203,1.9744,0.0203,1.9744 "1D4F78","1D4F78","Mso30win32client.dll",0.0200,1.9527,0.0200,1.9527 "21DDB5","21DDB5","Mso30win32client.dll",0.0187,1.8268,0.0187,1.8268 "21D39F","21D39F","Mso30win32client.dll",0.0187,1.8202,0.0187,1.8202 "315590","315590","Mso30win32client.dll",0.0186,1.8086,0.0186,1.8086 "1D5378","1D5378","Mso30win32client.dll",0.0179,1.7445,0.0179,1.7445 "1D0AE6","1D0AE6","Mso30win32client.dll",0.0177,1.7287,0.0177,1.7287 "1D4E3E","1D4E3E","Mso30win32client.dll",0.0166,1.6166,0.0166,1.6166 "1D4F37","1D4F37","Mso30win32client.dll",0.0161,1.5685,0.0161,1.5685 "508D0","508D0","Mso30win32client.dll",0.0156,1.5156,0.0156,1.5156 "3C618","3C618","Mso30win32client.dll",0.0154,1.5020,0.0154,1.5020 "220FD0","220FD0","Mso30win32client.dll",0.0150,1.4568,0.0150,1.4568 "1D5370","1D5370","Mso30win32client.dll",0.0137,1.3394,0.0137,1.3394 "9695A","9695A","Mso30win32client.dll",0.0129,1.2533,0.0129,1.2533 "1D4238","1D4238","Mso30win32client.dll",0.0127,1.2368,0.0127,1.2368 "C5265","C5265","Mso30win32client.dll",0.0120,1.1704,0.0120,1.1704 "1D4F1E","1D4F1E","Mso30win32client.dll",0.0119,1.1556,0.0119,1.1556 "1D64DD","1D64DD","Mso30win32client.dll",0.0109,1.0635,0.0109,1.0635 "86D3C","86D3C","Mso30win32client.dll",0.0109,1.0609,0.0109,1.0609 "1D8277","1D8277","Mso30win32client.dll",0.0108,1.0522,0.0108,1.0522 "1CF51E","1CF51E","Mso30win32client.dll",0.0108,1.0501,0.0108,1.0501 "1D4E95","1D4E95","Mso30win32client.dll",0.0107,1.0393,0.0107,1.0393 "1D4315","1D4315","Mso30win32client.dll",0.0107,1.0385,0.0107,1.0385 "6F724","6F724","Mso30win32client.dll",0.0107,1.0383,0.0107,1.0383 "D7030","D7030","Mso30win32client.dll",0.0107,1.0383,0.0107,1.0383 "18BB24","18BB24","Mso30win32client.dll",0.0107,1.0378,0.1031,10.0425 "3B59A9","3B59A9","Mso30win32client.dll",0.0106,1.0342,0.0106,1.0342 "1D4F7E","1D4F7E","Mso30win32client.dll",0.0106,1.0285,0.0106,1.0285 "27A567","27A567","Mso30win32client.dll",0.0105,1.0269,0.0105,1.0269 "1D4E55","1D4E55","Mso30win32client.dll",0.0105,1.0216,0.0105,1.0216 "223381","223381","Mso30win32client.dll",0.0105,1.0204,0.0105,1.0204 "8FF40","8FF40","Mso30win32client.dll",0.0105,1.0189,0.0105,1.0189 "1B5CF0","1B5CF0","Mso30win32client.dll",0.0104,1.0173,0.0104,1.0173 "2DBA28","2DBA28","Mso30win32client.dll",0.0104,1.0133,0.0104,1.0133 "9FC40","9FC40","Mso30win32client.dll",0.0104,1.0126,0.0104,1.0126 "21DDD7","21DDD7","Mso30win32client.dll",0.0104,1.0115,0.0104,1.0115 "1D1018","1D1018","Mso30win32client.dll",0.0104,1.0100,0.0104,1.0100 "21DD36","21DD36","Mso30win32client.dll",0.0104,1.0087,0.0104,1.0087 "A961","A961","Mso30win32client.dll",0.0103,1.0084,0.0103,1.0084 "3D11A","3D11A","Mso30win32client.dll",0.0103,1.0061,0.0103,1.0061 "21DD4E","21DD4E","Mso30win32client.dll",0.0103,1.0039,0.0103,1.0039 "22294A","22294A","Mso30win32client.dll",0.0103,1.0031,0.0103,1.0031 "1D537D","1D537D","Mso30win32client.dll",0.0103,1.0030,0.0103,1.0030 "19C03","19C03","Mso30win32client.dll",0.0103,1.0023,0.0103,1.0023 "26C05","26C05","Mso30win32client.dll",0.0103,1.0015,0.0103,1.0015 "1CAE4F","1CAE4F","Mso30win32client.dll",0.0103,1.0010,0.0103,1.0010 "21DDE2","21DDE2","Mso30win32client.dll",0.0103,1.0009,0.0103,1.0009 "171B0F","171B0F","Mso30win32client.dll",0.0103,1.0007,0.0103,1.0007 "1A90E","1A90E","Mso30win32client.dll",0.0103,1.0003,0.0103,1.0003 "1A938","1A938","Mso30win32client.dll",0.0103,1.0002,0.0103,1.0002 "4B413","4B413","Mso30win32client.dll",0.0103,1.0001,0.0103,1.0001 "1D4B98","1D4B98","Mso30win32client.dll",0.0103,1.0000,0.0103,1.0000 "70ACB","70ACB","Mso30win32client.dll",0.0103,1.0000,0.0103,1.0000 "842D0","842D0","Mso30win32client.dll",0.0103,0.9996,0.0103,0.9996 "3C601","3C601","Mso30win32client.dll",0.0103,0.9992,0.0103,0.9992 "A31EA","A31EA","Mso30win32client.dll",0.0103,0.9992,0.0103,0.9992 "189AC","189AC","Mso30win32client.dll",0.0103,0.9989,0.0103,0.9989 "1A8D1","1A8D1","Mso30win32client.dll",0.0103,0.9987,0.0103,0.9987 "1D7C9A","1D7C9A","Mso30win32client.dll",0.0102,0.9983,0.0102,0.9983 "1D4E98","1D4E98","Mso30win32client.dll",0.0102,0.9973,0.0102,0.9973 "1CAE53","1CAE53","Mso30win32client.dll",0.0102,0.9971,0.0102,0.9971 "22B36E","22B36E","Mso30win32client.dll",0.0102,0.9971,0.0102,0.9971 "251D8","251D8","Mso30win32client.dll",0.0102,0.9968,0.0102,0.9968 "18A93","18A93","Mso30win32client.dll",0.0102,0.9967,0.0102,0.9967 "21DD1D","21DD1D","Mso30win32client.dll",0.0102,0.9964,0.0102,0.9964 "1D4EF7","1D4EF7","Mso30win32client.dll",0.0102,0.9963,0.0102,0.9963 "90134","90134","Mso30win32client.dll",0.0102,0.9961,0.0102,0.9961 "1AD2D9","1AD2D9","Mso30win32client.dll",0.0102,0.9956,0.0102,0.9956 "1D4F87","1D4F87","Mso30win32client.dll",0.0102,0.9956,0.0102,0.9956 "22B336","22B336","Mso30win32client.dll",0.0102,0.9956,0.0102,0.9956 "A31BD","A31BD","Mso30win32client.dll",0.0102,0.9956,0.0102,0.9956 "3677C","3677C","Mso30win32client.dll",0.0102,0.9953,0.0102,0.9953 "1CAE6A","1CAE6A","Mso30win32client.dll",0.0102,0.9951,0.0102,0.9951 "1D4ED5","1D4ED5","Mso30win32client.dll",0.0102,0.9951,0.0102,0.9951 "F4B5A","F4B5A","Mso30win32client.dll",0.0102,0.9951,0.0102,0.9951 "18DEE","18DEE","Mso30win32client.dll",0.0102,0.9949,0.0102,0.9949 "F5389","F5389","Mso30win32client.dll",0.0102,0.9948,0.0102,0.9948 "1D66B0","1D66B0","Mso30win32client.dll",0.0102,0.9936,0.0102,0.9936 "3FF9D0","3FF9D0","Mso30win32client.dll",0.0102,0.9936,0.0102,0.9936 "1D4F30","1D4F30","Mso30win32client.dll",0.0102,0.9934,0.0102,0.9934 "19564","19564","Mso30win32client.dll",0.0102,0.9933,0.0102,0.9933 "1B024","1B024","Mso30win32client.dll",0.0102,0.9930,0.0102,0.9930 "1E859","1E859","Mso30win32client.dll",0.0102,0.9927,0.0102,0.9927 "18E10","18E10","Mso30win32client.dll",0.0102,0.9925,0.0102,0.9925 "7255B","7255B","Mso30win32client.dll",0.0102,0.9915,0.0102,0.9915 "1CAE68","1CAE68","Mso30win32client.dll",0.0102,0.9907,0.0102,0.9907 "74180","74180","Mso30win32client.dll",0.0102,0.9893,0.0102,0.9893 "1CF5E0","1CF5E0","Mso30win32client.dll",0.0101,0.9845,0.0101,0.9845 "17C985","17C985","Mso30win32client.dll",0.0101,0.9814,0.0101,0.9814 "22B35F","22B35F","Mso30win32client.dll",0.0101,0.9802,0.0101,0.9802 "E6F40","E6F40","Mso30win32client.dll",0.0101,0.9801,0.0101,0.9801 "21DDBF","21DDBF","Mso30win32client.dll",0.0101,0.9795,0.0101,0.9795 "8DD3C","8DD3C","Mso30win32client.dll",0.0101,0.9795,0.0101,0.9795 "3EFEF","3EFEF","Mso30win32client.dll",0.0100,0.9767,0.0100,0.9767 "3D81B0","3D81B0","Mso30win32client.dll",0.0100,0.9759,0.0100,0.9759 "1899B","1899B","Mso30win32client.dll",0.0099,0.9691,0.0099,0.9691 "1D6862","1D6862","Mso30win32client.dll",0.0098,0.9591,0.0098,0.9591 "1D4E9F","1D4E9F","Mso30win32client.dll",0.0098,0.9578,0.0098,0.9578 "1737F0","1737F0","Mso30win32client.dll",0.0095,0.9264,0.0095,0.9264 "37568","37568","Mso30win32client.dll",0.0092,0.8939,0.0092,0.8939 "37F68","37F68","Mso30win32client.dll",0.0086,0.8390,0.0998,9.7223 "1D7A00","1D7A00","Mso30win32client.dll",0.0085,0.8306,0.0085,0.8306 "21E5BE","21E5BE","Mso30win32client.dll",0.0075,0.7266,0.0075,0.7266 "528780","528780","Mso30win32client.dll",0.0068,0.6626,0.0068,0.6626 "1D4EEB","1D4EEB","Mso30win32client.dll",0.0065,0.6293,0.0065,0.6293 "1D4E67","1D4E67","Mso30win32client.dll",0.0060,0.5815,0.0060,0.5815 "2DBDA4","2DBDA4","Mso30win32client.dll",0.0056,0.5408,0.0056,0.5408 "18DFA","18DFA","Mso30win32client.dll",0.0047,0.4561,0.0047,0.4561 "1D4F09","1D4F09","Mso30win32client.dll",0.0047,0.4533,0.0047,0.4533 "1D4EA4","1D4EA4","Mso30win32client.dll",0.0021,0.2045,0.0021,0.2045 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Mso40UIwin32client.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "E29D5","E29D5","Mso40UIwin32client.dll",0.1230,11.9876,0.1230,11.9876 "E383B","E383B","Mso40UIwin32client.dll",0.0520,5.0628,0.0520,5.0628 "E3A0B","E3A0B","Mso40UIwin32client.dll",0.0410,3.9945,0.0730,7.1154 "50776","50776","Mso40UIwin32client.dll",0.0409,3.9862,0.0409,3.9862 "E3C1C","E3C1C","Mso40UIwin32client.dll",0.0405,3.9459,0.0405,3.9459 "E1EED","E1EED","Mso40UIwin32client.dll",0.0343,3.3378,0.0343,3.3378 "D460F","D460F","Mso40UIwin32client.dll",0.0337,3.2788,0.0337,3.2788 "6F785","6F785","Mso40UIwin32client.dll",0.0329,3.2042,0.0329,3.2042 "255B6","255B6","Mso40UIwin32client.dll",0.0311,3.0344,0.0311,3.0344 "AA93","AA93","Mso40UIwin32client.dll",0.0309,3.0112,0.0309,3.0112 "E3854","E3854","Mso40UIwin32client.dll",0.0308,3.0055,0.0308,3.0055 "AFA21","AFA21","Mso40UIwin32client.dll",0.0308,3.0046,0.0308,3.0046 "D4199","D4199","Mso40UIwin32client.dll",0.0308,2.9997,0.0308,2.9997 "E3848","E3848","Mso40UIwin32client.dll",0.0308,2.9971,0.0308,2.9971 "CF513","CF513","Mso40UIwin32client.dll",0.0308,2.9961,0.0308,2.9961 "5077C","5077C","Mso40UIwin32client.dll",0.0285,2.7781,0.0798,7.7726 "14383D","14383D","Mso40UIwin32client.dll",0.0282,2.7429,0.0282,2.7429 "E38F3","E38F3","Mso40UIwin32client.dll",0.0275,2.6773,0.0469,4.5660 "D4284","D4284","Mso40UIwin32client.dll",0.0272,2.6534,0.0272,2.6534 "14386C","14386C","Mso40UIwin32client.dll",0.0253,2.4667,0.0253,2.4667 "E3819","E3819","Mso40UIwin32client.dll",0.0247,2.4024,0.0247,2.4024 "D45C1","D45C1","Mso40UIwin32client.dll",0.0213,2.0791,0.0213,2.0791 "F1013","F1013","Mso40UIwin32client.dll",0.0213,2.0706,0.0213,2.0706 "D415C","D415C","Mso40UIwin32client.dll",0.0209,2.0350,0.0209,2.0350 "E2A35","E2A35","Mso40UIwin32client.dll",0.0208,2.0248,0.0208,2.0248 "166144","166144","Mso40UIwin32client.dll",0.0207,2.0134,0.0207,2.0134 "DF6A8","DF6A8","Mso40UIwin32client.dll",0.0206,2.0085,0.0206,2.0085 "18FD9A","18FD9A","Mso40UIwin32client.dll",0.0206,2.0070,0.0206,2.0070 "D4190","D4190","Mso40UIwin32client.dll",0.0206,2.0037,0.0206,2.0037 "BB119","BB119","Mso40UIwin32client.dll",0.0205,2.0021,0.0205,2.0021 "11E0FA","11E0FA","Mso40UIwin32client.dll",0.0205,2.0017,0.0205,2.0017 "E29D7","E29D7","Mso40UIwin32client.dll",0.0205,2.0014,0.0205,2.0014 "E2D75","E2D75","Mso40UIwin32client.dll",0.0205,2.0003,0.0205,2.0003 "123BA","123BA","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "126C16","126C16","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "14154","14154","Mso40UIwin32client.dll",0.0205,2.0000,0.0322,3.1381 "150583","150583","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "210D53","210D53","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "215A7","215A7","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "3DDA26","3DDA26","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "58A78","58A78","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "66147","66147","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "818D8","818D8","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "B687C","B687C","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "DD67B","DD67B","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "E2D6C","E2D6C","Mso40UIwin32client.dll",0.0205,2.0000,0.0205,2.0000 "E383D","E383D","Mso40UIwin32client.dll",0.0205,1.9994,0.0205,1.9994 "11E0D6","11E0D6","Mso40UIwin32client.dll",0.0205,1.9974,0.0205,1.9974 "E39B6","E39B6","Mso40UIwin32client.dll",0.0205,1.9974,0.0205,1.9974 "E34FF","E34FF","Mso40UIwin32client.dll",0.0205,1.9968,0.0205,1.9968 "E29E0","E29E0","Mso40UIwin32client.dll",0.0205,1.9949,0.0205,1.9949 "D4206","D4206","Mso40UIwin32client.dll",0.0205,1.9932,0.0205,1.9932 "D41A6","D41A6","Mso40UIwin32client.dll",0.0204,1.9896,0.0204,1.9896 "124885","124885","Mso40UIwin32client.dll",0.0196,1.9094,0.0196,1.9094 "E530F","E530F","Mso40UIwin32client.dll",0.0194,1.8861,0.0194,1.8861 "D4505","D4505","Mso40UIwin32client.dll",0.0193,1.8790,0.0193,1.8790 "95B12","95B12","Mso40UIwin32client.dll",0.0185,1.8010,0.0185,1.8010 "11BEA0","11BEA0","Mso40UIwin32client.dll",0.0165,1.6035,0.0165,1.6035 "E58B7","E58B7","Mso40UIwin32client.dll",0.0164,1.5975,0.0164,1.5975 "E2160","E2160","Mso40UIwin32client.dll",0.0160,1.5606,0.0160,1.5606 "1402D6","1402D6","Mso40UIwin32client.dll",0.0159,1.5474,0.0159,1.5474 "16A4F5","16A4F5","Mso40UIwin32client.dll",0.0155,1.5118,0.0155,1.5118 "E383F","E383F","Mso40UIwin32client.dll",0.0155,1.5097,0.0155,1.5097 "2220B","2220B","Mso40UIwin32client.dll",0.0154,1.5012,0.0154,1.5012 "54B14","54B14","Mso40UIwin32client.dll",0.0147,1.4369,0.0147,1.4369 "159335","159335","Mso40UIwin32client.dll",0.0144,1.4032,0.0144,1.4032 "E1ED6","E1ED6","Mso40UIwin32client.dll",0.0143,1.3894,0.0143,1.3894 "E3791","E3791","Mso40UIwin32client.dll",0.0132,1.2882,0.0132,1.2882 "E7564","E7564","Mso40UIwin32client.dll",0.0129,1.2574,0.0129,1.2574 "E1EE6","E1EE6","Mso40UIwin32client.dll",0.0126,1.2252,0.0126,1.2252 "D4279","D4279","Mso40UIwin32client.dll",0.0126,1.2251,0.0126,1.2251 "62F26","62F26","Mso40UIwin32client.dll",0.0122,1.1849,0.0122,1.1849 "14385B","14385B","Mso40UIwin32client.dll",0.0120,1.1649,2.9233,284.8250 "143834","143834","Mso40UIwin32client.dll",0.0114,1.1154,0.0114,1.1154 "4FD61","4FD61","Mso40UIwin32client.dll",0.0111,1.0807,0.0111,1.0807 "E19E3","E19E3","Mso40UIwin32client.dll",0.0108,1.0533,0.0108,1.0533 "FE709","FE709","Mso40UIwin32client.dll",0.0106,1.0353,0.0106,1.0353 "255C8","255C8","Mso40UIwin32client.dll",0.0106,1.0314,0.0106,1.0314 "53B4D","53B4D","Mso40UIwin32client.dll",0.0104,1.0172,0.0104,1.0172 "DF063","DF063","Mso40UIwin32client.dll",0.0104,1.0132,0.0104,1.0132 "810B9","810B9","Mso40UIwin32client.dll",0.0103,1.0075,0.0103,1.0075 "45120","45120","Mso40UIwin32client.dll",0.0103,1.0073,0.0103,1.0073 "113141","113141","Mso40UIwin32client.dll",0.0103,1.0072,0.0103,1.0072 "1A9006","1A9006","Mso40UIwin32client.dll",0.0103,1.0057,0.0103,1.0057 "D421C","D421C","Mso40UIwin32client.dll",0.0103,1.0053,0.0103,1.0053 "E448E","E448E","Mso40UIwin32client.dll",0.0103,1.0052,0.0103,1.0052 "FE73F","FE73F","Mso40UIwin32client.dll",0.0103,1.0051,0.4294,41.8400 "E2D5F","E2D5F","Mso40UIwin32client.dll",0.0103,1.0044,0.0103,1.0044 "6613D","6613D","Mso40UIwin32client.dll",0.0103,1.0043,0.0103,1.0043 "E64B0","E64B0","Mso40UIwin32client.dll",0.0103,1.0040,0.0103,1.0040 "E6AEB","E6AEB","Mso40UIwin32client.dll",0.0103,1.0039,0.0103,1.0039 "1B7286","1B7286","Mso40UIwin32client.dll",0.0103,1.0037,0.0103,1.0037 "D68A7","D68A7","Mso40UIwin32client.dll",0.0103,1.0035,0.0103,1.0035 "12757A","12757A","Mso40UIwin32client.dll",0.0103,1.0034,0.0103,1.0034 "E3909","E3909","Mso40UIwin32client.dll",0.0103,1.0033,0.0206,2.0027 "4B6A4","4B6A4","Mso40UIwin32client.dll",0.0103,1.0031,0.0103,1.0031 "D41FA","D41FA","Mso40UIwin32client.dll",0.0103,1.0029,0.0103,1.0029 "64E37","64E37","Mso40UIwin32client.dll",0.0103,1.0028,0.0103,1.0028 "E38E3","E38E3","Mso40UIwin32client.dll",0.0103,1.0028,0.0103,1.0028 "255F8","255F8","Mso40UIwin32client.dll",0.0103,1.0027,0.0103,1.0027 "E1EE0","E1EE0","Mso40UIwin32client.dll",0.0103,1.0024,0.0103,1.0024 "62C5F","62C5F","Mso40UIwin32client.dll",0.0103,1.0023,0.0103,1.0023 "D9F9E","D9F9E","Mso40UIwin32client.dll",0.0103,1.0021,0.0103,1.0021 "7B641","7B641","Mso40UIwin32client.dll",0.0103,1.0020,0.0103,1.0020 "E3B5A","E3B5A","Mso40UIwin32client.dll",0.0103,1.0020,0.0103,1.0020 "E37EE","E37EE","Mso40UIwin32client.dll",0.0103,1.0019,0.0103,1.0019 "255B3","255B3","Mso40UIwin32client.dll",0.0103,1.0018,0.0103,1.0018 "50300","50300","Mso40UIwin32client.dll",0.0103,1.0018,0.0103,1.0018 "E219C","E219C","Mso40UIwin32client.dll",0.0103,1.0017,0.0103,1.0017 "E21D7","E21D7","Mso40UIwin32client.dll",0.0103,1.0017,0.0103,1.0017 "E2CEA","E2CEA","Mso40UIwin32client.dll",0.0103,1.0016,0.0103,1.0016 "18B387","18B387","Mso40UIwin32client.dll",0.0103,1.0012,0.0103,1.0012 "1437E0","1437E0","Mso40UIwin32client.dll",0.0103,1.0010,0.0103,1.0010 "E1402","E1402","Mso40UIwin32client.dll",0.0103,1.0010,0.0103,1.0010 "E2192","E2192","Mso40UIwin32client.dll",0.0103,1.0010,0.0103,1.0010 "E2D4F","E2D4F","Mso40UIwin32client.dll",0.0103,1.0010,0.0103,1.0010 "11E0F5","11E0F5","Mso40UIwin32client.dll",0.0103,1.0007,0.0103,1.0007 "E2903","E2903","Mso40UIwin32client.dll",0.0103,1.0007,0.0103,1.0007 "E3770","E3770","Mso40UIwin32client.dll",0.0103,1.0007,0.0103,1.0007 "17AD61","17AD61","Mso40UIwin32client.dll",0.0103,1.0005,0.0103,1.0005 "51A13","51A13","Mso40UIwin32client.dll",0.0103,1.0005,0.0103,1.0005 "E2165","E2165","Mso40UIwin32client.dll",0.0103,1.0005,0.0103,1.0005 "3769BE","3769BE","Mso40UIwin32client.dll",0.0103,1.0004,0.0103,1.0004 "E3877","E3877","Mso40UIwin32client.dll",0.0103,1.0004,0.0103,1.0004 "157341","157341","Mso40UIwin32client.dll",0.0103,1.0003,0.0103,1.0003 "506F5","506F5","Mso40UIwin32client.dll",0.0103,1.0002,0.0103,1.0002 "E12F7","E12F7","Mso40UIwin32client.dll",0.0103,1.0002,0.0103,1.0002 "E2D59","E2D59","Mso40UIwin32client.dll",0.0103,1.0002,0.0103,1.0002 "E393B","E393B","Mso40UIwin32client.dll",0.0103,1.0002,0.0103,1.0002 "E290B","E290B","Mso40UIwin32client.dll",0.0103,1.0001,0.0103,1.0001 "10E9DC","10E9DC","Mso40UIwin32client.dll",0.0103,1.0000,0.0103,1.0000 "15726D","15726D","Mso40UIwin32client.dll",0.0103,1.0000,0.0103,1.0000 "502E1","502E1","Mso40UIwin32client.dll",0.0103,1.0000,0.0103,1.0000 "79443","79443","Mso40UIwin32client.dll",0.0103,1.0000,0.0103,1.0000 "E3A18","E3A18","Mso40UIwin32client.dll",0.0103,1.0000,0.0103,1.0000 "DF4A0","DF4A0","Mso40UIwin32client.dll",0.0103,0.9998,0.0103,0.9998 "E39DA","E39DA","Mso40UIwin32client.dll",0.0103,0.9998,0.0103,0.9998 "15517D","15517D","Mso40UIwin32client.dll",0.0103,0.9997,0.0103,0.9997 "BA459","BA459","Mso40UIwin32client.dll",0.0103,0.9997,0.0103,0.9997 "BA75C","BA75C","Mso40UIwin32client.dll",0.0103,0.9997,0.0103,0.9997 "1431FB","1431FB","Mso40UIwin32client.dll",0.0103,0.9996,0.0103,0.9996 "CD360","CD360","Mso40UIwin32client.dll",0.0103,0.9996,0.0103,0.9996 "E38F9","E38F9","Mso40UIwin32client.dll",0.0103,0.9996,0.0103,0.9996 "BA464","BA464","Mso40UIwin32client.dll",0.0103,0.9995,0.0103,0.9995 "17672D","17672D","Mso40UIwin32client.dll",0.0103,0.9994,0.0103,0.9994 "E56F0","E56F0","Mso40UIwin32client.dll",0.0103,0.9994,0.0103,0.9994 "E3874","E3874","Mso40UIwin32client.dll",0.0103,0.9993,0.3262,31.7793 "E391F","E391F","Mso40UIwin32client.dll",0.0103,0.9992,0.0103,0.9992 "D876E","D876E","Mso40UIwin32client.dll",0.0103,0.9991,2.0629,200.9925 "E3C2A","E3C2A","Mso40UIwin32client.dll",0.0102,0.9985,0.0102,0.9985 "D4287","D4287","Mso40UIwin32client.dll",0.0102,0.9984,0.0102,0.9984 "E2CBD","E2CBD","Mso40UIwin32client.dll",0.0102,0.9984,0.0102,0.9984 "10A058","10A058","Mso40UIwin32client.dll",0.0102,0.9981,0.0102,0.9981 "23920","23920","Mso40UIwin32client.dll",0.0102,0.9981,0.0102,0.9981 "6F7E4","6F7E4","Mso40UIwin32client.dll",0.0102,0.9981,0.0102,0.9981 "255D5","255D5","Mso40UIwin32client.dll",0.0102,0.9979,0.0102,0.9979 "D423C","D423C","Mso40UIwin32client.dll",0.0102,0.9979,0.0102,0.9979 "1572EB","1572EB","Mso40UIwin32client.dll",0.0102,0.9978,0.0102,0.9978 "2394C","2394C","Mso40UIwin32client.dll",0.0102,0.9978,0.0102,0.9978 "E0BB1","E0BB1","Mso40UIwin32client.dll",0.0102,0.9977,0.0102,0.9977 "10AFFA","10AFFA","Mso40UIwin32client.dll",0.0102,0.9974,0.0102,0.9974 "147F08","147F08","Mso40UIwin32client.dll",0.0102,0.9974,0.0102,0.9974 "E3522","E3522","Mso40UIwin32client.dll",0.0102,0.9974,0.0102,0.9974 "E1A36","E1A36","Mso40UIwin32client.dll",0.0102,0.9973,0.0102,0.9973 "661B4","661B4","Mso40UIwin32client.dll",0.0102,0.9972,0.0102,0.9972 "E12F4","E12F4","Mso40UIwin32client.dll",0.0102,0.9971,0.0102,0.9971 "D8280","D8280","Mso40UIwin32client.dll",0.0102,0.9968,0.0102,0.9968 "E3278","E3278","Mso40UIwin32client.dll",0.0102,0.9967,0.0205,1.9974 "126D32","126D32","Mso40UIwin32client.dll",0.0102,0.9963,0.0102,0.9963 "231EA","231EA","Mso40UIwin32client.dll",0.0102,0.9963,0.0102,0.9963 "E8D5B","E8D5B","Mso40UIwin32client.dll",0.0102,0.9963,0.0102,0.9963 "E043F","E043F","Mso40UIwin32client.dll",0.0102,0.9958,0.0102,0.9958 "E3832","E3832","Mso40UIwin32client.dll",0.0102,0.9956,0.0102,0.9956 "11E0E3","11E0E3","Mso40UIwin32client.dll",0.0102,0.9954,0.0102,0.9954 "E39F3","E39F3","Mso40UIwin32client.dll",0.0102,0.9953,0.0205,1.9992 "11640A","11640A","Mso40UIwin32client.dll",0.0102,0.9951,0.0102,0.9951 "E19F5","E19F5","Mso40UIwin32client.dll",0.0102,0.9951,0.0102,0.9951 "E290F","E290F","Mso40UIwin32client.dll",0.0102,0.9944,0.0102,0.9944 "6F9EA","6F9EA","Mso40UIwin32client.dll",0.0102,0.9943,0.0102,0.9943 "E29F3","E29F3","Mso40UIwin32client.dll",0.0102,0.9943,0.0102,0.9943 "52A3C","52A3C","Mso40UIwin32client.dll",0.0102,0.9938,0.0102,0.9938 "BA475","BA475","Mso40UIwin32client.dll",0.0102,0.9938,0.0102,0.9938 "8102D","8102D","Mso40UIwin32client.dll",0.0102,0.9937,0.0102,0.9937 "72EE1","72EE1","Mso40UIwin32client.dll",0.0102,0.9935,0.0102,0.9935 "E38ED","E38ED","Mso40UIwin32client.dll",0.0102,0.9933,0.0102,0.9933 "E36DB","E36DB","Mso40UIwin32client.dll",0.0102,0.9927,0.0102,0.9927 "D5836","D5836","Mso40UIwin32client.dll",0.0102,0.9921,0.0102,0.9921 "177618","177618","Mso40UIwin32client.dll",0.0102,0.9909,0.0102,0.9909 "E21EB","E21EB","Mso40UIwin32client.dll",0.0102,0.9902,0.0102,0.9902 "48C7C","48C7C","Mso40UIwin32client.dll",0.0102,0.9895,0.0102,0.9895 "126325","126325","Mso40UIwin32client.dll",0.0101,0.9875,0.0101,0.9875 "DEFB5","DEFB5","Mso40UIwin32client.dll",0.0101,0.9870,0.0101,0.9870 "B9A76","B9A76","Mso40UIwin32client.dll",0.0101,0.9861,0.0101,0.9861 "64E3C","64E3C","Mso40UIwin32client.dll",0.0101,0.9857,0.5214,50.8008 "111359","111359","Mso40UIwin32client.dll",0.0101,0.9851,0.0101,0.9851 "143196","143196","Mso40UIwin32client.dll",0.0101,0.9845,0.0101,0.9845 "190A20","190A20","Mso40UIwin32client.dll",0.0101,0.9840,0.0101,0.9840 "EBB2D","EBB2D","Mso40UIwin32client.dll",0.0101,0.9814,0.0101,0.9814 "4E3D7","4E3D7","Mso40UIwin32client.dll",0.0100,0.9763,0.0100,0.9763 "E29E4","E29E4","Mso40UIwin32client.dll",0.0100,0.9701,0.0100,0.9701 "164477","164477","Mso40UIwin32client.dll",0.0100,0.9699,0.0100,0.9699 "E3C1F","E3C1F","Mso40UIwin32client.dll",0.0100,0.9699,0.0100,0.9699 "149645","149645","Mso40UIwin32client.dll",0.0099,0.9656,0.0099,0.9656 "111312","111312","Mso40UIwin32client.dll",0.0099,0.9621,0.0099,0.9621 "10B32D","10B32D","Mso40UIwin32client.dll",0.0098,0.9536,0.0098,0.9536 "E530B","E530B","Mso40UIwin32client.dll",0.0086,0.8378,0.0086,0.8378 "B5F00","B5F00","Mso40UIwin32client.dll",0.0082,0.7989,3.0060,292.8820 "66114","66114","Mso40UIwin32client.dll",0.0081,0.7870,0.0081,0.7870 "158F9A","158F9A","Mso40UIwin32client.dll",0.0074,0.7235,0.0074,0.7235 "2697E","2697E","Mso40UIwin32client.dll",0.0071,0.6937,0.0071,0.6937 "14C06","14C06","Mso40UIwin32client.dll",0.0071,0.6901,0.0071,0.6901 "50676","50676","Mso40UIwin32client.dll",0.0069,0.6750,0.0069,0.6750 "1A91B5","1A91B5","Mso40UIwin32client.dll",0.0065,0.6368,0.0065,0.6368 "B0F1B","B0F1B","Mso40UIwin32client.dll",0.0065,0.6305,0.0065,0.6305 "B8FC4","B8FC4","Mso40UIwin32client.dll",0.0061,0.5926,0.0061,0.5926 "E108B","E108B","Mso40UIwin32client.dll",0.0059,0.5724,0.0059,0.5724 "CA44","CA44","Mso40UIwin32client.dll",0.0058,0.5699,0.0161,1.5729 "1130BF","1130BF","Mso40UIwin32client.dll",0.0057,0.5523,0.0161,1.5649 "32960","32960","Mso40UIwin32client.dll",0.0044,0.4331,0.0044,0.4331 "B6918","B6918","Mso40UIwin32client.dll",0.0031,0.3026,0.0031,0.3026 "E34F5","E34F5","Mso40UIwin32client.dll",0.0014,0.1381,0.0014,0.1381 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Mso50win32client.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "18180","18180","Mso50win32client.dll",0.0103,1.0017,0.0103,1.0017 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Mso98win32client.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "125ED0","125ED0","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "439E41","439E41","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "598730","598730","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "7F9E7","7F9E7","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "91FF2","91FF2","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "D1928","D1928","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "F076C","F076C","Mso98win32client.dll",0.0205,2.0000,0.0205,2.0000 "197600","197600","Mso98win32client.dll",0.0164,1.5946,0.0164,1.5946 "D010E","D010E","Mso98win32client.dll",0.0133,1.3004,0.0133,1.3004 "132448","132448","Mso98win32client.dll",0.0105,1.0223,0.0105,1.0223 "187160","187160","Mso98win32client.dll",0.0104,1.0124,0.0104,1.0124 "D0582","D0582","Mso98win32client.dll",0.0104,1.0087,0.0104,1.0087 "4D75A0","4D75A0","Mso98win32client.dll",0.0103,1.0035,0.0103,1.0035 "59D92","59D92","Mso98win32client.dll",0.0103,1.0011,0.0103,1.0011 "E7BCD","E7BCD","Mso98win32client.dll",0.0103,1.0008,0.0103,1.0008 "93D37","93D37","Mso98win32client.dll",0.0103,0.9992,0.0103,0.9992 "ED032","ED032","Mso98win32client.dll",0.0102,0.9984,0.0102,0.9984 "CFD25","CFD25","Mso98win32client.dll",0.0101,0.9878,0.0101,0.9878 "F5970","F5970","Mso98win32client.dll",0.0101,0.9869,0.0101,0.9869 "D5019","D5019","Mso98win32client.dll",0.0101,0.9868,0.0101,0.9868 "3570BC","3570BC","Mso98win32client.dll",0.0101,0.9823,0.0101,0.9823 "3088AC","3088AC","Mso98win32client.dll",0.0097,0.9472,0.0097,0.9472 "74800","74800","Mso98win32client.dll",0.0096,0.9331,0.0096,0.9331 "1000AD","1000AD","Mso98win32client.dll",0.0072,0.7001,0.0072,0.7001 "D004D","D004D","Mso98win32client.dll",0.0042,0.4088,0.0042,0.4088 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_NETIO.SYS_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "3D3E4","3D3E4","NETIO.SYS",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Ntfs.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1FE78E","1FE78E","Ntfs.sys",0.0211,2.0539,0.0211,2.0539 "1B2672","1B2672","Ntfs.sys",0.0205,2.0000,0.0205,2.0000 "138F09","138F09","Ntfs.sys",0.0197,1.9175,0.0197,1.9175 "167EE4","167EE4","Ntfs.sys",0.0166,1.6162,0.0166,1.6162 "16BBEE","16BBEE","Ntfs.sys",0.0144,1.4078,0.0144,1.4078 "601D","601D","Ntfs.sys",0.0141,1.3760,0.0141,1.3760 "14F79C","14F79C","Ntfs.sys",0.0125,1.2137,0.0125,1.2137 "12BFB7","12BFB7","Ntfs.sys",0.0114,1.1072,0.0114,1.1072 "1FC8FF","1FC8FF","Ntfs.sys",0.0106,1.0337,0.0106,1.0337 "203C60","203C60","Ntfs.sys",0.0104,1.0169,0.0104,1.0169 "1CE04D","1CE04D","Ntfs.sys",0.0102,0.9953,0.0102,0.9953 "15070B","15070B","Ntfs.sys",0.0102,0.9921,0.0102,0.9921 "12C088","12C088","Ntfs.sys",0.0101,0.9873,0.0101,0.9873 "150326","150326","Ntfs.sys",0.0091,0.8862,0.0091,0.8862 "156B5","156B5","Ntfs.sys",0.0074,0.7173,0.0074,0.7173 "18CD0E","18CD0E","Ntfs.sys",0.0069,0.6705,0.0069,0.6705 "1B26BF","1B26BF","Ntfs.sys",0.0025,0.2411,0.0025,0.2411 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_OART.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "12CA4","12CA4","OART.DLL",0.0103,1.0012,0.0103,1.0012 "33B21","33B21","OART.DLL",0.0077,0.7543,0.0077,0.7543 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_OLMAPI32.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "CFBE0","CFBE0","OLMAPI32.DLL",0.0205,2.0000,0.0205,2.0000 "295FF","295FF","OLMAPI32.DLL",0.0127,1.2337,0.0127,1.2337 "1845D7","1845D7","OLMAPI32.DLL",0.0114,1.1060,0.0114,1.1060 "B7C80","B7C80","OLMAPI32.DLL",0.0103,1.0075,0.0103,1.0075 "42410","42410","OLMAPI32.DLL",0.0103,1.0074,0.0103,1.0074 "108ACF","108ACF","OLMAPI32.DLL",0.0103,1.0025,0.0103,1.0025 "AF254","AF254","OLMAPI32.DLL",0.0102,0.9973,0.0102,0.9973 "966C7","966C7","OLMAPI32.DLL",0.0102,0.9958,0.0102,0.9958 "78730","78730","OLMAPI32.DLL",0.0102,0.9930,0.0102,0.9930 "8DCF5","8DCF5","OLMAPI32.DLL",0.0096,0.9358,0.0096,0.9358 "F13C4","F13C4","OLMAPI32.DLL",0.0095,0.9233,0.0095,0.9233 "1396E0","1396E0","OLMAPI32.DLL",0.0042,0.4115,0.0042,0.4115 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_OneCoreUAPCommonProxyStub.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "46E2","46E2","OneCoreUAPCommonProxyStub.dll",0.0207,2.0136,0.0207,2.0136 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_PPCORE.DLL_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "3DB834","3DB834","PPCORE.DLL",0.0313,3.0493,0.0313,3.0493 "1EE5F2","1EE5F2","PPCORE.DLL",0.0205,2.0000,0.0205,2.0000 "387625","387625","PPCORE.DLL",0.0205,2.0000,0.0205,2.0000 "445F70","445F70","PPCORE.DLL",0.0205,2.0000,0.0205,2.0000 "386D46","386D46","PPCORE.DLL",0.0183,1.7832,0.0183,1.7832 "367C55","367C55","PPCORE.DLL",0.0171,1.6656,0.0171,1.6656 "A9EB9","A9EB9","PPCORE.DLL",0.0104,1.0131,0.0104,1.0131 "E7CA","E7CA","PPCORE.DLL",0.0103,1.0027,0.0103,1.0027 "230558","230558","PPCORE.DLL",0.0103,1.0004,0.0103,1.0004 "D3A20","D3A20","PPCORE.DLL",0.0102,0.9970,0.0102,0.9970 "8BB28","8BB28","PPCORE.DLL",0.0099,0.9663,0.0099,0.9663 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_PktMon.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "85C0","85C0","PktMon.sys",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_TextShaping.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "4200","4200","TextShaping.dll",0.0374,3.6468,0.0374,3.6468 "1CB7E","1CB7E","TextShaping.dll",0.0224,2.1797,0.0224,2.1797 "10760","10760","TextShaping.dll",0.0119,1.1578,0.0119,1.1578 "41FE","41FE","TextShaping.dll",0.0110,1.0676,0.0110,1.0676 "A788","A788","TextShaping.dll",0.0103,1.0066,0.0103,1.0066 "18F1","18F1","TextShaping.dll",0.0103,1.0029,0.0103,1.0029 "8E9B","8E9B","TextShaping.dll",0.0103,1.0015,0.0103,1.0015 "1BCDF","1BCDF","TextShaping.dll",0.0103,1.0010,0.0103,1.0010 "17E1A","17E1A","TextShaping.dll",0.0103,1.0002,0.0103,1.0002 "3F5A","3F5A","TextShaping.dll",0.0103,0.9988,0.0103,0.9988 "A811","A811","TextShaping.dll",0.0102,0.9981,0.0102,0.9981 "55FB","55FB","TextShaping.dll",0.0102,0.9974,0.0102,0.9974 "277D5","277D5","TextShaping.dll",0.0101,0.9832,0.0101,0.9832 "41C0","41C0","TextShaping.dll",0.0058,0.5691,0.0058,0.5691 "25F9","25F9","TextShaping.dll",0.0023,0.2263,0.0023,0.2263 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_UIAutomationCore.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1DCD1","1DCD1","UIAutomationCore.dll",0.0205,2.0000,0.0205,2.0000 "BEFFF","BEFFF","UIAutomationCore.dll",0.0205,2.0000,0.0205,2.0000 "3ACB8","3ACB8","UIAutomationCore.dll",0.0047,0.4606,0.0047,0.4606 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_WdFilter.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "617BB","617BB","WdFilter.sys",0.0161,1.5718,0.0161,1.5718 "5C1BA","5C1BA","WdFilter.sys",0.0135,1.3168,0.0135,1.3168 "47260","47260","WdFilter.sys",0.0128,1.2434,0.0128,1.2434 "4DECF","4DECF","WdFilter.sys",0.0127,1.2386,0.0127,1.2386 "2BE7C","2BE7C","WdFilter.sys",0.0103,0.9998,0.0103,0.9998 "2B5D0","2B5D0","WdFilter.sys",0.0102,0.9974,0.0102,0.9974 "2B6B6","2B6B6","WdFilter.sys",0.0102,0.9974,0.0102,0.9974 "2BEA5","2BEA5","WdFilter.sys",0.0102,0.9974,0.0102,0.9974 "2BE88","2BE88","WdFilter.sys",0.0102,0.9945,0.0102,0.9945 "2BD9B","2BD9B","WdFilter.sys",0.0102,0.9942,0.0102,0.9942 "4BA31","4BA31","WdFilter.sys",0.0102,0.9932,0.0102,0.9932 "486FB","486FB","WdFilter.sys",0.0029,0.2806,0.0029,0.2806 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_WinTypes.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "DED0","DED0","WinTypes.dll",0.0207,2.0128,0.0207,2.0128 "26C79","26C79","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "2934","2934","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "2B48","2B48","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "38951","38951","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "39F45","39F45","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "B0A5","B0A5","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "D54C","D54C","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "D55C","D55C","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "D65C","D65C","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "DF50","DF50","WinTypes.dll",0.0205,2.0000,0.0205,2.0000 "E10D","E10D","WinTypes.dll",0.0204,1.9919,0.0204,1.9919 "1DFD0","1DFD0","WinTypes.dll",0.0155,1.5080,0.0155,1.5080 "1E110","1E110","WinTypes.dll",0.0123,1.2026,0.0123,1.2026 "14F78","14F78","WinTypes.dll",0.0103,0.9989,0.0103,0.9989 "1E124","1E124","WinTypes.dll",0.0102,0.9953,0.0102,0.9953 "1E107","1E107","WinTypes.dll",0.0102,0.9924,0.0102,0.9924 "2420","2420","WinTypes.dll",0.0102,0.9916,0.0102,0.9916 "15D54","15D54","WinTypes.dll",0.0089,0.8673,0.0089,0.8673 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Windows.Networking.Connectivity.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "58318","58318","Windows.Networking.Connectivity.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Windows.Security.Authentication.Web.Core.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "BCBE","BCBE","Windows.Security.Authentication.Web.Core.dll",0.0312,3.0407,0.0312,3.0407 "4697E","4697E","Windows.Security.Authentication.Web.Core.dll",0.0205,2.0000,0.0205,2.0000 "6AC5E","6AC5E","Windows.Security.Authentication.Web.Core.dll",0.0205,2.0000,0.0205,2.0000 "E5010","E5010","Windows.Security.Authentication.Web.Core.dll",0.0205,2.0000,0.0205,2.0000 "1B2DF","1B2DF","Windows.Security.Authentication.Web.Core.dll",0.0169,1.6437,2.4374,237.4791 "15CB5","15CB5","Windows.Security.Authentication.Web.Core.dll",0.0129,1.2522,0.0129,1.2522 "19EB0","19EB0","Windows.Security.Authentication.Web.Core.dll",0.0116,1.1320,0.0116,1.1320 "41218","41218","Windows.Security.Authentication.Web.Core.dll",0.0107,1.0453,0.0107,1.0453 "2B976","2B976","Windows.Security.Authentication.Web.Core.dll",0.0102,0.9933,0.0102,0.9933 "A1A10","A1A10","Windows.Security.Authentication.Web.Core.dll",0.0099,0.9685,0.0099,0.9685 "2BC75","2BC75","Windows.Security.Authentication.Web.Core.dll",0.0017,0.1663,0.0017,0.1663 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Windows.StateRepositoryCore.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "86DB","86DB","Windows.StateRepositoryCore.dll",0.0102,0.9952,0.0102,0.9952 "74BF","74BF","Windows.StateRepositoryCore.dll",0.0102,0.9906,0.0102,0.9906 "CED0","CED0","Windows.StateRepositoryCore.dll",0.0051,0.4997,0.0051,0.4997 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Windows.Web.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "5F98","5F98","Windows.Web.dll",0.1672,16.2860,0.1672,16.2860 "5F87","5F87","Windows.Web.dll",0.0889,8.6617,0.0889,8.6617 "5F6C","5F6C","Windows.Web.dll",0.0736,7.1683,0.0736,7.1683 "5FAE","5FAE","Windows.Web.dll",0.0614,5.9785,0.0614,5.9785 "6019","6019","Windows.Web.dll",0.0479,4.6696,0.0479,4.6696 "6025","6025","Windows.Web.dll",0.0428,4.1746,0.0428,4.1746 "6014","6014","Windows.Web.dll",0.0310,3.0243,0.0310,3.0243 "5F93","5F93","Windows.Web.dll",0.0291,2.8317,0.0291,2.8317 "10441","10441","Windows.Web.dll",0.0280,2.7285,0.0280,2.7285 "5FB9","5FB9","Windows.Web.dll",0.0274,2.6696,0.0274,2.6696 "107E0","107E0","Windows.Web.dll",0.0206,2.0066,0.0206,2.0066 "122B0","122B0","Windows.Web.dll",0.0205,2.0000,0.0205,2.0000 "5F69","5F69","Windows.Web.dll",0.0205,2.0000,0.0205,2.0000 "6BCA","6BCA","Windows.Web.dll",0.0205,2.0000,0.0205,2.0000 "E5FE","E5FE","Windows.Web.dll",0.0205,2.0000,0.0205,2.0000 "E7AD","E7AD","Windows.Web.dll",0.0205,2.0000,0.0205,2.0000 "535A","535A","Windows.Web.dll",0.0203,1.9804,0.0203,1.9804 "4B43","4B43","Windows.Web.dll",0.0202,1.9688,0.0202,1.9688 "5B010","5B010","Windows.Web.dll",0.0173,1.6875,0.0173,1.6875 "6022","6022","Windows.Web.dll",0.0172,1.6745,0.0172,1.6745 "5F77","5F77","Windows.Web.dll",0.0165,1.6064,0.0165,1.6064 "109B8","109B8","Windows.Web.dll",0.0164,1.5937,0.0164,1.5937 "6028","6028","Windows.Web.dll",0.0156,1.5180,0.0156,1.5180 "5519","5519","Windows.Web.dll",0.0156,1.5154,0.0156,1.5154 "141C0","141C0","Windows.Web.dll",0.0147,1.4297,0.0147,1.4297 "179F0","179F0","Windows.Web.dll",0.0144,1.4056,0.0144,1.4056 "52E1","52E1","Windows.Web.dll",0.0137,1.3346,0.0137,1.3346 "122BD","122BD","Windows.Web.dll",0.0133,1.2999,0.0133,1.2999 "5FA3","5FA3","Windows.Web.dll",0.0123,1.2013,0.0123,1.2013 "E657","E657","Windows.Web.dll",0.0110,1.0755,0.0110,1.0755 "1692A","1692A","Windows.Web.dll",0.0107,1.0429,0.0107,1.0429 "24B6","24B6","Windows.Web.dll",0.0104,1.0149,0.0104,1.0149 "62AD","62AD","Windows.Web.dll",0.0103,1.0023,0.0103,1.0023 "91A9","91A9","Windows.Web.dll",0.0102,0.9981,0.0102,0.9981 "E903","E903","Windows.Web.dll",0.0102,0.9976,0.0102,0.9976 "4DF5","4DF5","Windows.Web.dll",0.0102,0.9972,0.0102,0.9972 "901E","901E","Windows.Web.dll",0.0102,0.9943,0.0102,0.9943 "5820","5820","Windows.Web.dll",0.0102,0.9939,0.0102,0.9939 "8E4A","8E4A","Windows.Web.dll",0.0102,0.9903,0.0102,0.9903 "10216","10216","Windows.Web.dll",0.0089,0.8695,0.0089,0.8695 "16911","16911","Windows.Web.dll",0.0086,0.8338,0.0086,0.8338 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_WindowsCodecs.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "E3129","E3129","WindowsCodecs.dll",0.0205,2.0000,0.0205,2.0000 "30E76","30E76","WindowsCodecs.dll",0.0114,1.1112,0.0114,1.1112 "1A8AC9","1A8AC9","WindowsCodecs.dll",0.0113,1.0974,0.0113,1.0974 "30E15","30E15","WindowsCodecs.dll",0.0111,1.0831,0.0111,1.0831 "30DE4","30DE4","WindowsCodecs.dll",0.0111,1.0781,0.0111,1.0781 "1A8A71","1A8A71","WindowsCodecs.dll",0.0109,1.0656,0.0109,1.0656 "41A62","41A62","WindowsCodecs.dll",0.0109,1.0621,0.0109,1.0621 "9F3C3","9F3C3","WindowsCodecs.dll",0.0109,1.0595,0.0109,1.0595 "3129B","3129B","WindowsCodecs.dll",0.0107,1.0472,0.0107,1.0472 "311F0","311F0","WindowsCodecs.dll",0.0105,1.0190,0.0105,1.0190 "A4402","A4402","WindowsCodecs.dll",0.0103,1.0082,0.0103,1.0082 "1A8D09","1A8D09","WindowsCodecs.dll",0.0102,0.9901,0.0102,0.9901 "41B83","41B83","WindowsCodecs.dll",0.0092,0.8930,0.0092,0.8930 "30E79","30E79","WindowsCodecs.dll",0.0068,0.6646,0.0068,0.6646 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_Wldap32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "412F","412F","Wldap32.dll",0.0205,2.0000,0.0205,2.0000 "C49B","C49B","Wldap32.dll",0.0205,2.0000,0.0205,2.0000 "1838D","1838D","Wldap32.dll",0.0072,0.7034,0.0072,0.7034 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_ahcache.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "3DC47","3DC47","ahcache.sys",0.0103,1.0001,0.0103,1.0001 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_aitrx.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "4937F","4937F","aitrx.dll",0.0205,2.0000,0.0205,2.0000 "B4413","B4413","aitrx.dll",0.0205,2.0000,0.0205,2.0000 "B42CF","B42CF","aitrx.dll",0.0175,1.7096,0.0175,1.7096 "B3B6C","B3B6C","aitrx.dll",0.0109,1.0594,0.0109,1.0594 "B3EF6","B3EF6","aitrx.dll",0.0103,1.0055,0.0103,1.0055 "21100","21100","aitrx.dll",0.0103,1.0009,0.0103,1.0009 "B2D01","B2D01","aitrx.dll",0.0102,0.9979,0.0102,0.9979 "B42CA","B42CA","aitrx.dll",0.0102,0.9939,0.0102,0.9939 "B35B4","B35B4","aitrx.dll",0.0102,0.9931,0.0102,0.9931 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_bcrypt.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "7520","7520","bcrypt.dll",0.0205,2.0000,0.0205,2.0000 "7DA0","7DA0","bcrypt.dll",0.0134,1.3075,0.0134,1.3075 "5530","5530","bcrypt.dll",0.0103,0.9992,0.0103,0.9992 "80F8","80F8","bcrypt.dll",0.0102,0.9978,0.0102,0.9978 "2586","2586","bcrypt.dll",0.0062,0.6022,0.0062,0.6022 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_bcryptprimitives.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "13B8C","13B8C","bcryptprimitives.dll",0.0306,2.9817,0.0306,2.9817 "2CA25","2CA25","bcryptprimitives.dll",0.0208,2.0267,0.0208,2.0267 "4FF7D","4FF7D","bcryptprimitives.dll",0.0207,2.0175,0.0207,2.0175 "50DAF","50DAF","bcryptprimitives.dll",0.0207,2.0162,0.0207,2.0162 "13B00","13B00","bcryptprimitives.dll",0.0205,2.0000,0.0205,2.0000 "2E4E","2E4E","bcryptprimitives.dll",0.0205,2.0000,0.0205,2.0000 "4FBC0","4FBC0","bcryptprimitives.dll",0.0205,2.0000,0.0205,2.0000 "51078","51078","bcryptprimitives.dll",0.0189,1.8412,0.0189,1.8412 "51042","51042","bcryptprimitives.dll",0.0174,1.6982,0.0174,1.6982 "13B85","13B85","bcryptprimitives.dll",0.0150,1.4567,0.0150,1.4567 "5108B","5108B","bcryptprimitives.dll",0.0121,1.1808,0.0121,1.1808 "51143","51143","bcryptprimitives.dll",0.0108,1.0537,0.0108,1.0537 "506F9","506F9","bcryptprimitives.dll",0.0103,1.0002,0.0103,1.0002 "2C730","2C730","bcryptprimitives.dll",0.0103,0.9994,0.0103,0.9994 "11B17","11B17","bcryptprimitives.dll",0.0103,0.9992,0.0103,0.9992 "2D74","2D74","bcryptprimitives.dll",0.0103,0.9990,0.0103,0.9990 "5802B","5802B","bcryptprimitives.dll",0.0102,0.9983,0.0102,0.9983 "13B0D","13B0D","bcryptprimitives.dll",0.0102,0.9968,0.0102,0.9968 "11B09","11B09","bcryptprimitives.dll",0.0102,0.9967,0.0102,0.9967 "502FA","502FA","bcryptprimitives.dll",0.0102,0.9934,0.0102,0.9934 "5867B","5867B","bcryptprimitives.dll",0.0102,0.9898,0.0102,0.9898 "51064","51064","bcryptprimitives.dll",0.0101,0.9873,0.0101,0.9873 "50BB9","50BB9","bcryptprimitives.dll",0.0101,0.9863,0.0101,0.9863 "50FD1","50FD1","bcryptprimitives.dll",0.0101,0.9801,0.0101,0.9801 "50E73","50E73","bcryptprimitives.dll",0.0100,0.9724,0.0100,0.9724 "13A50","13A50","bcryptprimitives.dll",0.0099,0.9657,0.0099,0.9657 "506AC","506AC","bcryptprimitives.dll",0.0018,0.1794,0.0018,0.1794 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_bindflt.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "610E","610E","bindflt.sys",0.0205,2.0000,0.0205,2.0000 "6141","6141","bindflt.sys",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_cng.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "DDF4","DDF4","cng.sys",0.0512,4.9909,0.0512,4.9909 "DDC1","DDC1","cng.sys",0.0411,4.0000,0.0411,4.0000 "DE88","DE88","cng.sys",0.0410,3.9955,0.0410,3.9955 "E595","E595","cng.sys",0.0308,3.0035,0.0308,3.0035 "DBE5","DBE5","cng.sys",0.0308,3.0020,0.0308,3.0020 "E3B4","E3B4","cng.sys",0.0308,2.9989,0.0308,2.9989 "E341","E341","cng.sys",0.0307,2.9939,0.0307,2.9939 "D853","D853","cng.sys",0.0307,2.9873,0.0307,2.9873 "DC5B","DC5B","cng.sys",0.0304,2.9635,0.0304,2.9635 "D997","D997","cng.sys",0.0304,2.9596,0.0304,2.9596 "F08B","F08B","cng.sys",0.0238,2.3165,0.0238,2.3165 "F4C0","F4C0","cng.sys",0.0209,2.0408,0.0209,2.0408 "D6EE","D6EE","cng.sys",0.0206,2.0033,0.0206,2.0033 "D62A","D62A","cng.sys",0.0206,2.0026,0.0206,2.0026 "DC47","DC47","cng.sys",0.0205,2.0003,0.0205,2.0003 "D789","D789","cng.sys",0.0205,2.0000,0.0205,2.0000 "D7AC","D7AC","cng.sys",0.0205,2.0000,0.0205,2.0000 "D7C0","D7C0","cng.sys",0.0205,2.0000,0.0205,2.0000 "D90B","D90B","cng.sys",0.0205,2.0000,0.0205,2.0000 "DADC","DADC","cng.sys",0.0205,2.0000,0.0205,2.0000 "DEA3","DEA3","cng.sys",0.0205,2.0000,0.0205,2.0000 "E2BF","E2BF","cng.sys",0.0205,2.0000,0.0205,2.0000 "E2D3","E2D3","cng.sys",0.0205,2.0000,0.0205,2.0000 "E4E9","E4E9","cng.sys",0.0205,2.0000,0.0205,2.0000 "E548","E548","cng.sys",0.0205,2.0000,0.0205,2.0000 "E240","E240","cng.sys",0.0205,1.9968,0.0205,1.9968 "E995","E995","cng.sys",0.0205,1.9954,0.0205,1.9954 "EA4C","EA4C","cng.sys",0.0205,1.9953,0.0205,1.9953 "E219","E219","cng.sys",0.0204,1.9923,0.0204,1.9923 "E22B","E22B","cng.sys",0.0204,1.9906,0.0204,1.9906 "E8A4","E8A4","cng.sys",0.0204,1.9877,0.0204,1.9877 "EDD5","EDD5","cng.sys",0.0204,1.9862,0.0204,1.9862 "DA66","DA66","cng.sys",0.0203,1.9820,0.0203,1.9820 "D903","D903","cng.sys",0.0201,1.9605,0.0201,1.9605 "E295","E295","cng.sys",0.0110,1.0748,0.0110,1.0748 "E133","E133","cng.sys",0.0110,1.0717,0.0110,1.0717 "E81B","E81B","cng.sys",0.0104,1.0132,0.0104,1.0132 "ED0A","ED0A","cng.sys",0.0104,1.0128,0.0104,1.0128 "EEB6","EEB6","cng.sys",0.0104,1.0125,0.0104,1.0125 "F303","F303","cng.sys",0.0104,1.0112,0.0104,1.0112 "F3E2","F3E2","cng.sys",0.0104,1.0110,0.0104,1.0110 "E6DF","E6DF","cng.sys",0.0104,1.0108,0.0104,1.0108 "F4F9","F4F9","cng.sys",0.0104,1.0105,0.0104,1.0105 "EC5F","EC5F","cng.sys",0.0103,1.0084,0.0103,1.0084 "EA36","EA36","cng.sys",0.0103,1.0083,0.0103,1.0083 "DB0A","DB0A","cng.sys",0.0103,1.0082,0.0103,1.0082 "E070","E070","cng.sys",0.0103,1.0082,0.0103,1.0082 "EFC9","EFC9","cng.sys",0.0103,1.0081,0.0103,1.0081 "EC3C","EC3C","cng.sys",0.0103,1.0077,0.0103,1.0077 "EF0E","EF0E","cng.sys",0.0103,1.0069,0.0103,1.0069 "E4CD","E4CD","cng.sys",0.0103,1.0061,0.0103,1.0061 "EEF3","EEF3","cng.sys",0.0103,1.0059,0.0103,1.0059 "D5B1","D5B1","cng.sys",0.0103,1.0056,0.0103,1.0056 "F15F","F15F","cng.sys",0.0103,1.0043,0.0103,1.0043 "F4A5","F4A5","cng.sys",0.0103,1.0041,0.0103,1.0041 "E98D","E98D","cng.sys",0.0103,1.0030,0.0103,1.0030 "DB84","DB84","cng.sys",0.0103,1.0027,0.0103,1.0027 "F80F","F80F","cng.sys",0.0103,1.0024,0.0103,1.0024 "DB52","DB52","cng.sys",0.0103,1.0023,0.0103,1.0023 "F381","F381","cng.sys",0.0103,1.0023,0.0103,1.0023 "F3E9","F3E9","cng.sys",0.0103,1.0021,0.0103,1.0021 "D990","D990","cng.sys",0.0103,1.0017,0.0103,1.0017 "F4E4","F4E4","cng.sys",0.0103,1.0014,0.0103,1.0014 "D64D","D64D","cng.sys",0.0103,1.0011,0.0103,1.0011 "F5CB","F5CB","cng.sys",0.0103,1.0010,0.0103,1.0010 "EFDC","EFDC","cng.sys",0.0103,1.0006,0.0103,1.0006 "D9B2","D9B2","cng.sys",0.0103,1.0005,0.0103,1.0005 "F17C","F17C","cng.sys",0.0103,1.0005,0.0103,1.0005 "DF6F","DF6F","cng.sys",0.0103,1.0002,0.0103,1.0002 "F650","F650","cng.sys",0.0103,1.0002,0.0103,1.0002 "E5DB","E5DB","cng.sys",0.0103,1.0000,0.0103,1.0000 "DFBA","DFBA","cng.sys",0.0103,0.9999,0.0103,0.9999 "D560","D560","cng.sys",0.0103,0.9998,0.0103,0.9998 "DD60","DD60","cng.sys",0.0103,0.9998,0.0103,0.9998 "E1FF","E1FF","cng.sys",0.0103,0.9998,0.0103,0.9998 "DA33","DA33","cng.sys",0.0103,0.9997,0.0103,0.9997 "F51C","F51C","cng.sys",0.0103,0.9994,0.0103,0.9994 "E184","E184","cng.sys",0.0103,0.9991,0.0103,0.9991 "E77F","E77F","cng.sys",0.0103,0.9991,0.0103,0.9991 "D85B","D85B","cng.sys",0.0103,0.9989,0.0103,0.9989 "E2EF","E2EF","cng.sys",0.0103,0.9987,0.0103,0.9987 "E099","E099","cng.sys",0.0102,0.9984,0.0102,0.9984 "F7DE","F7DE","cng.sys",0.0102,0.9982,0.0102,0.9982 "DA28","DA28","cng.sys",0.0102,0.9981,0.0102,0.9981 "E432","E432","cng.sys",0.0102,0.9974,0.0102,0.9974 "E57A","E57A","cng.sys",0.0102,0.9969,0.0102,0.9969 "EE8D","EE8D","cng.sys",0.0102,0.9968,0.0102,0.9968 "E44E","E44E","cng.sys",0.0102,0.9964,0.0102,0.9964 "E4A8","E4A8","cng.sys",0.0102,0.9963,0.0102,0.9963 "EDA0","EDA0","cng.sys",0.0102,0.9963,0.0102,0.9963 "F6FF","F6FF","cng.sys",0.0102,0.9962,0.0102,0.9962 "F061","F061","cng.sys",0.0102,0.9961,0.0102,0.9961 "F3EF","F3EF","cng.sys",0.0102,0.9961,0.0102,0.9961 "564DC","564DC","cng.sys",0.0102,0.9956,0.0102,0.9956 "E1D1","E1D1","cng.sys",0.0102,0.9953,0.0102,0.9953 "E573","E573","cng.sys",0.0102,0.9953,0.0102,0.9953 "E14C","E14C","cng.sys",0.0102,0.9952,0.0102,0.9952 "E814","E814","cng.sys",0.0102,0.9952,0.0102,0.9952 "E59D","E59D","cng.sys",0.0102,0.9948,0.0102,0.9948 "D79C","D79C","cng.sys",0.0102,0.9947,0.0102,0.9947 "D8DA","D8DA","cng.sys",0.0102,0.9946,0.0102,0.9946 "DF0D","DF0D","cng.sys",0.0102,0.9938,0.0102,0.9938 "E729","E729","cng.sys",0.0102,0.9938,0.0102,0.9938 "EDCD","EDCD","cng.sys",0.0102,0.9938,0.0102,0.9938 "F357","F357","cng.sys",0.0102,0.9933,0.0102,0.9933 "E66B","E66B","cng.sys",0.0102,0.9930,0.0102,0.9930 "D9AA","D9AA","cng.sys",0.0102,0.9929,0.0102,0.9929 "E7A3","E7A3","cng.sys",0.0102,0.9923,0.0102,0.9923 "E65D","E65D","cng.sys",0.0102,0.9922,0.0102,0.9922 "D7A4","D7A4","cng.sys",0.0102,0.9916,0.0102,0.9916 "EA22","EA22","cng.sys",0.0102,0.9914,0.0102,0.9914 "F101","F101","cng.sys",0.0102,0.9913,0.0102,0.9913 "E07F","E07F","cng.sys",0.0102,0.9900,0.0102,0.9900 "F56F","F56F","cng.sys",0.0102,0.9899,0.0102,0.9899 "E4D9","E4D9","cng.sys",0.0101,0.9880,0.0101,0.9880 "E463","E463","cng.sys",0.0101,0.9870,0.0101,0.9870 "E1F2","E1F2","cng.sys",0.0101,0.9861,0.0101,0.9861 "572FA","572FA","cng.sys",0.0101,0.9822,0.0101,0.9822 "D60B","D60B","cng.sys",0.0100,0.9790,0.0100,0.9790 "DC1E","DC1E","cng.sys",0.0100,0.9781,0.0100,0.9781 "E4E1","E4E1","cng.sys",0.0100,0.9758,0.0100,0.9758 "E1E3","E1E3","cng.sys",0.0100,0.9756,0.0100,0.9756 "DB41","DB41","cng.sys",0.0100,0.9738,0.0100,0.9738 "D38D","D38D","cng.sys",0.0100,0.9721,0.0100,0.9721 "F42C","F42C","cng.sys",0.0099,0.9655,0.0099,0.9655 "DFE4","DFE4","cng.sys",0.0099,0.9632,0.0099,0.9632 "D645","D645","cng.sys",0.0099,0.9603,0.0099,0.9603 "D61F","D61F","cng.sys",0.0098,0.9580,0.0098,0.9580 "D710","D710","cng.sys",0.0098,0.9571,0.0098,0.9571 "D373","D373","cng.sys",0.0097,0.9497,0.0097,0.9497 "F285","F285","cng.sys",0.0097,0.9421,0.0097,0.9421 "F617","F617","cng.sys",0.0095,0.9250,0.0095,0.9250 "E417","E417","cng.sys",0.0089,0.8646,0.0089,0.8646 "E2CB","E2CB","cng.sys",0.0088,0.8557,0.0088,0.8557 "D3D4","D3D4","cng.sys",0.0084,0.8197,0.0084,0.8197 "EFE4","EFE4","cng.sys",0.0076,0.7444,0.0076,0.7444 "DBD1","DBD1","cng.sys",0.0062,0.6080,0.0062,0.6080 "D9E3","D9E3","cng.sys",0.0059,0.5794,0.0059,0.5794 "E382","E382","cng.sys",0.0050,0.4866,0.0050,0.4866 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_combase.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "5A600","5A600","combase.dll",0.0411,4.0000,0.0411,4.0000 "80E2B","80E2B","combase.dll",0.0411,4.0000,0.0411,4.0000 "F3AAC","F3AAC","combase.dll",0.0411,4.0000,0.0616,6.0000 "FB720","FB720","combase.dll",0.0411,4.0000,0.0411,4.0000 "74F9","74F9","combase.dll",0.0348,3.3945,0.0348,3.3945 "8583B","8583B","combase.dll",0.0325,3.1649,0.0325,3.1649 "1A5C17","1A5C17","combase.dll",0.0309,3.0112,0.0309,3.0112 "1D63E7","1D63E7","combase.dll",0.0308,3.0046,0.0308,3.0046 "C57B9","C57B9","combase.dll",0.0307,2.9882,0.0307,2.9882 "F3A07","F3A07","combase.dll",0.0302,2.9453,0.0302,2.9453 "835F5","835F5","combase.dll",0.0292,2.8459,0.0292,2.8459 "F8F8C","F8F8C","combase.dll",0.0209,2.0396,0.0209,2.0396 "168FB","168FB","combase.dll",0.0208,2.0276,0.0208,2.0276 "698C0","698C0","combase.dll",0.0206,2.0093,0.0206,2.0093 "1041D0","1041D0","combase.dll",0.0205,2.0000,0.0205,2.0000 "1091D0","1091D0","combase.dll",0.0205,2.0000,0.0205,2.0000 "12D860","12D860","combase.dll",0.0205,2.0000,0.0205,2.0000 "12E80A","12E80A","combase.dll",0.0205,2.0000,0.0205,2.0000 "18573C","18573C","combase.dll",0.0205,2.0000,0.0205,2.0000 "1905C0","1905C0","combase.dll",0.0205,2.0000,0.0205,2.0000 "456B","456B","combase.dll",0.0205,2.0000,0.0205,2.0000 "4BE6F","4BE6F","combase.dll",0.0205,2.0000,0.0205,2.0000 "5CE70","5CE70","combase.dll",0.0205,2.0000,0.0205,2.0000 "7A9CC","7A9CC","combase.dll",0.0205,2.0000,0.0205,2.0000 "7FBCE","7FBCE","combase.dll",0.0205,2.0000,0.0205,2.0000 "80E40","80E40","combase.dll",0.0205,2.0000,0.0308,3.0045 "80FD","80FD","combase.dll",0.0205,2.0000,0.0205,2.0000 "83601","83601","combase.dll",0.0205,2.0000,0.0205,2.0000 "8367D","8367D","combase.dll",0.0205,2.0000,0.0205,2.0000 "8393","8393","combase.dll",0.0205,2.0000,0.0205,2.0000 "84113","84113","combase.dll",0.0205,2.0000,1.5936,155.2622 "8C60C","8C60C","combase.dll",0.0205,2.0000,0.0205,2.0000 "8C926","8C926","combase.dll",0.0205,2.0000,0.0205,2.0000 "A69BC","A69BC","combase.dll",0.0205,2.0000,0.0205,2.0000 "B383F","B383F","combase.dll",0.0205,2.0000,0.0205,2.0000 "D9080","D9080","combase.dll",0.0205,2.0000,0.0205,2.0000 "EB9F8","EB9F8","combase.dll",0.0205,2.0000,0.0205,2.0000 "FA9DA","FA9DA","combase.dll",0.0205,2.0000,0.0205,2.0000 "FFB60","FFB60","combase.dll",0.0205,2.0000,0.0205,2.0000 "ACE4","ACE4","combase.dll",0.0205,1.9986,0.0205,1.9986 "91A5","91A5","combase.dll",0.0205,1.9936,0.0205,1.9936 "5E0F1","5E0F1","combase.dll",0.0205,1.9934,0.0205,1.9934 "5A62D","5A62D","combase.dll",0.0197,1.9206,0.0197,1.9206 "EB9EC","EB9EC","combase.dll",0.0190,1.8551,0.0190,1.8551 "857FA","857FA","combase.dll",0.0188,1.8291,0.0188,1.8291 "F4090","F4090","combase.dll",0.0182,1.7703,0.0182,1.7703 "8553","8553","combase.dll",0.0176,1.7129,0.0176,1.7129 "8981","8981","combase.dll",0.0168,1.6323,0.0168,1.6323 "10A9D0","10A9D0","combase.dll",0.0162,1.5787,0.0162,1.5787 "D2128","D2128","combase.dll",0.0161,1.5727,0.0161,1.5727 "100750","100750","combase.dll",0.0154,1.5014,0.0154,1.5014 "EB9C0","EB9C0","combase.dll",0.0151,1.4697,0.0151,1.4697 "1BF22","1BF22","combase.dll",0.0146,1.4251,0.0399,3.8885 "F9184","F9184","combase.dll",0.0145,1.4095,0.0145,1.4095 "85804","85804","combase.dll",0.0145,1.4090,0.0145,1.4090 "D2124","D2124","combase.dll",0.0144,1.4019,0.0144,1.4019 "1DF7F0","1DF7F0","combase.dll",0.0143,1.3961,0.0143,1.3961 "19111","19111","combase.dll",0.0143,1.3891,0.0143,1.3891 "85DF9","85DF9","combase.dll",0.0138,1.3405,0.0138,1.3405 "16306","16306","combase.dll",0.0138,1.3397,0.0138,1.3397 "12D86A","12D86A","combase.dll",0.0133,1.2915,0.0133,1.2915 "80E25","80E25","combase.dll",0.0124,1.2076,0.0124,1.2076 "19070","19070","combase.dll",0.0117,1.1359,0.0117,1.1359 "F3A81","F3A81","combase.dll",0.0110,1.0687,0.0110,1.0687 "C576C","C576C","combase.dll",0.0109,1.0588,0.0109,1.0588 "7A9C0","7A9C0","combase.dll",0.0105,1.0201,0.0105,1.0201 "5C81F","5C81F","combase.dll",0.0104,1.0111,0.0104,1.0111 "1164A2","1164A2","combase.dll",0.0103,1.0078,0.0103,1.0078 "4CC20","4CC20","combase.dll",0.0103,1.0072,0.0103,1.0072 "6B728","6B728","combase.dll",0.0103,1.0072,0.0103,1.0072 "26124","26124","combase.dll",0.0103,1.0070,0.0103,1.0070 "18FBF9","18FBF9","combase.dll",0.0103,1.0045,0.0103,1.0045 "1D5F5C","1D5F5C","combase.dll",0.0103,1.0045,0.0103,1.0045 "87E0D","87E0D","combase.dll",0.0103,1.0030,0.0103,1.0030 "896E","896E","combase.dll",0.0103,1.0023,0.0103,1.0023 "374C0","374C0","combase.dll",0.0103,1.0018,0.0103,1.0018 "260BD","260BD","combase.dll",0.0103,1.0008,0.0103,1.0008 "11CC72","11CC72","combase.dll",0.0103,1.0005,0.0103,1.0005 "5A7AE","5A7AE","combase.dll",0.0103,0.9991,0.0103,0.9991 "9165","9165","combase.dll",0.0103,0.9989,0.0103,0.9989 "12D090","12D090","combase.dll",0.0102,0.9979,0.0102,0.9979 "8C91A","8C91A","combase.dll",0.0102,0.9974,0.0102,0.9974 "665C4","665C4","combase.dll",0.0102,0.9952,0.0204,1.9874 "17EC17","17EC17","combase.dll",0.0102,0.9947,0.0102,0.9947 "1348D9","1348D9","combase.dll",0.0102,0.9930,0.2573,25.0658 "162BF","162BF","combase.dll",0.0102,0.9927,0.0102,0.9927 "10631D","10631D","combase.dll",0.0102,0.9921,0.0102,0.9921 "130BB","130BB","combase.dll",0.0102,0.9917,0.0102,0.9917 "126350","126350","combase.dll",0.0102,0.9915,0.0102,0.9915 "86942","86942","combase.dll",0.0102,0.9915,0.0102,0.9915 "184558","184558","combase.dll",0.0102,0.9902,0.0102,0.9902 "109375","109375","combase.dll",0.0101,0.9859,0.0101,0.9859 "85787","85787","combase.dll",0.0101,0.9858,0.0101,0.9858 "1210C4","1210C4","combase.dll",0.0101,0.9848,0.0101,0.9848 "8D9C0","8D9C0","combase.dll",0.0100,0.9777,0.0100,0.9777 "86D4","86D4","combase.dll",0.0099,0.9655,0.0358,3.4905 "18FBF7","18FBF7","combase.dll",0.0097,0.9449,0.0097,0.9449 "EB9CF","EB9CF","combase.dll",0.0095,0.9210,0.0095,0.9210 "10AA0A","10AA0A","combase.dll",0.0091,0.8847,0.0091,0.8847 "D2118","D2118","combase.dll",0.0061,0.5956,0.0061,0.5956 "26D30","26D30","combase.dll",0.0049,0.4773,0.0049,0.4773 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_comctl32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "9E6F5","9E6F5","comctl32.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_cpprestsdk.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "47F22","47F22","cpprestsdk.dll",0.0102,0.9904,0.0102,0.9904 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_crypt32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "5923C","5923C","crypt32.dll",0.0218,2.1201,0.0218,2.1201 "5913B","5913B","crypt32.dll",0.0205,2.0000,0.0205,2.0000 "591F9","591F9","crypt32.dll",0.0205,2.0000,0.0205,2.0000 "11F128","11F128","crypt32.dll",0.0190,1.8500,0.0190,1.8500 "12972","12972","crypt32.dll",0.0177,1.7229,0.0177,1.7229 "76A93","76A93","crypt32.dll",0.0170,1.6530,0.0170,1.6530 "5B258","5B258","crypt32.dll",0.0145,1.4150,0.0145,1.4150 "72C61","72C61","crypt32.dll",0.0131,1.2757,0.0131,1.2757 "31617","31617","crypt32.dll",0.0126,1.2237,0.0126,1.2237 "13193","13193","crypt32.dll",0.0122,1.1929,0.0122,1.1929 "8EFD0","8EFD0","crypt32.dll",0.0103,1.0070,0.0103,1.0070 "6AFD2","6AFD2","crypt32.dll",0.0103,1.0037,0.3026,29.4840 "2D48F","2D48F","crypt32.dll",0.0103,1.0026,0.0103,1.0026 "6A127","6A127","crypt32.dll",0.0103,1.0015,0.0103,1.0015 "12F45","12F45","crypt32.dll",0.0103,1.0001,0.0103,1.0001 "12FFA","12FFA","crypt32.dll",0.0103,0.9997,0.0103,0.9997 "4D724","4D724","crypt32.dll",0.0102,0.9959,0.0102,0.9959 "A912","A912","crypt32.dll",0.0102,0.9952,0.0102,0.9952 "2D52","2D52","crypt32.dll",0.0102,0.9924,0.0102,0.9924 "D4F4","D4F4","crypt32.dll",0.0102,0.9924,0.0102,0.9924 "5BF00","5BF00","crypt32.dll",0.0102,0.9902,0.0102,0.9902 "D5EE","D5EE","crypt32.dll",0.0101,0.9863,0.0101,0.9863 "65AE9","65AE9","crypt32.dll",0.0101,0.9824,0.0101,0.9824 "12F4A","12F4A","crypt32.dll",0.0100,0.9705,0.0100,0.9705 "12F4F","12F4F","crypt32.dll",0.0099,0.9616,0.0099,0.9616 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_d2d1.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "145E24","145E24","d2d1.dll",0.0214,2.0885,0.0214,2.0885 "4B8E0","4B8E0","d2d1.dll",0.0205,2.0000,0.0205,2.0000 "14758B","14758B","d2d1.dll",0.0105,1.0185,0.0105,1.0185 "76409","76409","d2d1.dll",0.0103,1.0072,0.0103,1.0072 "15CD47","15CD47","d2d1.dll",0.0102,0.9951,0.0102,0.9951 "76863","76863","d2d1.dll",0.0102,0.9920,0.0102,0.9920 "53D0D","53D0D","d2d1.dll",0.0102,0.9894,0.0102,0.9894 "14750D","14750D","d2d1.dll",0.0101,0.9827,0.0101,0.9827 "405C8","405C8","d2d1.dll",0.0087,0.8491,0.0087,0.8491 "E4182","E4182","d2d1.dll",0.0046,0.4449,0.0046,0.4449 "2E184E","2E184E","d2d1.dll",0.0023,0.2253,0.0023,0.2253 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_d3d11.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "666AB","666AB","d3d11.dll",0.0308,3.0033,0.0308,3.0033 "5CC70","5CC70","d3d11.dll",0.0208,2.0290,0.0208,2.0290 "1730F1","1730F1","d3d11.dll",0.0205,2.0000,0.0205,2.0000 "457CF","457CF","d3d11.dll",0.0205,2.0000,0.0205,2.0000 "1886D3","1886D3","d3d11.dll",0.0108,1.0552,0.0108,1.0552 "337BF","337BF","d3d11.dll",0.0103,1.0066,0.0103,1.0066 "15AB77","15AB77","d3d11.dll",0.0101,0.9800,0.0101,0.9800 "15CA69","15CA69","d3d11.dll",0.0084,0.8137,0.0084,0.8137 "182B88","182B88","d3d11.dll",0.0029,0.2782,0.0029,0.2782 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dcomp.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "515E5","515E5","dcomp.dll",0.0300,2.9264,0.0300,2.9264 "2BA25","2BA25","dcomp.dll",0.0205,2.0000,0.0205,2.0000 "4940C","4940C","dcomp.dll",0.0205,2.0000,0.0205,2.0000 "75687","75687","dcomp.dll",0.0205,2.0000,0.0205,2.0000 "A5610","A5610","dcomp.dll",0.0205,2.0000,0.0205,2.0000 "267E0","267E0","dcomp.dll",0.0168,1.6371,0.0168,1.6371 "E7FA0","E7FA0","dcomp.dll",0.0115,1.1183,0.0115,1.1183 "54E65","54E65","dcomp.dll",0.0115,1.1167,0.0115,1.1167 "562C7","562C7","dcomp.dll",0.0102,0.9972,0.0102,0.9972 "1F2CF","1F2CF","dcomp.dll",0.0102,0.9969,0.0102,0.9969 "F1BF8","F1BF8","dcomp.dll",0.0092,0.8968,0.0092,0.8968 "490F3","490F3","dcomp.dll",0.0085,0.8248,0.0085,0.8248 "598CD","598CD","dcomp.dll",0.0083,0.8076,0.0083,0.8076 "2C255","2C255","dcomp.dll",0.0045,0.4344,0.0045,0.4344 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dhcpcsvc.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2C50","2C50","dhcpcsvc.dll",0.0102,0.9917,0.0102,0.9917 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dhcpcsvc6.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "A010","A010","dhcpcsvc6.dll",0.0114,1.1154,0.0114,1.1154 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dpapi.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "13D5","13D5","dpapi.dll",0.0824,8.0252,0.0824,8.0252 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dxgi.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "48160","48160","dxgi.dll",0.0102,0.9974,0.0102,0.9974 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dxgkrnl.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "28AEB0","28AEB0","dxgkrnl.sys",0.0104,1.0173,0.0104,1.0173 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_dxgmms2.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "23B70","23B70","dxgmms2.sys",0.0104,1.0122,0.0104,1.0122 "1C24D","1C24D","dxgmms2.sys",0.0077,0.7500,0.0077,0.7500 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_e1d.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2BE26","2BE26","e1d.sys",0.0104,1.0148,0.0104,1.0148 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_fcon.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "786A3","786A3","fcon.dll",0.0205,1.9928,0.0205,1.9928 "783CF","783CF","fcon.dll",0.0102,0.9969,0.0102,0.9969 "33195","33195","fcon.dll",0.0102,0.9953,0.0102,0.9953 "32C30","32C30","fcon.dll",0.0102,0.9945,0.0102,0.9945 "10A6C","10A6C","fcon.dll",0.0102,0.9935,0.0102,0.9935 "7BC0B","7BC0B","fcon.dll",0.0102,0.9920,0.0102,0.9920 "786D1","786D1","fcon.dll",0.0101,0.9881,0.0101,0.9881 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_fileinfo.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "15A85","15A85","fileinfo.sys",0.0165,1.6067,0.0165,1.6067 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_fvevol.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "226E8","226E8","fvevol.sys",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_gdi32full.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "24A80","24A80","gdi32full.dll",0.0196,1.9122,0.0196,1.9122 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_iertutil.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "342FD","342FD","iertutil.dll",0.0205,2.0000,0.0205,2.0000 "A615","A615","iertutil.dll",0.0205,2.0000,0.0205,2.0000 "246A9","246A9","iertutil.dll",0.0203,1.9827,0.0203,1.9827 "1DA84","1DA84","iertutil.dll",0.0149,1.4523,0.0149,1.4523 "3F16D","3F16D","iertutil.dll",0.0103,1.0035,0.0103,1.0035 "793F","793F","iertutil.dll",0.0101,0.9858,0.0101,0.9858 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_imagehlp.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2224","2224","imagehlp.dll",0.1148,11.1803,0.1148,11.1803 "2230","2230","imagehlp.dll",0.0900,8.7674,0.0900,8.7674 "222E","222E","imagehlp.dll",0.0306,2.9803,0.0306,2.9803 "2206","2206","imagehlp.dll",0.0103,1.0080,0.0103,1.0080 "220E","220E","imagehlp.dll",0.0102,0.9955,0.0102,0.9955 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_intelppm.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1292","1292","intelppm.sys",0.0104,1.0090,0.0104,1.0090 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_kernel32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "84970","84970","kernel32.dll",0.0411,4.0015,0.0411,4.0015 "7DC4","7DC4","kernel32.dll",0.0351,3.4154,0.0351,3.4154 "3B1B0","3B1B0","kernel32.dll",0.0308,2.9978,0.0308,2.9978 "1A6E0","1A6E0","kernel32.dll",0.0241,2.3454,0.0241,2.3454 "3E7E0","3E7E0","kernel32.dll",0.0216,2.1024,0.0216,2.1024 "1A5C3","1A5C3","kernel32.dll",0.0205,2.0002,0.0205,2.0002 "4EB80","4EB80","kernel32.dll",0.0205,2.0000,0.0205,2.0000 "6606","6606","kernel32.dll",0.0205,2.0000,0.0205,2.0000 "1A700","1A700","kernel32.dll",0.0205,1.9980,0.0205,1.9980 "5C1E","5C1E","kernel32.dll",0.0204,1.9913,0.0204,1.9913 "1A5E3","1A5E3","kernel32.dll",0.0110,1.0685,0.0110,1.0685 "5AFA","5AFA","kernel32.dll",0.0104,1.0154,0.0104,1.0154 "65F4","65F4","kernel32.dll",0.0103,1.0057,0.0103,1.0057 "6890","6890","kernel32.dll",0.0103,1.0012,0.0103,1.0012 "6646","6646","kernel32.dll",0.0103,1.0002,0.0103,1.0002 "2BD27","2BD27","kernel32.dll",0.0102,0.9974,0.0102,0.9974 "382C0","382C0","kernel32.dll",0.0102,0.9964,0.0102,0.9964 "79CB","79CB","kernel32.dll",0.0102,0.9948,0.0102,0.9948 "304A0","304A0","kernel32.dll",0.0102,0.9938,0.0102,0.9938 "6460","6460","kernel32.dll",0.0102,0.9918,0.0102,0.9918 "2BD40","2BD40","kernel32.dll",0.0102,0.9909,0.0102,0.9909 "5B88","5B88","kernel32.dll",0.0101,0.9884,0.0101,0.9884 "84973","84973","kernel32.dll",0.0100,0.9770,0.0100,0.9770 "5B8F","5B8F","kernel32.dll",0.0099,0.9661,0.0099,0.9661 "84980","84980","kernel32.dll",0.0084,0.8184,0.0084,0.8184 "68E7","68E7","kernel32.dll",0.0076,0.7366,0.0076,0.7366 "6650","6650","kernel32.dll",0.0058,0.5619,0.0058,0.5619 "36EA0","36EA0","kernel32.dll",0.0032,0.3086,0.0032,0.3086 "5B14","5B14","kernel32.dll",0.0025,0.2448,0.0025,0.2448 "3E800","3E800","kernel32.dll",0.0019,0.1883,0.0019,0.1883 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_ksecdd.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "259E0","259E0","ksecdd.sys",0.0123,1.1984,0.0123,1.1984 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_msasn1.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2F9E","2F9E","msasn1.dll",0.0102,0.9943,0.0102,0.9943 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_mssecflt.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "A050","A050","mssecflt.sys",0.0334,3.2541,0.0334,3.2541 "3B4E8","3B4E8","mssecflt.sys",0.0316,3.0815,0.0316,3.0815 "A05E","A05E","mssecflt.sys",0.0205,2.0000,0.0205,2.0000 "606C","606C","mssecflt.sys",0.0202,1.9704,0.0202,1.9704 "A07B","A07B","mssecflt.sys",0.0166,1.6176,0.0166,1.6176 "2442B","2442B","mssecflt.sys",0.0162,1.5814,0.0162,1.5814 "3B467","3B467","mssecflt.sys",0.0114,1.1140,0.0114,1.1140 "350BE","350BE","mssecflt.sys",0.0112,1.0959,0.0112,1.0959 "FB7E","FB7E","mssecflt.sys",0.0106,1.0295,0.0106,1.0295 "32D2E","32D2E","mssecflt.sys",0.0103,1.0079,0.0103,1.0079 "34CD5","34CD5","mssecflt.sys",0.0103,1.0016,0.0103,1.0016 "34B5C","34B5C","mssecflt.sys",0.0103,1.0014,0.0103,1.0014 "3547A","3547A","mssecflt.sys",0.0103,0.9997,0.0103,0.9997 "38001","38001","mssecflt.sys",0.0102,0.9978,0.0102,0.9978 "FB2A","FB2A","mssecflt.sys",0.0083,0.8070,0.0083,0.8070 "A054","A054","mssecflt.sys",0.0080,0.7783,0.0080,0.7783 "23F26","23F26","mssecflt.sys",0.0067,0.6499,0.0067,0.6499 "3A0F4","3A0F4","mssecflt.sys",0.0020,0.1931,0.0020,0.1931 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_msvcp140.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "12822","12822","msvcp140.dll",0.0514,5.0038,0.0514,5.0038 "3AA36","3AA36","msvcp140.dll",0.0306,2.9859,0.0306,2.9859 "117BD","117BD","msvcp140.dll",0.0205,2.0000,0.0205,2.0000 "14742","14742","msvcp140.dll",0.0205,1.9991,0.0205,1.9991 "6554","6554","msvcp140.dll",0.0127,1.2372,0.0127,1.2372 "AC40","AC40","msvcp140.dll",0.0103,1.0024,0.0103,1.0024 "127F5","127F5","msvcp140.dll",0.0103,1.0022,0.0103,1.0022 "2D5AA","2D5AA","msvcp140.dll",0.0103,1.0017,0.0103,1.0017 "45CB5","45CB5","msvcp140.dll",0.0103,1.0017,0.0103,1.0017 "15251","15251","msvcp140.dll",0.0103,1.0010,0.0103,1.0010 "12724","12724","msvcp140.dll",0.0103,1.0006,0.0103,1.0006 "12860","12860","msvcp140.dll",0.0103,1.0001,0.0514,5.0103 "B050","B050","msvcp140.dll",0.0102,0.9963,0.0102,0.9963 "12E0B","12E0B","msvcp140.dll",0.0102,0.9958,0.0102,0.9958 "12530","12530","msvcp140.dll",0.0101,0.9831,0.0101,0.9831 "5955","5955","msvcp140.dll",0.0100,0.9740,0.0100,0.9740 "3AA20","3AA20","msvcp140.dll",0.0045,0.4391,0.0045,0.4391 "22AD3","22AD3","msvcp140.dll",0.0038,0.3703,0.0038,0.3703 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_mswsock.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1ADC0","1ADC0","mswsock.dll",0.0205,2.0000,0.0205,2.0000 "14133","14133","mswsock.dll",0.0103,0.9995,0.0103,0.9995 "B8FE","B8FE","mswsock.dll",0.0009,0.0862,0.0009,0.0862 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_msxml6.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "8DE0","8DE0","msxml6.dll",0.0029,0.2836,0.0029,0.2836 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_ntdll.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "15FFA4","15FFA4","ntdll.dll",5.6033,545.9343,5.6649,551.9347 "160804","160804","ntdll.dll",3.9304,382.9390,3.9405,383.9322 "160044","160044","ntdll.dll",3.2561,317.2456,3.4592,337.0298 "160024","160024","ntdll.dll",2.2144,215.7549,2.4053,234.3510 "15FE24","15FE24","ntdll.dll",1.9028,185.3956,1.9164,186.7124 "15FF44","15FF44","ntdll.dll",1.8660,181.8086,1.8660,181.8086 "160504","160504","ntdll.dll",1.3606,132.5672,1.3606,132.5672 "160F14","160F14","ntdll.dll",1.2849,125.1857,1.2950,126.1779 "15FE44","15FE44","ntdll.dll",0.8321,81.0708,0.8321,81.0708 "160914","160914","ntdll.dll",0.8168,79.5813,0.8831,86.0457 "274EF","274EF","ntdll.dll",0.8108,78.9997,0.8108,78.9997 "162794","162794","ntdll.dll",0.7934,77.3058,0.7934,77.3058 "15FE64","15FE64","ntdll.dll",0.7187,70.0214,0.7187,70.0214 "15FDE4","15FDE4","ntdll.dll",0.6659,64.8751,0.7379,71.8966 "15FFC4","15FFC4","ntdll.dll",0.4078,39.7307,0.4693,45.7274 "27456","27456","ntdll.dll",0.3917,38.1679,0.3917,38.1679 "1603A4","1603A4","ntdll.dll",0.3507,34.1650,0.4018,39.1464 "160424","160424","ntdll.dll",0.3315,32.2936,0.3315,32.2936 "160954","160954","ntdll.dll",0.3207,31.2482,0.3207,31.2482 "27363","27363","ntdll.dll",0.2874,27.9995,0.2874,27.9995 "160104","160104","ntdll.dll",0.2827,27.5416,0.2827,27.5416 "160264","160264","ntdll.dll",0.2596,25.2976,0.2596,25.2976 "ADBAF","ADBAF","ntdll.dll",0.2557,24.9159,0.2557,24.9159 "27357","27357","ntdll.dll",0.2517,24.5196,0.2517,24.5196 "1605A4","1605A4","ntdll.dll",0.2301,22.4159,0.2301,22.4159 "162714","162714","ntdll.dll",0.2299,22.4003,0.2299,22.4003 "15FF24","15FF24","ntdll.dll",0.2259,22.0057,0.2259,22.0057 "D07B","D07B","ntdll.dll",0.2246,21.8873,0.2246,21.8873 "D05D","D05D","ntdll.dll",0.2213,21.5589,0.2213,21.5589 "CF5D","CF5D","ntdll.dll",0.2193,21.3646,0.2193,21.3646 "D117","D117","ntdll.dll",0.2126,20.7104,0.2126,20.7104 "D07F","D07F","ntdll.dll",0.2056,20.0358,0.2056,20.0358 "1633D4","1633D4","ntdll.dll",0.1729,16.8449,0.1729,16.8449 "163834","163834","ntdll.dll",0.1703,16.5963,0.1803,17.5697 "15FF84","15FF84","ntdll.dll",0.1657,16.1416,0.1657,16.1416 "163A34","163A34","ntdll.dll",0.1642,16.0000,0.1847,18.0000 "93B01","93B01","ntdll.dll",0.1532,14.9259,0.1532,14.9259 "160D74","160D74","ntdll.dll",0.1436,13.9931,0.1436,13.9931 "1618D4","1618D4","ntdll.dll",0.1414,13.7767,0.1414,13.7767 "15FE84","15FE84","ntdll.dll",0.1287,12.5348,0.1287,12.5348 "1606A4","1606A4","ntdll.dll",0.1282,12.4916,0.1282,12.4916 "495CD","495CD","ntdll.dll",0.1275,12.4196,0.1275,12.4196 "93B0C","93B0C","ntdll.dll",0.1116,10.8749,0.1116,10.8749 "161494","161494","ntdll.dll",0.1076,10.4833,0.1076,10.4833 "D065","D065","ntdll.dll",0.1036,10.0951,0.1036,10.0951 "29050","29050","ntdll.dll",0.1023,9.9710,0.1023,9.9710 "2907E","2907E","ntdll.dll",0.0995,9.6966,0.0995,9.6966 "161674","161674","ntdll.dll",0.0966,9.4141,0.0966,9.4141 "160124","160124","ntdll.dll",0.0939,9.1459,0.1039,10.1268 "1639D4","1639D4","ntdll.dll",0.0924,9.0051,0.0924,9.0051 "2C40C","2C40C","ntdll.dll",0.0910,8.8687,0.0910,8.8687 "C5644","C5644","ntdll.dll",0.0897,8.7414,0.0897,8.7414 "6D3EC","6D3EC","ntdll.dll",0.0847,8.2549,0.0847,8.2549 "6E045","6E045","ntdll.dll",0.0835,8.1381,0.0835,8.1381 "D0E8","D0E8","ntdll.dll",0.0819,7.9796,0.0819,7.9796 "160764","160764","ntdll.dll",0.0815,7.9380,0.0815,7.9380 "160244","160244","ntdll.dll",0.0793,7.7246,0.0793,7.7246 "160B94","160B94","ntdll.dll",0.0786,7.6629,0.0786,7.6629 "ADC60","ADC60","ntdll.dll",0.0783,7.6282,0.0783,7.6282 "49D60","49D60","ntdll.dll",0.0766,7.4655,0.0766,7.4655 "15FF64","15FF64","ntdll.dll",0.0743,7.2392,0.0743,7.2392 "49DBD","49DBD","ntdll.dll",0.0731,7.1268,0.0731,7.1268 "D123","D123","ntdll.dll",0.0726,7.0704,0.0726,7.0704 "160084","160084","ntdll.dll",0.0724,7.0552,0.0724,7.0552 "F8E6","F8E6","ntdll.dll",0.0718,6.9994,0.0718,6.9994 "6D3D1","6D3D1","ntdll.dll",0.0676,6.5904,0.0676,6.5904 "163AE7","163AE7","ntdll.dll",0.0671,6.5365,0.0671,6.5365 "3BA5A","3BA5A","ntdll.dll",0.0641,6.2471,0.0641,6.2471 "15FF04","15FF04","ntdll.dll",0.0618,6.0178,0.0618,6.0178 "28313","28313","ntdll.dll",0.0616,6.0043,0.0616,6.0043 "93B23","93B23","ntdll.dll",0.0615,5.9957,0.0615,5.9957 "CF0F","CF0F","ntdll.dll",0.0611,5.9555,0.0611,5.9555 "160064","160064","ntdll.dll",0.0604,5.8853,0.0604,5.8853 "CF05","CF05","ntdll.dll",0.0591,5.7623,0.0591,5.7623 "897A0","897A0","ntdll.dll",0.0587,5.7229,0.0587,5.7229 "D093","D093","ntdll.dll",0.0541,5.2716,0.0541,5.2716 "ADBF0","ADBF0","ntdll.dll",0.0519,5.0588,0.0519,5.0588 "162D34","162D34","ntdll.dll",0.0519,5.0545,0.0519,5.0545 "49D65","49D65","ntdll.dll",0.0513,5.0006,0.0513,5.0006 "27200","27200","ntdll.dll",0.0513,5.0005,0.0513,5.0005 "2C9EE","2C9EE","ntdll.dll",0.0512,4.9911,0.0512,4.9911 "D069","D069","ntdll.dll",0.0511,4.9764,0.0511,4.9764 "12E65F","12E65F","ntdll.dll",0.0489,4.7669,0.0489,4.7669 "1601C4","1601C4","ntdll.dll",0.0484,4.7174,0.0484,4.7174 "160184","160184","ntdll.dll",0.0475,4.6239,0.0475,4.6239 "1601E4","1601E4","ntdll.dll",0.0473,4.6048,0.0473,4.6048 "ADC43","ADC43","ntdll.dll",0.0463,4.5085,0.0463,4.5085 "26D35","26D35","ntdll.dll",0.0463,4.5079,0.0463,4.5079 "D137","D137","ntdll.dll",0.0454,4.4224,0.0454,4.4224 "2758C","2758C","ntdll.dll",0.0441,4.3014,0.0441,4.3014 "D0C4","D0C4","ntdll.dll",0.0427,4.1569,0.0427,4.1569 "27449","27449","ntdll.dll",0.0424,4.1295,0.0424,4.1295 "6E010","6E010","ntdll.dll",0.0421,4.1006,0.0421,4.1006 "27300","27300","ntdll.dll",0.0415,4.0445,0.0415,4.0445 "163954","163954","ntdll.dll",0.0414,4.0344,0.0414,4.0344 "49AEE","49AEE","ntdll.dll",0.0411,4.0070,0.0411,4.0070 "1608B4","1608B4","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "170030","170030","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "26D3C","26D3C","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "27238","27238","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "3BA56","3BA56","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "49590","49590","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "51817","51817","ntdll.dll",0.0411,4.0000,0.0411,4.0000 "160DD4","160DD4","ntdll.dll",0.0410,3.9962,0.0410,3.9962 "2727B","2727B","ntdll.dll",0.0410,3.9901,0.0410,3.9901 "6E015","6E015","ntdll.dll",0.0409,3.9891,0.0409,3.9891 "ADC12","ADC12","ntdll.dll",0.0409,3.9888,0.0409,3.9888 "93B4B","93B4B","ntdll.dll",0.0409,3.9868,0.0409,3.9868 "49F9D","49F9D","ntdll.dll",0.0409,3.9845,0.0409,3.9845 "CF63","CF63","ntdll.dll",0.0408,3.9730,0.0408,3.9730 "1664AC","1664AC","ntdll.dll",0.0360,3.5052,0.0360,3.5052 "26B7E","26B7E","ntdll.dll",0.0349,3.3960,0.0349,3.3960 "93B12","93B12","ntdll.dll",0.0338,3.2966,0.0338,3.2966 "CF59","CF59","ntdll.dll",0.0336,3.2689,0.0336,3.2689 "26BC5","26BC5","ntdll.dll",0.0335,3.2617,0.0335,3.2617 "160664","160664","ntdll.dll",0.0333,3.2493,0.0333,3.2493 "93AC3","93AC3","ntdll.dll",0.0329,3.2074,0.0329,3.2074 "820D8","820D8","ntdll.dll",0.0329,3.2064,0.0329,3.2064 "9C490","9C490","ntdll.dll",0.0329,3.2034,0.0329,3.2034 "16560E","16560E","ntdll.dll",0.0318,3.0995,0.0318,3.0995 "26B20","26B20","ntdll.dll",0.0317,3.0931,0.0317,3.0931 "15FEA4","15FEA4","ntdll.dll",0.0316,3.0798,0.0316,3.0798 "93AFD","93AFD","ntdll.dll",0.0310,3.0209,0.0310,3.0209 "6D3D7","6D3D7","ntdll.dll",0.0310,3.0179,0.0310,3.0179 "6FC0D","6FC0D","ntdll.dll",0.0309,3.0154,0.0309,3.0154 "49AD0","49AD0","ntdll.dll",0.0309,3.0133,0.0309,3.0133 "495B5","495B5","ntdll.dll",0.0309,3.0105,0.0309,3.0105 "161634","161634","ntdll.dll",0.0309,3.0102,0.0309,3.0102 "90093","90093","ntdll.dll",0.0308,3.0038,0.0308,3.0038 "26B2F","26B2F","ntdll.dll",0.0308,3.0028,0.0308,3.0028 "162974","162974","ntdll.dll",0.0308,3.0008,0.0308,3.0008 "282FD","282FD","ntdll.dll",0.0308,3.0005,0.0709,6.9062 "49F77","49F77","ntdll.dll",0.0308,3.0005,0.0308,3.0005 "6BD52","6BD52","ntdll.dll",0.0308,3.0003,0.0308,3.0003 "6D014","6D014","ntdll.dll",0.0308,3.0003,0.0308,3.0003 "52AB0","52AB0","ntdll.dll",0.0308,2.9994,0.0308,2.9994 "49F91","49F91","ntdll.dll",0.0308,2.9981,0.0308,2.9981 "26D62","26D62","ntdll.dll",0.0308,2.9975,0.0308,2.9975 "274D9","274D9","ntdll.dll",0.0308,2.9975,0.0308,2.9975 "235D9","235D9","ntdll.dll",0.0307,2.9957,0.0307,2.9957 "C9266","C9266","ntdll.dll",0.0307,2.9956,0.0307,2.9956 "70570","70570","ntdll.dll",0.0307,2.9953,0.0307,2.9953 "1623D4","1623D4","ntdll.dll",0.0307,2.9951,0.0307,2.9951 "4EF1C","4EF1C","ntdll.dll",0.0307,2.9928,0.0307,2.9928 "D062","D062","ntdll.dll",0.0307,2.9926,0.0307,2.9926 "272CC","272CC","ntdll.dll",0.0307,2.9882,0.0307,2.9882 "93AB5","93AB5","ntdll.dll",0.0307,2.9874,0.0307,2.9874 "27205","27205","ntdll.dll",0.0306,2.9848,0.0306,2.9848 "93B10","93B10","ntdll.dll",0.0305,2.9739,0.0305,2.9739 "274A2","274A2","ntdll.dll",0.0303,2.9555,0.0817,7.9569 "12E624","12E624","ntdll.dll",0.0302,2.9384,0.0302,2.9384 "D6820","D6820","ntdll.dll",0.0296,2.8841,0.0296,2.8841 "D26E0","D26E0","ntdll.dll",0.0282,2.7465,0.0282,2.7465 "28355","28355","ntdll.dll",0.0274,2.6679,0.0274,2.6679 "1602A4","1602A4","ntdll.dll",0.0272,2.6480,0.0272,2.6480 "3BA77","3BA77","ntdll.dll",0.0259,2.5203,0.0259,2.5203 "275C5","275C5","ntdll.dll",0.0254,2.4763,0.0254,2.4763 "49594","49594","ntdll.dll",0.0250,2.4314,0.0250,2.4314 "2748D","2748D","ntdll.dll",0.0249,2.4236,0.0249,2.4236 "26D4D","26D4D","ntdll.dll",0.0246,2.3997,0.0246,2.3997 "34730","34730","ntdll.dll",0.0243,2.3719,0.0243,2.3719 "CFA8","CFA8","ntdll.dll",0.0243,2.3696,0.0243,2.3696 "2732D","2732D","ntdll.dll",0.0242,2.3606,0.0242,2.3606 "C5641","C5641","ntdll.dll",0.0232,2.2642,0.0338,3.2940 "D099","D099","ntdll.dll",0.0229,2.2343,0.0229,2.2343 "12F59A","12F59A","ntdll.dll",0.0226,2.1981,0.0226,2.1981 "93AF4","93AF4","ntdll.dll",0.0224,2.1821,0.0224,2.1821 "1951C","1951C","ntdll.dll",0.0222,2.1670,0.0222,2.1670 "3B600","3B600","ntdll.dll",0.0222,2.1616,0.0222,2.1616 "90016","90016","ntdll.dll",0.0221,2.1519,0.0221,2.1519 "68DDA","68DDA","ntdll.dll",0.0215,2.0909,0.0215,2.0909 "15FF70","15FF70","ntdll.dll",0.0215,2.0907,0.0215,2.0907 "CFDC","CFDC","ntdll.dll",0.0214,2.0887,0.0214,2.0887 "41759","41759","ntdll.dll",0.0209,2.0327,0.0209,2.0327 "15FFE4","15FFE4","ntdll.dll",0.0208,2.0256,0.0208,2.0256 "27210","27210","ntdll.dll",0.0208,2.0250,0.0208,2.0250 "6CE80","6CE80","ntdll.dll",0.0208,2.0243,0.0208,2.0243 "161934","161934","ntdll.dll",0.0208,2.0217,0.0208,2.0217 "CFCA","CFCA","ntdll.dll",0.0206,2.0112,0.0206,2.0112 "274E1","274E1","ntdll.dll",0.0206,2.0094,0.0206,2.0094 "ADC03","ADC03","ntdll.dll",0.0206,2.0053,0.0206,2.0053 "D086","D086","ntdll.dll",0.0206,2.0045,0.0206,2.0045 "27231","27231","ntdll.dll",0.0206,2.0032,0.0206,2.0032 "26B79","26B79","ntdll.dll",0.0206,2.0030,0.0206,2.0030 "6D478","6D478","ntdll.dll",0.0205,2.0020,0.0205,2.0020 "ADC78","ADC78","ntdll.dll",0.0205,2.0019,0.0205,2.0019 "2C3F5","2C3F5","ntdll.dll",0.0205,2.0010,0.0205,2.0010 "27583","27583","ntdll.dll",0.0205,2.0005,0.0205,2.0005 "129C0E","129C0E","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "15FF98","15FF98","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "160018","160018","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "160164","160164","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "160204","160204","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "160524","160524","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "1606E4","1606E4","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "160D14","160D14","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "162434","162434","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "163914","163914","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "163D80","163D80","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "163D9F","163D9F","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "165529","165529","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "165609","165609","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "165626","165626","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "16588B","16588B","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "166314","166314","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "1663C3","1663C3","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "19562","19562","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "19627","19627","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "256BD","256BD","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "26C02","26C02","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "2725C","2725C","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "274D3","274D3","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "27C31","27C31","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "29AF0","29AF0","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "2C3C4","2C3C4","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "2C3D2","2C3D2","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "2C58B","2C58B","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "34270","34270","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "3B2E0","3B2E0","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "41CC3","41CC3","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "431DF","431DF","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "49DB6","49DB6","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4C9DA","4C9DA","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4D8CC","4D8CC","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4E9E2","4E9E2","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4EEDC","4EEDC","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4EF11","4EF11","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4EF14","4EF14","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "4F2F3","4F2F3","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "5180A","5180A","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "529A2","529A2","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "529D8","529D8","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "52A4D","52A4D","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "55537","55537","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "6317B","6317B","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "68DD1","68DD1","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "6BAFA","6BAFA","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "6BB28","6BB28","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "6CFB8","6CFB8","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "6FBC9","6FBC9","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "70412","70412","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "70464","70464","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "75656","75656","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "81F9B","81F9B","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "84AC0","84AC0","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "89719","89719","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "92738","92738","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "93B34","93B34","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "ADBCB","ADBCB","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "ADC15","ADC15","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "B7DFD","B7DFD","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "C6B10","C6B10","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "C776E","C776E","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "CB400","CB400","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "D046","D046","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "D146","D146","ntdll.dll",0.0205,2.0000,0.0205,2.0000 "26C12","26C12","ntdll.dll",0.0205,1.9998,0.0205,1.9998 "C7740","C7740","ntdll.dll",0.0205,1.9996,0.0205,1.9996 "12E5D6","12E5D6","ntdll.dll",0.0205,1.9984,0.0205,1.9984 "26B87","26B87","ntdll.dll",0.0205,1.9976,0.0205,1.9976 "D10A","D10A","ntdll.dll",0.0205,1.9948,0.0205,1.9948 "27447","27447","ntdll.dll",0.0205,1.9943,0.0205,1.9943 "272E1","272E1","ntdll.dll",0.0204,1.9914,0.0204,1.9914 "49F7A","49F7A","ntdll.dll",0.0204,1.9906,0.0204,1.9906 "92721","92721","ntdll.dll",0.0204,1.9884,0.0204,1.9884 "26B62","26B62","ntdll.dll",0.0204,1.9883,0.0204,1.9883 "29AE9","29AE9","ntdll.dll",0.0204,1.9879,0.0204,1.9879 "27260","27260","ntdll.dll",0.0204,1.9841,0.0204,1.9841 "ADBC8","ADBC8","ntdll.dll",0.0203,1.9767,0.0203,1.9767 "2742C","2742C","ntdll.dll",0.0203,1.9760,0.0203,1.9760 "12F59F","12F59F","ntdll.dll",0.0203,1.9743,0.0203,1.9743 "27435","27435","ntdll.dll",0.0202,1.9688,0.0202,1.9688 "2C9D0","2C9D0","ntdll.dll",0.0202,1.9665,0.0202,1.9665 "529E2","529E2","ntdll.dll",0.0194,1.8924,0.0194,1.8924 "10FDA","10FDA","ntdll.dll",0.0188,1.8326,0.0188,1.8326 "27258","27258","ntdll.dll",0.0188,1.8298,0.0188,1.8298 "26BB3","26BB3","ntdll.dll",0.0187,1.8180,0.0187,1.8180 "D050","D050","ntdll.dll",0.0182,1.7756,0.0182,1.7756 "B7D47","B7D47","ntdll.dll",0.0178,1.7308,0.0178,1.7308 "160CB4","160CB4","ntdll.dll",0.0178,1.7307,0.0178,1.7307 "160444","160444","ntdll.dll",0.0177,1.7262,0.0177,1.7262 "129A6E","129A6E","ntdll.dll",0.0176,1.7172,0.0176,1.7172 "D3270","D3270","ntdll.dll",0.0176,1.7110,0.0176,1.7110 "16AFF","16AFF","ntdll.dll",0.0167,1.6314,0.0167,1.6314 "C5664","C5664","ntdll.dll",0.0166,1.6197,0.0166,1.6197 "6D3DB","6D3DB","ntdll.dll",0.0166,1.6173,0.0166,1.6173 "93B06","93B06","ntdll.dll",0.0162,1.5748,0.0162,1.5748 "6BD7E","6BD7E","ntdll.dll",0.0161,1.5665,0.0161,1.5665 "272ED","272ED","ntdll.dll",0.0160,1.5560,0.0160,1.5560 "CB43A","CB43A","ntdll.dll",0.0156,1.5244,0.0156,1.5244 "3B8CD","3B8CD","ntdll.dll",0.0156,1.5208,0.0156,1.5208 "A3745","A3745","ntdll.dll",0.0156,1.5185,0.0156,1.5185 "D151","D151","ntdll.dll",0.0152,1.4801,0.0152,1.4801 "506B0","506B0","ntdll.dll",0.0147,1.4347,0.0147,1.4347 "ADBB3","ADBB3","ntdll.dll",0.0146,1.4224,0.0146,1.4224 "26BF8","26BF8","ntdll.dll",0.0143,1.3942,0.0143,1.3942 "8FFD8","8FFD8","ntdll.dll",0.0141,1.3714,0.0141,1.3714 "6E12C","6E12C","ntdll.dll",0.0140,1.3682,0.0140,1.3682 "163C34","163C34","ntdll.dll",0.0139,1.3513,0.0139,1.3513 "2D87F","2D87F","ntdll.dll",0.0138,1.3482,0.0138,1.3482 "3B64A","3B64A","ntdll.dll",0.0137,1.3392,0.0137,1.3392 "52A76","52A76","ntdll.dll",0.0135,1.3133,0.0135,1.3133 "12EAFC","12EAFC","ntdll.dll",0.0135,1.3130,0.0135,1.3130 "27272","27272","ntdll.dll",0.0134,1.3008,0.0134,1.3008 "24C86","24C86","ntdll.dll",0.0133,1.2926,0.0133,1.2926 "ADC22","ADC22","ntdll.dll",0.0133,1.2921,0.0133,1.2921 "160224","160224","ntdll.dll",0.0131,1.2789,0.0131,1.2789 "6D3BF","6D3BF","ntdll.dll",0.0129,1.2542,0.0129,1.2542 "19513","19513","ntdll.dll",0.0128,1.2431,0.0128,1.2431 "26E59","26E59","ntdll.dll",0.0126,1.2247,0.0126,1.2247 "2C400","2C400","ntdll.dll",0.0126,1.2246,0.0126,1.2246 "3F400","3F400","ntdll.dll",0.0125,1.2166,0.0125,1.2166 "C2EDC","C2EDC","ntdll.dll",0.0124,1.2107,0.0124,1.2107 "27C70","27C70","ntdll.dll",0.0123,1.2023,0.0123,1.2023 "27573","27573","ntdll.dll",0.0121,1.1813,0.0121,1.1813 "68D1E","68D1E","ntdll.dll",0.0120,1.1667,0.0120,1.1667 "93ABA","93ABA","ntdll.dll",0.0119,1.1586,0.0119,1.1586 "1EDCE","1EDCE","ntdll.dll",0.0118,1.1545,0.0118,1.1545 "13D0E0","13D0E0","ntdll.dll",0.0118,1.1505,0.0118,1.1505 "6D390","6D390","ntdll.dll",0.0118,1.1501,0.0118,1.1501 "29ADD","29ADD","ntdll.dll",0.0114,1.1144,0.0114,1.1144 "6CE44","6CE44","ntdll.dll",0.0113,1.1008,0.0113,1.1008 "25A79","25A79","ntdll.dll",0.0113,1.0982,0.0113,1.0982 "1914A","1914A","ntdll.dll",0.0113,1.0978,0.0113,1.0978 "14202","14202","ntdll.dll",0.0112,1.0932,0.0112,1.0932 "12E650","12E650","ntdll.dll",0.0112,1.0913,0.0112,1.0913 "163AA0","163AA0","ntdll.dll",0.0110,1.0681,0.0110,1.0681 "274EB","274EB","ntdll.dll",0.0109,1.0657,0.0109,1.0657 "29EAA","29EAA","ntdll.dll",0.0109,1.0637,0.0109,1.0637 "27360","27360","ntdll.dll",0.0108,1.0499,0.0108,1.0499 "2746F","2746F","ntdll.dll",0.0108,1.0485,0.0108,1.0485 "26BB8","26BB8","ntdll.dll",0.0108,1.0480,0.0108,1.0480 "CAE80","CAE80","ntdll.dll",0.0107,1.0469,0.0107,1.0469 "160684","160684","ntdll.dll",0.0106,1.0338,0.0106,1.0338 "4B8D3","4B8D3","ntdll.dll",0.0106,1.0335,0.0106,1.0335 "2CA33","2CA33","ntdll.dll",0.0106,1.0285,0.0106,1.0285 "CF20","CF20","ntdll.dll",0.0105,1.0262,0.0105,1.0262 "163B20","163B20","ntdll.dll",0.0105,1.0257,0.0105,1.0257 "AD446","AD446","ntdll.dll",0.0105,1.0231,0.0105,1.0231 "84D1E","84D1E","ntdll.dll",0.0105,1.0187,0.0105,1.0187 "68D49","68D49","ntdll.dll",0.0104,1.0161,0.0104,1.0161 "160CD4","160CD4","ntdll.dll",0.0104,1.0146,0.0104,1.0146 "4C0F0","4C0F0","ntdll.dll",0.0104,1.0145,0.0104,1.0145 "2E9BA","2E9BA","ntdll.dll",0.0104,1.0137,0.0104,1.0137 "CFDA","CFDA","ntdll.dll",0.0104,1.0134,0.0104,1.0134 "162354","162354","ntdll.dll",0.0104,1.0131,0.0104,1.0131 "B7CC0","B7CC0","ntdll.dll",0.0104,1.0130,0.0104,1.0130 "D0A5","D0A5","ntdll.dll",0.0104,1.0128,0.0104,1.0128 "160364","160364","ntdll.dll",0.0104,1.0115,0.0104,1.0115 "C15D","C15D","ntdll.dll",0.0104,1.0092,0.0104,1.0092 "166300","166300","ntdll.dll",0.0103,1.0082,0.0103,1.0082 "29AEB","29AEB","ntdll.dll",0.0103,1.0082,0.0103,1.0082 "6CEE9","6CEE9","ntdll.dll",0.0103,1.0064,0.0103,1.0064 "26B5B","26B5B","ntdll.dll",0.0103,1.0058,0.0103,1.0058 "ADC3F","ADC3F","ntdll.dll",0.0103,1.0054,0.0103,1.0054 "1300E9","1300E9","ntdll.dll",0.0103,1.0043,0.0103,1.0043 "C563C","C563C","ntdll.dll",0.0103,1.0040,0.0103,1.0040 "26B8D","26B8D","ntdll.dll",0.0103,1.0038,0.0103,1.0038 "26B99","26B99","ntdll.dll",0.0103,1.0036,0.0103,1.0036 "29052","29052","ntdll.dll",0.0103,1.0036,0.0103,1.0036 "CFE3","CFE3","ntdll.dll",0.0103,1.0036,0.0103,1.0036 "49D75","49D75","ntdll.dll",0.0103,1.0035,0.0103,1.0035 "D163","D163","ntdll.dll",0.0103,1.0032,0.0103,1.0032 "26BBC","26BBC","ntdll.dll",0.0103,1.0031,0.0103,1.0031 "16083","16083","ntdll.dll",0.0103,1.0028,0.0103,1.0028 "29068","29068","ntdll.dll",0.0103,1.0028,0.0103,1.0028 "12FFB0","12FFB0","ntdll.dll",0.0103,1.0027,0.0103,1.0027 "27473","27473","ntdll.dll",0.0103,1.0027,0.0103,1.0027 "27580","27580","ntdll.dll",0.0103,1.0027,0.0103,1.0027 "165665","165665","ntdll.dll",0.0103,1.0023,0.0103,1.0023 "29AC3","29AC3","ntdll.dll",0.0103,1.0019,0.0103,1.0019 "6F4D9","6F4D9","ntdll.dll",0.0103,1.0018,0.0103,1.0018 "C775B","C775B","ntdll.dll",0.0103,1.0018,0.0103,1.0018 "26BFF","26BFF","ntdll.dll",0.0103,1.0015,0.0103,1.0015 "256D0","256D0","ntdll.dll",0.0103,1.0013,0.0103,1.0013 "CF10","CF10","ntdll.dll",0.0103,1.0013,0.0103,1.0013 "1663B0","1663B0","ntdll.dll",0.0103,1.0012,0.0103,1.0012 "272DC","272DC","ntdll.dll",0.0103,1.0010,0.0103,1.0010 "9253F","9253F","ntdll.dll",0.0103,1.0010,0.0103,1.0010 "26BA0","26BA0","ntdll.dll",0.0103,1.0008,0.0103,1.0008 "3BE1F","3BE1F","ntdll.dll",0.0103,1.0007,0.0103,1.0007 "C9255","C9255","ntdll.dll",0.0103,1.0007,0.0103,1.0007 "D072","D072","ntdll.dll",0.0103,1.0006,0.0103,1.0006 "27215","27215","ntdll.dll",0.0103,1.0005,0.0103,1.0005 "2CA15","2CA15","ntdll.dll",0.0103,1.0005,0.0103,1.0005 "6BD58","6BD58","ntdll.dll",0.0103,1.0003,0.0103,1.0003 "27588","27588","ntdll.dll",0.0103,1.0002,0.0103,1.0002 "8FF90","8FF90","ntdll.dll",0.0103,1.0002,0.0103,1.0002 "49D6F","49D6F","ntdll.dll",0.0103,1.0000,0.0103,1.0000 "93ABB","93ABB","ntdll.dll",0.0103,1.0000,0.0103,1.0000 "10343","10343","ntdll.dll",0.0103,0.9998,0.0103,0.9998 "495A4","495A4","ntdll.dll",0.0103,0.9997,0.0103,0.9997 "D075","D075","ntdll.dll",0.0103,0.9997,0.0103,0.9997 "D0FE","D0FE","ntdll.dll",0.0103,0.9995,0.0103,0.9995 "26B9C","26B9C","ntdll.dll",0.0103,0.9994,0.0103,0.9994 "29063","29063","ntdll.dll",0.0103,0.9992,0.0103,0.9992 "F9FA","F9FA","ntdll.dll",0.0103,0.9992,0.0103,0.9992 "CF3A","CF3A","ntdll.dll",0.0103,0.9989,0.0103,0.9989 "2731E","2731E","ntdll.dll",0.0103,0.9988,0.0103,0.9988 "27A6B","27A6B","ntdll.dll",0.0102,0.9984,0.0102,0.9984 "89CB0","89CB0","ntdll.dll",0.0102,0.9981,0.0102,0.9981 "27219","27219","ntdll.dll",0.0102,0.9979,0.0102,0.9979 "274E8","274E8","ntdll.dll",0.0102,0.9978,0.0102,0.9978 "2905A","2905A","ntdll.dll",0.0102,0.9978,0.0102,0.9978 "C1E4","C1E4","ntdll.dll",0.0102,0.9978,0.0102,0.9978 "2728C","2728C","ntdll.dll",0.0102,0.9977,0.0102,0.9977 "3B15B","3B15B","ntdll.dll",0.0102,0.9976,0.0102,0.9976 "ADC1A","ADC1A","ntdll.dll",0.0102,0.9976,0.0102,0.9976 "29AF2","29AF2","ntdll.dll",0.0102,0.9975,0.0102,0.9975 "D9FF0","D9FF0","ntdll.dll",0.0102,0.9975,0.0102,0.9975 "15FFA0","15FFA0","ntdll.dll",0.0102,0.9974,0.0102,0.9974 "CF00","CF00","ntdll.dll",0.0102,0.9974,0.0102,0.9974 "26B26","26B26","ntdll.dll",0.0102,0.9973,0.0102,0.9973 "CFB5","CFB5","ntdll.dll",0.0102,0.9973,0.0102,0.9973 "ADBA0","ADBA0","ntdll.dll",0.0102,0.9972,0.0102,0.9972 "274D1","274D1","ntdll.dll",0.0102,0.9969,0.0102,0.9969 "28346","28346","ntdll.dll",0.0102,0.9969,0.0102,0.9969 "B8B00","B8B00","ntdll.dll",0.0102,0.9969,0.0102,0.9969 "5A010","5A010","ntdll.dll",0.0102,0.9967,0.0102,0.9967 "12E656","12E656","ntdll.dll",0.0102,0.9966,0.0102,0.9966 "7045F","7045F","ntdll.dll",0.0102,0.9965,0.0102,0.9965 "26B95","26B95","ntdll.dll",0.0102,0.9963,0.0102,0.9963 "151476","151476","ntdll.dll",0.0102,0.9960,0.0102,0.9960 "49F98","49F98","ntdll.dll",0.0102,0.9958,0.0102,0.9958 "93700","93700","ntdll.dll",0.0102,0.9958,0.0102,0.9958 "13D2F1","13D2F1","ntdll.dll",0.0102,0.9957,0.0102,0.9957 "C9305","C9305","ntdll.dll",0.0102,0.9956,0.0102,0.9956 "27325","27325","ntdll.dll",0.0102,0.9955,0.0102,0.9955 "49F81","49F81","ntdll.dll",0.0102,0.9953,0.0102,0.9953 "ADC6F","ADC6F","ntdll.dll",0.0102,0.9951,0.0102,0.9951 "12E612","12E612","ntdll.dll",0.0102,0.9949,0.0102,0.9949 "25689","25689","ntdll.dll",0.0102,0.9949,0.0102,0.9949 "163AE3","163AE3","ntdll.dll",0.0102,0.9940,0.0102,0.9940 "89670","89670","ntdll.dll",0.0102,0.9938,0.0102,0.9938 "CF47","CF47","ntdll.dll",0.0102,0.9938,0.0102,0.9938 "93BBC","93BBC","ntdll.dll",0.0102,0.9932,0.0102,0.9932 "15FF58","15FF58","ntdll.dll",0.0102,0.9930,0.0102,0.9930 "26D26","26D26","ntdll.dll",0.0102,0.9930,0.0102,0.9930 "3BED6","3BED6","ntdll.dll",0.0102,0.9929,0.0102,0.9929 "27269","27269","ntdll.dll",0.0102,0.9927,0.0102,0.9927 "D108","D108","ntdll.dll",0.0102,0.9927,0.0102,0.9927 "93B41","93B41","ntdll.dll",0.0102,0.9925,0.0102,0.9925 "D002","D002","ntdll.dll",0.0102,0.9920,0.0102,0.9920 "4B452","4B452","ntdll.dll",0.0102,0.9917,0.0102,0.9917 "C161","C161","ntdll.dll",0.0102,0.9917,0.0102,0.9917 "2906B","2906B","ntdll.dll",0.0102,0.9914,0.0102,0.9914 "FD14","FD14","ntdll.dll",0.0102,0.9914,0.0102,0.9914 "2749D","2749D","ntdll.dll",0.0102,0.9912,0.0102,0.9912 "2906E","2906E","ntdll.dll",0.0102,0.9912,0.0102,0.9912 "28350","28350","ntdll.dll",0.0102,0.9909,0.0102,0.9909 "15FF30","15FF30","ntdll.dll",0.0102,0.9906,0.0102,0.9906 "ADC1D","ADC1D","ntdll.dll",0.0102,0.9904,0.0102,0.9904 "29053","29053","ntdll.dll",0.0102,0.9902,0.0102,0.9902 "19BBD","19BBD","ntdll.dll",0.0102,0.9899,0.0102,0.9899 "ADC62","ADC62","ntdll.dll",0.0102,0.9899,0.0102,0.9899 "5A028","5A028","ntdll.dll",0.0102,0.9894,0.0102,0.9894 "2720A","2720A","ntdll.dll",0.0102,0.9890,0.0102,0.9890 "2720F","2720F","ntdll.dll",0.0101,0.9889,0.0101,0.9889 "204D1","204D1","ntdll.dll",0.0101,0.9885,0.0101,0.9885 "6D39A","6D39A","ntdll.dll",0.0101,0.9884,0.0101,0.9884 "CF11","CF11","ntdll.dll",0.0101,0.9884,0.0101,0.9884 "45360","45360","ntdll.dll",0.0101,0.9881,0.0101,0.9881 "19500","19500","ntdll.dll",0.0101,0.9879,0.0101,0.9879 "26B24","26B24","ntdll.dll",0.0101,0.9863,0.0101,0.9863 "274CE","274CE","ntdll.dll",0.0101,0.9863,0.0101,0.9863 "93AB0","93AB0","ntdll.dll",0.0101,0.9863,0.0101,0.9863 "4AA2","4AA2","ntdll.dll",0.0101,0.9861,0.0101,0.9861 "ADC29","ADC29","ntdll.dll",0.0101,0.9857,0.0101,0.9857 "12F5BE","12F5BE","ntdll.dll",0.0101,0.9846,0.0101,0.9846 "12E648","12E648","ntdll.dll",0.0101,0.9845,0.0101,0.9845 "12FE9F","12FE9F","ntdll.dll",0.0101,0.9839,0.0101,0.9839 "6E024","6E024","ntdll.dll",0.0101,0.9838,0.0101,0.9838 "2C3D9","2C3D9","ntdll.dll",0.0101,0.9822,0.0101,0.9822 "34132","34132","ntdll.dll",0.0100,0.9699,0.0100,0.9699 "4AC43","4AC43","ntdll.dll",0.0099,0.9661,0.0099,0.9661 "163B05","163B05","ntdll.dll",0.0099,0.9653,0.0099,0.9653 "29ADA","29ADA","ntdll.dll",0.0099,0.9598,5.0232,489.4176 "1994F","1994F","ntdll.dll",0.0095,0.9266,0.0095,0.9266 "6E114","6E114","ntdll.dll",0.0094,0.9187,0.0094,0.9187 "ADC59","ADC59","ntdll.dll",0.0094,0.9146,0.0094,0.9146 "16636D","16636D","ntdll.dll",0.0093,0.9045,0.0093,0.9045 "12F902","12F902","ntdll.dll",0.0087,0.8460,0.0087,0.8460 "50780","50780","ntdll.dll",0.0082,0.8034,0.0082,0.8034 "897CC","897CC","ntdll.dll",0.0082,0.7973,0.0082,0.7973 "26D6C","26D6C","ntdll.dll",0.0081,0.7884,0.0081,0.7884 "13CB66","13CB66","ntdll.dll",0.0079,0.7668,0.0079,0.7668 "4E2C6","4E2C6","ntdll.dll",0.0077,0.7546,0.0077,0.7546 "ADBD0","ADBD0","ntdll.dll",0.0077,0.7476,0.0077,0.7476 "27419","27419","ntdll.dll",0.0072,0.7044,0.0072,0.7044 "ADBEB","ADBEB","ntdll.dll",0.0068,0.6620,0.0068,0.6620 "29066","29066","ntdll.dll",0.0066,0.6431,0.0066,0.6431 "165604","165604","ntdll.dll",0.0065,0.6314,0.0065,0.6314 "6D395","6D395","ntdll.dll",0.0060,0.5820,0.0060,0.5820 "49D71","49D71","ntdll.dll",0.0060,0.5815,0.0060,0.5815 "93B3A","93B3A","ntdll.dll",0.0057,0.5538,0.0057,0.5538 "ADBBD","ADBBD","ntdll.dll",0.0044,0.4280,0.0044,0.4280 "29ACC","29ACC","ntdll.dll",0.0036,0.3520,0.0036,0.3520 "C6838","C6838","ntdll.dll",0.0033,0.3184,0.0033,0.3184 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_ntoskrnl.exe_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2DE679","2DE679","ntoskrnl.exe",1.1227,109.3857,1.1227,109.3857 "C55ECC","C55ECC","ntoskrnl.exe",0.4941,48.1401,0.4941,48.1401 "624533","624533","ntoskrnl.exe",0.4337,42.2566,0.4337,42.2566 "C55B14","C55B14","ntoskrnl.exe",0.2866,27.9243,0.2866,27.9243 "2DE690","2DE690","ntoskrnl.exe",0.2498,24.3410,0.2498,24.3410 "2DE67E","2DE67E","ntoskrnl.exe",0.2114,20.5996,0.2114,20.5996 "2DE677","2DE677","ntoskrnl.exe",0.2061,20.0763,0.2061,20.0763 "2765CD","2765CD","ntoskrnl.exe",0.2013,19.6085,0.2013,19.6085 "73FB18","73FB18","ntoskrnl.exe",0.1922,18.7290,0.1922,18.7290 "2DE614","2DE614","ntoskrnl.exe",0.1707,16.6343,0.1707,16.6343 "2DE681","2DE681","ntoskrnl.exe",0.1629,15.8684,0.1629,15.8684 "626479","626479","ntoskrnl.exe",0.1571,15.3042,0.1571,15.3042 "2DE65B","2DE65B","ntoskrnl.exe",0.1505,14.6606,0.1505,14.6606 "2DE66A","2DE66A","ntoskrnl.exe",0.1303,12.6999,0.1303,12.6999 "2DE699","2DE699","ntoskrnl.exe",0.1288,12.5445,0.1288,12.5445 "2DE68E","2DE68E","ntoskrnl.exe",0.1258,12.2552,0.1258,12.2552 "27B4EA","27B4EA","ntoskrnl.exe",0.1257,12.2496,0.1257,12.2496 "271C15","271C15","ntoskrnl.exe",0.0983,9.5800,0.0983,9.5800 "734D6A","734D6A","ntoskrnl.exe",0.0941,9.1647,0.0941,9.1647 "624E98","624E98","ntoskrnl.exe",0.0929,9.0551,0.0929,9.0551 "516692","516692","ntoskrnl.exe",0.0927,9.0311,0.0927,9.0311 "2DE672","2DE672","ntoskrnl.exe",0.0881,8.5824,0.0881,8.5824 "624317","624317","ntoskrnl.exe",0.0850,8.2779,0.0850,8.2779 "2DB58C","2DB58C","ntoskrnl.exe",0.0834,8.1232,0.0834,8.1232 "2DE686","2DE686","ntoskrnl.exe",0.0833,8.1154,0.0833,8.1154 "2EC4BE","2EC4BE","ntoskrnl.exe",0.0820,7.9908,0.0820,7.9908 "27D181","27D181","ntoskrnl.exe",0.0787,7.6671,0.0787,7.6671 "2DB01E","2DB01E","ntoskrnl.exe",0.0735,7.1638,0.0735,7.1638 "26F364","26F364","ntoskrnl.exe",0.0727,7.0823,0.0727,7.0823 "8B6A30","8B6A30","ntoskrnl.exe",0.0718,6.9935,0.0718,6.9935 "6242A3","6242A3","ntoskrnl.exe",0.0698,6.8041,0.0698,6.8041 "27D187","27D187","ntoskrnl.exe",0.0697,6.7940,0.0697,6.7940 "C55875","C55875","ntoskrnl.exe",0.0697,6.7913,0.0697,6.7913 "73B512","73B512","ntoskrnl.exe",0.0671,6.5349,0.0671,6.5349 "2DE619","2DE619","ntoskrnl.exe",0.0667,6.4950,0.0667,6.4950 "2DE620","2DE620","ntoskrnl.exe",0.0661,6.4449,0.0661,6.4449 "62446E","62446E","ntoskrnl.exe",0.0658,6.4157,0.0658,6.4157 "62498D","62498D","ntoskrnl.exe",0.0641,6.2498,0.0641,6.2498 "27D0F8","27D0F8","ntoskrnl.exe",0.0636,6.1973,0.0636,6.1973 "2DB1B5","2DB1B5","ntoskrnl.exe",0.0627,6.1059,0.0627,6.1059 "624E19","624E19","ntoskrnl.exe",0.0618,6.0220,0.0618,6.0220 "2DE525","2DE525","ntoskrnl.exe",0.0617,6.0138,0.0617,6.0138 "624E2B","624E2B","ntoskrnl.exe",0.0617,6.0126,0.0617,6.0126 "627A2B","627A2B","ntoskrnl.exe",0.0608,5.9198,0.0608,5.9198 "27D1E4","27D1E4","ntoskrnl.exe",0.0603,5.8723,0.0603,5.8723 "624BDF","624BDF","ntoskrnl.exe",0.0597,5.8184,0.0597,5.8184 "624284","624284","ntoskrnl.exe",0.0594,5.7877,0.0594,5.7877 "3F0F66","3F0F66","ntoskrnl.exe",0.0578,5.6360,0.0578,5.6360 "6244C8","6244C8","ntoskrnl.exe",0.0563,5.4898,0.0563,5.4898 "401EEB","401EEB","ntoskrnl.exe",0.0556,5.4195,0.0556,5.4195 "62452A","62452A","ntoskrnl.exe",0.0554,5.3967,0.0554,5.3967 "6279FA","6279FA","ntoskrnl.exe",0.0544,5.3044,0.0544,5.3044 "624466","624466","ntoskrnl.exe",0.0539,5.2522,0.0539,5.2522 "6242B2","6242B2","ntoskrnl.exe",0.0538,5.2451,0.0538,5.2451 "624E9C","624E9C","ntoskrnl.exe",0.0523,5.0960,0.0523,5.0960 "627A24","627A24","ntoskrnl.exe",0.0520,5.0687,0.0520,5.0687 "385917","385917","ntoskrnl.exe",0.0517,5.0346,0.0517,5.0346 "C55ED6","C55ED6","ntoskrnl.exe",0.0516,5.0236,0.0516,5.0236 "62436E","62436E","ntoskrnl.exe",0.0515,5.0201,0.0515,5.0201 "624DE0","624DE0","ntoskrnl.exe",0.0514,5.0103,0.0514,5.0103 "27D435","27D435","ntoskrnl.exe",0.0514,5.0090,0.0514,5.0090 "C55BD1","C55BD1","ntoskrnl.exe",0.0514,5.0054,0.0514,5.0054 "6244B3","6244B3","ntoskrnl.exe",0.0513,4.9937,0.0513,4.9937 "2EDBB6","2EDBB6","ntoskrnl.exe",0.0512,4.9860,0.0512,4.9860 "401EE3","401EE3","ntoskrnl.exe",0.0510,4.9675,0.0510,4.9675 "6242F5","6242F5","ntoskrnl.exe",0.0508,4.9513,0.0508,4.9513 "6244BB","6244BB","ntoskrnl.exe",0.0498,4.8507,0.0498,4.8507 "20620A","20620A","ntoskrnl.exe",0.0491,4.7831,0.0491,4.7831 "624515","624515","ntoskrnl.exe",0.0490,4.7752,0.0490,4.7752 "C55E89","C55E89","ntoskrnl.exe",0.0487,4.7404,0.0487,4.7404 "734E86","734E86","ntoskrnl.exe",0.0470,4.5802,0.0470,4.5802 "624B9A","624B9A","ntoskrnl.exe",0.0468,4.5633,0.0468,4.5633 "72E0FD","72E0FD","ntoskrnl.exe",0.0468,4.5629,0.0468,4.5629 "6242D5","6242D5","ntoskrnl.exe",0.0468,4.5551,0.0468,4.5551 "6242AB","6242AB","ntoskrnl.exe",0.0467,4.5529,0.0467,4.5529 "62450A","62450A","ntoskrnl.exe",0.0461,4.4937,0.0461,4.4937 "2DE664","2DE664","ntoskrnl.exe",0.0459,4.4673,0.0459,4.4673 "2DE694","2DE694","ntoskrnl.exe",0.0454,4.4261,0.0454,4.4261 "2DC182","2DC182","ntoskrnl.exe",0.0453,4.4179,0.0453,4.4179 "6242C8","6242C8","ntoskrnl.exe",0.0450,4.3820,0.0450,4.3820 "2DA9D5","2DA9D5","ntoskrnl.exe",0.0434,4.2255,0.0434,4.2255 "6243D6","6243D6","ntoskrnl.exe",0.0431,4.2001,0.0431,4.2001 "2DE660","2DE660","ntoskrnl.exe",0.0423,4.1210,0.0423,4.1210 "62428F","62428F","ntoskrnl.exe",0.0422,4.1147,0.0422,4.1147 "9DAC2E","9DAC2E","ntoskrnl.exe",0.0419,4.0795,0.0419,4.0795 "625450","625450","ntoskrnl.exe",0.0412,4.0168,0.0412,4.0168 "624BC8","624BC8","ntoskrnl.exe",0.0411,4.0081,0.0411,4.0081 "27D131","27D131","ntoskrnl.exe",0.0411,4.0079,0.0411,4.0079 "2DB1EE","2DB1EE","ntoskrnl.exe",0.0411,4.0056,0.0411,4.0056 "2DE735","2DE735","ntoskrnl.exe",0.0411,4.0055,0.0411,4.0055 "2DA1A5","2DA1A5","ntoskrnl.exe",0.0411,4.0052,0.0411,4.0052 "624BFE","624BFE","ntoskrnl.exe",0.0411,4.0000,0.0411,4.0000 "627981","627981","ntoskrnl.exe",0.0411,4.0000,0.0411,4.0000 "73458F","73458F","ntoskrnl.exe",0.0411,4.0000,0.0411,4.0000 "C55A91","C55A91","ntoskrnl.exe",0.0411,4.0000,0.0411,4.0000 "2E932C","2E932C","ntoskrnl.exe",0.0409,3.9856,0.0409,3.9856 "6243D1","6243D1","ntoskrnl.exe",0.0393,3.8314,0.0393,3.8314 "2DE541","2DE541","ntoskrnl.exe",0.0383,3.7352,0.0383,3.7352 "2DB56F","2DB56F","ntoskrnl.exe",0.0379,3.6935,0.0379,3.6935 "8AA859","8AA859","ntoskrnl.exe",0.0378,3.6804,0.0378,3.6804 "624E7F","624E7F","ntoskrnl.exe",0.0373,3.6317,0.0373,3.6317 "C55B11","C55B11","ntoskrnl.exe",0.0369,3.5950,0.0369,3.5950 "2DE61B","2DE61B","ntoskrnl.exe",0.0367,3.5746,0.0367,3.5746 "6242BC","6242BC","ntoskrnl.exe",0.0366,3.5682,0.0366,3.5682 "285422","285422","ntoskrnl.exe",0.0352,3.4276,0.0352,3.4276 "384E0C","384E0C","ntoskrnl.exe",0.0347,3.3785,0.0347,3.3785 "2DE667","2DE667","ntoskrnl.exe",0.0346,3.3716,0.0346,3.3716 "2DB182","2DB182","ntoskrnl.exe",0.0344,3.3505,0.0344,3.3505 "6242B9","6242B9","ntoskrnl.exe",0.0338,3.2978,0.0338,3.2978 "62634F","62634F","ntoskrnl.exe",0.0333,3.2463,0.0333,3.2463 "21354E","21354E","ntoskrnl.exe",0.0331,3.2208,0.0331,3.2208 "6244B8","6244B8","ntoskrnl.exe",0.0330,3.2104,0.0330,3.2104 "626340","626340","ntoskrnl.exe",0.0328,3.1947,0.0328,3.1947 "62633C","62633C","ntoskrnl.exe",0.0327,3.1841,0.0327,3.1841 "401EE9","401EE9","ntoskrnl.exe",0.0323,3.1429,0.0323,3.1429 "2DB607","2DB607","ntoskrnl.exe",0.0319,3.1099,0.0319,3.1099 "C55A93","C55A93","ntoskrnl.exe",0.0316,3.0789,0.0316,3.0789 "624C08","624C08","ntoskrnl.exe",0.0315,3.0738,0.0315,3.0738 "2DE630","2DE630","ntoskrnl.exe",0.0315,3.0669,0.0315,3.0669 "624963","624963","ntoskrnl.exe",0.0313,3.0475,0.0313,3.0475 "2DB246","2DB246","ntoskrnl.exe",0.0312,3.0352,0.0312,3.0352 "6242AD","6242AD","ntoskrnl.exe",0.0311,3.0345,0.0311,3.0345 "8B66EB","8B66EB","ntoskrnl.exe",0.0309,3.0126,0.0309,3.0126 "2DE649","2DE649","ntoskrnl.exe",0.0309,3.0067,0.0309,3.0067 "3D8BBE","3D8BBE","ntoskrnl.exe",0.0309,3.0064,0.0309,3.0064 "2DB576","2DB576","ntoskrnl.exe",0.0308,3.0057,0.0308,3.0057 "2DE7C0","2DE7C0","ntoskrnl.exe",0.0308,3.0056,0.0308,3.0056 "624C4C","624C4C","ntoskrnl.exe",0.0308,3.0054,0.0308,3.0054 "2DE59E","2DE59E","ntoskrnl.exe",0.0308,3.0043,0.0308,3.0043 "28592B","28592B","ntoskrnl.exe",0.0308,3.0040,0.0308,3.0040 "2D98DE","2D98DE","ntoskrnl.exe",0.0308,3.0024,0.0308,3.0024 "516620","516620","ntoskrnl.exe",0.0308,3.0015,0.0308,3.0015 "624A60","624A60","ntoskrnl.exe",0.0308,2.9998,0.0308,2.9998 "C55BC0","C55BC0","ntoskrnl.exe",0.0308,2.9985,0.0308,2.9985 "624B74","624B74","ntoskrnl.exe",0.0308,2.9980,0.0308,2.9980 "6249F9","6249F9","ntoskrnl.exe",0.0308,2.9968,0.0308,2.9968 "734E89","734E89","ntoskrnl.exe",0.0307,2.9952,0.0307,2.9952 "73FB75","73FB75","ntoskrnl.exe",0.0307,2.9945,0.0307,2.9945 "625339","625339","ntoskrnl.exe",0.0307,2.9944,0.0307,2.9944 "624433","624433","ntoskrnl.exe",0.0307,2.9904,0.0307,2.9904 "358E60","358E60","ntoskrnl.exe",0.0307,2.9876,0.0307,2.9876 "8B694E","8B694E","ntoskrnl.exe",0.0305,2.9758,0.0305,2.9758 "2EE549","2EE549","ntoskrnl.exe",0.0305,2.9699,0.0305,2.9699 "2DA4F6","2DA4F6","ntoskrnl.exe",0.0305,2.9683,0.0305,2.9683 "2DB195","2DB195","ntoskrnl.exe",0.0297,2.8981,0.0297,2.8981 "3F0B8E","3F0B8E","ntoskrnl.exe",0.0297,2.8897,0.0297,2.8897 "624DD8","624DD8","ntoskrnl.exe",0.0295,2.8755,0.0295,2.8755 "624B11","624B11","ntoskrnl.exe",0.0290,2.8277,0.0290,2.8277 "2406B6","2406B6","ntoskrnl.exe",0.0290,2.8238,0.0290,2.8238 "626338","626338","ntoskrnl.exe",0.0288,2.8077,0.0288,2.8077 "626EA1","626EA1","ntoskrnl.exe",0.0285,2.7808,0.0285,2.7808 "2DE6BA","2DE6BA","ntoskrnl.exe",0.0278,2.7061,0.0278,2.7061 "3E4F91","3E4F91","ntoskrnl.exe",0.0274,2.6651,0.0274,2.6651 "624B53","624B53","ntoskrnl.exe",0.0270,2.6293,0.0270,2.6293 "2DE12C","2DE12C","ntoskrnl.exe",0.0268,2.6154,0.0268,2.6154 "3F0B92","3F0B92","ntoskrnl.exe",0.0264,2.5740,0.0264,2.5740 "2DB22E","2DB22E","ntoskrnl.exe",0.0263,2.5611,0.0263,2.5611 "2DE06C","2DE06C","ntoskrnl.exe",0.0260,2.5334,0.0260,2.5334 "27D0EB","27D0EB","ntoskrnl.exe",0.0258,2.5184,0.0258,2.5184 "62797C","62797C","ntoskrnl.exe",0.0254,2.4752,0.0254,2.4752 "734743","734743","ntoskrnl.exe",0.0247,2.4074,0.0247,2.4074 "317645","317645","ntoskrnl.exe",0.0247,2.4039,0.0247,2.4039 "625330","625330","ntoskrnl.exe",0.0239,2.3271,0.0239,2.3271 "624B36","624B36","ntoskrnl.exe",0.0238,2.3217,0.0238,2.3217 "23EE17","23EE17","ntoskrnl.exe",0.0237,2.3048,0.0237,2.3048 "624E3F","624E3F","ntoskrnl.exe",0.0236,2.3021,0.0236,2.3021 "2DE609","2DE609","ntoskrnl.exe",0.0233,2.2653,0.0233,2.2653 "2DE520","2DE520","ntoskrnl.exe",0.0231,2.2472,0.0231,2.2472 "C55E92","C55E92","ntoskrnl.exe",0.0230,2.2412,0.0230,2.2412 "624BF7","624BF7","ntoskrnl.exe",0.0229,2.2305,0.0229,2.2305 "2DA1B2","2DA1B2","ntoskrnl.exe",0.0228,2.2234,0.0228,2.2234 "625341","625341","ntoskrnl.exe",0.0225,2.1882,0.0225,2.1882 "2DB257","2DB257","ntoskrnl.exe",0.0223,2.1727,0.0223,2.1727 "2DE5C1","2DE5C1","ntoskrnl.exe",0.0223,2.1682,0.0223,2.1682 "624A58","624A58","ntoskrnl.exe",0.0216,2.1082,0.0216,2.1082 "428869","428869","ntoskrnl.exe",0.0216,2.1044,0.0216,2.1044 "2DA1AA","2DA1AA","ntoskrnl.exe",0.0216,2.1043,0.0216,2.1043 "2DE60D","2DE60D","ntoskrnl.exe",0.0216,2.1026,0.0216,2.1026 "22E415","22E415","ntoskrnl.exe",0.0215,2.0950,0.0215,2.0950 "2DB57A","2DB57A","ntoskrnl.exe",0.0214,2.0819,0.0214,2.0819 "27AC40","27AC40","ntoskrnl.exe",0.0213,2.0753,0.0213,2.0753 "2EE53E","2EE53E","ntoskrnl.exe",0.0212,2.0655,0.0212,2.0655 "73402E","73402E","ntoskrnl.exe",0.0210,2.0506,0.0210,2.0506 "72CB40","72CB40","ntoskrnl.exe",0.0210,2.0454,0.0210,2.0454 "624990","624990","ntoskrnl.exe",0.0210,2.0440,0.0210,2.0440 "2F3246","2F3246","ntoskrnl.exe",0.0208,2.0303,0.0208,2.0303 "734DBE","734DBE","ntoskrnl.exe",0.0208,2.0233,0.0208,2.0233 "3D8BB3","3D8BB3","ntoskrnl.exe",0.0206,2.0102,0.0206,2.0102 "62445D","62445D","ntoskrnl.exe",0.0206,2.0099,0.0206,2.0099 "2EC877","2EC877","ntoskrnl.exe",0.0206,2.0077,0.0206,2.0077 "8B66DE","8B66DE","ntoskrnl.exe",0.0206,2.0076,0.0206,2.0076 "3FF3F5","3FF3F5","ntoskrnl.exe",0.0206,2.0028,0.0206,2.0028 "2DE652","2DE652","ntoskrnl.exe",0.0206,2.0027,0.0206,2.0027 "516673","516673","ntoskrnl.exe",0.0205,2.0018,0.0205,2.0018 "204614","204614","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "206826","206826","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "206C73","206C73","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "20EC90","20EC90","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "20ECA0","20ECA0","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2109EB","2109EB","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2129A2","2129A2","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2141E6","2141E6","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "216F5A","216F5A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "220B3D","220B3D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "22B788","22B788","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "22E1AB","22E1AB","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "22EA63","22EA63","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "23EDE3","23EDE3","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "242122","242122","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "26184C","26184C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "26E211","26E211","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "26E649","26E649","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "26F8DF","26F8DF","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "26F994","26F994","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "27118C","27118C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "27659E","27659E","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "276631","276631","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "27A401","27A401","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "27A73C","27A73C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "27C00A","27C00A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2814BF","2814BF","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA1B0","2DA1B0","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA201","2DA201","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA21E","2DA21E","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA280","2DA280","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA2E9","2DA2E9","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA72E","2DA72E","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA850","2DA850","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DA8D7","2DA8D7","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DAEB2","2DAEB2","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB178","2DB178","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB17D","2DB17D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB1A5","2DB1A5","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB1AA","2DB1AA","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB1D6","2DB1D6","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB5D8","2DB5D8","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB65C","2DB65C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DB8FB","2DB8FB","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DBE16","2DBE16","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DBE3F","2DBE3F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DBE5B","2DBE5B","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DBF5B","2DBF5B","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DDFB0","2DDFB0","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE0AF","2DE0AF","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE0B1","2DE0B1","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE0C9","2DE0C9","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE0CE","2DE0CE","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE52F","2DE52F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE530","2DE530","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE53E","2DE53E","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE546","2DE546","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE5FD","2DE5FD","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE6C3","2DE6C3","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE73D","2DE73D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE772","2DE772","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE7AA","2DE7AA","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DF976","2DF976","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2EAAF8","2EAAF8","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2EBE34","2EBE34","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2EEFF3","2EEFF3","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "316B93","316B93","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "317C81","317C81","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "318DE9","318DE9","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3191A3","3191A3","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3191E7","3191E7","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3196B4","3196B4","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3197A4","3197A4","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "32817D","32817D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "361930","361930","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "38545D","38545D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3858C4","3858C4","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "38E551","38E551","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3D8B81","3D8B81","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3D8B8F","3D8B8F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3F0E95","3F0E95","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3FC2EC","3FC2EC","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3FDD7C","3FDD7C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "3FF3DD","3FF3DD","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "401ED5","401ED5","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "420800","420800","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "42722D","42722D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "437DF3","437DF3","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "44AEE9","44AEE9","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "458F02","458F02","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "51665D","51665D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "5166F7","5166F7","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "51670B","51670B","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "516750","516750","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "516758","516758","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "51675C","51675C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "516764","516764","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624277","624277","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62429F","62429F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "6243C0","6243C0","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624469","624469","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624669","624669","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "6247D5","6247D5","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "6248E5","6248E5","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62495C","62495C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62495F","62495F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624A24","624A24","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624A41","624A41","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624BD0","624BD0","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624C1A","624C1A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624C29","624C29","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624C55","624C55","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624C58","624C58","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "624CC4","624CC4","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62530C","62530C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "625484","625484","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "626339","626339","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62633A","62633A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62656B","62656B","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "626D16","626D16","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "626F75","626F75","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62705C","62705C","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "627835","627835","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62792A","62792A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "62799F","62799F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "627A04","627A04","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "627A0A","627A0A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "7308A4","7308A4","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "734565","734565","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "73460D","73460D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "7415A0","7415A0","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "74162A","74162A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "741684","741684","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "89B3C1","89B3C1","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "8B2345","8B2345","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "8B6A7B","8B6A7B","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "8ED64E","8ED64E","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "9DAC40","9DAC40","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "9EACA9","9EACA9","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "A26F10","A26F10","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "A7533A","A7533A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55880","C55880","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55A8A","C55A8A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55AD3","C55AD3","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55B0A","C55B0A","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55B0D","C55B0D","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55BCA","C55BCA","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55E8F","C55E8F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55E9F","C55E9F","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "C55EA9","C55EA9","ntoskrnl.exe",0.0205,2.0000,0.0205,2.0000 "2DE083","2DE083","ntoskrnl.exe",0.0205,1.9945,0.0205,1.9945 "27A94F","27A94F","ntoskrnl.exe",0.0204,1.9924,0.0204,1.9924 "378296","378296","ntoskrnl.exe",0.0204,1.9915,0.0204,1.9915 "8B6AAB","8B6AAB","ntoskrnl.exe",0.0204,1.9914,0.0204,1.9914 "2EC4A6","2EC4A6","ntoskrnl.exe",0.0204,1.9847,0.0204,1.9847 "9C5B4D","9C5B4D","ntoskrnl.exe",0.0201,1.9616,0.0201,1.9616 "626C32","626C32","ntoskrnl.exe",0.0201,1.9602,0.0201,1.9602 "2DB7FF","2DB7FF","ntoskrnl.exe",0.0201,1.9570,0.0201,1.9570 "6279C0","6279C0","ntoskrnl.exe",0.0201,1.9541,0.0201,1.9541 "2DA1C5","2DA1C5","ntoskrnl.exe",0.0200,1.9490,0.0200,1.9490 "516623","516623","ntoskrnl.exe",0.0200,1.9474,0.0200,1.9474 "6254AD","6254AD","ntoskrnl.exe",0.0199,1.9376,0.0199,1.9376 "6254B7","6254B7","ntoskrnl.exe",0.0198,1.9289,0.0198,1.9289 "6242E4","6242E4","ntoskrnl.exe",0.0198,1.9282,0.0198,1.9282 "9F852A","9F852A","ntoskrnl.exe",0.0196,1.9116,0.0196,1.9116 "2766C9","2766C9","ntoskrnl.exe",0.0196,1.9094,0.0196,1.9094 "624D7D","624D7D","ntoskrnl.exe",0.0189,1.8426,0.0189,1.8426 "225E8F","225E8F","ntoskrnl.exe",0.0187,1.8266,0.0187,1.8266 "62432D","62432D","ntoskrnl.exe",0.0187,1.8228,0.0187,1.8228 "3F0B7D","3F0B7D","ntoskrnl.exe",0.0184,1.7974,0.0184,1.7974 "2409D2","2409D2","ntoskrnl.exe",0.0184,1.7928,0.0184,1.7928 "27495C","27495C","ntoskrnl.exe",0.0183,1.7815,0.0183,1.7815 "2DB26E","2DB26E","ntoskrnl.exe",0.0183,1.7795,0.0183,1.7795 "626CC5","626CC5","ntoskrnl.exe",0.0182,1.7708,0.0182,1.7708 "27664F","27664F","ntoskrnl.exe",0.0180,1.7522,0.0180,1.7522 "2DB269","2DB269","ntoskrnl.exe",0.0179,1.7437,0.0179,1.7437 "27D07D","27D07D","ntoskrnl.exe",0.0179,1.7392,0.0179,1.7392 "417BA6","417BA6","ntoskrnl.exe",0.0177,1.7220,0.0177,1.7220 "7349A4","7349A4","ntoskrnl.exe",0.0175,1.7054,0.0175,1.7054 "624AE4","624AE4","ntoskrnl.exe",0.0174,1.6993,0.0174,1.6993 "3F4E76","3F4E76","ntoskrnl.exe",0.0174,1.6936,0.0174,1.6936 "624422","624422","ntoskrnl.exe",0.0173,1.6869,0.0173,1.6869 "2D9816","2D9816","ntoskrnl.exe",0.0172,1.6796,0.0172,1.6796 "23F09B","23F09B","ntoskrnl.exe",0.0171,1.6654,0.0171,1.6654 "624C96","624C96","ntoskrnl.exe",0.0170,1.6611,0.0170,1.6611 "624E36","624E36","ntoskrnl.exe",0.0170,1.6589,0.0170,1.6589 "6279F8","6279F8","ntoskrnl.exe",0.0168,1.6350,0.0168,1.6350 "8AA865","8AA865","ntoskrnl.exe",0.0167,1.6309,0.0167,1.6309 "627A27","627A27","ntoskrnl.exe",0.0167,1.6255,0.0167,1.6255 "624ABE","624ABE","ntoskrnl.exe",0.0166,1.6205,0.0166,1.6205 "3D8D25","3D8D25","ntoskrnl.exe",0.0163,1.5892,0.0163,1.5892 "2DE5C9","2DE5C9","ntoskrnl.exe",0.0162,1.5763,0.0162,1.5763 "2147C9","2147C9","ntoskrnl.exe",0.0161,1.5642,0.0161,1.5642 "260C33","260C33","ntoskrnl.exe",0.0159,1.5480,0.0159,1.5480 "2DE628","2DE628","ntoskrnl.exe",0.0158,1.5427,0.0158,1.5427 "22E498","22E498","ntoskrnl.exe",0.0158,1.5352,0.0158,1.5352 "318E9B","318E9B","ntoskrnl.exe",0.0157,1.5254,0.0157,1.5254 "3B5825","3B5825","ntoskrnl.exe",0.0156,1.5195,0.0156,1.5195 "734747","734747","ntoskrnl.exe",0.0156,1.5156,0.0156,1.5156 "624461","624461","ntoskrnl.exe",0.0155,1.5136,0.0155,1.5136 "23F420","23F420","ntoskrnl.exe",0.0154,1.5031,0.0154,1.5031 "206D13","206D13","ntoskrnl.exe",0.0153,1.4919,0.0153,1.4919 "3F0ACA","3F0ACA","ntoskrnl.exe",0.0152,1.4795,0.0152,1.4795 "627A0F","627A0F","ntoskrnl.exe",0.0151,1.4746,0.0151,1.4746 "72CBBC","72CBBC","ntoskrnl.exe",0.0150,1.4653,0.0150,1.4653 "8A0459","8A0459","ntoskrnl.exe",0.0150,1.4602,0.0150,1.4602 "419292","419292","ntoskrnl.exe",0.0150,1.4585,0.0150,1.4585 "3ACEA5","3ACEA5","ntoskrnl.exe",0.0150,1.4573,0.0150,1.4573 "73466A","73466A","ntoskrnl.exe",0.0149,1.4565,0.0149,1.4565 "6253C8","6253C8","ntoskrnl.exe",0.0149,1.4537,0.0149,1.4537 "3197B2","3197B2","ntoskrnl.exe",0.0149,1.4469,0.0149,1.4469 "2DE5D0","2DE5D0","ntoskrnl.exe",0.0148,1.4458,0.0148,1.4458 "35AD7D","35AD7D","ntoskrnl.exe",0.0148,1.4431,0.0148,1.4431 "624D6B","624D6B","ntoskrnl.exe",0.0148,1.4418,0.0148,1.4418 "516627","516627","ntoskrnl.exe",0.0148,1.4415,0.0148,1.4415 "3AA16F","3AA16F","ntoskrnl.exe",0.0148,1.4408,0.0148,1.4408 "734D75","734D75","ntoskrnl.exe",0.0147,1.4336,0.0147,1.4336 "8A614B","8A614B","ntoskrnl.exe",0.0147,1.4302,0.0147,1.4302 "626EC1","626EC1","ntoskrnl.exe",0.0146,1.4237,0.0146,1.4237 "23099C","23099C","ntoskrnl.exe",0.0146,1.4184,0.0146,1.4184 "6254AA","6254AA","ntoskrnl.exe",0.0145,1.4146,0.0145,1.4146 "75498A","75498A","ntoskrnl.exe",0.0144,1.4065,0.0144,1.4065 "32822A","32822A","ntoskrnl.exe",0.0144,1.4020,0.0144,1.4020 "47CB95","47CB95","ntoskrnl.exe",0.0142,1.3845,0.0142,1.3845 "62645C","62645C","ntoskrnl.exe",0.0141,1.3718,0.0141,1.3718 "206F2D","206F2D","ntoskrnl.exe",0.0140,1.3624,0.0140,1.3624 "2127B0","2127B0","ntoskrnl.exe",0.0139,1.3556,0.0139,1.3556 "44AE65","44AE65","ntoskrnl.exe",0.0137,1.3356,0.0137,1.3356 "2E64B3","2E64B3","ntoskrnl.exe",0.0136,1.3243,0.0136,1.3243 "38EE9D","38EE9D","ntoskrnl.exe",0.0136,1.3233,0.0136,1.3233 "276683","276683","ntoskrnl.exe",0.0136,1.3216,0.0136,1.3216 "3F0AD2","3F0AD2","ntoskrnl.exe",0.0134,1.3052,0.0134,1.3052 "2DE53A","2DE53A","ntoskrnl.exe",0.0134,1.3032,0.0134,1.3032 "21AE0E","21AE0E","ntoskrnl.exe",0.0134,1.3011,0.0134,1.3011 "2D0FF5","2D0FF5","ntoskrnl.exe",0.0133,1.2973,0.0133,1.2973 "23CCE5","23CCE5","ntoskrnl.exe",0.0132,1.2883,0.0132,1.2883 "275158","275158","ntoskrnl.exe",0.0131,1.2806,0.0131,1.2806 "27D19E","27D19E","ntoskrnl.exe",0.0130,1.2674,0.0130,1.2674 "626EAD","626EAD","ntoskrnl.exe",0.0129,1.2569,0.0129,1.2569 "319508","319508","ntoskrnl.exe",0.0129,1.2566,0.0129,1.2566 "626C48","626C48","ntoskrnl.exe",0.0129,1.2566,0.0129,1.2566 "2DE5D7","2DE5D7","ntoskrnl.exe",0.0128,1.2505,0.0128,1.2505 "3233DA","3233DA","ntoskrnl.exe",0.0127,1.2407,0.0127,1.2407 "754A5D","754A5D","ntoskrnl.exe",0.0126,1.2258,0.0126,1.2258 "62793D","62793D","ntoskrnl.exe",0.0126,1.2233,0.0126,1.2233 "2DE5A1","2DE5A1","ntoskrnl.exe",0.0125,1.2214,0.0125,1.2214 "417C77","417C77","ntoskrnl.exe",0.0125,1.2196,0.0125,1.2196 "31769C","31769C","ntoskrnl.exe",0.0124,1.2116,0.0124,1.2116 "35EF07","35EF07","ntoskrnl.exe",0.0124,1.2049,0.0124,1.2049 "269A4F","269A4F","ntoskrnl.exe",0.0123,1.1949,0.0123,1.1949 "38E564","38E564","ntoskrnl.exe",0.0122,1.1887,0.0122,1.1887 "2DBE88","2DBE88","ntoskrnl.exe",0.0122,1.1864,0.0122,1.1864 "626E80","626E80","ntoskrnl.exe",0.0121,1.1760,0.0121,1.1760 "277FFD","277FFD","ntoskrnl.exe",0.0120,1.1718,0.0120,1.1718 "62452F","62452F","ntoskrnl.exe",0.0119,1.1629,0.0119,1.1629 "624C5C","624C5C","ntoskrnl.exe",0.0118,1.1472,0.0118,1.1472 "626472","626472","ntoskrnl.exe",0.0117,1.1428,0.0117,1.1428 "211E09","211E09","ntoskrnl.exe",0.0117,1.1422,0.0117,1.1422 "2F3622","2F3622","ntoskrnl.exe",0.0114,1.1132,0.0114,1.1132 "38EF01","38EF01","ntoskrnl.exe",0.0114,1.1113,0.0114,1.1113 "6244AA","6244AA","ntoskrnl.exe",0.0114,1.1113,0.0114,1.1113 "2DB24E","2DB24E","ntoskrnl.exe",0.0112,1.0952,0.0112,1.0952 "26DA42","26DA42","ntoskrnl.exe",0.0112,1.0891,0.0112,1.0891 "624369","624369","ntoskrnl.exe",0.0110,1.0747,0.0110,1.0747 "2EB18D","2EB18D","ntoskrnl.exe",0.0110,1.0722,0.0110,1.0722 "62647D","62647D","ntoskrnl.exe",0.0110,1.0717,0.0110,1.0717 "625406","625406","ntoskrnl.exe",0.0110,1.0715,0.0110,1.0715 "26E50B","26E50B","ntoskrnl.exe",0.0109,1.0661,0.0109,1.0661 "624AC4","624AC4","ntoskrnl.exe",0.0109,1.0656,0.0109,1.0656 "2DE0B8","2DE0B8","ntoskrnl.exe",0.0109,1.0635,0.0109,1.0635 "2DE6B2","2DE6B2","ntoskrnl.exe",0.0109,1.0625,0.0109,1.0625 "4230D5","4230D5","ntoskrnl.exe",0.0109,1.0596,0.0109,1.0596 "73460B","73460B","ntoskrnl.exe",0.0109,1.0588,0.0109,1.0588 "624AB1","624AB1","ntoskrnl.exe",0.0109,1.0578,0.0109,1.0578 "3A9546","3A9546","ntoskrnl.exe",0.0108,1.0524,0.0108,1.0524 "3E4FA1","3E4FA1","ntoskrnl.exe",0.0107,1.0460,0.0107,1.0460 "27B4B6","27B4B6","ntoskrnl.exe",0.0107,1.0434,0.0107,1.0434 "22E369","22E369","ntoskrnl.exe",0.0107,1.0393,0.0107,1.0393 "2DB6DC","2DB6DC","ntoskrnl.exe",0.0106,1.0375,0.0106,1.0375 "27D165","27D165","ntoskrnl.exe",0.0106,1.0310,0.0106,1.0310 "2DBF42","2DBF42","ntoskrnl.exe",0.0106,1.0285,0.0106,1.0285 "4535EB","4535EB","ntoskrnl.exe",0.0106,1.0280,0.0106,1.0280 "2858AD","2858AD","ntoskrnl.exe",0.0105,1.0270,0.0105,1.0270 "2EB5ED","2EB5ED","ntoskrnl.exe",0.0105,1.0268,0.0105,1.0268 "741693","741693","ntoskrnl.exe",0.0105,1.0268,0.0105,1.0268 "2B7678","2B7678","ntoskrnl.exe",0.0105,1.0259,0.0105,1.0259 "2E1439","2E1439","ntoskrnl.exe",0.0105,1.0254,0.0105,1.0254 "2690E2","2690E2","ntoskrnl.exe",0.0105,1.0242,0.0105,1.0242 "2DBA1F","2DBA1F","ntoskrnl.exe",0.0105,1.0204,0.0105,1.0204 "624A9E","624A9E","ntoskrnl.exe",0.0105,1.0202,0.0105,1.0202 "404468","404468","ntoskrnl.exe",0.0105,1.0193,0.0105,1.0193 "2EDBF5","2EDBF5","ntoskrnl.exe",0.0104,1.0180,0.0104,1.0180 "3BE20D","3BE20D","ntoskrnl.exe",0.0104,1.0157,0.0104,1.0157 "3AB8A8","3AB8A8","ntoskrnl.exe",0.0104,1.0154,0.0104,1.0154 "2DC18A","2DC18A","ntoskrnl.exe",0.0104,1.0147,0.0104,1.0147 "2E65EF","2E65EF","ntoskrnl.exe",0.0104,1.0147,0.0104,1.0147 "270C38","270C38","ntoskrnl.exe",0.0104,1.0146,0.0104,1.0146 "2F528D","2F528D","ntoskrnl.exe",0.0104,1.0143,0.0104,1.0143 "624328","624328","ntoskrnl.exe",0.0104,1.0142,0.0104,1.0142 "318EA4","318EA4","ntoskrnl.exe",0.0104,1.0141,0.0104,1.0141 "2DB1DA","2DB1DA","ntoskrnl.exe",0.0104,1.0139,0.0104,1.0139 "2A6DC2","2A6DC2","ntoskrnl.exe",0.0104,1.0138,0.0104,1.0138 "2F85BA","2F85BA","ntoskrnl.exe",0.0104,1.0137,0.0104,1.0137 "3E5168","3E5168","ntoskrnl.exe",0.0104,1.0136,0.0104,1.0136 "22D210","22D210","ntoskrnl.exe",0.0104,1.0133,0.0104,1.0133 "2EA325","2EA325","ntoskrnl.exe",0.0104,1.0131,0.0104,1.0131 "385D5D","385D5D","ntoskrnl.exe",0.0104,1.0130,0.0104,1.0130 "324D5B","324D5B","ntoskrnl.exe",0.0104,1.0126,0.0104,1.0126 "2DA1F6","2DA1F6","ntoskrnl.exe",0.0104,1.0123,0.0104,1.0123 "9DAC51","9DAC51","ntoskrnl.exe",0.0104,1.0123,0.0104,1.0123 "2E6808","2E6808","ntoskrnl.exe",0.0104,1.0120,0.0104,1.0120 "3E4AF7","3E4AF7","ntoskrnl.exe",0.0104,1.0118,0.0104,1.0118 "51F32B","51F32B","ntoskrnl.exe",0.0104,1.0118,0.0104,1.0118 "734723","734723","ntoskrnl.exe",0.0104,1.0118,0.0104,1.0118 "324D11","324D11","ntoskrnl.exe",0.0104,1.0114,0.0104,1.0114 "6242CB","6242CB","ntoskrnl.exe",0.0104,1.0110,0.0104,1.0110 "26081E","26081E","ntoskrnl.exe",0.0104,1.0102,0.0104,1.0102 "3781DD","3781DD","ntoskrnl.exe",0.0104,1.0102,0.0104,1.0102 "8A566C","8A566C","ntoskrnl.exe",0.0104,1.0102,0.0104,1.0102 "8F2CDB","8F2CDB","ntoskrnl.exe",0.0104,1.0101,0.0104,1.0101 "3A15FC","3A15FC","ntoskrnl.exe",0.0104,1.0099,0.0104,1.0099 "7416C8","7416C8","ntoskrnl.exe",0.0104,1.0095,0.0104,1.0095 "3782EA","3782EA","ntoskrnl.exe",0.0104,1.0092,0.0104,1.0092 "229038","229038","ntoskrnl.exe",0.0104,1.0086,0.0104,1.0086 "22EF4A","22EF4A","ntoskrnl.exe",0.0103,1.0077,0.0103,1.0077 "2DE612","2DE612","ntoskrnl.exe",0.0103,1.0077,0.0103,1.0077 "2DB014","2DB014","ntoskrnl.exe",0.0103,1.0076,0.0103,1.0076 "43CCA9","43CCA9","ntoskrnl.exe",0.0103,1.0074,0.0103,1.0074 "624A9B","624A9B","ntoskrnl.exe",0.0103,1.0074,0.0103,1.0074 "9F8538","9F8538","ntoskrnl.exe",0.0103,1.0072,0.0103,1.0072 "204A3A","204A3A","ntoskrnl.exe",0.0103,1.0070,0.0103,1.0070 "62632D","62632D","ntoskrnl.exe",0.0103,1.0070,0.0103,1.0070 "205732","205732","ntoskrnl.exe",0.0103,1.0069,0.0103,1.0069 "220C07","220C07","ntoskrnl.exe",0.0103,1.0069,0.0103,1.0069 "516685","516685","ntoskrnl.exe",0.0103,1.0069,0.0103,1.0069 "27D0DD","27D0DD","ntoskrnl.exe",0.0103,1.0067,0.0103,1.0067 "624C0D","624C0D","ntoskrnl.exe",0.0103,1.0067,0.0103,1.0067 "3FD851","3FD851","ntoskrnl.exe",0.0103,1.0066,0.0103,1.0066 "2DA1CA","2DA1CA","ntoskrnl.exe",0.0103,1.0061,0.0103,1.0061 "B72B8A","B72B8A","ntoskrnl.exe",0.0103,1.0059,0.0103,1.0059 "212801","212801","ntoskrnl.exe",0.0103,1.0057,0.0103,1.0057 "247AEC","247AEC","ntoskrnl.exe",0.0103,1.0057,0.0103,1.0057 "2A6DB9","2A6DB9","ntoskrnl.exe",0.0103,1.0054,0.0103,1.0054 "2DE762","2DE762","ntoskrnl.exe",0.0103,1.0051,0.0103,1.0051 "624E32","624E32","ntoskrnl.exe",0.0103,1.0051,0.0103,1.0051 "627823","627823","ntoskrnl.exe",0.0103,1.0051,0.0103,1.0051 "627059","627059","ntoskrnl.exe",0.0103,1.0047,0.0103,1.0047 "32359E","32359E","ntoskrnl.exe",0.0103,1.0046,0.0103,1.0046 "277436","277436","ntoskrnl.exe",0.0103,1.0044,0.0103,1.0044 "2EC4DA","2EC4DA","ntoskrnl.exe",0.0103,1.0044,0.0103,1.0044 "734DA0","734DA0","ntoskrnl.exe",0.0103,1.0044,0.0103,1.0044 "27D47C","27D47C","ntoskrnl.exe",0.0103,1.0043,0.0103,1.0043 "2EE4F5","2EE4F5","ntoskrnl.exe",0.0103,1.0043,0.0103,1.0043 "3FDD8C","3FDD8C","ntoskrnl.exe",0.0103,1.0043,0.0103,1.0043 "40D881","40D881","ntoskrnl.exe",0.0103,1.0042,0.0103,1.0042 "624DF4","624DF4","ntoskrnl.exe",0.0103,1.0042,0.0103,1.0042 "2A53D7","2A53D7","ntoskrnl.exe",0.0103,1.0041,0.0103,1.0041 "351B80","351B80","ntoskrnl.exe",0.0103,1.0041,0.0103,1.0041 "516731","516731","ntoskrnl.exe",0.0103,1.0041,0.0103,1.0041 "2C536F","2C536F","ntoskrnl.exe",0.0103,1.0038,0.0103,1.0038 "230FDF","230FDF","ntoskrnl.exe",0.0103,1.0036,0.0103,1.0036 "2B6921","2B6921","ntoskrnl.exe",0.0103,1.0036,0.0103,1.0036 "3F0E5D","3F0E5D","ntoskrnl.exe",0.0103,1.0035,0.0103,1.0035 "2DE66E","2DE66E","ntoskrnl.exe",0.0103,1.0034,0.0103,1.0034 "4481A1","4481A1","ntoskrnl.exe",0.0103,1.0032,0.0103,1.0032 "37829C","37829C","ntoskrnl.exe",0.0103,1.0031,0.0103,1.0031 "42C1D3","42C1D3","ntoskrnl.exe",0.0103,1.0031,0.0103,1.0031 "51DF3A","51DF3A","ntoskrnl.exe",0.0103,1.0030,0.0103,1.0030 "2DE79E","2DE79E","ntoskrnl.exe",0.0103,1.0028,0.0103,1.0028 "318E06","318E06","ntoskrnl.exe",0.0103,1.0028,0.0103,1.0028 "626D6B","626D6B","ntoskrnl.exe",0.0103,1.0028,0.0103,1.0028 "2E65D4","2E65D4","ntoskrnl.exe",0.0103,1.0027,0.0103,1.0027 "2EC789","2EC789","ntoskrnl.exe",0.0103,1.0027,0.0103,1.0027 "733EF9","733EF9","ntoskrnl.exe",0.0103,1.0025,0.0103,1.0025 "21E808","21E808","ntoskrnl.exe",0.0103,1.0023,0.0103,1.0023 "625400","625400","ntoskrnl.exe",0.0103,1.0023,0.0103,1.0023 "3F0D05","3F0D05","ntoskrnl.exe",0.0103,1.0022,0.0103,1.0022 "51662B","51662B","ntoskrnl.exe",0.0103,1.0020,0.0103,1.0020 "625334","625334","ntoskrnl.exe",0.0103,1.0020,0.0103,1.0020 "2F31E7","2F31E7","ntoskrnl.exe",0.0103,1.0018,0.0103,1.0018 "277DFA","277DFA","ntoskrnl.exe",0.0103,1.0017,0.0103,1.0017 "2DAC84","2DAC84","ntoskrnl.exe",0.0103,1.0015,0.0103,1.0015 "2EC47F","2EC47F","ntoskrnl.exe",0.0103,1.0015,0.0103,1.0015 "2402F6","2402F6","ntoskrnl.exe",0.0103,1.0012,0.0103,1.0012 "73FCF5","73FCF5","ntoskrnl.exe",0.0103,1.0010,0.0103,1.0010 "2E63E6","2E63E6","ntoskrnl.exe",0.0103,1.0007,0.0103,1.0007 "2EDB81","2EDB81","ntoskrnl.exe",0.0103,1.0005,0.0103,1.0005 "3F0B4C","3F0B4C","ntoskrnl.exe",0.0103,1.0004,0.0103,1.0004 "205875","205875","ntoskrnl.exe",0.0103,1.0002,0.0103,1.0002 "2EC476","2EC476","ntoskrnl.exe",0.0103,1.0002,0.0103,1.0002 "9EACEF","9EACEF","ntoskrnl.exe",0.0103,1.0000,0.0103,1.0000 "2DBECA","2DBECA","ntoskrnl.exe",0.0103,0.9999,0.0103,0.9999 "8B6B6E","8B6B6E","ntoskrnl.exe",0.0103,0.9997,0.0103,0.9997 "9505B6","9505B6","ntoskrnl.exe",0.0103,0.9997,0.0103,0.9997 "358DF2","358DF2","ntoskrnl.exe",0.0103,0.9996,0.0103,0.9996 "627061","627061","ntoskrnl.exe",0.0103,0.9994,0.0103,0.9994 "2E38DF","2E38DF","ntoskrnl.exe",0.0103,0.9993,0.0103,0.9993 "2EC42E","2EC42E","ntoskrnl.exe",0.0103,0.9992,0.0103,0.9992 "2EDBBD","2EDBBD","ntoskrnl.exe",0.0103,0.9992,0.0103,0.9992 "2DE069","2DE069","ntoskrnl.exe",0.0103,0.9988,0.0103,0.9988 "3256AE","3256AE","ntoskrnl.exe",0.0102,0.9984,0.0102,0.9984 "9C88E5","9C88E5","ntoskrnl.exe",0.0102,0.9983,0.0102,0.9983 "8B67C6","8B67C6","ntoskrnl.exe",0.0102,0.9982,0.0102,0.9982 "734D93","734D93","ntoskrnl.exe",0.0102,0.9981,0.0102,0.9981 "8B6BD2","8B6BD2","ntoskrnl.exe",0.0102,0.9981,0.0102,0.9981 "32BD7A","32BD7A","ntoskrnl.exe",0.0102,0.9980,0.0102,0.9980 "3FA436","3FA436","ntoskrnl.exe",0.0102,0.9980,0.0102,0.9980 "429CA3","429CA3","ntoskrnl.exe",0.0102,0.9979,0.0102,0.9979 "8B677D","8B677D","ntoskrnl.exe",0.0102,0.9979,0.0102,0.9979 "9B7098","9B7098","ntoskrnl.exe",0.0102,0.9974,0.0102,0.9974 "9EAD00","9EAD00","ntoskrnl.exe",0.0102,0.9974,0.0102,0.9974 "32551B","32551B","ntoskrnl.exe",0.0102,0.9971,0.0102,0.9971 "247A8D","247A8D","ntoskrnl.exe",0.0102,0.9970,0.0102,0.9970 "C55EAF","C55EAF","ntoskrnl.exe",0.0102,0.9970,0.0102,0.9970 "8B69E3","8B69E3","ntoskrnl.exe",0.0102,0.9969,0.0102,0.9969 "2DB205","2DB205","ntoskrnl.exe",0.0102,0.9965,0.0102,0.9965 "9505BD","9505BD","ntoskrnl.exe",0.0102,0.9962,0.0102,0.9962 "2B687E","2B687E","ntoskrnl.exe",0.0102,0.9958,0.0102,0.9958 "C4E311","C4E311","ntoskrnl.exe",0.0102,0.9953,0.0102,0.9953 "337266","337266","ntoskrnl.exe",0.0102,0.9946,0.0102,0.9946 "8A563F","8A563F","ntoskrnl.exe",0.0102,0.9946,0.0102,0.9946 "22EE3F","22EE3F","ntoskrnl.exe",0.0102,0.9945,0.0102,0.9945 "C4EB24","C4EB24","ntoskrnl.exe",0.0102,0.9940,0.0102,0.9940 "27B82E","27B82E","ntoskrnl.exe",0.0102,0.9932,0.0102,0.9932 "353EBD","353EBD","ntoskrnl.exe",0.0102,0.9930,0.0102,0.9930 "35197E","35197E","ntoskrnl.exe",0.0102,0.9925,0.0102,0.9925 "2090FB","2090FB","ntoskrnl.exe",0.0102,0.9920,0.0102,0.9920 "2B5ED0","2B5ED0","ntoskrnl.exe",0.0102,0.9917,0.0102,0.9917 "2C559A","2C559A","ntoskrnl.exe",0.0102,0.9916,0.0102,0.9916 "7415E8","7415E8","ntoskrnl.exe",0.0102,0.9908,0.0102,0.9908 "62793F","62793F","ntoskrnl.exe",0.0101,0.9884,0.0101,0.9884 "27B4AF","27B4AF","ntoskrnl.exe",0.0101,0.9872,0.0101,0.9872 "7418E3","7418E3","ntoskrnl.exe",0.0101,0.9813,0.0101,0.9813 "C55B74","C55B74","ntoskrnl.exe",0.0101,0.9809,0.0101,0.9809 "26F560","26F560","ntoskrnl.exe",0.0100,0.9786,0.0100,0.9786 "2DA1AF","2DA1AF","ntoskrnl.exe",0.0100,0.9782,0.0100,0.9782 "90AB46","90AB46","ntoskrnl.exe",0.0100,0.9734,0.0100,0.9734 "2F6FFE","2F6FFE","ntoskrnl.exe",0.0100,0.9709,0.0100,0.9709 "2DE10E","2DE10E","ntoskrnl.exe",0.0100,0.9699,0.0100,0.9699 "734DAE","734DAE","ntoskrnl.exe",0.0099,0.9643,0.0099,0.9643 "44AEC3","44AEC3","ntoskrnl.exe",0.0098,0.9557,0.0098,0.9557 "206F5C","206F5C","ntoskrnl.exe",0.0098,0.9501,0.0098,0.9501 "624A17","624A17","ntoskrnl.exe",0.0097,0.9470,0.0097,0.9470 "73474D","73474D","ntoskrnl.exe",0.0097,0.9442,0.0097,0.9442 "2DC22B","2DC22B","ntoskrnl.exe",0.0096,0.9323,0.0096,0.9323 "6243FC","6243FC","ntoskrnl.exe",0.0094,0.9189,0.0094,0.9189 "624B7B","624B7B","ntoskrnl.exe",0.0094,0.9141,0.0094,0.9141 "6253F8","6253F8","ntoskrnl.exe",0.0093,0.9061,0.0093,0.9061 "31F681","31F681","ntoskrnl.exe",0.0092,0.8995,0.0092,0.8995 "288C96","288C96","ntoskrnl.exe",0.0092,0.8966,0.0092,0.8966 "2E0223","2E0223","ntoskrnl.exe",0.0091,0.8884,0.0091,0.8884 "316A57","316A57","ntoskrnl.exe",0.0091,0.8833,0.0091,0.8833 "20067C","20067C","ntoskrnl.exe",0.0089,0.8675,0.0089,0.8675 "22E156","22E156","ntoskrnl.exe",0.0088,0.8583,0.0088,0.8583 "9B3C82","9B3C82","ntoskrnl.exe",0.0088,0.8526,0.0088,0.8526 "3FF3E7","3FF3E7","ntoskrnl.exe",0.0087,0.8521,0.0087,0.8521 "5166D0","5166D0","ntoskrnl.exe",0.0086,0.8371,0.0086,0.8371 "62451A","62451A","ntoskrnl.exe",0.0084,0.8207,0.0084,0.8207 "AA20AC","AA20AC","ntoskrnl.exe",0.0084,0.8206,0.0084,0.8206 "2DB1F8","2DB1F8","ntoskrnl.exe",0.0084,0.8172,0.0084,0.8172 "417CF1","417CF1","ntoskrnl.exe",0.0083,0.8099,0.0083,0.8099 "624313","624313","ntoskrnl.exe",0.0083,0.8085,0.0083,0.8085 "624BA6","624BA6","ntoskrnl.exe",0.0083,0.8068,0.0083,0.8068 "624310","624310","ntoskrnl.exe",0.0080,0.7841,0.0080,0.7841 "45EB7B","45EB7B","ntoskrnl.exe",0.0080,0.7788,0.0080,0.7788 "222A22","222A22","ntoskrnl.exe",0.0080,0.7756,0.0080,0.7756 "8A04DF","8A04DF","ntoskrnl.exe",0.0079,0.7681,0.0079,0.7681 "9074BF","9074BF","ntoskrnl.exe",0.0078,0.7593,0.0078,0.7593 "213404","213404","ntoskrnl.exe",0.0078,0.7562,0.0078,0.7562 "432030","432030","ntoskrnl.exe",0.0078,0.7554,0.0078,0.7554 "624E6C","624E6C","ntoskrnl.exe",0.0078,0.7552,0.0078,0.7552 "23ED65","23ED65","ntoskrnl.exe",0.0078,0.7551,0.0078,0.7551 "624ADE","624ADE","ntoskrnl.exe",0.0077,0.7528,0.0077,0.7528 "2DE020","2DE020","ntoskrnl.exe",0.0076,0.7406,0.0076,0.7406 "C55A80","C55A80","ntoskrnl.exe",0.0076,0.7396,0.0076,0.7396 "2DE07F","2DE07F","ntoskrnl.exe",0.0075,0.7316,0.0075,0.7316 "A5833B","A5833B","ntoskrnl.exe",0.0075,0.7291,0.0075,0.7291 "212F49","212F49","ntoskrnl.exe",0.0072,0.7045,0.0072,0.7045 "3AD2F6","3AD2F6","ntoskrnl.exe",0.0071,0.6957,0.0071,0.6957 "243A70","243A70","ntoskrnl.exe",0.0071,0.6939,0.0071,0.6939 "2DE736","2DE736","ntoskrnl.exe",0.0070,0.6778,0.0070,0.6778 "319C7C","319C7C","ntoskrnl.exe",0.0069,0.6746,0.0069,0.6746 "6244A1","6244A1","ntoskrnl.exe",0.0069,0.6698,0.0069,0.6698 "624C3A","624C3A","ntoskrnl.exe",0.0068,0.6653,0.0068,0.6653 "625411","625411","ntoskrnl.exe",0.0068,0.6613,0.0068,0.6613 "62543F","62543F","ntoskrnl.exe",0.0068,0.6581,0.0068,0.6581 "22DF98","22DF98","ntoskrnl.exe",0.0067,0.6570,0.0067,0.6570 "401EDF","401EDF","ntoskrnl.exe",0.0066,0.6400,0.0066,0.6400 "516722","516722","ntoskrnl.exe",0.0066,0.6388,0.0066,0.6388 "2DAD0A","2DAD0A","ntoskrnl.exe",0.0063,0.6164,0.0063,0.6164 "327C77","327C77","ntoskrnl.exe",0.0062,0.6040,0.0062,0.6040 "2DB5C4","2DB5C4","ntoskrnl.exe",0.0062,0.6006,0.0062,0.6006 "2DB200","2DB200","ntoskrnl.exe",0.0061,0.5961,0.0061,0.5961 "8B6723","8B6723","ntoskrnl.exe",0.0061,0.5961,0.0061,0.5961 "73B653","73B653","ntoskrnl.exe",0.0061,0.5905,0.0061,0.5905 "27BEEA","27BEEA","ntoskrnl.exe",0.0061,0.5895,0.0061,0.5895 "2DC367","2DC367","ntoskrnl.exe",0.0060,0.5835,0.0060,0.5835 "624389","624389","ntoskrnl.exe",0.0060,0.5805,0.0060,0.5805 "626CB4","626CB4","ntoskrnl.exe",0.0058,0.5689,0.0058,0.5689 "C55ECF","C55ECF","ntoskrnl.exe",0.0058,0.5679,0.0058,0.5679 "26AB73","26AB73","ntoskrnl.exe",0.0057,0.5583,0.0057,0.5583 "2818BA","2818BA","ntoskrnl.exe",0.0057,0.5569,0.0057,0.5569 "2DB0B5","2DB0B5","ntoskrnl.exe",0.0057,0.5558,0.0057,0.5558 "913BA0","913BA0","ntoskrnl.exe",0.0055,0.5360,0.0055,0.5360 "516705","516705","ntoskrnl.exe",0.0055,0.5342,0.0055,0.5342 "3D8D2F","3D8D2F","ntoskrnl.exe",0.0055,0.5329,0.0055,0.5329 "51663F","51663F","ntoskrnl.exe",0.0055,0.5315,0.0055,0.5315 "2E1280","2E1280","ntoskrnl.exe",0.0055,0.5314,0.0055,0.5314 "204297","204297","ntoskrnl.exe",0.0053,0.5149,0.0053,0.5149 "2DE0BC","2DE0BC","ntoskrnl.exe",0.0053,0.5143,0.0053,0.5143 "626337","626337","ntoskrnl.exe",0.0052,0.5082,0.0052,0.5082 "2DB20F","2DB20F","ntoskrnl.exe",0.0052,0.5023,0.0052,0.5023 "6279FE","6279FE","ntoskrnl.exe",0.0050,0.4887,0.0050,0.4887 "2074F9","2074F9","ntoskrnl.exe",0.0050,0.4881,0.0050,0.4881 "627932","627932","ntoskrnl.exe",0.0050,0.4838,0.0050,0.4838 "73450B","73450B","ntoskrnl.exe",0.0049,0.4806,0.0049,0.4806 "51673E","51673E","ntoskrnl.exe",0.0049,0.4755,0.0049,0.4755 "326204","326204","ntoskrnl.exe",0.0047,0.4598,0.0047,0.4598 "626C1F","626C1F","ntoskrnl.exe",0.0047,0.4557,0.0047,0.4557 "7269E9","7269E9","ntoskrnl.exe",0.0046,0.4526,0.0046,0.4526 "317A2F","317A2F","ntoskrnl.exe",0.0046,0.4435,0.0046,0.4435 "6279E1","6279E1","ntoskrnl.exe",0.0045,0.4390,0.0045,0.4390 "2DDB50","2DDB50","ntoskrnl.exe",0.0043,0.4218,0.0043,0.4218 "3E4F8E","3E4F8E","ntoskrnl.exe",0.0043,0.4149,0.0043,0.4149 "206232","206232","ntoskrnl.exe",0.0042,0.4138,0.0042,0.4138 "2DE7C5","2DE7C5","ntoskrnl.exe",0.0042,0.4102,0.0042,0.4102 "8AA86F","8AA86F","ntoskrnl.exe",0.0042,0.4058,0.0042,0.4058 "2DFC8B","2DFC8B","ntoskrnl.exe",0.0041,0.4003,0.0041,0.4003 "6242FE","6242FE","ntoskrnl.exe",0.0041,0.3973,0.0041,0.3973 "2DA1BA","2DA1BA","ntoskrnl.exe",0.0041,0.3963,0.0041,0.3963 "51674B","51674B","ntoskrnl.exe",0.0040,0.3928,0.0040,0.3928 "2DA1A0","2DA1A0","ntoskrnl.exe",0.0040,0.3905,0.0040,0.3905 "212A36","212A36","ntoskrnl.exe",0.0039,0.3825,0.0039,0.3825 "2056D0","2056D0","ntoskrnl.exe",0.0038,0.3733,0.0038,0.3733 "6279E4","6279E4","ntoskrnl.exe",0.0038,0.3654,0.0038,0.3654 "426865","426865","ntoskrnl.exe",0.0037,0.3610,0.0037,0.3610 "624B55","624B55","ntoskrnl.exe",0.0037,0.3587,0.0037,0.3587 "C55BCD","C55BCD","ntoskrnl.exe",0.0036,0.3492,0.0036,0.3492 "221282","221282","ntoskrnl.exe",0.0035,0.3454,0.0035,0.3454 "240F1D","240F1D","ntoskrnl.exe",0.0035,0.3441,0.0035,0.3441 "3F0E68","3F0E68","ntoskrnl.exe",0.0035,0.3411,0.0035,0.3411 "401ED0","401ED0","ntoskrnl.exe",0.0034,0.3333,0.0034,0.3333 "205776","205776","ntoskrnl.exe",0.0032,0.3158,0.0032,0.3158 "27B4E4","27B4E4","ntoskrnl.exe",0.0032,0.3122,0.0032,0.3122 "334AD4","334AD4","ntoskrnl.exe",0.0032,0.3116,0.0032,0.3116 "21752F","21752F","ntoskrnl.exe",0.0031,0.3063,0.0031,0.3063 "624BA2","624BA2","ntoskrnl.exe",0.0031,0.3055,0.0031,0.3055 "38E164","38E164","ntoskrnl.exe",0.0031,0.3008,0.0031,0.3008 "2DA204","2DA204","ntoskrnl.exe",0.0028,0.2744,0.0028,0.2744 "2DE596","2DE596","ntoskrnl.exe",0.0027,0.2611,0.0027,0.2611 "23C63C","23C63C","ntoskrnl.exe",0.0026,0.2506,0.0026,0.2506 "2EB8C5","2EB8C5","ntoskrnl.exe",0.0025,0.2476,0.0025,0.2476 "2853D4","2853D4","ntoskrnl.exe",0.0024,0.2386,0.0024,0.2386 "27A276","27A276","ntoskrnl.exe",0.0023,0.2242,0.0023,0.2242 "2DE058","2DE058","ntoskrnl.exe",0.0019,0.1895,0.0019,0.1895 "2DE088","2DE088","ntoskrnl.exe",0.0019,0.1874,0.0019,0.1874 "27A942","27A942","ntoskrnl.exe",0.0019,0.1836,0.0019,0.1836 "214A4D","214A4D","ntoskrnl.exe",0.0015,0.1471,0.0015,0.1471 "396A43","396A43","ntoskrnl.exe",0.0014,0.1412,0.0014,0.1412 "8EE99E","8EE99E","ntoskrnl.exe",0.0013,0.1275,0.0013,0.1275 "285246","285246","ntoskrnl.exe",0.0012,0.1136,0.0012,0.1136 "7422F0","7422F0","ntoskrnl.exe",0.0009,0.0856,0.0009,0.0856 "3B8889","3B8889","ntoskrnl.exe",0.0009,0.0837,0.0009,0.0837 "72CBD6","72CBD6","ntoskrnl.exe",0.0007,0.0691,0.0007,0.0691 "27D0D1","27D0D1","ntoskrnl.exe",0.0006,0.0631,0.0006,0.0631 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_nvlddmkm.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "10FB29","10FB29","nvlddmkm.sys",0.0433,4.2205,0.0433,4.2205 "127ECD","127ECD","nvlddmkm.sys",0.0205,2.0000,0.0205,2.0000 "84752","84752","nvlddmkm.sys",0.0205,2.0000,0.0205,2.0000 "BBE8A4","BBE8A4","nvlddmkm.sys",0.0205,2.0000,0.0205,2.0000 "120F16","120F16","nvlddmkm.sys",0.0125,1.2221,0.0125,1.2221 "130228","130228","nvlddmkm.sys",0.0103,1.0051,0.0103,1.0051 "4F0EA4","4F0EA4","nvlddmkm.sys",0.0100,0.9771,0.0100,0.9771 "1275DE","1275DE","nvlddmkm.sys",0.0099,0.9673,0.0099,0.9673 "59B7DD","59B7DD","nvlddmkm.sys",0.0063,0.6139,0.0063,0.6139 "137490","137490","nvlddmkm.sys",0.0014,0.1384,0.0014,0.1384 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_nvldumdx.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "8D20","8D20","nvldumdx.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_nvwgf2umx_cfg.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "2A55CD","2A55CD","nvwgf2umx_cfg.dll",0.0432,4.2095,0.0432,4.2095 "2A52E2","2A52E2","nvwgf2umx_cfg.dll",0.0411,4.0000,0.6455,62.8880 "2A5EEA","2A5EEA","nvwgf2umx_cfg.dll",0.0411,4.0000,0.0411,4.0000 "2BD760","2BD760","nvwgf2umx_cfg.dll",0.0411,4.0000,0.0411,4.0000 "2A5EC7","2A5EC7","nvwgf2umx_cfg.dll",0.0222,2.1592,0.0222,2.1592 "12A544D","12A544D","nvwgf2umx_cfg.dll",0.0210,2.0434,0.0210,2.0434 "116CE0","116CE0","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "12C342C","12C342C","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "29DC76","29DC76","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "5F000","5F000","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "ACE260","ACE260","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "B10A5E","B10A5E","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "B34DA0","B34DA0","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "BE9A2F","BE9A2F","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "C77044","C77044","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "C93902","C93902","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "C94C0C","C94C0C","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "C95F58","C95F58","nvwgf2umx_cfg.dll",0.0205,2.0000,0.0205,2.0000 "1FA9B0","1FA9B0","nvwgf2umx_cfg.dll",0.0133,1.2960,0.0133,1.2960 "D320DC","D320DC","nvwgf2umx_cfg.dll",0.0123,1.1943,0.0123,1.1943 "AC906C","AC906C","nvwgf2umx_cfg.dll",0.0109,1.0609,0.0109,1.0609 "B3B100","B3B100","nvwgf2umx_cfg.dll",0.0103,1.0060,0.0103,1.0060 "13BE37","13BE37","nvwgf2umx_cfg.dll",0.0103,0.9997,0.0103,0.9997 "EF0460","EF0460","nvwgf2umx_cfg.dll",0.0102,0.9902,0.0102,0.9902 "2A5ECD","2A5ECD","nvwgf2umx_cfg.dll",0.0015,0.1419,0.0015,0.1419 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_oleaut32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "195F3","195F3","oleaut32.dll",0.0320,3.1187,0.0320,3.1187 "1961D","1961D","oleaut32.dll",0.0191,1.8633,0.0191,1.8633 "1ADD3","1ADD3","oleaut32.dll",0.0145,1.4089,0.0145,1.4089 "9EA38","9EA38","oleaut32.dll",0.0111,1.0776,0.0111,1.0776 "1C058","1C058","oleaut32.dll",0.0109,1.0643,0.0109,1.0643 "198A9","198A9","oleaut32.dll",0.0106,1.0369,0.0106,1.0369 "A0010","A0010","oleaut32.dll",0.0105,1.0188,0.0105,1.0188 "19608","19608","oleaut32.dll",0.0082,0.8022,0.0082,0.8022 "1A1F0","1A1F0","oleaut32.dll",0.0082,0.7944,0.0082,0.7944 "19AAF","19AAF","oleaut32.dll",0.0040,0.3910,0.0040,0.3910 "1473C","1473C","oleaut32.dll",0.0022,0.2167,0.0022,0.2167 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_rpcrt4.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "4194F","4194F","rpcrt4.dll",0.0718,6.9930,0.0718,6.9930 "472A1","472A1","rpcrt4.dll",0.0380,3.7023,0.4707,45.8597 "444C0","444C0","rpcrt4.dll",0.0308,2.9981,0.0308,2.9981 "23CA2","23CA2","rpcrt4.dll",0.0212,2.0689,0.0212,2.0689 "27869","27869","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "280BD","280BD","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "2A4F9","2A4F9","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "49071","49071","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "4C270","4C270","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "6DB19","6DB19","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "72799","72799","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "B0FC","B0FC","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "BF9B","BF9B","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "CCB9","CCB9","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "D219A","D219A","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "D53AB","D53AB","rpcrt4.dll",0.0205,2.0000,0.0205,2.0000 "2A1E0","2A1E0","rpcrt4.dll",0.0178,1.7325,0.0178,1.7325 "575A4","575A4","rpcrt4.dll",0.0153,1.4894,0.0153,1.4894 "80745","80745","rpcrt4.dll",0.0141,1.3747,0.0141,1.3747 "479A0","479A0","rpcrt4.dll",0.0113,1.1043,0.0113,1.1043 "4553D","4553D","rpcrt4.dll",0.0108,1.0532,0.0108,1.0532 "7E6E0","7E6E0","rpcrt4.dll",0.0104,1.0172,0.0104,1.0172 "D53BB","D53BB","rpcrt4.dll",0.0103,0.9998,0.0103,0.9998 "95FE5","95FE5","rpcrt4.dll",0.0102,0.9951,0.0102,0.9951 "29D47","29D47","rpcrt4.dll",0.0102,0.9935,0.0102,0.9935 "21F22","21F22","rpcrt4.dll",0.0102,0.9920,0.0102,0.9920 "20BA2","20BA2","rpcrt4.dll",0.0101,0.9829,0.0101,0.9829 "1F5E0","1F5E0","rpcrt4.dll",0.0085,0.8320,0.0085,0.8320 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_schannel.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "67AC","67AC","schannel.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_sechost.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "AF31","AF31","sechost.dll",0.0205,2.0000,0.0205,2.0000 "CDB0","CDB0","sechost.dll",0.0205,2.0000,0.0205,2.0000 "13EE0","13EE0","sechost.dll",0.0101,0.9804,0.0101,0.9804 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_sspicli.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "3FF0","3FF0","sspicli.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_ucrtbase.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "F178B","F178B","ucrtbase.dll",0.1700,16.5643,0.1700,16.5643 "64480","64480","ucrtbase.dll",0.1029,10.0261,0.1029,10.0261 "22A10","22A10","ucrtbase.dll",0.0842,8.2072,0.0842,8.2072 "64483","64483","ucrtbase.dll",0.0719,7.0045,0.0719,7.0045 "5098","5098","ucrtbase.dll",0.0706,6.8796,0.0706,6.8796 "64738","64738","ucrtbase.dll",0.0616,6.0035,0.0616,6.0035 "6448C","6448C","ucrtbase.dll",0.0513,4.9988,0.0513,4.9988 "64729","64729","ucrtbase.dll",0.0513,4.9985,0.0513,4.9985 "46E9B","46E9B","ucrtbase.dll",0.0454,4.4279,0.0454,4.4279 "22A20","22A20","ucrtbase.dll",0.0411,4.0082,0.0411,4.0082 "6471D","6471D","ucrtbase.dll",0.0410,3.9939,0.0410,3.9939 "1D569","1D569","ucrtbase.dll",0.0355,3.4565,0.0355,3.4565 "F1928","F1928","ucrtbase.dll",0.0354,3.4512,0.0354,3.4512 "F1921","F1921","ucrtbase.dll",0.0339,3.3014,0.0399,3.8919 "5090","5090","ucrtbase.dll",0.0333,3.2448,0.0333,3.2448 "1CF8D","1CF8D","ucrtbase.dll",0.0317,3.0871,0.0317,3.0871 "46F18","46F18","ucrtbase.dll",0.0315,3.0661,0.0315,3.0661 "22A2F","22A2F","ucrtbase.dll",0.0309,3.0069,0.0309,3.0069 "64736","64736","ucrtbase.dll",0.0308,3.0041,0.0308,3.0041 "64737","64737","ucrtbase.dll",0.0308,3.0036,0.0308,3.0036 "64482","64482","ucrtbase.dll",0.0308,3.0020,0.0308,3.0020 "6449C","6449C","ucrtbase.dll",0.0308,2.9985,0.0308,2.9985 "64487","64487","ucrtbase.dll",0.0307,2.9952,0.0307,2.9952 "22A4E","22A4E","ucrtbase.dll",0.0305,2.9722,0.0305,2.9722 "22A5E","22A5E","ucrtbase.dll",0.0303,2.9499,0.0303,2.9499 "30D2","30D2","ucrtbase.dll",0.0301,2.9334,0.0301,2.9334 "65919","65919","ucrtbase.dll",0.0210,2.0413,0.0210,2.0413 "8578","8578","ucrtbase.dll",0.0207,2.0159,0.0207,2.0159 "22A63","22A63","ucrtbase.dll",0.0206,2.0044,0.0206,2.0044 "64723","64723","ucrtbase.dll",0.0206,2.0036,0.0206,2.0036 "64726","64726","ucrtbase.dll",0.0205,2.0017,0.0205,2.0017 "22B4B","22B4B","ucrtbase.dll",0.0205,2.0014,0.0205,2.0014 "47FD0","47FD0","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "512F3","512F3","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "5DCA","5DCA","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "D300","D300","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "D3A0","D3A0","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "F16B7","F16B7","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "F16D7","F16D7","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "F1833","F1833","ucrtbase.dll",0.0205,2.0000,0.0205,2.0000 "6472B","6472B","ucrtbase.dll",0.0205,1.9983,0.0205,1.9983 "F19D6","F19D6","ucrtbase.dll",0.0187,1.8245,0.0187,1.8245 "1CF57","1CF57","ucrtbase.dll",0.0153,1.4951,0.0153,1.4951 "F16DF","F16DF","ucrtbase.dll",0.0148,1.4375,0.0148,1.4375 "F16C2","F16C2","ucrtbase.dll",0.0145,1.4171,0.0145,1.4171 "1CCC5","1CCC5","ucrtbase.dll",0.0134,1.3068,0.0134,1.3068 "F16CB","F16CB","ucrtbase.dll",0.0130,1.2697,0.0130,1.2697 "F197E","F197E","ucrtbase.dll",0.0125,1.2164,0.0125,1.2164 "1E01A","1E01A","ucrtbase.dll",0.0120,1.1720,0.0120,1.1720 "22B50","22B50","ucrtbase.dll",0.0119,1.1643,0.0119,1.1643 "2472B","2472B","ucrtbase.dll",0.0111,1.0773,0.0111,1.0773 "3A5FD","3A5FD","ucrtbase.dll",0.0110,1.0766,0.0110,1.0766 "22EC0","22EC0","ucrtbase.dll",0.0109,1.0629,0.0109,1.0629 "F1886","F1886","ucrtbase.dll",0.0107,1.0418,0.0107,1.0418 "F18BA","F18BA","ucrtbase.dll",0.0106,1.0375,0.0106,1.0375 "32D8","32D8","ucrtbase.dll",0.0103,1.0074,0.0103,1.0074 "1C7CE","1C7CE","ucrtbase.dll",0.0103,1.0070,0.0103,1.0070 "1CF43","1CF43","ucrtbase.dll",0.0103,1.0029,0.0103,1.0029 "3117","3117","ucrtbase.dll",0.0103,1.0012,0.0103,1.0012 "F1270","F1270","ucrtbase.dll",0.0103,1.0009,0.0103,1.0009 "22B20","22B20","ucrtbase.dll",0.0103,1.0007,0.0103,1.0007 "725C","725C","ucrtbase.dll",0.0103,1.0005,0.0103,1.0005 "64F70","64F70","ucrtbase.dll",0.0103,0.9999,0.0103,0.9999 "6449A","6449A","ucrtbase.dll",0.0103,0.9997,0.0103,0.9997 "843D","843D","ucrtbase.dll",0.0103,0.9994,0.0103,0.9994 "1775B","1775B","ucrtbase.dll",0.0103,0.9992,0.0103,0.9992 "F1A0F","F1A0F","ucrtbase.dll",0.0103,0.9992,0.0103,0.9992 "46F42","46F42","ucrtbase.dll",0.0103,0.9991,0.0103,0.9991 "4CDA2","4CDA2","ucrtbase.dll",0.0103,0.9990,0.0103,0.9990 "1BB52","1BB52","ucrtbase.dll",0.0102,0.9981,0.0102,0.9981 "F1808","F1808","ucrtbase.dll",0.0102,0.9981,0.0102,0.9981 "F17D0","F17D0","ucrtbase.dll",0.0102,0.9978,0.0102,0.9978 "50C5","50C5","ucrtbase.dll",0.0102,0.9976,0.0102,0.9976 "73CBE","73CBE","ucrtbase.dll",0.0102,0.9976,0.0102,0.9976 "65893","65893","ucrtbase.dll",0.0102,0.9975,0.0102,0.9975 "35A68","35A68","ucrtbase.dll",0.0102,0.9969,0.0102,0.9969 "64732","64732","ucrtbase.dll",0.0102,0.9966,0.0102,0.9966 "1CC20","1CC20","ucrtbase.dll",0.0102,0.9958,0.0102,0.9958 "C7757","C7757","ucrtbase.dll",0.0102,0.9958,0.0102,0.9958 "64734","64734","ucrtbase.dll",0.0102,0.9956,0.0102,0.9956 "1CE9C","1CE9C","ucrtbase.dll",0.0102,0.9946,0.4166,40.5911 "4FEE","4FEE","ucrtbase.dll",0.0102,0.9946,0.0102,0.9946 "30D9","30D9","ucrtbase.dll",0.0102,0.9917,0.0102,0.9917 "6CD42","6CD42","ucrtbase.dll",0.0102,0.9913,0.0102,0.9913 "1BC20","1BC20","ucrtbase.dll",0.0102,0.9910,0.0102,0.9910 "F17A0","F17A0","ucrtbase.dll",0.0101,0.9889,0.0101,0.9889 "87865","87865","ucrtbase.dll",0.0101,0.9877,0.0101,0.9877 "4FC0","4FC0","ucrtbase.dll",0.0101,0.9871,0.0101,0.9871 "F1A29","F1A29","ucrtbase.dll",0.0101,0.9848,0.0101,0.9848 "4FC6","4FC6","ucrtbase.dll",0.0101,0.9808,0.0101,0.9808 "666EB","666EB","ucrtbase.dll",0.0100,0.9768,0.0100,0.9768 "845C","845C","ucrtbase.dll",0.0100,0.9740,0.0100,0.9740 "22B22","22B22","ucrtbase.dll",0.0098,0.9580,0.0098,0.9580 "6B960","6B960","ucrtbase.dll",0.0090,0.8726,0.0090,0.8726 "6291","6291","ucrtbase.dll",0.0088,0.8562,0.0088,0.8562 "F18C6","F18C6","ucrtbase.dll",0.0080,0.7782,0.0080,0.7782 "4B030","4B030","ucrtbase.dll",0.0076,0.7359,0.0076,0.7359 "74C2","74C2","ucrtbase.dll",0.0057,0.5549,0.0057,0.5549 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_user32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "13CA3","13CA3","user32.dll",0.0205,2.0000,0.0205,2.0000 "18290","18290","user32.dll",0.0205,2.0000,0.0205,2.0000 "732B0","732B0","user32.dll",0.0205,2.0000,0.0205,2.0000 "B8E4","B8E4","user32.dll",0.0205,2.0000,0.0205,2.0000 "4A718","4A718","user32.dll",0.0102,0.9981,0.0102,0.9981 "9771","9771","user32.dll",0.0102,0.9956,0.0102,0.9956 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_uxtheme.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "A7D1","A7D1","uxtheme.dll",0.0205,2.0000,0.0205,2.0000 "66B2","66B2","uxtheme.dll",0.0105,1.0251,0.0105,1.0251 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_vaultcli.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "10FBC","10FBC","vaultcli.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_vcruntime140.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1055A","1055A","vcruntime140.dll",0.0516,5.0297,0.0516,5.0297 "1007B","1007B","vcruntime140.dll",0.0515,5.0198,0.0515,5.0198 "1059B","1059B","vcruntime140.dll",0.0515,5.0167,0.0515,5.0167 "113EB","113EB","vcruntime140.dll",0.0508,4.9450,0.0508,4.9450 "11571","11571","vcruntime140.dll",0.0304,2.9596,0.0304,2.9596 "13010","13010","vcruntime140.dll",0.0284,2.7681,0.0284,2.7681 "10430","10430","vcruntime140.dll",0.0222,2.1621,0.0222,2.1621 "113A4","113A4","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "113F0","113F0","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "11410","11410","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "11418","11418","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "116BC","116BC","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "501D","501D","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "52A0","52A0","vcruntime140.dll",0.0205,2.0000,0.0205,2.0000 "114B9","114B9","vcruntime140.dll",0.0204,1.9888,0.0204,1.9888 "10458","10458","vcruntime140.dll",0.0195,1.9030,0.0195,1.9030 "11B88","11B88","vcruntime140.dll",0.0187,1.8204,0.0187,1.8204 "1150C","1150C","vcruntime140.dll",0.0170,1.6518,0.0170,1.6518 "1154E","1154E","vcruntime140.dll",0.0163,1.5892,0.0163,1.5892 "11516","11516","vcruntime140.dll",0.0123,1.2001,0.0123,1.2001 "11327","11327","vcruntime140.dll",0.0110,1.0718,0.0110,1.0718 "11B18","11B18","vcruntime140.dll",0.0108,1.0512,0.0108,1.0512 "11A89","11A89","vcruntime140.dll",0.0107,1.0465,0.0107,1.0465 "11420","11420","vcruntime140.dll",0.0103,1.0079,0.0103,1.0079 "114B6","114B6","vcruntime140.dll",0.0103,1.0064,0.0103,1.0064 "113A8","113A8","vcruntime140.dll",0.0103,1.0054,0.0103,1.0054 "106F1","106F1","vcruntime140.dll",0.0103,1.0039,0.0103,1.0039 "113AE","113AE","vcruntime140.dll",0.0103,1.0023,0.0103,1.0023 "1053D","1053D","vcruntime140.dll",0.0103,1.0016,0.0103,1.0016 "10565","10565","vcruntime140.dll",0.0103,0.9998,0.0103,0.9998 "106C1","106C1","vcruntime140.dll",0.0103,0.9987,0.0103,0.9987 "105A2","105A2","vcruntime140.dll",0.0102,0.9983,0.0102,0.9983 "10444","10444","vcruntime140.dll",0.0102,0.9968,0.0102,0.9968 "55F9","55F9","vcruntime140.dll",0.0102,0.9966,0.0102,0.9966 "11460","11460","vcruntime140.dll",0.0102,0.9961,0.0102,0.9961 "1070A","1070A","vcruntime140.dll",0.0102,0.9951,0.0102,0.9951 "11C21","11C21","vcruntime140.dll",0.0102,0.9951,0.0102,0.9951 "1067F","1067F","vcruntime140.dll",0.0102,0.9945,0.0102,0.9945 "10483","10483","vcruntime140.dll",0.0102,0.9938,0.0102,0.9938 "11383","11383","vcruntime140.dll",0.0102,0.9938,0.0102,0.9938 "11ACB","11ACB","vcruntime140.dll",0.0101,0.9831,0.0101,0.9831 "1063E","1063E","vcruntime140.dll",0.0101,0.9827,0.0101,0.9827 "11312","11312","vcruntime140.dll",0.0100,0.9729,0.0100,0.9729 "10677","10677","vcruntime140.dll",0.0097,0.9406,0.0097,0.9406 "10550","10550","vcruntime140.dll",0.0054,0.5244,0.0054,0.5244 "11548","11548","vcruntime140.dll",0.0030,0.2912,0.0030,0.2912 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_webio.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "13287","13287","webio.dll",0.0205,2.0000,0.0205,2.0000 "1EFD2","1EFD2","webio.dll",0.0205,2.0000,0.0205,2.0000 "28CDC","28CDC","webio.dll",0.0205,2.0000,0.0205,2.0000 "2AD50","2AD50","webio.dll",0.0205,2.0000,0.0205,2.0000 "2B8BD","2B8BD","webio.dll",0.0205,2.0000,0.0205,2.0000 "32200","32200","webio.dll",0.0205,2.0000,0.0205,2.0000 "3D4BE","3D4BE","webio.dll",0.0205,2.0000,0.0205,2.0000 "404DD","404DD","webio.dll",0.0205,2.0000,0.0205,2.0000 "404E1","404E1","webio.dll",0.0205,2.0000,0.0205,2.0000 "8F010","8F010","webio.dll",0.0205,2.0000,0.0205,2.0000 "C7FA","C7FA","webio.dll",0.0205,2.0000,0.0205,2.0000 "EF88","EF88","webio.dll",0.0205,2.0000,0.0205,2.0000 "28288","28288","webio.dll",0.0101,0.9884,0.0101,0.9884 "35865","35865","webio.dll",0.0075,0.7273,0.0075,0.7273 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_webservices.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "FD50","FD50","webservices.dll",0.0205,2.0000,0.0205,2.0000 "12A45","12A45","webservices.dll",0.0140,1.3616,0.0140,1.3616 "16ED3","16ED3","webservices.dll",0.0106,1.0363,0.0106,1.0363 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_win32kbase.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "20531","20531","win32kbase.sys",0.0210,2.0444,0.0210,2.0444 "14ED9","14ED9","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "18195","18195","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "1BAC28","1BAC28","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "1D71C4","1D71C4","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "20F73","20F73","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "8EB8E","8EB8E","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "CB8F5","CB8F5","win32kbase.sys",0.0205,2.0000,0.0205,2.0000 "208C9","208C9","win32kbase.sys",0.0171,1.6676,0.0171,1.6676 "B33BD","B33BD","win32kbase.sys",0.0124,1.2042,0.0124,1.2042 "1AD15","1AD15","win32kbase.sys",0.0115,1.1179,0.0115,1.1179 "C75BA","C75BA","win32kbase.sys",0.0107,1.0446,0.0107,1.0446 "C75B0","C75B0","win32kbase.sys",0.0104,1.0112,0.0104,1.0112 "2053B","2053B","win32kbase.sys",0.0103,1.0082,0.0103,1.0082 "C74CB","C74CB","win32kbase.sys",0.0101,0.9858,0.0101,0.9858 "140D0","140D0","win32kbase.sys",0.0101,0.9828,0.0101,0.9828 "31813","31813","win32kbase.sys",0.0079,0.7718,0.0079,0.7718 "E7467","E7467","win32kbase.sys",0.0072,0.7003,0.0072,0.7003 "1C71C","1C71C","win32kbase.sys",0.0031,0.3021,0.0031,0.3021 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_win32kbase_rs.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "138EC","138EC","win32kbase_rs.sys",0.0205,2.0000,0.0205,2.0000 "F8DE","F8DE","win32kbase_rs.sys",0.0205,2.0000,0.0205,2.0000 "17E61","17E61","win32kbase_rs.sys",0.0198,1.9268,0.0198,1.9268 "BE42","BE42","win32kbase_rs.sys",0.0149,1.4470,0.0149,1.4470 "1419E","1419E","win32kbase_rs.sys",0.0142,1.3807,0.0142,1.3807 "145E9","145E9","win32kbase_rs.sys",0.0137,1.3389,0.0137,1.3389 "4BB3","4BB3","win32kbase_rs.sys",0.0103,1.0077,0.0103,1.0077 "D831","D831","win32kbase_rs.sys",0.0102,0.9954,0.0102,0.9954 "138B4","138B4","win32kbase_rs.sys",0.0102,0.9930,0.0102,0.9930 "A0E4","A0E4","win32kbase_rs.sys",0.0100,0.9704,0.0100,0.9704 "9C2D","9C2D","win32kbase_rs.sys",0.0068,0.6613,0.0068,0.6613 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_win32kfull.sys_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "5F746","5F746","win32kfull.sys",0.0381,3.7132,0.0381,3.7132 "1B49E8","1B49E8","win32kfull.sys",0.0217,2.1123,0.0217,2.1123 "5F59D","5F59D","win32kfull.sys",0.0205,2.0000,0.0205,2.0000 "14F4FD","14F4FD","win32kfull.sys",0.0161,1.5704,0.0161,1.5704 "5F5A5","5F5A5","win32kfull.sys",0.0136,1.3223,0.0136,1.3223 "5AFAF","5AFAF","win32kfull.sys",0.0121,1.1805,0.0121,1.1805 "594F4","594F4","win32kfull.sys",0.0115,1.1159,0.0115,1.1159 "CB0D3","CB0D3","win32kfull.sys",0.0114,1.1129,0.0114,1.1129 "594C1","594C1","win32kfull.sys",0.0104,1.0180,0.0104,1.0180 "2B57D","2B57D","win32kfull.sys",0.0104,1.0154,0.0104,1.0154 "5F5EE","5F5EE","win32kfull.sys",0.0103,1.0056,0.0103,1.0056 "5F5BD","5F5BD","win32kfull.sys",0.0099,0.9598,0.0099,0.9598 "5F74E","5F74E","win32kfull.sys",0.0053,0.5176,0.0053,0.5176 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_win32u.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "12C4","12C4","win32u.dll",0.4115,40.0890,0.9964,97.0850 "ACE4","ACE4","win32u.dll",0.3096,30.1676,0.3096,30.1676 "13A4","13A4","win32u.dll",0.1884,18.3594,0.1884,18.3594 "12A4","12A4","win32u.dll",0.1679,16.3559,0.1679,16.3559 "2084","2084","win32u.dll",0.1015,9.8908,0.2308,22.4867 "1344","1344","win32u.dll",0.0920,8.9620,0.4832,47.0821 "3924","3924","win32u.dll",0.0824,8.0248,0.0824,8.0248 "4B44","4B44","win32u.dll",0.0715,6.9626,0.0715,6.9626 "1CE4","1CE4","win32u.dll",0.0618,6.0210,0.7041,68.5968 "9804","9804","win32u.dll",0.0616,6.0000,0.0616,6.0000 "5104","5104","win32u.dll",0.0515,5.0203,0.0515,5.0203 "16C4","16C4","win32u.dll",0.0354,3.4443,0.0763,7.4303 "5EE4","5EE4","win32u.dll",0.0299,2.9089,0.0299,2.9089 "1424","1424","win32u.dll",0.0286,2.7829,0.0286,2.7829 "B484","B484","win32u.dll",0.0281,2.7397,0.0281,2.7397 "2124","2124","win32u.dll",0.0239,2.3248,0.0239,2.3248 "3AE4","3AE4","win32u.dll",0.0238,2.3161,0.0238,2.3161 "20C4","20C4","win32u.dll",0.0234,2.2824,0.0234,2.2824 "1BE4","1BE4","win32u.dll",0.0228,2.2253,0.0228,2.2253 "4D24","4D24","win32u.dll",0.0215,2.0977,0.0215,2.0977 "CB84","CB84","win32u.dll",0.0213,2.0759,0.0213,2.0759 "93A4","93A4","win32u.dll",0.0211,2.0523,0.0211,2.0523 "1444","1444","win32u.dll",0.0205,2.0000,0.0205,2.0000 "14C4","14C4","win32u.dll",0.0205,2.0000,0.0205,2.0000 "15C4","15C4","win32u.dll",0.0205,2.0000,0.0205,2.0000 "20B0","20B0","win32u.dll",0.0205,2.0000,0.0205,2.0000 "26E4","26E4","win32u.dll",0.0205,2.0000,0.0205,2.0000 "2BA4","2BA4","win32u.dll",0.0205,2.0000,0.0205,2.0000 "9CE4","9CE4","win32u.dll",0.0205,2.0000,0.0205,2.0000 "C784","C784","win32u.dll",0.0182,1.7695,0.0182,1.7695 "A044","A044","win32u.dll",0.0181,1.7659,0.0181,1.7659 "9A64","9A64","win32u.dll",0.0176,1.7141,0.0176,1.7141 "19E4","19E4","win32u.dll",0.0171,1.6671,0.0171,1.6671 "29A4","29A4","win32u.dll",0.0155,1.5056,0.0155,1.5056 "B9A4","B9A4","win32u.dll",0.0126,1.2282,0.0126,1.2282 "1704","1704","win32u.dll",0.0108,1.0518,0.0108,1.0518 "2C84","2C84","win32u.dll",0.0106,1.0342,0.0311,3.0342 "16A4","16A4","win32u.dll",0.0105,1.0207,0.0105,1.0207 "1364","1364","win32u.dll",0.0105,1.0204,0.0105,1.0204 "2804","2804","win32u.dll",0.0104,1.0127,0.0104,1.0127 "17A4","17A4","win32u.dll",0.0104,1.0126,0.0104,1.0126 "66C4","66C4","win32u.dll",0.0104,1.0118,0.0104,1.0118 "3584","3584","win32u.dll",0.0104,1.0091,0.0104,1.0091 "5444","5444","win32u.dll",0.0103,1.0042,0.0103,1.0042 "13C4","13C4","win32u.dll",0.0103,1.0041,0.0103,1.0041 "21C4","21C4","win32u.dll",0.0103,1.0007,0.0103,1.0007 "21A4","21A4","win32u.dll",0.0102,0.9969,0.0102,0.9969 "1DE4","1DE4","win32u.dll",0.0102,0.9934,0.0102,0.9934 "6E64","6E64","win32u.dll",0.0101,0.9885,0.0101,0.9885 "24E4","24E4","win32u.dll",0.0101,0.9854,0.0101,0.9854 "1C84","1C84","win32u.dll",0.0101,0.9822,0.0101,0.9822 "12E0","12E0","win32u.dll",0.0101,0.9818,0.0101,0.9818 "8644","8644","win32u.dll",0.0100,0.9786,0.0100,0.9786 "2564","2564","win32u.dll",0.0095,0.9270,0.0095,0.9270 "2F24","2F24","win32u.dll",0.0092,0.8954,0.0092,0.8954 "5524","5524","win32u.dll",0.0064,0.6212,0.0064,0.6212 "4BE4","4BE4","win32u.dll",0.0062,0.6003,0.0062,0.6003 "A304","A304","win32u.dll",0.0012,0.1207,0.0012,0.1207 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_windows.storage.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "1556CA","1556CA","windows.storage.dll",0.0131,1.2783,0.0131,1.2783 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_winhttp.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "10646","10646","winhttp.dll",0.0205,2.0000,0.0205,2.0000 "2F400","2F400","winhttp.dll",0.0205,2.0000,0.0205,2.0000 "3FD75","3FD75","winhttp.dll",0.0205,2.0000,0.0205,2.0000 "4DF51","4DF51","winhttp.dll",0.0110,1.0730,0.0110,1.0730 "54761","54761","winhttp.dll",0.0102,0.9955,0.0102,0.9955 "7C5D1","7C5D1","winhttp.dll",0.0102,0.9933,0.0102,0.9933 "170F4","170F4","winhttp.dll",0.0102,0.9899,0.0102,0.9899 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_wininet.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "9BB16","9BB16","wininet.dll",0.0314,3.0549,0.0314,3.0549 "1CC5FB","1CC5FB","wininet.dll",0.0307,2.9944,0.0307,2.9944 "3B1F8","3B1F8","wininet.dll",0.0300,2.9262,0.0300,2.9262 "613B7","613B7","wininet.dll",0.0205,2.0000,0.0205,2.0000 "66500","66500","wininet.dll",0.0205,2.0000,0.0205,2.0000 "9F26C","9F26C","wininet.dll",0.0205,2.0000,0.0205,2.0000 "A0E59","A0E59","wininet.dll",0.0205,2.0000,0.0205,2.0000 "736DC","736DC","wininet.dll",0.0103,1.0036,0.0103,1.0036 "AA950","AA950","wininet.dll",0.0103,1.0018,0.0103,1.0018 "4B72C","4B72C","wininet.dll",0.0101,0.9889,0.0101,0.9889 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_wosc.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "EF38","EF38","wosc.dll",0.0102,0.9956,0.0102,0.9956 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_ws2_32.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "272BC","272BC","ws2_32.dll",0.0308,2.9989,0.0308,2.9989 "B590","B590","ws2_32.dll",0.0205,2.0000,0.0205,2.0000 "D399","D399","ws2_32.dll",0.0205,2.0000,0.0205,2.0000 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/functions_xmllite.dll_baseline.csv ================================================ Name,Address,Module,SelfTimePercentage,SelfTimeMs,TotalTimePercentage,TotalTimeMs "FD30","FD30","xmllite.dll",0.0205,2.0000,0.0205,2.0000 "DC45","DC45","xmllite.dll",0.0154,1.4975,0.0154,1.4975 "DADC","DADC","xmllite.dll",0.0138,1.3490,0.0138,1.3490 "14AE8","14AE8","xmllite.dll",0.0081,0.7934,0.0081,0.7934 "14D2A","14D2A","xmllite.dll",0.0044,0.4307,0.0044,0.4307 "10CE4","10CE4","xmllite.dll",0.0035,0.3379,0.0035,0.3379 "1633A","1633A","xmllite.dll",0.0034,0.3327,0.3295,32.1016 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/modules_baseline.csv ================================================ Name,WeightPercentage,TimeMs "ntdll.dll",42.9829,4187.8697 "ntoskrnl.exe",19.1921,1869.9106 "Mso20win32client.dll",3.7002,360.5168 "Mso40UIwin32client.dll",3.1944,311.2328 "Mso30win32client.dll",3.0746,299.5610 "AppvIsvSubsystems64.dll",2.9577,288.1724 "CI.dll",2.4513,238.8320 "win32u.dll",2.3402,228.0078 "ucrtbase.dll",2.1845,212.8341 "cng.sys",1.8954,184.6721 "combase.dll",1.7229,167.8598 "KernelBase.dll",1.7068,166.2996 "Windows.Web.dll",1.0492,102.2255 "MSOARIA.DLL",0.9638,93.9026 "vcruntime140.dll",0.7893,76.9048 "rpcrt4.dll",0.5473,53.3289 "nvwgf2umx_cfg.dll",0.5245,51.1011 "DWrite.dll",0.5203,50.6927 "kernel32.dll",0.4280,41.6982 "bcryptprimitives.dll",0.3727,36.3167 "MSO.DLL",0.3535,34.4413 "Mso98win32client.dll",0.3271,31.8744 "WinTypes.dll",0.3239,31.5608 "crypt32.dll",0.3216,31.3348 "FLTMGR.SYS",0.2996,29.1923 "win32kbase.sys",0.2755,26.8409 "webio.dll",0.2639,25.7157 "msvcp140.dll",0.2565,24.9943 "imagehlp.dll",0.2559,24.9315 "mssecflt.sys",0.2482,24.1811 "Ntfs.sys",0.2077,20.2327 "wininet.dll",0.2050,19.9698 "dcomp.dll",0.2028,19.7562 "win32kfull.sys",0.1914,18.6439 "TextShaping.dll",0.1831,17.8370 "PPCORE.DLL",0.1794,17.4776 "Windows.Security.Authentication.Web.Core.dll",0.1667,16.2420 "WindowsCodecs.dll",0.1558,15.1791 "nvlddmkm.sys",0.1554,15.1444 "win32kbase_rs.sys",0.1511,14.7212 "MSPST32.DLL",0.1508,14.6954 "d3d11.dll",0.1351,13.1660 "oleaut32.dll",0.1313,12.7928 "WdFilter.sys",0.1296,12.6251 "OLMAPI32.DLL",0.1295,12.6138 "aitrx.dll",0.1207,11.7603 "d2d1.dll",0.1190,11.5927 "winhttp.dll",0.1032,10.0517 "user32.dll",0.1026,9.9937 "iertutil.dll",0.0967,9.4243 "dpapi.dll",0.0824,8.0252 "EMSMDB32.DLL",0.0822,8.0042 "CoreMessaging.dll",0.0821,7.9979 "fcon.dll",0.0816,7.9531 "ws2_32.dll",0.0718,6.9989 "xmllite.dll",0.0692,6.7412 "bcrypt.dll",0.0606,5.9067 "sechost.dll",0.0511,4.9804 "Wldap32.dll",0.0483,4.7034 "UIAutomationCore.dll",0.0458,4.4606 "webservices.dll",0.0451,4.3979 "bindflt.sys",0.0411,4.0000 "mswsock.dll",0.0317,3.0857 "uxtheme.dll",0.0310,3.0251 "MSPTLS.DLL",0.0309,3.0086 "Windows.StateRepositoryCore.dll",0.0255,2.4855 "FlightSettings.dll",0.0219,2.1378 "OneCoreUAPCommonProxyStub.dll",0.0207,2.0136 "C2R64.dll",0.0205,2.0000 "comctl32.dll",0.0205,2.0000 "fvevol.sys",0.0205,2.0000 "MicrosoftAccountWAMExtension.dll",0.0205,2.0000 "NETIO.SYS",0.0205,2.0000 "nvldumdx.dll",0.0205,2.0000 "PktMon.sys",0.0205,2.0000 "schannel.dll",0.0205,2.0000 "sspicli.dll",0.0205,2.0000 "vaultcli.dll",0.0205,2.0000 "Windows.Networking.Connectivity.dll",0.0205,2.0000 "gdi32full.dll",0.0196,1.9122 "dxgmms2.sys",0.0181,1.7622 "OART.DLL",0.0180,1.7555 "fileinfo.sys",0.0165,1.6067 "windows.storage.dll",0.0131,1.2783 "ksecdd.sys",0.0123,1.1984 "dhcpcsvc6.dll",0.0114,1.1154 "dxgkrnl.sys",0.0104,1.0173 "e1d.sys",0.0104,1.0148 "intelppm.sys",0.0104,1.0090 "Mso50win32client.dll",0.0103,1.0017 "ahcache.sys",0.0103,1.0001 "dxgi.dll",0.0102,0.9974 "wosc.dll",0.0102,0.9956 "msasn1.dll",0.0102,0.9943 "dhcpcsvc.dll",0.0102,0.9917 "cpprestsdk.dll",0.0102,0.9904 "IPHLPAPI.DLL",0.0102,0.9897 "msxml6.dll",0.0029,0.2836 ================================================ FILE: src/ProfileExplorerCoreTests/TestData/MsoTrace/processes_baseline.csv ================================================ Name,WeightPercentage,DurationMs,ProcessId,CommandLine "msiexec",15.8379,0.0000,43012,"C:\WINDOWS\system32\msiexec.exe /V" "MsMpEng",15.0104,0.0000,7852,"""C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25070.5-0\MsMpEng.exe""" "POWERPNT",11.8762,0.0000,34376,"""C:\Program Files\Microsoft Office\root\Office16\POWERPNT.EXE"" " "svchost",7.5690,0.0000,7416,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s TokenBroker" "System",6.0552,648.3761,4,"" "devenv",3.8146,0.0000,21220,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\devenv.exe"" ""D:\profile-explorer\src\ProfileExplorer.sln""" "MsSense",3.2469,0.0000,5500,"""C:\Program Files\Windows Defender Advanced Threat Protection\MsSense.exe""" "backgroundTaskHost",3.2183,0.0000,46296,"""C:\WINDOWS\system32\BackgroundTaskHost.exe"" -ServerName:BackgroundTaskHost.WebAccountProvider" "svchost",2.4074,0.0000,1248,"C:\WINDOWS\system32\svchost.exe -k RPCSS -p" "WmiPrvSE",2.0800,0.0000,7156,"C:\WINDOWS\system32\wbem\wmiprvse.exe -secured -Embedding" "Idle",1.9553,0.0000,0,"" "svchost",1.9268,5.4607,3288,"C:\WINDOWS\system32\svchost.exe -k NetworkService -p" "wpr",1.5874,1259.3971,16800,"""C:\WINDOWS\system32\wpr.exe"" -stop trace.etl" "dwm",1.5694,0.0000,1356,"""dwm.exe""" "lsass",1.4042,0.0000,1628,"C:\WINDOWS\system32\lsass.exe" "RuntimeBroker",1.3546,0.0000,46356,"C:\Windows\System32\RuntimeBroker.exe -Embedding" "services",1.2675,0.0000,1552,"C:\WINDOWS\system32\services.exe" "NisSrv",1.2300,0.0000,2608,"""C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25070.5-0\NisSrv.exe""" "svchost",1.0873,0.0000,2312,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s UserManager" "powershell",0.9296,576.2559,49428,"""powershell.exe"" ""C:\WINDOWS\system32\config\systemprofile\AppData\Local\AzureSecurityPack\Watchdog.ps1""" "sihost",0.8260,0.0000,9192,"sihost.exe" "svchost",0.8125,0.0000,8488,"C:\WINDOWS\System32\svchost.exe -k netsvcs -p -s NetSetupSvc" "ai",0.7839,785.5657,36368,"""C:\Program Files\Microsoft Office\root\vfs\ProgramFilesCommonX64\Microsoft Shared\OFFICE16\AI\ai.exe"" ""653D2B2D-4040-4765-AC6E-BE73CF322FDD"" ""54E1869C-B1D2-4ED1-AD42-18A506795C0F"" ""34376"" ""C:\Program Files\Microsoft Office\root\Office16\POWERPNT.EXE"" ""PowerPointCombinedFloatieLreOnline.onnx""" "MpDlpService",0.7734,0.0000,11476,"""C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25070.5-0\MpDlpService.exe""" "explorer",0.7539,0.0000,8464,"C:\WINDOWS\Explorer.EXE" "officesvcmgr",0.7058,6130.0417,40936,"officesvcmgr.exe /checkin {ea88725a-03af-4c5c-8c08-463fb7cbb8ef}" "svchost",0.6923,0.0000,1876,"C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p" "PAD.Console.Host",0.6428,0.0000,23092,"""C:\Program Files\WindowsApps\Microsoft.PowerAutomateDesktop_11.2508.104.0_x64__8wekyb3d8bbwe\dotnet\PAD.Console.Host.exe"" " "ms-teams",0.5842,0.0000,21028,"""C:\Program Files\WindowsApps\MSTeams_25227.201.3887.7121_x64__8wekyb3d8bbwe\ms-teams.exe"" msteams:system-initiated" "Widgets",0.5647,0.0000,1224,"""C:\Program Files\WindowsApps\MicrosoftWindows.Client.WebExperience_525.22301.0.0_x64__cw5n1h2txyewy\Dashboard\Widgets.exe"" -ServerName:Microsoft.Windows.DashboardServer" "GlobalSecureAccessTunnelingService",0.4175,0.0000,26060,"""C:\Program Files\Global Secure Access Client\GlobalSecureAccessTunnelingService.exe""" "PAD.AutomationServer",0.3289,0.0000,21472,"""C:\Program Files\WindowsApps\Microsoft.PowerAutomateDesktop_11.2508.104.0_x64__8wekyb3d8bbwe\dotnet\PAD.AutomationServer.exe"" --ClientId=""2cfe3c41-985f-4b38-80be-aa4676b17dfb"" --CallerProcessId=23092 --ParentCorrelationId=""cb6575f3-d03c-4e44-a4d8-51de166d4689"" --SessionId=""d1c42f05-af17-4d69-9f35-2ed959314426"" " "WindowsTerminal",0.3214,0.0000,49988,"""C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.22.12111.0_x64__8wekyb3d8bbwe\WindowsTerminal.exe"" " "svchost",0.2838,0.0000,4944,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s Winmgmt" "WmiPrvSE",0.2808,0.0000,8648,"C:\WINDOWS\system32\wbem\wmiprvse.exe -secured -Embedding" "GlobalSecureAccessEngineService",0.2718,0.0000,26340,"""C:\Program Files\Global Secure Access Client\GlobalSecureAccessEngineService.exe""" "svchost",0.2343,0.0000,1212,"C:\WINDOWS\system32\svchost.exe -k DcomLaunch -p -s LSM" "csrss",0.2313,0.0000,1464,"%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16" "msedgewebview2",0.2268,0.0000,3156,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-agent=""Mozilla/5.0 (Windows NT 10.0; Win64; x64; Cortana 1.18.9.23723; 10.0.0.0.29430.1000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.29430 IsWebView2/True (WebView2Version 139.0.3405.102)"" --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\LocalState\EBWebView"" --webview-exe-name=SearchHost.exe --webview-exe-version=2125.20401.0.2000 --embedded-browser-webview=1 --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=5 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330160127 --launch-time-ticks=31988846450 --always-read-main-dll --metrics-shmem-handle=3592,i,13601118859329866100,3094116253972930061,2097152 --field-trial-handle=1948,i,16794949237765112" "svchost",0.2208,0.0000,4024,"C:\WINDOWS\system32\svchost.exe -k LocalServiceHttp -p" "ctfmon",0.1892,0.0000,13824,"/QuitInfo:00000000000002BC;00000000000002C0; " "SenseTracer",0.1577,0.0000,11924,"""C:\Program Files\Windows Defender Advanced Threat Protection\SenseTracer.exe"" -in:etw -trace -sequence -session:{351166AE-A94D-493D-B349-E26DEA024EBA} -event:4148 -timer:60 -provider:128126 -level:31 -d ""C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Trace""" "svchost",0.1577,0.0000,10004,"C:\WINDOWS\System32\svchost.exe -k utcsvc -p" "svchost",0.1547,0.0000,5360,"C:\WINDOWS\System32\svchost.exe -k LocalServiceNoNetwork -p -s DPS" "OfficeClickToRun",0.1502,0.0000,5520,"""C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe"" /service" "vmms",0.1216,0.0000,8072,"C:\WINDOWS\system32\vmms.exe" "Microsoft.Engineering.FileVirtualization.Daemon",0.1171,0.0000,14020,"""C:\Users\benjaming.REDMOND\AppData\Local\VPack\VPackLegacy\Microsoft.Engineering.FileVirtualization.Daemon.exe""" "svchost",0.1171,0.0000,11500,"C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup -s CDPUserSvc" "Microsoft.Management.Services.IntuneWindowsAgent",0.1141,0.0000,6332,"""C:\Program Files (x86)\Microsoft Intune Management Extension\Microsoft.Management.Services.IntuneWindowsAgent.exe""" "MDMAppInstaller",0.1066,0.0000,9724,"""C:\WINDOWS\system32\MDMAppInstaller.exe""" "MemCompression",0.1036,0.0000,4384,"" "TextInputHost",0.0991,0.0000,5764,"""C:\Windows\SystemApps\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\TextInputHost.exe"" -ServerName:InputApp.AppXk0k6mrh4r2q0ct33a9wgbez0x7v9cz5y.mca" "GlobalSecureAccessClient",0.0976,0.0000,21716,"""C:\Program Files\Global Secure Access Client\TrayApp\GlobalSecureAccessClient.exe""" "pwsh",0.0976,0.0000,39536,"""C:\Program Files\PowerShell\7\pwsh.exe""" "svchost",0.0976,0.0000,10244,"C:\WINDOWS\System32\svchost.exe -k NetworkService -s TermService" "conhost",0.0961,567.5633,43904,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "SenseNdr",0.0946,0.0000,48664,"""C:\Program Files\Windows Defender Advanced Threat Protection\SenseNdr.exe"" -" "svchost",0.0946,0.0000,3228,"C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p -s Dhcp" "OpenConsole",0.0931,0.0000,38492,"""C:\Program Files\WindowsApps\Microsoft.WindowsTerminal_1.22.12111.0_x64__8wekyb3d8bbwe\OpenConsole.exe"" --headless --textMeasurement graphemes --width 120 --height 30 --signal 0xa28 --server 0x944" "svchost",0.0781,0.0000,3404,"C:\WINDOWS\system32\svchost.exe -k LocalService -p -s CDPSvc" "msedgewebview2",0.0721,0.0000,21124,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView"" --webview-exe-name=ms-teams.exe --webview-exe-version=25227.201.3887.7121 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --autoplay-policy=no-user-gesture-required --disable-background-timer-throttling --enable-blink-features=IndexedDbGetAllRecords --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=6 --js-flags=""--stack-trace-limit=50 --expose-gc --ms-user-locale=en-US"" --time-ticks-at-unix-epoch=-1755680330159115 --launch-time-ticks=32151898401 --always-read-main-dll --metrics-shmem-handle=4440,i,15304891087169025689,13205086796921645268,2097152 --field-trial-handle=1848,i,9232284790936083051,8827603450831" "SearchIndexer",0.0691,0.0000,11340,"C:\WINDOWS\system32\SearchIndexer.exe /Embedding" "svchost",0.0661,0.0000,3572,"C:\WINDOWS\System32\svchost.exe -k netprofm -p -s netprofm" "svchost",0.0646,0.0000,4488,"C:\WINDOWS\system32\svchost.exe -k LocalService -p -s FontCache" "msedgewebview2",0.0616,0.0000,30984,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=olk.exe --webview-exe-version=1.2025.806.300 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Olk\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --disable-features=msEnhancedTrackingPreventionEnabled --enable-aggressive-domstorage-flushing --enable-features=msSingleSignOnOSForPrimaryAccountIsShared,msAbydos,msAbydosHandwritingAttr,msAbydosGestureSupport,msEnhancedTextContrast --mojo-named-platform-channel-pipe=16472.30956.517669952921803472 /pfhostedapp:a8877bbce1455e1e7d0708640add3c7185451dd9" "qcmtusvc",0.0571,0.0000,5536,"""C:\Program Files (x86)\QUALCOMM Incorporated\Qualcomm USB Drivers For Windows\DriverPackage\Qualcomm\Tools\qcmtusvc.exe""" "System",0.0541,648.3761,4,"" "CcmExec",0.0526,0.0000,3124,"C:\Windows\CCM\CcmExec.exe" "svchost",0.0511,0.0000,4164,"C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p -s SysMain" "wslservice",0.0496,0.0000,5492,"""C:\Program Files\WSL\wslservice.exe""" "msedgewebview2",0.0451,0.0000,31928,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Olk\EBWebView"" --webview-exe-name=olk.exe --webview-exe-version=1.2025.806.300 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=6 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330158751 --launch-time-ticks=32210482544 --always-read-main-dll --metrics-shmem-handle=4224,i,17895423284350772904,11130741382341777934,2097152 --field-trial-handle=1940,i,8033129406060731551,14143038207632028611,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAbydos,msAbydosGestureSupport,msAbydosHandwritingAttr,msAggressiveCacheTrimming,msCustomDataPartition,msEnhancedTextContrast,msSingleSignOn" "schtasks",0.0451,46.3700,11152,"schtasks.exe /change /tn ""Microsoft\Office\Office Serviceability Manager"" /enable" "csrss",0.0436,0.0000,1364,"%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,3072,512 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16" "svchost",0.0421,0.0000,556,"C:\WINDOWS\System32\svchost.exe -k NetworkService -p" "svchost",0.0421,0.0000,2920,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s Schedule" "Notepad",0.0390,0.0000,27364,"""C:\Program Files\WindowsApps\Microsoft.WindowsNotepad_11.2507.28.0_x64__8wekyb3d8bbwe\Notepad\Notepad.exe"" RestartByRestartManager:*" "schtasks",0.0390,93.1604,32492,"schtasks.exe /Create /tn ""Microsoft\Office\Office Serviceability Manager"" /XML ""C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeSvcMgrSchedule_390M.xml""" "msedgewebview2",0.0375,0.0000,15000,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=ms-teams.exe --webview-exe-version=25227.201.3887.7121 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --autoplay-policy=no-user-gesture-required --disable-background-timer-throttling --disable-features=msEnhancedTrackingPreventionEnabled,BreakoutBoxPreferCaptureTimestampInVideoFrames,msWebOOUI --enable-blink-features=IndexedDbGetAllRecords --enable-features=msSingleSignOnOSForPrimaryAccountIsShared,AutofillReplaceCachedWebElementsByRendererIds,DocumentPolicyIncludeJSCallStacksInCrashReports,PartitionedCookies,PreferredAudioOutputDevices,SharedArrayBuffer,SkipGrantAccessToDataPathIfAlreadySet,ThirdPartyStoragePartitioning,msAbydos,msAbydosGestureSupport,msAbydosHandwritingAttr,msWebView2EnableDraggableRegions,msWebView2SetUserAgentOve" "schtasks",0.0375,44.2041,23744,"schtasks.exe /Delete /F /tn ""Microsoft\Office\Office Serviceability Manager""" "svchost",0.0375,0.0000,19072,"C:\WINDOWS\System32\svchost.exe -k UnistackSvcGroup" "msedgewebview2",0.0360,0.0000,16868,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=SearchHost.exe --webview-exe-version=2125.20401.0.2000 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\LocalState\EBWebView"" --noerrdialogs --disable-features=msSmartScreenProtection --edge-webview-enable-mojo-ipcz --enable-features=msEdgeFluentOverlayScrollbar --user-agent=""Mozilla/5.0 (Windows NT 10.0; Win64; x64; Cortana 1.18.9.23723; 10.0.0.0.29430.1000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.29430 IsWebView2/True (WebView2Version 139.0.3405.102)"" --lang=en-US --mojo-named-platform-channel-pipe=5140.16840.14487594390742658058 /pfhostedapp:f1b3cc9189bc16db4ff1ff60d85fd8edd4446ca1" "POWERPNT",0.0360,0.0000,36284,"""C:\Program Files\Microsoft Office\root\Office16\POWERPNT.EXE"" " "conhost",0.0345,6120.8743,39060,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "schtasks",0.0345,45.0367,13884,"schtasks.exe /change /tn ""Microsoft\Office\Office Serviceability Manager"" /enable" "PAD.BridgeToUIAutomation2",0.0330,0.0000,22796,"""C:\Program Files\WindowsApps\Microsoft.PowerAutomateDesktop_11.2508.104.0_x64__8wekyb3d8bbwe\dotnet\PAD.BridgeToUIAutomation2.exe"" --guid=79f94607-a7ed-4833-8f7b-d83b11f6a29c --callerProcessId=21472 --service=""uia2""" "schtasks",0.0330,36.2390,11528,"schtasks.exe /change /tn ""Microsoft\Office\Office Serviceability Manager"" /enable" "SenseAP",0.0330,0.0000,11848,"-" "svchost",0.0330,0.0000,9792,"C:\WINDOWS\system32\svchost.exe -k UnistackSvcGroup -s WpnUserService" "CrossDeviceService",0.0315,0.0000,15808,"""C:\Program Files\WindowsApps\MicrosoftWindows.CrossDevice_1.25082.21.0_x64__cw5n1h2txyewy\CrossDeviceService.exe"" " "EpmService",0.0315,0.0000,5440,"""C:\Program Files\Microsoft EPM Agent\EPMService\EpmService.exe""" "conhost",0.0300,84.4341,42996,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "conhost",0.0300,40.9768,45792,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "ServiceHub.Host.dotnet.x64",0.0300,0.0000,18732,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\ServiceHub\Hosts\ServiceHub.Host.dotnet.x64\ServiceHub.Host.dotnet.x64.exe"" dotnet$C94B8CFE-E3FD-4BAF-A941-2866DBB566FE net.pipe://1978095EEE757A78F755D74184C209DDF30C6 ""/TelemetrySession:{\""TelemetryLevel\"":null,\""IsOptedIn\"":true,\""HostName\"":\""Dev14\"",\""AppInsightsInstrumentationKey\"":\""f144292e-e3b2-4011-ac90-20e5c03fbce5\"",\""AsimovInstrumentationKey\"":\""AIF-312cbd79-9dbb-4c48-a7da-3cc2a931cb70\"",\""CollectorApiKey\"":\""f3e86b4023cc43f0be495508d51f588a-f70d0e59-0fb0-4473-9f19-b4024cc340be-7296\"",\""AppId\"":1001,\""UserId\"":\""2dba2122-c8a1-45b6-ac82-001f5865d3e3\"",\""Id\"":\""43746843-c2ce-42ef-9bc7-521b96990f7c\"",\""ProcessStartTime\"":638913092465839523,\""SkuName\"":\""VS_Enterprise\"",\""VSExeVersion\"":\""17.14.36408.4\"",\""BucketFiltersToEnableWatsonForFaults\"":[],\""BucketFiltersToAddDumpsToFaults\"":[]}"" $HostRemoteBrokerPipeName" "dllhost",0.0270,0.0000,13556,"C:\WINDOWS\system32\DllHost.exe /Processid:{3EB3C877-1F16-487C-9050-104DBCD66683}" "conhost",0.0255,39.7921,42372,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "svchost",0.0255,0.0000,5752,"C:\WINDOWS\system32\svchost.exe -k whesvc -p -s whesvc" "svchost",0.0255,0.0000,5068,"C:\WINDOWS\system32\svchost.exe -k appmodel -p -s StateRepository" "conhost",0.0240,34.8336,45892,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "ms-teams",0.0240,0.0000,22920,"""C:\Program Files\WindowsApps\MSTeams_25227.201.3887.7121_x64__8wekyb3d8bbwe\ms-teams.exe"" --process_type=native_module --cloud_type=tfw --module_name=SlimCore --native_msg_channel=efae90c4-9140-4abd-9719-30e192fa1062_nm_SlimCore_c_ --session_id=e1192526-138d-4206-a043-c1f4914dc198 /prefetch:1" "conhost",0.0225,32.5879,47800,"\??\C:\WINDOWS\system32\conhost.exe 0x4" "svchost",0.0225,0.0000,3756,"C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -p -s EventLog" "msedgewebview2",0.0210,0.0000,23712,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=Files.exe --webview-exe-version=2.2508.8001.0 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Files\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --disable-background-timer-throttling --disable-features=msEnhancedTrackingPreventionEnabled --mojo-named-platform-channel-pipe=24508.18624.12919052784708742098 /pfhostedapp:8d2be9d860645d1433e7026b8c330424301db0ff" "powershell",0.0210,0.0000,23584,"C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe -NoExit -Command ""& { Import-Module """"""$env:VSAPPIDDIR\..\Tools\Microsoft.VisualStudio.DevShell.dll""""""; Enter-VsDevShell -SkipAutomaticLocation -SetDefaultWindowTitle -InstallPath $env:VSAPPIDDIR\..\..\}""" "StartMenuExperienceHost",0.0210,0.0000,15732,"""C:\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\StartMenuExperienceHost.exe"" -ServerName:App.AppXywbrabmsek0gm3tkwpr5kwzbs55tkqay.mca" "svchost",0.0210,0.0000,2616,"C:\WINDOWS\system32\svchost.exe -k NetworkService -p" "OneDrive",0.0195,0.0000,19892,"""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\OneDrive.exe"" /background" "RuntimeBroker",0.0195,0.0000,14704,"C:\Windows\System32\RuntimeBroker.exe -Embedding" "SenseTVM",0.0195,0.0000,6464,"-" "msedgewebview2",0.0180,0.0000,26776,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe\LocalState\EBWebView"" --webview-exe-name=WebViewHost.exe --webview-exe-version=19.2508.47021.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=5 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330158914 --launch-time-ticks=32183936586 --always-read-main-dll --metrics-shmem-handle=3584,i,10806035289523513747,15074130377410245576,2097152 --field-trial-handle=1848,i,14228515077991255448,8574913679281551647,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msSingleSignOnOSForPrimaryAccountIs" "msiexec",0.0150,0.0000,37100,"""C:\WINDOWS\system32\msiexec.exe"" /quiet /l*v ""C:\WINDOWS\system32\config\systemprofile\AppData\Local\mdm\{72E753E8-1D66-468D-B882-EC8E61A87383}.log"" /qn /i ""C:\WINDOWS\system32\config\systemprofile\AppData\Local\mdm\{E1BF61B7-24EF-47F5-9396-1A6373DD3067}.msi"" " "svchost",0.0150,0.0000,38520,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s wlidsvc" "AlertusDesktopAlert",0.0135,0.0000,25408,"""C:\Program Files (x86)\Alertus Technologies\Alertus Desktop\AlertusDesktopAlert.exe"" startup" "msedgewebview2",0.0135,0.0000,8436,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=Widgets.exe --webview-exe-version=525.22300.0.0 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView"" --noerrdialogs --disk-cache-size=52428800 --edge-webview-is-background --lang=en-US --mojo-named-platform-channel-pipe=1224.13600.16636695828072262375 /pfhostedapp:1ec15097b557f7f931966541b3f105cc5a47009c" "SearchHost",0.0135,0.0000,5140,"""C:\Windows\SystemApps\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\SearchHost.exe"" -ServerName:CortanaUI.AppXstmwaab17q5s3y22tp6apqz7a45vwv65.mca" "msedgewebview2",0.0120,0.0000,17148,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-agent=""Mozilla/5.0 (Windows NT 10.0; Win64; x64; Cortana 1.18.9.23723; 10.0.0.0.29430.1000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.29430 IsWebView2/True (WebView2Version 139.0.3405.102)"" --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\LocalState\EBWebView"" --webview-exe-name=SearchHost.exe --webview-exe-version=2125.20401.0.2000 --embedded-browser-webview=1 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1780,i,2211480256080778027,5783864341995588904,262144 --field-trial-handle=1948,i,16794949237765112938,10744838110969316530,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCus" "PhoneExperienceHost",0.0120,0.0000,21920,"""C:\Program Files\WindowsApps\Microsoft.YourPhone_1.25072.63.0_x64__8wekyb3d8bbwe\PhoneExperienceHost.exe"" -ComServer:Background -Embedding" "Registry",0.0120,0.0000,296,"" "svchost",0.0120,0.0000,2800,"C:\WINDOWS\system32\svchost.exe -k LocalService -p -s nsi" "WUDFHost",0.0120,0.0000,1908,"""C:\Windows\System32\WUDFHost.exe"" -HostGUID:{193a1820-d9ac-4997-8c55-be817523f6aa} -IoEventPortName:\UMDFCommunicationPorts\WUDF\HostProcess-157bda5c-7958-42b6-932a-775815584c1d -SystemEventPortName:\UMDFCommunicationPorts\WUDF\HostProcess-ea6da5aa-96d6-4ad3-8fac-4057f51c553e -IoCancelEventPortName:\UMDFCommunicationPorts\WUDF\HostProcess-cb543c0e-8a47-4a12-9bb9-f492b3ef63ed -NonStateChangingEventPortName:\UMDFCommunicationPorts\WUDF\HostProcess-7e87a0b2-c54f-4bcb-b359-0ed508c7843c -LifetimeId:4702324e-c675-4c94-bb36-d9e5639ea046 -DeviceGroupId:WudfDefaultDevicePool -HostArg:0" "DlpUserAgent",0.0105,0.0000,5880,"""C:\ProgramData\Microsoft\Windows Defender\Platform\4.18.25070.5-0\DlpUserAgent.exe"" " "msedgewebview2",0.0105,0.0000,31524,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Olk\EBWebView"" --webview-exe-name=olk.exe --webview-exe-version=1.2025.806.300 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --always-read-main-dll --metrics-shmem-handle=2052,i,3655781657003280441,16471773334285400042,524288 --field-trial-handle=1940,i,8033129406060731551,14143038207632028611,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAbydos,msAbydosGestureSupport,msAbydosHandwritingAttr,msAggressiveCacheTrimming,msCustomDataPartition,msEnhancedTextContrast,msSingleSignOnOSForPrimaryAccountIsShared,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,C" "msedgewebview2",0.0105,0.0000,27868,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=Calendar.exe --webview-exe-version=2.2508.8001.0 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Calendar\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --disable-background-timer-throttling --disable-features=msEnhancedTrackingPreventionEnabled --mojo-named-platform-channel-pipe=23828.27764.6576086402115476544 /pfhostedapp:a4a3cd379b99ec60983c9a9c438ccaad66ddb308" "msedgewebview2",0.0090,0.0000,22364,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView"" --webview-exe-name=ms-teams.exe --webview-exe-version=25227.201.3887.7121 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1672,i,11217648657666743546,15881069491224149345,262144 --field-trial-handle=1848,i,9232284790936083051,8827603450831938181,262144 --enable-features=AutofillReplaceCachedWebElementsByRendererIds,DocumentPolicyIncludeJSCallStacksInCrashReports,ForceSWDCompWhenDCompFallbackRequired,PartitionedCookies,PreferredAudioOutputDevices,SharedArrayBuffer,SkipGrantAccessToDataPathIfAlreadySet,ThirdPartyStoragePartitioning," "msedgewebview2",0.0090,0.0000,17176,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --noerrdialogs --user-agent=""Mozilla/5.0 (Windows NT 10.0; Win64; x64; Cortana 1.18.9.23723; 10.0.0.0.29430.1000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.29430 IsWebView2/True (WebView2Version 139.0.3405.102)"" --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\LocalState\EBWebView"" --webview-exe-name=SearchHost.exe --webview-exe-version=2125.20401.0.2000 --embedded-browser-webview=1 --always-read-main-dll --metrics-shmem-handle=2180,i,11053815033230673970,12044020726328619558,524288 --field-trial-handle=1948,i,16794949237765112938,10744838110969316530,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msEdgeFluentOverlayScrollbar,msWebView2NoTabForScreenShare" "msedgewebview2",0.0090,0.0000,28768,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Calendar\EBWebView"" --webview-exe-name=Calendar.exe --webview-exe-version=2.2508.8001.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --disable-background-timer-throttling --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=5 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330158810 --launch-time-ticks=32200742489 --always-read-main-dll --metrics-shmem-handle=3616,i,18121546279730051107,1773683472842625965,2097152 --field-trial-handle=1844,i,14076789075349774618,5990026520275620378,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartitio" "svchost",0.0090,5.4607,3288,"C:\WINDOWS\system32\svchost.exe -k NetworkService -p" "LsaIso",0.0075,0.0000,1612,"\??\C:\WINDOWS\system32\lsaiso.exe -CredGuard -KeyGuard" "msedgewebview2",0.0075,0.0000,28260,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Files\EBWebView"" --webview-exe-name=Files.exe --webview-exe-version=2.2508.8001.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1684,i,12036929097228022419,13501132122943727893,262144 --field-trial-handle=1888,i,16605339906420287399,11502722819294103519,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,CollectAVProdu" "msedgewebview2",0.0075,0.0000,24724,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=WebViewHost.exe --webview-exe-version=19.2508.47021.0 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe\LocalState\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --disable-features=msEnhancedTrackingPreventionEnabled --enable-features=msSingleSignOnOSForPrimaryAccountIsShared --mojo-named-platform-channel-pipe=26552.26364.17986687398486298476 /pfhostedapp:1b1e04dbbaf59080f80ec12ce03b9627f1473e63" "msedgewebview2",0.0075,0.0000,17212,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=OneDrive.exe --webview-exe-version=25.149.0803.0003 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=1 --disable-features=msEnhancedTrackingPreventionEnabled --mojo-named-platform-channel-pipe=19892.19040.4596750522587944337 /pfhostedapp:36f66206d9a5f07f567effabe737fb9cf4c3919a" "olk",0.0075,0.0000,16472,"""C:\Program Files\WindowsApps\Microsoft.OutlookForWindows_1.2025.806.300_x64__8wekyb3d8bbwe\olk.exe"" --restart-on-update=3" "RuntimeBroker",0.0075,0.0000,3360,"C:\Windows\System32\RuntimeBroker.exe -Embedding" "ServiceHub.ThreadedWaitDialog",0.0075,0.0000,21280,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\ServiceHub\Hosts\ServiceHub.Host.dotnet.x64\ServiceHub.ThreadedWaitDialog.exe"" dotnet$ThreadedWaitDialog net.pipe://1978095EEE757A78F755D74184C209DDF30C6 ""/TelemetrySession:{\""TelemetryLevel\"":null,\""IsOptedIn\"":true,\""HostName\"":\""Dev14\"",\""AppInsightsInstrumentationKey\"":\""f144292e-e3b2-4011-ac90-20e5c03fbce5\"",\""AsimovInstrumentationKey\"":\""AIF-312cbd79-9dbb-4c48-a7da-3cc2a931cb70\"",\""CollectorApiKey\"":\""f3e86b4023cc43f0be495508d51f588a-f70d0e59-0fb0-4473-9f19-b4024cc340be-7296\"",\""AppId\"":1001,\""UserId\"":\""2dba2122-c8a1-45b6-ac82-001f5865d3e3\"",\""Id\"":\""43746843-c2ce-42ef-9bc7-521b96990f7c\"",\""ProcessStartTime\"":638913092465839523,\""SkuName\"":\""VS_Enterprise\"",\""VSExeVersion\"":\""17.14.36408.4\"",\""BucketFiltersToEnableWatsonForFaults\"":[],\""BucketFiltersToAddDumpsToFaults\"":[]}"" $HostRemoteBrokerPipeName" "svchost",0.0075,0.0000,3708,"C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetworkFirewall -p" "svchost",0.0075,0.0000,2780,"C:\WINDOWS\System32\svchost.exe -k netsvcs -p -s BDESVC" "WebViewHost",0.0075,0.0000,26552,"""C:\Program Files\WindowsApps\Microsoft.MicrosoftOfficeHub_19.2508.47021.0_x64__8wekyb3d8bbwe\WebViewHost.exe"" autostart" "backgroundTaskHost",0.0060,0.0000,20724,"""C:\WINDOWS\system32\backgroundTaskHost.exe"" -ServerName:App.AppXe9cvj1thv1hmcw0cs98xm3r97tyzy2xs.mca" "Calendar",0.0060,0.0000,23828,"""C:\Program Files\WindowsApps\Microsoft.M365Companions_2.2508.8001.0_x64__8wekyb3d8bbwe\Calendar\Calendar.exe"" /minimize " "msedge",0.0060,0.0000,23604,"""C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"" --no-startup-window" "msedgewebview2",0.0060,0.0000,18848,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView"" --webview-exe-name=Widgets.exe --webview-exe-version=525.22300.0.0 --embedded-browser-webview=1 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1708,i,13275522317397142690,12352364910837198964,262144 --field-trial-handle=1900,i,16685342306069031692,9043298843737266012,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,CollectAVProductsInfo,CollectCodeIntegrityInfo,En" "msedgewebview2",0.0060,0.0000,28616,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Files\EBWebView"" --webview-exe-name=Files.exe --webview-exe-version=2.2508.8001.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --disable-background-timer-throttling --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=5 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330158811 --launch-time-ticks=32200539892 --always-read-main-dll --metrics-shmem-handle=3456,i,9187861819967817321,14856818503084196906,2097152 --field-trial-handle=1888,i,16605339906420287399,11502722819294103519,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msW" "OneDrive.Sync.Service",0.0060,0.0000,18964,"""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\25.149.0803.0003\OneDrive.Sync.Service.exe"" " "People",0.0060,0.0000,18232,"""C:\Program Files\WindowsApps\Microsoft.M365Companions_2.2508.8001.0_x64__8wekyb3d8bbwe\People\People.exe"" /minimize " "ServiceHub.RoslynCodeAnalysisService",0.0060,0.0000,16236,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\ServiceHub\Hosts\ServiceHub.Host.dotnet.x64\ServiceHub.RoslynCodeAnalysisService.exe"" dotnet$RoslynCodeAnalysisService net.pipe://1978095EEE757A78F755D74184C209DDF30C6 ""/TelemetrySession:{\""TelemetryLevel\"":null,\""IsOptedIn\"":true,\""HostName\"":\""Dev14\"",\""AppInsightsInstrumentationKey\"":\""f144292e-e3b2-4011-ac90-20e5c03fbce5\"",\""AsimovInstrumentationKey\"":\""AIF-312cbd79-9dbb-4c48-a7da-3cc2a931cb70\"",\""CollectorApiKey\"":\""f3e86b4023cc43f0be495508d51f588a-f70d0e59-0fb0-4473-9f19-b4024cc340be-7296\"",\""AppId\"":1001,\""UserId\"":\""2dba2122-c8a1-45b6-ac82-001f5865d3e3\"",\""Id\"":\""43746843-c2ce-42ef-9bc7-521b96990f7c\"",\""ProcessStartTime\"":638913092465839523,\""SkuName\"":\""VS_Enterprise\"",\""VSExeVersion\"":\""17.14.36408.4\"",\""BucketFiltersToEnableWatsonForFaults\"":[],\""BucketFiltersToAddDumpsToFaults\"":[]}"" \\.\pipe\3A505534-A1E9-424B-9050-E572AE5293DC" "CrossDeviceResume",0.0045,0.0000,3688,"""C:\Windows\SystemApps\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\CrossDeviceResume.exe"" /tileid MicrosoftWindows.Client.CBS_cw5n1h2txyewy!CrossDeviceResumeApp" "msedgewebview2",0.0045,0.0000,28548,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Calendar\EBWebView"" --webview-exe-name=Calendar.exe --webview-exe-version=2.2508.8001.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1680,i,7670917632367265620,12804967711196561718,262144 --field-trial-handle=1844,i,14076789075349774618,5990026520275620378,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,CollectAVP" "msedgewebview2",0.0045,0.0000,17260,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=utility --utility-sub-type=storage.mojom.StorageService --lang=en-US --service-sandbox-type=service --noerrdialogs --user-agent=""Mozilla/5.0 (Windows NT 10.0; Win64; x64; Cortana 1.18.9.23723; 10.0.0.0.29430.1000) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.29430 IsWebView2/True (WebView2Version 139.0.3405.102)"" --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\LocalState\EBWebView"" --webview-exe-name=SearchHost.exe --webview-exe-version=2125.20401.0.2000 --embedded-browser-webview=1 --always-read-main-dll --metrics-shmem-handle=2460,i,17322209671434086416,1922754234432043119,524288 --field-trial-handle=1948,i,16794949237765112938,10744838110969316530,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msEdgeFluentOverlayScrollbar,msWebView2NoTabForScreenSha" "PerfWatson2",0.0045,0.0000,9268,""".\PerfWatson2.exe"" -p 21220 -version 16 -role 3 {%22TelemetryLevel%22:null,%22IsOptedIn%22:true,%22HostName%22:%22Dev14%22,%22AppInsightsInstrumentationKey%22:%22f144292e-e3b2-4011-ac90-20e5c03fbce5%22,%22AsimovInstrumentationKey%22:%22AIF-312cbd79-9dbb-4c48-a7da-3cc2a931cb70%22,%22CollectorApiKey%22:%22f3e86b4023cc43f0be495508d51f588a-f70d0e59-0fb0-4473-9f19-b4024cc340be-7296%22,%22AppId%22:1001,%22UserId%22:%222dba2122-c8a1-45b6-ac82-001f5865d3e3%22,%22Id%22:%2243746843-c2ce-42ef-9bc7-521b96990f7c%22,%22ProcessStartTime%22:638913092465839523,%22SkuName%22:%22VS_Enterprise%22,%22VSExeVersion%22:%2217.14.36408.4%22,%22BucketFiltersToEnableWatsonForFaults%22:[],%22BucketFiltersToAddDumpsToFaults%22:[]}" "RAVCpl64",0.0045,0.0000,15900,"""C:\Program Files\Realtek\Audio\HDA\RAVCpl64.exe"" -s" "RuntimeBroker",0.0045,0.0000,516,"C:\Windows\System32\RuntimeBroker.exe -Embedding" "ShellHost",0.0045,0.0000,40388,"""C:\Windows\System32\ShellHost.exe""" "StandardCollector.Service",0.0045,0.0000,4636,"""C:\Program Files (x86)\Microsoft Visual Studio\Shared\Common\DiagnosticsHub.Collection.Service\StandardCollector.Service.exe""" "svchost",0.0045,0.0000,2156,"C:\WINDOWS\system32\svchost.exe -k LocalServiceNoNetwork -p" "svchost",0.0045,0.0000,7964,"C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p -s PcaSvc" "svchost",0.0045,0.0000,4444,"C:\WINDOWS\System32\svchost.exe -k netsvcs -p -s ShellHWDetection" "TrustedInstaller",0.0045,0.0000,3540,"C:\WINDOWS\servicing\TrustedInstaller.exe" "audiodg",0.0030,0.0000,10232,"C:\WINDOWS\system32\AUDIODG.EXE 0x00000000000007EC 0x0000000000000704" "Files",0.0030,0.0000,24508,"""C:\Program Files\WindowsApps\Microsoft.M365Companions_2.2508.8001.0_x64__8wekyb3d8bbwe\Files\Files.exe"" /minimize /restart" "fontdrvhost",0.0030,0.0000,1960,"""fontdrvhost.exe""" "GlobalSecureAccessPolicyRetrieverService",0.0030,0.0000,25772,"""C:\Program Files\Global Secure Access Client\PolicyService\GlobalSecureAccessPolicyRetrieverService.exe""" "MoNotificationUx",0.0030,0.0000,40448,"C:\WINDOWS\uus\AMD64\MoNotificationUx.exe /NotificationType Reboot_Engaged /FormFactor Passive /CV bZdKO9dkakOz+3Gj.1.0.0" "msedgewebview2",0.0030,0.0000,31680,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Olk\EBWebView"" --webview-exe-name=olk.exe --webview-exe-version=1.2025.806.300 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=5 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330158751 --launch-time-ticks=32210213114 --always-read-main-dll --metrics-shmem-handle=3412,i,2909241507951412939,16861473697940000721,2097152 --field-trial-handle=1940,i,8033129406060731551,14143038207632028611,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAbydos,msAbydosGestureSupport,msAbydosHandwritingAttr,msAggressiveCacheTrimming,msCustomDataPartition,msEnhancedTextContrast,msSingleSignOnO" "msedgewebview2",0.0030,0.0000,28252,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\People\EBWebView"" --webview-exe-name=People.exe --webview-exe-version=2.2508.8001.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1720,i,9304133045324938329,402785107203038817,262144 --field-trial-handle=1904,i,7208261295524124571,16047749738743927188,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,CollectAVProduct" "msedgewebview2",0.0030,0.0000,22640,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=crashpad-handler --user-data-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView /prefetch:4 /pfhostedapp:3281cef100f69e01b7d11953c64af802068f63bb --monitor-self-annotation=ptype=crashpad-handler --database=C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView\Crashpad --metrics-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView --annotation=IsOfficialBuild=1 --annotation=channel= --annotation=chromium-version=139.0.7258.128 ""--annotation=exe=C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --annotation=plat=Win64 ""--annotation=prod=Edge WebView2"" --annotation=ver=139.0.3405.102 --initial-client-data=0x17c,0x180,0x184,0x158,0x190,0x7fff2f74c188,0x7fff2f74c194,0x7fff2f74c1a0" "msedgewebview2",0.0030,0.0000,24280,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --embedded-browser-webview=1 --webview-exe-name=People.exe --webview-exe-version=2.2508.8001.0 --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\People\EBWebView"" --noerrdialogs --embedded-browser-webview-dpi-awareness=2 --disable-background-timer-throttling --disable-features=msEnhancedTrackingPreventionEnabled --mojo-named-platform-channel-pipe=18232.24568.11851610380818306060 /pfhostedapp:fe6d713621f52aef031cb2cd8b5b199c4c7f0ea2" "msedgewebview2",0.0030,0.0000,28580,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=renderer --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\People\EBWebView"" --webview-exe-name=People.exe --webview-exe-version=2.2508.8001.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --disable-background-timer-throttling --video-capture-use-gpu-memory-buffer --lang=en-US --device-scale-factor=1.25 --num-raster-threads=4 --enable-main-frame-before-activation --renderer-client-id=5 --js-flags=""--expose-gc --ms-user-locale="" --time-ticks-at-unix-epoch=-1755680330158811 --launch-time-ticks=32200556055 --always-read-main-dll --metrics-shmem-handle=3636,i,16962075880517080349,3001479791945945315,2097152 --field-trial-handle=1904,i,7208261295524124571,16047749738743927188,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,ms" "msedgewebview2",0.0030,0.0000,27756,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=crashpad-handler --user-data-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\People\EBWebView /prefetch:4 /pfhostedapp:fe6d713621f52aef031cb2cd8b5b199c4c7f0ea2 --monitor-self-annotation=ptype=crashpad-handler --database=C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\People\EBWebView\Crashpad --metrics-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\People\EBWebView --annotation=IsOfficialBuild=1 --annotation=channel= --annotation=chromium-version=139.0.7258.128 ""--annotation=exe=C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --annotation=plat=Win64 ""--annotation=prod=Edge WebView2"" --annotation=ver=139.0.3405.102 --initial-client-data=0x180,0x184,0x188,0x15c,0x190,0x7fff2f74c188,0x7fff2f74c194,0x7fff2f74c" "msedgewebview2",0.0030,0.0000,19412,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=crashpad-handler --user-data-dir=C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\EBWebView /prefetch:4 /pfhostedapp:36f66206d9a5f07f567effabe737fb9cf4c3919a --monitor-self-annotation=ptype=crashpad-handler --database=C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\EBWebView\Crashpad --metrics-dir=C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\EBWebView --annotation=IsOfficialBuild=1 --annotation=channel= --annotation=chromium-version=139.0.7258.128 ""--annotation=exe=C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --annotation=plat=Win64 ""--annotation=prod=Edge WebView2"" --annotation=ver=139.0.3405.102 --initial-client-data=0x194,0x198,0x19c,0x140,0x1a4,0x7fff2f74c188,0x7fff2f74c194,0x7fff2f74c1a0" "msedgewebview2",0.0030,0.0000,8700,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.MicrosoftOfficeHub_8wekyb3d8bbwe\LocalState\EBWebView"" --webview-exe-name=WebViewHost.exe --webview-exe-version=19.2508.47021.0 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1700,i,4695494353964021269,10025719251604277449,262144 --field-trial-handle=1848,i,14228515077991255448,8574913679281551647,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msSingleSignOnOSForPrimaryAccountIsShared,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,Close" "OpenConsole",0.0030,0.0000,44820,"""c:\program files\microsoft visual studio\2022\enterprise\common7\ide\commonextensions\microsoft\terminal\ServiceHub\os64\OpenConsole.exe"" --headless --width 152 --height 30 --signal 0x7a8 --server 0x7e4" "RtkAudUService64",0.0030,0.0000,12072,"""C:\Windows\System32\DriverStore\FileRepository\realtekservice.inf_amd64_291337223b900dd5\RtkAudUService64.exe"" -background" "SecurityHealthSystray",0.0030,0.0000,18844,"""C:\Windows\System32\SecurityHealthSystray.exe"" " "svchost",0.0030,0.0000,4804,"C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p -s Wcmsvc" "svchost",0.0030,0.0000,4380,"C:\WINDOWS\System32\svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService" "svchost",0.0030,0.0000,3080,"C:\WINDOWS\system32\svchost.exe -k LocalServiceNetworkRestricted -p -s TimeBrokerSvc" "svchost",0.0030,0.0000,23760,"C:\WINDOWS\System32\svchost.exe -k Camera -s FrameServer" "svchost",0.0030,0.0000,5088,"C:\WINDOWS\system32\svchost.exe -k LocalSystemNetworkRestricted -p -s dot3svc" "svchost",0.0030,0.0000,1860,"C:\WINDOWS\system32\svchost.exe -k LocalServiceAndNoImpersonation -s SCardSvr" "AggregatorHost",0.0015,0.0000,10176,"AggregatorHost.exe" "InventoryService",0.0015,0.0000,5396,"""C:\Program Files\Microsoft Device Inventory Agent\InventoryService\InventoryService.exe""" "Microsoft.Management.Services.IntuneWindowsAgent",0.0015,0.0000,6332,"""C:\Program Files (x86)\Microsoft Intune Management Extension\Microsoft.Management.Services.IntuneWindowsAgent.exe""" "msedge",0.0015,0.0000,19680,"""C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"" --type=crashpad-handler ""--user-data-dir=C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Edge\User Data"" /prefetch:4 --monitor-self-annotation=ptype=crashpad-handler ""--database=C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Edge\User Data\Crashpad"" ""--metrics-dir=C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Edge\User Data"" --annotation=IsOfficialBuild=1 --annotation=channel= --annotation=chromium-version=139.0.7258.128 ""--annotation=exe=C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"" --annotation=plat=Win64 --annotation=prod=Edge --annotation=ver=139.0.3405.102 --initial-client-data=0x26c,0x270,0x274,0x268,0x27c,0x7fff2f74c188,0x7fff2f74c194,0x7fff2f74c1a0" "msedgewebview2",0.0015,0.0000,31536,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\Olk\EBWebView"" --webview-exe-name=olk.exe --webview-exe-version=1.2025.806.300 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1724,i,3980312206169518153,10127800526900623321,262144 --field-trial-handle=1940,i,8033129406060731551,14143038207632028611,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAbydos,msAbydosGestureSupport,msAbydosHandwritingAttr,msAggressiveCacheTrimming,msCustomDataPartition,msEnhancedTextContrast,msSingleSignOnOSForPrimaryAccountIsShared,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPer" "msedgewebview2",0.0015,0.0000,28020,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=crashpad-handler --user-data-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Calendar\EBWebView /prefetch:4 /pfhostedapp:a4a3cd379b99ec60983c9a9c438ccaad66ddb308 --monitor-self-annotation=ptype=crashpad-handler --database=C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Calendar\EBWebView\Crashpad --metrics-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\Microsoft.M365Companions_8wekyb3d8bbwe\LocalState\Calendar\EBWebView --annotation=IsOfficialBuild=1 --annotation=channel= --annotation=chromium-version=139.0.7258.128 ""--annotation=exe=C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --annotation=plat=Win64 ""--annotation=prod=Edge WebView2"" --annotation=ver=139.0.3405.102 --initial-client-data=0x184,0x188,0x18c,0x164,0x194,0x7fff2f74c188,0x7fff2f74c194,0x7ff" "msedgewebview2",0.0015,0.0000,18800,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=gpu-process --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\OneDrive\EBWebView"" --webview-exe-name=OneDrive.exe --webview-exe-version=25.149.0803.0003 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=1 --no-pre-read-main-dll --gpu-preferences=SAAAAAAAAADgAAAIAAAAAAAAAAAAAGAAAQAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA== --always-read-main-dll --metrics-shmem-handle=1712,i,1063670666240466674,9387671468166555505,262144 --field-trial-handle=1796,i,2078209863016788888,5383923420903493488,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,CollectAVProductsInfo,CollectCodeIntegrityInfo,EnableHangW" "msedgewebview2",0.0015,0.0000,9996,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=crashpad-handler --user-data-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView /prefetch:4 /pfhostedapp:1ec15097b557f7f931966541b3f105cc5a47009c --monitor-self-annotation=ptype=crashpad-handler --database=C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView\Crashpad --metrics-dir=C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView --annotation=IsOfficialBuild=1 --annotation=channel= --annotation=chromium-version=139.0.7258.128 ""--annotation=exe=C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --annotation=plat=Win64 ""--annotation=prod=Edge WebView2"" --annotation=ver=139.0.3405.102 --initial-client-data=0x17c,0x180,0x184,0x158,0x18c,0x7fff2f74c188,0x7fff2f" "msedgewebview2",0.0015,0.0000,22272,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=utility --utility-sub-type=storage.mojom.StorageService --lang=en-US --service-sandbox-type=service --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MSTeams_8wekyb3d8bbwe\LocalCache\Microsoft\MSTeams\EBWebView"" --webview-exe-name=ms-teams.exe --webview-exe-version=25227.201.3887.7121 --embedded-browser-webview=1 --embedded-browser-webview-dpi-awareness=2 --no-pre-read-main-dll --always-read-main-dll --metrics-shmem-handle=1944,i,4751668418685729185,3956135311537094280,524288 --field-trial-handle=1848,i,9232284790936083051,8827603450831938181,262144 --enable-features=AutofillReplaceCachedWebElementsByRendererIds,DocumentPolicyIncludeJSCallStacksInCrashReports,ForceSWDCompWhenDCompFallbackRequired,PartitionedCookies,PreferredAudioOutputDevices,SharedArrayBuffer,SkipGrantAccessToDataPathIfAlreadySet,ThirdPartyStoragePartitioning,msAbydos,msAbydosGestureSupport,msAbydosHandwritingAt" "msedgewebview2",0.0015,0.0000,15096,"""C:\Program Files (x86)\Microsoft\EdgeWebView\Application\139.0.3405.102\msedgewebview2.exe"" --type=utility --utility-sub-type=network.mojom.NetworkService --lang=en-US --service-sandbox-type=none --noerrdialogs --user-data-dir=""C:\Users\benjaming.REDMOND\AppData\Local\Packages\MicrosoftWindows.Client.WebExperience_cw5n1h2txyewy\LocalState\EBWebView"" --webview-exe-name=Widgets.exe --webview-exe-version=525.22300.0.0 --embedded-browser-webview=1 --no-pre-read-main-dll --always-read-main-dll --metrics-shmem-handle=2064,i,10059151636341397096,3423782810395223296,524288 --field-trial-handle=1900,i,16685342306069031692,9043298843737266012,262144 --enable-features=ForceSWDCompWhenDCompFallbackRequired,msAggressiveCacheTrimming,msCustomDataPartition,msWebView2NoTabForScreenShare,msWindowsTaskManager --disable-features=BackForwardCache,BackgroundTabLoadingFromPerformanceManager,CloseOmniboxPopupOnInactiveAreaClick,CollectAVProductsInfo,CollectCodeIntegrityInfo,EnableHangWatcher,FilterAdsOnAbusiveSites,GetWifiProtocol" "msinfo32",0.0015,0.0000,13752,"""C:\WINDOWS\system32\msinfo32.exe"" " "SCNotification",0.0015,0.0000,18140,"""C:\Windows\CCM\SCNotification.exe""" "SearchProtocolHost",0.0015,0.0000,49352,"""C:\WINDOWS\System32\SearchProtocolHost.exe"" Global\UsGthrFltPipeMssGthrPipe37_ Global\UsGthrCtrlFltPipeMssGthrPipe37 1 -2147483646 ""Software\Microsoft\Windows Search"" ""Mozilla/4.0 (compatible; MSIE 6.0; Windows NT; MS Search 4.0 Robot)"" ""C:\ProgramData\Microsoft\Search\Data\Temp\usgthrsvc"" ""DownLevelDaemon"" " "ServiceHub.IndexingService",0.0015,0.0000,18328,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\ServiceHub\Hosts\ServiceHub.Host.dotnet.x64\ServiceHub.IndexingService.exe"" dotnet$IndexingService net.pipe://1978095EEE757A78F755D74184C209DDF30C6 ""/TelemetrySession:{\""TelemetryLevel\"":null,\""IsOptedIn\"":true,\""HostName\"":\""Dev14\"",\""AppInsightsInstrumentationKey\"":\""f144292e-e3b2-4011-ac90-20e5c03fbce5\"",\""AsimovInstrumentationKey\"":\""AIF-312cbd79-9dbb-4c48-a7da-3cc2a931cb70\"",\""CollectorApiKey\"":\""f3e86b4023cc43f0be495508d51f588a-f70d0e59-0fb0-4473-9f19-b4024cc340be-7296\"",\""AppId\"":1001,\""UserId\"":\""2dba2122-c8a1-45b6-ac82-001f5865d3e3\"",\""Id\"":\""43746843-c2ce-42ef-9bc7-521b96990f7c\"",\""ProcessStartTime\"":638913092465839523,\""SkuName\"":\""VS_Enterprise\"",\""VSExeVersion\"":\""17.14.36408.4\"",\""BucketFiltersToEnableWatsonForFaults\"":[],\""BucketFiltersToAddDumpsToFaults\"":[]}"" $HostRemoteBrokerPipeName" "ServiceHub.IntellicodeModelService",0.0015,0.0000,19716,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\ServiceHub\Hosts\ServiceHub.Host.netfx.x64\ServiceHub.IntellicodeModelService.exe"" netfx.x64$IntellicodeModelService net.pipe://1978095EEE757A78F755D74184C209DDF30C6 ""/AppBasePath:C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\\"" /ConfigFile:C:\Users\benjaming.REDMOND\AppData\Local\Microsoft\VisualStudio\17.0_60475fee\devenv.exe.config" "ServiceHub.TestWindowStoreHost",0.0015,0.0000,18532,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\ServiceHub\Hosts\ServiceHub.Host.dotnet.x64\ServiceHub.TestWindowStoreHost.exe"" dotnet.x64$TestWindowStoreHost net.pipe://1978095EEE757A78F755D74184C209DDF30C6 ""/TelemetrySession:{\""TelemetryLevel\"":null,\""IsOptedIn\"":true,\""HostName\"":\""Dev14\"",\""AppInsightsInstrumentationKey\"":\""f144292e-e3b2-4011-ac90-20e5c03fbce5\"",\""AsimovInstrumentationKey\"":\""AIF-312cbd79-9dbb-4c48-a7da-3cc2a931cb70\"",\""CollectorApiKey\"":\""f3e86b4023cc43f0be495508d51f588a-f70d0e59-0fb0-4473-9f19-b4024cc340be-7296\"",\""AppId\"":1001,\""UserId\"":\""2dba2122-c8a1-45b6-ac82-001f5865d3e3\"",\""Id\"":\""43746843-c2ce-42ef-9bc7-521b96990f7c\"",\""ProcessStartTime\"":638913092465839523,\""SkuName\"":\""VS_Enterprise\"",\""VSExeVersion\"":\""17.14.36408.4\"",\""BucketFiltersToEnableWatsonForFaults\"":[],\""BucketFiltersToAddDumpsToFaults\"":[]}"" \\.\pipe\3A505534-A1E9-424B-9050-E572AE5293DC" "svchost",0.0015,0.0000,16120,"C:\WINDOWS\system32\svchost.exe -k ClipboardSvcGroup -p -s cbdhsvc" "svchost",0.0015,0.0000,3952,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s lfsvc" "svchost",0.0015,0.0000,2244,"C:\WINDOWS\system32\svchost.exe -k UserProfileService -p -s ProfSvc" "svchost",0.0015,0.0000,3992,"C:\WINDOWS\System32\svchost.exe -k netsvcs" "svchost",0.0015,0.0000,8260,"C:\WINDOWS\system32\svchost.exe -k NetSvcs -p -s HNS" "svchost",0.0015,0.0000,6160,"C:\WINDOWS\system32\svchost.exe -k netsvcs -p -s LanmanServer" "svchost",0.0015,0.0000,1896,"C:\WINDOWS\System32\svchost.exe -k NetworkService -p -s LanmanWorkstation" "svchost",0.0015,0.0000,12908,"C:\WINDOWS\System32\svchost.exe -k LocalServiceNetworkRestricted -s RmSvc" "svchost",0.0015,0.0000,3412,"C:\WINDOWS\System32\svchost.exe -k NetSvcs -p -s IpHlpSvc" "svchost",0.0015,0.0000,3196,"C:\WINDOWS\System32\svchost.exe -k PeerDist -s PeerDistSvc" "svchost",0.0015,0.0000,1248,"C:\WINDOWS\system32\svchost.exe -k RPCSS -p" "taskhostw",0.0015,0.0000,14240,"taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E}" "VBCSCompiler",0.0015,0.0000,18640,"""C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\Roslyn\VBCSCompiler.exe"" ""-pipename:JVjPNngeOMqiFdoh15dX0nMeMebM0yP_g1S1LVh2Brs""" "WidgetService",0.0015,0.0000,11188,"""C:\Program Files\WindowsApps\Microsoft.WidgetsPlatformRuntime_1.6.9.0_x64__8wekyb3d8bbwe\WidgetService\WidgetService.exe"" -RegisterProcessAsComServer -Embedding" ================================================ FILE: src/ProfileExplorerCoreTests/TestData/Symbols/MsoTrace/Mso20Win32Client.pdb ================================================ [File too large to display: 20.5 MB] ================================================ FILE: src/ProfileExplorerCoreTests/TestData/Traces/MsoTrace/trace.etl ================================================ version https://git-lfs.github.com/spec/v1 oid sha256:c16e3a2413a9e45c1fbef6cfcc695b77c9d925b0160d53e028d2ba43ba59b817 size 318242816 ================================================ FILE: src/ProfileExplorerCoreTests/TestDataHelper.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; namespace ProfileExplorer.CoreTests; /// /// Helper class for accessing test data files in a consistent manner. /// public static class TestDataHelper { private static readonly string TestDataRoot; static TestDataHelper() { // Get the directory where the test assembly is located var assemblyLocation = Assembly.GetExecutingAssembly().Location; var assemblyDirectory = Path.GetDirectoryName(assemblyLocation); // Navigate up to find the TestData directory // The build output is typically in bin/Debug/net8.0/, so we need to go up several levels var currentDir = assemblyDirectory; while (currentDir != null && !Directory.Exists(Path.Combine(currentDir, "TestData"))) { currentDir = Directory.GetParent(currentDir)?.FullName; } if (currentDir != null) { TestDataRoot = Path.Combine(currentDir, "TestData"); } else { throw new DirectoryNotFoundException("Could not locate TestData directory relative to test assembly"); } } /// /// Gets the root path for all test data. /// public static string GetTestDataRoot() => TestDataRoot; /// /// Gets the path to a specific trace file. /// /// Name of the test case (e.g., "MsoTrace") /// Name of the trace file (e.g., "trace.etl") /// Full path to the trace file public static string GetTracePath(string testCaseName, string fileName = "trace.etl") { return Path.Combine(TestDataRoot, "Traces", testCaseName, fileName); } /// /// Gets the path to the symbols directory for a test case. /// /// Name of the test case (e.g., "MsoTrace") /// Full path to the symbols directory public static string GetSymbolsPath(string testCaseName) { return Path.Combine(TestDataRoot, "Symbols", testCaseName); } /// /// Gets the path to a specific symbol file. /// /// Name of the test case (e.g., "MsoTrace") /// Name of the PDB file (e.g., "Mso20Win32Client.pdb") /// Full path to the symbol file public static string GetSymbolFilePath(string testCaseName, string fileName) { return Path.Combine(TestDataRoot, "Symbols", testCaseName, fileName); } /// /// Gets the path to the binaries directory for a test case. /// /// Name of the test case (e.g., "MsoTrace") /// Full path to the binaries directory public static string GetBinariesPath(string testCaseName) { return Path.Combine(TestDataRoot, "Binaries", testCaseName); } /// /// Gets the path to a specific binary file. /// /// Name of the test case (e.g., "MsoTrace") /// Name of the binary file (e.g., "Mso20win32client.dll") /// Full path to the binary file public static string GetBinaryFilePath(string testCaseName, string fileName) { return Path.Combine(TestDataRoot, "Binaries", testCaseName, fileName); } /// /// Checks if all required files exist for a test case. /// /// Name of the test case /// Expected trace file name /// List of required symbol files /// List of required binary files /// True if all files exist, false otherwise public static bool ValidateTestCase(string testCaseName, string traceFileName = "trace.etl", string[]? requiredSymbolFiles = null, string[]? requiredBinaryFiles = null) { // Check trace file var tracePath = GetTracePath(testCaseName, traceFileName); if (!File.Exists(tracePath)) { return false; } // Check symbol files if specified if (requiredSymbolFiles != null) { foreach (var symbolFile in requiredSymbolFiles) { var symbolPath = GetSymbolFilePath(testCaseName, symbolFile); if (!File.Exists(symbolPath)) { return false; } } } // Check binary files if specified if (requiredBinaryFiles != null) { foreach (var binaryFile in requiredBinaryFiles) { var binaryPath = GetBinaryFilePath(testCaseName, binaryFile); if (!File.Exists(binaryPath)) { return false; } } } return true; } /// /// Gets information about a specific test case by name. /// /// Name of the test case directory /// TestCaseInfo for the specified test case public static TestCaseInfo GetTestCase(string testCaseName) { return new TestCaseInfo(testCaseName); } /// /// Gets all available test cases by scanning the TestData directory. /// /// List of available test case names public static List GetAvailableTestCases() { var testCases = new List(); var tracesDir = Path.Combine(TestDataRoot, "Traces"); if (Directory.Exists(tracesDir)) { var directories = Directory.GetDirectories(tracesDir); foreach (var dir in directories) { var testCaseName = Path.GetFileName(dir); testCases.Add(testCaseName); } } return testCases; } /// /// Validates that all available test cases have complete data. /// /// Dictionary mapping test case names to their validation status public static Dictionary ValidateAllTestCases() { var results = new Dictionary(); var testCases = GetAvailableTestCases(); foreach (var testCase in testCases) { var info = GetTestCase(testCase); results[testCase] = info.IsValid; } return results; } /// /// Represents information about a test case. /// public class TestCaseInfo { public string TestCaseName { get; } public TestCaseInfo(string testCaseName) { TestCaseName = testCaseName; } public string TracePath => GetTracePath(TestCaseName, "trace.etl"); public string SymbolsPath => GetSymbolsPath(TestCaseName); public string BinariesPath => GetBinariesPath(TestCaseName); /// /// Gets all PDB files for this test case. /// public List PdbFiles { get { var pdbFiles = new List(); var symbolsDir = SymbolsPath; if (Directory.Exists(symbolsDir)) { pdbFiles.AddRange(Directory.GetFiles(symbolsDir, "*.pdb")); } return pdbFiles; } } /// /// Gets all binary files for this test case. /// public List BinaryFiles { get { var binaryFiles = new List(); var binariesDir = BinariesPath; if (Directory.Exists(binariesDir)) { binaryFiles.AddRange(Directory.GetFiles(binariesDir, "*.*")); } return binaryFiles; } } /// /// Checks if this test case has all required files. /// public bool IsValid { get { // Must have trace file if (!File.Exists(TracePath)) { return false; } // Must have symbols directory (but PDB files are optional) if (!Directory.Exists(SymbolsPath)) { return false; } // Must have binaries directory (but binary files are optional) if (!Directory.Exists(BinariesPath)) { return false; } return true; } } /// /// Gets a summary of this test case. /// public string GetSummary() { var summary = $"Test Case: {TestCaseName}\n"; summary += $" Trace: {(File.Exists(TracePath) ? "✓" : "✗")} {TracePath}\n"; summary += $" Symbols: {PdbFiles.Count} PDB file(s)\n"; summary += $" Binaries: {BinaryFiles.Count} binary file(s)\n"; summary += $" Valid: {(IsValid ? "✓" : "✗")}"; return summary; } } } ================================================ FILE: src/ProfileExplorerUI/App.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/App.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Threading.Tasks; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Shell; using System.Xml; using ProfileExplorer.Core.Utilities; using ProfileExplorer.UI.Settings; using ProfileExplorer.UI.Mcp; using ProfileExplorer.Mcp; namespace ProfileExplorer.UI; public class SyntaxFileInfo { public SyntaxFileInfo(string name, string compiler, string path) { Name = name; Compiler = compiler; Path = path; } public string Name { get; set; } public string Compiler { get; set; } public string Path { get; set; } public static bool operator ==(SyntaxFileInfo left, SyntaxFileInfo right) { return EqualityComparer.Default.Equals(left, right); } public static bool operator !=(SyntaxFileInfo left, SyntaxFileInfo right) { return !(left == right); } public override bool Equals(object obj) { return obj is SyntaxFileInfo info && Name == info.Name && Compiler == info.Compiler && Path == info.Path; } public override int GetHashCode() { return HashCode.Combine(Name, Compiler, Path); } } public partial class App : Application { #if DEBUG // For use with "mkdocs serve". private const string HelpLocation = @"http://127.0.0.1:8000"; private const string DocumentationLocation = @"http://127.0.0.1:8000"; #else private const string HelpLocation = @"https://microsoft.github.io/profile-explorer/site"; private const string DocumentationLocation = @"https://microsoft.github.io/profile-explorer"; #endif public const string AutoUpdateInfox64 = @"https://microsoft.github.io/profile-explorer/autoupdater.xml"; public const string AutoUpdateInfoArm64 = @"https://microsoft.github.io/profile-explorer/autoupdater_arm64.xml"; private const string SettingsPath = @"Microsoft\ProfileExplorer"; private const string SettingsFile = "ProfileExplorer.settings"; private const string HelpIndexFile = @"index.json"; private const string LicenseFile = "NOTICE.md"; private const string WorkspacesDirectory = "workspaces"; private const string ScriptsDirectory = "scripts"; private const string ThemesDirectory = "themes"; private const string TraceFile = "ProfileExplorer.log"; private const string BackupTraceFile = "ProfileExplorerBackup.log"; private const string RemarkDefinitionFile = @"remark-settings.json"; private const string SectionDefinitionFile = @"section-settings.json"; private const string FunctionMarkingsFile = @"function-markings.json"; private const string InternalIRSyntaxHighlightingFile = @"ir.xshd"; private const string InternalExtensionFile = @"VSExtension.vsix"; private const string SyntaxFileSearchPattern = @"*.xshd"; private const string SyntaxFileExtension = @"xshd"; private const string FunctionTaskScriptsDirectory = "scripts"; private const string FunctionTaskScriptSearchPattern = @"*.cs"; public static bool IsFirstRun; public static DateTime AppStartTime; public static ApplicationSettings Settings; public static IUISession Session; /// /// When true, suppresses UI dialogs (like source file prompts) during MCP/automation operations. /// public static bool SuppressDialogsForAutomation; private Task? mcpServerTask; private static List cachedSyntaxHighlightingFiles_; public static string ApplicationPath => Process.GetCurrentProcess().MainModule?.FileName; public static string ApplicationDirectory => Path.GetDirectoryName(ApplicationPath); public static string[] GetFunctionTaskScripts() { try { string path = GetSettingsFilePath(FunctionTaskScriptsDirectory); return Directory.GetFiles(path, FunctionTaskScriptSearchPattern); } catch (Exception ex) { Trace.TraceError($"Failed to get function task scripts: {ex}"); return new string[] { }; } } public static string GetCompilerSettingsDirectoryPath(string compilerName) { return GetSettingsFilePath(compilerName); } public static string GetWorkspacesPath() { return GetSettingsFilePath(WorkspacesDirectory); } public static string GetInternalWorkspacesPath() { return GetApplicationFilePath(WorkspacesDirectory); } public static string GetLicenseText() { try { return File.ReadAllText(GetApplicationFilePath(LicenseFile)); } catch (Exception ex) { Trace.TraceError($"Failed to get license text: {ex}"); return ""; } } public static string GetCompilerSettingsFilePath(string file, string compilerName, string extension = "") { // Remove extension if another one should be used. file = string.IsNullOrEmpty(extension) ? file : Path.GetFileNameWithoutExtension(file); return GetSettingsFilePath(compilerName, file, extension); } public static string GetTraceFilePath() { return GetSettingsFilePath(TraceFile); } public static string GetBackupTraceFilePath() { return GetSettingsFilePath(BackupTraceFile); } public static string GetExtensionFilePath() { return GetApplicationFilePath(InternalExtensionFile); } public static string GetInternalSyntaxHighlightingFilePath(string name, string compilerIRName) { var files = GetSyntaxHighlightingFiles(compilerIRName, true); var result = files.Find(item => item.Name == name); return result?.Path; } public static string GetInternalIRSyntaxHighlightingFilePath() { string appDir = ApplicationDirectory; return Path.Combine(appDir, InternalIRSyntaxHighlightingFile); } public static string GetHelpIndexFilePath() { return $"{HelpLocation}/{HelpIndexFile}"; } public static string GetHelpFilePath(string relativeURL) { return $"{HelpLocation}/{relativeURL}"; } public static string GetRemarksDefinitionFilePath(string compilerIRName) { string userFile = GetUserRemarksDefinitionFilePath(compilerIRName); if (File.Exists(userFile)) { return userFile; } string internalFile = GetInternalRemarksDefinitionFilePath(compilerIRName); if (File.Exists(internalFile) && CreateDirectoriesForFile(userFile)) { try { File.Copy(internalFile, userFile); } catch (Exception ex) { Trace.TraceError($"Failed to get copy file {internalFile} to {userFile}: {ex}"); return null; } return userFile; } return null; } public static string GetSectionsDefinitionFilePath(string compilerIRName) { string userFile = GetUserSectionsDefinitionFilePath(compilerIRName); if (File.Exists(userFile)) { return userFile; } string internalFile = GetInternalSectionsDefinitionFilePath(compilerIRName); if (File.Exists(internalFile) && CreateDirectoriesForFile(userFile)) { try { File.Copy(internalFile, userFile); } catch (Exception ex) { Trace.TraceError($"Failed to get copy file {internalFile} to {userFile}: {ex}"); } return userFile; } return null; } public static string GetUserRemarksDefinitionFilePath(string compilerIRName) { return GetSettingsFilePath(compilerIRName, RemarkDefinitionFile); } public static string GetInternalRemarksDefinitionFilePath(string compilerIRName) { return GetApplicationFilePath(compilerIRName, RemarkDefinitionFile); } public static string GetUserSectionsDefinitionFilePath(string compilerIRName) { return GetSettingsFilePath(compilerIRName, SectionDefinitionFile); } public static string GetInternalSectionsDefinitionFilePath(string compilerIRName) { return GetApplicationFilePath(compilerIRName, SectionDefinitionFile); } public static string GetFunctionMarkingsFilePath(string compilerIRName) { return GetSettingsFilePath(compilerIRName, FunctionMarkingsFile); } public static List GetSyntaxHighlightingFiles(string compilerIRName, bool internalFiles = false) { if (!internalFiles && cachedSyntaxHighlightingFiles_ != null) { return cachedSyntaxHighlightingFiles_; } var list = new List(); try { string baseDir = internalFiles ? GetCompilerApplicationDirectoryPath(compilerIRName) : GetCompilerSettingsDirectoryPath(compilerIRName); string[] themes = Directory.GetFiles(baseDir, SyntaxFileSearchPattern); foreach (string theme in themes) { list.Add(new SyntaxFileInfo(GetSyntaxFileName(theme), compilerIRName, theme)); } } catch (Exception ex) { Trace.TraceError($"Failed to get syntax file list: {ex}"); } if (!internalFiles) { cachedSyntaxHighlightingFiles_ = list; } return list; } public static List ReloadSyntaxHighlightingFiles(string compilerIRName) { cachedSyntaxHighlightingFiles_ = null; return GetSyntaxHighlightingFiles(compilerIRName); } public static SyntaxFileInfo GetSyntaxHighlightingFileInfo(string name, string compilerIRName) { var files = GetSyntaxHighlightingFiles(compilerIRName); return files.Find(item => item.Name == name); } public static string GetSyntaxHighlightingFilePath() { // If a file is not set yet (first run for ex), set the default one. var docSettings = Settings.DocumentSettings; //? TODO: Each compiler mode should have its own syntax saved if (string.IsNullOrEmpty(docSettings.SyntaxHighlightingName)) { docSettings.SyntaxHighlightingName = Session.CompilerInfo.DefaultSyntaxHighlightingFile; } var result = GetSyntaxHighlightingFileInfo(docSettings.SyntaxHighlightingName, Session.CompilerInfo.CompilerIRName); return result?.Path; } public static string GetSyntaxHighlightingFilePath(SyntaxFileInfo syntaxFile) { if (syntaxFile != null && File.Exists(syntaxFile.Path)) { return syntaxFile.Path; } return GetSyntaxHighlightingFilePath(); } public static string GetSyntaxHighlightingFilePath(string name, string compilerIRName) { InitializeSettingsFilesDirectory(compilerIRName); return GetCompilerSettingsFilePath(name, compilerIRName, SyntaxFileExtension); } public static bool LoadApplicationSettings() { try { CreateSettingsDirectory(); string path = GetSettingsFilePath(); byte[] data = File.ReadAllBytes(path); Settings = UIStateSerializer.Deserialize(data); // Do some basic sanity checks in case the settings file is incompatible. if (Settings.RecentFiles == null) { Settings.RecentFiles = new List(); } if (Settings.RecentComparedFiles == null) { Settings.RecentComparedFiles = new List>(); } return true; } catch (Exception ex) { Settings = new ApplicationSettings(); Trace.TraceError($"Failed to load app settings: {ex}"); return false; } } public static void SaveApplicationSettings() { try { byte[] data = UIStateSerializer.Serialize(Settings); CreateSettingsDirectory(); string path = GetSettingsFilePath(); File.WriteAllBytes(path, data); } catch (Exception ex) { Trace.TraceError($"Failed to save app settings: {ex}"); } } public static void LaunchSettingsFileEditor(string settingsPath) { if (string.IsNullOrEmpty(settingsPath) || !File.Exists(settingsPath)) { MessageBox.Show($"Could not file settings file {settingsPath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Warning); return; } try { var psi = new ProcessStartInfo(settingsPath) { UseShellExecute = true }; Process.Start(psi); } catch (Exception ex) { MessageBox.Show($"Failed to open settings file {settingsPath}\n{ex.Message}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } public static void OpenSettingsFolder(string settingsPath) { if (string.IsNullOrEmpty(settingsPath) || !Directory.Exists(settingsPath)) { MessageBox.Show($"Could not fine directory\n{settingsPath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Warning); return; } try { var psi = new ProcessStartInfo(settingsPath) { UseShellExecute = true }; Process.Start(psi); } catch (Exception ex) { MessageBox.Show($"Failed to open settings folder {settingsPath}\n{ex.Message}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } public static void DeleteSettingsFile(string settingsPath) { if (string.IsNullOrEmpty(settingsPath) || !File.Exists(settingsPath)) { return; } try { File.Delete(settingsPath); } catch (Exception ex) { Trace.TraceError($"Failed to delete file {settingsPath}: {ex}"); } } public static void InstallExtension() { if (!Utils.OpenExternalFile(GetExtensionFilePath())) { MessageBox.Show("Failed to open VS extension installer", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } public static void OpenDocumentation() { if (!Utils.OpenURL(DocumentationLocation)) { MessageBox.Show("Failed to open documentation page", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } public static bool StartNewApplicationInstance(string args = "", bool adminMode = false) { var psi = new ProcessStartInfo(ApplicationPath); psi.Arguments = args; psi.UseShellExecute = true; if (adminMode) { psi.Verb = "runas"; } try { using var process = new Process(); process.StartInfo = psi; process.Start(); return true; } catch (Exception ex) { Debug.WriteLine($"Failed to start new app instance: {ex}"); return false; } } public static void RestartApplicationAsAdmin(string args = "") { StartNewApplicationInstance(args, true); Current.Shutdown(); } private static bool CreateSettingsDirectory() { try { string path = GetSettingsDirectoryPath(); CreateDirectories(path); //? TODO: Walk over list of registers compilers InitializeSettingsFilesDirectory("llvm"); InitializeSettingsFilesDirectory("ASM"); InitializeSettingsFilesDirectory(ScriptsDirectory); InitializeSettingsFilesDirectory(ThemesDirectory); InitializeSettingsFilesDirectory(WorkspacesDirectory); return true; } catch (Exception ex) { Trace.TraceError($"Failed to create settings directory: {ex}"); return false; } } public static bool CreateDirectories(string path) { try { if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } return true; } catch (Exception ex) { Trace.TraceError($"Failed to create directories for {path}: {ex}"); return false; } } public static string GetSettingsDirectoryPath() { string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); return Path.Combine(path, SettingsPath); } private static string GetSettingsFilePath(string file) { // File relative to the settings directory. string path = GetSettingsDirectoryPath(); return Path.Combine(path, file); } private static string GetSettingsFilePath(string subDir, string file, string extension = "") { // File relative to the settings directory. string path = GetSettingsDirectoryPath(); return Path.Combine(path, subDir, !string.IsNullOrEmpty(extension) ? $"{file}.{extension}" : file); } private static string GetApplicationFilePath(string file) { // File relative to the application install directory. string path = ApplicationDirectory; return Path.Combine(path, file); } private static string GetApplicationFilePath(string subDir, string file, string extension = "") { // File relative to the application install directory. string path = ApplicationDirectory; return Path.Combine(path, subDir, file, extension); } private static string GetCompilerApplicationDirectoryPath(string compilerName) { return GetApplicationFilePath(compilerName); } private static string GetCompilerApplicationFilePath(string file, string compilerName, string extension = "") { file = string.IsNullOrEmpty(extension) ? file : Path.GetFileNameWithoutExtension(file); return GetApplicationFilePath(compilerName, file, extension); } private static bool CreateDirectoriesForFile(string file) { try { Directory.CreateDirectory(Path.GetDirectoryName(file)); return true; } catch (Exception ex) { Trace.TraceError($"Failed to create directories for {file}: {ex}"); return false; } } private static string GetSettingsFilePath() { return GetSettingsFilePath(SettingsFile); } public static bool ContainsSettingsFile(string dirPath) { return File.Exists(Path.Combine(dirPath, SettingsFile)); } private static string GetSyntaxFileName(string filePath) { try { var xmlDoc = new XmlDocument(); var ns = new XmlNamespaceManager(xmlDoc.NameTable); ns.AddNamespace("syntax", "http://icsharpcode.net/sharpdevelop/syntaxdefinition/2008"); xmlDoc.Load(filePath); var node = xmlDoc.SelectSingleNode("//syntax:SyntaxDefinition", ns); if (node != null) { return node.Attributes.GetNamedItem("name").InnerText; } } catch (Exception ex) { Trace.TraceError($"Failed to get syntax file name: {ex}"); } return ""; } private static bool InitializeSettingsFilesDirectory(string directory) { try { string syntaxFilesDir = GetCompilerSettingsDirectoryPath(directory); CreateDirectories(syntaxFilesDir); string compilerDir = GetCompilerApplicationDirectoryPath(directory); string[] files = Directory.GetFiles(compilerDir, "*.*"); foreach (string file in files) { string destFile = GetCompilerSettingsFilePath(Path.GetFileName(file), directory); //? TODO: This should rather try to merge the potentially newer file //? with the existing one that may have user customizations. File.Copy(file, destFile, true); } return true; } catch (Exception ex) { //Trace.TraceError($"Failed to create syntax file directory: {ex}"); return false; } } public void SetupExceptionHandling(bool showUIPrompt = true) { AppDomain.CurrentDomain.UnhandledException += (s, e) => ErrorReporting.LogUnhandledException((Exception)e.ExceptionObject, "AppDomain.CurrentDomain.UnhandledException", showUIPrompt); Dispatcher.UnhandledException += (s, e) => ErrorReporting.LogUnhandledException(e.Exception, "Application.Current.DispatcherUnhandledException", showUIPrompt); Current.DispatcherUnhandledException += (s, e) => ErrorReporting.LogUnhandledException(e.Exception, "Application.Current.DispatcherUnhandledException", showUIPrompt); TaskScheduler.UnobservedTaskException += (s, e) => ErrorReporting.LogUnhandledException(e.Exception, "TaskScheduler.UnobservedTaskException", showUIPrompt); } protected override void OnStartup(StartupEventArgs e) { AppStartTime = DateTime.UtcNow; base.OnStartup(e); // Initialize UI-specific JSON converters UIJsonUtils.Initialize(); // Register UI-specific type converters for settings system RegisterSettingsTypeConverters(); if (!Debugger.IsAttached) { SetupExceptionHandling(); } FixPopupPlacement(); // Disable most data-binding error reporting, slows down debugging too much. PresentationTraceSources.DataBindingSource.Switch.Level = SourceLevels.Critical; // Enable file output for tracing. OpenLogFile(); SetupJumplist(); if (!LoadApplicationSettings()) { // Failed to load settings, reset them. Utils.TryDeleteFile(GetSettingsFilePath()); Settings = new ApplicationSettings(); IsFirstRun = true; } // Configure CoreSettingsProvider to use UI settings instead of defaults CoreSettingsProvider.SetProvider(new UISettingsProvider()); if (Settings.GeneralSettings.DisableHardwareRendering) { Trace.WriteLine($"Disable hardware rendering"); RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly; } // Create and show the main window manually var mainWindow = new MainWindow(); mainWindow.Show(); // Initialize MCP server if enabled InitializeMcpServerAsync(mainWindow); } private void InitializeMcpServerAsync(MainWindow mainWindow) { try { // Create the MCP action executor var executor = new McpActionExecutor(mainWindow); // Start the MCP server in the background mcpServerTask = Task.Run(async () => { try { await McpServerConfiguration.StartServerWithExecutorAsync(executor); } catch (Exception ex) { Trace.WriteLine($"MCP Server error: {ex}"); } }); // When MCP session ends, close the application without confirmation // Only shutdown if we were actually in automation mode (MCP client was connected) mcpServerTask.ContinueWith(t => { if (SuppressDialogsForAutomation) { Trace.WriteLine("MCP session ended, shutting down application"); Current.Dispatcher.Invoke(() => { Current.Shutdown(); }); } }, TaskContinuationOptions.OnlyOnRanToCompletion); Trace.WriteLine("MCP Server initialization started"); } catch (Exception ex) { Trace.WriteLine($"Failed to initialize MCP Server: {ex}"); } } protected override void OnExit(ExitEventArgs e) { // Wait for MCP server to shutdown gracefully if (mcpServerTask != null && !mcpServerTask.IsCompleted) { try { // Give the server a moment to shutdown gracefully mcpServerTask.Wait(TimeSpan.FromSeconds(5)); } catch (Exception ex) { Trace.WriteLine($"Error during MCP server shutdown: {ex}"); } } base.OnExit(e); } private static void FixPopupPlacement() { // On touchscreen laptops, popups are not displayed in the right place. // Hack taken from https://stackoverflow.com/a/54298981 to fix it. bool ifLeft = SystemParameters.MenuDropAlignment; if (ifLeft) { // change to false var t = typeof(SystemParameters); var field = t.GetField("_menuDropAlignment", BindingFlags.NonPublic | BindingFlags.Static); field.SetValue(null, false); } } private void RegisterSettingsTypeConverters() { // Register UI-specific type converters for the settings system ProfileExplorer.Core.Settings.SettingsTypeRegistry.RegisterConverter(new ProfileExplorerUI.Settings.ColorSettingsConverter()); } private void SetupJumplist() { var instanceTask = new JumpTask { ApplicationPath = ApplicationPath, Arguments = "", Title = "New instance", Description = "Start a new Profile Explorer instance", CustomCategory = "Tasks" }; // var recordTask = new JumpTask { // ApplicationPath = ApplicationPath, // IconResourcePath = ApplicationPath, // IconResourceIndex = 2, // Arguments = "", // Title = "Record profile", // Description = "Start a new Profile Explorer instance", // CustomCategory = "Tasks" // }; // // // var recordSystemTask = new JumpTask { // ApplicationPath = ApplicationPath, // IconResourcePath = ApplicationPath, // IconResourceIndex = 2, // Arguments = "", // Title = "Record system-wide profile", // Description = "Start a new Profile Explorer instance", // CustomCategory = "Tasks" // }; var currentJumplist = JumpList.GetJumpList(Current); if (currentJumplist != null) { currentJumplist.JumpItems.Clear(); currentJumplist.JumpItems.Add(instanceTask); //currentJumplist.JumpItems.Add(recordTask); //currentJumplist.JumpItems.Add(recordSystemTask); currentJumplist.Apply(); } else { var jumpList = new JumpList(); jumpList.JumpItems.Add(instanceTask); //jumpList.JumpItems.Add(recordTask); //jumpList.JumpItems.Add(recordSystemTask); JumpList.SetJumpList(Current, jumpList); } } public static void OpenLogFile() { try { string traceFilePath = GetTraceFilePath(); if (File.Exists(traceFilePath)) { File.Copy(traceFilePath, GetBackupTraceFilePath(), true); File.Delete(traceFilePath); } Trace.Listeners.Add(new TextWriterTraceListener(traceFilePath)); #if DEBUG Trace.AutoFlush = true; #endif } catch (Exception ex) { Debug.WriteLine($"Failed to create trace file: {ex}"); } } public static void CloseLogFile() { try { Trace.Flush(); foreach (TraceListener listener in Trace.Listeners) { listener.Close(); } Trace.Close(); } catch (Exception ex) { Debug.WriteLine($"Failed to close trace file: {ex}"); } } public static void Restart() { //? TODO: Start new instance only after settings were saved. Process.Start(Process.GetCurrentProcess().MainModule.FileName); Current.Shutdown(); } } ================================================ FILE: src/ProfileExplorerUI/Client.vsdoc ================================================  default ]]> VSdocman]]> normal yes Client Reference client_reference vsdocman_escaped_]_]_> placeholder no 5fea6551b15041bab2b98628490e9d86 ]]> ================================================ FILE: src/ProfileExplorerUI/Compilers/ASM/ASMLoadedSectionHandler.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Threading.Tasks; using System.Windows; using ProfileExplorer.Core; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Compilers.LLVM; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.UI.Compilers.Default; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Query; using ProfileExplorerUI.Session; namespace ProfileExplorer.UI.Compilers.ASM; public class ASMLoadedSectionHandler : ILoadedSectionHandler { private ICompilerInfoProvider compilerInfo_; public ASMLoadedSectionHandler(ICompilerInfoProvider compilerInfo) { compilerInfo_ = compilerInfo; } public async Task HandleLoadedSection(IRDocument document, FunctionIR function, IRTextSection section) { // Since the ASM blocks don't have a number in the text, // attach an overlay label next to the first instr. in the block. CreateBlockLabelOverlays(document, function); // Annotate instrs. with source line numbers if debug info is available. var sourceMarker = new SourceDocumentMarker(App.Settings.DocumentSettings.SourceMarkerSettings, compilerInfo_); await sourceMarker.Mark(document, function); } private static void CreateBlockLabelOverlays(IRDocument document, FunctionIR function) { double overlayHeight = document.TextArea.TextView.DefaultLineHeight; var options = App.Settings.DocumentSettings.ProfileMarkerSettings; var blockPen = ColorPens.GetPen(options.BlockOverlayBorderColor, options.BlockOverlayBorderThickness); document.SuspendUpdate(); foreach (var block in function.Blocks) { if (block.Tuples.Count <= 0) { continue; } string label = $"B{block.Number}"; var overlay = document.AddIconElementOverlay(block, null, 0, overlayHeight, label, null, HorizontalAlignment.Left); overlay.MarginX = -8; overlay.Padding = 4; overlay.ShowOnMarkerBar = false; overlay.IsLabelPinned = true; overlay.AllowLabelEditing = false; overlay.TextWeight = FontWeights.Bold; overlay.TextColor = options.BlockOverlayTextColor.AsBrush(); var backColor = block.HasEvenIndexInFunction ? App.Settings.DocumentSettings.BackgroundColor : App.Settings.DocumentSettings.AlternateBackgroundColor; overlay.Background = ColorBrushes.GetBrush(backColor); overlay.Border = blockPen; overlay.ShowBackgroundOnMouseOverOnly = false; overlay.ShowBorderOnMouseOverOnly = false; overlay.UseLabelBackground = true; } document.ResumeUpdate(); } } ================================================ FILE: src/ProfileExplorerUI/Compilers/Default/BuiltinFunctionTasks/UnusedInstructionsFunctionTask.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Query; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI.Compilers.Default; class UnusedInstructionsTaskOptions : IFunctionTaskOptions { public UnusedInstructionsTaskOptions() { Reset(); } [DisplayName("Consider only SSA values")] [Description("Consider only instructions that have a destination operand in SSA form")] public bool HandleOnlySSA { get; set; } [DisplayName("Marker color")] [Description("Color to be used for marking unused instructions")] public Color MarkerColor { get; set; } public void Reset() { HandleOnlySSA = true; MarkerColor = Colors.Pink; } } class UnusedInstructionsFunctionTask { public static bool MarkUnusedInstructions(FunctionIR function, IRDocument document, IFunctionTaskOptions options, IUISession session, CancelableTask cancelableTask) { var taskOptions = options as UnusedInstructionsTaskOptions; var unusedInstr = new HashSet(); var walker = new CFGBlockOrdering(function); walker.PostorderWalk((block, index) => { foreach (var instr in block.InstructionsBack) { if (IsUnusedInstruction(GetSSADefinitionTag(instr), unusedInstr)) { document.Dispatcher.BeginInvoke((Action)(() => { document.MarkElement(instr, taskOptions.MarkerColor); })); unusedInstr.Add(instr); } } return !cancelableTask.IsCanceled; }); return true; } //? TODO: Add hooks for quierying IR if an instr is DCE candidate (reject calls for ex) private static SSADefinitionTag GetSSADefinitionTag(InstructionIR instr) { if (instr.Destinations.Count == 0) { return null; } var destOp = instr.Destinations[0]; if (destOp.IsTemporary) { return destOp.GetTag(); } return null; } private static bool IsUnusedInstruction(SSADefinitionTag ssaDefTag, HashSet unusedInstrs) { if (ssaDefTag == null) { return false; } if (!ssaDefTag.HasUsers) { return true; } foreach (var user in ssaDefTag.Users) { if (!unusedInstrs.Contains(user.OwnerInstruction)) { return false; } } return true; } } ================================================ FILE: src/ProfileExplorerUI/Compilers/Default/BuiltinQueries/RegisterQuery.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows.Media; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Query; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Session; namespace ProfileExplorer.UI.Compilers.Default; public class RegisterQuery : IElementQuery { public IUISession Session { get; private set; } public bool Initialize(IUISession session) { Session = session; return true; } public bool Execute(QueryData data) { data.ResetResults(); var element = data.GetInput(0); bool considerOverlapping = data.GetInput(1); bool isTemporary = data.GetInput(2); var color = data.GetInput(3); var func = element.ParentFunction; // Pick the query register. var tag = GetRegisterTag(element); if (tag == null) { data.SetOutputWarning("Value has no register"); return true; } int count = 0; var document = Session.CurrentDocument; var highlightingType = isTemporary ? HighlighingType.Selected : HighlighingType.Marked; document.BeginMarkElementAppend(highlightingType); foreach (var operand in func.AllElements) { var otherTag = GetRegisterTag(operand); if (otherTag == null) { continue; } if (otherTag.Register.Equals(tag.Register) || considerOverlapping && otherTag.Register.OverlapsWith(tag.Register)) { document.MarkElementAppend(operand, color, highlightingType); count++; } } document.EndMarkElementAppend(highlightingType); data.SetOutput("Register instances", count); data.ClearButtons(); return true; } public static QueryDefinition GetDefinition() { var query = new QueryDefinition(typeof(RegisterQuery), "Registers", "Details about post-lower registers"); query.Data.AddInput("Operand", QueryValueKind.Element); query.Data.AddInput("Consider overlapping registers", QueryValueKind.Bool, true); query.Data.AddInput("Use temporary marking", QueryValueKind.Bool, true); query.Data.AddInput("Marking color", QueryValueKind.Color, Colors.Pink); return query; } private static RegisterTag GetRegisterTag(IRElement element) { // For indirection, use the base value register. if (element is OperandIR op && op.IsIndirection) { return op.IndirectionBaseValue.GetTag(); } return element.GetTag(); } } ================================================ FILE: src/ProfileExplorerUI/Compilers/Default/BuiltinQueries/ValueNumberQuery.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Windows.Media; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Query; namespace ProfileExplorer.UI.Compilers.Default; public class ValueNumberQuery : IElementQuery { private static readonly string ValueNumberPrefix = "vn "; public IUISession Session { get; private set; } public bool Initialize(IUISession session) { Session = session; return true; } public bool Execute(QueryData data) { data.ResetResults(); var element = data.GetInput("Operand"); string vn = DefaultRemarkParser.ExtractValueNumber(element, ValueNumberPrefix); if (vn == null) { return true; } var func = element.ParentFunction; var sameVNInstrs = new HashSet(); func.ForEachInstruction(instr => { string instrVN = DefaultRemarkParser.ExtractValueNumber(instr, ValueNumberPrefix); if (instrVN == vn) { sameVNInstrs.Add(instr); } return true; }); data.SetOutput("Value number", vn); data.SetOutput("Instrs. with same value number", sameVNInstrs.Count); data.ClearButtons(); if (sameVNInstrs.Count > 0) { data.AddButton("Mark same value number instrs.", (sender, data) => { //? TODO: Check for document/function still being the same var document = Session.CurrentDocument; foreach (var instr in sameVNInstrs) { document.MarkElement(instr, Colors.YellowGreen); } }); } return true; } public static QueryDefinition GetDefinition() { var query = new QueryDefinition(typeof(ValueNumberQuery), "Value Numbers", "Details about values with SSA info"); query.Data.AddInput("Operand", QueryValueKind.Element); query.Data.AddInput("Consider only dominated values", QueryValueKind.Bool); query.Data.AddInput("Marking color", QueryValueKind.Color); query.Data.AddOutput("Value number", QueryValueKind.String); return query; } } ================================================ FILE: src/ProfileExplorerUI/Compilers/Default/DefaultRemarkParser.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.UI.Compilers.Default; public class DefaultRemarkParser { private IRSectionParser parser_; public DefaultRemarkParser(ICompilerIRInfo irInfo) { parser_ = irInfo.CreateSectionParser(null); } public static string ExtractValueNumber(IRElement element, string prefix) { var tag = element.GetTag(); if (tag == null) { return null; } foreach (var remark in tag.Remarks) { if (remark.RemarkText.StartsWith(prefix)) { string[] tokens = remark.RemarkText.Split(' ', ':'); string number = tokens[1]; return number; } } return null; } public void Initialize(ReadOnlyMemory line) { } public TupleIR ParseTuple() { return null; } public OperandIR ParseOperand() { return null; } } ================================================ FILE: src/ProfileExplorerUI/Compilers/Default/DefaultRemarkProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Utilities; using ProfileExplorerUI.Session; namespace ProfileExplorer.UI.Compilers.Default; public sealed class DefaultRemarkProvider : IRRemarkProvider { private const string MetadataStartString = "/// remark:"; private const string RemarkContextStartString = "context_start"; private const string RemarkContextEndString = "context_end"; private string compilerIRName_; private ICompilerIRInfo irInfo_; private List categories_; private List boundaries_; private List highlighting_; private RemarkCategory defaultCategory_; private bool settingsLoaded_; public DefaultRemarkProvider(ICompilerInfoProvider compilerInfo) { compilerIRName_ = compilerInfo.CompilerIRName; irInfo_ = compilerInfo.IR; categories_ = new List(); boundaries_ = new List(); highlighting_ = new List(); settingsLoaded_ = LoadSettings(); } public string SettingsFilePath => App.GetRemarksDefinitionFilePath(compilerIRName_); public List RemarkCategories { get { if (LoadSettings()) { return categories_; } return null; } } public List RemarkSectionBoundaries { get { if (LoadSettings()) { return boundaries_; } return null; } } public List RemarkTextHighlighting { get { if (LoadSettings()) { return highlighting_; } return null; } } public bool SaveSettings() { return false; } public bool LoadSettings() { if (settingsLoaded_) { return true; } var serializer = new RemarksDefinitionSerializer(); string settingsPath = SettingsFilePath; if (settingsPath == null) { return false; } if (!serializer.Load(settingsPath, out categories_, out boundaries_, out highlighting_)) { Trace.TraceError("Failed to load RemarkProvider data"); return false; } // Add a default category. defaultCategory_ = new RemarkCategory { Kind = RemarkKind.Default, Title = "", SearchedText = "", MarkColor = Colors.Transparent }; categories_.Add(defaultCategory_); return true; } public List ExtractRemarks(string text, FunctionIR function, IRTextSection section, RemarkProviderOptions options, CancelableTask cancelableTask) { string[] lines = text.SplitLines(); return ExtractRemarks(new List(lines), function, section, options, cancelableTask); } public List ExtractRemarks(List textLines, FunctionIR function, IRTextSection section, RemarkProviderOptions options, CancelableTask cancelableTask) { if (!settingsLoaded_) { return new List(); // Failed to load settings, bail out. } // The RemarkContextState allows multiple threads to use the provider // by not having any global state visible to all threads. var remarks = new List(); var state = new RemarkContextState(); ExtractInstructionRemarks(textLines, function, section, remarks, options, state, cancelableTask); return remarks; } public OptimizationRemark GetOptimizationRemarkInfo(Remark remark) { return null; } public List GetSectionList(IRTextSection currentSection, int maxDepth, bool stopAtSectionBoundaries) { var list = new List(); if (categories_ == null || boundaries_ == null) { return list; // Error loading settings. } var function = currentSection.ParentFunction; for (int i = currentSection.Number - 1, count = 0; i >= 0 && count < maxDepth; i--, count++) { var section = function.Sections[i]; list.Add(section); if (stopAtSectionBoundaries && boundaries_.Count > 0) { if (boundaries_.Find(boundary => TextSearcher.Contains(section.Name, boundary.SearchedText, boundary.SearchKind)) != null) { break; // Stop once section boundary reached. } } } list.Reverse(); return list; } public List ExtractAllRemarks(List sections, FunctionIR function, ILoadedDocument document, RemarkProviderOptions options, CancelableTask cancelableTask) { if (!settingsLoaded_) { return new List(); // Failed to load settings, bail out. } int maxConcurrency = App.Settings.GeneralSettings.CurrentCpuCoreLimit; var tasks = new Task>[sections.Count]; using var concurrencySemaphore = new SemaphoreSlim(maxConcurrency); int index = 0; foreach (var section in sections) { concurrencySemaphore.Wait(); tasks[index++] = Task.Run(() => { try { var sectionTextLines = document.Loader.GetSectionPassOutputTextLines(section.OutputBefore); return ExtractRemarks(sectionTextLines, function, section, options, cancelableTask); } finally { concurrencySemaphore.Release(); } }); } Task.WaitAll(tasks); // Combine all remarks into a single list. var remarks = new List(); for (int i = 0; i < sections.Count; i++) { remarks.AddRange(tasks[i].Result); } return remarks; } public RemarkCategory FindRemarkKind(string text, bool isInstructionElement) { if (categories_ == null) { return default(RemarkCategory); // Error loading settings. } text = text.Trim(); foreach (var category in categories_) { // Ignore remarks that expect an entire instruction reference // if the IR is not an instruction. if (category.ExpectInstructionIR && !isInstructionElement) { continue; } //? TODO: If SearchKind is Regex, this ends up creating a new Regex //? instance for each remark, should make it once and attach it to category if (TextSearcher.Contains(text, category.SearchedText, category.SearchKind)) { return category; } } return defaultCategory_; } private void ExtractInstructionRemarks(List lines, FunctionIR function, IRTextSection section, List remarks, RemarkProviderOptions options, RemarkContextState state, CancelableTask cancelableTask) { var similarValueFinder = new SimilarValueFinder(function); var refFinder = new ReferenceFinder(function, irInfo_); // The split lines don't include the endline, but considering // the \r \n is needed to get the proper document offset. int newLineLength = Environment.NewLine.Length; int lineStartOffset = 0; var lineParser = new DefaultRemarkParser(irInfo_); var parser = new DefaultRemarkParser(irInfo_); //? TODO: For many lines, must be split in chunks and parallelized, //? it can take 5-7s even on 30-40k instruction functs, which is not that uncommon... for (int i = 0; i < lines.Count; i++) { if (cancelableTask.IsCanceled) { return; } int index = 0; string line = lines[i]; if (line.StartsWith(MetadataStartString, StringComparison.Ordinal)) { if (HandleMetadata(line, i, state)) { lineStartOffset += line.Length + newLineLength; continue; } } while (index < line.Length) { // Find next chunk delimited by whitespace. if (index > 0) { int next = line.IndexOf(' ', index); if (next != -1) { index = next + 1; } } // Skip all whitespace. while (index < line.Length && char.IsWhiteSpace(line[index])) { index++; } if (index == line.Length) { break; } lineParser.Initialize(line.AsMemory(index)); var tuple = lineParser.ParseTuple(); if (tuple is InstructionIR instr) { var similarInstr = similarValueFinder.Find(instr); if (similarInstr != null) { var remarkLocation = new TextLocation(lineStartOffset, i, 0); var location = new TextLocation( instr.TextLocation.Offset + index + lineStartOffset, i, 0); instr.TextLocation = location; // Set actual location in output text. var remarkKind = FindRemarkKind(line, true); var remark = new Remark(remarkKind, section, line.Trim(), line, remarkLocation, true); remark.ReferencedElements.Add(similarInstr); remark.OutputElements.Add(instr); remarks.Add(remark); state.AttachToCurrentContext(remark); index += instr.TextLength; continue; } } index++; } // Extract remarks mentioning only operands, not whole instructions. //? TODO: If an operand is part of an instruction that was already matched //? by a remark, don't include the operand anymore if it's the same remark text if (!options.FindOperandRemarks) { lineStartOffset += line.Length + newLineLength; continue; } parser.Initialize(line.AsMemory()); var op = parser.ParseOperand(); while (op != null) { var value = refFinder.FindEquivalentValue(op, true); if (value != null && op.TextLocation.Line < lines.Count) { var location = new TextLocation(op.TextLocation.Offset + lineStartOffset, i, 0); op.TextLocation = location; // Set actual location in output text. var remarkLocation = new TextLocation(lineStartOffset, i, 0); var remarkKind = FindRemarkKind(line, false); var remark = new Remark(remarkKind, section, line.Trim(), line, remarkLocation, false); remark.ReferencedElements.Add(value); remark.OutputElements.Add(op); remarks.Add(remark); state.AttachToCurrentContext(remark); } op = parser.ParseOperand(); } lineStartOffset += line.Length + newLineLength; } } private bool HandleMetadata(string line, int lineNumber, RemarkContextState state) { string[] tokens = line.Split(new[] {' ', ':', ','}, StringSplitOptions.RemoveEmptyEntries); if (tokens.Length >= 2) { if (tokens[2].StartsWith(RemarkContextStartString) && tokens.Length >= 5) { state.StartNewContext(tokens[3], tokens[4], lineNumber); return true; } if (tokens[2].StartsWith(RemarkContextEndString)) { state.EndCurrentContext(lineNumber); return true; } } return false; } private class RemarkContextState { private Stack contextStack_; private List rootContexts_; public RemarkContextState() { contextStack_ = new Stack(); rootContexts_ = new List(); } public List RootContexts => rootContexts_; public void AttachToCurrentContext(Remark remark) { var context = GetCurrentContext(); if (context != null) { context.Remarks.Add(remark); remark.Context = context; } } public RemarkContext GetCurrentContext() { return contextStack_.Count > 0 ? contextStack_.Peek() : null; } public RemarkContext StartNewContext(string id, string name, int lineNumber) { var currentContext = GetCurrentContext(); var context = new RemarkContext(id, name, currentContext); if (currentContext != null) { currentContext.Children.Add(context); } else { rootContexts_.Add(context); } context.StartLine = lineNumber; contextStack_.Push(context); return context; } public void EndCurrentContext(int lineNumber) { if (contextStack_.Count > 0) { var context = contextStack_.Pop(); context.EndLine = lineNumber; } } } } ================================================ FILE: src/ProfileExplorerUI/Compilers/Default/DefaultSectionStyleProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Diagnostics; using ProfileExplorer.Core; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.UI.Compilers.Default; public sealed class DefaultSectionStyleProvider : ISectionStyleProvider { private List sectionNameMarkers_; private ICompilerInfoProvider compilerInfo_; public DefaultSectionStyleProvider(ICompilerInfoProvider compilerInfo) { compilerInfo_ = compilerInfo; sectionNameMarkers_ = new List(); LoadSettings(); } public string SettingsFilePath => App.GetSectionsDefinitionFilePath(compilerInfo_.CompilerIRName); public bool IsMarkedSection(IRTextSection section, out MarkedSectionName result) { foreach (var nameMarker in sectionNameMarkers_) { if (TextSearcher.Contains(section.Name, nameMarker.SearchedText, nameMarker.SearchKind)) { result = nameMarker; return true; } } result = null; return false; } public bool LoadSettings() { var serializer = new SectionStyleProviderSerializer(); string settingsPath = App.GetSectionsDefinitionFilePath(compilerInfo_.CompilerIRName); if (settingsPath == null) { return false; } if (!serializer.Load(settingsPath, out sectionNameMarkers_)) { Trace.TraceError("Failed to load SectionStyleProvider data"); return false; } return true; } public bool SaveSettings() { return false; } } ================================================ FILE: src/ProfileExplorerUI/Compilers/LLVM/LLVMLoadedSectionHandler.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Threading.Tasks; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Compilers.LLVM; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Diff; using ProfileExplorer.UI.Compilers.Default; using ProfileExplorer.Core.Settings; using ProfileExplorer.UI; using ProfileExplorer.UI.Query; using ProfileExplorerUI.Session; namespace ProfileExplorer.UI.Compilers.LLVM; public class LLVMLoadedSectionHandler : ILoadedSectionHandler { public Task HandleLoadedSection(IRDocument document, FunctionIR function, IRTextSection section) { return Task.CompletedTask; } } ================================================ FILE: src/ProfileExplorerUI/Controls/ColorPaletteSelector.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/ColorPaletteSelector.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; namespace ProfileExplorer.UI.Controls; /// /// Interaction logic for ColorPaletteSelector.xaml /// public partial class ColorPaletteSelector : UserControl, INotifyPropertyChanged { public static readonly DependencyProperty SelectedPaletteProperty = DependencyProperty.Register("SelectedPalette", typeof(ColorPalette), typeof(ColorPaletteSelector), new PropertyMetadata(null, OnSelectedPaletteChanged)); public static readonly DependencyProperty PalettesSourceProperty = DependencyProperty.Register("PalettesSource", typeof(List), typeof(ColorPaletteSelector), new PropertyMetadata(null)); public ColorPaletteSelector() { InitializeComponent(); ZoomTransform.ScaleX = WindowScaling; ZoomTransform.ScaleY = WindowScaling; } public double PreviewWidth { get => PaletteList.Width; set => PaletteList.Width = value; } public ColorPalette SelectedPalette { get => (ColorPalette)GetValue(SelectedPaletteProperty); set { if (value != SelectedPalette) { SetValue(SelectedPaletteProperty, value); PaletteViewer.Palette = value; OnPropertyChanged(); } } } public List PalettesSource { get => (List)GetValue(PalettesSourceProperty); set { if (value != PalettesSource) { SetValue(PalettesSourceProperty, value); PaletteList.ItemsSource = value; OnPropertyChanged(); } } } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public event PropertyChangedEventHandler PropertyChanged; private static void OnSelectedPaletteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var sender = d as ColorPaletteSelector; var value = e.NewValue as ColorPalette; sender.SelectedPalette = value; sender.PaletteViewer.Palette = value; } private void PaletteList_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { SelectedPalette = PaletteList.SelectedItem as ColorPalette; PaletteSplitButton.IsOpen = false; } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private void PaletteSplitButton_OnClick(object sender, RoutedEventArgs e) { PaletteSplitButton.IsOpen = true; } } ================================================ FILE: src/ProfileExplorerUI/Controls/ColorPaletteViewer.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/ColorPaletteViewer.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace ProfileExplorer.UI.Controls; /// /// Interaction logic for ColorPaletteViewer.xaml /// public partial class ColorPaletteViewer : UserControl { public static readonly DependencyProperty PaletteProperty = DependencyProperty.Register("Palette", typeof(ColorPalette), typeof(ColorPaletteViewer), new PropertyMetadata(null, OnPaletteChanged)); public ColorPaletteViewer() { InitializeComponent(); } public ColorPalette Palette { get => (ColorPalette)GetValue(PaletteProperty); set { SetValue(PaletteProperty, value); InvalidateVisual(); } } private static void OnPaletteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as ColorPaletteViewer; source.Palette = e.NewValue as ColorPalette; } protected override void OnRender(DrawingContext dc) { var palette = Palette; if (palette == null || palette.Colors.Count == 0) { return; } double width = ActualWidth; double height = ActualHeight; double cellWidth = width / palette.Colors.Count; var pen = ColorPens.GetTransparentPen(Colors.Black, 50, 0.5); for (int i = 0; i < palette.Colors.Count; i++) { var color = palette.Colors[i].AsBrush(); dc.DrawRectangle(color, pen, new Rect(i * cellWidth, 0, cellWidth, height)); } } } ================================================ FILE: src/ProfileExplorerUI/Controls/ColorSelector.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/IRDocumentPopup.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Profile; using ProfileExplorer.Core.Profile.Processing; namespace ProfileExplorer.UI.Controls; public partial class IRDocumentPopup : DraggablePopup, INotifyPropertyChanged { public static readonly double MinWidth = 300; public static readonly double MinHeight = 200; // For ASM/source preview. private string panelTitle_; private string panelToolTip_; private UIElement owner_; private bool showSourceFile_; private bool showModeButtons_; private IUISession session; private ParsedIRTextSection parsedSection_; private PreviewPopupSettings settings_; private bool showHistoryButtons_; private OptionsPanelHostPopup optionsPanelPopup_; public IRDocumentPopup(Point position, UIElement owner, IUISession session, PreviewPopupSettings settings) { Debug.Assert(settings != null); InitializeComponent(); SetupEvents(); settings_ = settings; double width = Math.Max(settings.PopupWidth, MinWidth); double height = Math.Max(settings.PopupHeight, MinHeight); Initialize(position, width, height, owner); PanelResizeGrip.ResizedControl = this; Session = session; owner_ = owner; DataContext = this; } public IRElement PreviewedElement { get; set; } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public IUISession Session { get => session; set { session = value; ProfileTextView.Session = value; } } public string PanelTitle { get => panelTitle_; set => SetField(ref panelTitle_, value); } public string PanelToolTip { get => panelToolTip_; set => SetField(ref panelToolTip_, value); } public string TitlePrefix { get; set; } public string TitleSuffix { get; set; } public string DescriptionPrefix { get; set; } public string DescriptionSuffix { get; set; } public bool ShowHistoryButtons { get => showHistoryButtons_; set => SetField(ref showHistoryButtons_, value); } public bool HasPreviousFunctions => ProfileTextView.HasPreviousFunctions; public bool HasNextFunctions => ProfileTextView.HasNextFunctions; public bool ShowAssembly { get => !showSourceFile_; set { SetField(ref showSourceFile_, !value); OnPropertyChanged(nameof(ShowSourceFile)); } } public bool ShowSourceFile { get => showSourceFile_; set { SetField(ref showSourceFile_, value); OnPropertyChanged(nameof(ShowAssembly)); } } public bool ShowModeButtons { get => showModeButtons_; set => SetField(ref showModeButtons_, value); } public event PropertyChangedEventHandler PropertyChanged; private void SetupEvents() { ProfileTextView.PreviewMouseWheel += ProfileTextViewOnMouseWheel; ProfileTextView.TitlePrefixChanged += (sender, s) => { TitlePrefix = s; UpdatePopupTitle(); }; ProfileTextView.TitleSuffixChanged += (sender, s) => { TitleSuffix = s; UpdatePopupTitle(); }; ProfileTextView.DescriptionPrefixChanged += (sender, s) => { DescriptionPrefix = !string.IsNullOrEmpty(s) ? s + "\n\n" : ""; UpdatePopupTitle(); }; ProfileTextView.DescriptionSuffixChanged += (sender, s) => { DescriptionSuffix = !string.IsNullOrEmpty(s) ? "\n\n" + s : ""; UpdatePopupTitle(); }; ProfileTextView.LoadedFunctionChanged += (sender, s) => { parsedSection_ = s; UpdatePopupTitle(); }; ProfileTextView.FunctionHistoryChanged += (sender, args) => { ShowHistoryButtons = ProfileTextView.HasPreviousFunctions || ProfileTextView.HasNextFunctions; OnPropertyChanged(nameof(HasNextFunctions)); OnPropertyChanged(nameof(HasPreviousFunctions)); }; } protected override void SetPanelAccentColor(Color color) { ToolbarPanel.Background = ColorBrushes.GetBrush(color); PanelBorder.BorderBrush = ColorBrushes.GetBrush(color); } public void SetPanelAccentColor(Brush color) { ToolbarPanel.Background = color; PanelBorder.BorderBrush = color; } private async Task SetupInitialMode(ParsedIRTextSection parsedSection, bool showSourceCode) { parsedSection_ = parsedSection; await ReloadDocument(showSourceCode); } private async Task ReloadDocument(bool showSourceCode = false) { if (parsedSection_ != null) { ShowModeButtons = true; ShowAssembly = !showSourceCode && !settings_.ShowSourcePreviewPopup; await SwitchAssemblySourceMode(); } } public static async Task CreateNew(IRDocument document, IRElement previewedElement, Point position, UIElement owner, PreviewPopupSettings settings, string titlePrefix = "") { var popup = CreatePopup(document.Section, previewedElement, position, owner ?? document.TextArea.TextView, document.Session, settings, titlePrefix); await popup.InitializeFromDocument(document); SetupNewPopup(popup, settings); return popup; } public static async Task CreateNew(ParsedIRTextSection parsedSection, Point position, UIElement owner, IUISession session, PreviewPopupSettings settings, string titlePrefix = "", bool showSourceCode = false, ProfileSampleFilter profileFilter = null) { var popup = CreatePopup(parsedSection.Section, null, position, owner, session, settings, titlePrefix); await popup.InitializeFromSection(parsedSection, profileFilter, showSourceCode); SetupNewPopup(popup, settings); return popup; } private static void SetupNewPopup(IRDocumentPopup popup, PreviewPopupSettings settings) { popup.PopupClosed += (sender, args) => { // Save resized popup dimension for next use. settings.PopupWidth = popup.Width; settings.PopupHeight = popup.Height; }; popup.UpdatePopupTitle(); popup.CaptureMouseWheel(); } private async Task InitializeFromSection(ParsedIRTextSection parsedSection, ProfileSampleFilter filter, bool showSourceCode) { ReloadSettings(); ProfileTextView.ProfileFilter = filter; ProfileTextView.Focus(); await SetupInitialMode(parsedSection, showSourceCode); } private void ReloadSettings() { ProfileTextView.IsPreviewDocument = true; ProfileTextView.UseSmallerFontSize = settings_.UseSmallerFontSize; ProfileTextView.UseCompactProfilingColumns = settings_.UseCompactProfilingColumns; ProfileTextView.ShowPerformanceCounterColumns = settings_.ShowPerformanceCounterColumns; ProfileTextView.ShowPerformanceMetricColumns = settings_.ShowPerformanceMetricColumns; ProfileTextView.Initialize(App.Settings.DocumentSettings); } private static IRDocumentPopup CreatePopup(IRTextSection section, IRElement previewedElement, Point position, UIElement owner, IUISession session, PreviewPopupSettings settings, string titlePrefix) { var popup = new IRDocumentPopup(position, owner, session, settings); popup.PreviewedElement = previewedElement; popup.TitlePrefix = titlePrefix; SetupNewPopup(popup, settings); return popup; } private void UpdatePopupTitle() { string title = GetFunctionName(); if (PreviewedElement != null) { string elementText = Utils.MakeElementDescription(PreviewedElement); title = $"{title}: {elementText}"; } if (!string.IsNullOrEmpty(TitlePrefix)) { title = $"{TitlePrefix}{title}"; } if (!string.IsNullOrEmpty(TitleSuffix)) { title = $"{title}{TitleSuffix}"; } string tooltip = GetTooltipFunctionName(); if (!string.IsNullOrEmpty(DescriptionPrefix)) { tooltip = $"{DescriptionPrefix}{tooltip}"; } if (!string.IsNullOrEmpty(DescriptionSuffix)) { tooltip = $"{tooltip}{DescriptionSuffix}"; } PanelTitle = title; PanelToolTip = tooltip; } private string GetFunctionName() { if (parsedSection_ != null) { return parsedSection_.ParentFunction.FormatFunctionName(session, 80); } return ""; } private string GetTooltipFunctionName() { if (parsedSection_ != null) { string funName = parsedSection_.ParentFunction.FormatFunctionName(session); return $"Module: {parsedSection_.Section.ModuleName}\nFunction: {DocumentUtils.FormatLongFunctionName(funName)}"; } return ""; } private async Task InitializeFromDocument(IRDocument document, string text = null) { await ProfileTextView.TextView.InitializeFromDocument(document, false, text); } public override void ShowPopup() { base.ShowPopup(); if (PreviewedElement != null) { MarkPreviewedElement(PreviewedElement, ProfileTextView.TextView); } } public override void PopupOpened() { ProfileTextView.Focus(); } public override void ClosePopup() { owner_.PreviewMouseWheel -= Owner_OnPreviewMouseWheel; Session.UnregisterDetachedPanel(this); base.ClosePopup(); } private void MarkPreviewedElement(IRElement element, IRDocument document) { if (PreviewedElement is BlockIR block) { if (block.HasLabel) { document.MarkElementWithDefaultStyle(block.Label); return; } } else { document.MarkElementWithDefaultStyle(PreviewedElement); return; } document.BringElementIntoView(PreviewedElement, BringIntoViewStyle.FirstLine); } private void CaptureMouseWheel() { owner_.PreviewMouseWheel += Owner_OnPreviewMouseWheel; } public override bool ShouldStartDragging(MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && ToolbarPanel.IsMouseOver) { if (!IsDetached) { DetachPopup(); EnableVerticalScrollbar(); Session.RegisterDetachedPanel(this); } return true; } return false; } public void AdjustVerticalPosition(double amount) { // Make scroll bar visible, it's not by default. EnableVerticalScrollbar(); amount *= ProfileTextView.TextView.DefaultLineHeight; double newOffset = ProfileTextView.TextView.VerticalOffset + amount; ProfileTextView.TextView.ScrollToVerticalOffset(newOffset); } private void Owner_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) { if (Utils.IsControlModifierActive()) { double amount = Utils.IsShiftModifierActive() ? 3 : 1; AdjustVerticalPosition(e.Delta < 0 ? amount : -amount); e.Handled = true; } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private void CloseButton_Click(object sender, RoutedEventArgs e) { ClosePopup(); } private void ProfileTextViewOnMouseWheel(object sender, MouseWheelEventArgs e) { EnableVerticalScrollbar(); } private void EnableVerticalScrollbar() { ProfileTextView.TextView.VerticalScrollBarVisibility = ScrollBarVisibility.Auto; ScrollViewer.SetVerticalScrollBarVisibility(ProfileTextView, ScrollBarVisibility.Auto); } private async void OpenButton_Click(object sender, RoutedEventArgs e) { var args = new OpenSectionEventArgs(ProfileTextView.TextView.Section, OpenSectionKind.NewTab); //? TODO: BeginInvoke prevents the "Dispatcher suspended" assert that happens // with profiling, when Source panel shows the open dialog. // The dialog code should rather invoke the dispatcher... await Dispatcher.BeginInvoke(async () => { var result = await Session.OpenDocumentSectionAsync(args); //? TODO: Mark the previewed elem in the new doc // var similarValueFinder = new SimilarValueFinder(function_); // refElement = similarValueFinder.Find(instr); result.TextView.ScrollToVerticalOffset(ProfileTextView.TextView.VerticalOffset); }, DispatcherPriority.Render); } private async void ModeToggleButton_Click(object sender, RoutedEventArgs e) { await SwitchAssemblySourceMode(); } private async Task SwitchAssemblySourceMode() { // Save current profile filter to restore after switch. var filter = ProfileTextView.ProfileFilter; await ProfileTextView.Reset(); if (showSourceFile_) { ProfileTextView.Initialize(App.Settings.SourceFileSettings); var function = parsedSection_.ParentFunction; var sourceFileFinder = new SourceFileFinder(Session); sourceFileFinder.LoadSettings(App.Settings.SourceFileSettings.FinderSettings); var (sourceInfo, debugInfo) = await sourceFileFinder.FindLocalSourceFile(function); bool loaded = false; if (!sourceInfo.IsUnknown) { loaded = await ProfileTextView.LoadSourceFile(sourceInfo, parsedSection_.Section, filter); } if (!loaded) { string failureText = $"Could not find debug info for function:\n{function.Name}"; await ProfileTextView.HandleMissingSourceFile(failureText); } } else { // Show assembly. ProfileTextView.Initialize(App.Settings.DocumentSettings); await ProfileTextView.LoadAssembly(parsedSection_, filter); } } private async void NextButton_Click(object sender, RoutedEventArgs e) { await ProfileTextView.LoadNextSection(); } private async void BackButton_Click(object sender, RoutedEventArgs e) { await ProfileTextView.LoadPreviousSection(); } private void OptionButton_Click(object sender, RoutedEventArgs e) { ShowOptionsPanel(); } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } FrameworkElement relativeControl = ProfileTextView; optionsPanelPopup_ = OptionsPanelHostPopup.Create( settings_.Clone(), relativeControl, Session, async (newSettings, commit) => { if (!newSettings.Equals(settings_)) { settings_ = newSettings; App.Settings.PreviewPopupSettings = newSettings; ReloadSettings(); await ReloadDocument(); if (commit) { App.SaveApplicationSettings(); } return settings_.Clone(); } return null; }, () => optionsPanelPopup_ = null); } } //? TODO: Replace all places using IRDocumentPopup with this, //? removes lots of duplicate code this way public class IRDocumentPopupInstance { public const double DefaultWidth = 600; public const double DefaultHeight = 200; private PreviewPopupSettings settings_; private IRDocumentPopup previewPopup_; private DelayedAction removeHoveredAction_; private Func previewedElementFinder_; private MouseHoverLogic hover_; private double width_; private double height_; private IUISession session_; public IRDocumentPopupInstance(PreviewPopupSettings settings, IUISession session) { settings_ = settings; width_ = settings != null ? Math.Max(settings.PopupWidth, DefaultWidth) : DefaultWidth; height_ = settings != null ? Math.Max(settings.PopupHeight, DefaultHeight) : DefaultHeight; session_ = session; } public void SetupHoverEvents(UIElement target, TimeSpan hoverDuration, Func previewedElementFinder) { previewedElementFinder_ = previewedElementFinder; hover_ = new MouseHoverLogic(target, hoverDuration); hover_.MouseHover += Hover_MouseHover; hover_.MouseHoverStopped += Hover_MouseHoverStopped; } public void UnregisterHoverEvents() { hover_.MouseHover -= Hover_MouseHover; hover_.MouseHoverStopped -= Hover_MouseHoverStopped; hover_.Dispose(); hover_ = null; } private async Task ShowPreviewPopupForDocument(PreviewPopupArgs args) { await ShowPreviewPopupForDocument(args.Document, args.Element, args.RelativeElement, args.Title); } private async Task ShowPreviewPopupForDocument(IRDocument document, IRElement element, UIElement relativeElement, string titlePrefix) { if (!Prepare(element)) { return; } var position = Mouse.GetPosition(relativeElement).AdjustForMouseCursor(); previewPopup_ = await IRDocumentPopup.CreateNew(document, element, position, relativeElement, settings_, titlePrefix); Complete(); } private async Task ShowPreviewPopupForLoadedSection(PreviewPopupArgs args) { if (!Prepare()) { return; } var position = Mouse.GetPosition(args.RelativeElement).AdjustForMouseCursor(); previewPopup_ = await IRDocumentPopup.CreateNew(args.LoadedSection, position, args.RelativeElement, session_, settings_, args.Title, args.ShowSourceCode, args.ProfilerFilter); Complete(); } private async Task ShowPreviewPopupForSection(PreviewPopupArgs args) { if (!Prepare()) { return; } var parsedSection = await session_.LoadAndParseSection(args.Section); if (parsedSection != null) { var position = Mouse.GetPosition(args.RelativeElement).AdjustForMouseCursor(); previewPopup_ = await IRDocumentPopup.CreateNew(parsedSection, position, args.RelativeElement, session_, settings_, args.Title, args.ShowSourceCode, args.ProfilerFilter); Complete(); } } public void HidePreviewPopup(bool force = false) { if (previewPopup_ != null && (force || !previewPopup_.IsMouseOver)) { previewPopup_.ClosePopup(); previewPopup_ = null; } } private void HidePreviewPopupDelayed() { removeHoveredAction_ = DelayedAction.StartNew(() => { if (removeHoveredAction_ != null) { removeHoveredAction_ = null; HidePreviewPopup(); } }); } private bool Prepare(IRElement element = null) { if (previewPopup_ != null) { if (element != null && previewPopup_.PreviewedElement == element) { return false; // Right preview already displayed. } HidePreviewPopup(true); } if (removeHoveredAction_ != null) { removeHoveredAction_.Cancel(); removeHoveredAction_ = null; } return true; } private void Complete() { previewPopup_.PopupDetached += Popup_PopupDetached; previewPopup_.ShowPopup(); } private void Popup_PopupDetached(object sender, EventArgs e) { var popup = (IRDocumentPopup)sender; if (popup == previewPopup_) { previewPopup_ = null; // Prevent automatic closing. } } private async void Hover_MouseHover(object sender, MouseEventArgs e) { var result = previewedElementFinder_(); if (result != null) { await ShowPreviewPopup(result); } } private async Task ShowPreviewPopup(PreviewPopupArgs args) { if (args.Document != null) { await ShowPreviewPopupForDocument(args); } else if (args.Section != null) { await ShowPreviewPopupForSection(args); } else if (args.LoadedSection != null) { await ShowPreviewPopupForLoadedSection(args); } else { throw new InvalidOperationException(); } return previewPopup_; } public static async Task ShowPreviewPopup(IRTextFunction function, string title, UIElement relativeElement, IUISession session, ProfileSampleFilter profileFilter = null, bool showSourceCode = false, Brush titleBarColor = null) { var settings = App.Settings.PreviewPopupSettings; var instance = new IRDocumentPopupInstance(settings, session); var args = PreviewPopupArgs.ForFunction(function, relativeElement, title, profileFilter, showSourceCode); var popup = await instance.ShowPreviewPopup(args); if (titleBarColor != null) { popup.SetPanelAccentColor(titleBarColor); } } private void Hover_MouseHoverStopped(object sender, MouseEventArgs e) { HidePreviewPopupDelayed(); } } public class PreviewPopupArgs { public string Title { get; set; } public IRElement Element { get; set; } public UIElement RelativeElement { get; set; } public IRDocument Document { get; set; } public ParsedIRTextSection LoadedSection { get; set; } public IRTextSection Section { get; set; } public bool ShowSourceCode { get; set; } public ProfileSampleFilter ProfilerFilter { get; set; } public static PreviewPopupArgs ForDocument(IRDocument document, IRElement element, UIElement relativeElement, string title = "") { return new PreviewPopupArgs { Element = element, Document = document, RelativeElement = relativeElement, Title = title }; } public static PreviewPopupArgs ForSection(IRTextSection section, UIElement relativeElement, string title = "", ProfileSampleFilter profileFilter = null, bool showSourceCode = false) { return new PreviewPopupArgs { Section = section, RelativeElement = relativeElement, Title = title, ProfilerFilter = profileFilter, ShowSourceCode = showSourceCode }; } public static PreviewPopupArgs ForFunction(IRTextFunction function, UIElement relativeElement, string title = "", ProfileSampleFilter profileFilter = null, bool showSourceCode = false) { if (function == null || function.Sections.Count == 0) { return null; } return new PreviewPopupArgs { Section = function.Sections[0], RelativeElement = relativeElement, Title = title, ProfilerFilter = profileFilter, ShowSourceCode = showSourceCode }; } public static PreviewPopupArgs ForLoadedSection(ParsedIRTextSection section, UIElement relativeElement, string title = "") { return new PreviewPopupArgs { LoadedSection = section, RelativeElement = relativeElement, Title = title }; } } ================================================ FILE: src/ProfileExplorerUI/Controls/IconSelector.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/IconSelector.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; namespace ProfileExplorer.UI; public sealed class SelectedIconEventArgs : EventArgs { public string SelectedIconName { get; set; } } public partial class IconSelector : UserControl { public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register("CommandTarget", typeof(IInputElement), typeof(IconSelector), new UIPropertyMetadata(null)); public static DependencyProperty IconSelectedCommandProperty = DependencyProperty.Register("IconSelectedCommand", typeof(ICommand), typeof(IconSelector)); private static readonly Color[] ButtonIcons; public IconSelector() { InitializeComponent(); Focusable = true; Loaded += IconSelector_Loaded; DataContext = this; } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public ICommand IconSelectedCommand { get => (ICommand)GetValue(IconSelectedCommandProperty); set => SetValue(IconSelectedCommandProperty, value); } public IInputElement CommandTarget { get => (IInputElement)GetValue(CommandTargetProperty); set => SetValue(CommandTargetProperty, value); } public event EventHandler IconSelected; private void IconSelector_Loaded(object sender, RoutedEventArgs e) { Focus(); } private void RaiseSelectedIconEvent(string iconName) { if (IconSelectedCommand == null && IconSelected == null) { return; } var parentHost = Utils.FindParentHost(this); if (parentHost != null) { parentHost.Focus(); } var args = new SelectedIconEventArgs { SelectedIconName = iconName }; if (IconSelectedCommand != null) { if (IconSelectedCommand.CanExecute(args)) { IconSelectedCommand.Execute(args); } } else { IconSelected?.Invoke(this, args); } } private UIElement FindParentHost() { var logicalRoot = LogicalTreeHelper.GetParent(this); while (logicalRoot != null) { if (logicalRoot is UserControl || logicalRoot is Window) { break; } logicalRoot = LogicalTreeHelper.GetParent(logicalRoot); } return logicalRoot as UIElement; } private void CloseParentMenu() { // Close the context menu hosting the control. var logicalRoot = LogicalTreeHelper.GetParent(this); while (logicalRoot != null) { if (logicalRoot is ContextMenu menu) { menu.IsOpen = false; break; } if (logicalRoot is Popup popup) { popup.IsOpen = false; break; } logicalRoot = LogicalTreeHelper.GetParent(logicalRoot); } } private void Button_MouseUp(object sender, MouseButtonEventArgs e) { var button = sender as Button; RaiseSelectedIconEvent((string)button.Tag); Utils.CloseParentMenu(this); e.Handled = true; } } ================================================ FILE: src/ProfileExplorerUI/Controls/NotesPopup.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/NotesPopup.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.ComponentModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI.Controls; public partial class NotesPopup : DraggablePopup, INotifyPropertyChanged { private string panelTitle_; public NotesPopup(Point position, double width, double height, UIElement referenceElement) { InitializeComponent(); Initialize(position, width, height, referenceElement); PanelResizeGrip.ResizedControl = this; DataContext = this; } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public IUISession Session { get => TextView.Session; set => TextView.Session = value; } public string PanelTitle { get => panelTitle_; set { if (panelTitle_ != value) { panelTitle_ = value; OnPropertyChange(nameof(PanelTitle)); } } } public event PropertyChangedEventHandler PropertyChanged; public void SetText(string text) { TextView.SetText(text); //? ProfileTextView.EnableIRSyntaxHighlighting(); } public async Task SetText(string text, FunctionIR function, IRTextSection section, IRDocument associatedDocument, IUISession session) { await TextView.SetText(text, function, section, associatedDocument, session); } public override bool ShouldStartDragging(MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && ToolbarPanel.IsMouseOver) { if (!IsDetached) { DetachPopup(); } return true; } return false; } private void OnPropertyChange(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } private void CloseButton_Click(object sender, RoutedEventArgs e) { ClosePopup(); } } ================================================ FILE: src/ProfileExplorerUI/Controls/OptionalColumn.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using ProfileExplorer.UI.Profile; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.UI; public delegate void OptionalColumnEventHandler(OptionalColumn column, GridViewColumnHeader columnHeader); public class OptionalColumn : ICloneable { public OptionalColumnEventHandler HeaderClickHandler; public OptionalColumnEventHandler HeaderRightClickHandler; public OptionalColumnEventHandler HeaderDoubleClickHandler; private int hashCode_; private OptionalColumn(string bindingName, string cellTemplateName, string columnName, string title, string tooltip, IValueConverter converter = null, double width = double.NaN, string columnTemplateName = null, OptionalColumnStyle style = null, bool isVisible = true) { BindingName = bindingName; CellTemplateName = cellTemplateName; ColumnName = string.Intern(columnName); Title = title; Tooltip = tooltip; Width = width; Converter = converter; ColumnTemplateName = columnTemplateName; Style = style ?? new OptionalColumnStyle(); IsVisible = isVisible; IsTemplateBinding = cellTemplateName != null; } public string BindingName { get; set; } public string CellTemplateName { get; set; } public string ColumnName { get; set; } public string ColumnTemplateName { get; set; } public string Title { get; set; } public string Tooltip { get; set; } public double Width { get; set; } public IValueConverter Converter { get; set; } public OptionalColumnStyle Style { get; set; } public PerformanceCounter PerformanceCounter { get; set; } public bool IsVisible { get; set; } public bool IsMainColumn { get; set; } public bool IsTemplateBinding { get; set; } public bool HasCustomStyle => !string.IsNullOrEmpty(ColumnTemplateName); public Style CustomStyle => !string.IsNullOrEmpty(ColumnTemplateName) ? (Style)Application.Current.FindResource(ColumnTemplateName) : null; public bool IsPerformanceCounter => PerformanceCounter is {IsMetric: false}; public bool IsPerformanceMetric => PerformanceCounter is {IsMetric: true}; public object Clone() { var clone = new OptionalColumn(BindingName, CellTemplateName, ColumnName, Title, Tooltip, Converter, Width, ColumnTemplateName, Style, IsVisible) { HeaderClickHandler = HeaderClickHandler, HeaderRightClickHandler = HeaderRightClickHandler, HeaderDoubleClickHandler = HeaderDoubleClickHandler, PerformanceCounter = PerformanceCounter }; return clone; } public static OptionalColumn Binding(string binding, string columnName, string title, string tooltip = null, IValueConverter converter = null, double width = double.NaN, string columnStyle = null, OptionalColumnStyle style = null, bool isVisible = true) { return new OptionalColumn(binding, null, columnName, title, tooltip, converter, width, columnStyle, style, isVisible); } public static OptionalColumn Template(string binding, string templateName, string columnName, string title, string tooltip = null, IValueConverter converter = null, double width = double.NaN, string columnStyle = null, OptionalColumnStyle style = null, bool isVisible = true) { return new OptionalColumn(binding, templateName, columnName, title, tooltip, converter, width, columnStyle, style, isVisible); } public static void RemoveListViewColumns(ListView listView, OptionalColumn[] columns, IGridViewColumnValueSorter columnSorter = null) { foreach (var column in columns) { RemoveListViewColumn(listView, column.ColumnName, columnSorter); } } public static void RemoveListViewColumns(ListView listView, Func predicate = null, IGridViewColumnValueSorter columnSorter = null) { var functionGrid = (GridView)listView.View; var removedColumns = new List(); foreach (var column in functionGrid.Columns) { var header = column.Header as GridViewColumnHeader; if (predicate == null || predicate(header)) { removedColumns.Add(column); } } foreach (var column in removedColumns) { functionGrid.Columns.Remove(column); columnSorter?.UnregisterColumnHeader((GridViewColumnHeader)column.Header); } } public static List<(GridViewColumnHeader Header, GridViewColumn Column)> AddListViewColumns( ListView listView, IEnumerable columns, IGridViewColumnValueSorter columnSorter = null, string titleSuffix = "", string tooltipSuffix = "", bool useValueConverter = true, int insertionIndex = -1) { var columnHeaders = new List<(GridViewColumnHeader, GridViewColumn)>(); foreach (var column in columns) { if (column.IsVisible) { columnHeaders.Add(AddListViewColumn(listView, column, columnSorter, titleSuffix, tooltipSuffix, useValueConverter, insertionIndex)); insertionIndex = insertionIndex != -1 ? insertionIndex + 1 : -1; } } return columnHeaders; } public static GridViewColumnHeader RemoveListViewColumn(ListView listView, string columnName, IGridViewColumnValueSorter columnSorter = null) { var functionGrid = (GridView)listView.View; foreach (var column in functionGrid.Columns) { if (column.Header is GridViewColumnHeader header) { if (header.Name == columnName) { functionGrid.Columns.Remove(column); columnSorter?.UnregisterColumnHeader(header); return header; } } } return null; } public static (GridViewColumnHeader Header, GridViewColumn Column) AddListViewColumn(ListView listView, OptionalColumn column, IGridViewColumnValueSorter columnSorter = null, string titleSuffix = "", string tooltipSuffix = "", bool useValueConverter = true, int index = -1) { var functionGrid = (GridView)listView.View; var columnHeader = new GridViewColumnHeader { Name = column.ColumnName, VerticalAlignment = VerticalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Stretch, VerticalContentAlignment = VerticalAlignment.Stretch, HorizontalContentAlignment = HorizontalAlignment.Left, Padding = new Thickness(0, 0, 7, 0), Width = column.Width, Content = string.Format(column.Title, titleSuffix), ToolTip = string.Format(column.Tooltip, tooltipSuffix), OverridesDefaultStyle = column.HasCustomStyle, Style = column.CustomStyle, Tag = column }; var converter = useValueConverter ? column.Converter : null; var gridColumn = new GridViewColumn { Header = columnHeader, Width = column.Width, CellTemplate = column.IsTemplateBinding ? CreateGridColumnTemplateBindingTemplate(column.BindingName, column.CellTemplateName) : CreateGridColumnBindingTemplate(column.BindingName, converter) }; if (index != -1) { functionGrid.Columns.Insert(index, gridColumn); } else { functionGrid.Columns.Add(gridColumn); } columnSorter?.RegisterColumnHeader(columnHeader); return (columnHeader, gridColumn); } public static int FindListViewColumnIndex(string name, ListView listView) { var functionGrid = (GridView)listView.View; int index = 0; foreach (var column in functionGrid.Columns) { if (column.Header is GridViewColumnHeader columnHeader && columnHeader.Name == name) { return index; } index++; } return -1; } private static DataTemplate CreateGridColumnBindingTemplate(string propertyName, IValueConverter valueConverter = null) { var template = new DataTemplate(); var factory = new FrameworkElementFactory(typeof(TextBlock)); factory.SetValue(TextBlock.TextAlignmentProperty, TextAlignment.Left); var binding = new Binding(propertyName); binding.Converter = valueConverter; factory.SetBinding(TextBlock.TextProperty, binding); template.VisualTree = factory; return template; } private static DataTemplate CreateGridColumnTemplateBindingTemplate(string propertyName, string sourceTampleteName) { //? Preloading XAML is faster //? https://stackoverflow.com/questions/24620656/how-does-use-xamlreader-to-load-from-a-xaml-file-from-within-the-assembly/24623673 var template = new DataTemplate(); var sourceTemplate = (DataTemplate)Application.Current.FindResource(sourceTampleteName); var factory = new FrameworkElementFactory(typeof(ContentControl)); var binding = new Binding(propertyName); factory.SetBinding(ContentControl.ContentProperty, binding); factory.SetValue(ContentControl.ContentTemplateProperty, sourceTemplate); template.VisualTree = factory; return template; } public override bool Equals(object? obj) { return obj is OptionalColumn other && other.IsTemplateBinding == IsTemplateBinding && other.ColumnName.Equals(ColumnName); } public override int GetHashCode() { if (hashCode_ != 0) { return hashCode_; } hashCode_ = HashCode.Combine(ColumnName, IsTemplateBinding); return hashCode_; } } ================================================ FILE: src/ProfileExplorerUI/Controls/PanelToolbarTray.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/PanelToolbarTray.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace ProfileExplorer.UI; public class PinEventArgs : EventArgs { public bool IsPinned { get; set; } } public class DuplicateEventArgs : EventArgs { public DuplicatePanelKind Kind { get; set; } } public class BindMenuItem { public string Header { get; set; } public string ToolTip { get; set; } public object Tag { get; set; } public bool IsChecked { get; set; } } public class BindMenuItemsArgs : EventArgs { public List MenuItems; public BindMenuItemsArgs() { MenuItems = new List(); } } public partial class PanelToolbarTray : ToolBarTray { public static readonly DependencyProperty HasPinButtonProperty = DependencyProperty.Register("HasPinButton", typeof(bool), typeof(PanelToolbarTray), new PropertyMetadata(true, OnHasPinButtonPropertyChanged)); public static readonly DependencyProperty HasDuplicateButtonProperty = DependencyProperty.Register("HasDuplicateButton", typeof(bool), typeof(PanelToolbarTray), new PropertyMetadata(true, OnHasDuplicateButtonPropertyChanged)); public static readonly DependencyProperty HasHelpButtonProperty = DependencyProperty.Register("HasHelpButton", typeof(bool), typeof(PanelToolbarTray), new PropertyMetadata(true, OnHasHelpButtonPropertyChanged)); private bool registerLeftButtonDown_; public PanelToolbarTray() { InitializeComponent(); } public bool HasPinButton { get => (bool)GetValue(HasPinButtonProperty); set => SetValue(HasPinButtonProperty, value); } public bool HasDuplicateButton { get => (bool)GetValue(HasDuplicateButtonProperty); set => SetValue(HasDuplicateButtonProperty, value); } public bool HasHelpButton { get => (bool)GetValue(HasHelpButtonProperty); set => SetValue(HasHelpButtonProperty, value); } public bool IsPinned { get => PinButton.IsChecked.HasValue && PinButton.IsChecked.Value; set => PinButton.IsChecked = value; } public event EventHandler PinnedChanged; public event EventHandler DuplicateClicked; public event EventHandler SettingsClicked; public event EventHandler HelpClicked; public event EventHandler BindMenuOpen; public event EventHandler BindMenuItemSelected; private static void OnHasPinButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as PanelToolbarTray; bool visible = (bool)e.NewValue; source.PinButton.Visibility = visible ? Visibility.Visible : Visibility.Collapsed; } private static void OnHasDuplicateButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as PanelToolbarTray; bool visible = (bool)e.NewValue; source.DuplicateButton.Visibility = visible ? Visibility.Visible : Visibility.Collapsed; } private static void OnHasHelpButtonPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as PanelToolbarTray; bool visible = (bool)e.NewValue; source.HelpButton.Visibility = visible ? Visibility.Visible : Visibility.Collapsed; } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.RemoveToolbarOverflowButton(sender as ToolBar); } private void PinButton_Checked(object sender, RoutedEventArgs e) { PinnedChanged?.Invoke(this, new PinEventArgs {IsPinned = true}); } private void PinButton_Unchecked(object sender, RoutedEventArgs e) { PinnedChanged?.Invoke(this, new PinEventArgs {IsPinned = false}); } private void SettingsButton_Click(object sender, RoutedEventArgs e) { // If popup was active when the click started, ignore it since // the user most likely wants to close the popup panel. if (!registerLeftButtonDown_) { registerLeftButtonDown_ = false; return; } registerLeftButtonDown_ = false; SettingsClicked?.Invoke(this, EventArgs.Empty); } private void HelpButton_Click(object sender, RoutedEventArgs e) { // If popup was active when the click started, ignore it since // the user most likely wants to close the popup panel. if (!registerLeftButtonDown_) { registerLeftButtonDown_ = false; return; } registerLeftButtonDown_ = false; HelpClicked?.Invoke(this, EventArgs.Empty); } private void DuplicateMenu_Click(object sender, RoutedEventArgs e) { DuplicateClicked?.Invoke(this, new DuplicateEventArgs {Kind = DuplicatePanelKind.SameSet}); } private void DuplicateLeftMenu_Click(object sender, RoutedEventArgs e) { DuplicateClicked?.Invoke( this, new DuplicateEventArgs {Kind = DuplicatePanelKind.NewSetDockedLeft}); } private void DuplicateRightMenu_Click(object sender, RoutedEventArgs e) { DuplicateClicked?.Invoke( this, new DuplicateEventArgs {Kind = DuplicatePanelKind.NewSetDockedRight}); } private void DuplicateFloatingMenu_Click(object sender, RoutedEventArgs e) { DuplicateClicked?.Invoke(this, new DuplicateEventArgs {Kind = DuplicatePanelKind.Floating}); } private void SettingsButton_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // This is a workaround for the way clicks on the options icon are handled by WPF // when the popup panel is active. The user most likely wants to close the popup // by clicking again on the icon, but instead the popup closes and immediately opens again. // // - When the button is clicked, it Opens the popup. // - When the button is clicked again, the button raises the MouseDown event // and the Popup closes on that event. // - Afterwards the Clicked event is raised, but since the Popup is already closed, // it will open it again, thus causing for the Popup to be closed & opened immediately. // // The MouseLeftButtonDown is not triggered when the popup is active. registerLeftButtonDown_ = true; } private void ToolBar_OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) { Utils.RemoveToolbarOverflowButton(sender as ToolBar); } private void ToolBar_OnSizeChanged(object sender, SizeChangedEventArgs e) { Utils.RemoveToolbarOverflowButton(sender as ToolBar); } } ================================================ FILE: src/ProfileExplorerUI/Controls/ResizeGrip.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/ResizeGrip.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; namespace ProfileExplorer.UI.Controls; public partial class ResizeGrip : UserControl { private Cursor cursor_; private FrameworkElement control_; public ResizeGrip() { InitializeComponent(); } public FrameworkElement ResizedControl { get => control_; set => control_ = value; } private void OnResizeThumbDragStarted(object sender, DragStartedEventArgs e) { // Disable min size constraints when manually resizing. control_.MaxHeight = double.PositiveInfinity; control_.MaxWidth = double.PositiveInfinity; cursor_ = control_.Cursor; Cursor = Cursors.SizeNWSE; } private void OnResizeThumbDragCompleted(object sender, DragCompletedEventArgs e) { Cursor = cursor_; } private void OnResizeThumbDragDelta(object sender, DragDeltaEventArgs e) { double yAdjust = control_.Height + e.VerticalChange; double xAdjust = control_.Width + e.HorizontalChange; xAdjust = control_.ActualWidth + xAdjust > control_.MinWidth ? xAdjust : control_.MinWidth; yAdjust = control_.ActualHeight + yAdjust > control_.MinHeight ? yAdjust : control_.MinHeight; control_.Width = xAdjust; control_.Height = yAdjust; } } ================================================ FILE: src/ProfileExplorerUI/Controls/WebViewPopup.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Controls/WebViewPopup.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.ComponentModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; namespace ProfileExplorer.UI.Controls; public partial class WebViewPopup : DraggablePopup, INotifyPropertyChanged { private string panelTitle_; public WebViewPopup(Point position, double width, double height, UIElement referenceElement) { InitializeComponent(); Initialize(position, width, height, referenceElement); PanelResizeGrip.ResizedControl = this; DataContext = this; } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public string PanelTitle { get => panelTitle_; set { if (panelTitle_ != value) { panelTitle_ = value; OnPropertyChange(nameof(PanelTitle)); } } } public event PropertyChangedEventHandler PropertyChanged; public async Task NavigateToURL(string url) { Browser.Source = new Uri(url); } public override bool ShouldStartDragging(MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && ToolbarPanel.IsMouseOver) { if (!IsDetached) { DetachPopup(); } return true; } return false; } private void OnPropertyChange(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } private void CloseButton_Click(object sender, RoutedEventArgs e) { ClosePopup(); } } ================================================ FILE: src/ProfileExplorerUI/Converters.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Diff/DocumentDiffUpdater.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using DiffPlex.DiffBuilder.Model; using ICSharpCode.AvalonEdit.Document; using ProfileExplorer.Core; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Document.Renderers.Highlighters; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.UI.Diff; public class DiffStatistics { public int LinesAdded { get; set; } public int LinesDeleted { get; set; } public int LinesModified { get; set; } public override string ToString() { if (LinesAdded == 0 && LinesDeleted == 0 && LinesModified == 0) { return "0 diffs"; } return $"A {LinesAdded}, D {LinesDeleted}, M {LinesModified}"; } } public class DocumentDiffUpdater { private const char RemovedDiffLineChar = ' '; private const char AddedDiffLineChar = ' '; private ICompilerInfoProvider compilerInfo_; private DiffSettings settings_; private IDiffOutputFilter diffFilter_; private char[] ignoredDiffLetters_; public DocumentDiffUpdater(IDiffOutputFilter diffFilter, DiffSettings settings, ICompilerInfoProvider compilerInfo) { diffFilter_ = diffFilter; settings_ = settings; compilerInfo_ = compilerInfo; ignoredDiffLetters_ = diffFilter_.IgnoredDiffLetters; } public DiffMarkingResult CreateNoDiffDocument(string text) { var document = new TextDocument(new StringTextSource(text)); document.SetOwnerThread(Thread.CurrentThread); var result = new DiffMarkingResult(document); result.DiffText = text; document.SetOwnerThread(null); return result; } public DiffMarkingResult MarkDiffs(string text, string otherText, DiffPaneModel diff, DiffPaneModel otherDiff, bool isRightDoc, FilteredDiffInput filteredInput, DiffStatistics diffStats, bool markRightDocDeletion = false) { // Create a new text document and associate it with the task worker. var document = new TextDocument(new StringTextSource(text)); document.SetOwnerThread(Thread.CurrentThread); var result = new DiffMarkingResult(document); int lineCount = diff.Lines.Count; int lineAdjustment = 0; for (int lineIndex = 0; lineIndex < lineCount; lineIndex++) { var line = diff.Lines[lineIndex]; switch (line.Type) { case ChangeType.Unchanged: { break; // Ignore. } case ChangeType.Inserted: { int actualLine = line.Position.Value + lineAdjustment; int offset; if (actualLine >= document.LineCount) { offset = document.TextLength; } else { offset = document.GetOffset(actualLine, 0); } document.Insert(offset, line.Text + Environment.NewLine); AppendInsertionChange(diffStats, result, line, offset); break; } case ChangeType.Deleted: { int actualLine = line.Position.Value + lineAdjustment; var docLine = document.GetLineByNumber(Math.Min(document.LineCount, actualLine)); AppendDeletionChange(diffStats, result, docLine); break; } case ChangeType.Imaginary: { int docLineIndex = lineIndex + 1; if (isRightDoc) { // Mark the lines that have been removed on the right side. if (docLineIndex <= document.LineCount) { var docLine = document.GetLineByNumber(docLineIndex); if (markRightDocDeletion) { // Show the actual text that has been deleted. result.DiffSegments.Add( new DiffTextSegment(DiffKind.Deletion, docLine.Offset, docLine.Length)); } else { document.Replace(docLine.Offset, docLine.Length, new string(RemovedDiffLineChar, docLine.Length)); result.DiffSegments.Add(new DiffTextSegment(DiffKind.Placeholder, docLine.Offset, docLine.Length)); } } } else { // Add a placeholder in the left side to mark // the lines inserted on the right side. int offset = docLineIndex <= document.LineCount ? document.GetOffset(docLineIndex, 0) : document.TextLength; string imaginaryText = new(AddedDiffLineChar, otherDiff.Lines[lineIndex].Text.Length); document.Insert(offset, imaginaryText + Environment.NewLine); result.DiffSegments.Add(new DiffTextSegment(DiffKind.Placeholder, offset, imaginaryText.Length)); } lineAdjustment++; break; } case ChangeType.Modified: { MarkLineModificationDiffs(line, lineIndex, lineAdjustment, document, isRightDoc, otherDiff, result, diffStats); break; } default: throw new ArgumentOutOfRangeException(); } // If the input text had parts replaced as a form of canonicalization, // replace those with the original text. if (filteredInput != null && line.Type != ChangeType.Imaginary) { int filteredLine = lineIndex - lineAdjustment; int docLineIndex = lineIndex + 1; if (filteredLine < filteredInput.LineReplacements.Count && docLineIndex <= document.LineCount) { var replacements = filteredInput.LineReplacements[filteredLine]; var docLine = document.GetLineByNumber(docLineIndex); foreach (var replacement in replacements) { int docLineOffset = docLine.Offset + replacement.Offset; if (docLineOffset + replacement.Length < document.TextLength) { document.Replace(docLineOffset, replacement.Length, replacement.Original); } } } } } result.DiffText = document.Text; document.SetOwnerThread(null); return result; } public async Task ReparseDiffedFunction(DiffMarkingResult diffResult, IRTextSection originalSection, ILoadedDocument loadedDoc) { try { var errorHandler = compilerInfo_.IR.CreateParsingErrorHandler(); var sectionParser = compilerInfo_.IR.CreateSectionParser(errorHandler); diffResult.DiffFunction = sectionParser.ParseSection(originalSection, diffResult.DiffText); if (diffResult.DiffFunction != null) { await compilerInfo_.AnalyzeLoadedFunction(diffResult.DiffFunction, originalSection, loadedDoc); } else { Trace.TraceWarning("Failed re-parsing diffed section\n"); } if (errorHandler.HadParsingErrors) { Trace.TraceWarning("Errors while re-parsing diffed section:\n"); if (errorHandler.ParsingErrors != null) { foreach (var error in errorHandler.ParsingErrors) { Trace.TraceWarning($" - {error}"); } } } } catch (Exception ex) { Trace.TraceError($"Crashed while re-parsing diffed section: {ex}"); diffResult.DiffFunction = new FunctionIR(); } } private void MarkLineModificationDiffs(DiffPiece line, int lineIndex, int lineAdjustment, TextDocument document, bool isRightDoc, DiffPaneModel otherDiff, DiffMarkingResult result, DiffStatistics diffStats) { int actualLine = line.Position.Value + lineAdjustment; int lineChanges = 0; int lineLength = 0; bool wholeLineReplaced = false; if (actualLine < document.LineCount) { // Use the modified line instead; below the segments // of the line that were changed (the sub-pieces) are marked. var docLine = document.GetLineByNumber(actualLine); document.Replace(docLine.Offset, docLine.Length, line.Text); wholeLineReplaced = true; lineLength = docLine.Length; } var modifiedSegments = new List(); int column = 0; int otherColumn = 0; //? TODO: This is an ugly hack to get the two piece lists aligned //? for Beyond Compare in case there is a word inserted at the line start //? like in "r t100" vs " t100" - the BC diff builder should match DiffPlex //? and insert a dummy whitespace diff corresponding to "r" instead two whitespaces in " t100", //? which would create the same number of diffs on both sides var pieces = line.SubPieces; var otherPieces = otherDiff.Lines[lineIndex].SubPieces; int pieceIndexAdjustment = 0; if (pieces[0].Type != otherPieces[0].Type) { if (isRightDoc) { if (otherPieces.Count > 1 && otherPieces[1].Type == pieces[0].Type && pieces[0].Text.EndsWith(otherPieces[1].Text)) { otherColumn += otherPieces[0].Text.Length; pieceIndexAdjustment = 1; } } else { if (pieces.Count > 1 && otherPieces[0].Type == pieces[1].Type && otherPieces[0].Text.EndsWith(pieces[1].Text)) { pieceIndexAdjustment = -1; } } } foreach (var piece in line.SubPieces) { switch (piece.Type) { case ChangeType.Inserted: { Debug.Assert(isRightDoc); int offset = actualLine >= document.LineCount ? document.TextLength : document.GetOffset(actualLine, 0) + column; if (offset >= document.TextLength) { // Text inserted at the end of the line and document. if (!wholeLineReplaced) { document.Insert(document.TextLength, piece.Text); } if (IsSignifficantDiff(piece)) { modifiedSegments.Add(new DiffTextSegment(DiffKind.Modification, offset, piece.Text.Length)); } } else { // Check if this insertion has an equivalent deletion on the other side. // If it does, try to mark it as a modification. var diffKind = DiffKind.Insertion; var otherPiece = FindPieceInOtherDocument(otherDiff, lineIndex, piece, pieceIndexAdjustment); if (otherPiece != null && otherPiece.Type == ChangeType.Deleted) { if (!wholeLineReplaced) { document.Replace(offset, otherPiece.Text.Length, piece.Text); } if (wholeLineReplaced) { string diffLine = line.Text; string otherDiffLine = otherDiff.Lines[lineIndex].Text; int otherPieceOffset = otherColumn; int pieceOffset = column; diffKind = EstimateModificationType(piece, otherPiece, pieceOffset, otherPieceOffset, diffLine, otherDiffLine); } } else { // Try again to find a piece that matches the same offset. otherPiece = FindOverlappingPieceInOtherDocument(otherDiff, lineIndex, column); if (otherPiece != null && otherPiece.Type == ChangeType.Unchanged) { if (!wholeLineReplaced) { document.Replace(offset, otherPiece.Text.Length, piece.Text); } string diffLine = line.Text; string otherDiffLine = otherDiff.Lines[lineIndex].Text; int otherPieceOffset = column; int pieceOffset = column; diffKind = EstimateModificationType(piece, otherPiece, pieceOffset, otherPieceOffset, diffLine, otherDiffLine); } else if (!wholeLineReplaced) { document.Insert(offset, piece.Text); } } if (otherPiece != null) { otherColumn += otherPiece.Text.Length; } if (IsSignifficantDiff(piece)) { var filteredPiece = diffFilter_.AdjustChange(piece, offset, column, line.Text); AppendModificationChange(modifiedSegments, diffKind, filteredPiece); } } break; } case ChangeType.Deleted: { Debug.Assert(!isRightDoc); int offset = actualLine >= document.LineCount ? document.TextLength : document.GetOffset(actualLine, 0) + column; // Check if this deletion has an equivalent insertion on the other side. // If it does, try to mark it as a modification. var diffKind = DiffKind.Deletion; var otherPiece = FindPieceInOtherDocument(otherDiff, lineIndex, piece, pieceIndexAdjustment); if (otherPiece != null && otherPiece.Type == ChangeType.Inserted) { if (wholeLineReplaced) { string diffLine = line.Text; string otherDiffLine = otherDiff.Lines[lineIndex].Text; int otherPieceOffset = otherColumn; int pieceOffset = column; diffKind = EstimateModificationType(piece, otherPiece, pieceOffset, otherPieceOffset, diffLine, otherDiffLine); } } //else { // otherPiece = FindOverlappingPieceInOtherDocument(otherDiff, lineIndex, column); // if (otherPiece != null && otherPiece.Type == ChangeType.Unchanged) { // var diffLine = line.Text; // var otherDiffLine = otherDiff.Lines[lineIndex].Text; // int otherPieceOffset = column; // int pieceOffset = column; // diffKind = EstimateModificationType(piece, otherPiece, // pieceOffset, otherPieceOffset, // diffLine, otherDiffLine); // } //} if (IsSignifficantDiff(piece)) { var filteredPiece = diffFilter_.AdjustChange(piece, offset, column, line.Text); AppendModificationChange(modifiedSegments, diffKind, filteredPiece); } if (otherPiece != null) { otherColumn += otherPiece.Text.Length; } break; } case ChangeType.Modified: case ChangeType.Imaginary: { break; // Nothing to do here. } case ChangeType.Unchanged: { if (!wholeLineReplaced && actualLine < document.LineCount) { int offset = document.GetOffset(actualLine, 0) + column; document.Replace(offset, piece.Text.Length, piece.Text); } var otherPiece = FindPieceInOtherDocument(otherDiff, lineIndex, piece, 0); if (otherPiece != null) { otherColumn += piece.Text.Length; } break; } default: throw new ArgumentOutOfRangeException("Unexpected change type!"); } // Adjust the current column in the document. if (piece.Text != null) { column += piece.Text.Length; if (piece.Type != ChangeType.Unchanged) { lineChanges += piece.Text.Length; } } } // If most of the line changed, mark the entire line, // otherwise mark each sub-piece. if (settings_.ManyDiffsMarkWholeLine) { double percentChanged = 0; if (lineLength > 0) { percentChanged = lineChanges / (double)lineLength * 100; } if (percentChanged > settings_.ManyDiffsModificationPercentage) { if (actualLine < document.LineCount) { var docLine = document.GetLineByNumber(actualLine); var changeKind = DiffKind.Modification; // If even more of the line changed, consider it an insertion/deletion. if (percentChanged > settings_.ManyDiffsInsertionPercentage) { changeKind = isRightDoc ? DiffKind.Insertion : DiffKind.Deletion; } AppendChange(changeKind, docLine.Offset, docLine.Length, result); return; } } } foreach (var segment in modifiedSegments) { AppendChange(segment, result); } if (isRightDoc) { diffStats.LinesModified++; } } private void AppendChange(DiffKind kind, int offset, int length, DiffMarkingResult result) { AppendChange(new DiffTextSegment(kind, offset, length), result); } private void AppendChange(DiffTextSegment segment, DiffMarkingResult result) { bool accepted = false; switch (segment.Kind) { case DiffKind.Insertion: { accepted = settings_.ShowInsertions; break; } case DiffKind.Deletion: { accepted = settings_.ShowDeletions; break; } case DiffKind.Modification: { accepted = settings_.ShowModifications; break; } case DiffKind.MinorModification: { accepted = settings_.ShowMinorModifications; break; } } if (accepted) { result.DiffSegments.Add(segment); } } private void AppendInsertionChange(DiffStatistics diffStats, DiffMarkingResult result, DiffPiece line, int offset) { AppendChange(DiffKind.Insertion, offset, line.Text.Length, result); diffStats.LinesAdded++; } private void AppendDeletionChange(DiffStatistics diffStats, DiffMarkingResult result, DocumentLine docLine) { AppendChange(DiffKind.Deletion, docLine.Offset, docLine.Length, result); diffStats.LinesDeleted++; } private void AppendModificationChange(List modifiedSegments, DiffKind diffKind, AdjustedDiffPiece filteredPiece) { // With modifications that are expanded, it's possible to have two diffs // be expanded to the same text range - in that case keep the initial segment. if (modifiedSegments.Count > 0) { var lastSegment = modifiedSegments[^1]; if (lastSegment.StartOffset == filteredPiece.Offset && lastSegment.Length == filteredPiece.Length) { return; } } modifiedSegments.Add(new DiffTextSegment(diffKind, filteredPiece.Offset, filteredPiece.Length)); } private DiffPiece FindPieceInOtherDocument(DiffPaneModel otherDiff, int lineIndex, DiffPiece piece, int piecePossitionOffset) { if (lineIndex < otherDiff.Lines.Count) { var otherLine = otherDiff.Lines[lineIndex]; int position = piece.Position.Value + piecePossitionOffset; if (position > 0 && position <= otherLine.SubPieces.Count) { var result = otherLine.SubPieces[position - 1]; return !string.IsNullOrEmpty(result.Text) ? result : null; } } return null; } private DiffPiece FindOverlappingPieceInOtherDocument(DiffPaneModel otherDiff, int lineIndex, int offset) { if (lineIndex < otherDiff.Lines.Count) { var otherLine = otherDiff.Lines[lineIndex]; int otherOffset = 0; foreach (var piece in otherLine.SubPieces) { if (!string.IsNullOrEmpty(piece.Text)) { if (otherOffset <= offset && otherOffset + piece.Text.Length >= offset) { return piece; } otherOffset += otherLine.Text.Length; } } } return null; } private bool IsSignifficantDiff(DiffPiece piece, DiffPiece otherPiece = null) { if (!settings_.FilterInsignificantDiffs) { return true; } if (piece.Text == null) { return false; } foreach (char letter in piece.Text) { if (!char.IsWhiteSpace(letter) && Array.IndexOf(ignoredDiffLetters_, letter) == -1) { return true; } } return false; } private DiffKind EstimateModificationType(DiffPiece before, DiffPiece after, int beforeOffset, int afterOffset, string beforeDocumentText, string afterDocumentText) { if (!settings_.IdentifyMinorDiffs) { return DiffKind.Modification; } return diffFilter_.EstimateModificationType(before, after, beforeOffset, afterOffset, beforeDocumentText, afterDocumentText); } } ================================================ FILE: src/ProfileExplorerUI/Document/ActionPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Document/ActionPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; namespace ProfileExplorer.UI.Document; public class ActionPanelButton { public ActionPanelButton(string name, object tag = null) { Name = name; Tag = tag; } public string Name { get; set; } public object Tag { get; set; } } public partial class ActionPanel : UserControl, INotifyPropertyChanged { private ObservableCollectionRefresh buttons_; private bool showRemarksButton_; public ActionPanel() { InitializeComponent(); DataContext = this; buttons_ = new ObservableCollectionRefresh(); ActionButtonsPanel.ItemsSource = buttons_; } public bool ShowRemarksButton { get => showRemarksButton_; set { if (showRemarksButton_ != value) { showRemarksButton_ = value; OnPropertyChange(nameof(ShowRemarksButton)); } } } public bool HasActionButtons => buttons_.Count > 0; public event PropertyChangedEventHandler PropertyChanged; public event EventHandler RemarksButtonClicked; public event EventHandler ActionButtonClicked; public ActionPanelButton AddActionButton(string name, object tag = null) { var button = new ActionPanelButton(name, tag); buttons_.Add(button); OnPropertyChange(nameof(HasActionButtons)); return button; } public void ClearActionButtons() { buttons_.Clear(); OnPropertyChange(nameof(HasActionButtons)); } public void OnPropertyChange(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } private void ActionButton_Click(object sender, RoutedEventArgs e) { var button = (ActionPanelButton)((Button)sender).DataContext; ActionButtonClicked?.Invoke(this, button); } private void RemarkButton_Click(object sender, RoutedEventArgs e) { RemarksButtonClicked?.Invoke(this, e); } } ================================================ FILE: src/ProfileExplorerUI/Document/BasicBlockFoldingStrategy.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Folding; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI; public interface IBlockFoldingStrategy { public void UpdateFoldings(FoldingManager manager, TextDocument document); } public sealed class BasicBlockFoldingStrategy : IBlockFoldingStrategy { private FunctionIR function_; public BasicBlockFoldingStrategy(FunctionIR function) { function_ = function; } public void UpdateFoldings(FoldingManager manager, TextDocument document) { var newFoldings = CreateNewFoldings(document, out int firstErrorOffset); manager.UpdateFoldings(newFoldings, firstErrorOffset); } private IEnumerable CreateNewFoldings(TextDocument document, out int firstErrorOffset) { firstErrorOffset = -1; return CreateNewFoldings(document); } private IEnumerable CreateNewFoldings(ITextSource document) { var newFoldings = new List(function_.Blocks.Count); if (function_.Blocks.Count == 0) { return newFoldings; } BlockIR lastBlock = null; int lastOffset = 0; int textLength = document.TextLength; foreach (var block in function_.Blocks) { int offset = block.TextLocation.Offset; int foldingLength = offset - lastOffset; if (lastBlock != null && foldingLength > 1) { //? TODO: This seems to be a bug with diff mode int endOffset = Math.Min(offset, textLength - 1); if (endOffset > lastOffset) { newFoldings.Add(new NewFolding(lastOffset, endOffset - 2)); } } lastOffset = offset; lastBlock = block; } // Handle the last block. if (lastOffset < textLength - 1) { int endOffset = Math.Min(lastOffset + function_.Blocks[^1].TextLength, textLength - 1); if (endOffset > lastOffset) { newFoldings.Add(new NewFolding(lastOffset, endOffset - 2)); } } return newFoldings; } } ================================================ FILE: src/ProfileExplorerUI/Document/BasicBlockFoldingStrategyProvider.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Folding; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Providers; namespace ProfileExplorer.UI.Document; public class BasicBlockFoldingStrategyProvider : IBlockFoldingStrategyProvider { public IBlockFoldingStrategy CreateFoldingStrategy(FunctionIR function) { return new BasicBlockFoldingStrategy(function); } } ================================================ FILE: src/ProfileExplorerUI/Document/DocumentAction.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI; public enum DocumentActionKind { SelectElement, MarkElement, MarkBlock, GoToDefinition, ShowReferences, MarkReferences, ShowUses, MarkUses, MarkExpression, ClearMarker, ClearAllMarkers, ClearBlockMarkers, ClearInstructionMarkers, ClearTemporaryMarkers, UndoAction, VerticalScroll, ShowExpressionGraph } public class DocumentAction { public DocumentAction(DocumentActionKind actionKind, IRElement element = null, object optionalData = null) { ActionKind = actionKind; Element = element; OptionalData = optionalData; } public DocumentActionKind ActionKind { get; set; } public IRElement Element { get; set; } public object OptionalData { get; set; } public DocumentAction WithNewElement(IRElement newElement) { return new DocumentAction(ActionKind, newElement, OptionalData); } public override string ToString() { return $"action: {ActionKind}, element: {Element}"; } } public class MarkActionData { public bool IsTemporary { get; set; } public PairHighlightingStyle Style { get; set; } } public class ReversibleDocumentAction { public ReversibleDocumentAction(DocumentAction action, Action undoAction) { Action = action; UndoAction = undoAction; } public Action UndoAction { get; set; } private DocumentAction Action { get; set; } public void Undo() { UndoAction?.Invoke(Action); } public override string ToString() { return Action.ToString(); } } ================================================ FILE: src/ProfileExplorerUI/Document/DocumentExporting.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; using System.Web; using System.Windows; using ClosedXML.Excel; using HtmlAgilityPack; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.UI.Document; public static class DocumentExporting { private static string ExcelFileFilter = "Excel Worksheets|*.xlsx"; private static string HtmlFileFilter = "HTML file|*.html"; private static string MarkdownFileFilter = "Markdown file|*.md"; private static string ExcelExtension = "*.xlsx|All Files|*.*"; private static string HtmlExtension = "*.html|All Files|*.*"; private static string MarkdownExtension = "*.md|All Files|*.*"; public static async Task ExportToExcelFile(IRDocument textView, Func> saveAction) { await ExportToFile(textView, ExcelFileFilter, ExcelExtension, saveAction); } public static async Task ExportToHtmlFile(IRDocument textView, Func> saveAction) { await ExportToFile(textView, HtmlFileFilter, HtmlExtension, saveAction); } public static async Task ExportToMarkdownFile(IRDocument textView, Func> saveAction) { await ExportToFile(textView, MarkdownFileFilter, MarkdownExtension, saveAction); } private static async Task ExportToFile(IRDocument textView, string fileFilter, string defaultExtension, Func> saveAction) { string path = Utils.ShowSaveFileDialog(fileFilter, defaultExtension); bool success = false; if (!string.IsNullOrEmpty(path)) { try { success = await saveAction(textView, path); } catch (Exception ex) { Trace.WriteLine($"Failed to save function to {path}: {ex.Message}"); } if (!success) { using var centerForm = new DialogCenteringHelper(textView); MessageBox.Show($"Failed to save list to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } public static async Task ExportSourceToExcelFile(IRDocument textView, Func toOriginalLineMapper, Func fromOriginalLineMapper) { string path = Utils.ShowSaveFileDialog(ExcelFileFilter, ExcelExtension); bool success = false; if (!string.IsNullOrEmpty(path)) { try { success = await ExportSourceAsExcelFile(textView, path, toOriginalLineMapper, fromOriginalLineMapper); } catch (Exception ex) { Trace.WriteLine($"Failed to save function to {path}: {ex.Message}"); } if (!success) { using var centerForm = new DialogCenteringHelper(textView); MessageBox.Show($"Failed to save list to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } public static async Task ExportSourceToHtmlFile(IRDocument textView, Func toOriginalLineMapper, Func fromOriginalLineMapper) { string path = Utils.ShowSaveFileDialog(HtmlFileFilter, HtmlExtension); bool success = false; if (!string.IsNullOrEmpty(path)) { try { success = await ExportSourceAsHtmlFile(textView, path, toOriginalLineMapper, fromOriginalLineMapper); } catch (Exception ex) { Trace.WriteLine($"Failed to save function to {path}: {ex.Message}"); } if (!success) { using var centerForm = new DialogCenteringHelper(textView); MessageBox.Show($"Failed to save list to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } public static async Task ExportSourceToMarkdownFile(IRDocument textView, Func toOriginalLineMapper, Func fromOriginalLineMapper) { string path = Utils.ShowSaveFileDialog(MarkdownFileFilter, MarkdownExtension); bool success = false; if (!string.IsNullOrEmpty(path)) { try { success = await ExportSourceAsMarkdownFile(textView, path, toOriginalLineMapper, fromOriginalLineMapper); } catch (Exception ex) { Trace.WriteLine($"Failed to save function to {path}: {ex.Message}"); } if (!success) { using var centerForm = new DialogCenteringHelper(textView); MessageBox.Show($"Failed to save list to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } public static async Task ExportSourceAsExcelFile(IRDocument textView, string filePath, Func toOriginalLineMapper = null, Func fromOriginalLineMapper = null) { var function = textView.Section.ParentFunction; (int firstSourceLineIndex, int lastSourceLineIndex) = await DocumentUtils.FindFunctionSourceLineRange(function, textView); if (firstSourceLineIndex == 0) { return false; } var wb = new XLWorkbook(); var ws = wb.Worksheets.Add("Source"); var columnData = textView.ProfileColumnData; int rowId = 2; // First row is for the table column names. int maxLineLength = 0; for (int i = firstSourceLineIndex; i <= lastSourceLineIndex; i++) { // Filter out instructions not in line range if requested. int lineNumber = i; if (fromOriginalLineMapper != null) { // Map original source line to the one in the document, // when inline assembly is being displayed. lineNumber = fromOriginalLineMapper(lineNumber); if (lineNumber == -1) { continue; } } var line = textView.Document.GetLineByNumber(lineNumber); string text = textView.Document.GetText(line.Offset, line.Length); ws.Cell(rowId, 1).Value = text; ws.Cell(rowId, 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; maxLineLength = Math.Max(text.Length, maxLineLength); ws.Cell(rowId, 2).Value = lineNumber; ws.Cell(rowId, 2).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; ws.Cell(rowId, 2).Style.Font.FontColor = XLColor.DarkGreen; if (columnData != null) { IRElement tuple = null; tuple = DocumentUtils.FindTupleOnSourceLine(lineNumber, textView); if (tuple != null) { columnData.ExportColumnsToExcel(tuple, ws, rowId, 3); } } rowId++; } // Set the table header column names. var firstCell = ws.Cell(1, 1); var lastCell = ws.LastCellUsed(); var range = ws.Range(firstCell.Address, lastCell.Address); var table = range.CreateTable(); table.Theme = XLTableTheme.None; foreach (var cell in table.HeadersRow().Cells()) { if (cell.Address.ColumnNumber == 1) { cell.Value = "Source"; } else if (cell.Address.ColumnNumber == 2) { cell.Value = "Line"; } else if (columnData != null && cell.Address.ColumnNumber - 3 < columnData.Columns.Count) { cell.Value = columnData.Columns[cell.Address.ColumnNumber - 3].Title; } cell.Style.Font.Bold = true; cell.Style.Fill.BackgroundColor = XLColor.LightGray; } // Adjust the width of the content column. ws.Column(1).AdjustToContents((double)1, maxLineLength); wb.SaveAs(filePath); return true; } public static async Task ExportSourceAsHtmlFile(IRDocument textView, string filePath, Func toOriginalLineMapper, Func fromOriginalLineMapper) { try { Trace.WriteLine("ExportFunctionAsHtmlFile"); var doc = new HtmlDocument(); string TitleStyle = @"text-align:left;font-family:Arial, sans-serif;font-weight:bold;font-size:16px;margin-top:0em"; var p = doc.CreateElement("p"); var function = textView.Section.ParentFunction; string funcName = function.FormatFunctionName(textView.Session); p.InnerHtml = $"Function: {HttpUtility.HtmlEncode(funcName)}"; p.SetAttributeValue("style", TitleStyle); doc.DocumentNode.AppendChild(p); p = doc.CreateElement("p"); p.InnerHtml = $"Module: {HttpUtility.HtmlEncode(function.ModuleName)}"; p.SetAttributeValue("style", TitleStyle); doc.DocumentNode.AppendChild(p); var node = await ExportSourceAsHtml(textView, -1, -1, toOriginalLineMapper, fromOriginalLineMapper); doc.DocumentNode.AppendChild(node); var writer = new StringWriter(); doc.Save(writer); await File.WriteAllTextAsync(filePath, writer.ToString()); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to export to HTML file: {filePath}, {ex.Message}"); return false; } } public static async Task ExportSourceAsHtml(IRDocument textView, int startLine = -1, int endLine = -1, Func toOriginalLineMapper = null, Func fromOriginalLineMapper = null) { string TableStyle = @"border-collapse:collapse;border-spacing:0;"; string HeaderStyle = @"background-color:#D3D3D3;white-space:nowrap;text-align:left;vertical-align:top;border-color:black;border-style:solid;border-width:1px;overflow:hidden;padding:2px 2px;font-size:14px;font-family:Arial, sans-serif;"; string CellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:500px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-size:14px;font-family:Arial, sans-serif;"; string LineNumberStyle = @"color:#006400;text-align:left;vertical-align:top;word-wrap:break-word;max-width:300px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-size:14px;font-family:Arial, sans-serif;"; var function = textView.Section.ParentFunction; (int firstSourceLineIndex, int lastSourceLineIndex) = await DocumentUtils.FindFunctionSourceLineRange(function, textView); var columnData = textView.ProfileColumnData; bool filterByLine = startLine != -1 && endLine != -1; int maxColumn = 2 + (columnData != null ? columnData.Columns.Count : 0); var doc = new HtmlDocument(); var table = doc.CreateElement("table"); table.SetAttributeValue("style", TableStyle); var thead = doc.CreateElement("thead"); var tbody = doc.CreateElement("tbody"); var tr = doc.CreateElement("tr"); var th = doc.CreateElement("th"); th.InnerHtml = "Source"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = "Line"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); if (columnData != null) { foreach (var column in columnData.Columns) { th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode(column.Title); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); } } thead.AppendChild(tr); table.AppendChild(thead); if (filterByLine && !MapStartEndSourceLines(ref startLine, ref endLine, toOriginalLineMapper)) { return doc.DocumentNode; } for (int i = firstSourceLineIndex; i <= lastSourceLineIndex; i++) { // Filter out instructions not in line range if requested. int lineNumber = i; if (filterByLine && (lineNumber < startLine || lineNumber > endLine)) { continue; } if (fromOriginalLineMapper != null) { // Map original source line to the one in the document, // when inline assembly is being displayed. lineNumber = fromOriginalLineMapper(lineNumber); if (lineNumber == -1) { continue; } } var line = textView.Document.GetLineByNumber(lineNumber); string text = textView.Document.GetText(line.Offset, line.Length); var tuple = columnData != null ? DocumentUtils.FindTupleOnSourceLine(lineNumber, textView) : null; tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = PreprocessHtmlIndentation(text); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(lineNumber); td.SetAttributeValue("style", LineNumberStyle); tr.AppendChild(td); if (columnData != null && tuple != null) { columnData.ExportColumnsAsHTML(tuple, doc, tr); } else { // Use empty cells for lines without data. for (int k = 2; k < maxColumn; k++) { td = doc.CreateElement("td"); td.InnerHtml = ""; td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); } } tbody.AppendChild(tr); } table.AppendChild(tbody); doc.DocumentNode.AppendChild(table); return doc.DocumentNode; } private static bool MapStartEndSourceLines(ref int startLine, ref int endLine, Func toOriginalLineMapper) { if (toOriginalLineMapper != null) { // Adjust selection start/end lines when inline assembly // is being displayed by mapping back from the document line // to the original source file line. int firstIndex = toOriginalLineMapper(startLine); while (firstIndex == -1 && startLine < endLine) { firstIndex = toOriginalLineMapper(++startLine); } if (firstIndex == -1) { return false; } int lastIndex = toOriginalLineMapper(endLine); while (lastIndex == -1 && endLine > startLine) { lastIndex = toOriginalLineMapper(--endLine); } if (lastIndex == -1) { return false; } startLine = firstIndex; endLine = lastIndex; } return true; } public static async Task ExportSourceAsMarkdownFile(IRDocument textView, string filePath, Func toOriginalLineMapper = null, Func fromOriginalLineMapper = null) { try { string text = await ExportSourceAsMarkdown(textView, -1, textView.Document.LineCount, toOriginalLineMapper, fromOriginalLineMapper); await File.WriteAllTextAsync(filePath, text); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to export to Markdown file: {filePath}, {ex.Message}"); return false; } } public static async Task ExportSourceAsMarkdown(IRDocument textView, int startLine = -1, int endLine = -1, Func toOriginalLineMapper = null, Func fromOriginalLineMapper = null) { var sb = new StringBuilder(); string header = "| Source | Line |"; string separator = "|--------|------|"; var function = textView.Section.ParentFunction; (int firstSourceLineIndex, int lastSourceLineIndex) = await DocumentUtils.FindFunctionSourceLineRange(function, textView); var columnData = textView.ProfileColumnData; int maxColumn = 2 + (columnData != null ? columnData.Columns.Count : 0); bool filterByLine = startLine != -1 && endLine != -1; if (columnData != null) { foreach (var column in columnData.Columns) { header += $" {column.Title} |"; separator += $"{new string('-', column.Title.Length)}|"; } } sb.AppendLine(header); sb.AppendLine(separator); if (filterByLine && !MapStartEndSourceLines(ref startLine, ref endLine, toOriginalLineMapper)) { return sb.ToString(); } for (int i = firstSourceLineIndex; i <= lastSourceLineIndex; i++) { // Filter out instructions not in line range if requested. int lineNumber = i; if (filterByLine && (lineNumber < startLine || lineNumber > endLine)) { continue; } if (fromOriginalLineMapper != null) { // Map original source line to the one in the document, // when inline assembly is being displayed. lineNumber = fromOriginalLineMapper(lineNumber); if (lineNumber == -1) { continue; } } var line = textView.Document.GetLineByNumber(lineNumber); string text = textView.Document.GetText(line.Offset, line.Length); var tuple = columnData != null ? DocumentUtils.FindTupleOnSourceLine(i, textView) : null; sb.Append($"| {text} | {i} |"); if (columnData != null && tuple != null) { columnData.ExportColumnsAsMarkdown(tuple, sb); } else { for (int k = 2; k < maxColumn; k++) { sb.Append(" |"); } } sb.AppendLine(); } return sb.ToString(); } private static string PreprocessHtmlIndentation(string text) { var sb = new StringBuilder(); for (int i = 0; i < text.Length; i++) { if (text[i] == ' ') { sb.Append(" "); } else if (text[i] == '\t') { sb.Append(" "); } else { sb.Append(text[i]); } } return sb.ToString(); } public static async Task ExportFunctionAsMarkdownFile(IRDocument textView, string filePath) { try { string text = ExportFunctionAsMarkdown(textView); await File.WriteAllTextAsync(filePath, text); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to export to Markdown file: {filePath}, {ex.Message}"); return false; } } public static async Task ExportFunctionAsHtmlFile(IRDocument textView, string filePath) { try { Trace.WriteLine("ExportFunctionAsHtmlFile"); var doc = new HtmlDocument(); string TitleStyle = @"text-align:left;font-family:Arial, sans-serif;font-weight:bold;font-size:16px;margin-top:0em"; var p = doc.CreateElement("p"); string funcName = textView.Section.FormatFunctionName(textView.Session); p.InnerHtml = $"Function: {HttpUtility.HtmlEncode(funcName)}"; p.SetAttributeValue("style", TitleStyle); doc.DocumentNode.AppendChild(p); p = doc.CreateElement("p"); p.InnerHtml = $"Module: {HttpUtility.HtmlEncode(textView.Section.ModuleName)}"; p.SetAttributeValue("style", TitleStyle); doc.DocumentNode.AppendChild(p); doc.DocumentNode.AppendChild(ExportFunctionAsHtml(textView)); var writer = new StringWriter(); doc.Save(writer); await File.WriteAllTextAsync(filePath, writer.ToString()); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to export to HTML file: {filePath}, {ex.Message}"); return false; } } public static async Task CopyAllLinesAsHtml(IRDocument textView) { await CopyLinesAsHtml(textView, 0, textView.Document.LineCount); } public static async Task CopyAllSourceLinesAsHtml(IRDocument textView, Func toOriginalLineMapper, Func fromOriginalLineMapper) { await CopySourceLinesAsHtml(textView, 0, textView.Document.LineCount, toOriginalLineMapper, fromOriginalLineMapper); } public static async Task CopySelectedLinesAsHtml(IRDocument textView) { int startLine = textView.TextArea.Selection.StartPosition.Line - 1; int endLine = textView.TextArea.Selection.EndPosition.Line - 1; // If no line is selected, copy the current line. if (startLine == -1 && endLine == -1) { startLine = endLine = textView.TextArea.Caret.Line - 1; } await CopyLinesAsHtml(textView, startLine, endLine); } private static async Task CopyLinesAsHtml(IRDocument textView, int startLine, int endLine) { if (startLine > endLine) { // Happens when selecting bottom-up. (startLine, endLine) = (endLine, startLine); } var doc = new HtmlDocument(); doc.DocumentNode.AppendChild(ExportFunctionAsHtml(textView, false, startLine, endLine)); var writer = new StringWriter(); doc.Save(writer); // Also save as Markdown so that it can be pasted in plain text editors. //var plainText = ExportFunctionListAsMarkdown(funcList); string plainText = ExportFunctionAsMarkdown(textView, false, startLine, endLine); Utils.CopyHtmlToClipboard(writer.ToString(), plainText); } private static HtmlNode ExportFunctionAsHtml(IRDocument textView, bool includeBlocks = true, int startLine = -1, int endLine = -1) { string TableStyle = @"border-collapse:collapse;border-spacing:0;"; string HeaderStyle = @"background-color:#D3D3D3;white-space:nowrap;text-align:left;vertical-align:top;border-color:black;border-style:solid;border-width:1px;overflow:hidden;padding:2px 2px;font-size:14px;font-family:Arial, sans-serif;"; string CellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:500px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-size:14px;font-family:Arial, sans-serif;"; string BlockStyle = @"color:#00008B;font-weight:bold;text-align:left;vertical-align:top;word-wrap:break-word;max-width:300px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-size:14px;font-family:Arial, sans-serif;"; string LineNumberStyle = @"color:#006400;text-align:left;vertical-align:top;word-wrap:break-word;max-width:300px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-size:14px;font-family:Arial, sans-serif;"; var columnData = textView.ProfileColumnData; bool filterByLine = startLine != -1 && endLine != -1; int maxColumn = 2 + (columnData != null ? columnData.Columns.Count : 0); var doc = new HtmlDocument(); var table = doc.CreateElement("table"); table.SetAttributeValue("style", TableStyle); var thead = doc.CreateElement("thead"); var tbody = doc.CreateElement("tbody"); var tr = doc.CreateElement("tr"); var th = doc.CreateElement("th"); th.InnerHtml = "Instruction"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = "Line"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); if (columnData != null) { foreach (var column in columnData.Columns) { th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode(column.Title); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); } } thead.AppendChild(tr); table.AppendChild(thead); void AddSimpleRow(string text, string style) { tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(text); td.SetAttributeValue("style", style); tr.AppendChild(td); for (int i = 1; i < maxColumn; i++) { td = doc.CreateElement("td"); td.SetAttributeValue("style", BlockStyle); tr.AppendChild(td); } tbody.AppendChild(tr); } foreach (var block in textView.Function.Blocks) { bool addedBlockRow = false; if (includeBlocks && !filterByLine) { AddSimpleRow($"Block {block.Number}", BlockStyle); addedBlockRow = true; } foreach (var tuple in block.Tuples) { // Filter out instructions not in line range if requested. if (filterByLine) { if (tuple.TextLocation.Line < startLine || tuple.TextLocation.Line > endLine) { continue; } if (!addedBlockRow) { AddSimpleRow($"Block {block.Number}", BlockStyle); addedBlockRow = true; if (tuple.IndexInBlock > 0) { AddSimpleRow($"...", CellStyle); } } } var line = textView.Document.GetLineByNumber(tuple.TextLocation.Line + 1); string text = textView.Document.GetText(line.Offset, line.Length); tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(text); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); var sourceTag = tuple.GetTag(); if (sourceTag != null) { td.InnerHtml = HttpUtility.HtmlEncode(sourceTag.Line); } td.SetAttributeValue("style", LineNumberStyle); tr.AppendChild(td); if (columnData != null) { columnData.ExportColumnsAsHTML(tuple, doc, tr); } tbody.AppendChild(tr); } } table.AppendChild(tbody); doc.DocumentNode.AppendChild(table); return doc.DocumentNode; } private static string ExportFunctionAsMarkdown(IRDocument textView, bool includeBlocks = true, int startLine = -1, int endLine = -1) { var sb = new StringBuilder(); string header = "| Instruction | Line |"; string separator = "|-------------|------|"; var columnData = textView.ProfileColumnData; int maxColumn = 2 + (columnData != null ? columnData.Columns.Count : 0); bool filterByLine = startLine != -1 && endLine != -1; if (columnData != null) { foreach (var column in columnData.Columns) { header += $" {column.Title} |"; separator += $"{new string('-', column.Title.Length)}|"; } } sb.AppendLine(header); sb.AppendLine(separator); void AddSimpleRow(string text) { sb.Append($"| {text} |"); for (int i = 1; i < maxColumn; i++) { sb.Append(" |"); } sb.AppendLine(); } foreach (var block in textView.Function.Blocks) { bool addedBlockRow = false; if (includeBlocks && !filterByLine) { AddSimpleRow($"Block {block.Number}"); addedBlockRow = true; } foreach (var tuple in block.Tuples) { // Filter out instructions not in line range if requested. if (filterByLine) { if (tuple.TextLocation.Line < startLine || tuple.TextLocation.Line > endLine) { continue; } if (!addedBlockRow) { AddSimpleRow($"Block {block.Number}"); addedBlockRow = true; if (tuple.IndexInBlock > 0) { AddSimpleRow($"..."); } } } var line = textView.Document.GetLineByNumber(tuple.TextLocation.Line + 1); string text = textView.Document.GetText(line.Offset, line.Length); var sourceTag = tuple.GetTag(); string sourceLine = sourceTag != null ? sourceTag.Line.ToString() : ""; sb.Append($"| {text} | {sourceLine} |"); if (columnData != null) { columnData.ExportColumnsAsMarkdown(tuple, sb); } sb.AppendLine(); } } return sb.ToString(); } public static async Task ExportFunctionAsExcelFile(IRDocument textView, string filePath) { var wb = new XLWorkbook(); var ws = wb.Worksheets.Add("Function"); var columnData = textView.ProfileColumnData; int rowId = 1; // First row is for the table column names. int maxColumn = 2 + (columnData != null ? columnData.Columns.Count : 0); int maxLineLength = 0; foreach (var block in textView.Function.Blocks) { rowId++; ws.Cell(rowId, 1).Value = $"Block {block.Number}"; ws.Cell(rowId, 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; ws.Cell(rowId, 1).Style.Font.Bold = true; ws.Cell(rowId, 1).Style.Font.FontColor = XLColor.DarkBlue; for (int i = 1; i <= maxColumn; i++) { ws.Cell(rowId, i).Style.Border.BottomBorder = XLBorderStyleValues.Thin; } foreach (var tuple in block.Tuples) { rowId++; var line = textView.Document.GetLineByNumber(tuple.TextLocation.Line + 1); string text = textView.Document.GetText(line.Offset, line.Length); ws.Cell(rowId, 1).Value = text; ws.Cell(rowId, 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; maxLineLength = Math.Max(text.Length, maxLineLength); var sourceTag = tuple.GetTag(); if (sourceTag != null) { ws.Cell(rowId, 2).Value = sourceTag.Line; ws.Cell(rowId, 2).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; ws.Cell(rowId, 2).Style.Font.FontColor = XLColor.DarkGreen; } if (columnData != null) { columnData.ExportColumnsToExcel(tuple, ws, rowId, 3); } } } // Set the table header column names. var firstCell = ws.Cell(1, 1); var lastCell = ws.LastCellUsed(); var range = ws.Range(firstCell.Address, lastCell.Address); var table = range.CreateTable(); table.Theme = XLTableTheme.None; foreach (var cell in table.HeadersRow().Cells()) { if (cell.Address.ColumnNumber == 1) { cell.Value = "Instruction"; } else if (cell.Address.ColumnNumber == 2) { cell.Value = "Line"; } else if (columnData != null && cell.Address.ColumnNumber - 3 < columnData.Columns.Count) { cell.Value = columnData.Columns[cell.Address.ColumnNumber - 3].Title; } cell.Style.Font.Bold = true; cell.Style.Fill.BackgroundColor = XLColor.LightGray; } // Adjust the width of the content column. ws.Column(1).AdjustToContents((double)1, maxLineLength); await Task.Run(() => wb.SaveAs(filePath)); return true; } public static async Task CopySelectedSourceLinesAsHtml(IRDocument textView, Func toOriginalLineMapper, Func fromOriginalLineMapper) { int startLine = textView.TextArea.Selection.StartPosition.Line; int endLine = textView.TextArea.Selection.EndPosition.Line; // If no line is selected, copy the current line. if (startLine == 0 && endLine == 0) { startLine = endLine = textView.TextArea.Caret.Line; } await CopySourceLinesAsHtml(textView, startLine, endLine, toOriginalLineMapper, fromOriginalLineMapper); } private static async Task CopySourceLinesAsHtml(IRDocument textView, int startLine, int endLine, Func toOriginalLineMapper, Func fromOriginalLineMapper) { if (startLine > endLine) { // Happens when selecting bottom-up. (startLine, endLine) = (endLine, startLine); } var doc = new HtmlDocument(); doc.DocumentNode.AppendChild(await ExportSourceAsHtml(textView, startLine, endLine, toOriginalLineMapper, fromOriginalLineMapper)); var writer = new StringWriter(); doc.Save(writer); // Also save as Markdown so that it can be pasted in plain text editors. //var plainText = ExportFunctionListAsMarkdown(funcList); string plainText = await ExportSourceAsMarkdown(textView, startLine, endLine, toOriginalLineMapper, fromOriginalLineMapper); Utils.CopyHtmlToClipboard(writer.ToString(), plainText); } } ================================================ FILE: src/ProfileExplorerUI/Document/DocumentUtils.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Globalization; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Profile.Document; using ProfileExplorer.Core.Session; namespace ProfileExplorer.UI.Document; public static class DocumentUtils { public static IRElement FindElement(int offset, List list) { if (list == null) { return null; } //? TODO: Use binary search foreach (var token in list) { if (offset >= token.TextLocation.Offset && offset < token.TextLocation.Offset + token.TextLength) { return token; } } return null; } public static bool FindElement(int offset, List list, out IRElement result) { result = FindElement(offset, list); return result != null; } public static IRElement FindPointedElement(Point position, TextEditor editor, List list) { int offset = GetOffsetFromMousePosition(position, editor, out _); return offset != -1 ? FindElement(offset, list) : null; } public static int GetOffsetFromMousePosition(Point positionRelativeToTextView, TextEditor editor, out int visualColumn) { visualColumn = 0; var textView = editor.TextArea.TextView; var pos = positionRelativeToTextView; if (pos.Y < 0) { pos.Y = 0; } if (pos.Y > textView.ActualHeight) { pos.Y = textView.ActualHeight; } pos += textView.ScrollOffset; if (pos.Y >= textView.DocumentHeight) { pos.Y = textView.DocumentHeight - 0.01; } var line = textView.GetVisualLineFromVisualTop(pos.Y); if (line != null) { visualColumn = line.GetVisualColumn(pos, false); return line.GetRelativeOffset(visualColumn) + line.FirstDocumentLine.Offset; } return -1; } public static FormattedText CreateFormattedText(FrameworkElement element, string text, Typeface typeface, double emSize, Brush foreground, FontWeight? fontWeight = null) { var formattedText = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, emSize, foreground, null, TextOptions.GetTextFormattingMode(element), VisualTreeHelper.GetDpi(element).PixelsPerDip); if (fontWeight.HasValue) { formattedText.SetFontWeight(fontWeight.Value); } return formattedText; } public static IEnumerable FindOverlappingSegments(this TextSegmentCollection list, TextView textView) where T : IRSegment { if (!FindVisibleTextLineAndOffsets(textView, out int viewStart, out int viewEnd, out int viewStartLine, out int viewEndLine)) { yield break; } foreach (var segment in list.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { // Blocks can start on a line that is out of view and the overlay // is meant to be associated with the start line, while GetRectsForSegment // would use the first line still in view, so skip manually over it. if (segment.Element is BlockIR && segment.Element.TextLocation.Line < viewStartLine - 1) { continue; } yield return segment; } } public static bool FindVisibleTextOffsets(TextView textView, out int viewStart, out int viewEnd) { textView.EnsureVisualLines(); var visualLines = textView.VisualLines; if (visualLines.Count == 0) { viewStart = viewEnd = 0; return false; } viewStart = visualLines[0].FirstDocumentLine.Offset; viewEnd = visualLines[^1].LastDocumentLine.EndOffset; return true; } public static bool FindVisibleTextLineAndOffsets(TextView textView, out int viewStart, out int viewEnd, out int viewStartLine, out int viewEndLine) { textView.EnsureVisualLines(); var visualLines = textView.VisualLines; if (visualLines.Count == 0) { viewStart = viewEnd = 0; viewStartLine = viewEndLine = 0; return false; } viewStartLine = visualLines[0].FirstDocumentLine.LineNumber; viewEndLine = visualLines[^1].LastDocumentLine.LineNumber; viewStart = visualLines[0].FirstDocumentLine.Offset; viewEnd = visualLines[^1].LastDocumentLine.EndOffset; return true; } public static ReferenceFinder CreateReferenceFinder(FunctionIR function, ISession session, DocumentSettings settings) { var irInfo = session.CompilerInfo.IR; IReachableReferenceFilter filter = null; if (settings != null) { if (settings.FilterSourceDefinitions || settings.FilterDestinationUses) { filter = irInfo.CreateReferenceFilter(function); if (filter != null) { filter.FilterUses = settings.FilterDestinationUses; filter.FilterDefinitions = settings.FilterSourceDefinitions; } } } return new ReferenceFinder(function, irInfo, filter); } public static List SaveDefaultMenuItems(MenuItem menu) { // Save the menu items that are always present, they are either // separators or menu items without an object tag. var defaultItems = new List(); foreach (object item in menu.Items) { if (item is MenuItem menuItem) { if (menuItem.Tag == null) { defaultItems.Add(item); } } else if (item is Separator) { defaultItems.Add(item); } } return defaultItems; } public static void RestoreDefaultMenuItems(MenuItem menu, List defaultItems) { defaultItems.ForEach(item => menu.Items.Add(item)); } public static void RemoveNonDefaultMenuItems(MenuItem menu) { var items = SaveDefaultMenuItems(menu); menu.Items.Clear(); RestoreDefaultMenuItems(menu, items); } public static string GenerateElementPreviewText(IRElement element, ReadOnlyMemory documentText, int maxLength = 0) { var instr = element.ParentInstruction; string text = ""; if (instr != null) { text = instr.GetText(documentText).ToString(); } else { if (element is OperandIR op) { // This is usually a parameter. text = op.GetText(documentText).ToString(); } else { return ""; } } int start = 0; int length = text.Length; if (instr != null) { // Set range start to cover destination. if (instr.Destinations.Count > 0) { var firstDest = instr.Destinations[0]; start = firstDest.TextLocation.Offset - instr.TextLocation.Offset; start = Math.Min(instr.OpcodeLocation.Offset - instr.TextLocation.Offset, start); // Include opcode. } else { start = instr.OpcodeLocation.Offset - instr.TextLocation.Offset; // Include opcode. } } start = Math.Max(0, start); //? TODO: Workaround for offset not being right // Extend range to cover all sources. if (instr != null && instr.Sources.Count > 0) { var lastSource = instr.Sources.FindLast(s => s.TextLocation.Offset != 0); if (lastSource != null) { length = lastSource.TextLocation.Offset - instr.TextLocation.Offset + lastSource.TextLength; if (length <= 0) { length = text.Length; } length = Math.Min(text.Length, length); //? TODO: Workaround for offset not being right } } // Extract the text in the range. if (start != 0 || length > 0) { int actualLength = Math.Min(length - start, text.Length - start); if (actualLength > 0) { text = text.Substring(start, actualLength); } } text = text.RemoveNewLines(); return maxLength != 0 ? text.TrimToLength(maxLength) : text; } public static IRElement FindTupleOnSourceLine(int line, IRDocument textView) { var pair1 = textView.ProfileProcessingResult.SampledElements. Find(e => e.Item1.TextLocation.Line == line - 1); if (pair1.Item1 != null) { return pair1.Item1; } // Look into performance counters. var pair2 = textView.ProfileProcessingResult.CounterElements. Find(e => e.Item1.TextLocation.Line == line - 1); return pair2.Item1; } public static void CreateBackMenu(MenuItem menu, Stack states, RoutedEventHandler menuClickHandler, TextViewSettingsBase settings, ISession session) { var defaultItems = SaveDefaultMenuItems(menu); var profileItems = new List(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings.ProfileMarkerSettings; var profile = session.ProfileData; double maxWidth = 0; foreach (var state in states) { double weightPercentage = profile.ScaleFunctionWeight(state.Weight); string title = state.Section.ParentFunction.Name.FormatFunctionName(session, 80); string text = $"({markerSettings.FormatWeightValue(state.Weight)})"; var value = new ProfileMenuItem(text, state.Weight.Ticks, weightPercentage) { PrefixText = title, ToolTip = "", ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, IsCheckable = true, StaysOpenOnClick = true, Tag = state, HeaderTemplate = valueTemplate, Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }; item.Click += menuClickHandler; defaultItems.Add(item); profileItems.Add(value); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(title, ref maxWidth, menu); } foreach (var value in profileItems) { value.MinTextWidth = maxWidth; } menu.Items.Clear(); RestoreDefaultMenuItems(menu, defaultItems); } public static async Task<(int, int)> FindFunctionSourceLineRange(IRTextFunction function, IRDocument textView) { int lineCount = textView.Document.LineCount; var session = textView.Session; return await Task.Run(async () => { var debugInfo = await session.GetDebugInfoProvider(function).ConfigureAwait(false); var funcProfile = session.ProfileData?.GetFunctionProfile(function); if (debugInfo == null || funcProfile == null) { return (0, 0); } int firstSourceLineIndex = 0; int lastSourceLineIndex = 0; if (debugInfo.PopulateSourceLines(funcProfile.FunctionDebugInfo)) { firstSourceLineIndex = funcProfile.FunctionDebugInfo.FirstSourceLine.Line; lastSourceLineIndex = funcProfile.FunctionDebugInfo.LastSourceLine.Line; } // Ensure source lines are within document bounds // just in case values are not right. firstSourceLineIndex = Math.Clamp(firstSourceLineIndex, 1, lineCount); lastSourceLineIndex = Math.Clamp(lastSourceLineIndex, 1, lineCount); return (firstSourceLineIndex, lastSourceLineIndex); }); } public static string FormatLongFunctionName(string name) { return FormatLongFunctionName(name, 80, 10, 1000); } public static string FormatLongFunctionName(string name, int maxLineLength, int maxSplitPointAdjustment, int maxLength) { if (name.Length <= maxLineLength) { return name; } // If name is really long cut out from the middle part // to make it fit into the maxLength. if (name.Length > maxLength) { int diff = name.Length - maxLength; int middle = name.Length / 2; name = name.Substring(0, middle - diff / 2) + " ... " + name.Substring(middle + diff / 2, middle - diff / 2); } // Try to split the name each maxLineLength letters. // If the split point happens to be inside a identifier, // look left or right for a template separator like < > : , // to pick as a splitting point since it looks better than // cutting a class/function name. var sb = new StringBuilder(); for (int i = 0; i < name.Length; i++) { int splitPoint = i + Math.Min(maxLineLength, name.Length - i); if (name.Length - splitPoint < maxSplitPointAdjustment) { // Split point is close to the name end, don't split anymore. return sb.ToString().Trim() + name.Substring(i, name.Length - i); } bool foundNew = false; // Look for a separator cahr on the right. for (int k = splitPoint + 1, distance = 0; k < name.Length && distance < maxSplitPointAdjustment; k++, distance++) { if (!char.IsLetterOrDigit(name[k])) { // Found a separator char as a splitting point. splitPoint = k; foundNew = true; break; } } if (!foundNew && splitPoint < name.Length - 1) { // Look for a separator char on the left. for (int k = splitPoint - 1, distance = 0; k > i && distance < maxSplitPointAdjustment; k--, distance++) { if (!char.IsLetterOrDigit(name[k])) { // Found a separator char as a splitting point. splitPoint = k; break; } } } int length = splitPoint - i; sb.AppendLine(name.Substring(i, length)); i += length - 1; } return sb.ToString().Trim(); } public static IRTextSection FindCallTargetSection(IRElement element, IRTextSection section, ISession session) { if (!element.HasName) { return null; } // Function names in the summary are mangled, while the document // has them demangled, run the demangler while searching for the target. var summary = section.ParentFunction.ParentSummary; string searchedName = element.Name; var targetFunc = summary.FindFunction(searchedName); if (targetFunc == null) { var nameProvider = session.CompilerInfo.NameProvider; targetFunc = summary.FindFunction(searchedName, nameProvider.FormatFunctionName); } if (targetFunc == null) { return null; } // Prefer the same section as this document if there are multiple. return targetFunc.SectionCount == 0 ? null : targetFunc.Sections[0]; } } ================================================ FILE: src/ProfileExplorerUI/Document/Highlighting/DefaultHighlightingStyles.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows.Media; namespace ProfileExplorer.UI; public static class DefaultHighlightingStyles { public static HighlightingStyleCollection StyleSet; public static HighlightingStyleCollection LightStyleSet; static DefaultHighlightingStyles() { StyleSet = new HighlightingStyleCollection(); StyleSet.Styles.Add( new HighlightingStyle(Color.FromRgb(254, 202, 165), ColorPens.GetPen(Colors.Gray))); StyleSet.Styles.Add( new HighlightingStyle(Color.FromRgb(232, 254, 165), ColorPens.GetPen(Colors.Gray))); StyleSet.Styles.Add( new HighlightingStyle(Color.FromRgb(173, 254, 165), ColorPens.GetPen(Colors.Gray))); StyleSet.Styles.Add( new HighlightingStyle(Color.FromRgb(165, 180, 254), ColorPens.GetPen(Colors.Gray))); StyleSet.Styles.Add( new HighlightingStyle(Color.FromRgb(254, 165, 187), ColorPens.GetPen(Colors.Gray))); LightStyleSet = new HighlightingStyleCollection(); LightStyleSet.Styles.Add(new HighlightingStyle(Color.FromRgb(253, 231, 216))); LightStyleSet.Styles.Add(new HighlightingStyle(Color.FromRgb(244, 253, 216))); LightStyleSet.Styles.Add(new HighlightingStyle(Color.FromRgb(220, 253, 216))); LightStyleSet.Styles.Add(new HighlightingStyle(Color.FromRgb(216, 223, 253))); LightStyleSet.Styles.Add(new HighlightingStyle(Color.FromRgb(253, 216, 226))); } public static HighlightingStyleCollection GetStyleSetWithBorder( HighlightingStyleCollection baseStyleSet, Pen pen) { var newStyle = new HighlightingStyleCollection(); foreach (var style in baseStyleSet.Styles) { newStyle.Styles.Add(new HighlightingStyle(style.BackColor, pen)); } return newStyle; } } ================================================ FILE: src/ProfileExplorerUI/Document/Highlighting/HighlightedElementGroup.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI; public sealed class HighlightedElementGroup { public HighlightedElementGroup(HighlightingStyle style) { Elements = new List(); Style = style; } public HighlightedElementGroup(IRElement element, HighlightingStyle style) : this(style) { Add(element); } public List Elements { get; set; } public HighlightingStyle Style { get; set; } public bool IsEmpty() { return Elements.Count == 0; } public void Add(IRElement element) { Elements.Add(element); } public void AddRange(IEnumerable elements) { Elements.AddRange(elements); } public void AddFront(IRElement element) { Elements.Insert(0, element); } public bool Contains(IRElement element) { return Elements.Contains(element); } public bool Remove(IRElement element) { return Elements.Remove(element); } } ================================================ FILE: src/ProfileExplorerUI/Document/Highlighting/HighlightingStyle.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows.Media; using ProtoBuf; namespace ProfileExplorer.UI; [ProtoContract] public sealed class HighlightingStyle : IEquatable { public HighlightingStyle() { } public HighlightingStyle(Color color) : this(color, 1.0) { } public HighlightingStyle(Color color, Pen border = null) : this(color, 1.0, border) { } public HighlightingStyle(string color, Pen border = null) : this( Utils.ColorFromString(color), 1.0, border) { } public HighlightingStyle(Color color, double opacity = 1.0, Pen border = null) { BackColor = Math.Abs(opacity - 1.0) < double.Epsilon ? ColorBrushes.GetBrush(color) : ColorBrushes.GetTransparentBrush(color, opacity); Border = border; } public HighlightingStyle(Brush backColor, Pen border = null) { BackColor = backColor; Border = border; } [ProtoMember(1)] public Brush BackColor { get; set; } [ProtoMember(2)] public Pen Border { get; set; } public bool Equals(HighlightingStyle other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Equals(BackColor, other.BackColor) && Equals(Border, other.Border); } public static bool operator ==(HighlightingStyle left, HighlightingStyle right) { return Equals(left, right); } public static bool operator !=(HighlightingStyle left, HighlightingStyle right) { return !Equals(left, right); } public override bool Equals(object obj) { return ReferenceEquals(this, obj) || obj is HighlightingStyle other && Equals(other); } public override int GetHashCode() { return HashCode.Combine(BackColor, Border); } } public sealed class PairHighlightingStyle { public PairHighlightingStyle() { ParentStyle = new HighlightingStyle(); ChildStyle = new HighlightingStyle(); } public HighlightingStyle ParentStyle { get; set; } public HighlightingStyle ChildStyle { get; set; } } public class HighlightingStyleCollection { public HighlightingStyleCollection(List styles = null) { if (styles == null) { Styles = new List(); } else { Styles = styles; } } public List Styles { get; set; } public HighlightingStyle ForIndex(int index) { return Styles[index % Styles.Count]; } } public class HighlightingStyleCyclingCollection : HighlightingStyleCollection { private int counter_; public HighlightingStyleCyclingCollection(List styles = null) : base(styles) { } public HighlightingStyleCyclingCollection(HighlightingStyleCollection styleSet) : base( styleSet.Styles) { } public HighlightingStyle GetNext() { var style = ForIndex(counter_); counter_ = (counter_ + 1) % Styles.Count; return style; } } ================================================ FILE: src/ProfileExplorerUI/Document/Highlighting/IRElementSegment.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI; public enum HighlighingType { Hovered, Selected, Marked } public class IRSegment : TextSegment { public IRSegment(IRElement element) { Element = element; if (element == null) { return; } StartOffset = element.TextLocation.Offset; Length = element.TextLength; } public IRElement Element { get; set; } } public sealed class HighlightedSegmentGroup { public HighlightedSegmentGroup(HighlightedElementGroup group, bool saveToFile = true) { Group = group; Segments = new TextSegmentCollection(); SavesStateToFile = saveToFile; foreach (var element in Group.Elements) { Add(element); } } public HighlightedElementGroup Group { get; set; } public TextSegmentCollection Segments { get; set; } public bool SavesStateToFile { get; set; } public Brush BackColor => Group.Style.BackColor; public Pen Border => Group.Style.Border; private void Add(IRElement element) { Segments.Add(new IRSegment(element)); } } ================================================ FILE: src/ProfileExplorerUI/Document/ILoadedSectionHandler.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Threading.Tasks; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Folding; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI; public interface ILoadedSectionHandler { Task HandleLoadedSection(IRDocument document, FunctionIR function, IRTextSection section); } ================================================ FILE: src/ProfileExplorerUI/Document/IRDocument.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; using System.Windows.Threading; using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Folding; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.Graph; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Query; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.UI; public enum BringIntoViewStyle { Default, FirstLine } public enum HighlightingEventAction { ReplaceHighlighting, AppendHighlighting, RemoveHighlighting } public class IRElementEventArgs : EventArgs { public IRElement Element { get; set; } public bool MirrorAction { get; set; } public IRDocument Document { get; set; } } public class IRHighlightingEventArgs : EventArgs { public HighlightingEventAction Action { get; set; } public IRElement Element { get; set; } public HighlightedElementGroup Group { get; set; } public bool MirrorAction { get; set; } public HighlighingType Type { get; set; } } public class IRElementMarkedEventArgs : EventArgs { public IRElement Element { get; set; } public HighlightingStyle Style { get; set; } } public class SelectedBookmarkInfo { public Bookmark Bookmark { get; set; } public int SelectedIndex { get; set; } public int TotalBookmarks { get; set; } } public static class DocumentCommand { public static readonly RoutedUICommand GoToDefinition = new("Untitled", "GoToDefinition", typeof(IRDocumentHost)); public static readonly RoutedUICommand GoToDefinitionSkipCopies = new("Untitled", "GoToDefinitionSkipCopies", typeof(IRDocumentHost)); public static readonly RoutedUICommand PreviewDefinition = new("Untitled", "PreviewDefinition", typeof(IRDocumentHost)); public static readonly RoutedUICommand MarkDefinition = new("Untitled", "MarkDefinition", typeof(IRDocumentHost)); public static readonly RoutedUICommand MarkDefinitionBlock = new("Untitled", "MarkDefinitionBlock", typeof(IRDocumentHost)); public static readonly RoutedUICommand Mark = new("Untitled", "Mark", typeof(IRDocumentHost)); public static readonly RoutedUICommand MarkIcon = new("Untitled", "MarkIcon", typeof(IRDocumentHost)); public static readonly RoutedUICommand ShowUses = new("Untitled", "ShowUses", typeof(IRDocumentHost)); public static readonly RoutedUICommand MarkUses = new("Untitled", "MarkUses", typeof(IRDocumentHost)); public static readonly RoutedUICommand MarkBlock = new("Untitled", "MarkBlock", typeof(IRDocumentHost)); public static readonly RoutedUICommand MarkReferences = new("Untitled", "MarkReferences", typeof(IRDocumentHost)); public static readonly RoutedUICommand ShowExpressionGraph = new("Untitled", "ShowExpressionGraph", typeof(IRDocumentHost)); public static readonly RoutedUICommand NextBlock = new("Untitled", "NextBlock", typeof(IRDocumentHost)); public static readonly RoutedUICommand PreviousBlock = new("Untitled", "PreviousBlock", typeof(IRDocumentHost)); public static readonly RoutedUICommand ShowReferences = new("Untitled", "ShowReferences", typeof(IRDocumentHost)); public static readonly RoutedUICommand AddBookmark = new("Untitled", "AddBookmark", typeof(IRDocumentHost)); public static readonly RoutedUICommand RemoveBookmark = new("Untitled", "RemoveBookmark", typeof(IRDocumentHost)); public static readonly RoutedUICommand RemoveAllBookmarks = new("Untitled", "RemoveAllBookmarks", typeof(IRDocumentHost)); public static readonly RoutedUICommand PreviousBookmark = new("Untitled", "PreviousBookmark", typeof(IRDocumentHost)); public static readonly RoutedUICommand NextBookmark = new("Untitled", "NextBookmark", typeof(IRDocumentHost)); public static readonly RoutedUICommand ShowBookmarks = new("Untitled", "ShowBookmarks", typeof(IRDocumentHost)); public static readonly RoutedUICommand FirstBookmark = new("Untitled", "FirstBookmark", typeof(IRDocumentHost)); public static readonly RoutedUICommand LastBookmark = new("Untitled", "LastBookmark", typeof(IRDocumentHost)); public static readonly RoutedUICommand FocusBlockSelector = new("Untitled", "FocusBlockSelector", typeof(IRDocumentHost)); public static readonly RoutedUICommand ClearMarker = new("Untitled", "ClearMarker", typeof(IRDocumentHost)); public static readonly RoutedUICommand ClearBlockMarkers = new("Untitled", "ClearBlockMarkers", typeof(IRDocumentHost)); public static readonly RoutedUICommand ClearInstructionMarkers = new("Untitled", "ClearInstructionMarkers", typeof(IRDocumentHost)); public static readonly RoutedUICommand ClearAllMarkers = new("Untitled", "ClearAllMarkers", typeof(IRDocumentHost)); public static readonly RoutedUICommand UndoAction = new("Untitled", "UndoAction", typeof(IRDocumentHost)); } public sealed class IRDocument : TextEditor, INotifyPropertyChanged { private const float ParentStyleLightAdjustment = 1.20f; private const int DefaultMaxExpressionLevel = 4; private const int ExpressionLevelIncrement = 2; private static DocumentActionKind[] AutomationActions = { DocumentActionKind.SelectElement, DocumentActionKind.MarkElement, DocumentActionKind.ShowReferences, DocumentActionKind.GoToDefinition }; private Stack actionUndoStack_; private List blockElements_; private BlockBackgroundHighlighter blockHighlighter_; private BookmarkManager bookmarks_; private BlockIR currentBlock_; private HighlightedElementGroup currentSearchResultGroup_; private PairHighlightingStyle definitionStyle_; private DiffLineHighlighter diffHighlighter_; private List diffSegments_; private bool disableCaretEvent_; public bool disableOverlayEvents_; private ScrollBar docVerticalScrollBar_; private bool duringDiffModeSetup_; private bool eventSetupDone_; private HighlightingStyleCollection expressionOperandStyle_; private HighlightingStyleCollection expressionStyle_; private FoldingManager folding_; private MarkerMarginVersionInfo highlighterVersion_; private MarkerBarElement hoveredBarElement_; private IRElement hoveredElement_; private ElementHighlighter hoverHighlighter_; private bool ignoreNextBarHover_; private bool ignoreNextCaretEvent_; private bool ignoreNextHoverEvent_; private IRElement ignoreNextPreviewElement_; private bool ignoreNextScrollEvent_; private CurrentLineHighlighter lineHighlighter_; private DocumentMargin margin_; private ElementHighlighter markedHighlighter_; private OverlayRenderer overlayRenderer_; private bool overlayRendererConnectedTemporarely_; private HighlightingStyleCyclingCollection markerChildStyle_; private Canvas markerMargin_; private List markerMargingElements_; private HighlightingStyleCyclingCollection markerParentStyle_; private IRDocumentPopup previewPopup_; private bool preparingPreviewPopup_; private List operandElements_; private RemarkHighlighter remarkHighlighter_; private DelayedAction removeHoveredAction_; private Dictionary searchResultMap_; private HighlightedElementGroup searchResultsGroup_; private HighlightingStyle selectedBlockStyle_; private HashSet selectedElements_; private ElementHighlighter selectedHighlighter_; private HighlightingStyle selectedStyle_; private TextViewSettingsBase settings_; private PairHighlightingStyle ssaDefinitionStyle_; private PairHighlightingStyle ssaUserStyle_; private PairHighlightingStyle iteratedUserStyle_; private PairHighlightingStyle iteratedDefinitionStyle_; private List tupleElements_; private bool updateSuspended_; private IRElement currentExprElement_; private int currentExprStyleIndex_; private int currentExprLevel_; private Remark selectedRemark_; private bool selectingText_; private HashSet foldedBlocks_; private bool hasCustomLineNumbers_; private List registerdTransformers_; private List registeredHoverPreviews_; private CancelableTaskInstance markerBarUpdateTask_; private ReaderWriterLockSlim markerBarUpdateLock_; public IRDocument() { // Setup element tracking data structures. selectedElements_ = new HashSet(); bookmarks_ = new BookmarkManager(); actionUndoStack_ = new Stack(); highlighterVersion_ = new MarkerMarginVersionInfo(); // Setup styles and colors. //? TODO: Expose colors as option definitionStyle_ = new PairHighlightingStyle { ParentStyle = new HighlightingStyle(Color.FromRgb(255, 215, 191)), ChildStyle = new HighlightingStyle(Color.FromRgb(255, 197, 163), ColorPens.GetBoldPen(Colors.Black)) }; expressionOperandStyle_ = DefaultHighlightingStyles.StyleSet; expressionStyle_ = DefaultHighlightingStyles.LightStyleSet; markerChildStyle_ = new HighlightingStyleCyclingCollection(DefaultHighlightingStyles.StyleSet); markerParentStyle_ = new HighlightingStyleCyclingCollection(DefaultHighlightingStyles.LightStyleSet); registerdTransformers_ = new List(); registeredHoverPreviews_ = new List(); markerBarUpdateTask_ = new CancelableTaskInstance(true); markerBarUpdateLock_ = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); SetupProperties(); SetupStableRenderers(); SetupCommands(); } public List Blocks => Function.Blocks; public BookmarkManager BookmarkManager => bookmarks_; public IUISession Session { get; private set; } public FunctionIR Function { get; set; } public IRTextSection Section { get; set; } public ReadOnlyMemory SectionText { get; set; } public bool DiffModeEnabled { get; set; } public bool IsLoaded { get; set; } public bool DuringSectionLoading { get; set; } public TextViewSettingsBase Settings { get => settings_; private set { settings_ = value; ReloadSettings(); } } public IRDocumentColumnData ProfileColumnData { get; set; } public FunctionProcessingResult ProfileProcessingResult { get; set; } public double DefaultLineHeight => TextArea.TextView.DefaultLineHeight; public IEnumerable BlockFoldings => folding_?.AllFoldings; public event PropertyChangedEventHandler PropertyChanged; public event EventHandler ActionPerformed; public event EventHandler BlockSelected; public event EventHandler BookmarkAdded; public event EventHandler BookmarkChanged; public event EventHandler BookmarkListCleared; public event EventHandler BookmarkRemoved; public event EventHandler BookmarkSelected; public event EventHandler ElementHighlighting; public event EventHandler ElementSelected; public event EventHandler ElementUnselected; public event EventHandler CaretChanged; public event EventHandler TextRegionFolded; public event EventHandler TextRegionUnfolded; public event EventHandler FunctionCallOpen; private static int AdjustVisibleLine(int line) { // Leave a few lines be visible above. if (line > 2) { line -= 2; } return line; } public void Initialize(TextViewSettingsBase settings, IUISession session) { Session = session; Settings = settings; } public void BookmarkInfoChanged(Bookmark bookmark) { UpdateHighlighting(); } public void DisableOverlayEventHandlers() { disableOverlayEvents_ = true; overlayRenderer_.MouseLeave(); } public void EnableOverlayEventHandlers() { disableOverlayEvents_ = false; } public void ExecuteDocumentAction(DocumentAction action) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Execute {action}"); #endif switch (action.ActionKind) { case DocumentActionKind.SelectElement: { if (action.Element != null) { SelectElement(action.Element); } break; } case DocumentActionKind.MarkElement: { if (action.Element != null) { MarkElement(action.Element, action.OptionalData as PairHighlightingStyle); } break; } case DocumentActionKind.MarkExpression: { if (action.Element != null) { var highlighter = action.OptionalData is MarkActionData data && data.IsTemporary ? selectedHighlighter_ : markedHighlighter_; if (action.Element is InstructionIR instr) { if (instr.Destinations.Count > 0) { HandleElement(instr.Destinations[0], highlighter, true, false); } } else { HandleElement(action.Element, highlighter, true, false); } } break; } case DocumentActionKind.ShowExpressionGraph: { if (action.Element != null) { ShowExpressionGraph(action.Element); } break; } case DocumentActionKind.MarkBlock: { if (action.Element != null) { MarkBlock(action.Element, action.OptionalData as HighlightingStyle); } break; } case DocumentActionKind.GoToDefinition: { if (action.Element != null) { GoToElementDefinition(action.Element); } break; } case DocumentActionKind.ShowReferences: { if (action.Element is OperandIR op) { ShowReferences(op); } else if (action.Element is InstructionIR instr) { // For an instruction, look for the references of the dest. operand. if (instr.Destinations.Count > 0) { ShowReferences(instr.Destinations[0]); } } break; } case DocumentActionKind.MarkReferences: { if (action.Element is OperandIR op) { MarkReferences(op, markedHighlighter_); } else if (action.Element is InstructionIR instr) { // For an instruction, look for the references of the dest. operand. if (instr.Destinations.Count > 0) { MarkReferences(instr.Destinations[0], markedHighlighter_); } } break; } case DocumentActionKind.ShowUses: { if (action.Element is OperandIR op) { ShowUses(op); } else if (action.Element is InstructionIR instr) { // For an instruction, look for the uses of the dest. operand. if (instr.Destinations.Count > 0) { ShowUses(instr.Destinations[0]); } } break; } case DocumentActionKind.MarkUses: { if (action.Element is OperandIR op) { MarkUses(op, action.OptionalData as PairHighlightingStyle); } else if (action.Element is InstructionIR instr) { // For an instruction, look for the uses of the dest. operand. if (instr.Destinations.Count > 0) { MarkUses(instr.Destinations[0], action.OptionalData as PairHighlightingStyle); } } break; } case DocumentActionKind.ClearMarker: { if (action.Element != null) { ClearMarkedElement(action.Element); } break; } case DocumentActionKind.ClearAllMarkers: { ClearAllMarkers(); break; } case DocumentActionKind.ClearBlockMarkers: { ClearBlockMarkers(); break; } case DocumentActionKind.ClearInstructionMarkers: { ClearInstructionMarkers(); break; } case DocumentActionKind.ClearTemporaryMarkers: { ClearTemporaryHighlighting(); UpdateHighlighting(); break; } case DocumentActionKind.UndoAction: { UndoReversibleAction(); break; } } UpdateHighlighting(); UpdateMargin(); } public void BringTextOffsetIntoView(int offset) { ignoreNextHoverEvent_ = true; ignoreNextCaretEvent_ = true; int line = Document.GetLineByOffset(offset).LineNumber; ScrollToLine(AdjustVisibleLine(line)); } public void BringElementIntoView(IRElement op, BringIntoViewStyle style = BringIntoViewStyle.Default) { if (op.TextLocation.Offset < 0 || op.TextLocation.Offset >= Document.TextLength) { return; } ignoreNextHoverEvent_ = true; ignoreNextCaretEvent_ = true; int line = Document.GetLineByOffset(op.TextLocation.Offset).LineNumber; if (style == BringIntoViewStyle.Default) { if (!IsElementOutsideView(op)) { UpdateHighlighting(); return; } ScrollToLine(AdjustVisibleLine(line)); } else if (style == BringIntoViewStyle.FirstLine) { double y = TextArea.TextView.GetVisualTopByDocumentLine(line); ScrollToVerticalOffset(y); } UpdateHighlighting(); } public void ClearMarkedElement(IRElement element) { markedHighlighter_.Remove(element); ClearTemporaryHighlighting(); UpdateHighlighting(); RaiseElementRemoveHighlightingEvent(element); } public void ClearMarkedElementAt(Point point) { var element = FindPointedElement(point, out _); if (element != null) { ClearMarkedElement(element); } } public void ClearMarkedElementAt(int offset) { var element = FindElementAtOffset(offset); if (element != null) { ClearMarkedElement(element); } } public void GoToBlock(BlockIR block) { SelectElement(block); BringElementIntoView(block); currentBlock_ = block; } public BlockIR GoToNextBlock() { int index = Function.Blocks.IndexOf(currentBlock_); if (index + 1 < Function.Blocks.Count) { GoToBlock(Function.Blocks[index + 1]); } return currentBlock_; } public BlockIR GoToPredecessorBlock() { return currentBlock_; } public BlockIR GoToPreviousBlock() { int index = Function.Blocks.IndexOf(currentBlock_); if (index == -1) { return currentBlock_; } if (index > 0 && Function.Blocks.Count > 0) { GoToBlock(Function.Blocks[index - 1]); } return currentBlock_; } public void HighlightElement(IRElement element, HighlighingType type) { HighlightSingleElement(element, GetHighlighter(type)); } public void SelectElementsOnSourceLine(int lineNumber, SourceStackFrame inlinee = null) { ClearTemporaryHighlighting(); MarkElementsOnSourceLine(selectedHighlighter_, lineNumber, Colors.Transparent, false, true, inlinee); } public void SelectElementsInLineRange(int startLine, int endLine, Func lineMapper = null, Brush backColor = null) { ClearTemporaryHighlighting(); var style = selectedStyle_; if (backColor != null) { style = new HighlightingStyle(backColor, selectedStyle_.Border); } var group = new HighlightedElementGroup(style); if (lineMapper != null) { startLine = lineMapper(startLine); endLine = lineMapper(endLine); } foreach (var block in Function.Blocks) { foreach (var tuple in block.Tuples) { if (tuple.TextLocation.Line + 1 >= startLine && tuple.TextLocation.Line + 1 <= endLine) { group.Add(tuple); } } } if (!group.IsEmpty()) { selectedHighlighter_.Add(group); } UpdateHighlighting(); } public void SelectLine(int line) { if (line >= 0 && line <= Document.LineCount) { TextArea.Caret.Line = line; ScrollToLine(line); } } public void MarkElementsOnSourceLine(int lineNumber, Color selectedColor, bool raiseEvent = true) { MarkElementsOnSourceLine(markedHighlighter_, lineNumber, selectedColor, raiseEvent, false, null); } public void MarkElementWithDefaultStyle(IRElement element) { HighlightSingleElement(element, markedHighlighter_); } public void UnloadDocument() { UnregisterTextTransformers(); UnregisterHoverPreviews(); ResetRenderers(); IsLoaded = false; Text = ""; SectionText = ReadOnlyMemory.Empty; ProfileColumnData = null; Section = null; Function = null; selectedRemark_ = null; currentExprElement_ = null; foldedBlocks_ = null; ClearSelectedElements(); } public async Task InitializeFromDocument(IRDocument doc, bool copyTemporaryHighlighting = true, string text = null, bool analyzeFunction = true) { if (Section == doc.Section) { return false; } UnloadDocument(); Session = doc.Session; Settings = doc.Settings; Section = doc.Section; Function = doc.Function; blockElements_ = doc.blockElements_; tupleElements_ = doc.tupleElements_; operandElements_ = doc.operandElements_; if (copyTemporaryHighlighting) { hoverHighlighter_.CopyFrom(doc.hoverHighlighter_); selectedHighlighter_.CopyFrom(doc.selectedHighlighter_); } markedHighlighter_.CopyFrom(doc.markedHighlighter_); bookmarks_.CopyFrom(doc.bookmarks_); margin_.CopyFrom(doc.margin_); ignoreNextCaretEvent_ = true; if (text != null) { Text = text; SectionText = text.AsMemory(); } else { Text = doc.SectionText.ToString(); SectionText = doc.SectionText; } SetupBlockFolding(); if (analyzeFunction) { await Session.LoadedSectionHandler.HandleLoadedSection(this, Function, Section); } return true; } public bool JumpToBookmark(Bookmark bookmark) { if (bookmark != null) { margin_.SelectBookmark(bookmark); BringElementIntoView(bookmark.Element); RaiseBookmarkSelectedEvent(bookmark); return true; } return false; } public async Task LoadSavedSection(ParsedIRTextSection parsedSection, IRDocumentState savedState) { #if DEBUG Trace.TraceInformation( $"Document {ObjectTracker.Track(this)}: Load saved section {parsedSection}"); #endif selectedElements_ = savedState.SelectedElements?.ToHashSet(item => (IRElement)item) ?? new HashSet(); bookmarks_.LoadState(savedState.Bookmarks, Function); hoverHighlighter_.LoadState(savedState.HoverHighlighter, Function); selectedHighlighter_.LoadState(savedState.SelectedHighlighter, Function); markedHighlighter_.LoadState(savedState.MarkedHighlighter, Function); overlayRenderer_.LoadState(savedState.ElementOverlays, Function, SetupElementOverlayEvents); margin_.LoadState(savedState.Margin); bookmarks_.Bookmarks.ForEach(item => RaiseBookmarkAddedEvent(item)); SetCaretAtOffset(savedState.CaretOffset); await ComputeElementListsAsync(); await LateLoadSectionSetup(parsedSection); } public async Task LoadSection(ParsedIRTextSection parsedSection, bool isSourceCode = false) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Load section {parsedSection}"); #endif // If the section loading is not done in two stages, // run the first stage now to initialize the text view. if (!DuringSectionLoading) { PreloadSection(parsedSection); } await ComputeElementListsAsync(); await LateLoadSectionSetup(parsedSection, isSourceCode); } public void MarkBlock(IRElement element, HighlightingStyle style, bool raiseEvent = true) { var group = new HighlightedElementGroup(element, style); margin_.AddBlock(group, raiseEvent); if (raiseEvent) { RecordReversibleAction(DocumentActionKind.MarkElement, element); } ClearTemporaryHighlighting(); UpdateMargin(); UpdateHighlighting(); if (raiseEvent) { RaiseElementHighlightingEvent(element, group, markedHighlighter_.Type, HighlightingEventAction.ReplaceHighlighting); } } public void MarkElement(IRElement element, Color selectedColor, bool raiseEvent = true) { var style = new HighlightingStyle(selectedColor, null); MarkElement(element, style, raiseEvent); } public void MarkElements(IEnumerable elements, Color selectedColor) { var style = new HighlightingStyle(selectedColor, null); var group = new HighlightedElementGroup(style); group.AddRange(elements); ClearTemporaryHighlighting(); markedHighlighter_.Add(group); UpdateHighlighting(); } public void SelectElements(IEnumerable elements) { var group = new HighlightedElementGroup(selectedStyle_); group.AddRange(elements); ClearTemporaryHighlighting(); selectedHighlighter_.Add(group); UpdateHighlighting(); } public void MarkElement(IRElement element, HighlightingStyle style, bool raiseEvent = true) { if (raiseEvent) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Mark element {element.Id}"); #endif RecordReversibleAction(DocumentActionKind.MarkElement, element); } ClearTemporaryHighlighting(); var group = new HighlightedElementGroup(element, style); markedHighlighter_.Remove(element); markedHighlighter_.Add(group); UpdateHighlighting(); if (raiseEvent) { RaiseElementHighlightingEvent(element, group, markedHighlighter_.Type, HighlightingEventAction.AppendHighlighting); } } public void BeginMarkElementAppend(HighlighingType highlightingType) { if (highlightingType == HighlighingType.Hovered || highlightingType == HighlighingType.Selected) { ClearTemporaryHighlighting(); } } public void EndMarkElementAppend(HighlighingType highlightingType) { UpdateHighlighting(); } public void MarkElementAppend(IRElement element, Color selectedColor, HighlighingType highlightingType, bool raiseEvent = true) { var style = new HighlightingStyle(selectedColor, null); MarkElementAppend(element, style, highlightingType, raiseEvent); } public void MarkElementAppend(IRElement element, HighlightingStyle style, HighlighingType highlightingType, bool raiseEvent = true) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Mark element {element.Id}"); #endif var highlighter = GetHighlighter(highlightingType); var group = new HighlightedElementGroup(element, style); highlighter.Remove(element); highlighter.Add(group); if (raiseEvent) { RaiseElementHighlightingEvent(element, group, highlightingType, HighlightingEventAction.AppendHighlighting); } } public void SetRootConnectedElement(IRElement element, HighlightingStyle style, bool isTemporary) { overlayRenderer_.SetRootElement(element, style); overlayRendererConnectedTemporarely_ = isTemporary; } public void AddConnectedElement(IRElement element, HighlightingStyle style) { overlayRenderer_.AddConnectedElement(element, style); } public void ClearConnectedElements() { overlayRenderer_.ClearConnectedElements(); } public void MarkElementAt(Point point, Color selectedColor) { var element = FindPointedElement(point, out _); if (element != null) { MarkElement(element, selectedColor); } } public void MarkElementAt(int offset, Color selectedColor) { var element = FindElementAtOffset(offset); if (element != null) { MarkElement(element, selectedColor); } } public void MarkTextRange(int offset, int length, Color color) { var style = new HighlightingStyle(color, ColorPens.GetPen(Colors.DarkGray)); var element = CreateDummyElement(offset, length); var group = new HighlightedElementGroup(element, style); markedHighlighter_.Add(group); UpdateHighlighting(); } public void MarkSearchResults(List results, Color color) { ClearSearchResults(); if (results.Count == 0) { return; } var style = new HighlightingStyle(color, ColorPens.GetPen(Colors.DarkGray)); searchResultMap_ = new Dictionary(results.Count); searchResultsGroup_ = new HighlightedElementGroup(style); foreach (var result in results) { var element = CreateDummyElement(result.Offset, result.Length); searchResultsGroup_.Add(element); searchResultMap_[result] = element; } markedHighlighter_.Add(searchResultsGroup_, false); ClearTemporaryHighlighting(); UpdateHighlighting(); } public void ClearSearchResults() { if (searchResultsGroup_ != null) { markedHighlighter_.Remove(searchResultsGroup_); searchResultsGroup_ = null; if (currentSearchResultGroup_ != null) { markedHighlighter_.Remove(currentSearchResultGroup_); currentSearchResultGroup_ = null; } } UpdateHighlighting(); } public void JumpToSearchResult(TextSearchResult result, Color color) { if (currentSearchResultGroup_ != null) { markedHighlighter_.Remove(currentSearchResultGroup_); searchResultsGroup_.Add(currentSearchResultGroup_.Elements[0]); } var style = new HighlightingStyle(color, ColorPens.GetPen(Colors.Black)); currentSearchResultGroup_ = new HighlightedElementGroup(style); var element = searchResultMap_[result]; searchResultsGroup_.Remove(element); currentSearchResultGroup_.Add(element); markedHighlighter_.Add(currentSearchResultGroup_, false); BringElementIntoView(element); ClearTemporaryHighlighting(); UpdateHighlighting(); } public void RemoveAllBookmarks() { bookmarks_.Clear(); margin_.ClearBookmarks(); UpdateMargin(); UpdateHighlighting(); RaiseBookmarkListClearedEvent(); } public void RemoveBookmark(Bookmark bookmark) { bookmarks_.RemoveBookmark(bookmark); margin_.RemoveBookmark(bookmark); UpdateMargin(); UpdateHighlighting(); RaiseBookmarkRemovedEvent(bookmark); } public IRDocumentState SaveState() { var savedState = new IRDocumentState(); savedState.SelectedElements = selectedElements_.ToList(item => new IRElementReference(item)); savedState.Bookmarks = bookmarks_.SaveState(Function); savedState.HoverHighlighter = hoverHighlighter_.SaveState(Function); savedState.SelectedHighlighter = selectedHighlighter_.SaveState(Function); savedState.MarkedHighlighter = markedHighlighter_.SaveState(Function); savedState.ElementOverlays = overlayRenderer_.SaveState(Function); savedState.Margin = margin_.SaveState(); savedState.CaretOffset = TextArea.Caret.Offset; return savedState; } public void SelectElement(IRElement element, bool raiseEvent = true, bool fromUICommand = false, int textOffset = -1) { if (settings_ is not DocumentSettings) { // For source code documents. return; } // During a text selection, don't select more // than the first clicked element. if (selectingText_) { return; } ClearTemporaryHighlighting(); ResetExpressionLevel(element); if (element != null) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Select element {element.Id}"); #endif // Don't highlight a block unless the header is selected. if (element is BlockIR && fromUICommand && textOffset != -1) { int line = Document.GetLineByOffset(textOffset).LineNumber; int blockStartLine = element.TextLocation.Line; if (line - 1 != blockStartLine) { HandelNoElementSelection(); return; } } bool markExpression = fromUICommand && Utils.IsControlModifierActive(); bool markReferences = fromUICommand && Utils.IsShiftModifierActive(); AddSelectedElement(element, raiseEvent); var highlighter = Utils.IsAltModifierActive() ? markedHighlighter_ : selectedHighlighter_; HandleElement(element, highlighter, markExpression, markReferences); UpdateHighlighting(); if (fromUICommand) { ignoreNextCaretEvent_ = true; MirrorAction(DocumentActionKind.SelectElement, element); } } else if (raiseEvent) { // Notify of no element being selected. HandelNoElementSelection(); } } public void UnselectElements() { ClearSelectedElements(); UpdateHighlighting(); ResetExpressionLevel(); } public void SelectElementAt(Point point) { var element = FindPointedElement(point, out _); if (element != null) { SelectElement(element); } } public void UnmarkBlock(IRElement element, HighlighingType type) { margin_.RemoveBlock(element); UpdateMargin(); } public void PanelContentLoaded(IToolPanel panel) { if (panel.PanelKind == ToolPanelKind.FlowGraph || panel.PanelKind == ToolPanelKind.DominatorTree || panel.PanelKind == ToolPanelKind.PostDominatorTree) { // Mark the nodes in the graph panel. foreach (var blockGroup in margin_.BlockGroups) { if (!blockGroup.SavesStateToFile) { continue; } foreach (var element in blockGroup.Group.Elements) { RaiseElementHighlightingEvent(element, blockGroup.Group, markedHighlighter_.Type, HighlightingEventAction.ReplaceHighlighting); } } } } public Bookmark AddBookmark(IRElement selectedElement, string text = null, bool pinned = false) { var bookmark = bookmarks_.AddBookmark(selectedElement); bookmark.Text = text; bookmark.IsPinned = pinned; margin_.AddBookmark(bookmark); margin_.SelectBookmark(bookmark); UpdateMargin(); UpdateHighlighting(); RaiseBookmarkAddedEvent(bookmark); return bookmark; } public void PreloadSection(ParsedIRTextSection parsedSection) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Start setup for {parsedSection}"); #endif DuringSectionLoading = true; Section = parsedSection.Section; Function = parsedSection.Function; ignoreNextCaretEvent_ = true; ClearSelectedElements(); ResetRenderers(); // Replace the text in the view. Text = parsedSection.Text.ToString(); SectionText = parsedSection.Text; // Cache raw text. SetCaretAtOffset(0); } public IRElement GetElementAt(Point position) { int offset = DocumentUtils.GetOffsetFromMousePosition(position, this, out _); return offset != -1 ? FindElementAtOffset(offset) : null; } public async Task LoadDiffedFunction(DiffMarkingResult diffResult, IRTextSection newSection) { StartDiffSegmentAdding(); Function = diffResult.DiffFunction; Section = newSection; SectionText = diffResult.DiffText.AsMemory(); // Compute the element lists before removing the block folding. // If done after, the UI may update during the async call // and it would be noticeable how the block folding disappears, then immediately // reappears once LateLoadSectionSetup reinstalls the block folding. await ComputeElementListsAsync(); // Take ownership of the text document. diffResult.DiffDocument.SetOwnerThread(Thread.CurrentThread); Document = diffResult.DiffDocument; // Remove the current block folding since it's bound to the current text area. UninstallBlockFolding(); ClearTemporaryHighlighting(); await LateLoadSectionSetup(null); AddDiffTextSegments(diffResult.DiffSegments); AllDiffSegmentsAdded(); } public void SetCaretAtElement(IRElement element) { SetCaretAtOffset(element.TextLocation.Offset); } public void SetCaretAtOffset(int offset) { if (offset < Document.TextLength) { ignoreNextCaretEvent_ = true; TextArea.Caret.Offset = offset; BringTextOffsetIntoView(offset); } } public void UninstallBlockFolding() { if (folding_ != null) { FoldingManager.Uninstall(folding_); folding_ = null; } } private void SetupBlockFolding() { if (settings_ is not DocumentSettings docSettings) { return; } if (!docSettings.ShowBlockFolding) { UninstallBlockFolding(); return; } if (Function == null) { return; // Function couldn't be parsed. } UninstallBlockFolding(); folding_ = FoldingManager.Install(TextArea); var foldingStrategy = Session.BlockFoldingStrategyProvider.CreateFoldingStrategy(Function); foldingStrategy.UpdateFoldings(folding_, Document); SetupBlockFoldingEvents(folding_.AllFoldings); } public IEnumerable SetupCustomBlockFolding(IBlockFoldingStrategy foldingStrategy) { UninstallBlockFolding(); folding_ = FoldingManager.Install(TextArea); foldingStrategy.UpdateFoldings(folding_, Document); SetupBlockFoldingEvents(folding_.AllFoldings); return folding_.AllFoldings; } private void SetupBlockFoldingEvents(IEnumerable foldings) { var foldingMargin = TextArea.LeftMargins.OfType().FirstOrDefault(); if (foldingMargin == null) { return; } // Set initial folded state. foldedBlocks_ = new HashSet(); foreach (var folding in foldings) { if (folding.IsFolded) { foldedBlocks_.Add(folding); } } void DetectFoldingChanges() { // Check each folding if there is a change, since there is // no event for a single folding being changed. foreach (var folding in folding_.AllFoldings) { if (folding.IsFolded) { if (foldedBlocks_.Add(folding)) { TextRegionFolded?.Invoke(this, folding); } } else { if (foldedBlocks_.Remove(folding)) { TextRegionUnfolded?.Invoke(this, folding); } } } } foldingMargin.PreviewMouseLeftButtonUp += (sender, args) => DetectFoldingChanges(); foldingMargin.PreviewTouchUp += (sender, args) => DetectFoldingChanges(); } public void SetupCustomLineNumbers(LineNumberMargin lineNumbers) { // Disable builtin line numbers margin and replace it with a custom one, // plus a dotted line between it and the document itself. ShowLineNumbers = false; UninstallCustomLineNumbers(false); var leftMargins = TextArea.LeftMargins; var line = (Line)DottedLineMargin.Create(); leftMargins.Insert(0, lineNumbers); leftMargins.Insert(1, line); var lineNumbersForeground = new Binding("LineNumbersForeground") {Source = this}; line.SetBinding(Shape.StrokeProperty, lineNumbersForeground); lineNumbers.SetBinding(ForegroundProperty, lineNumbersForeground); hasCustomLineNumbers_ = true; } public void UninstallCustomLineNumbers(bool restoreBuiltin) { if (hasCustomLineNumbers_) { var leftMargins = TextArea.LeftMargins; for (int i = 0; i < leftMargins.Count; i++) { if (leftMargins[i] is LineNumberMargin || leftMargins[i] is Line) { leftMargins.RemoveAt(i); i--; } } hasCustomLineNumbers_ = false; } ShowLineNumbers = restoreBuiltin; } public void RegisterTextTransformer(DocumentColorizingTransformer transformer) { if (!TextArea.TextView.LineTransformers.Contains(transformer)) { TextArea.TextView.LineTransformers.Add(transformer); registerdTransformers_.Add(transformer); } } public void UnregisterTextTransformer(DocumentColorizingTransformer transformer) { if (registerdTransformers_.Remove(transformer)) { TextArea.TextView.LineTransformers.Remove(transformer); } } public void UnregisterTextTransformers() { foreach (var transformer in registerdTransformers_) { TextArea.TextView.LineTransformers.Remove(transformer); } registerdTransformers_.Clear(); } public void RegisterHoverPreview(PopupHoverPreview preview) { registeredHoverPreviews_.Add(preview); } public void UnregisterHoverPreviews() { foreach (var ppreview in registeredHoverPreviews_) { ppreview.Unregister(); } registeredHoverPreviews_.Clear(); } private void AddDiffTextSegments(List segments) { diffSegments_ = segments; diffHighlighter_.Add(segments); } public void RemoveDiffTextSegments() { diffHighlighter_.Clear(); UpdateHighlighting(); } private void StartDiffSegmentAdding() { diffHighlighter_.Clear(); ClearAllMarkers(); TextArea.IsEnabled = false; // Disable the caret event because it triggers redrawing of // the right marker bar, which besides being slow, causes a // GDI handle leak from the usage of RenderTargetBitmap (known WPF issue). disableCaretEvent_ = true; duringDiffModeSetup_ = true; } private void AllDiffSegmentsAdded() { disableCaretEvent_ = false; duringDiffModeSetup_ = false; TextArea.IsEnabled = true; // This forces the updating of the right bar with the diffed line markers // to execute after the editor displayed the scroll bars. Dispatcher.Invoke(() => UpdateHighlighting(), DispatcherPriority.Render); } public void SelectDocumentRemark(Remark remark) { var element = remark.ReferencedElements[0]; HighlightElement(element, HighlighingType.Hovered); selectedRemark_ = remark; } public void AddRemarks(List allRemarks, List markerRemarksGroups, bool hasContextFilter) { if (markerRemarksGroups != null) { AddMarginRemarks(markerRemarksGroups, hasContextFilter); } if (allRemarks != null) { AddDocumentRemarks(allRemarks, hasContextFilter); } UpdateMargin(); UpdateHighlighting(); } public void RemoveRemarks() { selectedRemark_ = null; remarkHighlighter_.Clear(); margin_.RemoveRemarkBookmarks(); UpdateMargin(); UpdateHighlighting(); } public void UpdateRemarks(List allRemarks, List markerRemarksGroups, bool hasContextFilter) { RemoveRemarks(); AddRemarks(allRemarks, markerRemarksGroups, hasContextFilter); } public void AddElementOverlay(IRElement element, IElementOverlay overlay) { overlayRenderer_.AddElementOverlay(element, overlay); UpdateHighlighting(); } public IconElementOverlay AddIconElementOverlay(IRElement element, IconDrawing icon, double width = 16, double height = 0, string label = "", string tooltip = "", HorizontalAlignment alignmentX = HorizontalAlignment.Right, VerticalAlignment alignmentY = VerticalAlignment.Center, double marginX = 8, double marginY = 4) { var overlay = RegisterIconElementOverlay(element, icon, width, height, label, tooltip, alignmentX, alignmentY, marginX, marginY); UpdateHighlighting(); return overlay; } private IconElementOverlay RegisterIconElementOverlay(IRElement element, IconDrawing icon, double width, double height, string label, string tooltip, HorizontalAlignment alignmentX, VerticalAlignment alignmentY, double marginX, double marginY) { var overlay = IconElementOverlay.CreateDefault(icon, width, height, ColorBrushes.Transparent, selectedStyle_.BackColor, selectedStyle_.Border, label, tooltip, alignmentX, alignmentY, marginX, marginY); return (IconElementOverlay)RegisterElementOverlay(element, overlay); } public IElementOverlay RegisterElementOverlay(IRElement element, string label, string tooltip) { return RegisterIconElementOverlay(element, null, 0, 0, label, tooltip); } public IElementOverlay RegisterElementOverlay(IRElement element, IElementOverlay overlay, bool prepend = false) { SetupElementOverlayEvents(overlay); overlayRenderer_.AddElementOverlay(element, overlay, prepend); return overlay; } public void RemoveElementOverlays(IRElement element, object onlyWithTag = null) { overlayRenderer_.RemoveAllElementOverlays(element, onlyWithTag); } public void ClearElementOverlays() { overlayRenderer_.ClearElementOverlays(); UpdateHighlighting(); } public void EnterDiffMode() { DiffModeEnabled = true; SectionText = ReadOnlyMemory.Empty; } public void ExitDiffMode() { margin_.ClearMarkers(); diffHighlighter_.Clear(); SectionText = ReadOnlyMemory.Empty; DiffModeEnabled = false; } //? TODO: This is a more efficient way of marking the loop blocks //? by using a single group that covers all blocks in a loop //private void MarkLoopNest(Loop loop, HashSet handledBlocks) { // foreach(var nestedLoop in loop.NestedLoops) { // MarkLoopNest(nestedLoop, handledBlocks); // } // HighlightedGroup group = null; // foreach (var block in loop.Blocks) { // if(handledBlocks.Contains(block)) { // continue; // Block already marked as part of a nested loop. // } // handledBlocks.Add(block); // if(group == null) { // group = new HighlightedGroup(gr.GetDefaultBlockStyle(block)); // } // group.Elements.Add(block); // } // if (group != null) { // margin_.AddBlock(group); // } //} public DocumentLine GetLineByNumber(int lineNumber) { return Document.GetLineByNumber(lineNumber); } public DocumentLine GetLineByOffset(int offset) { return Document.GetLineByOffset(offset); } public void MarkBlock(IRElement element, Color selectedColor, bool raiseEvent = true) { var style = new HighlightingStyle(selectedColor, null); MarkBlock(element, style, raiseEvent); } public void MarkBlock(IRElement element, Brush selectedColor, bool raiseEvent = true) { var style = new HighlightingStyle(selectedColor, null); MarkBlock(element, style, raiseEvent); } public void MarkElements(ICollection> elementColorPairs) { var colorGroupMap = new Dictionary(elementColorPairs.Count); ClearTemporaryHighlighting(); foreach (var pair in elementColorPairs) { var element = pair.Item1; var color = pair.Item2; if (!colorGroupMap.TryGetValue(color, out var group)) { var style = new HighlightingStyle(color, null); group = new HighlightedElementGroup(style); colorGroupMap[color] = group; } group.Add(element); } foreach (var pair in colorGroupMap) { markedHighlighter_.Add(pair.Value); } UpdateHighlighting(); } public void ClearInstructionMarkers() { markedHighlighter_.ForEachElement(RaiseElementRemoveHighlightingEvent); markedHighlighter_.Clear(); UpdateHighlighting(); } public IconElementOverlay RegisterIconElementOverlay(IRElement element, IconDrawing icon, double width, double height, string label = null, string tooltip = null, bool prepend = false) { var overlay = IconElementOverlay.CreateDefault(icon, width, height, ColorBrushes.Transparent, selectedStyle_.BackColor, selectedStyle_.Border, label, tooltip); return (IconElementOverlay)RegisterElementOverlay(element, overlay, prepend); } public void SuspendUpdate() { updateSuspended_ = true; disableCaretEvent_ = true; overlayRenderer_.SuspendUpdate(); markerBarUpdateTask_.CancelTask(); markerBarUpdateLock_.EnterWriteLock(); } public void ResumeUpdate() { updateSuspended_ = false; disableCaretEvent_ = false; overlayRenderer_.ResumeUpdate(); markerBarUpdateLock_.ExitWriteLock(); UpdateHighlighting(); } public bool HandleOverlayKeyPress(KeyEventArgs e) { return overlayRenderer_.KeyPressed(e); } private void IRDocument_PreviewKeyDown(object sender, KeyEventArgs e) { if (margin_.SelectedBookmark != null) { e.Handled = EditBookmarkText(margin_.SelectedBookmark, e.Key); return; } // Notify overlay layer in case there is a selected overlay visual. if (overlayRenderer_.KeyPressed(e)) { e.Handled = true; return; } switch (e.Key) { case Key.Return: { if (Utils.IsAltModifierActive()) { PreviewDefinitionExecuted(this, null); } else { if (GetSelectedElement() is var element && TryOpenFunctionCallTarget(element)) { } else { GoToDefinitionExecuted(this, null); } } e.Handled = true; break; } case Key.Escape: { HidePreviewPopup(); e.Handled = true; break; } // Saving of markings with profiling not yet implemented. // case Key.M: { // if (Utils.IsControlModifierActive()) { // if (Utils.IsShiftModifierActive()) { // MarkBlockExecuted(this, null); // } // else { // MarkExecuted(this, null); // } // } // // e.Handled = true; // break; // } // case Key.D: { // if (Utils.IsControlModifierActive()) { // if (Utils.IsShiftModifierActive()) { // MarkDefinitionBlockExecuted(this, null); // } // else { // MarkDefinitionExecuted(this, null); // } // } // // e.Handled = true; // break; // } // case Key.U: { // if (Utils.IsControlModifierActive()) { // if (Utils.IsShiftModifierActive()) { // MarkUsesExecuted(this, null); // } // else { // ShowUsesExecuted(this, null); // } // } // // e.Handled = true; // break; // } // case Key.Delete: { // if (Utils.IsControlModifierActive() || // Utils.IsShiftModifierActive()) { // ClearAllMarkersExecuted(this, null); // } // else { // ClearMarkerExecuted(this, null); // } // // e.Handled = true; // break; // } case Key.B: { if (Utils.IsControlModifierActive()) { if (Utils.IsShiftModifierActive()) { RemoveBookmarkExecuted(this, null); } else { AddBookmarkExecuted(this, null); } } e.Handled = true; break; } case Key.R: { if (Utils.IsControlModifierActive()) { if (Utils.IsShiftModifierActive()) { MarkReferencesExecuted(this, null); } else { ShowReferencesExecuted(this, null); } } e.Handled = true; break; } case Key.F2: { if (Utils.IsShiftModifierActive()) { PreviousBookmarkExecuted(this, null); } else { NextBookmarkExecuted(this, null); } e.Handled = true; break; } case Key.Down: { if (Utils.IsControlModifierActive()) { GoToNextBlock(); e.Handled = true; } break; } case Key.Up: { if (Utils.IsControlModifierActive()) { GoToPreviousBlock(); e.Handled = true; } break; } case Key.Z: { if (Utils.IsControlModifierActive()) { UndoReversibleAction(); if (Utils.IsAltModifierActive()) { MirrorAction(DocumentActionKind.UndoAction, null); } e.Handled = true; } break; } case Key.E: { if (Utils.IsControlModifierActive()) { ShowExpressionGraphExecuted(this, null); e.Handled = true; } break; } } } private void SetupStyles() { if (settings_ is not DocumentSettings docSettings) { // Selection styles are also used in non-IR documents, // make sure they are not null and have reasonable defaults. selectedStyle_ = new HighlightingStyle { BackColor = ColorBrushes.GetTransparentBrush(settings_.SelectedValueColor, 0.5), Border = settings_.CurrentLineBorderColor.AsPen() }; selectedBlockStyle_ = new HighlightingStyle { BackColor = settings_.BackgroundColor.AsBrush(), Border = settings_.CurrentLineBorderColor.AsPen() }; return; } var borderPen = ColorPens.GetBoldPen(docSettings.BorderColor); var lightBorderPen = ColorPens.GetTransparentPen(docSettings.BorderColor, 150); selectedStyle_ ??= new HighlightingStyle { BackColor = ColorBrushes.GetTransparentBrush(settings_.SelectedValueColor, 0.5), Border = borderPen }; selectedBlockStyle_ = selectedStyle_; ssaUserStyle_ ??= new PairHighlightingStyle(); ssaUserStyle_.ParentStyle.BackColor = ColorBrushes.GetBrush( ColorUtils.AdjustLight(docSettings.UseValueColor, ParentStyleLightAdjustment)); ssaUserStyle_.ChildStyle.BackColor = ColorBrushes.GetBrush(docSettings.UseValueColor); ssaUserStyle_.ChildStyle.Border = borderPen; iteratedUserStyle_ = new PairHighlightingStyle { ParentStyle = { BackColor = ColorBrushes.GetTransparentBrush(docSettings.UseValueColor, 0) }, ChildStyle = { BackColor = ColorBrushes.GetTransparentBrush(docSettings.UseValueColor, 50), Border = lightBorderPen } }; ssaDefinitionStyle_ = new PairHighlightingStyle { ParentStyle = { BackColor = ColorBrushes.GetBrush( ColorUtils.AdjustLight(docSettings.DefinitionValueColor, ParentStyleLightAdjustment)) }, ChildStyle = { BackColor = ColorBrushes.GetBrush(docSettings.DefinitionValueColor), Border = borderPen } }; iteratedDefinitionStyle_ = new PairHighlightingStyle { ParentStyle = { BackColor = ColorBrushes.GetTransparentBrush(docSettings.DefinitionValueColor, 0) }, ChildStyle = { BackColor = ColorBrushes.GetTransparentBrush(docSettings.DefinitionValueColor, 50), Border = lightBorderPen } }; } private void ReloadSettings() { Background = ColorBrushes.GetBrush(settings_.BackgroundColor); Foreground = ColorBrushes.GetBrush(settings_.TextColor); FontFamily = new FontFamily(settings_.FontName); FontSize = settings_.FontSize; SetupRenderers(); SetupStyles(); SetupBlockFolding(); SetupEvents(); SyntaxHighlighting = Utils.LoadSyntaxHighlightingFile(App.GetSyntaxHighlightingFilePath()); UpdateHighlighting(); } private void MirrorAction(DocumentActionKind actionKind, IRElement element, object optionalData = null) { if (Utils.IsAltModifierActive()) { var action = new DocumentAction(actionKind, element, optionalData); ActionPerformed?.Invoke(this, action); } } private void RecordReversibleAction(DocumentActionKind actionKind, IRElement element, object optionalData = null) { ReversibleDocumentAction action = null; switch (actionKind) { case DocumentActionKind.MarkElement: { action = new ReversibleDocumentAction( new DocumentAction(actionKind, element, optionalData), action => ClearMarkedElement(action.Element)); break; } case DocumentActionKind.MarkUses: case DocumentActionKind.MarkReferences: { action = new ReversibleDocumentAction( new DocumentAction(actionKind, element, optionalData), action => { ClearMarkedElement(action.Element); ClearMarkedElement(action.Element.ParentTuple); var refList = action.OptionalData as List; foreach (var reference in refList) { ClearMarkedElement(reference.Element); ClearMarkedElement(reference.Element.ParentTuple); } SelectAndActivateElement(action.Element); }); break; } case DocumentActionKind.GoToDefinition: { action = new ReversibleDocumentAction( new DocumentAction(actionKind, element, optionalData), action => { SelectAndActivateElement(action.Element); }); break; } } if (action != null) { #if DEBUG Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Record undo action {action}"); #endif actionUndoStack_.Push(action); } } private void SelectAndActivateElement(IRElement element) { SelectElement(element); SetCaretAtElement(element); BringElementIntoView(element); } private bool UndoReversibleAction() { if (actionUndoStack_.Count == 0) { return false; } var undoAction = actionUndoStack_.Pop(); undoAction.Undo(); return true; } private ElementHighlighter GetHighlighter(HighlighingType type) { return type switch { HighlighingType.Hovered => hoverHighlighter_, HighlighingType.Selected => selectedHighlighter_, HighlighingType.Marked => markedHighlighter_, _ => throw new Exception("Unknown type") }; } private void MarkElementsOnSourceLine(ElementHighlighter highlighter, int lineNumber, Color selectedColor, bool raiseEvent, bool bringIntoView, SourceStackFrame inlinee) { var style = highlighter == selectedHighlighter_ ? selectedStyle_ : new HighlightingStyle(selectedColor); var group = new HighlightedElementGroup(style); IRElement firstTuple = null; foreach (var block in Function.Blocks) { foreach (var tuple in block.Tuples) { var sourceTag = tuple.GetTag(); bool found = false; if (sourceTag == null) { continue; } if (inlinee == null) { found = sourceTag.Line == lineNumber; } else if (sourceTag.HasInlinees) { found = sourceTag.Inlinees.Find(item => item.Function == inlinee.Function && item.Line == lineNumber) != null; } if (found) { group.Add(tuple); if (firstTuple == null) { firstTuple = tuple; } if (raiseEvent) { RaiseElementHighlightingEvent(tuple, group, highlighter.Type, HighlightingEventAction.AppendHighlighting); } } } } if (!group.IsEmpty()) { highlighter.Add(group); if (bringIntoView) { BringElementIntoView(firstTuple); } } UpdateHighlighting(); } private IRElement CreateDummyElement(int offset, int length) { int line = Document.GetLineByOffset(offset).LineNumber; var location = new ProfileExplorer.Core.TextLocation(offset, line, 0); return new IRElement(location, length); } private void HandelNoElementSelection() { UpdateHighlighting(); RaiseElementUnselectedEvent(); RaiseElementHighlightingEvent(null, null, HighlighingType.Selected, HighlightingEventAction.ReplaceHighlighting); } private void AddBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { var selectedElement = GetSelectedElement(); if (selectedElement != null) { AddBookmark(selectedElement); } } private void AddCommand(RoutedUICommand command, ExecutedRoutedEventHandler handler, CanExecuteRoutedEventHandler canExecuteHandler = null) { var binding = new CommandBinding(command); binding.Executed += handler; if (canExecuteHandler != null) { binding.CanExecute += canExecuteHandler; } CommandBindings.Add(binding); } private void AddSelectedElement(IRElement element, bool raiseEvent) { selectedElements_.Add(element); var previousBlock = currentBlock_; currentBlock_ = element.ParentBlock; if (raiseEvent) { if (currentBlock_ != previousBlock) { RaiseBlockSelectedEvent(currentBlock_); } RaiseElementSelectedEvent(element); } } private void ScrollBar_MouseLeave(object sender, MouseEventArgs e) { if (hoveredBarElement_ != null) { hoveredBarElement_.Style.Border = null; hoveredBarElement_ = null; RenderMarkerBar(); } HideTemporaryUI(); } private void ScrollBar_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { HideTemporaryUI(); var position = e.GetPosition(markerMargin_); var barElement = FindMarkerBarElement(position); if (barElement != null && barElement.HandlesInput) { ignoreNextPreviewElement_ = barElement.Element; ignoreNextBarHover_ = true; ignoreNextScrollEvent_ = true; BringElementIntoView(barElement.Element); e.Handled = true; } } private async void ScrollBar_PreviewMouseMove(object sender, MouseEventArgs e) { if (ignoreNextBarHover_) { ignoreNextBarHover_ = false; return; } if (e.LeftButton != MouseButtonState.Released || e.RightButton != MouseButtonState.Released) { return; } bool needsRendering = false; if (hoveredBarElement_ != null) { hoveredBarElement_.Style.Border = null; hoveredBarElement_ = null; needsRendering = true; } var position = e.GetPosition(markerMargin_); var barElement = FindMarkerBarElement(position); if (barElement != null && barElement.HandlesInput) { barElement.Style.Border = ColorPens.GetBoldPen(Colors.Black); hoveredBarElement_ = barElement; needsRendering = true; await ShowPreviewPopup(barElement.Element); } else { HideTemporaryUI(); } if (needsRendering) { RenderMarkerBar(true); } } private void Caret_PositionChanged(object sender, EventArgs e) { if (disableCaretEvent_) { return; } // Trigger event, used during diff mode to sync caret with other document. CaretChanged?.Invoke(this, TextArea.Caret.Offset); if (ignoreNextCaretEvent_) { ignoreNextCaretEvent_ = false; return; } var element = FindElementAtOffset(TextArea.Caret.Offset); SelectElement(element, true, false, TextArea.Caret.Offset); } private void ClearAllMarkersExecuted(object sender, ExecutedRoutedEventArgs e) { ClearAllMarkers(); } private void ClearAllMarkers() { ClearBlockMarkers(); ClearInstructionMarkers(); overlayRenderer_.Clear(); TextArea.TextView.Redraw(); } private void ClearBlockMarkersExecuted(object sender, ExecutedRoutedEventArgs e) { ClearBlockMarkers(); MirrorAction(DocumentActionKind.ClearBlockMarkers, null); } private void ClearBlockMarkers() { // Don't respond to block removal events, it changes the list being iterated // and all blocks will be removed after that anyway. margin_.DisableBlockRemoval = true; margin_.ForEachBlockElement(element => { RaiseElementRemoveHighlightingEvent(element); }); margin_.DisableBlockRemoval = false; margin_.ClearMarkers(); UpdateMargin(); } private void ClearInstructionMarkersExecuted(object sender, ExecutedRoutedEventArgs e) { ClearInstructionMarkers(); MirrorAction(DocumentActionKind.ClearBlockMarkers, null); } private void ClearMarkerExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { ClearMarkedElement(element); } } public void ClearSelectedElements() { selectedHighlighter_.Clear(); selectedElements_.Clear(); UpdateHighlighting(); } private void ClearTemporaryHighlighting(bool clearSelected = true) { if (!IsLoaded) { return; } HideHoverHighlighting(); if (clearSelected) { ClearSelectedElements(); } if (overlayRendererConnectedTemporarely_) { overlayRenderer_.ClearConnectedElements(); } } private void CreateRightMarkerMargin() { if (markerMargin_ != null) { return; // Margin already set up. } // Find the right scrollbar and place the canvas under it, // then make it semi-transparent so that the canvas is visible. var scrollViewer = Utils.FindChild(this); if (scrollViewer != null) { docVerticalScrollBar_ = Utils.FindChild(scrollViewer); if (docVerticalScrollBar_ != null) { docVerticalScrollBar_.Opacity = 0.6; docVerticalScrollBar_.PreviewMouseMove += ScrollBar_PreviewMouseMove; docVerticalScrollBar_.PreviewMouseLeftButtonDown += ScrollBar_PreviewMouseLeftButtonDown; docVerticalScrollBar_.MouseLeave += ScrollBar_MouseLeave; var parent = VisualTreeHelper.GetParent(docVerticalScrollBar_) as Grid; markerMargin_ = new Canvas(); Panel.SetZIndex(markerMargin_, 1); Panel.SetZIndex(docVerticalScrollBar_, 2); Grid.SetColumn(markerMargin_, Grid.GetColumn(docVerticalScrollBar_)); markerMargin_.Background = Brushes.White; parent.Children.Add(markerMargin_); } } } private void ResetRenderers() { markerBarUpdateTask_.CancelTask(); bookmarks_?.Clear(); hoverHighlighter_?.Clear(); selectedHighlighter_?.Clear(); markedHighlighter_?.Clear(); blockHighlighter_?.Clear(); diffHighlighter_?.Clear(); remarkHighlighter_?.Clear(); overlayRenderer_?.Clear(); margin_?.Reset(); } private bool EditBookmarkText(Bookmark bookmark, Key key) { // Because a TextBox is not used for the bookmarks, // editing the optional text must be handled manually. // This method is not part of Bookmark because it handles lots // of state through the BookmarkManager. var keyInfo = Utils.KeyToChar(key); if (keyInfo.IsLetter) { // Append a new letter. string keyString = keyInfo.Letter.ToString(); string text = bookmark.Text; if (text == null) { text = keyString; } else { text += keyString; } bookmark.Text = text; margin_.SelectedBookmarkChanged(); RaiseBookmarkChangedEvent(bookmark); } else if (key == Key.Back) { // Remove last letter. string text = bookmark.Text; if (!string.IsNullOrEmpty(text)) { text = text.Substring(0, text.Length - 1); bookmark.Text = text; margin_.SelectedBookmarkChanged(); RaiseBookmarkChangedEvent(bookmark); } } else if (key == Key.Return) { if (Utils.IsKeyboardModifierActive()) { bookmark.IsPinned = true; } margin_.UnselectBookmark(); margin_.SelectedBookmarkChanged(); RaiseBookmarkChangedEvent(bookmark); } else if (key == Key.Delete) { // Delete all text. bookmark.Text = ""; margin_.SelectedBookmarkChanged(); RaiseBookmarkChangedEvent(bookmark); } else if (key == Key.F2) { if (Utils.IsShiftModifierActive()) { PreviousBookmarkExecuted(this, null); } else { NextBookmarkExecuted(this, null); } return true; } else if (keyInfo.IsShift && keyInfo.IsControl) { if (keyInfo.Letter == 'B') { RemoveBookmark(bookmark); } } else if (!Utils.IsKeyboardModifierActive()) { margin_.UnselectBookmark(); margin_.SelectedBookmarkChanged(); return false; } return true; } private IRElement FindElementAtOffset(int offset) { // Exit if the element lists are still being computed or // for source code documents. if (DuringSectionLoading || Function == null) { return null; } IRElement element; if (DocumentUtils.FindElement(offset, operandElements_, out element) || DocumentUtils.FindElement(offset, tupleElements_, out element) || DocumentUtils.FindElement(offset, blockElements_, out element)) { return element; } return null; } private MarkerBarElement FindMarkerBarElement(Point position) { if (markerMargingElements_ != null) { //? TODO: This is inefficient, at least sort by Y and do binary search foreach (var barElement in markerMargingElements_) { if (barElement.Element == null) { continue; } if (barElement.Visual.Contains(position)) { return barElement; } if (barElement.Visual.Top > position.Y) { break; } } } return null; } private IRElement FindPointedElement(Point position, out int textOffset) { if (Function == null) { // For source code documents. textOffset = 0; return null; } int offset = DocumentUtils.GetOffsetFromMousePosition(position, this, out _); if (offset != -1) { textOffset = offset; return FindElementAtOffset(offset); } textOffset = -1; return null; } private void FirstBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToBookmark(bookmarks_.JumpToFirstBookmark()); } private HighlightingStyle GetMarkerStyleForCommand(ExecutedRoutedEventArgs e) { if (e != null && e.Parameter is SelectedColorEventArgs colorArgs) { return new HighlightingStyle(colorArgs.SelectedColor); } return PickMarkerStyle(); } private PairHighlightingStyle GetPairMarkerStyleForCommand(ExecutedRoutedEventArgs e) { if (e != null && e.Parameter is SelectedColorEventArgs colorArgs) { var style = new HighlightingStyle(colorArgs.SelectedColor); return new PairHighlightingStyle { ChildStyle = new HighlightingStyle(colorArgs.SelectedColor), ParentStyle = new HighlightingStyle(Utils.ChangeColorLuminisity(colorArgs.SelectedColor, 1.4)) }; } return PickPairMarkerStyle(); } private PairHighlightingStyle GetReferenceStyle(Reference reference) { //? TODO: Expose colors in settings return reference.Kind switch { ReferenceKind.Address => new PairHighlightingStyle { ChildStyle = new HighlightingStyle("#FF9090", ColorPens.GetBoldPen(Colors.DarkRed)), ParentStyle = new HighlightingStyle("#FFC9C9") }, ReferenceKind.Load => new PairHighlightingStyle { ChildStyle = new HighlightingStyle("#BDBAEC", ColorPens.GetPen(Colors.DarkBlue)), ParentStyle = new HighlightingStyle("#D9D8F4") }, ReferenceKind.Store => ssaUserStyle_, ReferenceKind.SSA => new PairHighlightingStyle { ChildStyle = new HighlightingStyle("#BAD6EC", ColorPens.GetPen(Colors.DarkBlue)), ParentStyle = new HighlightingStyle("#D8E9F4") }, _ => throw new InvalidOperationException("Unknown ReferenceKind") }; } public IRElement GetSelectedElement() { if (selectedElements_.Count == 0) { return null; } var selectedEnum = selectedElements_.GetEnumerator(); selectedEnum.MoveNext(); return selectedEnum.Current; } private OperandIR GetSelectedElementDefinition() { var defs = GetSelectedElementDefinitions(); return defs.Count == 1 ? defs[0] : null; } private List GetSelectedElementDefinitions() { var selectedOp = GetSelectedElement(); if (!(selectedOp is OperandIR op)) { return new List(); } var refFinder = CreateReferenceFinder(); return refFinder.FindAllDefinitions(op). ConvertAll(item => item as OperandIR); } private void UndoActionExecuted(object sender, ExecutedRoutedEventArgs e) { UndoReversibleAction(); e.Handled = true; } private void UndoActionCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = actionUndoStack_.Count > 0; e.Handled = true; } private void GoToDefinitionExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { if (!TryOpenFunctionCallTarget(element)) { GoToElementDefinition(element); MirrorAction(DocumentActionKind.GoToDefinition, element); } } } private async void PreviewDefinitionExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { await ShowDefinitionPreview(element, true); } } private void GoToDefinitionSkipCopiesExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { if (!TryOpenFunctionCallTarget(element)) { GoToElementDefinition(element, true); MirrorAction(DocumentActionKind.GoToDefinition, element); } } } private IRElement SkipAllCopies(IRElement op) { //? TODO: This should be in some IR utility class. var defInstr = op.ParentInstruction; while (defInstr != null) { var sourceOp = Session.CompilerInfo.IR.SkipCopyInstruction(defInstr); if (sourceOp != null && sourceOp != defInstr) { op = sourceOp; defInstr = sourceOp.ParentInstruction; } else { break; } } return op; } private ReferenceFinder CreateReferenceFinder() { return DocumentUtils.CreateReferenceFinder(Function, Session, settings_ as DocumentSettings); } private bool GoToElementDefinition(IRElement element, bool skipCopies = false) { RecordReversibleAction(DocumentActionKind.GoToDefinition, element); ClearTemporaryHighlighting(); if (element == null) { return false; } if (element is OperandIR op) { // If it's a destination operand and has a single user, jump to it. var refFinder = CreateReferenceFinder(); if (op.Role == OperandRole.Destination) { var useOp = refFinder.GetSingleUse(op); if (useOp != null) { HighlightSingleElement(useOp, selectedHighlighter_); SetCaretAtElement(useOp); return true; } } // Try to find a definition for the source operand. var defOp = refFinder.FindSingleDefinition(op); if (defOp != null) { if (skipCopies) { defOp = SkipAllCopies(defOp); } HighlightSingleElement(defOp, selectedHighlighter_); SetCaretAtElement(defOp); return true; } if (op.IsLabelAddress) { // For labels go to the target block. var targetOp = op.BlockLabelValue; HighlightSingleElement(targetOp, selectedHighlighter_); SetCaretAtElement(targetOp); return true; } } else if (element is InstructionIR instr) { // For single-source instructions, go to the source definition. if (instr.Sources.Count == 1) { GoToElementDefinition(instr.Sources[0]); } } return false; } private void HandleElement(IRElement element, ElementHighlighter highlighter, bool markExpression, bool markReferences) { var action = HighlightingEventAction.ReplaceHighlighting; bool highlighted = false; if (element is OperandIR op) { highlighted = HandleOperandElement(op, highlighter, markExpression, markReferences, action); } else if (element is InstructionIR instr) { highlighted = HandleInstructionElement(instr, highlighter, markExpression, ref action); } else if (element is BlockLabelIR blockLabel) { highlighted = HandleBlockLabel(highlighter, action, blockLabel); } if (!highlighted) { HandleOtherElement(element, highlighter, action); } } private bool HandleBlockLabel(ElementHighlighter highlighter, HighlightingEventAction action, BlockLabelIR blockLabel) { var block = blockLabel.Parent; if (block.Predecessors.Count == 0) { return false; } // Mark all branches referencing the label. var group = new HighlightedElementGroup(ssaDefinitionStyle_.ChildStyle); foreach (var predBlock in block.Predecessors) { var branchInstr = Session.CompilerInfo.IR.GetTransferInstruction(predBlock); if (branchInstr != null) { group.Add(branchInstr); RaiseElementHighlightingEvent(branchInstr, group, highlighter.Type, action); } } // Mark the label itself. group.Add(blockLabel); RaiseElementHighlightingEvent(blockLabel, group, highlighter.Type, action); highlighter.Add(group); return true; } private bool HandleInstructionElement(InstructionIR instr, ElementHighlighter highlighter, bool markExpression, ref HighlightingEventAction action) { if (markExpression) { // Mark an entire SSA def-use expression DAG. HighlightExpression(instr, highlighter, expressionOperandStyle_, expressionStyle_); return true; } if (settings_ is not DocumentSettings docSettings) { return false; } if (!docSettings.HighlightInstructionOperands) { return false; } // Highlight each source operand. The instruction itself // is also highlighted below, in append mode. action = HighlightingEventAction.AppendHighlighting; RaiseRemoveHighlightingEvent(highlighter.Type); foreach (var sourceOp in instr.Sources) { if (sourceOp.IsLabelAddress) { HighlightBlockLabel(sourceOp, highlighter, ssaUserStyle_, action); } else { HighlightDefinition(sourceOp, highlighter, ssaDefinitionStyle_, action, false); } } if (docSettings.HighlightDestinationUses) { foreach (var destOp in instr.Destinations) { HandleOperandElement(destOp, highlighter, markExpression, false, action); } } return true; } private bool HandleOperandElement(OperandIR op, ElementHighlighter highlighter, bool markExpression, bool markReferences, HighlightingEventAction action) { if (settings_ is not DocumentSettings docSettings) { return false; } if (op.Role == OperandRole.Source) { if (markExpression) { // Mark an entire SSA def-use expression DAG. HighlightExpression(op, highlighter, expressionOperandStyle_, expressionStyle_); return true; } // Further handling of sources is done below. } else if ((op.Role == OperandRole.Destination || op.Role == OperandRole.Parameter) && docSettings.HighlightDestinationUses) { // First look for an SSA definition and its uses, // if not found highlight every load of the same symbol. var refFinder = CreateReferenceFinder(); var useList = refFinder.FindAllUses(op); List iteratedUseList = null; bool handled = false; //? TODO: Default expansion needs an option if (markExpression) { // Collect the transitive set of users, marking instructions // that depend on the value of this destination operand. iteratedUseList = ExpandIteratedUseList(op, useList); handled = true; } else if (markReferences) { MarkReferences(op, highlighter); } if (useList.Count > 0) { HighlightUsers(op, useList, highlighter, ssaUserStyle_, action); handled = true; if (iteratedUseList != null && iteratedUseList.Count > 0) { HighlightUsers(op, iteratedUseList, highlighter, iteratedUserStyle_, action); } } // If the operand is an indirection, also try to mark // the definition of the base address value below. if (!op.IsIndirection) { return handled; } } if (docSettings.HighlightSourceDefinition) { if (op.IsLabelAddress) { return HighlightBlockLabel(op, highlighter, ssaUserStyle_, action); } if (markReferences) { MarkReferences(op, highlighter); return true; } return HighlightDefinition(op, highlighter, ssaDefinitionStyle_, action); } return false; } private List ExpandIteratedUseList(OperandIR operand, List useList) { var handledElements = new HashSet(useList.Count); foreach (var use in useList) { handledElements.Add(use); } // Each expansion of the same element doubles the recursion depth. if (currentExprElement_ == operand) { currentExprLevel_ += ExpressionLevelIncrement; } else { currentExprElement_ = operand; currentExprLevel_ = DefaultMaxExpressionLevel; } int maxLevel = currentExprLevel_; var refFinder = CreateReferenceFinder(); var newUseList = new List(useList); ExpandIteratedUseList(newUseList, handledElements, 0, maxLevel, refFinder); newUseList.RemoveRange(0, useList.Count); return newUseList; } private void ExpandIteratedUseList(List useList, HashSet handledElements, int level, int maxLevel, ReferenceFinder refFinder) { if (level > maxLevel) { return; } var newUseLists = new List>(1 << maxLevel - level + 1); foreach (var use in useList) { if (use is not OperandIR op) { continue; } var useInstr = op.ParentInstruction; if (useInstr != null) { foreach (var iteratedUse in refFinder.FindAllUses(useInstr)) { if (!handledElements.Add(iteratedUse)) { continue; // Use already visited during recursion. } // Recursively iterate over and collect uses. var iteratedUseList = new List(1 << maxLevel - level); iteratedUseList.Add(iteratedUse); ExpandIteratedUseList(iteratedUseList, handledElements, level + 1, maxLevel, refFinder); newUseLists.Add(iteratedUseList); } } } // Merge the children lists into the input list. // This is fairly inefficient, but not an issue with the max. level used. foreach (var list in newUseLists) { useList.AddRange(list); } } private void HandleOtherElement(IRElement element, ElementHighlighter highlighter, HighlightingEventAction action) { var style = element is BlockIR ? selectedBlockStyle_ : selectedStyle_; HandleOtherElement(element, highlighter, style, action); } private void HandleOtherElement(IRElement element, ElementHighlighter highlighter, HighlightingStyle style, HighlightingEventAction action) { var group = new HighlightedElementGroup(element, style); highlighter.Add(group); RaiseElementHighlightingEvent(element, group, highlighter.Type, action); } private void HideTemporaryUI() { HidePreviewPopup(); margin_.UnselectBookmark(); } private void HidePreviewPopup(bool force = false) { ignoreNextPreviewElement_ = null; if (previewPopup_ != null && (force || !previewPopup_.IsMouseOver)) { previewPopup_.ClosePopup(); previewPopup_ = null; } } private bool HighlightBlockLabel(OperandIR op, ElementHighlighter highlighter, PairHighlightingStyle style, HighlightingEventAction action) { var labelOp = op.BlockLabelValue; if (labelOp?.Parent == null) { return false; } var group = new HighlightedElementGroup(style.ChildStyle); group.Add(op); group.Add(labelOp); highlighter.Add(group); RaiseElementHighlightingEvent(op, group, highlighter.Type, action); return true; } private HighlightedElementGroup HighlightDefinedOperand(IRElement op, IRElement defElement, ElementHighlighter highlighter, PairHighlightingStyle style) { var group = new HighlightedElementGroup(style.ChildStyle); group.Add(op); group.Add(defElement); highlighter.Add(group); return group; } private HighlightedElementGroup HighlightInstruction(InstructionIR instr, ElementHighlighter highlighter, PairHighlightingStyle style) { var group = new HighlightedElementGroup(instr, style.ParentStyle); highlighter.Add(group); return group; } private HighlightedElementGroup HighlightOperand(IRElement op, ElementHighlighter highlighter, PairHighlightingStyle style) { var group = new HighlightedElementGroup(op, style.ChildStyle); highlighter.Add(group); return group; } private void HighlightSingleElement(IRElement element, ElementHighlighter highlighter) { ClearTemporaryHighlighting(highlighter.Type == HighlighingType.Selected); highlighter.Clear(); if (element is OperandIR op && op.Parent != null) { // Also highlight operand's parent instruction. highlighter.Add(new HighlightedElementGroup(op.Parent, definitionStyle_.ParentStyle)); } if (element is BlockIR && highlighter.Type == HighlighingType.Selected) { highlighter.Add(new HighlightedElementGroup(element, selectedBlockStyle_)); } else { highlighter.Add(new HighlightedElementGroup(element, definitionStyle_.ChildStyle)); } BringElementIntoView(element); } private bool HighlightDefinition(OperandIR op, ElementHighlighter highlighter, PairHighlightingStyle style, HighlightingEventAction action, bool highlightDefInstr = true) { // First look for an SSA definition, if not found // highlight every store to the same symbol. var refFinder = CreateReferenceFinder(); var defList = refFinder.FindAllDefinitions(op); if (defList.Count == 0) { return false; } // Highlight the definition instructions. if (highlightDefInstr) { var instrGroup = new HighlightedElementGroup(style.ParentStyle); foreach (var element in defList) { instrGroup.Add(element.ParentTuple); } highlighter.Add(instrGroup); } // Highlight the definitions. var group = new HighlightedElementGroup(op, style.ChildStyle); foreach (var element in defList) { group.Add(element); } highlighter.Add(group); RaiseElementHighlightingEvent(op, group, highlighter.Type, action); return true; } private void HighlightExpression(IRElement element, ElementHighlighter highlighter, HighlightingStyleCollection style, HighlightingStyleCollection instrStyle) { var locationTag = element.GetTag(); var handledElements = new HashSet(128); // Each expansion of the same element doubles the recursion depth. if (currentExprElement_ == element) { currentExprLevel_ += ExpressionLevelIncrement; } else { currentExprElement_ = element; currentExprStyleIndex_ = new Random().Next(style.Styles.Count - 1); currentExprLevel_ = DefaultMaxExpressionLevel; } int maxLevel = currentExprLevel_; int styleIndex = currentExprStyleIndex_; var refFinder = CreateReferenceFinder(); HighlightExpression(element, null, handledElements, highlighter, style, instrStyle, styleIndex, 0, maxLevel, refFinder); } private void HighlightExpression(IRElement element, IRElement parent, HashSet handledElements, ElementHighlighter highlighter, HighlightingStyleCollection style, HighlightingStyleCollection instrStyle, int styleIndex, int level, int maxLevel, ReferenceFinder refFinder) { if (!handledElements.Add(element)) { return; // Element already handled during recursion. } switch (element) { case OperandIR op: { //highlighter.Add(new HighlightedGroup(element, style.ForIndex(styleIndex))); highlighter.Add(new HighlightedElementGroup(element, iteratedDefinitionStyle_.ChildStyle)); if (level >= maxLevel) { return; } var sourceDefOp = refFinder.FindSingleDefinition(op); if (sourceDefOp != null) { //highlighter.Add(new HighlightedGroup(sourceDefOp, style.ForIndex(styleIndex))); highlighter.Add(new HighlightedElementGroup(sourceDefOp, iteratedDefinitionStyle_.ChildStyle)); if (sourceDefOp.ParentInstruction != null) { HighlightExpression(sourceDefOp.ParentInstruction, parent, handledElements, highlighter, style, instrStyle, styleIndex, level, maxLevel, refFinder); } } break; } case InstructionIR instr: { //highlighter.Add(new HighlightedGroup(instr, instrStyle.ForIndex(styleIndex))); highlighter.Add(new HighlightedElementGroup(instr, iteratedDefinitionStyle_.ParentStyle)); if (level >= maxLevel) { return; } foreach (var sourceOp in instr.Sources) { HighlightExpression(sourceOp, instr, handledElements, highlighter, style, instrStyle, styleIndex, level + 1, maxLevel, refFinder); } if (level > 0) { foreach (var destOp in instr.Destinations) { HighlightExpression(destOp, instr, handledElements, highlighter, style, instrStyle, styleIndex, level + 1, maxLevel, refFinder); } } break; } } } private void ResetExpressionLevel(IRElement element = null) { if (element == null || element != currentExprElement_ || !Utils.IsControlModifierActive()) { currentExprElement_ = null; currentExprLevel_ = 0; } } private void HighlightUsers(OperandIR op, List useList, ElementHighlighter highlighter, PairHighlightingStyle style, HighlightingEventAction action) { var instrGroup = new HighlightedElementGroup(style.ParentStyle); var useGroup = new HighlightedElementGroup(style.ChildStyle); useGroup.Add(op); //? TODO: Implement arrows - either to all uses, or just ones outside view // overlayRenderer_.SetRootElement(op, new HighlightingStyle(Colors.Black)); // overlayRendererConnectedTemporarely_ = highlighter.Type != HighlighingType.Marked; // var arrowStyle = new HighlightingStyle(Colors.DarkGreen, ColorPens.GetDashedPen(Colors.DarkGreen, DashStyles.Dash, 1.5)); foreach (var use in useList) { useGroup.Add(use); var useInstr = use.ParentTuple; if (useInstr != null) { instrGroup.Add(useInstr); } // overlayRenderer_.AddConnectedElement(use.Element, arrowStyle); } highlighter.Add(instrGroup); highlighter.Add(useGroup); RaiseElementHighlightingEvent(op, useGroup, highlighter.Type, action); } private async void IRDocument_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) { // If Ctrl is pressed, instead of go to definition // the action is a text search, which is handled by the host. if (Utils.IsControlModifierActive()) { return; } var position = e.GetPosition(TextArea.TextView); var element = FindPointedElement(position, out _); if (TryOpenFunctionCallTarget(element)) { e.Handled = true; return; } e.Handled = GoToElementDefinition(element, Utils.IsAltModifierActive()); } private bool TryOpenFunctionCallTarget(IRElement element) { // For call function names, notify owner in case it wants // to switch the view to the called function. if (IsCallTargetElement(element)) { var targetSection = DocumentUtils.FindCallTargetSection(element, Section, Session); if (targetSection != null && FunctionCallOpen != null) { FunctionCallOpen.Invoke(this, targetSection); return true; } } return false; } private async void IRDocument_PreviewMouseHover(object sender, MouseEventArgs e) { if (settings_ is not DocumentSettings docSettings) { return; } if (ignoreNextHoverEvent_) { ignoreNextHoverEvent_ = false; return; } bool highlightElement = docSettings.ShowInfoOnHover && (!docSettings.ShowInfoOnHoverWithModifier || Utils.IsKeyboardModifierActive()); if (!highlightElement) { return; } var position = e.GetPosition(TextArea.TextView); var element = FindPointedElement(position, out _); if (element != null) { if (removeHoveredAction_ != null) { removeHoveredAction_.Cancel(); removeHoveredAction_ = null; } if (element == hoveredElement_) { return; } // For hover ignore blocks and instructions, it's too jarring. if (!selectedElements_.Contains(element) && !(element is BlockIR) && !(element is InstructionIR)) { bool previewDisplayed = await ShowDefinitionPreview(element); if (previewDisplayed) { HideHoverHighlighting(); hoveredElement_ = element; HandleElement(element, hoverHighlighter_, Utils.IsControlModifierActive(), Utils.IsShiftModifierActive()); UpdateHighlighting(); return; } } } HideHoverHighlighting(); UpdateHighlighting(); } private void IRDocument_PreviewMouseHoverStopped(object sender, MouseEventArgs e) { removeHoveredAction_ = DelayedAction.StartNew(() => { if (removeHoveredAction_ != null) { removeHoveredAction_ = null; HideHoverHighlighting(); HidePreviewPopup(); } }); ignoreNextHoverEvent_ = false; } private void HideHoverHighlighting() { if (hoveredElement_ == null) { return; } RaiseElementHighlightingEvent(null, null, HighlighingType.Hovered, HighlightingEventAction.ReplaceHighlighting); hoverHighlighter_.Clear(); hoveredElement_ = null; } private void IRDocument_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { HidePreviewPopup(); selectingText_ = false; if (ignoreNextScrollEvent_) { ignoreNextScrollEvent_ = false; //e.Handled = true; } } private void IRDocument_PreviewMouseMove(object sender, MouseEventArgs e) { ForceCursor = true; Cursor = Cursors.Arrow; margin_.MouseMoved(e); // Don't send event to overlays that may extend under the scrollbar. if (!disableOverlayEvents_ && (docVerticalScrollBar_ == null || !docVerticalScrollBar_.IsMouseOver) && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released) { overlayRenderer_.MouseMoved(e); } } private void IRDocument_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { Focus(); HideTemporaryUI(); } private bool IsElementOutsideView(IRElement element) { if (!TextArea.TextView.VisualLinesValid) { return true; } int targetLine = element.TextLocation.Line; var visualLines = TextArea.TextView.VisualLines; int viewStart = visualLines[0].FirstDocumentLine.LineNumber; int viewEnd = visualLines[^1].LastDocumentLine.LineNumber; return targetLine < viewStart || targetLine > viewEnd; } private void LastBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToBookmark(bookmarks_.JumpToLastBookmark()); } private async Task ComputeElementListsAsync() { // Compute the element lists on another thread, for large functions // it can be slow would block showing of any text before it's done. await Task.Run(() => ComputeElementLists()); } private async Task LateLoadSectionSetup(ParsedIRTextSection parsedSection, bool isSourceCode = false) { #if DEBUG Trace.TraceInformation( $"Document {ObjectTracker.Track(this)}: Complete setup for {parsedSection}"); #endif // Folding uses the basic block boundaries. actionUndoStack_.Clear(); SetupBlockHighlighter(); SetupBlockFolding(); ClearElementOverlays(); CreateRightMarkerMargin(); MarkLoopBlocks(); DuringSectionLoading = false; IsLoaded = true; //? TODO: Check if other sections have marked elements and try to mark same ones //! - session can be queried //! - load func and deserialize state object //! - for each marker/bookmark, use FindEquivalentValue //! - maybe set "no saving" flag for these copied markers //var other = Session.GetNextSection(Section); //if (other != null) // CloneOtherSectionAnnotations(other); // Do compiler-specific document work. if (!isSourceCode) { await Session.LoadedSectionHandler.HandleLoadedSection(this, Function, Section); } UpdateHighlighting(); } //? TODO: Check if other sections have marked elements and try to mark same ones private async Task CloneOtherSectionAnnotations(IRTextSection otherSection) { var parsedSection = await Session.LoadAndParseSection(otherSection); if (parsedSection == null) return; object data = Session.LoadDocumentState(otherSection); var refFinder = CreateReferenceFinder(); if (data != null) { var state = UIStateSerializer.Deserialize(data, parsedSection.Function); var markerState = state.DocumentState.MarkedHighlighter; if (markerState != null && markerState.Groups != null) { foreach (var groupState in markerState.Groups) { var group = new HighlightedElementGroup(groupState.Style); foreach (var item in groupState.Elements) { if (item.Value == null) { continue; } // Search for equivalent value in current section. var equivElement = refFinder.FindEquivalentValue(item); if (equivElement != null) { group.Add(equivElement); } } if (!group.IsEmpty()) { markedHighlighter_.Add(new HighlightedSegmentGroup(group, false)); } } } } } private void SetupBlockHighlighter() { if (!settings_.ShowBlockSeparatorLine) { return; } // Setup highlighting of block background. blockHighlighter_.Clear(); foreach (var element in blockElements_) { blockHighlighter_.Add(element); } } private void ComputeElementLists() { // In case the function couldn't be parsed, bail // after creating the elements, this should prevent further issues. int blocks = Function != null ? Function.Blocks.Count + 1 : 1; blockElements_ = new List(blocks); tupleElements_ = new List(blocks * 4); operandElements_ = new List(blocks * 12); selectedElements_ = new HashSet(); if (Function == null) { // For source code documents. return; } // Add the function parameters. foreach (var param in Function.Parameters) { operandElements_.Add(param); } // Add the elements from the entire function. foreach (var block in Function.Blocks) { blockElements_.Add(block); if (block.Label != null) { operandElements_.Add(block.Label); } foreach (var tuple in block.Tuples) { tupleElements_.Add(tuple); if (tuple is InstructionIR instr) { foreach (var op in instr.Destinations) { operandElements_.Add(op); } foreach (var op in instr.Sources) { operandElements_.Add(op); } } } } } private void Margin__BookmarkChanged(object sender, Bookmark bookmark) { RaiseBookmarkChangedEvent(bookmark); } private void Margin__BookmarkRemoved(object sender, Bookmark bookmark) { RemoveBookmark(bookmark); } private void MarkBlockExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { element = element.ParentBlock; var style = GetMarkerStyleForCommand(e); MarkBlock(element, style); MirrorAction(DocumentActionKind.MarkBlock, element, style); } } private void MarkDefinitionBlockExecuted(object sender, ExecutedRoutedEventArgs e) { if (selectedElements_.Count == 1) { var defOps = GetSelectedElementDefinitions(); foreach (var defOp in defOps) { var element = defOp.ParentBlock; var style = GetMarkerStyleForCommand(e); MarkBlock(element, style); MirrorAction(DocumentActionKind.MarkElement, defOp, style); } } } private void MarkDefinitionExecuted(object sender, ExecutedRoutedEventArgs e) { if (selectedElements_.Count == 1) { var defOps = GetSelectedElementDefinitions(); foreach (var defOp in defOps) { var style = GetPairMarkerStyleForCommand(e); MarkElement(defOp, style); MirrorAction(DocumentActionKind.MarkElement, defOp, style); } } } private void MarkElement(IRElement element, PairHighlightingStyle style) { MarkElement(element, style.ChildStyle); } private void MarkExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { var style = GetPairMarkerStyleForCommand(e); MarkElement(element, style); MirrorAction(DocumentActionKind.MarkElement, element, style); } } private void MarkIconExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetSelectedElement() is var element) { if (e != null && e.Parameter is SelectedIconEventArgs iconArgs) { var icon = IconDrawing.FromIconResource(iconArgs.SelectedIconName); var overlay = AddIconElementOverlay(element, icon, DefaultLineHeight, DefaultLineHeight); overlay.Background = Background; overlay.ShowBorderOnMouseOverOnly = true; overlay.ShowBackgroundOnMouseOverOnly = true; overlay.IsLabelPinned = true; // MirrorAction(DocumentActionKind.MarkIcon, element, iconArgs); } } } private void MarkLoopBlocks() { var dummyGraph = new Graph(GraphKind.FlowGraph); var graphStyle = new FlowGraphStyleProvider(dummyGraph, App.Settings.FlowGraphSettings); var loopGroups = new Dictionary(); foreach (var block in Function.Blocks) { var loopTag = block.GetTag(); if (loopTag != null) { var style = graphStyle.GetBlockNodeStyle(block); if (!loopGroups.TryGetValue(style, out var group)) { group = new HighlightedElementGroup(style); loopGroups[style] = group; } group.Add(block); } } foreach (var group in loopGroups.Values) { margin_.AddBlock(group, false); } } private void MarkReferencesExecuted(object sender, ExecutedRoutedEventArgs e) { var selectedOp = GetSelectedElement(); if (selectedOp is OperandIR op) { MarkReferences(op, markedHighlighter_); MirrorAction(DocumentActionKind.MarkReferences, selectedOp); } UpdateHighlighting(); } private void MarkReferences(OperandIR op, ElementHighlighter highlighter) { if (op.IsIndirection) { op = op.IndirectionBaseValue; } var refFinder = CreateReferenceFinder(); var operandRefs = refFinder.FindAllReferences(op); var markedInstrs = new HashSet(operandRefs.Count); //? TODO: Issue when an instr has multiple operands highlighted (PHI) //? the prev ops are covered by the background of the other ops, //? plus it wastes time with the redundant highlighting ClearTemporaryHighlighting(); foreach (var operandRef in operandRefs) { var style = GetReferenceStyle(operandRef); // Highlight instruction. var instr = operandRef.Element.ParentInstruction; if (instr != null && !markedInstrs.Contains(instr)) { HighlightInstruction(instr, highlighter, style); markedInstrs.Add(instr); } var group = HighlightOperand(operandRef.Element, highlighter, style); RaiseElementHighlightingEvent(operandRef.Element, group, HighlighingType.Marked, HighlightingEventAction.AppendHighlighting); } if (highlighter == markedHighlighter_) { // Show references in panel. Session.ShowAllReferences(op, this); RecordReversibleAction(DocumentActionKind.MarkReferences, op, operandRefs); } } private void MarkUsesExecuted(object sender, ExecutedRoutedEventArgs e) { var defOp = GetSelectedElementDefinition(); var style = GetPairMarkerStyleForCommand(e); if (defOp != null) { MarkUses(defOp, style); MirrorAction(DocumentActionKind.MarkUses, defOp, style); } } private void MarkUses(OperandIR defOp, PairHighlightingStyle style) { ClearTemporaryHighlighting(); var refFinder = CreateReferenceFinder(); var useList = refFinder.FindAllUses(defOp); HighlightUsers(defOp, useList, markedHighlighter_, style, HighlightingEventAction.AppendHighlighting); UpdateHighlighting(); Session.ShowSSAUses(defOp, this); RecordReversibleAction(DocumentActionKind.MarkUses, defOp, useList); } private void NextBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { if (!JumpToBookmark(bookmarks_.GetNext())) { JumpToBookmark(bookmarks_.JumpToFirstBookmark()); } } private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private HighlightingStyle PickMarkerLightStyle() { return markerParentStyle_.GetNext(); } private HighlightingStyle PickMarkerStyle() { return markerChildStyle_.GetNext(); } private PairHighlightingStyle PickPairMarkerStyle() { return new PairHighlightingStyle { ParentStyle = markerParentStyle_.GetNext(), ChildStyle = markerChildStyle_.GetNext() }; } private bool HighlighterVersionChanged(MarkerMarginVersionInfo info) { return markedHighlighter_.Version != info.LastMarkedVersion || selectedHighlighter_.Version != info.LastSelectedVersion || hoverHighlighter_.Version != info.LastHoveredVersion || diffHighlighter_.Version != info.LastDiffVersion || margin_.Version != info.LastBlockMarginVersion || bookmarks_.Version != info.LastBookmarkVersion || overlayRenderer_.Version != info.LastOverlayVersion; } private void SaveHighlighterVersion(MarkerMarginVersionInfo info) { info.LastMarkedVersion = markedHighlighter_.Version; info.LastSelectedVersion = selectedHighlighter_.Version; info.LastHoveredVersion = hoverHighlighter_.Version; info.LastDiffVersion = diffHighlighter_.Version; info.LastBlockMarginVersion = margin_.Version; info.LastBookmarkVersion = bookmarks_.Version; info.LastOverlayVersion = overlayRenderer_.Version; info.NeedsRedrawing = true; } //? TODO: Extract all right margin code into own class private void PopulateMarkerBar() { // Try again to create the margin bar, the scrollbar may not have // been visible when the document view was loaded. if (markerMargin_ == null) { CreateRightMarkerMargin(); if (markerMargin_ == null) { //? TODO: Fix //Trace.WriteLine("NO MARGIN"); //Trace.WriteLine(Environment.StackTrace); return; } } if (!HighlighterVersionChanged(highlighterVersion_)) { return; } markerMargingElements_ = new List(128); int arrowButtonHeight = 16; int startY = arrowButtonHeight; // Delay the update to ensure the markerMargin has layout updated. // Since the code runs later on the UI thread, it can end up interleaved // with code that changes the OverlayRenderer data structs. used by the // PopulateMarker* functions, abort the update in that case. var updateTask = markerBarUpdateTask_.CancelCurrentAndCreateTask(); Dispatcher.BeginInvoke(() => { if (updateTask.IsCanceled) { return; } markerBarUpdateLock_.EnterWriteLock(); double width = markerMargin_.ActualWidth; double height = markerMargin_.ActualHeight; double availableHeight = height - arrowButtonHeight * 2; int lines = Document.LineCount; double dotSize = Math.Max(2, availableHeight / lines); double dotWidth = width / 3; availableHeight -= dotSize; PopulateMarkerBarForHighlighter(markedHighlighter_, startY, width, availableHeight, dotSize); PopulateMarkerBarForHighlighter(selectedHighlighter_, startY, width, availableHeight, dotSize); PopulateMarkerBarForHighlighter(hoverHighlighter_, startY, width, availableHeight, dotSize); PopulateMarkerBarForElementOverlays(startY, width, availableHeight, dotSize); PopulateMarkerBarForDiffs(startY, width, availableHeight); PopulateMarkerBarForBlocks(startY, width, availableHeight); margin_.ForEachBookmark(bookmark => { PopulateMarkerBarForBookmark(bookmark, startY, width, height, dotWidth, dotSize); }); // Sort so that searching for elements can be speed up. markerMargingElements_.Sort((a, b) => (int)(a.Visual.Top - b.Visual.Top)); SaveHighlighterVersion(highlighterVersion_); RenderMarkerBar(); markerBarUpdateLock_.ExitWriteLock(); updateTask.Complete(); }, DispatcherPriority.Background); } private void PopulateMarkerBarForBookmark(Bookmark bookmark, int startY, double width, double height, double dotWidth, double dotHeight) { double y = (double)bookmark.Element.TextLocation.Line / LineCount * height; var elementVisual = new Rect(width / 3, startY + y, dotWidth, dotHeight); var style = bookmark.Style; if (bookmark.Style != null) { var brush = style.BackColor as SolidColorBrush; var color = ColorUtils.AdjustSaturation(brush.Color); style = new HighlightingStyle(color); } else { style = new HighlightingStyle(Colors.Crimson); } markerMargingElements_.Add(new MarkerBarElement { Element = bookmark.Element, Visual = elementVisual, Style = style, HandlesInput = true }); } private void PopulateMarkerBarForHighlighter(ElementHighlighter highlighter, int startY, double width, double height, double dotSize) { highlighter.ForEachStyledElement((element, style) => { double y = (double)element.TextLocation.Line / LineCount * height; var brush = style.BackColor as SolidColorBrush; if (brush.Color == Colors.Transparent) { return; } var color = ColorUtils.AdjustSaturation(brush.Color); var elementVisual = new Rect(0, startY + y, width, dotSize); var barStyle = new HighlightingStyle(color); markerMargingElements_.Add(new MarkerBarElement { Element = element, Visual = elementVisual, Style = barStyle, HandlesInput = true }); }); } private void PopulateMarkerBarForBlocks(int startY, double width, double height) { foreach (var blockGroup in margin_.BlockGroups) { var brush = blockGroup.Group.Style.BackColor as SolidColorBrush; var color = ColorUtils.AdjustSaturation(brush.Color, 1.5f); if (!blockGroup.SavesStateToFile) { continue; } foreach (var segment in blockGroup.Segments) { int startLine = Document.GetLineByOffset(segment.StartOffset).LineNumber; int endLine = Document.GetLineByOffset(segment.EndOffset - 1).LineNumber; int lineSpan = endLine - startLine + 1; double y = Math.Floor((double)startLine / LineCount * height); double lineHeight = Math.Ceiling(Math.Max(1, (double)lineSpan / LineCount * height)); var elementVisual = new Rect(0, startY + y, width / 3, lineHeight); var barStyle = new HighlightingStyle(color); markerMargingElements_.Add(new MarkerBarElement { Element = segment.Element, Visual = elementVisual, Style = barStyle, HandlesInput = false }); } } } private void PopulateMarkerBarForDiffs(int startY, double width, double height) { if (duringDiffModeSetup_) { return; } int lastLine = -1; int lineSpan = 1; var lastColor = Colors.Transparent; diffHighlighter_.ForEachDiffSegment((segment, color) => { // Combine the marking of multiple diffs of the same type // to speed up rendering. int line = Document.GetLineByOffset(segment.StartOffset).LineNumber; if (line != lastLine) { if (line == lastLine + 1 && color == lastColor) { lastLine = line; lastColor = color; lineSpan++; } else { if (lineSpan > 0 && lastColor != Colors.Transparent) { PopulateDiffLines(lastLine, lineSpan, startY, width, height, lastColor); } lastLine = line; lineSpan = 1; lastColor = color; } } }); if (lineSpan > 0 && lastColor != Colors.Transparent) { PopulateDiffLines(lastLine, lineSpan, startY, width, height, lastColor); } } private void PopulateDiffLines(int lastLine, int lineSpan, int startY, double width, double height, Color color) { int startLine = lastLine - lineSpan; double y = Math.Floor((double)startLine / LineCount * height); double lineHeight = Math.Ceiling(Math.Max(1, (double)lineSpan / LineCount * height)); color = ColorUtils.AdjustSaturation(color, 1.5f); var elementVisual = new Rect(2 * width / 3, startY + y, width / 3, lineHeight); var barStyle = new HighlightingStyle(color); markerMargingElements_.Add(new MarkerBarElement { Element = null, Visual = elementVisual, Style = barStyle, HandlesInput = false }); } private void PopulateMarkerBarForElementOverlays(int startY, double width, double height, double dotSize) { overlayRenderer_.ForEachElementOverlay((element, overlaySegment) => { // Only consider elements with overlays that should appear on the marker bar. bool showOnMarkerBar = false; foreach (var overlay in overlaySegment.Overlays) { if (overlay.ShowOnMarkerBar) { showOnMarkerBar = true; break; } } if (!showOnMarkerBar) { return; } double y = (double)element.TextLocation.Line / LineCount * height; var brush = Brushes.Blue; var color = ColorUtils.AdjustSaturation(brush.Color); var elementVisual = new Rect(0, startY + y, width, dotSize); var barStyle = new HighlightingStyle(color); markerMargingElements_.Add(new MarkerBarElement { Element = element, Visual = elementVisual, Style = barStyle, HandlesInput = true }); }); } private void PreviousBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { if (!JumpToBookmark(bookmarks_.GetPrevious())) { JumpToBookmark(bookmarks_.JumpToLastBookmark()); } } private void RaiseBlockSelectedEvent(IRElement element) { BlockSelected?.Invoke(this, new IRElementEventArgs {Element = element, Document = this}); } private void RaiseBookmarkAddedEvent(Bookmark bookmark) { BookmarkAdded?.Invoke(this, bookmark); } private void RaiseBookmarkChangedEvent(Bookmark bookmark) { BookmarkChanged?.Invoke(this, bookmark); } private void RaiseBookmarkListClearedEvent() { BookmarkListCleared?.Invoke(this, new EventArgs()); } private void RaiseBookmarkRemovedEvent(Bookmark bookmark) { BookmarkRemoved?.Invoke(this, bookmark); } private void RaiseBookmarkSelectedEvent(Bookmark bookmark) { BookmarkSelected?.Invoke(this, new SelectedBookmarkInfo { Bookmark = bookmark, SelectedIndex = bookmarks_.SelectedIndex, TotalBookmarks = bookmarks_.Bookmarks.Count }); } private void RaiseElementHighlightingEvent(IRElement element, HighlightedElementGroup group, HighlighingType type, HighlightingEventAction action) { ElementHighlighting?.Invoke(this, new IRHighlightingEventArgs { Action = action, Type = type, Element = element, Group = group, MirrorAction = Utils.IsAltModifierActive() }); } private void RaiseElementRemoveHighlightingEvent(IRElement element) { ElementHighlighting?.Invoke(this, new IRHighlightingEventArgs { Action = HighlightingEventAction.RemoveHighlighting, Element = element }); } private void RaiseElementSelectedEvent(IRElement element) { ElementSelected?.Invoke(this, new IRElementEventArgs { Element = element, Document = this, MirrorAction = Utils.IsAltModifierActive() }); } private void RaiseElementUnselectedEvent() { ElementUnselected?.Invoke(this, new IRElementEventArgs { Element = null, Document = this, MirrorAction = Utils.IsAltModifierActive() }); } private void RaiseRemoveHighlightingEvent(HighlighingType type) { ElementHighlighting?.Invoke(this, new IRHighlightingEventArgs { Action = HighlightingEventAction.RemoveHighlighting, Type = type }); } private void RemoveAllBookmarksExecuted(object sender, ExecutedRoutedEventArgs e) { RemoveAllBookmarks(); } private void RemoveBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { if (margin_.SelectedBookmark != null) { RemoveBookmark(margin_.SelectedBookmark); return; } // Find the bookmark associated with the current element. var selectedElement = GetSelectedElement(); if (selectedElement != null) { var bookmark = bookmarks_.RemoveBookmark(selectedElement); if (bookmark == null && selectedElement is OperandIR op) { bookmark = bookmarks_.RemoveBookmark(op.ParentTuple); } if (bookmark != null) { RemoveBookmark(bookmark); } } } private void RenderMarkerBar(bool forceUpdate = false) { if (!forceUpdate && (markerMargingElements_ == null || !highlighterVersion_.NeedsRedrawing)) { return; } if (Math.Abs(markerMargin_.ActualWidth) < double.Epsilon || Math.Abs(markerMargin_.ActualHeight) < double.Epsilon) { return; // View not properly initialized yet. } var drawingVisual = new DrawingVisual(); using (var draw = drawingVisual.RenderOpen()) { foreach (var barElement in markerMargingElements_) { draw.DrawRectangle(barElement.Style.BackColor, barElement.Style.Border, barElement.Visual); } } // Create a bitmap with an area matching the margin, // render the visual over it and use it instead since it is more efficient to draw. var bitmap = new RenderTargetBitmap((int)markerMargin_.ActualWidth, (int)markerMargin_.ActualHeight, 96, 96, PixelFormats.Default); bitmap.Render(drawingVisual); bitmap.Freeze(); Image image = null; if (markerMargin_.Children.Count > 0) { image = markerMargin_.Children[0] as Image; if (image != null) { var prevBitmap = image.Source as RenderTargetBitmap; prevBitmap.Clear(); // Required to prevent GDI leaks. } } if (image == null) { image = new Image(); image.Source = bitmap; markerMargin_.Children.Add(image); } else { image.Source = bitmap; } highlighterVersion_.NeedsRedrawing = false; } private void SetupCommands() { AddCommand(DocumentCommand.GoToDefinition, GoToDefinitionExecuted); AddCommand(DocumentCommand.GoToDefinitionSkipCopies, GoToDefinitionSkipCopiesExecuted); AddCommand(DocumentCommand.PreviewDefinition, PreviewDefinitionExecuted); AddCommand(DocumentCommand.Mark, MarkExecuted); AddCommand(DocumentCommand.MarkIcon, MarkIconExecuted); AddCommand(DocumentCommand.MarkBlock, MarkBlockExecuted); AddCommand(DocumentCommand.MarkDefinition, MarkDefinitionExecuted); AddCommand(DocumentCommand.MarkDefinitionBlock, MarkDefinitionBlockExecuted); AddCommand(DocumentCommand.ShowUses, ShowUsesExecuted); AddCommand(DocumentCommand.MarkUses, MarkUsesExecuted); AddCommand(DocumentCommand.MarkReferences, MarkReferencesExecuted); AddCommand(DocumentCommand.ShowReferences, ShowReferencesExecuted); AddCommand(DocumentCommand.ShowExpressionGraph, ShowExpressionGraphExecuted); AddCommand(DocumentCommand.ClearMarker, ClearMarkerExecuted); AddCommand(DocumentCommand.ClearAllMarkers, ClearAllMarkersExecuted); AddCommand(DocumentCommand.ClearBlockMarkers, ClearBlockMarkersExecuted); AddCommand(DocumentCommand.ClearInstructionMarkers, ClearInstructionMarkersExecuted); AddCommand(DocumentCommand.AddBookmark, AddBookmarkExecuted); AddCommand(DocumentCommand.RemoveBookmark, RemoveBookmarkExecuted); AddCommand(DocumentCommand.RemoveAllBookmarks, RemoveAllBookmarksExecuted); AddCommand(DocumentCommand.PreviousBookmark, PreviousBookmarkExecuted); AddCommand(DocumentCommand.NextBookmark, NextBookmarkExecuted); AddCommand(DocumentCommand.FirstBookmark, FirstBookmarkExecuted); AddCommand(DocumentCommand.LastBookmark, LastBookmarkExecuted); AddCommand(DocumentCommand.UndoAction, UndoActionExecuted, UndoActionCanExecute); } private void SetupEvents() { if (eventSetupDone_) { return; } PreviewKeyDown += IRDocument_PreviewKeyDown; MouseDown += IRDocument_MouseDown; PreviewMouseLeftButtonDown += IRDocument_PreviewMouseLeftButtonDown; PreviewMouseRightButtonDown += IRDocument_PreviewMouseRightButtonDown; PreviewMouseLeftButtonUp += IRDocument_PreviewMouseLeftButtonUp; PreviewMouseHover += IRDocument_PreviewMouseHover; PreviewMouseHoverStopped += IRDocument_PreviewMouseHoverStopped; PreviewMouseDoubleClick += IRDocument_PreviewMouseDoubleClick; PreviewMouseMove += IRDocument_PreviewMouseMove; MouseLeave += IRDocument_MouseLeave; Drop += IRDocument_Drop; DragOver += IRDocument_DragOver; GiveFeedback += IRDocument_GiveFeedback; TextArea.Caret.PositionChanged += Caret_PositionChanged; margin_.BookmarkRemoved += Margin__BookmarkRemoved; margin_.BookmarkChanged += Margin__BookmarkChanged; eventSetupDone_ = true; AllowDrop = true; // Enable drag-and-drop handilng. } private void IRDocument_MouseLeave(object sender, MouseEventArgs e) { HideTemporaryUI(); overlayRenderer_.MouseLeave(); } private void IRDocument_GiveFeedback(object sender, GiveFeedbackEventArgs e) { e.UseDefaultCursors = false; Mouse.OverrideCursor = Cursors.Arrow; } private void IRDocument_DragOver(object sender, DragEventArgs e) { var position = e.GetPosition(TextArea.TextView); var element = FindPointedElement(position, out _); if (element != null) { HighlightElement(element, HighlighingType.Hovered); e.Effects = DragDropEffects.All; e.Handled = true; } else { HideHoverHighlighting(); } } private void IRDocument_Drop(object sender, DragEventArgs e) { if (e.Data.GetData(typeof(IRElementDragDropSelection)) is IRElementDragDropSelection selection) { var position = e.GetPosition(TextArea.TextView); var element = FindPointedElement(position, out _); selection.Element = element; e.Effects = DragDropEffects.All; e.Handled = true; } } private void IRDocument_MouseDown(object sender, MouseButtonEventArgs e) { // Handle the mouse back-button being pressed. if (e.ChangedButton == MouseButton.XButton1) { UndoLastAction(); } } private void UndoLastAction() { UndoReversibleAction(); if (Utils.IsAltModifierActive()) { MirrorAction(DocumentActionKind.UndoAction, null); } } private void SetupProperties() { IsReadOnly = true; HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; Options.AllowScrollBelowDocument = false; Options.EnableEmailHyperlinks = false; Options.EnableHyperlinks = false; // Don't use rounded corners for selection rectangles. TextArea.SelectionCornerRadius = 0; TextArea.SelectionBorder = null; } private void SetupStableRenderers() { hoverHighlighter_ = new ElementHighlighter(HighlighingType.Hovered); selectedHighlighter_ = new ElementHighlighter(HighlighingType.Selected); markedHighlighter_ = new ElementHighlighter(HighlighingType.Marked); diffHighlighter_ = new DiffLineHighlighter(); TextArea.TextView.BackgroundRenderers.Add(diffHighlighter_); TextArea.TextView.BackgroundRenderers.Add(markedHighlighter_); TextArea.TextView.BackgroundRenderers.Add(selectedHighlighter_); TextArea.TextView.BackgroundRenderers.Add(hoverHighlighter_); } private void SetupRenderers() { // Highlighting of current line. if (lineHighlighter_ != null) { TextArea.TextView.BackgroundRenderers.Remove(lineHighlighter_); lineHighlighter_ = null; } if (blockHighlighter_ != null) { TextArea.TextView.BackgroundRenderers.Remove(blockHighlighter_); blockHighlighter_ = null; } if (settings_.ShowBlockSeparatorLine) { blockHighlighter_ = new BlockBackgroundHighlighter(settings_.ShowBlockSeparatorLine, settings_.BlockSeparatorColor, settings_.BackgroundColor, settings_.AlternateBackgroundColor); TextArea.TextView.BackgroundRenderers.Insert(0, blockHighlighter_); if (Function != null) { SetupBlockHighlighter(); } } if (margin_ != null) { margin_.BackgroundColor = settings_.MarginBackgroundColor; } else { margin_ = new DocumentMargin(settings_.MarginBackgroundColor); TextArea.LeftMargins.Add(margin_); } if (remarkHighlighter_ != null) { TextArea.TextView.BackgroundRenderers.Remove(remarkHighlighter_); } remarkHighlighter_ = new RemarkHighlighter(HighlighingType.Marked); TextArea.TextView.BackgroundRenderers.Add(remarkHighlighter_); if (overlayRenderer_ != null) { TextArea.TextView.BackgroundRenderers.Remove(overlayRenderer_); TextArea.TextView.Layers.Remove(overlayRenderer_); } // Create the overlay and place it on top of the text. overlayRenderer_ ??= new OverlayRenderer(markedHighlighter_); overlayRenderer_.TextFont = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch); TextArea.TextView.BackgroundRenderers.Add(overlayRenderer_); TextArea.TextView.InsertLayer(overlayRenderer_, KnownLayer.Text, LayerInsertionPosition.Above); if (DiffModeEnabled) { if (diffHighlighter_ != null) { diffHighlighter_.Clear(); TextArea.TextView.BackgroundRenderers.Remove(diffHighlighter_); } if (diffSegments_ != null) { // Insert below the marker renderer so that marked, // selected and hovered elements get the usual highlighting. diffHighlighter_ = new DiffLineHighlighter(); int index = TextArea.TextView.BackgroundRenderers.IndexOf(markedHighlighter_); if (index != -1) { TextArea.TextView.BackgroundRenderers.Insert(index, diffHighlighter_); } else { TextArea.TextView.BackgroundRenderers.Add(diffHighlighter_); } // AvalonEdit text segments cannot be reused, even when removed from the // segment collection, since they are left with internal fields referencing // the old tree data struct and adding them to another collection would fail. // Make a copy of each segment as a workaround. diffSegments_ = diffSegments_.ConvertAll(segment => new DiffTextSegment(segment)); StartDiffSegmentAdding(); AddDiffTextSegments(diffSegments_); AllDiffSegmentsAdded(); } } if (settings_.HighlightCurrentLine) { lineHighlighter_ = new CurrentLineHighlighter(this, settings_.CurrentLineBorderColor); TextArea.TextView.BackgroundRenderers.Add(lineHighlighter_); } } private HighlightingStyle GetRemarkLineStyle(Remark remark, bool hasContextFilter, bool isSelected = false) { //? TODO: Caching of the style if (hasContextFilter) { // Use the background of the remark with the same bold pen for all kinds. var backColor = remark.Category.MarkColor; if (backColor == Colors.Black || backColor == Colors.Transparent) { backColor = Colors.LightGray; } var borderColor = Colors.Black; double borderWeight = Math.Max(2, remark.Category.TextMarkBorderWeight); return new HighlightingStyle(backColor, ColorPens.GetPen(borderColor, borderWeight)); } return new HighlightingStyle(remark.Category.MarkColor, ColorPens.GetPen(remark.Category.TextMarkBorderColor, remark.Category.TextMarkBorderWeight)); } private HighlightingStyle GetRemarkBookmarkStyle(Remark remark, bool hasContextFilter) { //? TODO: Caching return new HighlightingStyle(remark.Category.MarkColor); } private void AddMarginRemarks(List markerRemarksGroups, bool hasContextFilter) { foreach (var remarkGroup in markerRemarksGroups) { bool groupHandled = false; foreach (var remark in remarkGroup.Remarks) { foreach (var element in remark.ReferencedElements) { // Add a single marker for all remarks mapping to the same line (group). if (remark.Category.AddLeftMarginMark && !groupHandled) { var style = GetRemarkBookmarkStyle(remarkGroup.LeaderRemark, hasContextFilter); var bookmark = new Bookmark(0, element, remarkGroup.LeaderRemark.RemarkText, style); margin_.AddRemarkBookmark(bookmark, remarkGroup); groupHandled = true; break; } } if (groupHandled) { break; } } } } private void AddDocumentRemarks(List allRemarks, bool hasContextFilter) { var markedElements = new HashSet>(allRemarks.Count); foreach (var remark in allRemarks) { foreach (var element in remark.ReferencedElements) { if (remark.Category.AddTextMark || hasContextFilter) { // Mark each element only once with the same kind of remark. var elementKindPair = new Tuple(element, remark.Kind); if (!markedElements.Contains(elementKindPair)) { var style = GetRemarkLineStyle(remark, hasContextFilter); var group = new HighlightedElementGroup(element, style); remarkHighlighter_.Add(group); markedElements.Add(elementKindPair); } } } } } private async Task ShowDefinitionPreview(IRElement element, bool alwaysShow = false) { if (settings_ is not DocumentSettings docSettings) { return false; } IRElement target = null; bool isCallTarget = false; bool show = false; if (!alwaysShow) { if (!docSettings.ShowPreviewPopup) { HidePreviewPopup(); return false; } } if (element is OperandIR op) { if (op.IsLabelAddress) { target = op.BlockLabelValue; show = target != null && (alwaysShow || IsElementOutsideView(target)); } else if (op.ParentInstruction != null) { if (op.Equals(Session.CompilerInfo.IR.GetCallTarget(op.ParentInstruction))) { target = op; isCallTarget = true; show = true; } } if (target == null) { var refFinder = CreateReferenceFinder(); target = refFinder.FindSingleDefinition(op); show = target != null && (alwaysShow || IsElementOutsideView(target)); } } // Show the preview only if outside the current view. if (show) { await ShowPreviewPopup(target, isCallTarget, alwaysShow); return true; } return false; } private bool IsCallTargetElement(IRElement element) { if (element is OperandIR op && op.ParentInstruction != null) { return op.Equals(Session.CompilerInfo.IR.GetCallTarget(op.ParentInstruction)); } return false; } private void ShowReferencesExecuted(object sender, ExecutedRoutedEventArgs e) { var selectedOp = GetSelectedElement(); if (selectedOp is OperandIR op) { ShowReferences(op); MirrorAction(DocumentActionKind.ShowReferences, selectedOp); } } private void ShowExpressionGraphExecuted(object sender, ExecutedRoutedEventArgs e) { var element = GetSelectedElement(); if (element != null) { ShowExpressionGraph(element); } } private void ShowExpressionGraph(IRElement element) { var action = new DocumentAction(DocumentActionKind.ShowExpressionGraph, element); ActionPerformed?.Invoke(this, action); } private void ShowReferences(OperandIR op) { Session.ShowAllReferences(op, this); } private async Task ShowPreviewPopup(IRElement element, bool isCallTarget = false, bool alwaysShow = false) { if (element == null || preparingPreviewPopup_) { return; // Valid case for search results. } // Close current popup. if (previewPopup_ != null) { if (previewPopup_.PreviewedElement == element) { return; // Already showing preview for this element. } HidePreviewPopup(); } if (ignoreNextPreviewElement_ == element) { return; } // Try to create a popup for the element. var position = Mouse.GetPosition(TextArea.TextView).AdjustForMouseCursor(); preparingPreviewPopup_ = true; // Prevent another popup to be created due to await. if (isCallTarget) { previewPopup_ = await CreateCallTargetPreviewPopup(element, alwaysShow, position); } else { previewPopup_ = await CreateElementPreviewPopup(element, position); } preparingPreviewPopup_ = false; if (previewPopup_ != null) { previewPopup_.PopupDetached += Popup_PopupDetached; previewPopup_.ShowPopup(); if (alwaysShow) { // Keep open when triggered manually from UI or shortcut. previewPopup_.DetachPopup(); } } } private async Task CreateElementPreviewPopup(IRElement element, Point position) { return await IRDocumentPopup.CreateNew(this, element, position, this, App.Settings.GetElementPreviewPopupSettings(ToolPanelKind.Other)); } private async Task CreateCallTargetPreviewPopup(IRElement element, bool alwaysShow, Point position) { // Try to find a function definition for the call. var targetSection = DocumentUtils.FindCallTargetSection(element, Section, Session); if (targetSection == null) { if (alwaysShow) { Utils.ShowWarningMessageBox($"Couldn't find call target in opened document:\n{element.Name}", this); } return null; } var result = await Session.LoadAndParseSection(targetSection); if (result == null) return null; return await IRDocumentPopup.CreateNew(result, position, this, Session, App.Settings.PreviewPopupSettings, $"Function: {element.Name}"); } private void Popup_PopupDetached(object sender, EventArgs e) { var popup = (IRDocumentPopup)sender; if (popup == previewPopup_) { previewPopup_ = null; // Prevent automatic closing. } } private void ShowUsesExecuted(object sender, ExecutedRoutedEventArgs e) { var defOp = GetSelectedElementDefinition(); if (defOp != null) { ShowUses(defOp); MirrorAction(DocumentActionKind.ShowUses, defOp); } } private void ShowUses(OperandIR defOp) { Session.ShowSSAUses(defOp, this); } private void IRDocument_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (updateSuspended_) { return; } var position = e.GetPosition(TextArea.TextView); // Ignore click outside the text view, such as the right marker bar. if (position.X <= 0 || position.X >= TextArea.TextView.ActualWidth || position.Y >= TextArea.TextView.ActualHeight) { return; } // Ignore click on a bookmark. if (margin_.HasHoveredBookmark()) { return; } Focus(); HideTemporaryUI(); // Check if there is any overlay being clicked // and don't propagate event to elements if it is. if (overlayRenderer_.MouseClick(e)) { e.Handled = true; return; } var element = FindPointedElement(position, out int textOffset); SelectElement(element, true, true, textOffset); selectingText_ = true; //? TODO: This would prevent selection of text from working, //? but allowing it also sometimes selects a letter of the element... // e.Handled = element != null; } private void SetupElementOverlayEvents(IElementOverlay overlay) { overlay.OnKeyPress += ElementOverlay_OnKeyPress; overlay.OnClick += ElementOverlay_OnClick; } private void ElementOverlay_OnClick(object sender, MouseEventArgs e) { var overlay = (IElementOverlay)sender; SelectElement(overlay.Element); } private void ElementOverlay_OnKeyPress(object sender, KeyEventArgs e) { if (e.Key == Key.Delete) { overlayRenderer_.RemoveElementOverlay((IElementOverlay)sender); } } private void UpdateHighlighting() { if (updateSuspended_ || !IsLoaded) { return; } PopulateMarkerBar(); TextArea.TextView.Redraw(); } private void UpdateMargin() { if (updateSuspended_) { return; } margin_.InvalidateVisual(); } public void Redraw() { UpdateHighlighting(); UpdateMargin(); } private class MarkerMarginVersionInfo { public int LastBlockMarginVersion; public int LastBookmarkVersion; public int LastDiffVersion; public int LastHoveredVersion; public int LastMarkedVersion; public int LastSelectedVersion; public int LastOverlayVersion; public bool NeedsRedrawing; } private class MarkerBarElement { public IRElement Element { get; set; } public HighlightingStyle Style { get; set; } public Rect Visual { get; set; } public bool HandlesInput { get; set; } } } ================================================ FILE: src/ProfileExplorerUI/Document/IRDocumentColumnData.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Text; using System.Web; using System.Windows; using System.Windows.Media; using ClosedXML.Excel; using HtmlAgilityPack; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; using HtmlDocument = HtmlAgilityPack.HtmlDocument; namespace ProfileExplorer.UI; public class IRDocumentColumnData { public IRDocumentColumnData(int capacity = 0) { Columns = new List(); Rows = new Dictionary(capacity); ColumnValues = new Dictionary>(new ColumnComparer()); } public List Columns { get; set; } public Dictionary Rows { get; set; } public Dictionary> ColumnValues { get; set; } public bool HasData => Rows.Count > 0; public OptionalColumn MainColumn => Columns.Find(column => column.IsMainColumn); public void ExportColumnsToExcel(IRElement tuple, IXLWorksheet ws, int rowId, int columnId) { foreach (var column in Columns) { var value = GetColumnValue(tuple, column); if (value != null) { ws.Cell(rowId, columnId).Value = value.Text.Replace(" ms", ""); if (value.BackColor != null && value.BackColor is SolidColorBrush colorBrush) { var color = XLColor.FromArgb(colorBrush.Color.A, colorBrush.Color.R, colorBrush.Color.G, colorBrush.Color.B); ws.Cell(rowId, columnId).Style.Fill.BackgroundColor = color; if (column.IsMainColumn) { ws.Cell(rowId, 1).Style.Fill.BackgroundColor = color; ws.Cell(rowId, 2).Style.Fill.BackgroundColor = color; } } if (value.TextWeight != FontWeights.Normal) { ws.Cell(rowId, columnId).Style.Font.Bold = true; if (column.IsMainColumn) { ws.Cell(rowId, 1).Style.Font.Bold = true; ws.Cell(rowId, 2).Style.Font.Bold = true; } } } columnId++; } } public void ExportColumnsAsHTML(IRElement tuple, HtmlDocument doc, HtmlNode tr) { string CellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:500px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-size:14px;font-family:Arial, sans-serif;"; foreach (var column in Columns) { var value = GetColumnValue(tuple, column); var td = doc.CreateElement("td"); string style = CellStyle; if (value != null) { td.InnerHtml = HttpUtility.HtmlEncode(value.Text); if (value.BackColor is SolidColorBrush colorBrush) { style += $"background-color:{Utils.ColorToString(colorBrush.Color)};"; } if (value.TextWeight != FontWeights.Normal) { style += $"font-weight:bold;"; } } // Apply main column style for entire row. if (column.IsMainColumn && tr.ChildNodes.Count >= 2) { tr.ChildNodes[0].SetAttributeValue("style", style); tr.ChildNodes[1].SetAttributeValue("style", style); } td.SetAttributeValue("style", style); tr.AppendChild(td); } } public void ExportColumnsAsMarkdown(IRElement tuple, StringBuilder sb) { foreach (var column in Columns) { var value = GetColumnValue(tuple, column); string text = value != null ? value.Text : ""; sb.Append($" {text} |"); } } public OptionalColumn AddColumn(OptionalColumn column) { // Make a clone so that changing values such as the width // doesn't modify the column template. var columnClone = (OptionalColumn)column.Clone(); if (!string.IsNullOrEmpty(column.Style.AlternateTitle)) { columnClone.Title = column.Style.AlternateTitle; } Columns.Add(columnClone); return columnClone; } public OptionalColumn GetColumn(OptionalColumn templateColumn) { return Columns.Find(column => column.ColumnName == templateColumn.ColumnName); } public ElementRowValue AddValue(ElementColumnValue value, IRElement element, OptionalColumn column) { if (!Rows.TryGetValue(element, out var rowValues)) { rowValues = new ElementRowValue(element); Rows[element] = rowValues; } rowValues.ColumnValues[column] = value; value.Element = element; AddColumnValue(value, column); return rowValues; } public void AddColumnValue(ElementColumnValue value, OptionalColumn column) { if (!ColumnValues.TryGetValue(column, out var list)) { list = new List(); ColumnValues[column] = list; } list.Add(value); } public ElementRowValue GetValues(IRElement element) { if (Rows.TryGetValue(element, out var valueGroup)) { return valueGroup; } return null; } public void AddRow(ElementRowValue rowValues, IRElement element) { rowValues.Element = element; Rows[element] = rowValues; } public ElementColumnValue GetColumnValue(IRElement element, OptionalColumn column) { var values = GetValues(element); return values?[column]; } public void Reset() { } public class ColumnComparer : IEqualityComparer { public bool Equals(OptionalColumn x, OptionalColumn y) { if (ReferenceEquals(x, y)) return true; if (ReferenceEquals(x, null)) return false; if (ReferenceEquals(y, null)) return false; if (x.GetType() != y.GetType()) return false; return x.ColumnName == y.ColumnName; } public int GetHashCode(OptionalColumn obj) { return obj.ColumnName != null ? obj.ColumnName.GetHashCode() : 0; } } } // Represents a value in the row associated with an element. // Can be viewed as a cell in a spreadsheet. public sealed class ElementColumnValue : BindableObject { public static readonly ElementColumnValue Empty = new(string.Empty); private Thickness borderThickness_; private Brush borderBrush_; private string text_; private double minTextWidth_; private string toolTip_; private Brush textColor_; private Brush backColor_; private ImageSource icon_; private bool showPercentageBar_; private Brush percentageBarBackColor__; private double percentageBarBorderThickness_; private Brush percentageBarBorderBrush_; private FontWeight textWeight_; private double textSize_; private FontFamily textFont_; private bool canShowPercentageBar_; private double percentageBarMaxWidth_; private bool canShowBackgroundColor_; private bool canShowIcon_; public ElementColumnValue(string text, long value = 0, double valueValuePercentage = 0.0, int valueOrder = int.MaxValue, string tooltip = null) { Text = text; Value = value; ValuePercentage = valueValuePercentage; ValueOrder = valueOrder; TextWeight = FontWeights.Normal; TextColor = Brushes.Black; ToolTip = tooltip; CanShowPercentageBar = true; CanShowBackgroundColor = true; CanShowIcon = true; } public IRElement Element { get; set; } public long Value { get; set; } public double ValuePercentage { get; set; } public int ValueOrder { get; set; } public Thickness BorderThickness { get => borderThickness_; set => SetAndNotify(ref borderThickness_, value); } public Brush BorderBrush { get => borderBrush_; set => SetAndNotify(ref borderBrush_, value); } public string Text { get => text_; set => SetAndNotify(ref text_, value); } public double MinTextWidth { get => minTextWidth_; set => SetAndNotify(ref minTextWidth_, value); } public string ToolTip { get => toolTip_; set => SetAndNotify(ref toolTip_, value); } public Brush TextColor { get => textColor_; set => SetAndNotify(ref textColor_, value); } public Brush BackColor { get => backColor_; set => SetAndNotify(ref backColor_, value); } public bool CanShowBackgroundColor { get => canShowBackgroundColor_; set => SetAndNotify(ref canShowBackgroundColor_, value); } public bool CanShowIcon { get => canShowIcon_; set => SetAndNotify(ref canShowIcon_, value); } public ImageSource Icon { get => icon_; set { SetAndNotify(ref icon_, value); Notify(nameof(ShowIcon)); } } public bool ShowIcon => icon_ != null; public bool ShowPercentageBar { get => showPercentageBar_; set => SetAndNotify(ref showPercentageBar_, value); } public bool CanShowPercentageBar { get => canShowPercentageBar_; set => SetAndNotify(ref canShowPercentageBar_, value); } public Brush PercentageBarBackColor { get => percentageBarBackColor__; set => SetAndNotify(ref percentageBarBackColor__, value); } public double PercentageBarBorderThickness { get => percentageBarBorderThickness_; set => SetAndNotify(ref percentageBarBorderThickness_, value); } public Brush PercentageBarBorderBrush { get => percentageBarBorderBrush_; set => SetAndNotify(ref percentageBarBorderBrush_, value); } public double PercentageBarMaxWidth { get => percentageBarMaxWidth_; set => SetAndNotify(ref percentageBarMaxWidth_, value); } public FontWeight TextWeight { get => textWeight_; set => SetAndNotify(ref textWeight_, value); } public double TextSize { get => textSize_; set => SetAndNotify(ref textSize_, value); } public FontFamily TextFont { get => textFont_; set => SetAndNotify(ref textFont_, value); } } // Represents a set of values (by column) associated with an element. // Can be view as a row with cells in a spreadsheet. public sealed class ElementRowValue : BindableObject { private Brush backColor_; private Thickness borderThickness_; private Brush borderBrush_; public ElementRowValue(IRElement element) { Element = element; ColumnValues = new Dictionary(); } public IRElement Element { get; set; } public Dictionary ColumnValues { get; set; } public ICollection Values => ColumnValues.Values; public ICollection Columns => ColumnValues.Keys; public int Count => ColumnValues.Count; public Brush BackColor { get => backColor_; set => SetAndNotify(ref backColor_, value); } public Thickness BorderThickness { get => borderThickness_; set => SetAndNotify(ref borderThickness_, value); } public Brush BorderBrush { get => borderBrush_; set => SetAndNotify(ref borderBrush_, value); } public object Tag { get; set; } public ElementColumnValue this[OptionalColumn column] => ColumnValues.GetValueOrNull(column); public ElementColumnValue this[string columnName] { get { foreach (var pair in ColumnValues) { if (pair.Key.ColumnName == columnName) { return pair.Value; } } return null; } } } ================================================ FILE: src/ProfileExplorerUI/Document/IRDocumentHost.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Document/IRDocumentHost.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; using ICSharpCode.AvalonEdit.Folding; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Panels; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Profile.Document; using ProfileExplorer.UI.Query; using ProtoBuf; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.CallTree; namespace ProfileExplorer.UI; public static class DocumentHostCommand { public static readonly RoutedUICommand ShowSearch = new("Untitled", "ShowSearch", typeof(IRDocumentHost)); public static readonly RoutedUICommand ToggleSearch = new("Untitled", "ToggleSearch", typeof(IRDocumentHost)); public static readonly RoutedUICommand ShowSectionList = new("Untitled", "ShowSectionList", typeof(IRDocumentHost)); public static readonly RoutedUICommand PreviousSection = new("Untitled", "PreviousSection", typeof(IRDocumentHost)); public static readonly RoutedUICommand NextSection = new("Untitled", "NextSection", typeof(IRDocumentHost)); public static readonly RoutedUICommand SearchSymbol = new("Untitled", "SearchSymbol", typeof(IRDocumentHost)); public static readonly RoutedUICommand SearchSymbolAllSections = new("Untitled", "SearchSymbolAllSections", typeof(IRDocumentHost)); public static readonly RoutedUICommand JumpToProfiledElement = new("Untitled", "JumpToProfiledElement", typeof(IRDocumentHost)); public static readonly RoutedUICommand JumpToNextProfiledElement = new("Untitled", "JumpToNextProfiledElement", typeof(IRDocumentHost)); public static readonly RoutedUICommand JumpToPreviousProfiledElement = new("Untitled", "JumpToPreviousProfiledElement", typeof(IRDocumentHost)); public static readonly RoutedUICommand JumpToNextProfiledBlock = new("Untitled", "JumpToNextProfiledBlock", typeof(IRDocumentHost)); public static readonly RoutedUICommand JumpToPreviousProfiledBlock = new("Untitled", "JumpToPreviousProfiledBlock", typeof(IRDocumentHost)); public static readonly RoutedUICommand ExportFunctionProfile = new("Untitled", "ExportFunctionProfile", typeof(IRDocumentHost)); public static readonly RoutedUICommand ExportFunctionProfileHTML = new("Untitled", "ExportFunctionProfileHTML", typeof(IRDocumentHost)); public static readonly RoutedUICommand ExportFunctionProfileMarkdown = new("Untitled", "ExportFunctionProfileMarkdown", typeof(IRDocumentHost)); public static readonly RoutedUICommand CopySelectedLinesAsHTML = new("Untitled", "CopySelectedLinesAsHTML", typeof(IRDocumentHost)); public static readonly RoutedUICommand CopySelectedText = new("Untitled", "CopySelectedText", typeof(IRDocumentHost)); } [ProtoContract] public class IRDocumentHostState { [ProtoMember(1)] public IRDocumentState DocumentState; [ProtoMember(2)] public double HorizontalOffset; [ProtoMember(3)] public double VerticalOffset; public bool HasAnnotations => DocumentState.HasAnnotations; } public partial class IRDocumentHost : UserControl, INotifyPropertyChanged { private const double ActionPanelInitialOpacity = 0.5; private const int ActionPanelHeight = 20; private const double AnimationDuration = 0.1; private const int ActionPanelOffset = 15; private bool actionPanelHovered_; private bool actionPanelFromClick_; private bool actionPanelVisible_; private bool duringSwitchSearchResults_; private IRElement hoveredElement_; private Point hoverPoint_; private bool remarkOptionsPanelVisible_; private IRElement remarkElement_; private IRElement selectedElement_; private RemarkSettings remarkSettings_; private RemarkPreviewPanel remarkPanel_; private Point remarkPanelLocation_; private CancelableTaskInstance loadTask_; private bool remarkPanelVisible_; private bool searchPanelVisible_; private SectionSearchResult searchResult_; private IRElement selectedBlock_; private IUISession session_; private DocumentSettings settings_; private List remarkList_; private RemarkContext activeRemarkContext_; private List activeQueryPanels_; private QueryValue mainQueryInputValue_; private bool pasOutputVisible_; private bool columnsVisible_; private bool duringSectionSwitching_; private double previousVerticalOffset_; private List<(IRElement, TimeSpan)> profileElements_; private List<(BlockIR, TimeSpan)> profileBlocks_; private int profileElementIndex_; private int profileBlockIndex_; private OptionsPanelHostPopup remarkOptionsPanelPopup_; private OptionsPanelHostPopup optionsPanelPopup_; private DelayedAction delayedHideActionPanel_; private bool profileVisible_; private double columnsListItemHeight_; private ProfileDocumentMarker profileMarker_; private ProfileSampleFilter profileFilter_; private FunctionProfileData funcProfile_; private bool ignoreNextRowSelectedEvent_; private ProfileHistoryManager historyManager_; private MenuItem[] viewMenuItems_; public IRDocumentHost(IUISession session) { InitializeComponent(); DataContext = this; PassOutput.DataContext = this; ActionPanel.Visibility = Visibility.Collapsed; Session = session; remarkSettings_ = App.Settings.RemarkSettings; Settings = App.Settings.DocumentSettings; TextView.Initialize(Settings, Session); // Initialize pass output panel. PassOutput.Session = session; PassOutput.HasPinButton = false; PassOutput.HasDuplicateButton = false; PassOutput.DiffModeButtonVisible = false; PassOutput.SectionNameVisible = false; SetupEvents(); var hover = new MouseHoverLogic(this); hover.MouseHover += Hover_MouseHover; loadTask_ = new CancelableTaskInstance(false, Session.SessionState.RegisterCancelableTask, Session.SessionState.UnregisterCancelableTask); activeQueryPanels_ = new List(); profileFilter_ = new ProfileSampleFilter(); historyManager_ = new ProfileHistoryManager(() => { var state = new ProfileFunctionState(TextView.Section, TextView.Function, TextView.SectionText, profileFilter_); if (funcProfile_ != null) { state.Weight = funcProfile_.Weight; } return state; }, () => { UpdateHistoryMenu(); }); viewMenuItems_ = new[] { ViewMenuItem1, ViewMenuItem2, ViewMenuItem3 }; } public string TitlePrefix { get; set; } public string TitleSuffix { get; set; } public string DescriptionPrefix { get; set; } public string DescriptionSuffix { get; set; } public double ColumnsListItemHeight { get => columnsListItemHeight_; set { if (Math.Abs(columnsListItemHeight_ - value) > double.Epsilon) { columnsListItemHeight_ = value; NotifyPropertyChanged(nameof(ColumnsListItemHeight)); } } } public IUISession Session { get => session_; private set => session_ = value; } public DocumentSettings Settings { get => settings_; set { settings_ = value; ProfileColumns.Settings = value; ProfileColumns.ColumnSettings = value.ColumnSettings; ProfileViewMenu.DataContext = value.ColumnSettings; } } public RemarkSettings RemarkSettings { get => remarkSettings_; set { if (!value.Equals(remarkSettings_)) { remarkSettings_ = value.Clone(); NotifyPropertyChanged(nameof(ShowRemarks)); NotifyPropertyChanged(nameof(ShowPreviousSections)); } } } public bool ShowRemarks { get => remarkSettings_.ShowRemarks; set { if (value != remarkSettings_.ShowRemarks) { remarkSettings_.ShowRemarks = value; NotifyPropertyChanged(nameof(ShowRemarks)); HandleRemarkSettingsChange(); } } } public bool HasRemarks => remarkList_ is {Count: > 0}; public bool ShowPreviousSections { get => ShowRemarks && remarkSettings_.ShowPreviousSections; set { if (value != remarkSettings_.ShowPreviousSections) { remarkSettings_.ShowPreviousSections = value; NotifyPropertyChanged(nameof(ShowPreviousSections)); HandleRemarkSettingsChange(); } } } public IRTextSection Section => TextView.Section; public FunctionIR Function => TextView.Function; public bool PassOutputVisible { get => pasOutputVisible_; set { if (pasOutputVisible_ != value) { if (!pasOutputVisible_) { PassOutput.SwitchSection(Section, TextView); } pasOutputVisible_ = value; NotifyPropertyChanged(nameof(PassOutputVisible)); PassOutputVisibilityChanged?.Invoke(this, value); } } } public bool ColumnsVisible { get => columnsVisible_; set { if (columnsVisible_ != value) { columnsVisible_ = value; NotifyPropertyChanged(nameof(ColumnsVisible)); } } } public bool ProfileVisible { get => profileVisible_; set { if (profileVisible_ != value) { profileVisible_ = value; NotifyPropertyChanged(nameof(ProfileVisible)); } } } public bool HasPreviousFunctions => historyManager_.HasPreviousStates; public bool HasNextFunctions => historyManager_.HasNextStates; public bool HasProfileInstanceFilter => profileFilter_ is {HasInstanceFilter: true}; public bool HasProfileThreadFilter => profileFilter_ is {HasThreadFilter: true}; public RelayCommand CopyDocumentCommand => new(async obj => { await DocumentExporting.CopyAllLinesAsHtml(TextView); }); public event PropertyChangedEventHandler PropertyChanged; private void SetupEvents() { PassOutput.ScrollChanged += PassOutput_ScrollChanged; PassOutput.ShowBeforeOutputChanged += PassOutput_ShowBeforeOutputChanged; PreviewKeyDown += IRDocumentHost_PreviewKeyDown; TextView.PreviewMouseRightButtonDown += TextView_PreviewMouseRightButtonDown; TextView.MouseDoubleClick += TextViewOnMouseDoubleClick; TextView.PreviewMouseMove += TextView_PreviewMouseMove; TextView.PreviewMouseDown += TextView_PreviewMouseDown; TextView.BlockSelected += TextView_BlockSelected; TextView.ElementSelected += TextView_ElementSelected; TextView.ElementUnselected += TextView_ElementUnselected; TextView.GotKeyboardFocus += TextView_GotKeyboardFocus; TextView.CaretChanged += TextViewOnCaretChanged; TextView.TextArea.TextView.ScrollOffsetChanged += TextViewOnScrollOffsetChanged; TextView.TextArea.SelectionChanged += TextAreaOnSelectionChanged; TextView.TextRegionFolded += TextViewOnTextRegionFolded; TextView.TextRegionUnfolded += TextViewOnTextRegionUnfolded; TextView.FunctionCallOpen += TextViewOnFunctionCallOpen; SectionPanel.OpenSection += SectionPanel_OpenSection; SearchPanel.SearchChanged += SearchPanel_SearchChanged; SearchPanel.NavigateToPreviousResult += SearchPanel_NavigateToPreviousResult; SearchPanel.NavigateToNextResult += SearchPanel_NavigateToNextResult; SearchPanel.CloseSearchPanel += SearchPanel_CloseSearchPanel; ProfileColumns.ScrollChanged += ProfileColumns_ScrollChanged; ProfileColumns.RowSelected += ProfileColumn_RowSelected; Unloaded += IRDocumentHost_Unloaded; } private async void TextViewOnFunctionCallOpen(object sender, IRTextSection targetSection) { var targetFunc = targetSection.ParentFunction; ProfileSampleFilter targetFilter = null; if (profileFilter_ is {IncludesAll: false}) { targetFilter = profileFilter_.CloneForCallTarget(targetFunc); } historyManager_.ClearNextStates(); // Reset forward history. var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await Session.OpenProfileFunction(targetFunc, mode, targetFilter, this); } private void ProfileColumn_RowSelected(object sender, int line) { if (ignoreNextRowSelectedEvent_) { ignoreNextRowSelectedEvent_ = false; return; } TextView.SelectLine(line + 1); } private void TextViewOnTextRegionUnfolded(object sender, FoldingSection e) { ProfileColumns.HandleTextRegionUnfolded(e); } private void TextViewOnTextRegionFolded(object sender, FoldingSection e) { ProfileColumns.HandleTextRegionFolded(e); } private void ProfileColumns_ScrollChanged(object sender, ScrollChangedEventArgs e) { if (Math.Abs(e.VerticalChange) < double.Epsilon) { return; } TextView.ScrollToVerticalOffset(e.VerticalOffset); } public event EventHandler<(double offset, double offsetChangeAmount)> VerticalScrollChanged; public event EventHandler<(double offset, double offsetChangeAmount)> PassOutputVerticalScrollChanged; public event EventHandler PassOutputShowBeforeChanged; public event EventHandler PassOutputVisibilityChanged; public void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public async Task UpdateRemarkSettings(RemarkSettings newSettings) { RemarkSettings = newSettings; await HandleNewRemarkSettings(newSettings, false); } public async Task ReloadSettings(bool hasProfilingChanges = true) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); await HandleNewRemarkSettings(App.Settings.RemarkSettings, false, true); TextView.Initialize(settings_, session_); if (hasProfilingChanges) { await LoadProfile(); } } public async void UnloadSection(IRTextSection section, bool switchingActiveDocument) { // Cancel any running tasks and hide panels. using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (Section != section) { return; } if (!duringSwitchSearchResults_ && !switchingActiveDocument) { HideSearchPanel(); } await HideRemarkPanel(); HideActionPanel(); SaveSectionState(section); if (!switchingActiveDocument) { if (PassOutputVisible) { await PassOutput.UnloadSection(section, TextView); } // Clear references to IR objects that would keep the previous function alive. await RemoveRemarks(); hoveredElement_ = null; selectedElement_ = null; remarkElement_ = null; selectedBlock_ = null; profileFilter_ = new ProfileSampleFilter(); TitlePrefix = TitleSuffix = null; DescriptionPrefix = DescriptionSuffix = null; PassOutputVisible = false; BlockSelector.SelectedItem = null; BlockSelector.ItemsSource = null; } } public void OnSessionSave() { if (Section != null) { SaveSectionState(Section); } } public async Task SwitchSearchResultsAsync(SectionSearchResult searchResults, IRTextSection section, SearchInfo searchInfo) { // Ensure the right section is being displayed. duringSwitchSearchResults_ = true; var openArgs = new OpenSectionEventArgs(section, OpenSectionKind.ReplaceCurrent, this); await Session.SwitchDocumentSectionAsync(openArgs); duringSwitchSearchResults_ = false; // Show the search panel and mark all results on the document. searchResult_ = searchResults; searchInfo.CurrentResult = 1; searchInfo.ResultCount = searchResults.Results.Count; ShowSearchPanel(searchInfo); TextView.MarkSearchResults(searchResults.Results, Colors.Khaki); } public bool HasSameSearchResultSection(IRTextSection section) { if (Section != section) { return false; } // Force the search panel to be displayed in case it was closed. return searchPanelVisible_; } public void JumpToSearchResult(TextSearchResult result, int index) { if (index >= SearchPanel.SearchInfo.ResultCount) { return; } SearchPanel.SearchInfo.CurrentResult = index; TextView.JumpToSearchResult(result, Colors.LightSkyBlue); } public async Task LoadSectionMinimal(ParsedIRTextSection parsedSection) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); // Save state of currently loaded function for going back. if (TextView.IsLoaded) { historyManager_.SaveCurrentState(); TextView.UnloadDocument(); } TextView.PreloadSection(parsedSection); } public async Task LoadSection(ParsedIRTextSection parsedSection) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); duringSectionSwitching_ = true; object data = Session.LoadDocumentState(parsedSection.Section); double horizontalOffset = 0; double verticalOffset = 0; if (data != null) { var state = UIStateSerializer.Deserialize(data, parsedSection.Function); await TextView.LoadSavedSection(parsedSection, state.DocumentState); horizontalOffset = state.HorizontalOffset; verticalOffset = state.VerticalOffset; } else { await TextView.LoadSection(parsedSection); } if (PassOutputVisible) { await PassOutput.SwitchSection(parsedSection.Section, TextView); } PopulateBlockSelector(); await ReloadRemarks(task); // When applying profile, jump to hottest element // only if the vertical offset is 0. bool jumpToHottestElement = verticalOffset < double.Epsilon; if (parsedSection.LoadFailed || !await LoadProfile(true, jumpToHottestElement)) { await HideProfile(); } if (!jumpToHottestElement) { Dispatcher.BeginInvoke(() => { TextView.ScrollToHorizontalOffset(horizontalOffset); TextView.ScrollToVerticalOffset(verticalOffset); }, DispatcherPriority.Render); } duringSectionSwitching_ = false; } private void UpdateHistoryMenu() { NotifyPropertyChanged(nameof(HasPreviousFunctions)); NotifyPropertyChanged(nameof(HasNextFunctions)); DocumentUtils.CreateBackMenu(BackMenu, historyManager_.PreviousFunctions, BackMenuItem_OnClick, settings_, session_); } private async void BackMenuItem_OnClick(object sender, RoutedEventArgs e) { var state = ((MenuItem)sender)?.Tag as ProfileFunctionState; if (state != null) { historyManager_.RevertToState(state); await LoadPreviousSectionState(state); } } private async Task LoadPreviousSection() { var state = historyManager_.PopPreviousState(); if (state != null) { await LoadPreviousSectionState(state); } } private async Task LoadNextSection() { var state = historyManager_.PopNextState(); if (state != null) { await LoadPreviousSectionState(state); } } private async Task LoadPreviousSectionState(ProfileFunctionState state) { await session_.OpenDocumentSectionAsync( new OpenSectionEventArgs(state.Section, OpenSectionKind.ReplaceCurrent, this)); if (state.ProfileFilter is {IncludesAll: false}) { await SwitchProfileInstanceAsync(state.ProfileFilter); } } //? TODO: Create a new class to do the remark finding/filtering work public bool IsAcceptedRemark(Remark remark, IRTextSection section, RemarkSettings remarkSettings) { if (!remarkSettings.ShowPreviousSections && remark.Section != section) { return false; } //? TODO: Move SearchText into a state object if (!string.IsNullOrEmpty(remarkSettings.SearchedText)) { if (!remark.RemarkText.Contains(remarkSettings.SearchedText, StringComparison.OrdinalIgnoreCase)) { return false; } } bool kindResult = remark.Kind switch { RemarkKind.Analysis => remarkSettings.Analysis, RemarkKind.Optimization => remarkSettings.Optimization, RemarkKind.Default => remarkSettings.Default, RemarkKind.Verbose => remarkSettings.Verbose, RemarkKind.Trace => remarkSettings.Trace, _ => false }; if (!kindResult) { return false; } if (remark.Category.HasTitle && remarkSettings.HasCategoryFilters) { if (remarkSettings.CategoryFilter.TryGetValue(remark.Category.Title, out bool isCategoryEnabled)) { return isCategoryEnabled; } } return true; } public bool IsAcceptedContextRemark(Remark remark, IRTextSection section, RemarkSettings remarkSettings) { if (!IsAcceptedRemark(remark, section, remarkSettings)) { return false; } // Filter based on context, accept any context that is a child of the active context. if (activeRemarkContext_ != null) { return IsActiveContextTreeRemark(remark); } return true; } public bool IsActiveContextTreeRemark(Remark remark) { var context = remark.Context; while (context != null) { if (context == activeRemarkContext_) { Trace.TraceInformation($"=> Accept remark in context {remark.Context.Name}"); Trace.TraceInformation($" text \"{remark.RemarkText}\""); return true; } context = context.Parent; } return false; } public async Task EnterDiffMode() { if (Section != null) { SaveSectionState(Section); } await HideOptionalPanels(); TextView.EnterDiffMode(); } public async Task ExitDiffMode() { TextView.ExitDiffMode(); if (PassOutputVisible) { await PassOutput.RestorePassOutput(); } await HideOptionalPanels(); } public async Task LoadDiffedFunction(DiffMarkingResult diffResult, IRTextSection newSection) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); await TextView.LoadDiffedFunction(diffResult, newSection); if (PassOutputVisible) { await PassOutput.SwitchSection(newSection, TextView); } await ReloadRemarks(task); } public async Task LoadDiffedPassOutput(DiffMarkingResult diffResult) { if (PassOutputVisible) { await PassOutput.LoadDiffedPassOutput(diffResult); } } private void TextViewOnMouseDoubleClick(object sender, MouseButtonEventArgs e) { if (Utils.IsControlModifierActive()) { return; } SearchSymbolImpl(Utils.IsShiftModifierActive()); } private void TextViewOnCaretChanged(object? sender, int offset) { if (columnsVisible_) { ignoreNextRowSelectedEvent_ = true; var line = TextView.Document.GetLineByOffset(offset); ProfileColumns.SelectRow(line.LineNumber - 1); } } private void TextViewOnScrollOffsetChanged(object? sender, EventArgs e) { HideActionPanel(); DetachRemarkPanel(true); double offset = TextView.TextArea.TextView.VerticalOffset; double changeAmount = offset - previousVerticalOffset_; previousVerticalOffset_ = offset; // Sync scrolling with the optional columns. SyncColumnsVerticalScrollOffset(offset); VerticalScrollChanged?.Invoke(this, (offset, changeAmount)); } private void TextAreaOnSelectionChanged(object sender, EventArgs e) { if (funcProfile_ == null) { return; } // Compute the weight sum of the selected range of instructions // and display it in the main status bar. int startLine = TextView.TextArea.Selection.StartPosition.Line; int endLine = TextView.TextArea.Selection.EndPosition.Line; if (!ProfilingUtils.ComputeAssemblyWeightInRange(startLine, endLine, Function, funcProfile_, out var weightSum, out int count)) { Session.SetApplicationStatus(""); return; } double weightPercentage = funcProfile_.ScaleWeight(weightSum); string text = $"Selected {count}: {weightPercentage.AsPercentageString()} ({weightSum.AsMillisecondsString()})"; Session.SetApplicationStatus(text, "Sum of time for the selected instructions"); } private void SyncColumnsVerticalScrollOffset(double offset) { // Sync scrolling with the optional columns. if (columnsVisible_) { ProfileColumns.ScrollToVerticalOffset(offset); } } private async void HandleRemarkSettingsChange() { if (!remarkPanelVisible_ && !remarkOptionsPanelVisible_) { await HandleNewRemarkSettings(remarkSettings_, false, true); } } private async void IRDocumentHost_Unloaded(object sender, RoutedEventArgs e) { await HideRemarkPanel(true); } private async void TextView_PreviewMouseDown(object sender, MouseButtonEventArgs e) { await HideRemarkPanel(); // Handle the back/forward mouse buttons // to navigate through the function history. if (e.ChangedButton == MouseButton.XButton1) { e.Handled = true; await LoadPreviousSection(); return; } else if (e.ChangedButton == MouseButton.XButton2) { e.Handled = true; await LoadNextSection(); return; } var point = e.GetPosition(TextView.TextArea.TextView); var element = TextView.GetElementAt(point); if (element == null) { HideActionPanel(true); return; } if (element != hoveredElement_ && !actionPanelHovered_) { await ShowActionPanel(element, true); } // Middle-button click sets the input element in the active query panel. if (mainQueryInputValue_ != null && e.MiddleButton == MouseButtonState.Pressed) { mainQueryInputValue_.ForceValueUpdate(element); e.Handled = true; } } private async void TextView_PreviewMouseMove(object sender, MouseEventArgs e) { if (!actionPanelVisible_) { return; } var point = e.GetPosition(TextView.TextArea.TextView); var element = TextView.GetElementAt(point); if (!remarkPanelVisible_ && !actionPanelHovered_ && !actionPanelFromClick_) { if (element == null || element != hoveredElement_) { HideActionPanel(); await HideRemarkPanel(); } } } private async void Hover_MouseHover(object sender, MouseEventArgs e) { if (!remarkSettings_.ShowActionButtonOnHover || remarkSettings_.ShowActionButtonWithModifier && !Utils.IsKeyboardModifierActive()) { actionPanelHovered_ = false; return; } if (remarkPanelVisible_ || actionPanelHovered_) { return; } var point = e.GetPosition(TextView.TextArea.TextView); if (point.X <= 0 || point.Y <= 0) { // Don't consider the left margin and other elements outside the text view. return; } //? TODO: If other panels are opened over the document, don't consider their area. var element = TextView.GetElementAt(point); if (element != null) { // If the panel is already showing for this element, ignore the action // so that it doesn't move around after the mouse cursor. if (element != hoveredElement_) { await ShowActionPanel(element); hoveredElement_ = element; } } else { HideActionPanel(); hoveredElement_ = null; } } private async void TextView_ElementUnselected(object sender, IRElementEventArgs e) { HideActionPanel(true); await HideRemarkPanel(); } private async void TextView_ElementSelected(object sender, IRElementEventArgs e) { selectedElement_ = e.Element; await ShowActionPanel(e.Element); } private IRElement GetRemarkElement(IRElement element) { if (element.GetTag() != null) { return element; } // If it's an operand, check if the instr. has a remark instead. if (element is OperandIR op) { var instr = op.ParentTuple; if (instr.GetTag() != null) { return instr; } } return null; } private async Task ShowActionPanel(IRElement element, bool fromClickEvent = false) { remarkElement_ = GetRemarkElement(element); var visualElement = remarkElement_; if (remarkElement_ == null) { await HideRemarkPanel(); // If there are action buttons in the panel, keep showing it. if (!ActionPanel.HasActionButtons) { HideActionPanel(); return; } visualElement = element; ActionPanel.ShowRemarksButton = false; } else { ActionPanel.ShowRemarksButton = true; } var visualLine = TextView.TextArea.TextView.GetVisualLine(visualElement.TextLocation.Line + 1); if (visualLine != null) { // If there is an ongoing hiding operation, cancel it since it would // likely hide the action panel being set up here. if (delayedHideActionPanel_ != null) { delayedHideActionPanel_.Cancel(); delayedHideActionPanel_ = null; } var linePos = visualLine.GetVisualPosition(0, VisualYPosition.LineBottom); double x = Mouse.GetPosition(this).X + ActionPanelOffset; double y = linePos.Y + DocumentToolbar.ActualHeight - 1 - TextView.TextArea.TextView.ScrollOffset.Y; Canvas.SetLeft(ActionPanel, x); Canvas.SetTop(ActionPanel, y); ActionPanel.Opacity = 0.0; ActionPanel.Visibility = Visibility.Visible; var animation2 = new DoubleAnimation(ActionPanelInitialOpacity, TimeSpan.FromSeconds(fromClickEvent ? 0 : AnimationDuration)); ActionPanel.BeginAnimation(OpacityProperty, animation2, HandoffBehavior.SnapshotAndReplace); actionPanelFromClick_ = fromClickEvent; actionPanelVisible_ = true; remarkPanelLocation_ = new Point(x, y + ActionPanelHeight); } } private void HideActionPanel(bool force = false) { // Ignore if panel not visible or in process of being hidden. if (!actionPanelVisible_ || delayedHideActionPanel_ != null) { return; } if (force) { HideActionPanelImpl(); return; } delayedHideActionPanel_ = DelayedAction.StartNew(() => { if (remarkPanelVisible_ || ActionPanel.IsMouseOver) { return; } HideActionPanelImpl(); }); } private void HideActionPanelImpl() { var animation = new DoubleAnimation(0.0, TimeSpan.FromSeconds(AnimationDuration)); animation.Completed += (s, e) => { ActionPanel.Visibility = Visibility.Collapsed; }; ActionPanel.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); actionPanelVisible_ = false; delayedHideActionPanel_ = null; } private void ShowRemarkPanel() { if (remarkPanelVisible_ || remarkElement_ == null) { return; } remarkPanel_ = new RemarkPreviewPanel(); remarkPanel_.PopupClosed += RemarkPanel__PanelClosed; remarkPanel_.PopupDetached += RemarkPanel__PanelDetached; remarkPanel_.RemarkContextChanged += RemarkPanel__RemarkContextChanged; remarkPanel_.RemarkChanged += RemarkPanel__RemarkChanged; remarkPanel_.Opacity = 0.0; remarkPanel_.IsOpen = true; var animation = new DoubleAnimation(1.0, TimeSpan.FromSeconds(AnimationDuration)); remarkPanel_.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); remarkPanelVisible_ = true; InitializeRemarkPanel(remarkElement_); } private void RemarkPanel__RemarkChanged(object sender, Remark e) { TextView.SelectDocumentRemark(e); } private void RemarkPanel__PanelDetached(object sender, EventArgs e) { // Keep the remark panel floating over the document. DetachRemarkPanel(); } private void DetachRemarkPanel(bool notifyPanel = false) { if (remarkPanel_ == null) { return; } Session.RegisterDetachedPanel(remarkPanel_); HideActionPanel(); if (notifyPanel) { remarkPanel_.PopupDetached -= RemarkPanel__PanelDetached; remarkPanel_.DetachPanel(); } remarkPanelVisible_ = false; remarkPanel_ = null; } private async void RemarkPanel__PanelClosed(object sender, EventArgs e) { // If it's one of the detached panels, unregister it. var panel = (RemarkPreviewPanel)sender; if (panel.IsDetached) { Session.UnregisterDetachedPanel(panel); return; } await HideRemarkPanel(); } private async void RemarkPanel__RemarkContextChanged(object sender, RemarkContextChangedEventArgs e) { activeRemarkContext_ = e.Context; if (e.Context != null && e.Remarks != null) { await UpdateDocumentRemarks(e.Remarks); } else { // Filtering of context remarks disabled. await UpdateDocumentRemarks(remarkList_); } } private void InitializeRemarkPanel(IRElement element) { remarkPanel_.Session = Session; remarkPanel_.Function = Function; remarkPanel_.Section = Section; remarkPanel_.Initialize(element, remarkPanelLocation_, this, remarkSettings_); } private async Task HideRemarkPanel(bool force = false) { if (!remarkPanelVisible_) { return; } if (force) { remarkPanel_.IsOpen = false; remarkPanel_ = null; return; } await ResetActiveRemarkContext(); var animation = new DoubleAnimation(0.0, TimeSpan.FromSeconds(AnimationDuration)); animation.Completed += (s, e) => { if (remarkPanel_ != null) { // When section unloads, can be before animation completes. remarkPanel_.IsOpen = false; remarkPanel_ = null; } }; remarkPanel_.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); remarkPanelVisible_ = false; } private async Task ResetActiveRemarkContext() { if (activeRemarkContext_ != null) { activeRemarkContext_ = null; await UpdateDocumentRemarks(remarkList_); } } private async Task LoadNewSettings(DocumentSettings newSettings, bool force, bool commit) { if (force || !newSettings.Equals(Settings)) { bool hasProfilingChanges = newSettings.HasProfilingChanges(Settings); App.Settings.DocumentSettings = newSettings; Settings = newSettings; await ReloadSettings(hasProfilingChanges); } if (commit) { // Apply settings to other open documents in the session. await Session.ReloadDocumentSettings(newSettings, TextView); App.SaveApplicationSettings(); } } private void TextView_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { //CloseSectionPanel(); } private void SearchPanel_CloseSearchPanel(object sender, SearchInfo e) { HideSearchPanel(); } private void SearchPanel_NavigateToNextResult(object sender, SearchInfo e) { TextView.JumpToSearchResult(searchResult_.Results[e.CurrentResult], Colors.LightSkyBlue); } private void SearchPanel_NavigateToPreviousResult(object sender, SearchInfo e) { TextView.JumpToSearchResult(searchResult_.Results[e.CurrentResult], Colors.LightSkyBlue); } private async void IRDocumentHost_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) { CloseSectionPanel(); HideSearchPanel(); e.Handled = true; } else if (e.Key == Key.C && Utils.IsControlModifierActive()) { // Override Ctrl+C to copy instruction details instead of just text, // but not if Shift/Alt key is also pressed, copy plain text then. if (!Utils.IsAltModifierActive() && !Utils.IsShiftModifierActive() && !TextView.HandleOverlayKeyPress(e)) { // Send to overlays first. await DocumentExporting.CopySelectedLinesAsHtml(TextView); e.Handled = true; } } else if (e.Key == Key.Back) { if (Utils.IsKeyboardModifierActive()) { await LoadNextSection(); } else { await LoadPreviousSection(); } } else if (e.Key == Key.H && Utils.IsControlModifierActive()) { JumpToHottestProfiledElement(); } else if (e.Key == Key.F2) { if (Utils.IsShiftModifierActive()) { JumpToProfiledElement(1); } else { JumpToProfiledElement(-1); } } } private void SectionPanel_ClosePanel(object sender, EventArgs e) { CloseSectionPanel(); } private async void SectionPanel_OpenSection(object sender, OpenSectionEventArgs e) { SectionPanelHost.Visibility = Visibility.Collapsed; e.TargetDocument = this; await Session.SwitchDocumentSectionAsync(e); TextView.Focus(); } private void CloseSectionPanel() { if (SectionPanelHost.Visibility == Visibility.Visible) { SectionPanelHost.Visibility = Visibility.Collapsed; } } private async Task RemoveRemarks() { if (HasRemarks) { remarkList_ = null; activeRemarkContext_ = null; await UpdateDocumentRemarks(remarkList_); } } private void SaveSectionState(IRTextSection section) { // Annotations made in diff mode are not saved right now, // since the text and function IR can be different from the original function. if (TextView.DiffModeEnabled) { return; } var state = new IRDocumentHostState(); state.DocumentState = TextView.SaveState(); state.HorizontalOffset = TextView.HorizontalOffset; state.VerticalOffset = TextView.VerticalOffset; byte[] data = UIStateSerializer.Serialize(state, Function); Session.SaveDocumentState(data, section); Session.SetSectionAnnotationState(section, state.HasAnnotations); } private async Task LoadProfile(bool reloadFilterMenus = true, bool jumpToHottestElement = true) { if (Session.ProfileData == null) { return false; } UpdateProfileFilterUI(); var funcProfile = Session.ProfileData.GetFunctionProfile(Section.ParentFunction); if (funcProfile == null) { return false; } await MarkFunctionProfile(funcProfile); if (reloadFilterMenus) { ProfilingUtils.CreateInstancesMenu(InstancesMenu, Section, funcProfile, InstanceMenuItem_OnClick, InstanceMenuItem_OnRightClick, settings_, Session); ProfilingUtils.CreateThreadsMenu(ThreadsMenu, Section, funcProfile, ThreadMenuItem_OnClick, settings_, Session); } if (jumpToHottestElement && settings_.ProfileMarkerSettings.JumpToHottestElement) { JumpToHottestProfiledElement(); } return true; } private void InstanceMenuItem_OnRightClick(object sender, MouseButtonEventArgs e) { if (sender is MenuItem menuItem) { if (menuItem.Tag is ProfileCallTreeNode node) { Session.SelectProfileFunctionInPanel(node, ToolPanelKind.FlameGraph); Session.SelectProfileFunctionInPanel(node, ToolPanelKind.CallTree); e.Handled = true; } } } private async Task UpdateProfilingColumns() { var columnData = TextView.ProfileColumnData; ColumnsVisible = columnData is {HasData: true}; if (columnData == null || !columnData.HasData) { ProfileColumns.Reset(); ProfileBlocksMenu.Items.Clear(); return false; } ResetViewMenuItemEvents(); ProfileColumns.Settings = settings_; ProfileColumns.ColumnSettings = settings_.ColumnSettings; await ProfileColumns.Display(columnData, TextView); profileMarker_.UpdateColumnStyles(columnData, Function, TextView); ProfileColumns.UpdateColumnWidths(); ProfileColumns.ColumnSettingsChanged -= OnProfileColumnsOnColumnSettingsChanged; ProfileColumns.ColumnSettingsChanged += OnProfileColumnsOnColumnSettingsChanged; // Add the columns to the View menu. ProfileColumns.BuildColumnsVisibilityMenu(columnData, ProfileViewMenu, () => { // UpdateProfilingColumns handles reentrancy by calling ResetViewMenuItemEvents() // synchronously before any await, which unsubscribes the event handlers. _ = UpdateProfilingColumns(); }); SetViewMenuItemEvents(); return true; } private void SetViewMenuItemEvents() { foreach (var item in viewMenuItems_) { item.Checked += ViewMenuItem_OnCheckedChanged; item.Unchecked += ViewMenuItem_OnCheckedChanged; } } private void ResetViewMenuItemEvents() { foreach (var item in viewMenuItems_) { item.Checked -= ViewMenuItem_OnCheckedChanged; item.Unchecked -= ViewMenuItem_OnCheckedChanged; } } private async void OnProfileColumnsOnColumnSettingsChanged(object sender, OptionalColumn column) { ProfileDocumentMarker.UpdateColumnStyle(column, TextView.ProfileColumnData, Function, TextView, settings_.ProfileMarkerSettings, settings_.ColumnSettings); } private void CreateProfileBlockMenu(FunctionProfileData funcProfile, FunctionProcessingResult result) { profileBlocks_ = result.BlockSampledElements; var list = new List(result.BlockSampledElements.Count); double maxWidth = 0; ProfileBlocksMenu.Items.Clear(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings_.ProfileMarkerSettings; int order = 0; foreach (var (block, weight) in result.BlockSampledElements) { double weightPercentage = funcProfile.ScaleWeight(weight); if (!markerSettings.IsVisibleValue(order++, weightPercentage)) { break; } string prefixText = $"B{block.Number}"; string text = $"({markerSettings.FormatWeightValue(weight)})"; var value = new ProfileMenuItem(text, weight.Ticks, weightPercentage) { Element = block, PrefixText = prefixText, ToolTip = $"Line {block.TextLocation.Line + 1}", ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, Tag = list.Count, HeaderTemplate = valueTemplate }; item.Click += (sender, args) => { var menuItem = (MenuItem)sender; JumpToProfiledBlockAt((int)menuItem.Tag); }; ProfileBlocksMenu.Items.Add(item); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(prefixText, ref maxWidth, ProfileBlocksMenu); list.Add(value); } foreach (var value in list) { value.MinTextWidth = maxWidth; } } private void CreateProfileElementMenu(FunctionProfileData funcProfile, FunctionProcessingResult result) { var list = new List(result.SampledElements.Count); ProfileElementsMenu.Items.Clear(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings_.ProfileMarkerSettings; int order = 0; double maxWidth = 0; foreach (var (element, weight) in result.SampledElements) { double weightPercentage = funcProfile.ScaleWeight(weight); if (!markerSettings.IsVisibleValue(order++, weightPercentage)) { break; } string prefixText = DocumentUtils.GenerateElementPreviewText(element, TextView.SectionText, 50); string text = $"({markerSettings.FormatWeightValue(weight)})"; var value = new ProfileMenuItem(text, weight.Ticks, weightPercentage) { Element = element, PrefixText = prefixText, ToolTip = $"Line {element.TextLocation.Line + 1}", ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, Tag = list.Count, HeaderTemplate = valueTemplate }; item.Click += (sender, args) => { var menuItem = (MenuItem)sender; JumpToProfiledElementAt((int)menuItem.Tag); }; ProfileElementsMenu.Items.Add(item); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(prefixText, ref maxWidth, ProfileElementsMenu); list.Add(value); } foreach (var value in list) { value.MinTextWidth = maxWidth; } } private async Task ApplyProfileFilter() { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (profileFilter_ is {IncludesAll: false}) { await LoadProfileInstance(); } else { await LoadProfile(false); } // Apply the same filter in the Source File view. await Session.OpenProfileSourceFile(Section.ParentFunction, profileFilter_); TitlePrefix = ProfilingUtils.CreateProfileFilterTitle(profileFilter_, session_); DescriptionSuffix = "\n\n" + ProfilingUtils.CreateProfileFilterDescription(profileFilter_, Session); Session.UpdateDocumentTitles(); } public async Task SwitchProfileInstanceAsync(ProfileSampleFilter instanceFilter) { profileFilter_ = instanceFilter; ProfilingUtils.SyncInstancesMenuWithFilter(InstancesMenu, instanceFilter); ProfilingUtils.SyncThreadsMenuWithFilter(ThreadsMenu, instanceFilter); await LoadProfileInstance(); } private async Task LoadProfileInstance() { UpdateProfileFilterUI(); var instanceProfile = await ComputeInstanceProfile(); var funcProfile = instanceProfile.GetFunctionProfile(Section.ParentFunction); if (funcProfile == null) { return; } await MarkFunctionProfile(funcProfile); } private async Task ComputeInstanceProfile() { return await LongRunningAction.Start( async () => await Task.Run(() => Session.ProfileData. ComputeProfile(Session.ProfileData, profileFilter_, false)), TimeSpan.FromMilliseconds(500), "Filtering function instance", this, Session); } private void UpdateProfileFilterUI() { NotifyPropertyChanged(nameof(HasProfileInstanceFilter)); NotifyPropertyChanged(nameof(HasProfileThreadFilter)); } private async Task MarkFunctionProfile(FunctionProfileData funcProfile) { // Mark instructions. profileMarker_ = new ProfileDocumentMarker(funcProfile, Session.ProfileData, settings_.ProfileMarkerSettings, settings_.ColumnSettings, Session.CompilerInfo); await profileMarker_.Mark(TextView, Function, Section.ParentFunction); // Redraw the flow graphs, may have loaded before the marker set the node tags. Session.RedrawPanels(); if (TextView.ProfileProcessingResult != null) { var inlineeList = profileMarker_.GenerateInlineeList(TextView.ProfileProcessingResult); ProfilingUtils.CreateInlineesMenu(InlineesMenu, Section, inlineeList, funcProfile, InlineeMenuItem_OnClick, settings_, Session); CreateProfileBlockMenu(funcProfile, TextView.ProfileProcessingResult); CreateProfileElementMenu(funcProfile, TextView.ProfileProcessingResult); } UpdateDocumentTitle(funcProfile); profileElements_ = TextView.ProfileProcessingResult?.SampledElements; funcProfile_ = funcProfile; ProfileVisible = true; // Show optional columns with timing, counters, etc. // First remove any previous columns. await UpdateProfilingColumns(); } private void UpdateDocumentTitle(FunctionProfileData funcProfile) { // Update document tooltip. DescriptionPrefix = ProfilingUtils.CreateProfileFunctionDescription(funcProfile, settings_.ProfileMarkerSettings, Session) + "\n\n"; Session.UpdateDocumentTitles(); } private async Task HideProfile() { ProfileVisible = false; ColumnsVisible = false; ResetProfilingMenus(); } private void ResetProfilingMenus() { DocumentUtils.RemoveNonDefaultMenuItems(ProfileBlocksMenu); DocumentUtils.RemoveNonDefaultMenuItems(ProfileElementsMenu); DocumentUtils.RemoveNonDefaultMenuItems(InstancesMenu); DocumentUtils.RemoveNonDefaultMenuItems(ThreadsMenu); DocumentUtils.RemoveNonDefaultMenuItems(InlineesMenu); } private async Task ReloadRemarks(CancelableTask loadTask) { await RemoveRemarks(); // Loading remarks can take several seconds for very large functions, // this makes it possible to cancel the work if section switches. var prevRemarkList = remarkList_; remarkList_ = await FindRemarks(loadTask); if (loadTask.IsCanceled) { return; } if (HasRemarks) { await AddRemarks(remarkList_); } else if (prevRemarkList is {Count: > 0}) { TextView.RemoveRemarks(); } } private async Task> FindRemarks(CancelableTask cancelableTask) { var remarkProvider = Session.RemarkProvider; return await Task.Run(() => { var sections = remarkProvider.GetSectionList(Section, remarkSettings_.SectionHistoryDepth, remarkSettings_.StopAtSectionBoundaries); var document = Session.SessionState.FindLoadedDocument(Section); var options = new RemarkProviderOptions(); var results = remarkProvider.ExtractAllRemarks(sections, Function, document, options, cancelableTask); return results; }); } private async Task AddRemarks(List remarks) { await AddRemarkTags(remarks); await UpdateDocumentRemarks(remarks); } private (List, List) FilterDocumentRemarks(List remarks) { // Filter list based on selected options. var filteredList = new List(remarks.Count); foreach (var remark in remarks) { if (IsAcceptedContextRemark(remark, Section, remarkSettings_)) { filteredList.Add(remark); } } // Group remarks by element line number. var markerRemarksGroups = new List(remarks.Count); if (remarkSettings_.ShowMarginRemarks) { var markerRemarksMap = new Dictionary(remarks.Count); foreach (var remark in filteredList) { if (!remark.Category.AddLeftMarginMark) { continue; } if (remark.Section != Section) { // Remark is from previous section. Accept only if user wants // to see previous optimization remarks on the left margin. bool isAccepted = remark.Category.Kind == RemarkKind.Optimization && remarkSettings_.ShowPreviousOptimizationRemarks || remark.Category.Kind == RemarkKind.Analysis && remarkSettings_.ShowPreviousAnalysisRemarks; if (!isAccepted) { continue; } } bool handled = false; int elementLine = -1; foreach (var element in remark.ReferencedElements) { elementLine = element.TextLocation.Line; if (markerRemarksMap.TryGetValue(elementLine, out var remarkGroup)) { remarkGroup.Add(remark, Section); handled = true; break; } } if (!handled) { var remarkGroup = new RemarkLineGroup(elementLine, remark); markerRemarksMap[elementLine] = remarkGroup; markerRemarksGroups.Add(remarkGroup); } } } return (remarkSettings_.ShowDocumentRemarks ? filteredList : null, remarkSettings_.ShowMarginRemarks ? markerRemarksGroups : null); } private async Task UpdateDocumentRemarks(List remarks) { if (remarks == null || !remarkSettings_.ShowRemarks || !remarkSettings_.ShowMarginRemarks && !remarkSettings_.ShowDocumentRemarks) { TextView.RemoveRemarks(); // No remarks or disabled. return; } var (allRemarks, markerRemarksGroups) = await Task.Run(() => FilterDocumentRemarks(remarks)); TextView.UpdateRemarks(allRemarks, markerRemarksGroups, activeRemarkContext_ != null); } private void RemoveRemarkTags() { Function.ForEachElement(element => { element.RemoveTag(); return true; }); } private Task AddRemarkTags(List remarks) { return Task.Run(() => { RemoveRemarkTags(); foreach (var remark in remarks) { foreach (var element in remark.ReferencedElements) { var remarkTag = element.GetOrAddTag(); remarkTag.Remarks.Add(remark); } } }); } private async Task HideOptionalPanels() { HideSearchPanel(); HideActionPanel(); await HideRemarkPanel(); } private void TextView_BlockSelected(object sender, IRElementEventArgs e) { if (e.Element != selectedBlock_) { selectedBlock_ = e.Element; BlockSelector.SelectedItem = e.Element; } } private void PopulateBlockSelector() { if (TextView.Blocks != null) { var blockList = new CollectionView(TextView.Blocks); BlockSelector.ItemsSource = blockList; } else { BlockSelector.ItemsSource = null; } } private void TextView_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { hoverPoint_ = e.GetPosition(TextView.TextArea.TextView); TextView.SelectElementAt(hoverPoint_); } private void MenuItem_Click(object sender, RoutedEventArgs e) { TextView.ClearMarkedElementAt(hoverPoint_); } private void ComboBox_Loaded(object sender, RoutedEventArgs e) { if (sender is ComboBox control) { Utils.PatchComboBoxStyle(control); } } private void BlockSelector_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (duringSectionSwitching_ || e.AddedItems.Count != 1) { return; } var block = e.AddedItems[0] as BlockIR; // If the event triggers during loading the section, while the combobox is update, // ignore it, otherwise it selects the first block. if (block != selectedBlock_ && !TextView.DuringSectionLoading) { selectedBlock_ = block; TextView.GoToBlock(block); } } private void NextBlockExecuted(object sender, ExecutedRoutedEventArgs e) { TextView.GoToNextBlock(); } private void PreviousBlockExecuted(object sender, ExecutedRoutedEventArgs e) { TextView.GoToPreviousBlock(); } private void FocusBlockSelectorExecuted(object sender, ExecutedRoutedEventArgs e) { BlockSelector.Focus(); BlockSelector.IsDropDownOpen = true; } private void ToggleSearchExecuted(object sender, ExecutedRoutedEventArgs e) { ShowSearchPanel(true); } private void ShowSearchExecuted(object sender, ExecutedRoutedEventArgs e) { ShowSearchPanel(false); } private void ShowSearchPanel(bool fromKeyboardShortcut) { // Use selected text as initial search input. var info = new SearchInfo(); bool hasInitialText = false; if (TextView.SelectionLength > 1) { info.SearchedText = TextView.SelectedText; info.IsCaseInsensitive = true; hasInitialText = true; } if (!searchPanelVisible_) { ShowSearchPanel(info); } else if (fromKeyboardShortcut) { // For a subsequent keyboard shortcut press, // don't hide the visible panel, instead either use the new selected text, // or there is no selection, select the entire text in the search panel. SearchPanel.SearchInfo.SearchedText = info.SearchedText; SearchPanel.SearchInfo.IsCaseInsensitive = info.IsCaseInsensitive; SearchPanel.Show(SearchPanel.SearchInfo, SearchPanel.SearchInfo.SearchAll, !hasInitialText); } else { HideSearchPanel(); } } private void HideSearchPanel() { if (!searchPanelVisible_) { return; } searchPanelVisible_ = false; SearchPanel.Hide(); SearchPanel.Reset(); SearchPanel.Visibility = Visibility.Collapsed; SearchButton.IsChecked = false; } private void ShowSearchPanel(SearchInfo searchInfo, bool searchAll = false) { SearchPanel.Visibility = Visibility.Visible; SearchPanel.Show(searchInfo, searchAll); SearchButton.IsChecked = true; searchPanelVisible_ = true; } private void ShowSectionListExecuted(object sender, ExecutedRoutedEventArgs e) { if (SectionPanelHost.Visibility == Visibility.Visible) { SectionPanelHost.Visibility = Visibility.Collapsed; } else { SectionPanel.CompilerInfo = Session.CompilerInfo; SectionPanel.Session = Session; SectionPanel.Summary = Session.GetDocumentSummary(Section); SectionPanel.SelectSection(Section, true, true); SectionPanelHost.Visibility = Visibility.Visible; SectionPanelHost.Focus(); } } private void PreviousSectionExecuted(object sender, ExecutedRoutedEventArgs e) { Session.SwitchToPreviousSection(Section, TextView); TextView.Focus(); } private void NextSectionExecuted(object sender, ExecutedRoutedEventArgs e) { Session.SwitchToNextSection(Section, TextView); TextView.Focus(); } private void SearchSymbolExecuted(object sender, ExecutedRoutedEventArgs e) { SearchSymbolImpl(false); } private void SearchSymbolAllSectionsExecuted(object sender, ExecutedRoutedEventArgs e) { SearchSymbolImpl(true); } private void JumpToProfiledElement(IRElement element) { TextView.SetCaretAtElement(element); double offset = TextView.TextArea.TextView.VerticalOffset; SyncColumnsVerticalScrollOffset(offset); } private void SearchSymbolImpl(bool searchAllSections) { var element = TextView.GetSelectedElement(); if (element == null || !element.HasName) { return; } string symbolName = element.Name; var searchInfo = new SearchInfo(); searchInfo.SearchedText = symbolName; searchInfo.SearchAll = searchAllSections; ShowSearchPanel(searchInfo); } private async void SearchPanel_SearchChanged(object sender, SearchInfo info) { string searchedText = info.SearchedText.Trim(); if (searchedText.Length > 1) { searchResult_ = await Session.SearchSectionAsync(info, Section, TextView); if (!searchResult_.HasResults) { // Nothing found in the current document. info.ResultCount = 0; TextView.ClearSearchResults(); return; } info.ResultCount = searchResult_.Results.Count; TextView.MarkSearchResults(searchResult_.Results, Colors.Khaki); if (searchResult_.Results.Count > 0) { TextView.JumpToSearchResult(searchResult_.Results[0], Colors.LightSkyBlue); } } else if (searchedText.Length == 0) { // Reset search panel and markers. if (info.ResultCount > 0) { SearchPanel.Reset(); } await Session.SearchSectionAsync(info, Section, TextView); TextView.ClearSearchResults(); searchResult_ = null; } } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async void PanelToolbarTray_SettingsClicked(object sender, EventArgs e) { ShowOptionsPanel(); } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } FrameworkElement relativeElement = ProfileVisible ? ProfileColumns : TextView; optionsPanelPopup_ = OptionsPanelHostPopup.Create( Settings.Clone(), relativeElement, Session, async (newSettings, commit) => { if (!newSettings.Equals(Settings)) { await LoadNewSettings(newSettings, true, commit); } if (commit) { TextView.EnableOverlayEventHandlers(); } return newSettings.Clone(); }, () => optionsPanelPopup_ = null); } private void ShowRemarkOptionsPanel() { if (remarkOptionsPanelVisible_) { return; } // double width = Math.Max(RemarkOptionsPanel.MinimumWidth, // Math.Min(TextView.ActualWidth, RemarkOptionsPanel.DefaultWidth)); // double height = Math.Max(RemarkOptionsPanel.MinimumHeight, // Math.Min(TextView.ActualHeight, RemarkOptionsPanel.DefaultHeight)); // var position = new Point(RemarkOptionsPanel.LeftMargin, 0); // // remarkOptionsPanelPopup_ = new OptionsPanelHostPopup(new RemarkOptionsPanel(), // position, width, height, TextView, // remarkSettings_.Clone(), Session); // remarkOptionsPanelPopup_.PanelClosed += RemarkOptionsPanel_PanelClosed; // remarkOptionsPanelPopup_.PanelReset += RemarkOptionsPanel_PanelReset; // remarkOptionsPanelPopup_.SettingsChanged += RemarkOptionsPanel_SettingsChanged; // remarkOptionsPanelPopup_.IsOpen = true; remarkOptionsPanelVisible_ = true; } private async Task CloseRemarkOptionsPanel() { if (!remarkOptionsPanelVisible_) { return; } remarkOptionsPanelPopup_.IsOpen = false; remarkOptionsPanelPopup_.PanelClosed -= RemarkOptionsPanel_PanelClosed; remarkOptionsPanelPopup_.PanelReset -= RemarkOptionsPanel_PanelReset; remarkOptionsPanelPopup_.SettingsChanged -= RemarkOptionsPanel_SettingsChanged; var newSettings = (RemarkSettings)remarkOptionsPanelPopup_.Settings; await HandleNewRemarkSettings(newSettings, true); remarkOptionsPanelPopup_ = null; remarkOptionsPanelVisible_ = false; } private async Task HandleNewRemarkSettings(RemarkSettings newSettings, bool commit, bool force = false) { if (commit) { await Session.ReloadRemarkSettings(newSettings, TextView); App.Settings.RemarkSettings = newSettings; App.SaveApplicationSettings(); } // Toolbar remark buttons change remarkSettings_ directly, // force an update in this case since newSettings is remarkSettings_. if (force || !newSettings.Equals(remarkSettings_)) { await ApplyRemarkSettings(newSettings); } } private async Task ApplyRemarkSettings(RemarkSettings newSettings) { // If only the remark filters changed, don't recompute the list of remarks. bool rebuildRemarkList = remarkList_ == null || newSettings.ShowPreviousSections && (newSettings.StopAtSectionBoundaries != remarkSettings_.StopAtSectionBoundaries || newSettings.SectionHistoryDepth != remarkSettings_.SectionHistoryDepth); App.Settings.RemarkSettings = newSettings; await UpdateRemarkSettings(newSettings); if (rebuildRemarkList) { Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Find and load remarks"); await ReloadRemarks(loadTask_.CurrentInstance); } else { Trace.TraceInformation($"Document {ObjectTracker.Track(this)}: Load remarks"); await UpdateDocumentRemarks(remarkList_); } } private async void RemarkOptionsPanel_SettingsChanged(object sender, EventArgs e) { if (remarkOptionsPanelVisible_) { var newSettings = (RemarkSettings)remarkOptionsPanelPopup_.Settings; if (newSettings != null) { await HandleNewRemarkSettings(newSettings, false); remarkOptionsPanelPopup_.Settings = remarkSettings_.Clone(); } } } private async void RemarkOptionsPanel_PanelReset(object sender, EventArgs e) { await HandleNewRemarkSettings(new RemarkSettings(), true); remarkOptionsPanelPopup_.Settings = remarkSettings_.Clone(); } private async void RemarkOptionsPanel_PanelClosed(object sender, EventArgs e) { await CloseRemarkOptionsPanel(); } private void PassOutput_ScrollChanged(object sender, ScrollChangedEventArgs e) { PassOutputVerticalScrollChanged?.Invoke(this, (e.VerticalOffset, e.VerticalChange)); } private void PassOutput_ShowBeforeOutputChanged(object sender, bool e) { PassOutputShowBeforeChanged?.Invoke(this, e); } private void ActionPanel_MouseEnter(object sender, MouseEventArgs e) { var animation = new DoubleAnimation(1, TimeSpan.FromSeconds(AnimationDuration)); ActionPanel.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); actionPanelHovered_ = true; } private void ActionPanel_MouseLeave(object sender, MouseEventArgs e) { actionPanelHovered_ = false; } private async void MenuItem_Click_1(object sender, RoutedEventArgs e) { if (remarkOptionsPanelVisible_) { await CloseRemarkOptionsPanel(); } else { ShowRemarkOptionsPanel(); } } // private void QueryMenuItem_SubmenuOpened(object sender, RoutedEventArgs e) { // var defaultItems = DocumentUtils.SaveDefaultMenuItems(QueryMenuItem); // QueryMenuItem.Items.Clear(); // // // Append the available queries. // var queries = Session.CompilerInfo.BuiltinQueries; // // foreach (var query in queries) { // var item = new MenuItem { // Header = query.Name, // ToolTip = query.Description, // Tag = query // }; // // item.Click += QueryMenuItem_Click; // QueryMenuItem.Items.Add(item); // } // // // Add back the default menu items. // DocumentUtils.RestoreDefaultMenuItems(QueryMenuItem, defaultItems); // } private void QueryMenuItem_Click(object sender, RoutedEventArgs e) { var menuItem = (MenuItem)sender; var query = (QueryDefinition)menuItem.Tag; var queryPanel = CreateQueryPanel(); queryPanel.AddQuery(query); CreateQueryActionButtons(query.Data); } private QueryPanel CreateQueryPanel() { var documentHost = this; var position = new Point(); if (documentHost != null) { double left = documentHost.ActualWidth - QueryPanel.DefaultWidth - 32; double top = documentHost.ActualHeight - QueryPanel.DefaultHeight - 32; position = new Point(left, top); } var queryPanel = new QueryPanel(position, QueryPanel.DefaultWidth, QueryPanel.DefaultHeight, documentHost, Session); queryPanel.PanelActivated += QueryPanel_PanelActivated; queryPanel.PanelTitle = "Queries"; queryPanel.ShowAddButton = true; queryPanel.PopupClosed += QueryPanel_Closed; queryPanel.IsOpen = true; queryPanel.StaysOpen = true; SwitchActiveQueryPanel(queryPanel); Session.RegisterDetachedPanel(queryPanel); return queryPanel; } private void QueryPanel_PanelActivated(object sender, EventArgs e) { // Change action buttons when another query is activated. var panel = (QueryPanel)sender; SwitchActiveQueryPanel(panel); } private void SwitchActiveQueryPanel(QueryPanel panel) { if (activeQueryPanels_.Count > 0) { // Deactivate the currently active panel. var currentPanel = activeQueryPanels_[^1]; if (currentPanel != panel) { currentPanel.IsActivePanel = false; mainQueryInputValue_ = null; SetActiveQueryPanel(panel); } } else { SetActiveQueryPanel(panel); } } private void SetActiveQueryPanel(QueryPanel panel) { // Bring to end of list, which is the top of the "stack" of panels. activeQueryPanels_.Remove(panel); activeQueryPanels_.Add(panel); panel.IsActivePanel = true; if (panel.QueryCount > 0) { // Update the action panel buttons. CreateQueryActionButtons(panel.GetQueryAt(0).Data); } } private void QueryPanel_Closed(object sender, EventArgs e) { var queryPanel = (QueryPanel)sender; CloseQueryPanel(queryPanel); } private void CloseQueryPanel(QueryPanel queryPanel) { queryPanel.PopupClosed -= QueryPanel_Closed; queryPanel.IsOpen = false; Session.UnregisterDetachedPanel(queryPanel); // Update the active query. activeQueryPanels_.Remove(queryPanel); if (activeQueryPanels_.Count > 0) { SetActiveQueryPanel(activeQueryPanels_[^1]); } else { RemoveQueryActionButtons(); } } // private async void TaskMenuItem_SubmenuOpened(object sender, RoutedEventArgs e) { // var defaultItems = DocumentUtils.SaveDefaultMenuItems(TaskMenuItem); // TaskMenuItem.Items.Clear(); // // foreach (var action in Session.CompilerInfo.BuiltinFunctionTasks) { // AddFunctionTaskDefinitionMenuItem(action); // } // // // Since first loading the scripts takes 1-2 sec, // // temporarily add a menu entry to show initially in the menu. // var item = new MenuItem { // Header = "Loading scripts...", // IsEnabled = false // }; // // TaskMenuItem.Items.Add(item); // // var scriptTasks = await Task.Run(() => Session.CompilerInfo.ScriptFunctionTasks); // // foreach (var action in scriptTasks) { // AddFunctionTaskDefinitionMenuItem(action); // } // // DocumentUtils.RestoreDefaultMenuItems(TaskMenuItem, defaultItems); // TaskMenuItem.Items.Remove(item); // } // private void AddFunctionTaskDefinitionMenuItem(FunctionTaskDefinition action) { // var item = new MenuItem { // Header = action.TaskInfo.Name, // ToolTip = action.TaskInfo.Description, // Tag = action // }; // // item.Click += TaskActionMenuItem_Click; // TaskMenuItem.Items.Add(item); // } private async void TaskActionMenuItem_Click(object sender, RoutedEventArgs e) { var menuItem = (MenuItem)sender; var task = (FunctionTaskDefinition)menuItem.Tag; if (!await LoadDocumentTask(task)) { //? TODO: Error handling, message box } } private QueryPanel CreateFunctionTaskQueryPanel() { var documentHost = this; var position = new Point(); if (documentHost != null) { double left = documentHost.ActualWidth - QueryPanel.DefaultWidth - 32; double top = documentHost.ActualHeight - QueryPanel.DefaultHeight - 32; position = documentHost.PointToScreen(new Point(left, top)); } var queryPanel = new QueryPanel(position, QueryPanel.DefaultWidth, QueryPanel.DefaultHeight, documentHost, Session); Session.RegisterDetachedPanel(queryPanel); queryPanel.PanelTitle = "Function Tasks"; queryPanel.ShowAddButton = false; queryPanel.PopupClosed += FunctionTaskPanel_PopupClosed; queryPanel.IsOpen = true; queryPanel.StaysOpen = true; return queryPanel; } private void AddFunctionTaskPanelButtons(QueryPanel queryPanel, IFunctionTask taskInstance, QueryData optionsData) { optionsData.AddButton("Execute", async (sender, value) => { taskInstance.LoadOptionsFromValues(optionsData); taskInstance.SaveOptions(); await ExecuteFunctionTask(taskInstance, optionsData, queryPanel); }); optionsData.AddButton("Reset", (sender, value) => { taskInstance.ResetOptions(); taskInstance.SaveOptions(); // Force a refresh by recreating the query panel. var dummyQuery = queryPanel.GetQueryAt(0); dummyQuery.Data = taskInstance.GetOptionsValues(); AddFunctionTaskPanelButtons(queryPanel, taskInstance, dummyQuery.Data); }); } private async Task ExecuteFunctionTask(IFunctionTask taskInstance, QueryData optionsData, QueryPanel queryPanel) { var cancelableTask = new CancelableTask(); optionsData.ResetOutputValues(); if (!await taskInstance.Execute(Function, TextView, cancelableTask)) { string description = ""; if (taskInstance is ScriptFunctionTask scriptTask) { description = scriptTask.ScriptException != null ? scriptTask.ScriptException.Message : ""; } optionsData.SetOutputWarning("Task failed to execute!", description); } else if (!string.IsNullOrEmpty(taskInstance.ResultMessage)) { if (taskInstance.Result) { optionsData.SetOutputInfo(taskInstance.ResultMessage); } else { optionsData.SetOutputWarning(taskInstance.ResultMessage); } } if (!string.IsNullOrEmpty(taskInstance.OutputText)) { optionsData.ReplaceButton("View Output", async (sender, value) => { var view = new NotesPopup(new Point(queryPanel.HorizontalOffset, queryPanel.VerticalOffset + queryPanel.Height), 500, 200, null); view.Session = Session; Session.RegisterDetachedPanel(view); var button = (QueryButton)sender; button.IsEnabled = false; view.PanelTitle = "Function Task Output"; view.IsOpen = true; view.PopupClosed += (sender, value) => { //? TODO: Should save size of panel and use it next time view.IsOpen = false; button.IsEnabled = true; Session.UnregisterDetachedPanel(view); }; view.DetachPopup(); await view.SetText(taskInstance.OutputText, Function, Section, TextView, Session); }); } } private async Task LoadDocumentTask(FunctionTaskDefinition task) { var instance = task.CreateInstance(Session); if (instance == null) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to create function task instance for {task.TaskInfo.Name}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Warning); return false; } CreateFunctionTaskOptionsPanel(task, instance); return true; } private void CreateFunctionTaskOptionsPanel(FunctionTaskDefinition task, IFunctionTask instance) { QueryData optionsValues; if (task.TaskInfo.HasOptionsPanel) { optionsValues = instance.GetOptionsValues(); } else { optionsValues = new QueryData(); } var dummyQuery = new QueryDefinition(typeof(DummyQuery), task.TaskInfo.Name, task.TaskInfo.Description); dummyQuery.Data = optionsValues; var queryPanel = CreateFunctionTaskQueryPanel(); AddFunctionTaskPanelButtons(queryPanel, instance, optionsValues); queryPanel.AddQuery(dummyQuery); } private void CreateQueryActionButtons(QueryData optionsValues) { RemoveQueryActionButtons(); int actionButtonIndex = 1; foreach (var inputValue in optionsValues.InputValues) { if (inputValue.IsElement) { ActionPanel.AddActionButton($"{actionButtonIndex}", inputValue); if (actionButtonIndex == 1) { // Attach event only once if it's needed. ActionPanel.ActionButtonClicked += ActionPanel_ActionButtonClicked; mainQueryInputValue_ = inputValue; } actionButtonIndex++; } } } private void RemoveQueryActionButtons() { ActionPanel.ClearActionButtons(); mainQueryInputValue_ = null; } private void ActionPanel_ActionButtonClicked(object sender, ActionPanelButton e) { var inputValue = (QueryValue)e.Tag; if (hoveredElement_ != null) { inputValue.ForceValueUpdate(hoveredElement_); } if (selectedElement_ != null) { inputValue.ForceValueUpdate(selectedElement_); } } private void FunctionTaskPanel_PopupClosed(object sender, EventArgs e) { var queryPanel = (QueryPanel)sender; queryPanel.PopupClosed -= FunctionTaskPanel_PopupClosed; queryPanel.IsOpen = false; Session.UnregisterDetachedPanel(queryPanel); } private async void ActionPanel_RemarksButtonClicked(object sender, EventArgs e) { if (remarkPanelVisible_) { await HideRemarkPanel(); } else { ShowRemarkPanel(); } } private void CloseAllQueryPanelsMenuItem_Click(object sender, RoutedEventArgs e) { while (activeQueryPanels_.Count > 0) { CloseQueryPanel(activeQueryPanels_[0]); } } private void ColumnsList_ScrollChanged(object sender, ScrollChangedEventArgs e) { if (duringSectionSwitching_ || Math.Abs(e.VerticalChange) < double.Epsilon) { return; } TextView.ScrollToVerticalOffset(e.VerticalOffset); } private void JumpToProfiledElementExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToHottestProfiledElement(); } private void JumpToHottestProfiledElement() { Dispatcher.BeginInvoke(() => { if (!HasProfileElements()) { return; } profileElementIndex_ = 0; JumpToProfiledElement(profileElements_[profileElementIndex_].Item1); }, DispatcherPriority.Render); } private bool HasProfileElements() { return ProfileVisible && profileElements_ != null && profileElements_.Count > 0; } private bool HasProfileElement(int offset) { return ProfileVisible && profileElements_ != null && profileElementIndex_ + offset >= 0 && profileElementIndex_ + offset < profileElements_.Count; } private bool HasProfiledBlock(int offset) { return ProfileVisible && profileBlocks_ != null && profileBlockIndex_ + offset >= 0 && profileBlockIndex_ + offset < profileElements_.Count; } private void JumpToNextProfiledElementExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToProfiledElement(-1); } private void JumpToProfiledElement(int offset) { if (!HasProfileElement(offset)) { return; } profileElementIndex_ += offset; JumpToProfiledElement(profileElements_[profileElementIndex_].Item1); } private void JumpToProfiledElementAt(int index) { profileElementIndex_ = index; JumpToProfiledElement(0); } private void JumpToProfiledBlock(int offset) { if (!HasProfiledBlock(offset)) { return; } profileBlockIndex_ += offset; JumpToProfiledBlock(profileBlocks_[profileBlockIndex_].Item1); } private void JumpToProfiledBlockAt(int index) { profileBlockIndex_ = index; JumpToProfiledBlock(0); } private void JumpToProfiledBlock(BlockIR block) { TextView.GoToBlock(block); } private void JumpToPreviousProfiledElementExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToProfiledElement(1); } private void JumpToNextProfiledBlockExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToProfiledBlock(-1); } private void JumpToPreviousProfiledBlockExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToProfiledBlock(1); } private void JumpToNextProfiledElementCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = HasProfileElement(-1); } private void JumpToPreviousProfiledElementCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = HasProfileElement(1); } private void JumpToNextProfiledBlockCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = HasProfiledBlock(-1); } private void JumpToPreviousProfiledBlockCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = HasProfiledBlock(1); } private async void ExportFunctionProfileExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the function failed to load. } await DocumentExporting.ExportToExcelFile(TextView, DocumentExporting.ExportFunctionAsExcelFile); } private async void ExportFunctionProfileHtmlExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the function failed to load. } await DocumentExporting.ExportToHtmlFile(TextView, DocumentExporting.ExportFunctionAsHtmlFile); } private async void ExportFunctionProfileMarkdownExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the function failed to load. } await DocumentExporting.ExportToMarkdownFile(TextView, DocumentExporting.ExportFunctionAsMarkdownFile); } private async void CopySelectedLinesAsHtmlExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the function failed to load. } await DocumentExporting.CopySelectedLinesAsHtml(TextView); } private void CopySelectedTextExecuted(object sender, ExecutedRoutedEventArgs e) { TextView.Copy(); } private async void ViewMenuItem_OnCheckedChanged(object sender, RoutedEventArgs e) { await UpdateProfilingColumns(); } private async void InstanceMenuItem_OnClick(object sender, RoutedEventArgs e) { ProfilingUtils.HandleInstanceMenuItemChanged(sender as MenuItem, InstancesMenu, profileFilter_); await ApplyProfileFilter(); } private async void ThreadMenuItem_OnClick(object sender, RoutedEventArgs e) { ProfilingUtils.HandleThreadMenuItemChanged(sender as MenuItem, ThreadsMenu, profileFilter_); await ApplyProfileFilter(); } private async void InlineeMenuItem_OnClick(object sender, RoutedEventArgs e) { var inlinee = ((MenuItem)sender)?.Tag as InlineeListItem; if (inlinee != null && inlinee.ElementWeights is {Count: > 0}) { // Sort by weight and bring the hottest element into view. var elements = inlinee.SortedElements; TextView.SetCaretAtElement(elements[0]); TextView.SelectElements(elements); } } private async void OpenPopupButton_Click(object sender, RoutedEventArgs e) { if (Section == null) { return; //? TODO: Button should rather be disabled } await IRDocumentPopupInstance.ShowPreviewPopup(Section.ParentFunction, "", this, Session, profileFilter_); } private async void BackButton_Click(object sender, RoutedEventArgs e) { await LoadPreviousSection(); } private async void NextButton_Click(object sender, RoutedEventArgs e) { await LoadNextSection(); } private class DummyQuery : IElementQuery { public IUISession Session { get; } public bool Initialize(IUISession session) { return true; } public bool Execute(QueryData data) { return true; } } private async void PanelToolbarTray_OnHelpClicked(object sender, EventArgs e) { await HelpPanel.DisplayPanelHelp(ToolPanelKind.Other, Session); } } class RemarksButtonState : INotifyPropertyChanged { private RemarkSettings remarkSettings_; public RemarksButtonState(RemarkSettings settings) { remarkSettings_ = settings.Clone(); } public RemarkSettings Settings { get => remarkSettings_; set { if (!value.Equals(remarkSettings_)) { NotifyPropertyChanged(nameof(ShowRemarks)); NotifyPropertyChanged(nameof(ShowPreviousSections)); } remarkSettings_ = value.Clone(); } } public bool ShowRemarks { get => remarkSettings_.ShowRemarks; set { if (value != remarkSettings_.ShowRemarks) { remarkSettings_.ShowRemarks = value; NotifyPropertyChanged(nameof(ShowRemarks)); } } } public bool ShowPreviousSections { get => ShowRemarks && remarkSettings_.ShowPreviousSections; set { if (value != remarkSettings_.ShowPreviousSections) { remarkSettings_.ShowPreviousSections = value; NotifyPropertyChanged(nameof(ShowPreviousSections)); } } } public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } ================================================ FILE: src/ProfileExplorerUI/Document/IRDocumentState.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using ProfileExplorer.Core.Controls; using ProfileExplorer.UI.Document; using ProtoBuf; namespace ProfileExplorer.UI; [ProtoContract] public class IRDocumentState { [ProtoMember(5)] public byte[] Bookmarks; [ProtoMember(7)] public int CaretOffset; [ProtoMember(1)] public ElementHighlighterState HoverHighlighter; [ProtoMember(4)] public DocumentMarginState Margin; [ProtoMember(3)] public ElementHighlighterState MarkedHighlighter; [ProtoMember(6)] public List SelectedElements; [ProtoMember(2)] public ElementHighlighterState SelectedHighlighter; [ProtoMember(8)] public ElementOverlayState ElementOverlays; public bool HasAnnotations => MarkedHighlighter.HasAnnotations || Margin.HasAnnotations; } ================================================ FILE: src/ProfileExplorerUI/Document/LightIRDocument.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; using System.Windows.Media; using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Document; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.Utilities; // TODO: Clicking on scroll bar not working if there is an IR element under it, // that one should be ignored if in the scroll bar bounds. GraphPanel does thats namespace ProfileExplorer.UI; public sealed class LightIRDocument : TextEditor { public enum TextSearchMode { Mark, Filter } private ElementHighlighter elementMarker_; private List elements_; private HighlightingStyle elementStyle_; private FunctionIR function_; private ElementHighlighter hoverElementMarker_; private HighlightingStyle hoverElementStyle_; private object lockObject_; private string initialText_; private bool initialTextChanged_; private List> initialTextLines_; private IRElement prevSelectedElement_; private TextSearchMode searchMode_; private ElementHighlighter searchResultMarker_; private HighlightingStyle searchResultStyle_; private IRTextSection section_; private IRDocument associatedDocument_; private int selectedElementRefIndex_; private List selectedElementRefs_; private bool syntaxHighlightingLoaded_; private CancelableTask updateHighlightingTask_; private DiffLineHighlighter diffHighlighter_; private IRDocumentPopupInstance previewPopup_; private IUISession session_; public LightIRDocument() { lockObject_ = new object(); elements_ = new List(); elementStyle_ = new HighlightingStyle(Utils.ColorFromString("#FFFCDC")); hoverElementStyle_ = new HighlightingStyle(Utils.ColorFromString("#FFF487")); searchResultStyle_ = new HighlightingStyle(Colors.Khaki); //? TODO: Customize elementMarker_ = new ElementHighlighter(HighlighingType.Marked); hoverElementMarker_ = new ElementHighlighter(HighlighingType.Marked); searchResultMarker_ = new ElementHighlighter(HighlighingType.Marked); diffHighlighter_ = new DiffLineHighlighter(); TextArea.TextView.BackgroundRenderers.Add(diffHighlighter_); TextArea.TextView.BackgroundRenderers.Add(elementMarker_); TextArea.TextView.BackgroundRenderers.Add(searchResultMarker_); TextArea.TextView.BackgroundRenderers.Add(hoverElementMarker_); TextChanged += TextView_TextChanged; PreviewMouseLeftButtonDown += TextView_PreviewMouseLeftButtonDown; MouseLeave += TextView_MouseLeave; PreviewMouseMove += TextView_PreviewMouseMove; // Don't use rounded corners for selection rectangles. TextArea.SelectionCornerRadius = 0; TextArea.SelectionBorder = null; Options.EnableEmailHyperlinks = false; Options.EnableHyperlinks = false; } public IUISession Session { get => session_; set { session_ = value; SetupPreviewPopup(); } } public IRTextSection Section => section_; public FunctionIR Function => function_; public IRDocument AssociatedDocument => associatedDocument_; public TextSearchMode SearchMode { get => searchMode_; set => searchMode_ = value; } public void UnloadDocument() { initialText_ = null; section_ = null; function_ = null; Text = ""; } public async Task SwitchText(string text, FunctionIR function, IRTextSection section, IRDocument associatedDocument) { function_ = function; section_ = section; associatedDocument_ = associatedDocument; await SwitchText(text); } public async Task SwitchText(string text) { Text = text; await SwitchTextImpl(text); } public async Task SwitchDocument(TextDocument document, string text) { // Take ownership of the document and replace current text. document.SetOwnerThread(Thread.CurrentThread); Document = document; await SwitchTextImpl(text); } public void EnableIRSyntaxHighlighting() { if (!syntaxHighlightingLoaded_) { SyntaxHighlighting = Utils.LoadSyntaxHighlightingFile(App.GetSyntaxHighlightingFilePath()); syntaxHighlightingLoaded_ = true; } } public void ResetTextSearch() { RestoreInitialText(); IsReadOnly = false; UpdateHighlighting(); } public async Task> SearchText(SearchInfo info) { searchResultMarker_.Clear(); if (!info.HasSearchedText) { ResetTextSearch(); return null; } if (info.SearchedText.Length < 2) { UpdateHighlighting(); return null; } // Disable text editing while search is used. IsReadOnly = true; if (searchMode_ == TextSearchMode.Filter) { EnsureInitialTextLines(); string searchResult = await Task.Run(() => SearchAndFilterTextLines(info)); Text = searchResult; initialTextChanged_ = true; await UpdateElementHighlighting(); return null; } RestoreInitialText(); var searchResults = await Task.Run(() => TextSearcher.AllIndexesOf(initialText_, info.SearchedText, 0, info.SearchKind)); HighlightSearchResults(searchResults); return searchResults; } public void AddDiffTextSegments(List segments) { diffHighlighter_.Clear(); diffHighlighter_.Add(segments); UpdateHighlighting(); } public void RemoveDiffTextSegments() { diffHighlighter_.Clear(); UpdateHighlighting(); } internal void JumpToSearchResult(TextSearchResult result) { int line = Document.GetLineByOffset(result.Offset).LineNumber; ScrollToLine(line); } private void SetupPreviewPopup() { if (previewPopup_ != null) { previewPopup_.UnregisterHoverEvents(); previewPopup_ = null; } previewPopup_ = new IRDocumentPopupInstance(App.Settings.GetElementPreviewPopupSettings(ToolPanelKind.Other), Session); previewPopup_.SetupHoverEvents(this, HoverPreview.HoverDuration, () => { if (Session.CurrentDocument == null) { return null; } var position = Mouse.GetPosition(TextArea.TextView); var element = DocumentUtils.FindPointedElement(position, this, elements_); if (element != null) { var refFinder = new ReferenceFinder(Session.CurrentDocument.Function); var refElement = refFinder.FindEquivalentValue(element); if (refElement != null) { // Don't show tooltip when user switches between references. if (selectedElementRefs_ != null && refElement == prevSelectedElement_) { return null; } var refElementDef = refFinder.FindSingleDefinition(refElement); var tooltipElement = refElementDef ?? refElement; return PreviewPopupArgs.ForDocument(Session.CurrentDocument, tooltipElement, this, $"Preview"); } } return null; }); } private void TextView_MouseLeave(object sender, MouseEventArgs e) { hoverElementMarker_.Clear(); ForceCursor = false; UpdateHighlighting(); } private void TextView_PreviewMouseMove(object sender, MouseEventArgs e) { var position = e.GetPosition(TextArea.TextView); var element = DocumentUtils.FindPointedElement(position, this, elements_); hoverElementMarker_.Clear(); if (element != null) { hoverElementMarker_.Add(new HighlightedElementGroup(element, hoverElementStyle_)); ForceCursor = true; Cursor = Cursors.Arrow; } else { ForceCursor = false; selectedElementRefs_ = null; } UpdateHighlighting(); } private IRDocument FindTargetDocument() { if (associatedDocument_ != null && associatedDocument_.Section == section_) { return associatedDocument_; } if (Session?.CurrentDocument == null || Session?.CurrentDocument.Section == section_) { return Session.CurrentDocument; } return null; } private void TextView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { previewPopup_?.HidePreviewPopup(true); var position = e.GetPosition(TextArea.TextView); // Ignore click outside the text view. if (position.X >= TextArea.TextView.ActualWidth || position.Y >= TextArea.TextView.ActualHeight) { return; } var element = DocumentUtils.FindPointedElement(position, this, elements_); if (element != null) { var targetDocument = FindTargetDocument(); ReferenceFinder refFinder = null; IRElement refElement = null; if (element is InstructionIR instr) { var similarValueFinder = new SimilarValueFinder(function_); refElement = similarValueFinder.Find(instr); } else { refFinder = new ReferenceFinder(function_); refElement = refFinder.FindEquivalentValue(element); } if (refElement != null) { if (refFinder == null) { // Highlight an entire instruction. targetDocument.HighlightElement(refElement, HighlighingType.Hovered); selectedElementRefs_ = null; e.Handled = true; return; } // Cycle between all references of the operand. if (refElement != prevSelectedElement_) { selectedElementRefs_ = refFinder.FindAllSSAUsesOrReferences(refElement); selectedElementRefIndex_ = 0; prevSelectedElement_ = refElement; } if (selectedElementRefs_ == null) { return; } if (selectedElementRefIndex_ == selectedElementRefs_.Count) { selectedElementRefIndex_ = 0; // Cycle back to first ref. } var currentRefElement = selectedElementRefs_[selectedElementRefIndex_++]; targetDocument.HighlightElement(currentRefElement.Element, HighlighingType.Hovered); e.Handled = true; return; } } selectedElementRefs_ = null; prevSelectedElement_ = null; } private async void TextView_TextChanged(object sender, EventArgs e) { await UpdateElementHighlighting(); } private async Task SwitchTextImpl(string text) { initialText_ = text; initialTextChanged_ = false; EnableIRSyntaxHighlighting(); EnsureInitialTextLines(); if (function_ != null) { await UpdateElementHighlighting(); } } private async Task UpdateElementHighlighting() { // If there is another task running, cancel it and wait for it to complete // before starting a new task, this can happen when quickly changing sections. CancelableTask currentUpdateTask = null; lock (lockObject_) { if (updateHighlightingTask_ != null) { updateHighlightingTask_.Cancel(); currentUpdateTask = updateHighlightingTask_; } } if (currentUpdateTask != null) { await currentUpdateTask.WaitToCompleteAsync(); } elements_.Clear(); elementMarker_.Clear(); hoverElementMarker_.Clear(); searchResultMarker_.Clear(); UpdateHighlighting(); // When unloading a document, no point to start a new task. string currentText = initialTextChanged_ ? Text : initialText_; if (string.IsNullOrEmpty(currentText)) { return; } var defElements = new HighlightedElementGroup(elementStyle_); updateHighlightingTask_ = new CancelableTask(); await Task.Run(() => { lock (lockObject_) { if (updateHighlightingTask_.IsCanceled) { // Task got canceled in the meantime. updateHighlightingTask_.Complete(); return; } if (function_ == null || string.IsNullOrEmpty(currentText)) { // No function set yet or switching sections. return; } elements_ = ExtractTextOperands(currentText, function_, updateHighlightingTask_); foreach (var element in elements_) { defElements.Add(element); } } }); elementMarker_.Add(defElements); UpdateHighlighting(); } private List ExtractTextOperands(string text, FunctionIR function, CancelableTask cancelableTask) { var elements = new List(); var remarkProvider = Session.RemarkProvider; var options = new RemarkProviderOptions { FindOperandRemarks = false, IgnoreOverlappingOperandRemarks = true }; var remarks = remarkProvider.ExtractRemarks(text, function, section_, options, cancelableTask); if (cancelableTask.IsCanceled) { cancelableTask.Complete(); return elements; } foreach (var remark in remarks) { foreach (var element in remark.OutputElements) { elements.Add(element); } } cancelableTask.Complete(); return elements; } private void UpdateHighlighting() { TextArea.TextView.Redraw(); } private void RestoreInitialText() { if (initialTextChanged_) { Text = initialText_; initialTextChanged_ = false; } initialTextLines_ = null; } private void HighlightSearchResults(List searchResults) { var group = new HighlightedElementGroup(searchResultStyle_); foreach (var result in searchResults) { int line = Document.GetLineByOffset(result.Offset).LineNumber; var location = new ProfileExplorer.Core.TextLocation(result.Offset, line, 0); var element = new IRElement(location, result.Length); group.Add(element); } if (!group.IsEmpty()) { searchResultMarker_.Add(group); UpdateHighlighting(); } } private void EnsureInitialTextLines() { if (initialTextLines_ == null) { initialText_ = Text; initialTextLines_ = new List>(Document.LineCount); foreach (var line in Document.Lines) { initialTextLines_.Add(new Tuple(line.Offset, line.Length)); } } } private string SearchAndFilterTextLines(SearchInfo info) { var builder = new StringBuilder(); var text = initialText_.AsSpan(); foreach (var line in initialTextLines_) { string lineText = text.Slice(line.Item1, line.Item2).ToString(); if (TextSearcher.Contains(lineText, info.SearchedText, info.SearchKind)) { builder.AppendLine(lineText); } } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerUI/Document/RemarkPreviewPanel.xaml ================================================  #00008b ================================================ FILE: src/ProfileExplorerUI/Document/RemarkPreviewPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; using ProfileExplorer.UI.Controls; namespace ProfileExplorer.UI.Document; public class RemarkEx { private static readonly FontFamily RemarkFont = new("Consolas"); public Remark Remark { get; set; } public TextBlock Text => FormatRemarkTextLine(Remark); public Brush Background => GetRemarkBackground(Remark); public static SolidColorBrush GetRemarkBackground(Remark remark) { return Utils.EstimateBrightness(remark.Category.MarkColor) < 200 ? ColorBrushes.GetBrush(Utils.ChangeColorLuminisity(remark.Category.MarkColor, 1.75)) : ColorBrushes.GetBrush(Utils.ChangeColorLuminisity(remark.Category.MarkColor, 1.2)); } public static TextBlock FormatRemarkTextLine(Remark remark, List highlightingList = null) { int lineOffset = remark.RemarkLocation.Offset; int elementOffset = remark.OutputElements[0].TextLocation.Offset; int elementLength = remark.OutputElements[0].TextLength; int elementLineOffset = elementOffset - lineOffset; int afterElementOffset = elementLineOffset + elementLength; string textLine = remark.RemarkLine; var textBlock = new TextBlock(); textBlock.FontFamily = RemarkFont; textBlock.FontWeight = FontWeights.Normal; textBlock.Foreground = Brushes.Black; if (elementLineOffset > 0) { // Append text found before the IR element. string text = textLine.Substring(0, elementLineOffset); AppendExtraOutputTextRun(text, textBlock, highlightingList); } if (elementLength > 0) { // Append the IR element text. string text = textLine.Substring(elementLineOffset, elementLength); textBlock.Inlines.Add(new Run(text) { FontWeight = FontWeights.Bold, Foreground = Brushes.DarkBlue }); } if (afterElementOffset < textLine.Length) { // Append text following the IR element. string text = textLine.Substring(afterElementOffset, textLine.Length - afterElementOffset); AppendExtraOutputTextRun(text, textBlock, highlightingList); } return textBlock; } public static TextBlock FormatExtraTextLine(string text, List highlightingList = null) { var textBlock = new TextBlock(); textBlock.FontFamily = RemarkFont; textBlock.Foreground = Brushes.Black; textBlock.FontWeight = FontWeights.Normal; AppendExtraOutputTextRun(text, textBlock, highlightingList); return textBlock; } private static void AppendExtraOutputTextRun(string text, TextBlock textBlock, List highlightingList = null) { if (highlightingList == null || highlightingList.Count == 0) { textBlock.Inlines.Add(text); return; } int index = 0; while (index < text.Length) { // Try to find a highlighting match in the order they are in the list, // as defined by the user in the settings. RemarkTextHighlighting matchingQuery = null; TextSearchResult? matchResult = null; foreach (var query in highlightingList) { var result = TextSearcher.FirstIndexOf(text, query.SearchedText, index, query.SearchKind); if (result.HasValue) { matchResult = result.Value; matchingQuery = query; break; } } if (matchingQuery != null) { if (index < matchResult.Value.Offset) { textBlock.Inlines.Add(text.Substring(index, matchResult.Value.Offset - index)); } textBlock.Inlines.Add(new Run(text.Substring(matchResult.Value.Offset, matchResult.Value.Length)) { Foreground = matchingQuery.HasTextColor ? ColorBrushes.GetBrush(matchingQuery.TextColor) : Brushes.Black, Background = matchingQuery.HasBackgroundColor ? ColorBrushes.GetBrush(matchingQuery.BackgroundColor) : null, FontStyle = matchingQuery.UseItalicText ? FontStyles.Italic : FontStyles.Normal, FontWeight = matchingQuery.UseBoldText ? FontWeights.Bold : FontWeights.Normal }); index = matchResult.Value.Offset + matchResult.Value.Length; } else { break; } } if (index < text.Length) { // Append any remaining text at the end. textBlock.Inlines.Add(text.Substring(index, text.Length - index)); } } private string FormatRemarkText() { if (Remark.Kind == RemarkKind.None) { return Remark.RemarkText; } return $"{Remark.Section.Number} | {Remark.RemarkText}"; } } public class ListRemarkEx : RemarkEx { public ListRemarkEx(Remark remark, string sectionName, bool inCurrentSection) { Remark = remark; InCurrentSection = inCurrentSection; SectionName = sectionName; } public bool InCurrentSection { get; set; } public bool HasContext => Remark.Context != null; public string SectionName { get; set; } public bool IsOptimization => Remark.Kind == RemarkKind.Optimization; public bool IsAnalysis => Remark.Kind == RemarkKind.Analysis; public bool HasCustomBackground => Remark.Category.MarkColor != Colors.Black; public string Description => SectionName; } public class RemarkSettingsEx : BindableObject { private bool hasOptimizationRemarks_; private bool hasAnalysisRemarks_; private bool hasDefaultRemarks_; private bool hasVerboseRemarks_; private bool hasTraceRemarks_; public RemarkSettingsEx(RemarkSettings settings) { Settings = settings; } public RemarkSettings Settings { get; set; } public bool HasOptimizationRemarks { get => hasOptimizationRemarks_; set => SetAndNotify(ref hasOptimizationRemarks_, value); } public bool HasAnalysisRemarks { get => hasAnalysisRemarks_; set => SetAndNotify(ref hasAnalysisRemarks_, value); } public bool HasDefaultRemarks { get => hasDefaultRemarks_; set => SetAndNotify(ref hasDefaultRemarks_, value); } public bool HasVerboseRemarks { get => hasVerboseRemarks_; set => SetAndNotify(ref hasVerboseRemarks_, value); } public bool HasTraceRemarks { get => hasTraceRemarks_; set => SetAndNotify(ref hasTraceRemarks_, value); } } public class RemarkContextChangedEventArgs : EventArgs { public RemarkContextChangedEventArgs(RemarkContext context, List remarks) { Context = context; Remarks = remarks; } public RemarkContext Context { get; set; } public List Remarks { get; set; } } public partial class RemarkPreviewPanel : DraggablePopup, INotifyPropertyChanged { private const double RemarkListTop = 48; private const double RemarkPreviewWidth = 600; private const double RemarkPreviewHeight = 300; private const double RemarkListItemHeight = 20; private const double MaxRemarkListItems = 10; private const double MinRemarkListItems = 3; private const double ColorButtonLeft = 175; private IRDocumentHost parentDocument_; private RemarkContext activeRemarkContext_; private IRElement element_; private RemarkSettingsEx remarkFilter_; private bool showPreview_; private bool filterActiveContextRemarks_; private Remark selectedRemark_; private bool contextSearchPanelVisible_; private SearchInfo contextSearchInfo_; private List contextSearchResults_; public RemarkPreviewPanel() { InitializeComponent(); PanelResizeGrip.ResizedControl = this; DataContext = this; // Used for auto-resizing with ShowPreview. //? TODO: Add options filterActiveContextRemarks_ = true; // Setup search panel for context tree. ContextSearchPanel.UseAutoComplete = false; RemarkTextView.UseAutoComplete = false; ContextSearchPanel.SearchChanged += ContextSearchPanel_SearchChanged; ContextSearchPanel.CloseSearchPanel += ContextSearchPanel_CloseSearchPanel; ContextSearchPanel.NavigateToNextResult += ContextSearchPanel_NavigateToResult; ContextSearchPanel.NavigateToPreviousResult += ContextSearchPanel_NavigateToResult; } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public bool ShowPreview { get => showPreview_; set { if (showPreview_ != value) { showPreview_ = value; NotifyPropertyChanged(nameof(ShowPreview)); UpdateSize(); } } } public IRElement Element { get => element_; set { if (element_ == value) { return; } element_ = value; UpdateRemarkList(); } } public bool FilterActiveContextRemarks { get => filterActiveContextRemarks_; set { if (filterActiveContextRemarks_ != value) { if (value && selectedRemark_ != null) { NotifyRemarkContextChanged(selectedRemark_.Context, null); // Recomputes the list. } else { NotifyRemarkContextChanged(null, null); // Disables filtering. } filterActiveContextRemarks_ = value; } } } public bool ShowSearchPanel { get { if (IsContextTreeVisible()) { return contextSearchPanelVisible_; } return RemarkTextView.SearchPanelVisible; } set { if (IsContextTreeVisible()) { if (value != contextSearchPanelVisible_) { contextSearchPanelVisible_ = value; ContextSearchPanel.Visibility = value ? Visibility.Visible : Visibility.Collapsed; if (value) { ContextSearchPanel.Show(); } else { ContextSearchPanel.Hide(); } NotifyPropertyChanged(nameof(ShowSearchPanel)); } } else { if (value != RemarkTextView.SearchPanelVisible) { RemarkTextView.SearchPanelVisible = value; NotifyPropertyChanged(nameof(ShowSearchPanel)); } } } } public FunctionIR Function { get; set; } public IRTextSection Section { get; set; } public IUISession Session { get => RemarkTextView.Session; set => RemarkTextView.Session = value; } public event PropertyChangedEventHandler PropertyChanged; public event EventHandler RemarkContextChanged; public event EventHandler RemarkChanged; public void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public void Initialize(IRElement element, Point position, IRDocumentHost parent, RemarkSettings filter) { parentDocument_ = parent; filter = filter.Clone(); remarkFilter_ = new RemarkSettingsEx(filter); ToolbarPanel.DataContext = remarkFilter_; UpdatePosition(position, parent); RemarkList.UnselectAll(); SectionLabel.Content = ""; ShowPreview = false; Element = element; UpdateSize(); } public void DetachPanel() { if (IsDetached) { return; } DetachPopup(); PopupPanelButton.Visibility = Visibility.Collapsed; ColorButton.Visibility = Visibility.Visible; } protected override void SetPanelAccentColor(Color color) { ToolbarPanel.Background = ColorBrushes.GetBrush(color); ContextToolbarPanel.Background = ColorBrushes.GetBrush(color); PanelBorder.BorderBrush = ColorBrushes.GetBrush(color); } public override bool ShouldStartDragging(MouseButtonEventArgs e) { base.ShouldStartDragging(e); if (e.LeftButton == MouseButtonState.Pressed && ToolbarPanel.IsMouseOver) { DetachPanel(); return true; } return false; } private void UpdateRemarkList() { RemarkList.ItemsSource = null; RemarkContextTree.Items.Clear(); var remarkTag = element_.GetTag(); if (remarkTag == null) { return; } var list = new List(); var listEx = new List(); ListRemarkEx firstSectionRemark = null; foreach (var remark in remarkTag.Remarks) { AccountForRemarkKind(remark); if (parentDocument_.IsAcceptedContextRemark(remark, Section, remarkFilter_.Settings)) { var remarkEx = AppendAcceptedRemark(listEx, remark); // Find first remark in current section. if (remark.Section == Section && firstSectionRemark == null) { firstSectionRemark = remarkEx; } } } RemarkList.ItemsSource = listEx; // Scroll down to current section. if (firstSectionRemark != null) { RemarkList.ScrollIntoView(firstSectionRemark); } } private (TreeViewItem, int) BuildContextRemarkTreeView(RemarkContext context, Dictionary treeNodeMap, List outputTextLines) { if (!treeNodeMap.TryGetValue(context, out var treeNode)) { treeNode = new TreeViewItem { Header = context.Name, Foreground = ColorBrushes.GetBrush(Colors.DarkBlue), FontWeight = FontWeights.Bold, ItemContainerStyle = Application.Current.FindResource("RemarkTreeViewItemStyle") as Style }; treeNodeMap[context] = treeNode; } // Combine the remarks and child contexts into one list and sort it by start line. // This then allows adding the non-remark text found between remarks, but not part // part of a child context (they would be added too when processing the child context, // ending up with duplicate text lines). var inputItems = new List>(context.Remarks.Count + context.Children.Count); foreach (var remark in context.Remarks) { inputItems.Add(new Tuple(remark, remark.RemarkLocation.Line, remark.RemarkLocation.Line)); } foreach (var child in context.Children) { inputItems.Add(new Tuple(child, child.StartLine, child.EndLine)); } inputItems.Sort((a, b) => a.Item2 - b.Item2); // Append all remarks in the context to the result list. var items = new List>(); var highlightingList = Session.RemarkProvider.RemarkTextHighlighting; Tuple prevRemark = null; foreach (var item in inputItems) { int line = item.Item2; // Start line. if (prevRemark != null) { // Add text between consecutive remarks or the end // of a child context and a remark. int prevLine = prevRemark.Item3 + 1; // End line. ExtractOutputTextInRange(prevLine, line, outputTextLines, highlightingList, items); } prevRemark = item; if (!(item.Item1 is Remark remark)) { continue; // Child context. } if (parentDocument_.IsAcceptedRemark(remark, Section, remarkFilter_.Settings)) { var tempTreeNode = new TreeViewItem { Background = RemarkEx.GetRemarkBackground(remark), ItemContainerStyle = Application.Current.FindResource("RemarkTreeViewItemStyle") as Style, ToolTip = remark.RemarkText, Tag = remark }; tempTreeNode.Header = RemarkEx.FormatRemarkTextLine(remark, highlightingList); tempTreeNode.Selected += TempTreeNode_Selected; items.Add(new Tuple(tempTreeNode, remark.RemarkLocation.Line)); } } // Include text preceding the first remark or child context, // and following the last remark or child context. int firstRegionStart = context.StartLine; int firstRegionEnd = context.Remarks.Count > 0 ? context.Remarks[0].RemarkLocation.Line : context.EndLine; if (context.Children.Count > 0) { firstRegionEnd = Math.Min(firstRegionEnd, context.Children[0].StartLine); } ExtractOutputTextInRange(firstRegionStart, firstRegionEnd, outputTextLines, highlightingList, items); // Recursively add remarks from the child contexts. foreach (var child in context.Children) { (var childTreeNode, int childFirstLine) = BuildContextRemarkTreeView(child, treeNodeMap, outputTextLines); items.Add(new Tuple(childTreeNode, childFirstLine)); } // Add text found after the last remark in the context. int secondRegionStart = Math.Max(firstRegionEnd, context.Remarks.Count > 0 ? context.Remarks[^1].RemarkLocation.Line + 1 : context.StartLine); int secondRegionEnd = context.EndLine; if (context.Children.Count > 0) { secondRegionStart = Math.Max(secondRegionStart, context.Children[^1].EndLine); } ExtractOutputTextInRange(secondRegionStart, secondRegionEnd, outputTextLines, highlightingList, items); // Sort by line number, so that remarks and sub-contexts // appear in the same order as in the output text. items.Sort((a, b) => a.Item2 - b.Item2); Tuple prevItem = null; foreach (var item in items) { // Ignore multiple remarks on the same line. // If this remark represents an entire instruction and the other one // is one of its operands, pick the instruction remark. //? TODO: Probably the remark provider shouldn't create the operand remarks at all in this case if (prevItem != null && prevItem.Item2 == item.Item2) { if (prevItem.Item1.Tag is Remark prevItemRemark && item.Item1.Tag is Remark itemRemark) { if (itemRemark.OutputElements[0] is InstructionIR && !(prevItemRemark.OutputElements[0] is InstructionIR)) { treeNode.Items.Remove(prevItem.Item1); treeNode.Items.Add(item.Item1); } } } else { treeNode.Items.Add(item.Item1); } prevItem = item; } return (treeNode, context.StartLine); } private void TempTreeNode_Selected(object sender, RoutedEventArgs e) { var remark = (RemarkContextTree.SelectedItem as TreeViewItem)?.Tag as Remark; if (remark != null) { RemarkChanged?.Invoke(this, remark); } } private void ExtractOutputTextInRange(int prevLine, int line, List outputTextLines, List highlightingList, List> items) { for (int k = prevLine; k < line; k++) { string lineText = outputTextLines[k]; //? TODO: Check could be part of the remark provider (ShouldIgnore...) //? but a cleaner approach should be having a pass output filter interface, //? with Session.GetSectionPassOutputAsync using it, plus a new //? GetRawSectionPassOutputAsync so that the remark prov. gets the metadata lines if (!lineText.StartsWith("/// remark:")) { var lineTreeNode = new TreeViewItem(); lineTreeNode.Header = RemarkEx.FormatExtraTextLine(lineText, highlightingList); lineTreeNode.ToolTip = lineText.Trim(); items.Add(new Tuple(lineTreeNode, k)); } } } private TextBlock ApplyTextLineSearch(TextBlock textBlock, SearchInfo searchInfo) { List newInlines = null; foreach (var element in textBlock.Inlines) { if (element is Run run) { var searchResults = TextSearcher.AllIndexesOf(run.Text, searchInfo.SearchedText, 0, searchInfo.SearchKind); if (searchResults == null || searchResults.Count == 0) { if (newInlines != null) { // A new text block is being made, append to it. newInlines.Add(element); } continue; } if (newInlines == null) { // Create a new text block that will have the highlighted searched text. // Copy all elements that were skipped until now. newInlines = new List(textBlock.Inlines.Count); var prevElement = textBlock.Inlines.FirstInline; while (prevElement != element) { newInlines.Add(prevElement); prevElement = prevElement.NextInline; } } int previousOffset = 0; foreach (var searchResult in searchResults) { if (searchResult.Offset > previousOffset) { // Append text before the searched text. previousOffset = AppendTextInRange(newInlines, run.Text, searchResult.Offset, previousOffset); } string searchText = run.Text.Substring(searchResult.Offset, searchResult.Length); previousOffset += searchText.Length; newInlines.Add(new Run(searchText) { Background = ColorBrushes.GetBrush(Colors.Khaki) //? TODO: Customize from UI }); } if (previousOffset < run.Text.Length) { AppendTextInRange(newInlines, run.Text, run.Text.Length, previousOffset); } } else if (newInlines != null) { // A new text block is being made, append to it. newInlines.Add(element); } } if (newInlines != null) { var markedTextBlock = CloneEmptyTextBlock(textBlock); markedTextBlock.Inlines.AddRange(newInlines); return markedTextBlock; } return textBlock; } private int AppendTextInRange(List newInlines, string text, int offset, int previousOffset) { int distance = offset - previousOffset; string rangeText = text.Substring(previousOffset, distance); newInlines.Add(new Run(rangeText)); return previousOffset + distance; } private TextBlock CloneEmptyTextBlock(TextBlock textBlock) { var copyTextBlock = new TextBlock(); copyTextBlock.FontFamily = textBlock.FontFamily; copyTextBlock.Foreground = textBlock.Foreground; copyTextBlock.Background = textBlock.Background; copyTextBlock.FontWeight = textBlock.FontWeight; copyTextBlock.FontSize = textBlock.FontSize; copyTextBlock.FontStyle = textBlock.FontStyle; return copyTextBlock; } private void BuildContextRemarkTreeView(RemarkContext rootContext, List outputTextLines) { var treeNodeMap = new Dictionary(); var (rootTreeNode, _) = BuildContextRemarkTreeView(rootContext, treeNodeMap, outputTextLines); RemarkContextTree.Items.Clear(); RemarkContextTree.Items.Add(rootTreeNode); ExpandAllTreeViewNodes(RemarkContextTree); } private Remark CollectContextTreeRemarks(RemarkContext rootContext, List list, bool filterDuplicates) { Remark firstSectionRemark = null; var worklist = new Queue(); worklist.Enqueue(rootContext); while (worklist.Count > 0) { var context = worklist.Dequeue(); foreach (var remark in context.Remarks) { if (parentDocument_.IsAcceptedRemark(remark, Section, remarkFilter_.Settings)) { list.Add(remark); // Find first remark in current section. if (remark.Section == Section && firstSectionRemark == null) { firstSectionRemark = remark; } } } } list.Sort((a, b) => a.RemarkLocation.Line - b.RemarkLocation.Line); if (filterDuplicates) { Remark prevItem = null; foreach (var item in list) { if (prevItem != null && prevItem.RemarkLocation.Line == item.RemarkLocation.Line) { continue; // Ignore multiple remarks on the same line. } prevItem = item; } } return firstSectionRemark; } private void ExpandAllTreeViewNodes(TreeViewItem rootItem) { foreach (object item in rootItem.Items) { var treeItem = item as TreeViewItem; if (treeItem != null) { ExpandAllTreeViewNodes(treeItem); treeItem.IsExpanded = true; } } } private void ExpandAllTreeViewNodes(TreeView treeView) { foreach (object item in treeView.Items) { var treeItem = (TreeViewItem)item; if (treeItem != null) { ExpandAllTreeViewNodes(treeItem); treeItem.IsExpanded = true; } } } private bool SelectTreeViewNode(TreeViewItem rootItem, object tag) { foreach (object item in rootItem.Items) { var treeItem = item as TreeViewItem; if (treeItem != null) { if (treeItem.Tag == tag) { SelectTreeViewNode(treeItem); return true; } if (SelectTreeViewNode(treeItem, tag)) { return true; } } } return false; } private void SelectTreeViewNode(TreeViewItem treeItem) { treeItem.IsSelected = true; treeItem.BringIntoView(); } private void SelectTreeViewNode(TreeView treeView, object tag) { foreach (object item in treeView.Items) { var treeItem = (TreeViewItem)item; if (treeItem != null) { if (treeItem.Tag == tag) { treeItem.IsSelected = true; treeItem.BringIntoView(); return; } if (SelectTreeViewNode(treeItem, tag)) { return; } } } } private void ResetContextTreeTextSearch() { contextSearchInfo_ = null; contextSearchResults_ = null; } private void ApplyContextTreeTextSearch(TreeView treeView, SearchInfo searchInfo) { if (searchInfo == null || !searchInfo.HasSearchedText || searchInfo.SearchedText.Length < 2) { return; // Search not enabled. } contextSearchInfo_ = searchInfo; contextSearchResults_ = new List(); foreach (object item in treeView.Items) { var treeItem = (TreeViewItem)item; if (treeItem != null) { ApplyContextTreeTextSearch(treeItem); } } searchInfo.ResultCount = contextSearchResults_.Count; searchInfo.CurrentResult = 0; if (contextSearchResults_.Count > 0) { SelectTreeViewNode(contextSearchResults_[0]); } } private void ApplyContextTreeTextSearch(TreeViewItem rootItem) { var textBlock = rootItem.Header as TextBlock; if (textBlock != null) { // Change formatting of the line if it contains the searched text. var newTextBlock = ApplyTextLineSearch(textBlock, contextSearchInfo_); if (newTextBlock != textBlock) { rootItem.Header = newTextBlock; contextSearchResults_.Add(rootItem); } } foreach (object item in rootItem.Items) { var treeItem = item as TreeViewItem; if (treeItem != null) { ApplyContextTreeTextSearch(treeItem); } } } private ListRemarkEx AppendAcceptedRemark(List list, Remark remark) { string sectionName = Session.CompilerInfo.NameProvider.GetSectionName(remark.Section); sectionName = $"({remark.Section.Number}) {sectionName}"; var remarkEx = new ListRemarkEx(remark, sectionName, remark.Section == Section); list.Add(remarkEx); return remarkEx; } private void AccountForRemarkKind(Remark remark) { switch (remark.Kind) { case RemarkKind.Optimization: { remarkFilter_.HasOptimizationRemarks = true; break; } case RemarkKind.Analysis: { remarkFilter_.HasAnalysisRemarks = true; break; } case RemarkKind.Default: { remarkFilter_.HasDefaultRemarks = true; break; } case RemarkKind.Verbose: { remarkFilter_.HasVerboseRemarks = true; break; } case RemarkKind.Trace: { remarkFilter_.HasTraceRemarks = true; break; } } } private void UpdateSize() { double width = Math.Max(RemarkPreviewWidth, ActualWidth); double height = Math.Max(RemarkListTop + RemarkListItemHeight * Math.Clamp(RemarkList.Items.Count, MinRemarkListItems, MaxRemarkListItems), ActualHeight); if (ShowPreview) { height += RemarkPreviewHeight; } UpdateSize(width, height); } private async void RemarkList_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count != 1) { return; } var itemEx = e.AddedItems[0] as ListRemarkEx; selectedRemark_ = itemEx.Remark; activeRemarkContext_ = selectedRemark_.Context; SectionLabel.Content = itemEx.Description; ShowPreview = true; if (selectedRemark_.Context != null && IsContextTreeVisible()) { // Show context and children. await UpdateContextTree(selectedRemark_, activeRemarkContext_); } else { RemarksTabControl.SelectedItem = OutputTextTabItem; await UpdateOutputText(selectedRemark_); } } private async Task UpdateContextTree(Remark remark, RemarkContext context) { // Note that the context can also be a parent of the remarks context. var outputText = await Session.GetSectionOutputTextLinesAsync(remark.Section.OutputBefore, remark.Section); var list = new List(); CollectContextTreeRemarks(context, list, true); BuildContextRemarkTreeView(context, outputText); SelectTreeViewNode(RemarkContextTree, remark); if (FilterActiveContextRemarks) { NotifyRemarkContextChanged(context, list); } } private void NotifyRemarkContextChanged(RemarkContext context, List list) { if (list == null && context != null) { list = new List(); CollectContextTreeRemarks(context, list, true); } RemarkContextChanged?.Invoke(this, new RemarkContextChangedEventArgs(context, list)); } private void Button_Click(object sender, RoutedEventArgs e) { UpdateRemarkList(); } private void RemarkList_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var itemEx = RemarkList.SelectedItem as ListRemarkEx; if (itemEx != null) { RemarkChanged?.Invoke(this, itemEx.Remark); } } private void TextBox_TextChanged(object sender, TextChangedEventArgs e) { UpdateRemarkList(); } private void PopupPanelButton_Click(object sender, RoutedEventArgs e) { DetachPanel(); } private void ClosePanelButton_Click(object sender, RoutedEventArgs e) { IsOpen = false; } private bool IsOutputTextVisible() { return RemarksTabControl.SelectedItem == OutputTextTabItem; } private bool IsContextTreeVisible() { return RemarksTabControl.SelectedItem == ContextTreeTabItem; } private async Task UpdateOutputText(Remark remark) { string outputText = await Session.GetSectionOutputTextAsync(remark.Section.OutputBefore, remark.Section); await RemarkTextView.SetText(outputText, Function, Section, parentDocument_.TextView, Session); RemarkTextView.SelectText(remark.RemarkLocation.Offset, remark.RemarkText.Length, remark.RemarkLocation.Line); } private async void TabControl_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (selectedRemark_ == null) { return; } await UpdateRemarkView(); NotifyPropertyChanged(nameof(ShowSearchPanel)); } private async Task UpdateRemarkView() { if (IsOutputTextVisible()) { await UpdateOutputText(selectedRemark_); } else if (IsContextTreeVisible() && activeRemarkContext_ != null) { await UpdateContextTree(selectedRemark_, activeRemarkContext_); } } private async void ContextParentButton_Click(object sender, RoutedEventArgs e) { if (activeRemarkContext_ == null || activeRemarkContext_.Parent == null) { return; } activeRemarkContext_ = activeRemarkContext_.Parent; await UpdateContextTree(selectedRemark_, activeRemarkContext_); } private async void ContextSearchPanel_CloseSearchPanel(object sender, SearchInfo e) { ShowSearchPanel = false; ResetContextTreeTextSearch(); await UpdateRemarkView(); } private async void ContextSearchPanel_SearchChanged(object sender, SearchInfo e) { await UpdateRemarkView(); ApplyContextTreeTextSearch(RemarkContextTree, e); } private void ContextSearchPanel_NavigateToResult(object sender, SearchInfo e) { if (contextSearchResults_ == null) { return; } SelectTreeViewNode(contextSearchResults_[e.CurrentResult]); } //? TODO: ColorButton_Click private class ColorSelectorPopup : Popup { } } ================================================ FILE: src/ProfileExplorerUI/Document/RemarkTag.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Text; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI; public class RemarkTag : ITag { public RemarkTag() { Remarks = new List(); } public List Remarks { get; } public string Name => "Remark tag"; public TaggedObject Owner { get; set; } public override string ToString() { var builder = new StringBuilder(); builder.AppendLine($"remarks count: {Remarks.Count}"); foreach (var remark in Remarks) { builder.Append($" o {remark}".Indent(4)); } return builder.ToString(); } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/DocumentMargin.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Input; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Document; using ProtoBuf; namespace ProfileExplorer.UI; public enum BookmarkSegmentKind { Bookmark, Remark } [ProtoContract] public sealed class BookmarkSegment : IRSegment { public BookmarkSegment() : base(null) { } public BookmarkSegment(Bookmark bookmark, BookmarkSegmentKind kind, object tag = null) : base( bookmark.Element) { Bookmark = bookmark; Kind = kind; Tag = tag; } [ProtoMember(1)] public Bookmark Bookmark { get; set; } [ProtoMember(2)] public BookmarkSegmentKind Kind { get; set; } public Rect Bounds { get; set; } public Rect PinButtonBounds { get; set; } public Rect RemoveButtonBounds { get; set; } public bool IsHovered { get; set; } public bool IsTextHovered { get; set; } public bool IsNearby { get; set; } public object Tag { get; set; } public bool IsSelected { get => Bookmark.IsSelected; set => Bookmark.IsSelected = value; } public bool IsPinned { get => Bookmark.IsPinned; set => Bookmark.IsPinned = value; } public bool IsExpanded => IsSelected || IsPinned || IsHovered; public bool HasText => !string.IsNullOrWhiteSpace(Bookmark.Text); } [ProtoContract] public class DocumentMarginState { [ProtoMember(1)] public List BlockGroups; [ProtoMember(2)] public List BookmarkSegments; [ProtoMember(3)] public BookmarkSegment HoveredBookmark; [ProtoMember(4)] public BookmarkSegment SelectedBookmark; public DocumentMarginState() { BlockGroups = new List(); BookmarkSegments = new List(); } public bool HasAnnotations => BlockGroups.Count > 0 || BookmarkSegments.Count > 0; } public class DocumentMargin : AbstractMargin { private const int NearbyBookmarkDistance = 100; private const int NearbyBookmarkExtraWidth = 16; private const double HoveredPinnedBookmarkOpacity = 0.2; private const int ButtonSectionWidth = 32; private const int ButtonTextPadding = 8; private static readonly int MarginWidth = 16; private static readonly int ButtonWidth = 16; private static readonly int ButtonIconWidth = 12; private static readonly Typeface DefaultFont = new("Consolas"); private static readonly HighlightingStyle defaultBookmarkStyle_ = new(Colors.LemonChiffon, ColorPens.GetPen(Colors.Silver)); private static readonly HighlightingStyle selectedBookmarkStyle_ = new(Colors.PeachPuff, ColorPens.GetPen(Colors.Black)); private static readonly HighlightingStyle pinnedBookmarkStyle_ = new(Colors.PapayaWhip, ColorPens.GetPen(Colors.Black)); private static readonly HighlightingStyle pinButtonStyle_ = new(Colors.Silver, ColorPens.GetPen(Colors.Black)); private static readonly HighlightingStyle hoverBookmarkStyle_ = new(Colors.LightBlue, ColorPens.GetPen(Colors.Gray)); private static readonly HighlightingStyle nearbyBookmarkStyle_ = new(Colors.LightBlue, ColorPens.GetPen(Colors.Silver)); private SolidColorBrush backgroundBrush_; private HashSet blockElements_; private List blockGroups_; private IconDrawing bookmarkIcon_; private TextSegmentCollection bookmarkSegments_; private BookmarkSegment hoveredBookmark_; private HashSet nearbyBookmarks_; private IconDrawing pinIcon_; private List remarkIcons_; private IconDrawing removeIcon_; private BookmarkSegment selectedBookmark_; public DocumentMargin(Color backgroundColor) { BackgroundColor = backgroundColor; blockGroups_ = new List(); blockElements_ = new HashSet(); bookmarkSegments_ = new TextSegmentCollection(); nearbyBookmarks_ = new HashSet(); bookmarkIcon_ = IconDrawing.FromIconResource("MarkerIcon"); removeIcon_ = IconDrawing.FromIconResource("RemoveIcon"); pinIcon_ = IconDrawing.FromIconResource("PinIcon"); remarkIcons_ = new List(); remarkIcons_.Add(IconDrawing.FromIconResource("DotIcon")); remarkIcons_.Add(IconDrawing.FromIconResource("ZapIcon")); remarkIcons_.Add(IconDrawing.FromIconResource("StarIcon")); remarkIcons_.Add(IconDrawing.FromIconResource("TagIcon")); remarkIcons_.Add(IconDrawing.FromIconResource("WarningIcon")); Version = 1; } public int Version { get; set; } public bool DisableBlockRemoval { get; set; } public Bookmark SelectedBookmark => selectedBookmark_?.Bookmark; public List BlockGroups => blockGroups_; public Color BackgroundColor { get => backgroundBrush_.Color; set { backgroundBrush_ = ColorBrushes.GetBrush(value); InvalidateVisual(); } } public event EventHandler BookmarkRemoved; public event EventHandler BookmarkChanged; public DocumentMarginState SaveState() { var marginState = new DocumentMarginState(); marginState.BlockGroups = UIStateSerializer.SaveElementGroupState(blockGroups_); marginState.BookmarkSegments = bookmarkSegments_.ToList(); marginState.HoveredBookmark = hoveredBookmark_; marginState.SelectedBookmark = selectedBookmark_; return marginState; } public void LoadState(DocumentMarginState state) { if (state == null) { return; // Most likely a file from an older version of the app. } blockGroups_ = UIStateSerializer.LoadElementGroupState(state.BlockGroups); hoveredBookmark_ = state.HoveredBookmark; selectedBookmark_ = state.SelectedBookmark; bookmarkSegments_ = new TextSegmentCollection(); state.BookmarkSegments.ForEach(item => { if (item.Kind == BookmarkSegmentKind.Bookmark) { AddBookmark(item.Bookmark); } }); } public void AddBlock(HighlightedElementGroup group, bool saveToFile = true) { foreach (var block in group.Elements) { RemoveBlock(block); blockElements_.Add(block); } blockGroups_.Add(new HighlightedSegmentGroup(group, saveToFile)); Version++; } public void AddBookmark(Bookmark bookmark) { bookmarkSegments_.Add(new BookmarkSegment(bookmark, BookmarkSegmentKind.Bookmark)); Version++; } public void AddRemarkBookmark(Bookmark bookmark, RemarkLineGroup remarkGroup) { bookmarkSegments_.Add(new BookmarkSegment(bookmark, BookmarkSegmentKind.Remark, remarkGroup)); Version++; } public void RemoveBookmark(Bookmark bookmark) { BookmarkSegment segment = null; foreach (var value in bookmarkSegments_) { if (value.Bookmark == bookmark) { segment = value; break; } } if (segment != null) { bookmarkSegments_.Remove(segment); Version++; } } public void RemoveBlock(IRElement block) { if (DisableBlockRemoval) { return; } if (!blockElements_.Contains(block)) { return; } int index = blockGroups_.FindIndex(e => e.Group.Elements.Contains(block)); if (index != -1) { if (blockGroups_[index].Segments.Count == 1) { blockGroups_.RemoveAt(index); } else { var segments = blockGroups_[index].Segments; IRSegment blockSegment = null; foreach (var segment in segments) { if (segment.Element == block) { blockSegment = segment; break; } } if (blockSegment != null) { segments.Remove(blockSegment); Version++; } } } } public void CopyFrom(DocumentMargin other) { foreach (var item in other.blockGroups_) { blockGroups_.Add(new HighlightedSegmentGroup(item.Group)); } foreach (var item in other.bookmarkSegments_) { bookmarkSegments_.Add(new BookmarkSegment(item.Bookmark, item.Kind)); } } public void ClearMarkers() { blockGroups_.Clear(); Version++; } public void ClearBookmarks() { bookmarkSegments_ = new TextSegmentCollection(); Version++; } public void Reset() { ClearMarkers(); ClearBookmarks(); blockElements_.Clear(); blockGroups_.Clear(); nearbyBookmarks_.Clear(); selectedBookmark_ = null; hoveredBookmark_ = null; } public void ForEachBlockElement(Action action) { blockGroups_.ForEach(group => { group.Group.Elements.ForEach(action); }); } public void ForEachBookmark(Action action) { foreach (var segment in bookmarkSegments_) { action(segment.Bookmark); } } public void MouseMoved(MouseEventArgs e) { HandleMouseMoved(e.GetPosition(this)); } public bool HasHoveredBookmark() { return HitTestBookmarks() != null; } public void SelectBookmark(Bookmark bookmark) { foreach (var segment in bookmarkSegments_) { if (segment.Bookmark == bookmark) { UnselectBookmark(); SelectBookmark(segment); break; } } } public void UnselectBookmark() { UnselectHoveredBookmark(); if (selectedBookmark_ != null) { selectedBookmark_.IsSelected = false; selectedBookmark_ = null; InvalidateVisual(); } } public void SelectedBookmarkChanged() { InvalidateVisual(); } public void RemoveRemarkBookmarks() { var bookmarkList = new List(); foreach (var segment in bookmarkSegments_) { if (segment.Kind == BookmarkSegmentKind.Bookmark) { bookmarkList.Add(segment); } } // Clear current segments and add back just the bookmarks. if (bookmarkList.Count < bookmarkSegments_.Count) { bookmarkSegments_.Clear(); foreach (var segment in bookmarkList) { bookmarkSegments_.Add(segment); } } } protected override HitTestResult HitTestCore(PointHitTestParameters hitParams) { HandleMouseMoved(Mouse.GetPosition(this)); return new PointHitTestResult(this, hitParams.HitPoint); } protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e) { var result = HitTestBookmarks(); if (result != null) { var segment = result.Item1; var element = result.Item2; switch (element) { case BookmarkSegmentElement.Bookmark: UnselectBookmark(); SelectBookmark(segment); InvalidateVisual(); BookmarkChanged?.Invoke(this, segment.Bookmark); e.Handled = true; return; case BookmarkSegmentElement.PinButton: UnselectBookmark(); SelectBookmark(segment); segment.IsPinned = !segment.IsPinned; segment.IsHovered = !segment.IsPinned; InvalidateVisual(); BookmarkChanged?.Invoke(this, segment.Bookmark); e.Handled = true; return; case BookmarkSegmentElement.RemoveButton: BookmarkRemoved?.Invoke(this, segment.Bookmark); break; } } UnselectBookmark(); base.OnPreviewMouseLeftButtonDown(e); } protected override Size MeasureOverride(Size availableSize) { return new Size(MarginWidth, 0); } protected override void OnTextViewChanged(TextView oldTextView, TextView newTextView) { // Register to get notified when the visual lines are changing // so that the margin can be redrawn. if (oldTextView != null) { oldTextView.VisualLinesChanged -= VisualLinesChanged; } if (newTextView != null) { newTextView.VisualLinesChanged += VisualLinesChanged; } base.OnTextViewChanged(oldTextView, newTextView); InvalidateVisual(); } protected override void OnRender(DrawingContext drawingContext) { // Draw margin background. drawingContext.DrawRectangle(backgroundBrush_, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height)); // Draw highlighted blocks. if (!DocumentUtils.FindVisibleTextOffsets(TextView, out int viewStart, out int viewEnd)) { return; } foreach (var group in blockGroups_) { DrawGroup(group, TextView, drawingContext, viewStart, viewEnd); } // Draw bookmarks in two steps, first the unselected ones, then the selected ones. // This is done so that the borders of the selected ones are not drawn over by other // segments with a different border color. double lineHeight = Math.Ceiling(TextView.DefaultLineHeight); var segments = bookmarkSegments_.FindOverlappingSegments(TextView); foreach (var segment in segments) { if (!(segment.IsSelected || segment.IsHovered || segment.IsPinned)) { DrawSegment(segment, lineHeight, drawingContext); } } foreach (var segment in segments) { if (segment.IsSelected || segment.IsHovered || segment.IsPinned) { DrawSegment(segment, lineHeight, drawingContext); } } } private void HandleMouseMoved(Point point) { // Test only with visible bookmarks. BookmarkSegment newHoveredBookmark = null; bool newTextHoveredBookmark = false; bool needsRedrawing = false; foreach (var segment in bookmarkSegments_.FindOverlappingSegments(TextView)) { if (newHoveredBookmark == null) { if (segment.PinButtonBounds.Contains(point) || segment.RemoveButtonBounds.Contains(point)) { newHoveredBookmark = segment; newTextHoveredBookmark = false; continue; } if (segment.Bounds.Contains(point)) { newHoveredBookmark = segment; newTextHoveredBookmark = true; continue; } } if (!segment.IsExpanded) { double distance = (segment.Bounds.TopLeft - point).Length; bool onSameLine = point.Y >= segment.Bounds.Top && point.Y <= segment.Bounds.Bottom; if (distance < NearbyBookmarkDistance && onSameLine) { if (!nearbyBookmarks_.Contains(segment)) { nearbyBookmarks_.Add(segment); segment.IsNearby = true; needsRedrawing = true; } } else if (nearbyBookmarks_.Contains(segment)) { segment.IsNearby = false; nearbyBookmarks_.Remove(segment); needsRedrawing = true; } } } if (newHoveredBookmark != null) { if (newHoveredBookmark != hoveredBookmark_ || hoveredBookmark_.IsTextHovered != newTextHoveredBookmark) { // Replace hovered bookmark. if (hoveredBookmark_ != null) { UnselectHoveredBookmark(); } newHoveredBookmark.IsHovered = true; newHoveredBookmark.IsTextHovered = newTextHoveredBookmark; hoveredBookmark_ = newHoveredBookmark; needsRedrawing = true; } if (nearbyBookmarks_.Contains(newHoveredBookmark)) { // Remove from nearby bookmarks. newHoveredBookmark.IsNearby = false; nearbyBookmarks_.Remove(newHoveredBookmark); needsRedrawing = true; } } else if (hoveredBookmark_ != null) { UnselectHoveredBookmark(); needsRedrawing = true; } if (needsRedrawing) { InvalidateVisual(); } } private Tuple HitTestBookmarks() { var point = Mouse.GetPosition(this); foreach (var segment in bookmarkSegments_.FindOverlappingSegments(TextView)) { if (segment.PinButtonBounds.Contains(point)) { return new Tuple( segment, BookmarkSegmentElement.PinButton); } if (segment.RemoveButtonBounds.Contains(point)) { return new Tuple( segment, BookmarkSegmentElement.RemoveButton); } if (segment.Bounds.Contains(point)) { return new Tuple( segment, BookmarkSegmentElement.Bookmark); } } return null; } private void UnselectHoveredBookmark() { if (hoveredBookmark_ != null) { hoveredBookmark_.IsHovered = false; hoveredBookmark_.IsTextHovered = false; hoveredBookmark_ = null; } } private void SelectBookmark(BookmarkSegment segment) { UnselectHoveredBookmark(); selectedBookmark_ = segment; selectedBookmark_.IsSelected = true; } private void VisualLinesChanged(object sender, EventArgs e) { InvalidateVisual(); } private HighlightingStyle GetBookmarkStyle(BookmarkSegment segment) { var style = defaultBookmarkStyle_; if (segment.Bookmark.IsSelected) { style = selectedBookmarkStyle_; } else if (segment.Bookmark.IsPinned) { style = pinnedBookmarkStyle_; } else if (segment.IsHovered) { style = hoverBookmarkStyle_; } else if (segment.IsNearby) { style = nearbyBookmarkStyle_; } // Combine user style background with default pen. if (segment.Bookmark.Style != null) { //if (style == defaultBookmarkStyle_ && // segment.Kind != BookmarkSegmentKind.Bookmark) //{ // style = new HighlightingStyle(ColorBrushes.Transparent, null); //} //else //{ // style = new HighlightingStyle(segment.Bookmark.Style.BackColor, style.Border); //} style = new HighlightingStyle(segment.Bookmark.Style.BackColor, style.Border); } return style; } private HighlightingStyle GetPinButtonStyle(BookmarkSegment segment) { if (segment.IsPinned) { return pinButtonStyle_; } return GetBookmarkStyle(segment); } private void DrawGroup(HighlightedSegmentGroup group, TextView textView, DrawingContext drawingContext, int viewStart, int viewEnd) { var renderSize = RenderSize; foreach (var result in group.Segments.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, result)) { drawingContext.DrawRectangle(group.BackColor, null, Utils.SnapRectToPixels(renderSize.Width - MarginWidth, rect.Top, MarginWidth, rect.Height + 1)); } } } private void DrawSegment(BookmarkSegment segment, double lineHeight, DrawingContext drawingContext) { foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(TextView, segment)) { double y = rect.Top; var style = GetBookmarkStyle(segment); Rect bounds; Rect pinBounds; Rect removeBounds; //if (segment.Kind == BookmarkSegmentKind.AnalysisRemark) //{ // var vn = UTCRemarkParser.ExtractVN(segment.Bookmark.Element); // if (vn != null) // { // //? Click on a VN would mark all other identical VNs // var text = CreateFormattedText(this, $"VN {vn}", DefaultFont, 12, Brushes.Black); // drawingContext.DrawText(text, new Point(4, y)); // } //} bool popOpacity = false; if (segment.HasText && segment.IsExpanded) { double baseWidth = RenderSize.Width + ButtonSectionWidth; double fontSize = App.Settings.DocumentSettings.FontSize; //? TODO: Add option to control little opacity on hover if (segment.IsPinned && segment.IsTextHovered) { drawingContext.PushOpacity(HoveredPinnedBookmarkOpacity); popOpacity = true; } if (segment.Tag is RemarkLineGroup remarkGroup) { double maxTextWidth = 0; var textSegments = new List(remarkGroup.Remarks.Count); int index = 0; int leaderIndex = 0; foreach (var remark in remarkGroup.Remarks) { var fontWeight = FontWeights.Normal; if (remark == remarkGroup.LeaderRemark) { leaderIndex = index; fontWeight = FontWeights.Medium; } var text = DocumentUtils.CreateFormattedText(this, remark.RemarkText, DefaultFont, fontSize, Brushes.Black, fontWeight); textSegments.Add(text); maxTextWidth = Math.Max(maxTextWidth, text.Width); index++; } index = 0; foreach (var remark in remarkGroup.Remarks) { var remarkColor = remark.Category.MarkColor == Colors.Black || remark.Category.MarkColor == Colors.Transparent ? backgroundBrush_.Color : remark.Category.MarkColor; var remarkBrush = ColorBrushes.GetBrush(remarkColor); var text = textSegments[index]; double offsetY = y + (index - leaderIndex) * lineHeight; var remarkBounds = Utils.SnapRectToPixels(0, offsetY - 1, maxTextWidth + baseWidth + 2 * ButtonTextPadding, lineHeight); drawingContext.DrawRectangle(remarkBrush, style.Border, remarkBounds); drawingContext.DrawText(text, new Point(baseWidth + ButtonTextPadding, offsetY - 1)); if (index == leaderIndex) { bounds = remarkBounds; } index++; } } else { var text = DocumentUtils.CreateFormattedText(this, segment.Bookmark.Text, DefaultFont, fontSize, Brushes.Black); bounds = Utils.SnapRectToPixels(0, y - 1, text.Width + baseWidth + 2 * ButtonTextPadding, lineHeight); drawingContext.DrawRectangle(style.BackColor, style.Border, bounds); drawingContext.DrawText(text, new Point(baseWidth + ButtonTextPadding, y)); } } else { double nearbyExtraWidth = segment.IsNearby || segment.IsExpanded ? NearbyBookmarkExtraWidth : 0; bounds = Utils.SnapRectToPixels(0, y - 1, RenderSize.Width + nearbyExtraWidth, lineHeight); drawingContext.DrawRectangle(style.BackColor, style.Border, bounds); } var icon = SelectBookmarkIcon(segment); if (icon != null) { icon.Draw(0, y - 1, lineHeight - 1, RenderSize.Width, lineHeight, drawingContext); } if (segment.IsExpanded) { var buttonBounds = new Rect(MarginWidth, y - 1, ButtonSectionWidth, lineHeight); removeBounds = DrawBookmarkButton(removeIcon_, buttonBounds, style, drawingContext); var pinStyle = GetPinButtonStyle(segment); pinBounds = DrawBookmarkButton(pinIcon_, buttonBounds, pinStyle, drawingContext, removeBounds.Width); } if (popOpacity) { drawingContext.Pop(); } segment.Bounds = bounds; // Update bounds for later hit testing. segment.PinButtonBounds = pinBounds; segment.RemoveButtonBounds = removeBounds; return; // Stop after drawing it once. } } private IconDrawing SelectBookmarkIcon(BookmarkSegment segment) { switch (segment.Kind) { case BookmarkSegmentKind.Bookmark: { return bookmarkIcon_; } case BookmarkSegmentKind.Remark: { if (segment.Tag == null) { return null; } var remarkGroup = (RemarkLineGroup)segment.Tag; var remark = remarkGroup.LeaderRemark; if (remark.Category.MarkIconIndex >= 0 && remark.Category.MarkIconIndex < remarkIcons_.Count) { return remarkIcons_[remark.Category.MarkIconIndex]; } return null; } default: throw new InvalidOperationException("Unknown segment kind!"); } } private Rect DrawBookmarkButton(IconDrawing icon, Rect startBounds, HighlightingStyle pinStyle, DrawingContext drawingContext, double extraLeftSpace = 0) { var bounds = Utils.SnapRectToPixels(startBounds.Left + extraLeftSpace, startBounds.Top, ButtonWidth, startBounds.Height); drawingContext.DrawRectangle(pinStyle.BackColor, pinStyle.Border, bounds); icon.Draw(bounds.Left + 1, bounds.Top, ButtonIconWidth, bounds.Width, bounds.Height, drawingContext); return bounds; } private enum BookmarkSegmentElement { Bookmark, PinButton, RemoveButton } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Highlighters/BlockBackgroundHighlighter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI; public sealed class BlockBackgroundHighlighter : IBackgroundRenderer { private Pen blockSeparatorPen_; private Brush oddBlockBrush_; private TextSegmentCollection segments_; public BlockBackgroundHighlighter(bool showSeparatorLine, Color separatorLineColor, Color evenBlockColor, Color oddBlockColor) { segments_ = new TextSegmentCollection(); oddBlockBrush_ = ColorBrushes.GetBrush(oddBlockColor); if (showSeparatorLine) { blockSeparatorPen_ = ColorPens.GetPen(separatorLineColor); } } public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { if (textView.Document == null) { return; } textView.EnsureVisualLines(); var visualLines = textView.VisualLines; if (visualLines.Count == 0) { return; } int viewStart = visualLines[0].FirstDocumentLine.Offset; int viewEnd = visualLines[^1].LastDocumentLine.EndOffset; var firstLinePos = visualLines[0].GetVisualPosition(0, VisualYPosition.LineTop); double scrollOffsetY = textView.ScrollOffset.Y % textView.DefaultLineHeight; double lineAdjustmentY = firstLinePos.Y + scrollOffsetY; int minOffset = viewStart; int maxOffset = visualLines[^1].LastDocumentLine.EndOffset; double maxViewHeight = textView.ActualHeight; var oddGeoBuilder = CreateGeometryBuilder(); Span separatorLines = stackalloc Rect[visualLines.Count + 1]; int separatorLineCount = 0; double width = textView.ActualWidth + textView.HorizontalOffset; foreach (var segment in segments_.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { var block = segment.Element as BlockIR; if (block == null) { continue; } var startLine = textView.Document.GetLineByOffset(Math.Max(minOffset, segment.StartOffset)); var endLine = textView.Document.GetLineByOffset(Math.Min(maxOffset, segment.EndOffset)); var startLineVisual = textView.GetVisualLine(startLine.LineNumber); var endLineVisual = textView.GetVisualLine(endLine.LineNumber); var startLinePos = startLineVisual.GetVisualPosition(0, VisualYPosition.LineTop); var endLinePos = endLineVisual.GetVisualPosition(0, VisualYPosition.LineBottom); var blockRect = Utils.SnapRectToPixels(0, startLinePos.Y - lineAdjustmentY, width, Math.Min(maxViewHeight, endLinePos.Y - startLinePos.Y)); if (block.HasOddIndexInFunction) { oddGeoBuilder.AddRectangle(textView, blockRect); } // Draw separator line between blocks, if it doesn't end up outside the view. if (blockRect.Bottom <= maxViewHeight && separatorLineCount < separatorLines.Length) { separatorLines[separatorLineCount] = blockRect; separatorLineCount++; } } var oddGeometry = oddGeoBuilder.CreateGeometry(); if (oddGeometry != null) { drawingContext.DrawGeometry(oddBlockBrush_, null, oddGeometry); } if (blockSeparatorPen_ != null) { for (int i = 0; i < separatorLineCount; i++) { drawingContext.DrawLine(blockSeparatorPen_, separatorLines[i].BottomLeft, new Point(textView.ActualWidth, separatorLines[i].Bottom)); } } } public void Add(IRElement elem) { segments_.Add(new IRSegment(elem)); } public void Clear() { segments_.Clear(); } public object SaveState() { return segments_.ToList(); } public void LoadState(object stateObject) { segments_ = new TextSegmentCollection(); var list = stateObject as List; list.ForEach(item => Add(item.Element)); } private BackgroundGeometryBuilder CreateGeometryBuilder() { var geoBuilder = new BackgroundGeometryBuilder(); geoBuilder.ExtendToFullWidthAtLineEnd = true; geoBuilder.AlignToWholePixels = true; geoBuilder.BorderThickness = 0; geoBuilder.CornerRadius = 0; return geoBuilder; } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Highlighters/CurrentLineHighlighter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows.Media; using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Rendering; namespace ProfileExplorer.UI; public sealed class CurrentLineHighlighter : IBackgroundRenderer { private TextEditor editor_; private Pen borderPen_; public CurrentLineHighlighter(TextEditor editor, Color borderColor) { editor_ = editor; borderPen_ = ColorPens.GetPen(borderColor, 1.5); } public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { if (textView.Document == null || textView.Document.TextLength == 0) { return; } // Draw a border around the current line. textView.EnsureVisualLines(); var currentLine = textView.Document.GetLineByOffset(editor_.CaretOffset); double width = textView.ActualWidth + textView.HorizontalOffset; foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, currentLine)) { var lineRect = Utils.SnapRectToPixels(rect.X, rect.Y, width, rect.Height); lineRect.Inflate(1, 1); drawingContext.DrawRectangle(null, borderPen_, lineRect); } } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Highlighters/DiffLineHighlighter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.Document.Renderers.Highlighters; namespace ProfileExplorer.UI; public sealed class DiffTextSegment : TextSegment { public DiffTextSegment(DiffKind kind, int startOffset, int length) { Kind = kind; StartOffset = startOffset; Length = length; } public DiffTextSegment(DiffTextSegment other) : this(other.Kind, other.StartOffset, other.Length) { } public DiffKind Kind { get; set; } public bool IsContinuation(DiffTextSegment otherSegment) { if (Kind != otherSegment.Kind) { return false; } // Whole-line changes don't include the new line characters, // take those into consideration to properly identify a block of changes. int otherEndOffset = otherSegment.StartOffset + otherSegment.Length; return Math.Abs(StartOffset - otherEndOffset) <= Environment.NewLine.Length; } } public sealed class DiffLineHighlighter : IBackgroundRenderer { private Brush deletionBrush_; private Pen deletionPen_; private Brush insertionBrush_; private Pen insertionPen_; private Brush minorModificationBrush_; private Pen minorModificationPen_; private Brush modificationBrush_; private Pen modificationPen_; private Pen placeholderPen_; private DrawingBrush placeholderTileBrush_; private TextSegmentCollection segments_; public DiffLineHighlighter() { segments_ = new TextSegmentCollection(); placeholderPen_ = null; deletionPen_ = ColorPens.GetPen(App.Settings.DiffSettings.DeletionBorderColor); insertionPen_ = ColorPens.GetPen(App.Settings.DiffSettings.InsertionBorderColor); modificationPen_ = ColorPens.GetPen(App.Settings.DiffSettings.ModificationBorderColor); minorModificationPen_ = ColorPens.GetPen(App.Settings.DiffSettings.MinorModificationBorderColor); insertionBrush_ = ColorBrushes.GetBrush(App.Settings.DiffSettings.InsertionColor); deletionBrush_ = ColorBrushes.GetBrush(App.Settings.DiffSettings.DeletionColor); modificationBrush_ = ColorBrushes.GetBrush(App.Settings.DiffSettings.ModificationColor); minorModificationBrush_ = ColorBrushes.GetBrush(App.Settings.DiffSettings.MinorModificationColor); } public int Version { get; set; } public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { if (textView.Document == null || textView.Document.TextLength == 0) { return; } // Find start/end index of visible lines. if (!DocumentUtils.FindVisibleTextOffsets(textView, out int viewStart, out int viewEnd)) { return; } BackgroundGeometryBuilder geoBuilder = null; DiffTextSegment prevSegment = null; CreatePlaceholderTiledBrush(textView.DefaultLineHeight / 2); foreach (var segment in segments_.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { if (geoBuilder == null) { geoBuilder = CreateGeometryBuilder(); } else if (prevSegment != null && !segment.IsContinuation(prevSegment)) { DrawGeometry(geoBuilder, prevSegment, drawingContext); geoBuilder = CreateGeometryBuilder(); } geoBuilder.AddSegment(textView, segment); prevSegment = segment; } if (geoBuilder != null && prevSegment != null) { DrawGeometry(geoBuilder, prevSegment, drawingContext); } } public void ForEachDiffSegment(Action action) { foreach (var segment in segments_) { var pen = GetSegmentColor(segment, false); var color = pen != null ? ((SolidColorBrush)pen).Color : Colors.Transparent; action(segment, color); } } public void Add(DiffTextSegment segment) { segments_.Add(segment); Version++; } public void Add(List segments) { foreach (var segment in segments) { segments_.Add(segment); } Version++; } public void Clear() { segments_.Clear(); Version++; } private void CreatePlaceholderTiledBrush(double tileSize) { // Create the brush once, freeze and reuse it everywhere. if (placeholderTileBrush_ != null) { return; } tileSize = Math.Ceiling(tileSize); var line = new LineSegment(new Point(0, 0), true); line.IsSmoothJoin = false; line.Freeze(); var figure = new PathFigure(); figure.IsClosed = false; figure.StartPoint = new Point(tileSize, tileSize); figure.Segments.Add(line); figure.Freeze(); var geometry = new PathGeometry(); geometry.Figures.Add(figure); geometry.Freeze(); var drawing = new GeometryDrawing(); drawing.Geometry = geometry; var penBrush = ColorBrushes.GetBrush(App.Settings.DiffSettings.PlaceholderBorderColor); drawing.Pen = new Pen(penBrush, 0.5); drawing.Freeze(); var brush = new DrawingBrush(); brush.Drawing = drawing; brush.Stretch = Stretch.None; brush.TileMode = TileMode.Tile; brush.Viewbox = new Rect(0, 0, tileSize, tileSize); brush.ViewboxUnits = BrushMappingMode.Absolute; brush.Viewport = new Rect(0, 0, tileSize, tileSize); brush.ViewportUnits = BrushMappingMode.Absolute; RenderOptions.SetCachingHint(brush, CachingHint.Cache); brush.Freeze(); placeholderTileBrush_ = brush; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private Brush GetSegmentColor(DiffTextSegment segment, bool fromDrawing = true) { switch (segment.Kind) { case DiffKind.Deletion: return deletionBrush_; case DiffKind.Insertion: return insertionBrush_; case DiffKind.Placeholder: { return fromDrawing ? placeholderTileBrush_ : null; } case DiffKind.Modification: return modificationBrush_; case DiffKind.MinorModification: return minorModificationBrush_; } return ColorBrushes.Transparent; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private Pen GetSegmentPen(DiffTextSegment segment) { return segment.Kind switch { DiffKind.Deletion => deletionPen_, DiffKind.Insertion => insertionPen_, DiffKind.Modification => modificationPen_, DiffKind.MinorModification => minorModificationPen_, DiffKind.Placeholder => placeholderPen_, _ => null }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private BackgroundGeometryBuilder CreateGeometryBuilder() { var geoBuilder = new BackgroundGeometryBuilder(); geoBuilder.ExtendToFullWidthAtLineEnd = false; geoBuilder.AlignToWholePixels = true; geoBuilder.BorderThickness = 0; geoBuilder.CornerRadius = 0; return geoBuilder; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void DrawGeometry(BackgroundGeometryBuilder geoBuilder, DiffTextSegment segment, DrawingContext drawingContext) { var geometry = geoBuilder.CreateGeometry(); if (geometry != null) { drawingContext.DrawGeometry(GetSegmentColor(segment), GetSegmentPen(segment), geometry); } } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Highlighters/ElementHighlighter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Document; using ProtoBuf; namespace ProfileExplorer.UI; [ProtoContract] public class ElementGroupState { [ProtoMember(1)] public List Elements; [ProtoMember(2)] public HighlightingStyle Style; public ElementGroupState() { Elements = new List(); } } [ProtoContract] public class ElementHighlighterState { [ProtoMember(1)] public List Groups; public ElementHighlighterState() { Groups = new List(); } public ElementHighlighterState(List groups) { Groups = groups; } public bool HasAnnotations => Groups.Count > 0; } public sealed class ElementHighlighter : IBackgroundRenderer { //? TODO: Change to Set to have faster Remove (search panel) private List groups_; public ElementHighlighter(HighlighingType type) { Type = type; groups_ = new List(64); Version = 1; } public HighlighingType Type { get; set; } public int Version { get; set; } public List Groups { get => groups_; set => groups_ = value; } public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { if (textView.Document == null || textView.Document.TextLength == 0) { return; } // Find start/end index of visible lines. if (!DocumentUtils.FindVisibleTextOffsets(textView, out int viewStart, out int viewEnd)) { return; } // Query and draw visible segments from each group. foreach (var group in groups_) { DrawGroup(group, textView, drawingContext, viewStart, viewEnd); } } public void Add(HighlightedElementGroup group, bool saveToFile = true) { groups_.Add(new HighlightedSegmentGroup(group, saveToFile)); Version++; } public void Add(HighlightedSegmentGroup group) { groups_.Add(group); Version++; } public void AddFront(HighlightedElementGroup group, bool saveToFile = true) { groups_.Insert(0, new HighlightedSegmentGroup(group, saveToFile)); Version++; } public void CopyFrom(ElementHighlighter other) { foreach (var item in other.groups_) { groups_.Add(new HighlightedSegmentGroup(item.Group)); } Version++; } public void Remove(HighlightedElementGroup group) { for (int i = 0; i < groups_.Count; i++) { if (groups_[i].Group == group) { groups_.RemoveAt(i); break; } } Version++; } public void Remove(IRElement element) { for (int i = 0; i < groups_.Count; i++) { groups_[i].Group.Remove(element); if (groups_[i].Group.IsEmpty()) { groups_.RemoveAt(i); i--; } } Version++; } public void Clear() { groups_.Clear(); Version++; } public void ForEachElement(Action action) { groups_.ForEach(group => { group.Group.Elements.ForEach(action); }); } public void ForEachStyledElement(Action action) { groups_.ForEach(group => { group.Group.Elements.ForEach(element => { action(element, group.Group.Style); }); }); } public ElementHighlighterState SaveState(FunctionIR function) { return new ElementHighlighterState(UIStateSerializer.SaveElementGroupState(groups_)); } public void LoadState(ElementHighlighterState state, FunctionIR function) { if (state == null) { return; // Most likely a file from an older version of the app. } groups_ = UIStateSerializer.LoadElementGroupState(state.Groups); Version++; } private void DrawGroup(HighlightedSegmentGroup group, TextView textView, DrawingContext drawingContext, int viewStart, int viewEnd) { // Create BackgroundGeometryBuilder only if needed. BackgroundGeometryBuilder geoBuilder = null; var mergedRect = new Rect(); int prevMergedLine = -1; int mergedLineCount = 0; double prevMergedY = -1; foreach (var segment in group.Segments.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { if (geoBuilder == null) { geoBuilder = new BackgroundGeometryBuilder { BorderThickness = 0 }; } if (segment.Element is BlockIR) { geoBuilder.AddSegment(textView, segment); } else if (segment.Element is TupleIR) { int line = segment.Element.TextLocation.Line; // Extend width to cover entire line. foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) { double width = textView.ActualWidth + textView.HorizontalOffset; var actualRect = Utils.SnapRectToPixels(rect.X - 1, rect.Y, width, rect.Height); // When selecting multiple consecutive tuples, create a single // rect covering the region of each individual selection rect. // This is done to avoid horizontal lines showing sometimes otherwise. if (mergedLineCount > 0) { if (prevMergedLine == line - 1) { // Don't extend the accumulated height if the Y position // is unchanged, this happens with lines that are in a collapsed block folding. if (Math.Abs(actualRect.Y - prevMergedY) > double.Epsilon) { mergedRect = new Rect(mergedRect.Left, mergedRect.Top, Math.Max(mergedRect.Width, actualRect.Width), mergedRect.Height + actualRect.Height); } mergedLineCount++; prevMergedLine = line; prevMergedY = actualRect.Y; continue; } else { // Disjoint line, commit the current merged rect and start a new region. geoBuilder.AddRectangle(textView, mergedRect); } } mergedRect = actualRect; prevMergedLine = line; prevMergedY = actualRect.Y; mergedLineCount = 1; } } else { foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) { var actualRect = Utils.SnapRectToPixels(rect, -1, 0, 2, 1); geoBuilder.AddRectangle(textView, actualRect); } } } if (mergedLineCount > 0) { geoBuilder.AddRectangle(textView, mergedRect); } if (geoBuilder != null) { var geometry = geoBuilder.CreateGeometry(); if (geometry != null) { drawingContext.DrawGeometry(group.BackColor, group.Border, geometry); } } } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Highlighters/RemarkHighlighter.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows.Media; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Document; namespace ProfileExplorer.UI; public sealed class RemarkHighlighter : IBackgroundRenderer { //? TODO: Change to Set to have faster Remove (search panel) private List groups_; private Dictionary remarkBrushCache_; private int remarkBackgroundOpacity_; private bool useTransparentRemarkBackground_; public RemarkHighlighter(HighlighingType type) { Type = type; groups_ = new List(64); remarkBrushCache_ = new Dictionary(); Version = 1; } public HighlighingType Type { get; set; } public int Version { get; set; } public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { if (textView.Document == null || textView.Document.TextLength == 0) { return; } // Find start/end index of visible lines. if (!DocumentUtils.FindVisibleTextOffsets(textView, out int viewStart, out int viewEnd)) { return; } InvalidateRemarkBrushCache(); // Query and draw visible segments from each group. foreach (var group in groups_) { DrawGroup(group, textView, drawingContext, viewStart, viewEnd); } } public void Add(HighlightedElementGroup group, bool saveToFile = true) { groups_.Add(new HighlightedSegmentGroup(group, saveToFile)); Version++; } public void AddFront(HighlightedElementGroup group, bool saveToFile = true) { groups_.Insert(0, new HighlightedSegmentGroup(group, saveToFile)); Version++; } public void CopyFrom(RemarkHighlighter other) { foreach (var item in other.groups_) { groups_.Add(new HighlightedSegmentGroup(item.Group)); } Version++; } public void Remove(HighlightedElementGroup group) { for (int i = 0; i < groups_.Count; i++) { if (groups_[i].Group == group) { groups_.RemoveAt(i); break; } } Version++; } public void Remove(IRElement element) { for (int i = 0; i < groups_.Count; i++) { groups_[i].Group.Remove(element); if (groups_[i].Group.IsEmpty()) { groups_.RemoveAt(i); i--; } } Version++; } public void ChangeStyle(IRElement element, HighlightingStyle newStyle) { for (int i = 0; i < groups_.Count; i++) { if (groups_[i].Group.Contains(element)) { groups_[i].Group.Style = newStyle; break; } } Version++; } public void Clear() { groups_.Clear(); Version++; } public void ForEachElement(Action action) { groups_.ForEach(group => { group.Group.Elements.ForEach(action); }); } public void ForEachStyledElement(Action action) { groups_.ForEach(group => { group.Group.Elements.ForEach(element => { action(element, group.Group.Style); }); }); } private void DrawGroup(HighlightedSegmentGroup group, TextView textView, DrawingContext drawingContext, int viewStart, int viewEnd) { // Create BackgroundGeometryBuilder only if needed. BackgroundGeometryBuilder geoBuilder = null; foreach (var segment in group.Segments.FindOverlappingSegments(viewStart, viewEnd - viewStart)) { if (geoBuilder == null) { geoBuilder = new BackgroundGeometryBuilder { AlignToWholePixels = true, BorderThickness = 0, CornerRadius = 0 }; } foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) { var actualRect = Utils.SnapRectToPixels(rect, -1, 0, 2, 1); geoBuilder.AddRectangle(textView, actualRect); } } if (geoBuilder != null) { var geometry = geoBuilder.CreateGeometry(); if (geometry != null) { var brush = GetRemarkBackgroundBrush(group); drawingContext.DrawGeometry(brush, group.Border, geometry); } } } private void InvalidateRemarkBrushCache() { if (App.Settings.RemarkSettings.UseTransparentRemarkBackground != useTransparentRemarkBackground_ || App.Settings.RemarkSettings.RemarkBackgroundOpacity != remarkBackgroundOpacity_) { remarkBrushCache_.Clear(); useTransparentRemarkBackground_ = App.Settings.RemarkSettings.UseTransparentRemarkBackground; remarkBackgroundOpacity_ = App.Settings.RemarkSettings.RemarkBackgroundOpacity; } } private Brush GetRemarkBackgroundBrush(HighlightedSegmentGroup group) { if (!App.Settings.RemarkSettings.UseRemarkBackground) { return ColorBrushes.Transparent; } var color = ((SolidColorBrush)group.BackColor).Color; if (color == Colors.Black || color == Colors.Transparent) { return ColorBrushes.Transparent; } if (remarkBrushCache_.TryGetValue(color, out var brush)) { return brush; } if (useTransparentRemarkBackground_) { byte alpha = (byte)(255.0 * (remarkBackgroundOpacity_ / 100.0)); brush = ColorBrushes.GetBrush(Color.FromArgb(alpha, color.R, color.G, color.B)); } else { brush = ColorBrushes.GetBrush(color); } remarkBrushCache_[color] = brush; return brush; } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/IElementOverlay.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core.IR; using ProtoBuf; namespace ProfileExplorer.UI.Document; [ProtoContract] [ProtoInclude(100, typeof(ElementOverlayBase))] public interface IElementOverlay { public IRElement Element { get; set; } public HorizontalAlignment AlignmentX { get; } public VerticalAlignment AlignmentY { get; } public double MarginX { get; } public double MarginY { get; } public double Padding { get; } Size Size { get; } Rect Bounds { get; } public bool IsMouseOver { get; set; } public bool IsSelected { get; set; } public bool ShowOnMarkerBar { get; set; } public bool SaveStateToFile { get; set; } object Tag { get; set; } public event MouseEventHandler OnClick; public event KeyEventHandler OnKeyPress; public event MouseEventHandler OnHover; public event MouseEventHandler OnHoverEnd; public void Draw(Rect elementRect, IRElement element, Typeface font, IElementOverlay previousOverlay, double horizontalOffset, DrawingContext drawingContext); public bool CheckIsMouseOver(Point point); public bool MouseClicked(MouseEventArgs e); public bool KeyPressed(KeyEventArgs e); public bool Hovered(MouseEventArgs e); public bool HoveredEnded(MouseEventArgs e); } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/IconDrawing.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Windows; using System.Windows.Media; using ProtoBuf; namespace ProfileExplorer.UI; [ProtoContract(SkipConstructor = true)] public class IconDrawing { public static readonly IconDrawing Empty = new(); public IconDrawing() { // Used for deserialization. } public IconDrawing(ImageSource icon, double proportion) { Icon = icon; Proportion = proportion; } [ProtoMember(1)] public string IconResourceName { get; set; } [ProtoMember(2)] public double Proportion { get; set; } public ImageSource Icon { get; set; } public static IconDrawing FromIconResource(string name) { if (!Application.Current.Resources.Contains(name)) { return null; } var icon = (ImageSource)Application.Current.Resources[name]; return new IconDrawing(icon, icon.Width / icon.Height) { IconResourceName = name }; } public void Draw(double x, double y, double size, double availableWidth, double availableHeight, DrawingContext drawingContext) { // This assumes the icon should be centered inside a rectangle {availableWidth, availableHeight} // with {x, y} as top-left corner, scaling down if available space is not enough. double height; double width; if (availableHeight < availableWidth) { height = Math.Min(size, availableHeight); width = height * Proportion; } else { height = Math.Min(size, availableWidth); width = height * Proportion; } y += (availableHeight - height) / 2; x += (availableWidth - width) / 2; // Center icon in the available space. var rect = Utils.SnapRectToPixels(x, y, width, height); drawingContext.DrawImage(Icon, rect); } public void Draw(double x, double y, double size, double avaiableWidth, double availableHeight, double opacity, DrawingContext drawingContext) { drawingContext.PushOpacity(opacity); Draw(x, y, size, avaiableWidth, availableHeight, drawingContext); drawingContext.Pop(); } [ProtoAfterDeserialization] private void AfterDeserialization() { if (!string.IsNullOrEmpty(IconResourceName)) { Icon = (ImageSource)Application.Current.Resources[IconResourceName]; } } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/MarkerScroolBar.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.UI.Document.Renderers; class MarkerScroolBar { } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/OverlayRenderer.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProtoBuf; namespace ProfileExplorer.UI.Document; [ProtoContract] public class ElementOverlayState { [ProtoMember(1)] public List>> Overlays; public ElementOverlayState() { Overlays = new List>>(); } } public sealed class OverlayRenderer : Canvas, IBackgroundRenderer { private TextView textView_; private ElementHighlighter highlighter_; private ConnectedElement rootConnectedElement_; private List connectedElements_; private TextSegmentCollection conntectedSegments_; private Dictionary connectedSegmentMap_; private Dictionary overlaySegmentMap_; private TextSegmentCollection overlaySegments_; private IElementOverlay hoveredOverlay_; private IElementOverlay selectedOverlay_; private ToolTip hoverTooltip_; private IElementOverlay tooltipOverlay_; private bool updateSuspended_; public OverlayRenderer(ElementHighlighter highlighter) { overlaySegments_ = new TextSegmentCollection(); overlaySegmentMap_ = new Dictionary(); SnapsToDevicePixels = true; IsHitTestVisible = true; Background = ColorBrushes.Transparent; // Needed for mouse events to fire... highlighter_ = highlighter; ClearConnectedElements(); } public int Version { get; set; } public Typeface TextFont { get; set; } public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { if (updateSuspended_) { return; } textView_ = textView; Width = textView.RenderSize.Width; Height = textView.RenderSize.Height; Children.Clear(); if (textView.Document == null || textView.Document.TextLength == 0) { return; } var visual = new DrawingVisual(); var overlayDC = visual.RenderOpen(); // Query and draw visible segments from each group. foreach (var group in highlighter_.Groups) { DrawGroup(group, textView, overlayDC); } Tuple hoverSegment = null; Tuple selectedSegment = null; IElementOverlay hoverPrevOverlay = null; IElementOverlay selectedPrevOverlay = null; foreach (var segment in overlaySegments_.FindOverlappingSegments(textView_)) { bool isBlockElement = segment.Element is BlockIR; IElementOverlay prevOverlay = null; foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) { foreach (var overlay in segment.Overlays) { // Draw hover/selected overlay last so that it shows up on top // in case there is some overlap between overlays. if (overlay == hoveredOverlay_) { hoverSegment = new Tuple(overlay, segment.Element, rect); hoverPrevOverlay = prevOverlay; prevOverlay = overlay; continue; } if (overlay == selectedOverlay_) { selectedSegment = new Tuple(overlay, segment.Element, rect); selectedPrevOverlay = prevOverlay; prevOverlay = overlay; continue; } overlay.Draw(rect, segment.Element, TextFont, prevOverlay, textView.HorizontalOffset, overlayDC); prevOverlay = overlay; } // For blocks, consider only the first line, otherwise the overlay // would be applied to each each tuple in the block. if (isBlockElement) { break; } } } if (selectedSegment != null) { selectedSegment.Item1.Draw(selectedSegment.Item3, selectedSegment.Item2, TextFont, selectedPrevOverlay, textView.HorizontalOffset, overlayDC); } if (hoverSegment != null) { hoverSegment.Item1.Draw(hoverSegment.Item3, hoverSegment.Item2, TextFont, hoverPrevOverlay, textView.HorizontalOffset, overlayDC); } double dotSize = 3; //var dotBackground = ColorBrushes.GetTransparentBrush(Colors.DarkRed, 255); //var dotPen = ColorPens.GetTransparentPen(Colors.DarkRed, 255); bool first = true; //? TODO: Disabled, used from IRDocument // Draw extra annotations for remarks in the same context. foreach (var connectedElement in connectedElements_) { var prevSegmentRect = GetRemarkSegmentRect(rootConnectedElement_.Element, textView); var segmentRect = GetRemarkSegmentRect(connectedElement.Element, textView); double horizontalOffset = 4; double verticalOffset = prevSegmentRect.Height / 2; var startPoint = Utils.SnapPointToPixels(prevSegmentRect.Right + horizontalOffset, prevSegmentRect.Top + verticalOffset); var endPoint = Utils.SnapPointToPixels(segmentRect.Right + horizontalOffset, segmentRect.Top + verticalOffset); var edgeStartPoint = startPoint; var edgeEndPoint = endPoint; double dx = endPoint.X - startPoint.X; double dy = endPoint.Y - startPoint.Y; var vect = new Vector(dy, -dx); var middlePoint = new Point(startPoint.X + dx / 2, startPoint.Y + dy / 2); double factor = FindBezierControlPointFactor(startPoint, endPoint); var controlPoint = middlePoint + -factor * vect; // Keep the control point in the horizontal bounds of the document. if (controlPoint.X < 0 || controlPoint.X > Width) { controlPoint = new Point(Math.Clamp(controlPoint.X, 0, Width), controlPoint.Y); } //overlayDC.DrawLine(ColorPens.GetPen(Colors.Green, 2), startPoint, middlePoint); //overlayDC.DrawLine(ColorPens.GetPen(Colors.Green, 2), middlePoint, endPoint); var startOrientation = FindArrowOrientation(new[] {edgeEndPoint, edgeStartPoint, controlPoint}, out var _); var orientation = FindArrowOrientation(new[] {edgeStartPoint, controlPoint, edgeEndPoint}, out var _); edgeStartPoint = edgeStartPoint + startOrientation * (dotSize - 1); edgeEndPoint = edgeEndPoint - orientation * dotSize * 2; var edgeGeometry = new StreamGeometry(); var edgeSC = edgeGeometry.Open(); edgeSC.BeginFigure(edgeStartPoint, false, false); edgeSC.BezierTo(edgeStartPoint, controlPoint, edgeEndPoint, true, false); DrawEdgeArrow(new[] {edgeStartPoint, controlPoint, edgeEndPoint}, edgeSC); //edgeSC.BeginFigure(edgeStartPoint, false, false); //edgeSC.LineTo(edgeEndPoint, true, false); //edgeSC.BeginFigure(startPoint, false, false); //edgeSC.LineTo(endPoint, true, false); // overlayDC.DrawLine(ColorPens.GetPen(Colors.Red, 2), startPoint, endPoint); //overlayDC.DrawLine(ColorPens.GetPen(Colors.Red, 2), point, point2); // overlayDC.DrawEllipse(connectedElement.Style.BackColor, connectedElement.Style.Border, endPoint, dotSize, dotSize); if (first) { overlayDC.DrawEllipse(rootConnectedElement_.Style.BackColor, rootConnectedElement_.Style.Border, startPoint, dotSize, dotSize); first = false; } edgeSC.Close(); edgeGeometry.Freeze(); overlayDC.DrawGeometry(connectedElement.Style.BackColor, connectedElement.Style.Border, edgeGeometry); //var text = DocumentUtils.CreateFormattedText(textView, i.ToString(), DefaultFont, 11, Brushes.Black); //overlayDC.DrawText(text, Utils.SnapPointToPixels(startPoint.X - text.Width / 2, startPoint.Y - text.Height / 2)); } overlayDC.Close(); Add(visual); if (hoverSegment != null) { ShowTooltip(hoverSegment.Item1); } } public void AddElementOverlay(IRElement element, IElementOverlay overlay, bool prepend = false) { overlay.Element = element; Version++; if (overlaySegmentMap_.TryGetValue(element, out var segment)) { if (prepend) { segment.Overlays.Insert(0, overlay); } else { segment.Overlays.Add(overlay); } } else { segment = new IROverlaySegment(element, overlay); overlaySegments_.Add(segment); overlaySegmentMap_[element] = segment; } } public bool RemoveAllElementOverlays(IRElement element, object onlyWithTag = null) { if (!overlaySegmentMap_.TryGetValue(element, out var segment)) return false; if (onlyWithTag != null) { segment.Overlays.RemoveAll(overlay => overlay.Tag == onlyWithTag); } else { segment.Overlays.Clear(); } if (segment.Overlays.Count == 0) { overlaySegmentMap_.Remove(element); overlaySegments_.Remove(segment); } Version++; return true; } public bool RemoveElementOverlay(IElementOverlay overlay) { if (!overlaySegmentMap_.TryGetValue(overlay.Element, out var segment)) return false; if (segment.Overlays.Remove(overlay)) { if (segment.Overlays.Count == 0) { overlaySegmentMap_.Remove(overlay.Element); overlaySegments_.Remove(segment); } Version++; return true; } return false; } public void ForEachElementOverlay(Action action) { foreach (var pair in overlaySegmentMap_) { action(pair.Key, pair.Value); } } public void SetRootElement(IRElement element, HighlightingStyle style) { ClearConnectedElements(); rootConnectedElement_ = new ConnectedElement(element, style); var segment = new IRSegment(element); conntectedSegments_.Add(segment); connectedSegmentMap_[element] = segment; } public void AddConnectedElement(IRElement element, HighlightingStyle style) { connectedElements_.Add(new ConnectedElement(element, style)); var segment = new IRSegment(element); conntectedSegments_.Add(segment); connectedSegmentMap_[element] = segment; } public void ClearConnectedElements() { rootConnectedElement_ = null; connectedElements_ = new List(); conntectedSegments_ = new TextSegmentCollection(); connectedSegmentMap_ = new Dictionary(); } public bool MouseClick(MouseEventArgs e) { return HandleMouseClicked(e.GetPosition(this), e); } public void MouseMoved(MouseEventArgs e) { HandleMouseMoved(e.GetPosition(this), e); } public new void MouseLeave() { HideTooltip(); if (hoveredOverlay_ != null) { hoveredOverlay_.IsMouseOver = false; hoveredOverlay_ = null; textView_.Redraw(); } } public bool KeyPressed(KeyEventArgs e) { if (selectedOverlay_ == null) return false; if (selectedOverlay_.KeyPressed(e)) { textView_.Redraw(); // Force refresh return true; } return false; } public void Clear() { Children.Clear(); ClearConnectedElements(); ClearElementOverlays(); Version++; } public void ClearElementOverlays() { overlaySegments_ = new TextSegmentCollection(); overlaySegmentMap_ = new Dictionary(); } public void Add(Visual drawingVisual) { // Hit testing and focus must be disabled to allow events to propagate properly. var visualHost = new VisualHost {Visual = drawingVisual}; visualHost.IsHitTestVisible = false; visualHost.Focusable = false; Children.Add(visualHost); } public void Add(UIElement element) { Children.Add(element); } public ElementOverlayState SaveState(FunctionIR function) { var state = new ElementOverlayState(); foreach (var pair in overlaySegmentMap_) { //? TODO: Casting to ElementOverlayBase is done to avoid issues when deserializing //? the IElementOverlay objects with protobuf-net. var savedOverlays = new List(); foreach (var overlay in pair.Value.Overlays) { if (overlay.SaveStateToFile) { savedOverlays.Add((ElementOverlayBase)overlay); } } if (savedOverlays.Count > 0) { state.Overlays.Add(new Tuple>(pair.Key, savedOverlays)); } } return state; } public void LoadState(ElementOverlayState state, FunctionIR function, Action registerAction) { if (state == null) { return; // Most likely a file from an older version of the app. } foreach (var item in state.Overlays) { foreach (var overlay in item.Item2) { registerAction(overlay); AddElementOverlay(item.Item1, overlay); } } Version++; } public void SuspendUpdate() { updateSuspended_ = true; } public void ResumeUpdate() { updateSuspended_ = false; } private Rect GetRemarkSegmentRect(IRElement element, TextView textView) { var segment = connectedSegmentMap_[element]; foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) { return rect; } // The segment is outside the visible document. // A visual line must be created for it, then extract the location. var line = textView.Document.GetLineByOffset(segment.StartOffset); var visualLine = textView.GetOrConstructVisualLine(line); var start = new TextViewPosition(textView.Document.GetLocation(segment.StartOffset)); var end = new TextViewPosition(textView.Document.GetLocation(segment.StartOffset + segment.Length)); int startColumn = visualLine.ValidateVisualColumn(start, false); int endColumn = visualLine.ValidateVisualColumn(end, false); foreach (var rect in BackgroundGeometryBuilder. GetRectsFromVisualSegment(textView, visualLine, startColumn, endColumn)) { return rect; } return Rect.Empty; } private double FindBezierControlPointFactor(Point a, Point b) { const double startLength = 20; const double startFactor = 0.5; const double endLength = 1000; const double endFactor = 0.2; const double slope = (endFactor - startFactor) / (endLength - startLength); const double intercept = slope * startLength - startFactor; double distance = (a - b).Length; return Math.Clamp(distance * slope + intercept, endFactor, startFactor); } private void ShowTooltip(IElementOverlay overlay) { if (!(overlay is ElementOverlayBase {HasToolTip: true} elementOverlay)) { return; } if (hoverTooltip_ != null && tooltipOverlay_ == elementOverlay) { return; // Already showing the right tooltip. } tooltipOverlay_ = elementOverlay; hoverTooltip_ ??= new ToolTip(); hoverTooltip_.Closed += (sender, args) => hoverTooltip_ = null; // Showing the tooltip from the Dispatcher somehow prevents // it from temporarily showing in the top-left screen corner // with an annoying flicker... Dispatcher.BeginInvoke(() => { hoverTooltip_.Placement = PlacementMode.Mouse; hoverTooltip_.PlacementTarget = textView_; hoverTooltip_.Content = elementOverlay.ToolTip; hoverTooltip_.IsOpen = true; }); } private void HideTooltip() { if (hoverTooltip_ != null) { hoverTooltip_.IsOpen = false; } } private void DrawEdgeArrow(Point[] tempPoints, StreamGeometryContext sc) { // Draw arrow head with a slope matching the line, // this uses the last two points to find the angle. Point start; var v = FindArrowOrientation(tempPoints, out start); sc.BeginFigure(start + v * 5, true, true); double t = v.X; v.X = v.Y; v.Y = -t; // Rotate 90 sc.LineTo(start + v * 5, true, true); sc.LineTo(start + v * -5, true, true); } private Vector FindArrowOrientation(Point[] tempPoints, out Point start) { for (int i = tempPoints.Length - 1; i > 0; i--) { start = tempPoints[i]; var v = start - tempPoints[i - 1]; if (v.LengthSquared != 0) { v.Normalize(); return v; } } return new Vector(0, 0); } private void HandleMouseMoved(Point point, MouseEventArgs e) { if (overlaySegments_.Count == 0 || textView_ == null) { return; } IElementOverlay hoverOverlay = null; foreach (var segment in overlaySegments_.FindOverlappingSegments(textView_)) { if (hoverOverlay != null) { break; } foreach (var overlay in segment.Overlays) { if (overlay.CheckIsMouseOver(point)) { hoverOverlay = overlay; break; } } } if (hoverOverlay != hoveredOverlay_) { if (hoveredOverlay_ != null) { // Deselect previous overlay. hoveredOverlay_.IsMouseOver = false; hoveredOverlay_.HoveredEnded(e); hoveredOverlay_ = null; } if (hoverOverlay != null) { hoverOverlay.IsMouseOver = true; hoveredOverlay_ = hoverOverlay; hoveredOverlay_.Hovered(e); } HideTooltip(); textView_.Redraw(); } } private bool HandleMouseClicked(Point point, MouseEventArgs e) { if (overlaySegments_.Count == 0 || textView_ == null) { return false; } IElementOverlay hoverOverlay = null; bool redraw = false; foreach (var segment in overlaySegments_.FindOverlappingSegments(textView_)) { if (hoverOverlay != null) { break; } foreach (var overlay in segment.Overlays) { if (overlay.CheckIsMouseOver(point)) { hoverOverlay = overlay; break; } } } if (hoverOverlay != selectedOverlay_) { if (selectedOverlay_ != null) { // Deselect previous overlay. selectedOverlay_.IsSelected = false; selectedOverlay_ = null; redraw = true; } if (hoverOverlay != null) { selectedOverlay_ = hoverOverlay; selectedOverlay_.IsSelected = true; redraw = true; } } // Send click event to selected overlay. if (selectedOverlay_ != null) { if (selectedOverlay_.MouseClicked(e)) { redraw = true; } } if (redraw) { textView_.Redraw(); } return hoverOverlay != null; } private void DrawGroup(HighlightedSegmentGroup group, TextView textView, DrawingContext drawingContext) { IRElement element = null; double fontSize = App.Settings.DocumentSettings.FontSize; foreach (var segment in group.Segments.FindOverlappingSegments(textView_)) { element = segment.Element; foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, segment)) { var notesTag = element.GetTag(); if (notesTag != null) { string label = notesTag.Title; //? TODO: Show only on hover //if(notesTag.Notes.Count > 0) //{ // label += $", {notesTag.Notes[0]}"; //} var pen = group.Border ?? ColorPens.GetPen(Colors.Gray); var text = DocumentUtils.CreateFormattedText(textView, label, TextFont, fontSize, Brushes.Black); drawingContext.DrawRectangle(group.BackColor, pen, Utils.SnapRectToPixels(rect.X + rect.Width + 8, rect.Y, text.Width + 10, textView.DefaultLineHeight + 1)); drawingContext.DrawText(text, Utils.SnapPointToPixels(rect.X + rect.Width + 12, rect.Y + 1)); } } } } public sealed class IROverlaySegment : IRSegment { public IROverlaySegment(IRElement element, IElementOverlay overlay) : base(element) { Overlays = new List(); Overlays.Add(overlay); } public List Overlays { get; set; } } private class VisualHost : FrameworkElement { public Visual Visual { get; set; } protected override int VisualChildrenCount => Visual != null ? 1 : 0; protected override Visual GetVisualChild(int index) { return Visual; } } private class ConnectedElement { public ConnectedElement(IRElement element, HighlightingStyle style) { Element = element; Style = style; } public IRElement Element { get; set; } public HighlightingStyle Style { get; set; } } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Overlays/ElementOverlayBase.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Windows; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; using ProtoBuf; namespace ProfileExplorer.UI.Document; [ProtoContract(SkipConstructor = true)] [ProtoInclude(200, typeof(IconElementOverlay))] public abstract class ElementOverlayBase : IElementOverlay { private static readonly Typeface DefaultFont = new("Consolas"); private Rect labelBounds_; [ProtoMember(1)] private IRElementReference elementRef_; protected ElementOverlayBase() { // Used for deserialization. } protected ElementOverlayBase(double width, double height, double marginX, double marginY, HorizontalAlignment alignmentX, VerticalAlignment alignmentY, string label, string tooltip) { Label = label; ToolTip = tooltip; Width = width; Height = height; MarginX = marginX; MarginY = marginY; AlignmentX = alignmentX; AlignmentY = alignmentY; DefaultOpacity = 1; SaveStateToFile = false; } [ProtoMember(2)] public string Label { get; set; } [ProtoMember(3)] public double Width { get; set; } [ProtoMember(4)] public double Height { get; set; } [ProtoMember(10)] public bool ShowBackgroundOnMouseOverOnly { get; set; } [ProtoMember(11)] public bool ShowBorderOnMouseOverOnly { get; set; } [ProtoMember(12)] public bool ShowLabelOnMouseOverOnly { get; set; } [ProtoMember(13)] public bool UseLabelBackground { get; set; } [ProtoMember(14)] public bool AllowLabelEditing { get; set; } [ProtoMember(15)] public bool IsLabelPinned { get; set; } [ProtoMember(17)] public double DefaultOpacity { get; set; } [ProtoMember(18)] public double MouseOverOpacity { get; set; } [ProtoMember(19)] public Brush Background { get; set; } [ProtoMember(20)] public Brush SelectedBackground { get; set; } [ProtoMember(21)] public Pen Border { get; set; } [ProtoMember(22)] public Brush TextColor { get; set; } [ProtoMember(23)] public Brush SelectedTextColor { get; set; } [ProtoMember(24)] public int TextSize { get; set; } [ProtoMember(25)] public FontWeight TextWeight { get; set; } [ProtoMember(26)] public double VirtualColumn { get; set; } [ProtoMember(27)] public string ToolTip { get; set; } public bool HasLabel => !string.IsNullOrEmpty(Label); public bool HasToolTip => !string.IsNullOrEmpty(ToolTip); protected virtual bool ShowLabel => !string.IsNullOrEmpty(Label) && (!ShowLabelOnMouseOverOnly || IsLabelPinned || IsMouseOver || IsSelected); protected virtual bool ShowBackground => Width > 0 && Height > 0 && (!ShowBackgroundOnMouseOverOnly || IsMouseOver || IsSelected); protected virtual bool ShowBorder => !ShowBorderOnMouseOverOnly || IsMouseOver || IsSelected; protected virtual Brush CurrentBackgroundBrush => IsSelected && SelectedBackground != null ? SelectedBackground : Background; protected virtual Pen CurrentBorder => ShowBorder ? Border : null; protected virtual Brush CurrentLabelBackgroundBrush => Background == null || IsSelected && SelectedBackground != null ? SelectedBackground : Background; protected virtual Brush ActiveTextBrush => IsSelected && SelectedTextColor != null ? SelectedTextColor : TextColor ?? Brushes.Black; protected virtual double ActiveOpacity => IsMouseOver || IsSelected ? MouseOverOpacity > 0 ? MouseOverOpacity : 1.0 : DefaultOpacity > 0 ? DefaultOpacity : 1.0; protected double ActualWidth => Width + 2 * Padding; protected double ActualHeight => Height + 2 * Padding; public event MouseEventHandler OnClick; public event KeyEventHandler OnKeyPress; public event MouseEventHandler OnHover; public event MouseEventHandler OnHoverEnd; [ProtoMember(5)] public double MarginX { get; set; } [ProtoMember(6)] public double MarginY { get; set; } [ProtoMember(7)] public double Padding { get; set; } public Size Size => new(ActualWidth, ActualHeight); [ProtoMember(8)] public HorizontalAlignment AlignmentX { get; set; } [ProtoMember(9)] public VerticalAlignment AlignmentY { get; set; } [ProtoMember(16)] public bool ShowOnMarkerBar { get; set; } public Rect Bounds { get; set; } [ProtoMember(28)] public bool SaveStateToFile { get; set; } [ProtoMember(29)] public object Tag { get; set; } public bool IsMouseOver { get; set; } public bool IsSelected { get; set; } public IRElement Element { get => elementRef_; set => elementRef_ = value; } public abstract void Draw(Rect elementRect, IRElement element, Typeface font, IElementOverlay previousOverlay, double horizontalOffset, DrawingContext drawingContext); public virtual bool CheckIsMouseOver(Point point) { IsMouseOver = Bounds.Contains(point); if (!IsMouseOver && ShowLabel) { IsMouseOver = labelBounds_.Contains(point); } return IsMouseOver; } public virtual bool Hovered(MouseEventArgs e) { OnHover?.Invoke(this, e); return true; } public virtual bool MouseClicked(MouseEventArgs e) { OnClick?.Invoke(this, e); return e.Handled; } public virtual bool KeyPressed(KeyEventArgs e) { OnKeyPress?.Invoke(this, e); if (!IsSelected) { return e.Handled; } if (AllowLabelEditing) { var keyInfo = Utils.KeyToChar(e.Key); if (keyInfo.IsLetter && Keyboard.Modifiers == ModifierKeys.None) { // Append a new letter. string keyString = keyInfo.Letter.ToString(); if (string.IsNullOrEmpty(Label)) { Label = keyString; } else { Label += keyString; } return true; } else if (e.Key == Key.Back) { // Remove last letter. if (!string.IsNullOrEmpty(Label)) { Label = Label.Substring(0, Label.Length - 1); return true; } } else if (e.Key == Key.Delete) { Label = null; // Delete all text. return true; } else if (e.Key == Key.Enter) { IsLabelPinned = true; return true; } else if (e.Key == Key.Escape) { IsLabelPinned = false; return true; } } if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control) { // Copy the label to the clipboard. if (HasToolTip) { Clipboard.Clear(); Clipboard.SetText($"{Label}\n{ToolTip}", TextDataFormat.UnicodeText); } else { Clipboard.Clear(); Clipboard.SetText(Label, TextDataFormat.UnicodeText); } return true; } return e.Handled; } public bool HoveredEnded(MouseEventArgs e) { OnHoverEnd?.Invoke(this, e); return true; } protected void DrawBackground(Rect elementRect, double opacity, DrawingContext drawingContext) { if ((ShowBackground || ShowBorder) && !(ShowLabel && UseLabelBackground)) { drawingContext.PushOpacity(opacity); drawingContext.DrawRectangle(CurrentBackgroundBrush, CurrentBorder, elementRect); drawingContext.Pop(); } } protected Rect DrawLabel(Rect elementRect, Typeface font, double opacity, DrawingContext drawingContext) { var host = Application.Current.MainWindow; // Used to get DPI. double fontSize = TextSize != 0 ? TextSize : App.Settings.DocumentSettings.FontSize; var text = DocumentUtils.CreateFormattedText(host, Label, font, fontSize, ActiveTextBrush, TextWeight); int lines = Label.CountLines(); double extraHeight = lines > 1 ? elementRect.Height * (lines - 1) : 0; double height = elementRect.Height + extraHeight; double width = elementRect.Width + text.WidthIncludingTrailingWhitespace + 2 * Padding; double textX = elementRect.Left + elementRect.Width + Padding; double textY = elementRect.Top + height / 2 - text.Height / 2; labelBounds_ = Utils.SnapRectToPixels(elementRect.X, elementRect.Y, width, height); drawingContext.PushOpacity(opacity); if (UseLabelBackground) { // Draw a rectangle covering both the icon and label. drawingContext.DrawRectangle(CurrentLabelBackgroundBrush, CurrentBorder, labelBounds_); } drawingContext.DrawText(text, Utils.SnapPointToPixels(textX, textY)); drawingContext.Pop(); return labelBounds_; } protected double ComputePositionX(Rect rect, IElementOverlay previousOveraly, double horizontalOffset) { if (AlignmentX == HorizontalAlignment.Left) { double leftEdgeX = rect.Left; if (previousOveraly != null && previousOveraly.AlignmentX == HorizontalAlignment.Left) { // Align to the right of the previous overlay. leftEdgeX = Math.Max(rect.Left, previousOveraly.Bounds.Right); } return Utils.SnapToPixels(leftEdgeX + MarginX); } if (AlignmentX == HorizontalAlignment.Right) { double rightEdgeX = rect.Right; if (previousOveraly != null && previousOveraly.AlignmentX == HorizontalAlignment.Right) { // Align to the right of the previous overlay. rightEdgeX = Math.Max(rect.Right, previousOveraly.Bounds.Right); } // Consider the horizontal scrollbar offset change. return Utils.SnapToPixels(Math.Max(VirtualColumn - horizontalOffset, rightEdgeX + MarginX - horizontalOffset)); } return Utils.SnapToPixels(rect.Left + (rect.Width - ActualWidth) / 2); } protected double ComputeHeight(Rect rect) { if (Height > 0) { return Math.Min(ActualHeight, rect.Height); } return rect.Height; } protected double ComputePositionY(Rect rect, IElementOverlay previousOveraly) { if (AlignmentY == VerticalAlignment.Top) { return Utils.SnapToPixels(rect.Top - ComputeHeight(rect) - MarginY); } if (AlignmentY == VerticalAlignment.Bottom) { return Utils.SnapToPixels(rect.Bottom + MarginY); } return Utils.SnapToPixels(rect.Top + (rect.Height - ComputeHeight(rect)) / 2); } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Overlays/IconElementOverlay.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Media; using ProfileExplorer.Core.IR; using ProtoBuf; namespace ProfileExplorer.UI.Document; [ProtoContract(SkipConstructor = true)] public sealed class IconElementOverlay : ElementOverlayBase { public IconElementOverlay() { // Used by deserialization. } public IconElementOverlay(IconDrawing icon, double width, double height, string label, string tooltip, HorizontalAlignment alignmentX, VerticalAlignment alignmentY, double marginX, double marginY) : base(width, height, marginX, marginY, alignmentX, alignmentY, label, tooltip) { Icon = icon; } [ProtoMember(1)] public IconDrawing Icon { get; set; } public static IconElementOverlay CreateDefault(IconDrawing icon, double width, double height, Brush backColor, Brush selectedBackColor, Pen border, string label = "", string tooltip = "", HorizontalAlignment alignmentX = HorizontalAlignment.Right, VerticalAlignment alignmentY = VerticalAlignment.Center, double marginX = 4, double marginY = 4, double padding = 2) { return new IconElementOverlay(icon, width, height, label, tooltip, alignmentX, alignmentY, marginX, marginY) { Background = backColor, SelectedBackground = selectedBackColor, Border = border, ShowBackgroundOnMouseOverOnly = true, ShowBorderOnMouseOverOnly = true, ShowLabelOnMouseOverOnly = true, UseLabelBackground = true, Padding = padding, AllowLabelEditing = true }; } public override void Draw(Rect elementRect, IRElement element, Typeface font, IElementOverlay previousOverlay, double horizontalOffset, DrawingContext drawingContext) { double x = ComputePositionX(elementRect, previousOverlay, horizontalOffset); double y = ComputePositionY(elementRect, previousOverlay); double opacity = ActiveOpacity; Bounds = Utils.SnapRectToPixels(x, y, ActualWidth, ComputeHeight(elementRect)); double iconHeight = Bounds.Height; if (ShowLabel) { if (Icon == null) { Bounds = Utils.SnapRectToPixels(Bounds.X + Bounds.Width, Bounds.Y, 0, Bounds.Height); } Bounds = DrawLabel(Bounds, font, opacity, drawingContext); } if (Icon != null) { DrawBackground(Bounds, opacity, drawingContext); Icon.Draw(x + 1, y - 1, Width, Width, iconHeight, opacity, drawingContext); } // For debugging, border around whole element. // drawingContext.DrawRectangle(ColorBrushes.Transparent, ColorPens.GetPen(Colors.Red), elementRect); } } ================================================ FILE: src/ProfileExplorerUI/Document/Renderers/Overlays/TextElementOverlay.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Media; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI.Document; public sealed class TextElementOverlay : ElementOverlayBase { public TextElementOverlay(string text, double width, double height, double marginX = 2, double marginY = 2, HorizontalAlignment alignmentX = HorizontalAlignment.Right, VerticalAlignment alignmentY = VerticalAlignment.Center, string toolTip = "") : base(width, height, marginX, marginY, alignmentX, alignmentY, text, toolTip) { } public override void Draw(Rect elementRect, IRElement element, Typeface font, IElementOverlay previousOverlay, double horizontalOffset, DrawingContext drawingContext) { } } ================================================ FILE: src/ProfileExplorerUI/Document/SearchInfo.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.ComponentModel; using ProtoBuf; namespace ProfileExplorer.UI.Document; [ProtoContract] public class SearchInfo : INotifyPropertyChanged { [ProtoMember(1)] private int currentResult_; [ProtoMember(2)] private TextSearchKind kind_; [ProtoMember(3)] private int resultCount_; [ProtoMember(4)] private bool searchAllEnabled_; [ProtoMember(5)] private bool searchAll_; [ProtoMember(6)] private string searchedText_; [ProtoMember(7)] private bool showSearchAllButton_; [ProtoMember(8)] private bool showNavigationSection_; public SearchInfo() { searchedText_ = string.Empty; kind_ = TextSearchKind.CaseInsensitive; showSearchAllButton_ = true; searchAllEnabled_ = true; showNavigationSection_ = true; } public TextSearchKind SearchKind { get => kind_; set => kind_ = value; } public string SearchedText { get => searchedText_; set { if (value != searchedText_) { searchedText_ = value; OnPropertyChange(nameof(SearchedText)); } } } public bool HasSearchedText => !string.IsNullOrEmpty(searchedText_); public bool IsCaseInsensitive { get => kind_.HasFlag(TextSearchKind.CaseInsensitive); set { if (SetKindFlag(TextSearchKind.CaseInsensitive, value)) { OnPropertyChange(nameof(IsCaseInsensitive)); } } } public bool IsWholeWord { get => kind_.HasFlag(TextSearchKind.WholeWord); set { if (SetKindFlag(TextSearchKind.WholeWord, value)) { OnPropertyChange(nameof(IsWholeWord)); } } } public bool IsRegex { get => kind_.HasFlag(TextSearchKind.Regex); set { if (SetKindFlag(TextSearchKind.Regex, value)) { OnPropertyChange(nameof(IsRegex)); } } } public bool SearchAll { get => searchAll_ && searchAllEnabled_; set { if (value != searchAll_) { searchAll_ = value; OnPropertyChange(nameof(SearchAll)); } } } public bool SearchAllEnabled { get => searchAllEnabled_; set { if (value != searchAllEnabled_) { searchAllEnabled_ = value; OnPropertyChange(nameof(SearchAllEnabled)); } } } public int ResultCount { get => resultCount_; set { if (resultCount_ != value) { resultCount_ = value; OnPropertyChange(nameof(ResultText)); } } } public int CurrentResult { get => currentResult_; set { if (currentResult_ != value) { currentResult_ = value; OnPropertyChange(nameof(ResultText)); } } } public string ResultText => $"{(resultCount_ > 0 ? currentResult_ + 1 : 0)} / {resultCount_}"; public bool ShowSearchAllButton { get => showSearchAllButton_; set { if (value != showSearchAllButton_) { showSearchAllButton_ = value; OnPropertyChange(nameof(ShowSearchAllButton)); } } } public bool ShowNavigationSection { get => showNavigationSection_; set { if (value != showNavigationSection_) { showNavigationSection_ = value; OnPropertyChange(nameof(ShowNavigationSection)); } } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChange(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } private bool SetKindFlag(TextSearchKind flag, bool value) { if (value && !kind_.HasFlag(flag)) { kind_ |= flag; return true; } if (!value && kind_.HasFlag(flag)) { kind_ &= ~flag; return true; } return false; } } ================================================ FILE: src/ProfileExplorerUI/Document/SearchPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Document/SearchPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace ProfileExplorer.UI.Document; public static class SearchCommand { public static readonly RoutedUICommand PreviousResult = new("Untitled", "PreviousResult", typeof(SearchPanel)); public static readonly RoutedUICommand NextResult = new("Untitled", "NextResult", typeof(SearchPanel)); public static readonly RoutedUICommand ClearText = new("Untitled", "ClearText", typeof(SearchPanel)); public static readonly RoutedUICommand ToggleCaseSensitive = new("Untitled", "ToggleCaseSensitive", typeof(SearchPanel)); public static readonly RoutedUICommand ToggleWholeWord = new("Untitled", "ToggleWholeWord", typeof(SearchPanel)); public static readonly RoutedUICommand ToggleRegex = new("Untitled", "ToggleRegex", typeof(SearchPanel)); public static readonly RoutedUICommand ToggleSearchAll = new("Untitled", "ToggleSearchAll", typeof(SearchPanel)); } public partial class SearchPanel : UserControl { private SearchInfo searchInfo_; private bool selectTextOnFocus_; public SearchPanel() { InitializeComponent(); UseAutoComplete = true; // The AutoCompleteBox has no SelectAll method, get the underlying TextBox // to do that when it gets focus. var textBox = Utils.FindChild(TextSearch); if (textBox != null) { textBox.GotFocus += TextBox_GotFocus; } } public SearchInfo SearchInfo => searchInfo_; public bool UseAutoComplete { get; set; } public event EventHandler SearchChanged; public event EventHandler NavigateToNextResult; public event EventHandler NavigateToPreviousResult; public event EventHandler CloseSearchPanel; public void Show(SearchInfo initialInfo = null, bool searchAll = false, bool selectTextOnFocus = false) { Reset(initialInfo, searchAll); selectTextOnFocus_ = selectTextOnFocus; Keyboard.Focus(TextSearch); } public void Hide() { if (UseAutoComplete) { string text = TextSearch.Text; if (text.Trim().Length > 0) { App.Settings.AddRecentTextSearch(text); } } } public void Reset(SearchInfo initialInfo = null, bool searchAll = false) { if (searchInfo_ != null) { searchInfo_.PropertyChanged -= SearchInfo__PropertyChanged; if (initialInfo == null) { var temp = new SearchInfo(); temp.SearchAll = searchInfo_.SearchAll; temp.SearchKind = searchInfo_.SearchKind; searchInfo_ = temp; } } if (initialInfo != null) { searchInfo_ = initialInfo; } else if (searchInfo_ == null) { searchInfo_ = new SearchInfo(); searchInfo_.SearchAll = searchAll; } DataContext = searchInfo_; searchInfo_.PropertyChanged += SearchInfo__PropertyChanged; if (initialInfo == null || initialInfo.ResultCount == 0) { SearchChanged?.Invoke(this, searchInfo_); } } private void TextBox_GotFocus(object sender, RoutedEventArgs e) { if (selectTextOnFocus_) { ((TextBox)sender).SelectAll(); selectTextOnFocus_ = false; } } private void SearchInfo__PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName != "ResultText") { searchInfo_.CurrentResult = 0; searchInfo_.ResultCount = 0; SearchChanged?.Invoke(this, searchInfo_); } } private void PreviousResultExecuted(object sender, ExecutedRoutedEventArgs e) { if (searchInfo_.CurrentResult > 0) { searchInfo_.CurrentResult--; NavigateToPreviousResult?.Invoke(this, searchInfo_); } } private void NextResultExecuted(object sender, ExecutedRoutedEventArgs e) { if (searchInfo_.CurrentResult < searchInfo_.ResultCount - 1) { searchInfo_.CurrentResult++; NavigateToNextResult?.Invoke(this, searchInfo_); } } private void PreviousResultCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = NavigateToPreviousResult != null; } private void NextResultCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = NavigateToNextResult != null; } private void ClearTextExecuted(object sender, ExecutedRoutedEventArgs e) { if (TextSearch.Text == "") { CloseSearchPanel?.Invoke(this, searchInfo_); } else { ClearSearchedText(); } } private void ClearSearchedText() { TextSearch.Text = ""; Reset(); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private void TextSearch_Loaded(object sender, RoutedEventArgs e) { Keyboard.Focus((AutoCompleteBox)sender); } private void TextSearch_Populating(object sender, PopulatingEventArgs e) { if (UseAutoComplete) { var box = (AutoCompleteBox)sender; box.ItemsSource = null; box.ItemsSource = App.Settings.RecentTextSearches; box.PopulateComplete(); } } private void ToggleCaseSensitiveExecuted(object sender, ExecutedRoutedEventArgs e) { searchInfo_.IsCaseInsensitive = !searchInfo_.IsCaseInsensitive; } private void ToggleWholeWordExecuted(object sender, ExecutedRoutedEventArgs e) { searchInfo_.IsWholeWord = !searchInfo_.IsWholeWord; } private void ToggleRegexExecuted(object sender, ExecutedRoutedEventArgs e) { searchInfo_.IsRegex = !searchInfo_.IsRegex; } private void ToggleSearchAllExecuted(object sender, ExecutedRoutedEventArgs e) { searchInfo_.SearchAll = !searchInfo_.SearchAll; } } ================================================ FILE: src/ProfileExplorerUI/Document/SearcheableIRDocument.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Document/SearcheableIRDocument.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using ICSharpCode.AvalonEdit.Highlighting; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI.Document; public static class SearcheableIRDocumentCommand { public static readonly RoutedUICommand ToggleSearch = new("Untitled", "ToggleSearch", typeof(SearcheableIRDocument)); } public partial class SearcheableIRDocument : UserControl, INotifyPropertyChanged { private bool searchPanelVisible_; private List searchResults_; public SearcheableIRDocument() { InitializeComponent(); DataContext = this; SearchPanel.SearchChanged += SearchPanel_SearchChanged; SearchPanel.CloseSearchPanel += SearchPanel_CloseSearchPanel; SearchPanel.NavigateToPreviousResult += SearchPanel_NaviateToPreviousResult; SearchPanel.NavigateToNextResult += SearchPanel_NavigateToNextResult; } public bool SearchPanelVisible { get => searchPanelVisible_; set { if (value != searchPanelVisible_) { searchPanelVisible_ = value; if (searchPanelVisible_) { SearchPanel.Visibility = Visibility.Visible; SearchPanel.Show(); } else { SearchPanel.Reset(); SearchPanel.Visibility = Visibility.Collapsed; } OnPropertyChange("SearchPanelVisible"); } } } public IUISession Session { get => TextView.Session; set => TextView.Session = value; } public bool UseAutoComplete { get => SearchPanel.UseAutoComplete; set => SearchPanel.UseAutoComplete = value; } public bool FilterSearchResults { get => TextView.SearchMode == LightIRDocument.TextSearchMode.Filter; set { var prevSearchMode = TextView.SearchMode; TextView.SearchMode = value ? LightIRDocument.TextSearchMode.Filter : LightIRDocument.TextSearchMode.Mark; if (TextView.SearchMode != prevSearchMode) { Dispatcher.InvokeAsync(async () => await SearchText()); OnPropertyChange("FilterSearchResults"); } } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChange(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } public async Task SetText(string text, IHighlightingDefinition syntaxHighlighting = null) { await TextView.SwitchText(text); TextView.SyntaxHighlighting = syntaxHighlighting; } public async Task SetText(string text, FunctionIR function, IRTextSection section, IRDocument associatedDocument, IUISession session) { TextView.Session = session; await TextView.SwitchText(text, function, section, associatedDocument); } public void SelectText(int offset, int length, int line) { TextView.Select(offset, length); TextView.ScrollToLine(line); } public void ScrollToEnd() { TextView.ScrollToEnd(); } private async Task SearchText(SearchInfo info = null) { if (info == null) { if (searchPanelVisible_) { info = SearchPanel.SearchInfo; } else { //? TODO: Should rather be an assert #if DEBUG MessageBox.Show("SearchText without searchPanelVisible_, attach debugger"); Utils.WaitForDebugger(); #endif return; } } searchResults_ = await TextView.SearchText(info); if (searchResults_ != null && searchResults_.Count > 0) { info.ResultCount = searchResults_.Count; TextView.JumpToSearchResult(searchResults_[0]); } } private void SearchPanel_NaviateToPreviousResult(object sender, SearchInfo e) { if (searchResults_ == null) { return; } TextView.JumpToSearchResult(searchResults_[e.CurrentResult]); } private void SearchPanel_NavigateToNextResult(object sender, SearchInfo e) { if (searchResults_ == null) { return; } TextView.JumpToSearchResult(searchResults_[e.CurrentResult]); } private void SearchPanel_CloseSearchPanel(object sender, SearchInfo e) { SearchPanelVisible = false; } private async void SearchPanel_SearchChanged(object sender, SearchInfo e) { await SearchText(e); } private void ToggleSearchExecuted(object sender, ExecutedRoutedEventArgs e) { SearchPanelVisible = !SearchPanelVisible; } } ================================================ FILE: src/ProfileExplorerUI/GlobalSuppressions.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:ProfileExplorer.UI.UTCRemarkProvider.GetSectionList(Core.IRTextSection,System.Int32)~System.Collections.Generic.List{Core.IRTextSection}")] [assembly: SuppressMessage("Design", "CA1062:Validate arguments of public methods", Justification = "", Scope = "member", Target = "~M:ProfileExplorer.UI.UTCRemarkProvider.ExtractAllRemarks(System.Collections.Generic.List{Core.IRTextSection},Core.IR.FunctionIR,Client.LoadedDocument)~System.Collections.Generic.List{Client.Remark}")] ================================================ FILE: src/ProfileExplorerUI/GrpcServer/DebugSectionLoader.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading.Tasks; using ProfileExplorer.Core; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI; public class DebugSectionLoader : IRTextSectionLoader { private Dictionary sectionTextMap_; private IRTextSummary summary_; private IRTextSection lastSection_; private string lastSectionText_; public DebugSectionLoader(ICompilerIRInfo irInfo) { Initialize(irInfo, false); sectionTextMap_ = new Dictionary(); } public async override Task LoadDocument(ProgressInfoHandler progressHandler) { return summary_ ??= new IRTextSummary(); } public override string GetDocumentOutputText() { var builder = new StringBuilder(); var list = new List>(); foreach (var pair in sectionTextMap_) { list.Add(new Tuple(pair.Key, pair.Value)); } list.Sort((a, b) => a.Item1.Number.CompareTo(b.Item1.Number)); foreach (var pair in list) { builder.AppendLine(pair.Item1.Name); // Section name. builder.AppendLine(pair.Item2.ToString()); // Section text. builder.AppendLine(); } return builder.ToString(); } public override byte[] GetDocumentTextBytes() { return Encoding.UTF8.GetBytes(GetDocumentOutputText()); } public void AddSection(IRTextSection section, string text) { Trace.TraceInformation($"Adding section {section.Name}, length {text.Length}"); sectionTextMap_[section] = new CompressedString(text); lastSection_ = section; lastSectionText_ = text; } public override ParsedIRTextSection LoadSection(IRTextSection section) { lock (lockObject_) { Trace.TraceInformation( $"Debug section loader {ObjectTracker.Track(this)}: ({section.Number}) {section.Name}"); if (cacheEnabled_ && sectionCache_.TryGetValue(section, out var result)) { Trace.TraceInformation( $"Debug section loader {ObjectTracker.Track(this)}: found in cache"); return result; } var (sectionParser, errorHandler) = InitializeParser(); var text = GetSectionTextSpan(section); var function = sectionParser.ParseSection(section, text); result = new ParsedIRTextSection(section, text, function); if (cacheEnabled_ && function != null) { sectionCache_[section] = result; } if (errorHandler.HadParsingErrors) { result.ParsingErrors = errorHandler.ParsingErrors; } return result; } } public override string GetSectionText(IRTextSection section) { if (section == lastSection_) { return lastSectionText_; } return sectionTextMap_[section].ToString(); } public override ReadOnlyMemory GetSectionTextSpan(IRTextSection section) { if (section == lastSection_) { return lastSectionText_.AsMemory(); } return sectionTextMap_[section].ToString().AsMemory(); } public override string GetSectionOutputText(IRPassOutput output) { return ""; } public override ReadOnlyMemory GetSectionPassOutputTextSpan(IRPassOutput output) { return ReadOnlyMemory.Empty; } public override List GetSectionPassOutputTextLines(IRPassOutput output) { return new List(); } public override string GetRawSectionText(IRTextSection section) { return GetSectionText(section); } public override string GetRawSectionPassOutput(IRPassOutput output) { return ""; } public override ReadOnlyMemory GetRawSectionTextSpan(IRTextSection section) { return GetSectionTextSpan(section); } public override ReadOnlyMemory GetRawSectionPassOutputSpan(IRPassOutput output) { return ReadOnlyMemory.Empty; } protected override void Dispose(bool disposing) { if (!disposed_) { disposed_ = true; } } } ================================================ FILE: src/ProfileExplorerUI/GrpcServer/DebugService.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using System.Threading.Tasks; using Grpc.Core; namespace ProfileExplorer.UI.DebugServer; public class RequestResponsePair { public T1 Request; public T2 Response; public RequestResponsePair(T1 request, T2 response = default) { Request = request; Response = response; } } public class DebugService : global::DebugService.DebugServiceBase { private const int Port = 50051; private static Server serverInstance_; private bool handleSetCurrentElement_; public DebugService() { handleSetCurrentElement_ = true; } public event EventHandler OnStartSession; public event EventHandler OnUpdateIR; public event EventHandler OnMarkElement; public event EventHandler OnSetCurrentElement; public event EventHandler OnExecuteCommand; public event EventHandler> OnHasActiveBreakpoint; public event EventHandler OnClearTemporaryHighlighting; public event EventHandler OnUpdateCurrentStackFrame; public static bool StartServer(DebugService instance) { var options = new[] { new ChannelOption("grpc.max_receive_message_length", -1), new ChannelOption("grpc.max_send_message_length", -1) }; serverInstance_ = new Server(options) { Services = {global::DebugService.BindService(instance)}, Ports = {new ServerPort("localhost", Port, ServerCredentials.Insecure)} }; serverInstance_.Start(); return true; } public void StopServer() { serverInstance_.ShutdownAsync().Wait(); } public override Task StartSession(StartSessionRequest request, ServerCallContext context) { Trace.TraceInformation("Grpc: new session {0}, process {1}, args {2}", request.Kind, request.ProcessId, request.ProcessId); var result = HandleNewSession(request); return Task.FromResult(result); } public override Task EndSession(EndSessionRequest request, ServerCallContext context) { Trace.TraceInformation($"Grpc: end session {0}", request.SessionId); return Task.FromResult(GetSuccessResult()); } public override Task UpdateIR(UpdateIRRequest request, ServerCallContext context) { Trace.TraceInformation("Grpc: update IR {0}, length {1}", request.SessionId, request.Text.Length); OnUpdateIR?.Invoke(this, request); return Task.FromResult(GetSuccessResult()); } public override Task MarkElement(MarkElementRequest request, ServerCallContext context) { Trace.TraceInformation("Grpc: mark element {0}, label {1}, kind {2}", request.ElementAddress, request.Label, request.Highlighting); OnMarkElement?.Invoke(this, request); return Task.FromResult(GetSuccessResult()); } public override Task SetCurrentElement(SetCurrentElementRequest request, ServerCallContext context) { //Trace.TraceInformation("Grpc: set current element {0}, {1}, {2}, lable {3}", request.ElementId, // request.ElementKind, request.ElementAddress, request.Label); if (handleSetCurrentElement_) { OnSetCurrentElement?.Invoke(this, request); } return Task.FromResult(GetSuccessResult()); } public override Task ExecuteCommand(ElementCommandRequest request, ServerCallContext context) { Trace.TraceInformation("Grpc: execute command {0}, element {1}", request.Command, request.ElementAddress); OnExecuteCommand?.Invoke(this, request); return Task.FromResult(GetSuccessResult()); } public override Task HasActiveBreakpoint( ActiveBreakpointRequest request, ServerCallContext context) { //Trace.TraceInformation("Grpc: has active breakpoint element {0}", request.ElementAddress); var query = new RequestResponsePair(request); OnHasActiveBreakpoint?.Invoke(this, query); return Task.FromResult(new ActiveBreakpointResult { HasBreakpoint = query.Response, Success = true }); } public override Task ClearTemporaryHighlighting(ClearHighlightingRequest request, ServerCallContext context) { //Trace.TraceInformation("Grpc: clear highlighting {0}", request.Highlighting); OnClearTemporaryHighlighting?.Invoke(this, request); return Task.FromResult(GetSuccessResult()); } public override Task SetSessionState(SessionStateRequest request, ServerCallContext context) { Trace.TraceInformation("Grpc: set session state {0}", request.State); handleSetCurrentElement_ = request.State == global::SessionState.Listening; return Task.FromResult(GetSuccessResult()); } public override Task UpdateCurrentStackFrame(CurrentStackFrameRequest request, ServerCallContext context) { Trace.TraceInformation("Grpc: update stack frame{0}", request.CurrentFrame); OnUpdateCurrentStackFrame?.Invoke(this, request); return Task.FromResult(GetSuccessResult()); } private StartSessionResult HandleNewSession(StartSessionRequest request) { OnStartSession?.Invoke(this, request); return new StartSessionResult {SessionId = 1}; } private Result GetSuccessResult() { return new Result {Success = true}; } } ================================================ FILE: src/ProfileExplorerUI/Icons.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/MainWindow.xaml ================================================ ================================================ FILE: src/ProfileExplorerUI/MainWindow.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Threading; using AutoUpdaterDotNET; using AvalonDock; using AvalonDock.Layout; using ProfileExplorer.Core; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Graph; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.UI.Compilers.ASM; using ProfileExplorer.UI.Compilers.LLVM; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.Panels; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Scripting; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorerUI.Session; using ProfileExplorer.UI.Providers; using ProfileExplorer.UI.Compilers.Default; using ProfileExplorer.Core.Compilers.LLVM; namespace ProfileExplorer.UI; public static class AppCommand { public static readonly RoutedUICommand FullScreen = new("Untitled", "FullScreen", typeof(Window)); public static readonly RoutedUICommand OpenDocument = new("Untitled", "OpenDocument", typeof(Window)); public static readonly RoutedUICommand OpenNewDocument = new("Untitled", "OpenNewDocument", typeof(Window)); public static readonly RoutedUICommand OpenDebug = new("Untitled", "OpenDebug", typeof(Window)); public static readonly RoutedUICommand OpenDiffDebug = new("Untitled", "OpenDiffDebug", typeof(Window)); public static readonly RoutedUICommand OpenExecutable = new("Untitled", "OpenExecutable", typeof(Window)); public static readonly RoutedUICommand OpenExecutableDiff = new("Untitled", "OpenExecutableDiff", typeof(Window)); public static readonly RoutedUICommand CloseDocument = new("Untitled", "CloseDocument", typeof(Window)); public static readonly RoutedUICommand SaveDocument = new("Untitled", "SaveDocument", typeof(Window)); public static readonly RoutedUICommand SaveAsDocument = new("Untitled", "SaveAsDocument", typeof(Window)); public static readonly RoutedUICommand ToggleDiffMode = new("Untitled", "ToggleDiffMode", typeof(Window)); public static readonly RoutedUICommand ReloadDocument = new("Untitled", "ReloadDocument", typeof(Window)); public static readonly RoutedUICommand AutoReloadDocument = new("Untitled", "AutoReloadDocument", typeof(Window)); public static readonly RoutedUICommand OpenDiffDocument = new("Untitled", "OpenDiffDocument", typeof(Window)); public static readonly RoutedUICommand OpenBaseDiffDocuments = new("Untitled", "OpenBaseDiffDocuments", typeof(Window)); public static readonly RoutedUICommand CloseDiffDocument = new("Untitled", "CloseDiffDocument", typeof(Window)); public static readonly RoutedUICommand SwapDiffDocuments = new("Untitled", "SwapDiffDocuments", typeof(Window)); public static readonly RoutedUICommand ShowDocumentSearch = new("Untitled", "ShowDocumentSearch", typeof(Window)); public static readonly RoutedUICommand LoadProfile = new("Untitled", "LoadProfile", typeof(Window)); public static readonly RoutedUICommand RecordProfile = new("Untitled", "RecordProfile", typeof(Window)); public static readonly RoutedUICommand ViewProfileReport = new("Untitled", "ViewProfileReport", typeof(Window)); public static readonly RoutedUICommand ShowProfileCallGraph = new("Untitled", "ShowProfileCallGraph", typeof(Window)); public static readonly RoutedUICommand OpenHelpPage = new("Untitled", "OpenHelpPage", typeof(Window)); public static readonly RoutedUICommand OpenHelpPanel = new("Untitled", "OpenHelpPanel", typeof(Window)); } public partial class MainWindow : Window, IUISession, INotifyPropertyChanged { private LayoutDocumentPane activeDocumentPanel_; private AssemblyMetadataTag addressTag_; private bool appIsActivated_; private DispatcherTimer autoSaveTimer_; private Dictionary changedDocuments_; private ICompilerInfoProvider compilerInfo_; private ISectionStyleProvider sectionStyleProvider_; private IRRemarkProvider remarkProvider_; private ILoadedSectionHandler loadedSectionHandler_; private IBlockFoldingStrategyProvider blockFoldingStrategyProvider_; private MainWindowState fullScreenRestoreState_; private Dictionary graphLayout_; private bool ignoreDiffModeButtonEvent_; private Dictionary> panelHostSet_; private IRTextSection previousDebugSection_; private SessionStateManager sessionState_; private DispatcherTimer updateTimer_; private List detachedPanels_; private Point previousWindowPosition_; private DateTime lastDocumentLoadTime_; private DateTime lastDocumentReloadQueryTime_; private DelayedAction statusTextAction_; private CancelableTaskInstance documentLoadTask_; private object lockObject_; private bool documentSearchVisible_; private DocumentSearchPanel documentSearchPanel_; private bool initialDockLayoutRestored_; private bool profileControlsVisible; public MainWindow() { InitializeComponent(); panelHostSet_ = new Dictionary>(); changedDocuments_ = new Dictionary(); detachedPanels_ = new List(); lockObject_ = new object(); SetupMainWindow(); SetupGraphLayoutCache(); SetupEvents(); DataContext = this; } public FunctionMarkingSettings MarkingSettings => App.Settings.MarkingSettings; public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public bool ProfileControlsVisible { get => profileControlsVisible; set { if (value == profileControlsVisible) return; profileControlsVisible = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; public SessionStateManager SessionState => sessionState_; public IRTextSummary GetDocumentSummary(IRTextSection section) { return sessionState_.FindLoadedDocument(section).Summary; } public void SetSectionAnnotationState(IRTextSection section, bool hasAnnotations) { SectionPanel.SetSectionAnnotationState(section, hasAnnotations); } public async Task SwitchDocumentSectionAsync(OpenSectionEventArgs args) { var documentHost = args.TargetDocument; if (documentHost != null) { // Use the existing editor to show the section. documentHost = await OpenDocumentSectionAsync(args, documentHost); } else { // Open a new editor to show the section. documentHost = await OpenDocumentSectionAsync(args); } await SectionPanel.SelectSection(args.Section, false); return documentHost; } public async Task SwitchGraphsAsync(GraphPanel graphPanel, IRTextSection section, IRDocument document) { var action = GetComputeGraphAction(graphPanel.PanelKind); await SwitchGraphsAsync(graphPanel, section, document, action); } public void ShowAllReferences(IRElement element, IRDocument document) { ShowAllReferencesImpl(element, document, false); } public void ShowSSAUses(IRElement element, IRDocument document) { ShowAllReferencesImpl(element, document, true); } public Task SwitchActiveFunction(IRTextFunction function, bool handleProfiling = true) { return SectionPanel.SelectFunction(function, handleProfiling); } private void SetupEvents() { ContentRendered += MainWindow_ContentRendered; StateChanged += MainWindow_StateChanged; LocationChanged += MainWindow_LocationChanged; Closing += MainWindow_Closing; Activated += MainWindow_Activated; Deactivated += MainWindow_Deactivated; SizeChanged += MainWindow_SizeChanged; } private static void CheckForUpdate() { string autoUpdateInfo; switch (RuntimeInformation.OSArchitecture) { case Architecture.Arm64: autoUpdateInfo = App.AutoUpdateInfoArm64; break; case Architecture.X64: autoUpdateInfo = App.AutoUpdateInfox64; break; default: autoUpdateInfo = App.AutoUpdateInfox64; break; } try { AutoUpdater.Start(autoUpdateInfo); } catch (Exception ex) { Trace.TraceError($"Failed update check: {ex}"); } } private static void InstallExtension() { App.InstallExtension(); } protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); WindowPlacement.SetPlacement(this, App.Settings.MainWindowPlacement); // Handle touchpad horizontal scroll event, which is not supported // in WPF by default. This sends the event to any ScrollViewer. var source = PresentationSource.FromVisual(this); ((HwndSource)source)?.AddHook(Hook); } private IntPtr Hook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case NativeMethods.WM_MOUSEHWHEEL: int tilt = (short)NativeMethods.HIWORD(wParam); OnMouseTilt(tilt); return (IntPtr)1; } return IntPtr.Zero; } private void OnMouseTilt(int tilt) { var element = Mouse.DirectlyOver as UIElement; if (element == null) return; var scrollViewer = element is ScrollViewer viewer ? viewer : Utils.FindParent(element); if (scrollViewer != null) { scrollViewer.ScrollToHorizontalOffset(scrollViewer.HorizontalOffset + tilt); } } private void MainWindow_SizeChanged(object sender, SizeChangedEventArgs e) { UpdateStartPagePanelPosition(); } private void MainWindow_StateChanged(object sender, EventArgs e) { if (WindowState == WindowState.Minimized) { detachedPanels_.ForEach(panel => panel.Minimize()); } else if (WindowState == WindowState.Normal) { detachedPanels_.ForEach(panel => panel.Restore()); } } private void MainWindow_LocationChanged(object sender, EventArgs e) { var currentWindowPosition = new Point(Left, Top); if (detachedPanels_.Count > 0) { var diff = currentWindowPosition - previousWindowPosition_; detachedPanels_.ForEach(panel => { panel.HorizontalOffset += diff.X; panel.VerticalOffset += diff.Y; }); } previousWindowPosition_ = currentWindowPosition; } private void CloseDetachedPanels() { // Close all popups. var clone = detachedPanels_.CloneList(); clone.ForEach(panel => panel.ClosePopup()); detachedPanels_.Clear(); } private void ShowAllReferencesImpl(IRElement element, IRDocument document, bool showSSAUses) { var panelInfo = FindTargetPanel(document, ToolPanelKind.References); var refPanel = panelInfo.Panel as ReferencesPanel; panelInfo.Host.IsSelected = true; refPanel.FindAllReferences(element, showSSAUses); } private void MainWindow_Deactivated(object sender, EventArgs e) { appIsActivated_ = false; detachedPanels_.ForEach(panel => { panel.SendToBack(); }); } private async void MainWindow_Activated(object sender, EventArgs e) { appIsActivated_ = true; detachedPanels_.ForEach(panel => { panel.BringToFront(); }); await HandleChangedDocuments(); } private async Task HandleChangedDocuments() { var reloadedDocuments = new List(); lock (lockObject_) { foreach (var pair in changedDocuments_) { if (pair.Value < lastDocumentLoadTime_ || pair.Value < lastDocumentReloadQueryTime_) { continue; // Event happened before the last document reload, ignore. } reloadedDocuments.Add(pair.Key); } changedDocuments_.Clear(); } foreach (string documentPath in reloadedDocuments) { if (ShowDocumentReloadQuery(documentPath)) { await ReloadDocument(documentPath); } else { // Don't keep showing the dialog if no reload is wanted. changedDocuments_.Clear(); } } } private void SetupMainWindow() { App.Session = this; PopulateRecentFilesMenu(); PopulateWorkspacesCombobox(); ThemeCombobox.SelectedIndex = App.Settings.GeneralSettings.ThemeIndex; DiffModeButton.IsEnabled = false; SetActiveProfileFilter(new ProfileFilterState()); } private void SetupMainWindowCompilerTarget() { IRTypeLabel.Content = compilerInfo_.CompilerDisplayName; } private void AddRecentFile(string path) { App.Settings.AddRecentFile(path); App.SaveApplicationSettings(); PopulateRecentFilesMenu(); } private void PopulateRecentFilesMenu() { var savedItems = new List(); foreach (object item in RecentFilesMenu.Items) { if (item is MenuItem menuItem) { if (menuItem.Tag == null) { savedItems.Add(menuItem); } } else { savedItems.Add(item); } } RecentFilesMenu.Items.Clear(); foreach (string path in App.Settings.RecentFiles) { var item = new MenuItem(); item.Header = path; item.Tag = path; item.Click += RecentMenuItem_Click; RecentFilesMenu.Items.Add(item); } foreach (object item in savedItems) { RecentFilesMenu.Items.Add(item); } } private async void RecentMenuItem_Click(object sender, RoutedEventArgs e) { var menuItem = sender as MenuItem; if (menuItem?.Tag != null) { await OpenDocument((string)menuItem.Tag); } } private async void MainWindow_Closing(object sender, CancelEventArgs e) { // Save settings, including the window state. App.Settings.MainWindowPlacement = WindowPlacement.GetPlacement(this); App.Settings.GeneralSettings.ThemeIndex = ThemeCombobox.SelectedIndex; SaveDockLayout(); App.SaveApplicationSettings(); Trace.Flush(); if (!IsSessionStarted) { return; } // Skip confirmation dialogs during MCP automation if (App.SuppressDialogsForAutomation) { return; } // If the window is minimized, restore it first, otherwise // the message box will not be visible even after restoring the window // and the entire UI is blocked. if (WindowState == WindowState.Minimized) { WindowState = WindowState.Normal; } if (sessionState_.Info.IsFileSession) { using var centerForm = new DialogCenteringHelper(this); if (IsProfileSession) { // TODO: Profile session saving not yet implemented. var result = MessageBox.Show("Do you want to close the application?", "Profile Explorer", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.Yes); if (result == MessageBoxResult.No) { e.Cancel = true; return; } } else { var result = MessageBox.Show("Save session changes before closing?", "Profile Explorer", MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.No); if (result == MessageBoxResult.Yes) { SaveDocumentExecuted(this, null); } else if (result == MessageBoxResult.Cancel) { e.Cancel = true; return; } } } else { NotifyPanelsOfSessionSave(); NotifyDocumentsOfSessionSave(); if (SectionPanel.HasAnnotatedSections) { using var centerForm = new DialogCenteringHelper(this); var result = MessageBox.Show("Save file changes as a new session before closing?", "Profile Explorer", MessageBoxButton.YesNoCancel, MessageBoxImage.Question, MessageBoxResult.No); if (result == MessageBoxResult.Yes) { SaveDocumentExecuted(this, null); } else if (result == MessageBoxResult.Cancel) { e.Cancel = true; return; } } } await EndSession(); App.SaveApplicationSettings(); Trace.Flush(); } private async void MainWindow_ContentRendered(object sender, EventArgs e) { SetupStartPagePanel(); if (!IsSessionStarted) { ShowStartPage(); } var time = DateTime.UtcNow - App.AppStartTime; DevMenuStartupTime.Header = $"Startup time: {time.TotalMilliseconds} ms"; if (App.Settings.GeneralSettings.CheckForUpdates) { CheckForUpdatesOnStartup(); } string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1 && args[1] == "--open-trace") { var session = RecordingSession.FromCommandLineArgs(); await LoadProfileSession(session); } } private async Task LoadProfileSession(RecordingSession session) { var window = new ProfileLoadWindow(this, false, session, true); window.Owner = this; bool? result = window.ShowDialog(); if (result.HasValue && result.Value) { await SetupLoadedProfile(); } } private void CheckForUpdatesOnStartup() { DelayedAction.StartNew(TimeSpan.FromSeconds(1), () => { Dispatcher.BeginInvoke(new Action(() => { CheckForUpdate(); })); }); } private void StartApplicationUpdateTimer() { AutoUpdater.RunUpdateAsAdmin = true; AutoUpdater.ShowRemindLaterButton = false; AutoUpdater.CheckForUpdateEvent += AutoUpdaterOnCheckForUpdateEvent; updateTimer_ = new DispatcherTimer {Interval = TimeSpan.FromMinutes(10)}; updateTimer_.Tick += delegate { CheckForUpdate(); }; updateTimer_.Start(); } private void AutoUpdaterOnCheckForUpdateEvent(UpdateInfoEventArgs args) { if (args == null) { return; } if (args.IsUpdateAvailable) { UpdateButton.Visibility = Visibility.Visible; UpdateButton.Tag = args; } } private async Task ShowSectionPanelDiffs(ILoadedDocument result) { await SectionPanel.AnalyzeDocumentDiffs(); await SectionPanel.RefreshDocumentsDiffs(); } private void ShowProgressBar(string title) { documentLoadProgressVisible_ = true; DocumentLoadProgressBar.Value = 0; DocumentLoadProgressBar.Visibility = Visibility.Visible; DocumentLoadProgressPanel.Visibility = Visibility.Visible; if (string.IsNullOrEmpty(title)) { title = "Loading"; } DocumentLoadLabel.Text = title; } private void HideProgressBar() { DocumentLoadProgressPanel.Visibility = Visibility.Collapsed; DocumentLoadProgressBar.Visibility = Visibility.Hidden; DocumentLoadProgressBar.IsIndeterminate = false; DocumentLoadProgressBar.Value = 0; documentLoadProgressVisible_ = false; } private void UpdateWindowTitle() { string title = "Profile Explorer"; if (sessionState_.Info.IsFileSession) { title += $" - {sessionState_.Info.FilePath}"; if (sessionState_.MainDocument != null && sessionState_.MainDocument.BinaryFileExists) { if (ProfileData != null && !string.IsNullOrEmpty(ProfileData.Report.TraceInfo.TraceFilePath)) { title += $" ({Utils.TryGetFileName(ProfileData.Report.TraceInfo.TraceFilePath)}, {sessionState_.MainDocument.BinaryFile})"; } else { title += $" ({sessionState_.MainDocument.BinaryFile})"; } } } else { if (sessionState_.Documents.Count == 1) { string name = sessionState_.Documents[0].BinaryFile?.FilePath ?? sessionState_.Documents[0].FilePath; title += $" - {name}"; } else if (sessionState_.Documents.Count == 2) { string baseName = sessionState_.Documents[0].BinaryFile?.FilePath ?? sessionState_.Documents[0].FilePath; string diffName = sessionState_.Documents[1].BinaryFile?.FilePath ?? sessionState_.Documents[1].FilePath; title += $" - Base: {baseName} | Diff: {diffName}"; } } Title = title; } private async void Window_Loaded(object sender, RoutedEventArgs e) { await SetupCompilerTarget(); SectionPanel.OpenSection += SectionPanel_OpenSection; SectionPanel.EnterDiffMode += SectionPanel_EnterDiffMode; SectionPanel.SyncDiffedDocumentsChanged += SectionPanel_SyncDiffedDocumentsChanged; SectionPanel.DisplayCallGraph += SectionPanel_DisplayCallGraph; SearchResultsPanel.OpenSection += SectionPanel_OpenSection; if (!RestoreDockLayout()) { RegisterDefaultToolPanels(); } ResetStatusBar(); // Make help panel active on the first run. if (App.IsFirstRun) { await ShowPanel(ToolPanelKind.Help); } await ProcessStartupArgs(); if (!IsSessionStarted) { UpdatePanelEnabledState(false); } else { // Hide the start page if a file was loaded on start. HideStartPage(); } if (App.Settings.GeneralSettings.CheckForUpdates) { StartApplicationUpdateTimer(); } } private async Task ProcessStartupArgs() { //? TODO: This needs a proper arg parsing lib string[] args = Environment.GetCommandLineArgs(); if (args.Length > 1 && args[1] == "--open-trace") { // TODO: Opening Profile Explorer with a trace is handled once the ProfileLoadWindow is rendered. } else if (args.Length >= 3) { // Mode for comparing the functions from two different files. string baseFilePath = args[1]; string diffFilePath = args[2]; bool opened = false; if (File.Exists(baseFilePath) && File.Exists(diffFilePath)) { baseFilePath = Path.GetFullPath(baseFilePath); diffFilePath = Path.GetFullPath(diffFilePath); var (baseLoadedDoc, diffLoadedDoc) = await OpenBaseDiffIRDocumentsImpl(baseFilePath, diffFilePath); opened = baseLoadedDoc != null && diffLoadedDoc != null; } if (!opened) { MessageBox.Show($"Failed to open base/diff files {baseFilePath} and {diffFilePath}"); return; } if (args.Length >= 5 && IsInTwoDocumentsDiffMode) { if (args[3].EndsWith("script")) { SilentMode = true; string scriptPath = args[4]; var script = Script.LoadFromFile(scriptPath); if (script == null) { MessageBox.Show($"Failed {scriptPath}"); MessageBox.Show(string.Join(Environment.NewLine, args)); } string scriptOutPath = null; if (args.Length >= 7) { if (args[5].EndsWith("out")) { scriptOutPath = args[6]; } } var session = new ScriptSession(null, this) { SilentMode = true, SessionName = scriptOutPath }; script.Execute(session); Close(); } else if (args[3].EndsWith("func")) { // Open a certain function and section from a file. string funcName = args[4]; var func = sessionState_.MainDocument.Summary.FindFunction(funcName); if (func != null) { await SectionPanel.SelectFunction(func); if (args.Length >= 7) { if (args[5].EndsWith("section")) { string sectionName = args[6]; var section = func.FindSection(sectionName); if (section != null) { await SectionPanel.SelectSection(section); SectionPanel.DiffSelectedSection(); } } } } } } } else if (args.Length == 2) { // Mode for opening a single file. string filePath = args[1]; if (File.Exists(filePath)) { filePath = Path.GetFullPath(filePath); await OpenDocument(filePath); } } // Mode for starting the GRPC server used by the VS extension. foreach (string arg in args) { if (arg.Contains("grpc-server")) { StartGrpcServer(); break; } } } private async void SectionPanel_DisplayCallGraph(object sender, DisplayCallGraphEventArgs e) { await DisplayCallGraph(e.Summary, e.Section, e.BuildPartialGraph); } private void SetupStartPagePanel() { StartPage.OpenRecentDocument += StartPage_OpenRecentDocument; StartPage.OpenRecentDiffDocuments += StartPage_OpenRecentDiffDocuments; StartPage.OpenRecentProfileSession += StartPage_OpenRecentProfileSession; StartPage.OpenFile += StartPage_OpenFile; StartPage.CompareFiles += StartPage_CompareFiles; StartPage.ClearRecentDocuments += StartPage_ClearRecentDocuments; StartPage.ClearRecentDiffDocuments += StartPage_ClearRecentDiffDocuments; StartPage.ClearRecentProfileSessions += StartPage_ClearRecentProfileSessions; StartPage.LoadProfile += StartPage_LoadProfile; StartPage.RecordProfile += StartPage_RecordProfile; UpdateStartPagePanelPosition(); } private void StartPage_ClearRecentProfileSessions(object sender, EventArgs e) { using var centerForm = new DialogCenteringHelper(this); if (MessageBox.Show("Clear the list of recent profile sessions?", "Profile Explorer", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes) { App.Settings.ClearLoadedProfileSession(); App.SaveApplicationSettings(); StartPage.ReloadFileList(); } } private async void StartPage_OpenRecentProfileSession(object sender, RecordingSession session) { await LoadProfileSession(session); } private async void StartPage_LoadProfile(object sender, EventArgs e) { await LoadProfile(); } private async void StartPage_RecordProfile(object sender, EventArgs e) { await RecordProfile(); } private void StartPage_ClearRecentDiffDocuments(object sender, EventArgs e) { using var centerForm = new DialogCenteringHelper(this); if (MessageBox.Show("Clear the list of recent compared documents?", "Profile Explorer", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes) { App.Settings.ClearRecentComparedFiles(); App.SaveApplicationSettings(); StartPage.ReloadFileList(); } } private void StartPage_ClearRecentDocuments(object sender, EventArgs e) { using var centerForm = new DialogCenteringHelper(this); if (MessageBox.Show("Clear the list of recent documents?", "Profile Explorer", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No) == MessageBoxResult.Yes) { App.Settings.ClearRecentFiles(); App.SaveApplicationSettings(); StartPage.ReloadFileList(); } } private async void StartPage_CompareFiles(object sender, EventArgs e) { await OpenBaseDiffDocuments(); } private async void StartPage_OpenFile(object sender, EventArgs e) { await OpenDocument(); } private async void StartPage_OpenRecentDiffDocuments(object sender, Tuple e) { await OpenBaseDiffDocuments(e.Item1, e.Item2); } private async void StartPage_OpenRecentDocument(object sender, string e) { await OpenDocument(e); } private void UpdateStartPagePanelPosition() { if (IsSessionStarted) { return; } var documentHost = Utils.FindChildLogical(this); if (documentHost != null) { double height = Math.Max(StartPage.MinHeight, documentHost.ActualHeight * 0.5); StartPage.Height = height; } } private void ShowStartPage() { StartPage.ReloadFileList(); StartPage.Visibility = Visibility.Visible; Utils.EnableControl(StartPage); } private void HideStartPage() { StartPage.Visibility = Visibility.Collapsed; } private void UpdateBlockStatusBar(BlockIR block) { string text = Utils.MakeBlockDescription(block); BlockStatus.Text = text; BlockStatus.ToolTip = text; } private void ResetStatusBar() { BlockStatus.Text = ""; BlockStatus.ToolTip = null; BookmarkStatus.Text = ""; BookmarkStatus.ToolTip = ""; DiffStatusText.Text = ""; OptionalStatusText.Text = ""; OptionalStatusText.ToolTip = ""; } private void FullScreenExecuted(object sender, ExecutedRoutedEventArgs e) { if (e.Source != FullScreenButton) { FullScreenButton.IsChecked = !FullScreenButton.IsChecked; } if (FullScreenButton.IsChecked.HasValue && FullScreenButton.IsChecked.Value) { fullScreenRestoreState_ = new MainWindowState(this); Visibility = Visibility.Collapsed; ResizeMode = ResizeMode.NoResize; WindowStyle = WindowStyle.None; WindowState = WindowState.Maximized; Visibility = Visibility.Visible; Focus(); } else if (fullScreenRestoreState_ != null) { fullScreenRestoreState_.Restore(this); Focus(); } e.Handled = true; } private void ShowDocumentSearchExecuted(object sender, ExecutedRoutedEventArgs e) { ShowDocumentSearchPanel(); } private void CanExecuteAlways(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } private string GetDocumentTitle(IRDocumentHost document, IRTextSection section) { bool includeNumber = ProfileData == null || section.ParentFunction.SectionCount > 1; string title = compilerInfo_.NameProvider.GetSectionName(section, includeNumber); if (sessionState_.SectionDiffState.IsEnabled) { if (sessionState_.SectionDiffState.LeftDocument == document) { return $"Base: {title}"; } if (sessionState_.SectionDiffState.RightDocument == document) { return $"Diff: {title}"; } } if (!string.IsNullOrEmpty(document.TitlePrefix)) { title = $"{document.TitlePrefix}{title}"; } if (!string.IsNullOrEmpty(document.TitleSuffix)) { title = $"{title}{document.TitleSuffix}"; } return title; } private string GetDocumentDescription(IRDocumentHost document, IRTextSection section) { var docInfo = sessionState_.FindLoadedDocument(section); string funcName = compilerInfo_.NameProvider.FormatFunctionName(section.ParentFunction); funcName = DocumentUtils.FormatLongFunctionName(funcName); string text = $"Module: {section.ModuleName}\nFunction: {funcName}"; if (!string.IsNullOrEmpty(document.DescriptionPrefix)) { text = $"{document.DescriptionPrefix}{text}"; } if (!string.IsNullOrEmpty(document.DescriptionSuffix)) { text = $"{text}{document.DescriptionSuffix}"; } return text.Trim(); } private async Task DisplayCallGraph(IRTextSummary summary, IRTextSection section, bool buildPartialGraph) { var loadedDoc = sessionState_.FindLoadedDocument(summary); var layoutGraph = await Task.Run(() => CallGraphUtils.BuildCallGraphLayout(summary, section, loadedDoc, CompilerInfo, buildPartialGraph)); DisplayCallGraph(layoutGraph, section); } private void DisplayCallGraph(Graph layoutGraph, IRTextSection section) { var panel = new CallGraphPanel(this); panel.TitleSuffix = $" - S{section.Number} ({CompilerInfo.NameProvider.GetSectionName(section)})"; DisplayFloatingPanel(panel); panel.DisplayGraph(layoutGraph); } private async void GraphViewer_NodeSelected(object sender, TaggedObject e) { var graphNode = e as CallGraphNode; if (graphNode != null && graphNode.Function != null) { await SectionPanel.SelectFunction(graphNode.Function); } } private void UpdateButton_Click(object sender, RoutedEventArgs e) { var updateWindow = new UpdateWindow(UpdateButton.Tag as UpdateInfoEventArgs); updateWindow.Owner = this; bool? installUpdate = updateWindow.ShowDialog(); if (installUpdate.HasValue && installUpdate.Value) { Close(); } UpdateButton.Visibility = Visibility.Collapsed; } private void ExitMenuItem_Click(object sender, RoutedEventArgs e) { Close(); } private void RecentFilesMenu_Click(object sender, RoutedEventArgs e) { App.Settings.ClearRecentFiles(); PopulateRecentFilesMenu(); } private void SettingsMenu_Click(object sender, RoutedEventArgs e) { var optionsWindow = new OptionsWindow(this); optionsWindow.Owner = this; optionsWindow.ShowDialog(); } private void OpenHelpPageExecuted(object sender, ExecutedRoutedEventArgs e) { App.OpenDocumentation(); } private async void OpenHelpPanelExecuted(object sender, ExecutedRoutedEventArgs e) { await ShowPanel(ToolPanelKind.Help); } private void AboutMenu_Click(object sender, RoutedEventArgs e) { var window = new AboutWindow(); window.Owner = this; window.ShowDialog(); } private void DiagnosticLogMenu_Click(object sender, RoutedEventArgs e) { try { string logInfo = DiagnosticLogger.GetLogFileInfo(); var result = MessageBox.Show(logInfo + "\n\nClick OK to open the log file location in Windows Explorer.", "Diagnostic Log", MessageBoxButton.OKCancel, MessageBoxImage.Information); if (result == MessageBoxResult.OK) { DiagnosticLogger.ShowLogFileLocation(); } } catch (Exception ex) { MessageBox.Show($"Failed to access diagnostic log: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } private void SetOptionalStatus(TimeSpan duration, string text, string tooltip = "", Brush textBrush = null) { SetOptionalStatus(text, tooltip, textBrush); statusTextAction_ = DelayedAction.StartNew(duration, () => SetOptionalStatus("")); } private void SetOptionalStatus(string text, string tooltip = "", Brush textBrush = null) { statusTextAction_?.Cancel(); if (!Dispatcher.CheckAccess()) { Dispatcher.Invoke(() => SetOptionalStatusImpl(text, tooltip, textBrush)); } else { SetOptionalStatusImpl(text, tooltip, textBrush); } } private void SetOptionalStatusImpl(string text, string tooltip = "", Brush textBrush = null) { OptionalStatusText.Text = text; OptionalStatusText.Foreground = textBrush ?? Brushes.Black; OptionalStatusText.ToolTip = tooltip; OptionalStatusText.Visibility = !string.IsNullOrEmpty(text) ? Visibility.Visible : Visibility.Collapsed; } private void MenuItem_Click_9(object sender, RoutedEventArgs e) { InstallExtension(); } private void AlwaysOnTopMenu_Click(object sender, RoutedEventArgs e) { SetAlwaysOnTop(AlwaysOnTopCheckbox.IsChecked); } private void AlwaysOnTopButton_Click(object sender, RoutedEventArgs e) { SetAlwaysOnTop(AlwaysOnTopButton.IsChecked.HasValue && AlwaysOnTopButton.IsChecked.Value); } private void SetAlwaysOnTop(bool state) { Topmost = state; AlwaysOnTopCheckbox.IsChecked = state; AlwaysOnTopButton.IsChecked = state; } private async Task SwitchCompilerTarget(ICompilerInfoProvider compilerInfo) { await EndSession(); compilerInfo_ = compilerInfo; remarkProvider_ = new DefaultRemarkProvider(compilerInfo); blockFoldingStrategyProvider_ = new BasicBlockFoldingStrategyProvider(); switch (compilerInfo.CompilerIRKind) { case CompilerIRKind.ASM: sectionStyleProvider_ = new DummySectionStyleProvider(); loadedSectionHandler_ = new ASMLoadedSectionHandler(compilerInfo); break; case CompilerIRKind.LLVM: sectionStyleProvider_ = new DefaultSectionStyleProvider(compilerInfo); loadedSectionHandler_ = new LLVMLoadedSectionHandler(); break; default: throw new NotSupportedException($"Unsupported compiler IR kind: {compilerInfo.CompilerIRKind}"); } App.Settings.CompilerIRSwitched(compilerInfo_.CompilerIRName, compilerInfo.IR.Mode); SetupMainWindowCompilerTarget(); } private async Task SetupCompilerTarget() { await SwitchCompilerTarget(App.Settings.DefaultCompilerIR, App.Settings.DefaultIRMode); } private async Task SwitchCompilerTarget(string name, IRMode irMode = IRMode.Default) { if (Enum.TryParse(name, out var compilerKind)) { switch (compilerKind) { case CompilerIRKind.LLVM: { await SwitchCompilerTarget(new LLVMCompilerInfoProvider()); break; } case CompilerIRKind.ASM: { await SwitchCompilerTarget(new ASMCompilerInfoProvider(irMode)); break; } } } else { await SwitchCompilerTarget(new ASMCompilerInfoProvider(IRMode.x86_64)); } App.Settings.SwitchDefaultCompilerIR(compilerInfo_.CompilerIRName, irMode); App.SaveApplicationSettings(); } private void FindButton_Click(object sender, RoutedEventArgs e) { ShowDocumentSearchPanel(); } private async void FunctionReportMenu_Click(object sender, RoutedEventArgs e) { await SectionPanel.ShowModuleReport(); } private void ShowWorkspacesMenu_Click(object sender, RoutedEventArgs e) { ShowWorkspacesWindow(); } private async void HelpButton_Click(object sender, RoutedEventArgs e) { await ShowPanel(ToolPanelKind.Help); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private void ProfileMenuItem_Click(object sender, RoutedEventArgs e) { ReloadMarkingSettings(); } private void ZoomInUIMenu_Click(object sender, RoutedEventArgs e) { App.Settings.GeneralSettings.ZoomInWindow(); OnPropertyChanged(nameof(WindowScaling)); } private void ZoomOutUIMenu_Click(object sender, RoutedEventArgs e) { App.Settings.GeneralSettings.ZoomOutWindow(); OnPropertyChanged(nameof(WindowScaling)); } private void ResetUIZoomMenu_Click(object sender, RoutedEventArgs e) { App.Settings.GeneralSettings.ResetWindowZoom(); OnPropertyChanged(nameof(WindowScaling)); } private void CheckUpdatesMenu_Click(object sender, RoutedEventArgs e) { CheckForUpdate(); } private class MainWindowState { public MainWindowState(MainWindow window) { CurrentResizeMode = window.ResizeMode; CurrentWindowStyle = window.WindowStyle; CurrentWindowState = window.WindowState; IsTopmost = window.Topmost; CurrentMenuVisibility = window.MainMenu.Visibility; CurrentMenuHeight = window.MainGrid.RowDefinitions[0].Height; } public ResizeMode CurrentResizeMode { get; set; } public WindowStyle CurrentWindowStyle { get; set; } public WindowState CurrentWindowState { get; set; } public bool IsTopmost { get; set; } public Visibility CurrentMenuVisibility { get; set; } public GridLength CurrentMenuHeight { get; set; } public void Restore(MainWindow window) { window.ResizeMode = CurrentResizeMode; window.WindowStyle = CurrentWindowStyle; window.WindowState = CurrentWindowState; window.Topmost = IsTopmost; window.MainMenu.Visibility = CurrentMenuVisibility; window.MainGrid.RowDefinitions[0].Height = CurrentMenuHeight; } } } ================================================ FILE: src/ProfileExplorerUI/MainWindowDebugRpc.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.UI.DebugServer; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Session; namespace ProfileExplorer.UI; public partial class MainWindow : Window, IUISession { private DebugServer.DebugService debugService_; private Dictionary debugCurrentIteratorElement_; private StackFrame debugCurrentStackFrame_; private IRTextFunction debugFunction_; private long debugProcessId_; private int debugSectionId_; private DebugSectionLoader debugSections_; private IRTextSummary debugSummary_; private CancelableTask sessionStartTask_; private void StartGrpcServer() { try { Trace.TraceInformation("Starting Grpc server..."); debugService_ = new DebugServer.DebugService(); debugService_.OnStartSession += DebugService_OnSessionStarted; debugService_.OnUpdateIR += DebugService_OnIRUpdated; debugService_.OnMarkElement += DebugService_OnElementMarked; debugService_.OnSetCurrentElement += DebugService_OnSetCurrentElement; debugService_.OnExecuteCommand += DebugService_OnExecuteCommand; debugService_.OnHasActiveBreakpoint += DebugService_OnHasActiveBreakpoint; debugService_.OnClearTemporaryHighlighting += DebugService__OnClearTemporaryHighlighting; debugService_.OnUpdateCurrentStackFrame += DebugService__OnUpdateCurrentStackFrame; Trace.TraceInformation("Grpc server started, waiting for client..."); SetOptionalStatus("Waiting for client..."); DiffPreviousSectionCheckbox.Visibility = Visibility.Visible; DebugServer.DebugService.StartServer(debugService_); } catch (Exception ex) { Trace.TraceError("Failed to start Grpc server: {0}", $"{ex.Message}\n{ex.StackTrace}"); SetOptionalStatus("Failed to start Grpc server.", $"{ex.Message}\n{ex.StackTrace}", Brushes.Red); } } private async Task WaitForSessionInitialization() { // Wait until the session initialized properly. if (sessionStartTask_ == null) { return false; } Trace.WriteLine("=> WaitForSessionInitialization\n"); if (sessionStartTask_.IsCompleted) { Trace.WriteLine(" < already completed\n"); return true; } Trace.WriteLine(" > start waiting\n"); if (!await Task.Run(() => sessionStartTask_.WaitToComplete(TimeSpan.FromSeconds(30))).ConfigureAwait(false)) { Trace.WriteLine(" < timeout\n"); return false; } Trace.WriteLine($" < completed {sessionStartTask_.IsCompleted}\n"); return sessionStartTask_.IsCompleted; } private async void DebugService__OnUpdateCurrentStackFrame(object sender, CurrentStackFrameRequest e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } await Dispatcher.BeginInvoke(new Action(async () => { debugCurrentStackFrame_ = e.CurrentFrame; })); } private async void DebugService__OnClearTemporaryHighlighting(object sender, ClearHighlightingRequest e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } await Dispatcher.BeginInvoke(new Action(async () => { var activeDoc = await GetDebugSessionDocument(); if (activeDoc == null) { return; } var action = new DocumentAction(DocumentActionKind.ClearTemporaryMarkers); activeDoc.TextView.ExecuteDocumentAction(action); })); } private async void DebugService_OnHasActiveBreakpoint(object sender, RequestResponsePair e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } if (addressTag_ == null) { return; } if (addressTag_.AddressToElementMap.TryGetValue(e.Request.ElementAddress, out var element)) { await Dispatcher.BeginInvoke(async () => { var activeDoc = await GetDebugSessionDocument(); if (activeDoc == null) return; e.Response = activeDoc.TextView.BookmarkManager.FindBookmark(element) != null; }); } } private DocumentActionKind CommandToAction(ElementCommand command) { return command switch { ElementCommand.GoToDefinition => DocumentActionKind.GoToDefinition, ElementCommand.MarkBlock => DocumentActionKind.MarkBlock, ElementCommand.MarkExpression => DocumentActionKind.MarkExpression, ElementCommand.MarkReferences => DocumentActionKind.MarkReferences, ElementCommand.MarkUses => DocumentActionKind.MarkUses, ElementCommand.ShowExpression => DocumentActionKind.ShowExpressionGraph, ElementCommand.ShowReferences => DocumentActionKind.ShowReferences, ElementCommand.ShowUses => DocumentActionKind.ShowUses, ElementCommand.ClearMarker => DocumentActionKind.ClearMarker, _ => throw new NotImplementedException() }; } private async void DebugService_OnExecuteCommand(object sender, ElementCommandRequest e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } //? TODO: This can be another race condition, it should wait for the IR to be set if (addressTag_ == null) { return; } if (addressTag_.AddressToElementMap.TryGetValue(e.ElementAddress, out var element)) { await Dispatcher.BeginInvoke(new Action(async () => { var activeDoc = await GetDebugSessionDocument(); if (activeDoc == null) return; AppendNotesTag(element, e.Label); var style = new PairHighlightingStyle(); style.ParentStyle = new HighlightingStyle(Colors.Transparent, ColorPens.GetPen(Colors.Purple)); style.ChildStyle = new HighlightingStyle(Colors.LightPink, ColorPens.GetPen(Colors.MediumVioletRed)); var actionKind = CommandToAction(e.Command); if (actionKind == DocumentActionKind.MarkExpression) { var data = new MarkActionData { IsTemporary = e.Highlighting == HighlightingType.Temporary }; var action = new DocumentAction(actionKind, element, data); activeDoc.TextView.ExecuteDocumentAction(action); } else { var action = new DocumentAction(actionKind, element, style); activeDoc.TextView.ExecuteDocumentAction(action); } })); } } private async void DebugService_OnSetCurrentElement(object sender, SetCurrentElementRequest e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } if (addressTag_ == null) { return; } await Dispatcher.BeginInvoke(new Action(async () => { var activeDoc = await GetDebugSessionDocument(); if (activeDoc == null) return; try { var elementIteratorId = new ElementIteratorId(e.ElementId, e.ElementKind); if (debugCurrentIteratorElement_.TryGetValue(elementIteratorId, out var currentElement)) { currentElement.RemoveTag(); activeDoc.TextView.ClearMarkedElement(currentElement); debugCurrentIteratorElement_.Remove(elementIteratorId); } if (e.ElementAddress != 0 && addressTag_.AddressToElementMap.TryGetValue(e.ElementAddress, out var element)) { var notesTag = AppendNotesTag(element, e.Label); if (e.ElementKind == IRElementKind.Block) { activeDoc.TextView.MarkBlock(element, GetIteratorElementStyle(elementIteratorId)); } else { activeDoc.TextView.MarkElement(element, GetIteratorElementStyle(elementIteratorId)); } activeDoc.TextView.BringElementIntoView(element); debugCurrentIteratorElement_[elementIteratorId] = element; } } catch (Exception ex) { Trace.TraceError($"Failed OnSetCurrentElement: {ex.Message}, {ex.StackTrace}"); } })); } private NotesTag AppendNotesTag(IRElement element, string label) { if (!string.IsNullOrEmpty(label)) { element.RemoveTag(); var notesTag = element.GetOrAddTag(); notesTag.Title = label; if (debugCurrentStackFrame_ != null) { notesTag.Notes.Add( $"{debugCurrentStackFrame_.Function}:{debugCurrentStackFrame_.LineNumber}"); } return notesTag; } return null; } private HighlightingStyle GetIteratorElementStyle(ElementIteratorId elementIteratorId) { return elementIteratorId.ElementKind switch { IRElementKind.Instruction => new HighlightingStyle( Colors.LightBlue, ColorPens.GetPen(Colors.MediumBlue)), IRElementKind.Operand => new HighlightingStyle(Colors.PeachPuff, ColorPens.GetPen(Colors.SaddleBrown)), IRElementKind.User => new HighlightingStyle(Utils.ColorFromString("#EFBEE6"), ColorPens.GetPen(Colors.Purple)), IRElementKind.UserParent => new HighlightingStyle(Colors.Lavender, ColorPens.GetPen(Colors.Purple)), IRElementKind.Block => new HighlightingStyle(Colors.LightBlue, ColorPens.GetPen(Colors.LightBlue)), _ => new HighlightingStyle(Colors.Gray) }; } private async void DebugService_OnElementMarked(object sender, MarkElementRequest e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } if (addressTag_ == null) { return; } if (addressTag_.AddressToElementMap.TryGetValue(e.ElementAddress, out var element)) { Dispatcher.BeginInvoke(new Action(async () => { var activeDoc = await GetDebugSessionDocument(); var notesTag = AppendNotesTag(element, e.Label); if (e.Highlighting == HighlightingType.Temporary) { activeDoc.TextView.HighlightElement(element, HighlighingType.Selected); } else { HighlightingStyle style; if (e.Color != null && e.Color.IsValidRGBColor()) { style = new HighlightingStyle(e.Color.ToColor()); } else if (debugCurrentStackFrame_ != null) { // Pick a color based on the source line number. style = DefaultHighlightingStyles.StyleSet.ForIndex(debugCurrentStackFrame_.LineNumber); } else { style = new HighlightingStyle(Colors.Gray); } activeDoc.TextView.MarkElement(element, style); } activeDoc.TextView.BringElementIntoView(element); })); } } private async Task GetDebugSessionDocument() { // Find the document with the last version of the IR loaded. // If there is none, use the current active document. var result = FindDebugSessionDocument(); if (result != null) { return result; } var activeDoc = FindActiveDocumentHost(); if (activeDoc != null) { return activeDoc; } return await ReopenDebugSessionDocument(); } private IRDocumentHost FindDebugSessionDocument() { var result = sessionState_.DocumentHosts.Find(item => item.DocumentHost.Section == previousDebugSection_); if (result != null) { return result.DocumentHost; } return null; } private async Task ReopenDebugSessionDocument() { if (previousDebugSection_ == null) { return null; } return await OpenDocumentSectionAsync( new OpenSectionEventArgs(previousDebugSection_, OpenSectionKind.ReplaceCurrent)); } private string ExtractFunctionName(string text) { int startIndex = 0; while (startIndex < text.Length) { int index = text.IndexOfAny(new[] {'\r', '\n'}, startIndex); if (index != -1) { string line = text.Substring(startIndex, index - startIndex + 1); startIndex = index + 1; } else { break; } } return null; } private async void DebugService_OnIRUpdated(object sender, UpdateIRRequest e) { if (!await WaitForSessionInitialization().ConfigureAwait(false)) { return; } await Dispatcher.BeginInvoke(new Action(async () => { if (!IsSessionStarted || sessionState_.MainDocument == null) { return; } string funcName = ExtractFunctionName(e.Text); funcName ??= "Debugged function"; if (previousDebugSection_ != null) { // Task.Run(() => previousDebugSection_.CompressLineMetadata()); previousDebugSection_.CompressLineMetadata(); } if (debugFunction_ == null || funcName != debugFunction_.Name) { debugFunction_ = new IRTextFunction(funcName); previousDebugSection_ = null; debugSectionId_ = 0; debugCurrentIteratorElement_ = new Dictionary(); sessionState_.MainDocument.Summary.AddFunction(debugFunction_); } string sectionName = $"Version {debugSectionId_ + 1}"; if (debugCurrentStackFrame_ != null) { sectionName += $" ({debugCurrentStackFrame_.Function}:{debugCurrentStackFrame_.LineNumber})"; } var section = new IRTextSection(debugFunction_, sectionName, IRPassOutput.Empty); string filteredText = ExtractLineMetadata(section, e.Text); // Ignore if nothing changed. try { if (previousDebugSection_ != null && debugSections_.GetSectionText(previousDebugSection_) == filteredText) { return; // Text unchanged } } catch (Exception ex) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Unexpected RPC failure: {ex.Message}\n {ex.StackTrace}"); } debugFunction_.AddSection(section); debugSummary_.AddSection(section); debugSections_.AddSection(section, filteredText); // Force function list update when updating summary. await SectionPanel.SetMainSummary(debugSummary_, true); await SectionPanel.SelectSection(section); //? TODO: After switch, try to restore same position in doc //? Markers, bookmarks, notes, etc should be copied over var document = FindDebugSessionDocument(); double horizontalOffset = 0; double verticalOffset = 0; if (previousDebugSection_ != null && document != null) { horizontalOffset = document.TextView.HorizontalOffset; verticalOffset = document.TextView.VerticalOffset; } await OpenDocumentSectionAsync(new OpenSectionEventArgs(section, OpenSectionKind.ReplaceCurrent), document); //? TODO: Have a proper option in the UI for diffing previous section if (previousDebugSection_ != null && document != null) { if (DiffPreviousSectionCheckbox.IsChecked.HasValue && DiffPreviousSectionCheckbox.IsChecked.Value) { await DiffSingleDocumentSections(document, section, previousDebugSection_); document.TextView.ScrollToHorizontalOffset(horizontalOffset); document.TextView.ScrollToVerticalOffset(verticalOffset); } } previousDebugSection_ = section; debugSectionId_++; })); } //? TODO: Not needed anymore, parser should have extracted metadata already private string ExtractLineMetadata(IRTextSection section, string text) { var builder = new StringBuilder(text.Length); string[] lines = text.Split(new[] {"\r\n", "\r", "\n"}, StringSplitOptions.None); int metadataLines = 0; for (int i = 0; i < lines.Length; i++) { string line = lines[i]; if (line.StartsWith("/// metadata:")) { section.AddLineMetadata(i - metadataLines - 1, line); metadataLines++; } else { builder.AppendLine(line); } } return builder.ToString(); } private async void DebugService_OnSessionStarted(object sender, StartSessionRequest e) { if (e.ProcessId == debugProcessId_) { return; } // Mark that session is about to start. await WaitForSessionInitialization().ConfigureAwait(false); sessionStartTask_ = new CancelableTask(); Trace.WriteLine("=> OnSessionStarted\n"); Dispatcher.BeginInvoke(new Action(async () => { try { Trace.WriteLine("=> BeginInvoke OnSessionStarted\n"); SetOptionalStatus(TimeSpan.FromSeconds(10), $"Client connected to process #{e.ProcessId}"); await EndSession(); FunctionAnalysisCache.DisableCache(); // Reduce memory usage. var result = new LoadedDocument("Debug session", "", Guid.NewGuid()); debugSections_ = new DebugSectionLoader(compilerInfo_.IR); debugSummary_ = await debugSections_.LoadDocument(null); result.Loader = debugSections_; result.Summary = debugSummary_; result.ModuleName = "Debug session"; SetupOpenedIRDocument(SessionKind.DebugSession, result).Wait(); debugCurrentIteratorElement_ = new Dictionary(); debugProcessId_ = e.ProcessId; debugSectionId_ = 0; debugFunction_ = null; previousDebugSection_ = null; // Mark session started. Trace.WriteLine("<= OnSessionStarted\n"); sessionStartTask_.Complete(); } catch (Exception ex) { Trace.TraceError("Failed to start debug session: {0}", $"{ex.Message}\n{ex.StackTrace}"); SetOptionalStatus("Failed to start debug session", ex.Message, Brushes.Red); sessionStartTask_.Cancel(); } }), DispatcherPriority.Send); } private struct ElementIteratorId { public int ElementId; public IRElementKind ElementKind; public ElementIteratorId(int elementId, IRElementKind elementKind) { ElementId = elementId; ElementKind = elementKind; } public override bool Equals(object obj) { return obj is ElementIteratorId id && ElementId == id.ElementId && ElementKind == id.ElementKind; } public override int GetHashCode() { return HashCode.Combine(ElementId, ElementKind); } } } ================================================ FILE: src/ProfileExplorerUI/MainWindowDiff.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using DiffPlex.DiffBuilder.Model; using ProfileExplorer.Core; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Document.Renderers.Highlighters; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Utilities; using ProfileExplorer.UI.Diff; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorerUI.Session; using static System.Runtime.InteropServices.JavaScript.JSType; namespace ProfileExplorer.UI; public partial class MainWindow : Window, IUISession { private OptionsPanelHostPopup diffOptionsPanelHost_; private DateTime documentLoadStartTime_; private bool documentLoadProgressVisible_; private bool loadingDocuments_; private bool diffOptionsVisible_; public async Task ReloadDiffSettings(DiffSettings newSettings, bool hasHandlingChanges) { if (!IsInDiffMode) { return; } if (hasHandlingChanges) { // Diffs must be recomputed. var leftDocument = sessionState_.SectionDiffState.LeftDocument; var rightDocument = sessionState_.SectionDiffState.RightDocument; await ExitDocumentDiffState(); await EnterDocumentDiffState(leftDocument, rightDocument); } else { // Only diff style must be updated. await sessionState_.SectionDiffState.LeftDocument.ReloadSettings(); await sessionState_.SectionDiffState.RightDocument.ReloadSettings(); } } private async void OpenBaseDiffDocumentsExecuted(object sender, ExecutedRoutedEventArgs e) { await OpenBaseDiffDocuments(); } private async Task OpenBaseDiffDocuments() { var openWindow = new DiffOpenWindow(this); openWindow.Owner = this; bool? result = openWindow.ShowDialog(); if (result.HasValue && result.Value) { await OpenBaseDiffDocuments(openWindow.BaseFilePath, openWindow.DiffFilePath); } } private async Task<(ILoadedDocument, ILoadedDocument)> OpenBaseDiffDocuments(string baseFilePath, string diffFilePath) { var (baseDoc, diffDoc) = await OpenBaseDiffIRDocumentsImpl(baseFilePath, diffFilePath); if (baseDoc == null || diffDoc == null) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show("Failed to load base/diff files", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } return (baseDoc, diffDoc); } private async void ToggleDiffModeExecuted(object sender, ExecutedRoutedEventArgs e) { if (!IsSessionStarted) { return; // No sessions started yet. } if (IsInDiffMode) { await ExitDocumentDiffState(); } else { await EnterDocumentDiffState(); } } private async void SwapDiffDocumentsExecuted(object sender, ExecutedRoutedEventArgs e) { if (!IsSessionStarted) { return; // No sessions started yet. } await SwapDiffedDocuments(); } private async Task<(ILoadedDocument, ILoadedDocument)> OpenBaseDiffIRDocumentsImpl(string baseFilePath, string diffFilePath) { ILoadedDocument baseResult = null; ILoadedDocument diffResult = null; try { await EndSession(); UpdateUIBeforeLoadDocument($"Loading {baseFilePath}, {diffFilePath}"); if (Utils.IsBinaryFile(baseFilePath) && Utils.IsBinaryFile(diffFilePath)) { (baseResult, diffResult) = await OpenBinaryBaseDiffIRDocuments(baseFilePath, diffFilePath); } else { //? HACK: Set the module name of both docs to be the same, //? otherwise lookup by IRTextFunction in the diff doc will fail the hash checks. (baseResult, diffResult) = await LoadBaseDiffIRDocuments(baseFilePath, baseFilePath, diffFilePath, diffFilePath); } } catch (Exception ex) { await EndSession(); Trace.TraceError($"Failed to load base/diff documents: {ex}"); } UpdateUIAfterLoadDocument(); return (baseResult, diffResult); } private async Task<(ILoadedDocument, ILoadedDocument)> LoadBinaryBaseDiffIRDocuments(string baseFilePath, string baseModuleName, string diffFilePath, string diffModuleName) { await SwitchBinaryCompilerTarget(baseFilePath); var baseTask = Task.Run(() => LoadBinaryDocument(baseFilePath, baseModuleName, Guid.NewGuid(), UpdateIRDocumentLoadProgress)); var diffTask = Task.Run(() => LoadBinaryDocument(diffFilePath, diffModuleName, Guid.NewGuid(), UpdateIRDocumentLoadProgress)); var baseResult = await baseTask; var diffResult = await diffTask; if (baseResult != null && diffResult != null) { await SetupOpenedIRDocument(SessionKind.Default, baseResult); await SetupOpenedDiffIRDocument(diffFilePath, diffResult); return (baseResult, diffResult); } await EndSession(); Trace.TraceWarning($"Failed to load base/diff documents: base {baseResult != null}, diff {diffResult != null}"); return (null, null); } private async Task<(ILoadedDocument, ILoadedDocument)> LoadBaseDiffIRDocuments(string baseFilePath, string baseModuleName, string diffFilePath, string diffModuleName) { var baseTask = Task.Run(() => LoadDocument(baseFilePath, baseModuleName, Guid.NewGuid(), UpdateIRDocumentLoadProgress)); var diffTask = Task.Run(() => LoadDocument(diffFilePath, diffModuleName, Guid.NewGuid(), UpdateIRDocumentLoadProgress)); var baseResult = await baseTask; var diffResult = await diffTask; if (baseResult != null && diffResult != null) { await SetupOpenedIRDocument(SessionKind.Default, baseResult); await SetupOpenedDiffIRDocument(diffFilePath, diffResult); return (baseResult, diffResult); } await EndSession(); Trace.TraceWarning($"Failed to load base/diff documents: base {baseResult != null}, diff {diffResult != null}"); return (null, null); } private async Task<(ILoadedDocument, ILoadedDocument)> OpenBinaryBaseDiffIRDocuments(string baseFilePath, string diffFilePath) { //? HACK: Set the module name of both docs to be the same, //? otherwise lookup by IRTextFunction in the diff doc will fail the hash checks. var (baseLoadedDoc, diffLoadedDoc) = await LoadBinaryBaseDiffIRDocuments(baseFilePath, baseFilePath, diffFilePath, baseFilePath); UpdateWindowTitle(); return (baseLoadedDoc, diffLoadedDoc); } private async void ToggleButton_Checked(object sender, RoutedEventArgs e) { if (ignoreDiffModeButtonEvent_) { return; } bool result = await EnterDocumentDiffState(); if (!result) { UpdateDiffModeButton(false); } } private async void OpenDiffDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { await Utils.ShowOpenFileDialogAsync(CompilerInfo.OpenFileFilter, "*.*", "Open diff file", async path => { bool loaded = await OpenDiffIRDocument(path); if (!loaded) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to load diff file {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } }); } private async void CloseDiffDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { if (!sessionState_.IsInTwoDocumentsDiffMode) { await ExitDocumentDiffState(); // Close each opened section associated with this document. var closedDocuments = new List(); foreach (var docHostInfo in sessionState_.DocumentHosts) { var summary = docHostInfo.DocumentHost.Section.ParentFunction.ParentSummary; if (summary == sessionState_.DiffDocument.Summary) { CloseDocument(docHostInfo); closedDocuments.Add(docHostInfo); } } foreach (var docHostInfo in closedDocuments) { sessionState_.DocumentHosts.Remove(docHostInfo); } sessionState_.RemoveLoadedDocuemnt(sessionState_.DiffDocument); // Reset the section panel. await SectionPanel.SetDiffSummary(null); sessionState_.ExitTwoDocumentDiffMode(); UpdateWindowTitle(); } } private bool IsDiffModeDocument(IRDocumentHost document) { return IsInDiffMode && (document == sessionState_.SectionDiffState.LeftDocument || document == sessionState_.SectionDiffState.RightDocument); } private async Task EnterDocumentDiffState() { if (!IsSessionStarted) { // No session started yet. return false; } await sessionState_.SectionDiffState.StartModeChange(); if (IsInDiffMode) { sessionState_.SectionDiffState.EndModeChange(); return true; } if (!PickLeftRightDocuments(out var leftDocument, out var rightDocument)) { sessionState_.SectionDiffState.EndModeChange(); return false; } bool result = await EnterDocumentDiffState(leftDocument, rightDocument); sessionState_.SectionDiffState.EndModeChange(); return result; } private async Task EnterDocumentDiffState(IRDocumentHost leftDocument, IRDocumentHost rightDocument) { //? TODO: Both these checks should be an assert if (!IsSessionStarted) { // No session started yet. return false; } if (IsInDiffMode) { return true; } sessionState_.SectionDiffState.LeftDocument = leftDocument; sessionState_.SectionDiffState.RightDocument = rightDocument; if (sessionState_.IsInTwoDocumentsDiffMode) { // Used when diffing two different documents. await SwitchDiffedDocumentSection(leftDocument.Section, leftDocument, false); } else { sessionState_.SectionDiffState.LeftSection = leftDocument.Section; sessionState_.SectionDiffState.RightSection = rightDocument.Section; await DiffCurrentDocuments(sessionState_.SectionDiffState); } // CreateDefaultSideBySidePanels(); ShowDiffsControlsPanel(); await UpdateUIAfterSectionSwitch(leftDocument.Section, leftDocument); await UpdateUIAfterSectionSwitch(rightDocument.Section, rightDocument); return true; } private bool PickLeftRightDocuments(out IRDocumentHost leftDocument, out IRDocumentHost rightDocument) { if (sessionState_.DocumentHosts.Count < 2) { leftDocument = rightDocument = null; return false; } // If one of the sections is already open, pick the associated document. // Otherwise, pick the last two created ones. leftDocument = sessionState_.DocumentHosts[^2].DocumentHost; rightDocument = sessionState_.DocumentHosts[^1].DocumentHost; return true; } private async Task ExitDocumentDiffState(bool isSessionEnding = false, bool disableControls = true) { await sessionState_.SectionDiffState.StartModeChange(); if (!IsInDiffMode) { sessionState_.SectionDiffState.EndModeChange(); return; } if (!isSessionEnding) { // Reload sections in the same documents. Trace.TraceInformation("Diff mode: Reload original sections"); var leftDocument = sessionState_.SectionDiffState.LeftDocument; var rightDocument = sessionState_.SectionDiffState.RightDocument; await DisableDocumentDiffState(sessionState_.SectionDiffState); var leftArgs = new OpenSectionEventArgs(leftDocument.Section, OpenSectionKind.ReplaceCurrent); var rightArgs = new OpenSectionEventArgs(rightDocument.Section, OpenSectionKind.ReplaceCurrent); await OpenDocumentSectionAsync(leftArgs, leftDocument, false); await OpenDocumentSectionAsync(rightArgs, rightDocument, false); } else { sessionState_.SectionDiffState.End(); } if (disableControls) { HideDiffsControlsPanel(); } sessionState_.SectionDiffState.EndModeChange(); sessionState_.ClearDiffModePanelState(); Trace.TraceInformation("Diff mode: Exited"); } private async void SectionPanel_EnterDiffMode(object sender, DiffModeEventArgs e) { if (IsInDiffMode) { sessionState_.SectionDiffState.End(); } await sessionState_.SectionDiffState.StartModeChange(); var leftDocument = FindDocumentWithSection(e.Left.Section); var rightDocument = FindDocumentWithSection(e.Right.Section); Trace.TraceInformation($"Diff mode: Start with left doc. {ObjectTracker.Track(leftDocument)}, " + $"right doc. {ObjectTracker.Track(rightDocument)}"); leftDocument = await OpenDocumentSectionAsync(e.Left, leftDocument, false); rightDocument = await OpenDocumentSectionAsync(e.Right, rightDocument, false); bool result = await EnterDocumentDiffState(leftDocument, rightDocument); UpdateDiffModeButton(result); sessionState_.SectionDiffState.EndModeChange(); Trace.TraceInformation("Diff mode: Entered"); } private async void SectionPanel_SyncDiffedDocumentsChanged(object sender, bool value) { if (IsInDiffMode) { if (IsInTwoDocumentsDiffMode && !value || !IsInTwoDocumentsDiffMode && value) { await ExitDocumentDiffState(); } } sessionState_.SyncDiffedDocuments = value; } private async Task DiffCurrentDocuments(DiffModeInfo diffState) { await EnableDocumentDiffState(diffState); var leftDocument = diffState.LeftDocument.TextView; var rightDocument = diffState.RightDocument.TextView; string leftText = await GetSectionTextAsync(leftDocument.Section); string rightText = await GetSectionTextAsync(rightDocument.Section); await DiffDocuments(leftDocument, rightDocument, leftText, rightText, leftDocument.Section, rightDocument.Section); if (diffState.PassOutputVisible) { await DiffDocumentPassOutput(leftDocument, rightDocument, diffState.PassOutputShowBefore); } } private async Task EnableDocumentDiffState(DiffModeInfo diffState) { // Notify panels about the current sections being unloaded // before diff mode is activated, since otherwise those sections // may be wrongly be associated with diff mode, for ex. the panel states. var leftDocumentHost = FindDocumentHost(diffState.LeftDocument.TextView); var rightDocumentHost = FindDocumentHost(diffState.RightDocument.TextView); await NotifyPanelsOfSectionUnload(diffState.LeftDocument.Section, leftDocumentHost, true); await NotifyPanelsOfSectionUnload(diffState.RightDocument.Section, rightDocumentHost, true); // Prepare documents for diff mode. await diffState.LeftDocument.EnterDiffMode(); await diffState.RightDocument.EnterDiffMode(); sessionState_.SectionDiffState.IsEnabled = true; } private async Task DisableDocumentDiffState(DiffModeInfo diffState) { // Notify panels about the current sections being unloaded // before diff mode is ended, since otherwise those sections // may be wrongly be associated with diff mode, for ex. the panel states. var leftDocumentHost = FindDocumentHost(diffState.LeftDocument.TextView); var rightDocumentHost = FindDocumentHost(diffState.RightDocument.TextView); await NotifyPanelsOfSectionUnload(diffState.LeftDocument.Section, leftDocumentHost, true); await NotifyPanelsOfSectionUnload(diffState.RightDocument.Section, rightDocumentHost, true); await diffState.LeftDocument.ExitDiffMode(); await diffState.RightDocument.ExitDiffMode(); sessionState_.SectionDiffState.End(); } private Task MarkSectionDiffs(IRTextSection section, string text, string otherText, DiffPaneModel diff, DiffPaneModel otherDiff, bool isRightDoc, IDiffOutputFilter diffFilter, FilteredDiffInput filteredInput, DiffStatistics diffStats) { var diffUpdater = new DocumentDiffUpdater(diffFilter, App.Settings.DiffSettings, compilerInfo_); return Task.Run(async () => { var result = diffUpdater.MarkDiffs(text, otherText, diff, otherDiff, isRightDoc, filteredInput, diffStats); var loadedDoc = FindLoadedDocument(section.ParentFunction); await diffUpdater.ReparseDiffedFunction(result, section, loadedDoc); return result; }); } private Task MarkIdenticalSectionDiffs(IRTextSection section, string text, IDiffOutputFilter diffFilter) { var diffUpdater = new DocumentDiffUpdater(diffFilter, App.Settings.DiffSettings, compilerInfo_); return Task.Run(async () => { var result = diffUpdater.CreateNoDiffDocument(text); var loadedDoc = FindLoadedDocument(section.ParentFunction); await diffUpdater.ReparseDiffedFunction(result, section, loadedDoc); return result; }); } private async Task ComputeSectionDiffs(string leftText, string rightText, IRTextSection newLeftSection, IRTextSection newRightSection) { if (CanReuseSectionDiffs(newLeftSection, newRightSection)) { return sessionState_.SectionDiffState.CurrentDiffResults; } // Start the actual document diffing on another thread. var diffBuilder = new DocumentDiffBuilder(App.Settings.DiffSettings); var diff = await Task.Run(() => diffBuilder.ComputeDiffs(leftText, rightText)); sessionState_.SectionDiffState.CurrentDiffResults = diff; sessionState_.SectionDiffState.CurrentDiffSettings = App.Settings.DiffSettings; return diff; } private bool IsSectionTextDifferent(IRTextSection sectionA, IRTextSection sectionB) { if (!sessionState_.AreSectionSignaturesComputed(sectionA) || !sessionState_.AreSectionSignaturesComputed(sectionB)) { return true; } return sectionA.IsSectionTextDifferent(sectionB); } private bool CanReuseSectionDiffs(IRTextSection newLeftSection, IRTextSection newRightSection) { // Check if the text of the two sections is the same // as the ones being currently compared. if (sessionState_.SectionDiffState.CurrentDiffResults == null || sessionState_.SectionDiffState.CurrentDiffSettings == null) { return false; } if (!sessionState_.SectionDiffState.CurrentDiffSettings.Equals(App.Settings.DiffSettings)) { return false; } return !IsSectionTextDifferent(newLeftSection, sessionState_.SectionDiffState.LeftSection) && !IsSectionTextDifferent(newRightSection, sessionState_.SectionDiffState.RightSection); } private async Task DiffDocuments(IRDocument leftDocument, IRDocument rightDocument, string leftText, string rightText, IRTextSection newLeftSection, IRTextSection newRightSection) { var leftDocumentHost = FindDocumentHost(leftDocument); var rightDocumentHost = FindDocumentHost(rightDocument); var leftDiffStats = new DiffStatistics(); var rightDiffStats = new DiffStatistics(); DiffMarkingResult leftDiffResult; DiffMarkingResult rightDiffResult; // Create the diff filter that will post-process the diff results. var leftDiffInputFilter = compilerInfo_.DiffFilterProvider?.CreateDiffInputFilter(); var rightDiffInputFilter = compilerInfo_.DiffFilterProvider?.CreateDiffInputFilter(); var diffFilter = compilerInfo_.DiffFilterProvider?.CreateDiffOutputFilter(); diffFilter?.Initialize(App.Settings.DiffSettings, compilerInfo_.IR); // Fairly often the text is identical, don't do the diffing for such cases. // Also frequent is to have different text, but it is on both left/right sides // identical to the previous sections - in this case the diff results are reused. if (IsSectionTextDifferent(newLeftSection, newRightSection)) { string leftDiffText = leftText; string rightDiffText = rightText; FilteredDiffInput leftFilteredInput = null; FilteredDiffInput rightFilteredInput = null; if (leftDiffInputFilter != null) { var leftTask = Task.Run(() => leftDiffInputFilter.FilterInputText(leftText)); var rightTask = Task.Run(() => rightDiffInputFilter.FilterInputText(rightText)); await Task.WhenAll(leftTask, rightTask); leftFilteredInput = await leftTask; rightFilteredInput = await rightTask; leftDiffText = leftFilteredInput.Text; rightDiffText = rightFilteredInput.Text; } var diff = await ComputeSectionDiffs(leftDiffText, rightDiffText, newLeftSection, newRightSection); // Apply the diff results on the left and right documents in parallel. // This will produce two AvalonEdit documents that will be installed // in the doc. hosts once back on the UI thread. var leftMarkTask = MarkSectionDiffs(newLeftSection, leftText, rightText, diff.OldText, diff.NewText, false, diffFilter, leftFilteredInput, leftDiffStats); var rightMarkTask = MarkSectionDiffs(newRightSection, leftText, rightText, diff.NewText, diff.OldText, true, diffFilter, rightFilteredInput, rightDiffStats); await Task.WhenAll(leftMarkTask, rightMarkTask); leftDiffResult = await leftMarkTask; rightDiffResult = await rightMarkTask; } else { var leftMarkTask = MarkIdenticalSectionDiffs(newLeftSection, leftText, diffFilter); var rightMarkTask = MarkIdenticalSectionDiffs(newRightSection, rightText, diffFilter); await Task.WhenAll(leftMarkTask, rightMarkTask); leftDiffResult = await leftMarkTask; rightDiffResult = await rightMarkTask; } // Update the diff session state. sessionState_.SectionDiffState.UpdateResults(leftDiffResult, newLeftSection, rightDiffResult, newRightSection); // The UI-thread dependent work. //? TODO: Workaround for some cases where the updated left/right docs //? don't have the same length due to a bug in diff updating. //? Making the docs the same length by appending whitespace prevents other //? problems that usually end up with the application asserting. if (leftDiffResult.DiffText.Length != rightDiffResult.DiffText.Length) { int length = Math.Max(leftDiffResult.DiffText.Length, rightDiffResult.DiffText.Length); leftDiffResult.DiffText = leftDiffResult.DiffText.PadRight(length); rightDiffResult.DiffText = rightDiffResult.DiffText.PadRight(length); } await leftDocumentHost.LoadDiffedFunction(leftDiffResult, newLeftSection); await rightDocumentHost.LoadDiffedFunction(rightDiffResult, newRightSection); ScrollToFirstDiff(leftDocument, rightDocument, leftDiffResult, rightDiffResult); UpdateDiffStatus(rightDiffStats); // For the active document only, notify panels of the change // and redo other section post-load tasks. if (IsActiveDocument(leftDocumentHost)) { await NotifyPanelsOfSectionLoad(newLeftSection, leftDocumentHost, true); await GenerateGraphs(newLeftSection, leftDocument, false); } else if (IsActiveDocument(rightDocumentHost)) { await NotifyPanelsOfSectionLoad(newRightSection, rightDocumentHost, true); await GenerateGraphs(newRightSection, rightDocument, false); } } private async Task DiffDocumentPassOutput() { await DiffDocumentPassOutput(sessionState_.SectionDiffState.LeftDocument.TextView, sessionState_.SectionDiffState.RightDocument.TextView, sessionState_.SectionDiffState.PassOutputShowBefore); } private async Task DiffDocumentPassOutput(IRDocument leftDocument, IRDocument rightDocument, bool useOutputBefore) { string leftText = await GetSectionOutputTextAsync(leftDocument.Section, useOutputBefore); string rightText = await GetSectionOutputTextAsync(rightDocument.Section, useOutputBefore); // Start the actual document diffing on another thread. var diffBuilder = new DocumentDiffBuilder(App.Settings.DiffSettings); var diff = await Task.Run(() => diffBuilder.ComputeDiffs(leftText, rightText)); // Apply the diff results on the left and right documents in parallel. // This will produce two AvalonEdit documents that will be installed // in the doc. hosts once back on the UI thread. var leftDiffStats = new DiffStatistics(); var rightDiffStats = new DiffStatistics(); var diffFilter = compilerInfo_.DiffFilterProvider?.CreateDiffOutputFilter(); diffFilter.Initialize(App.Settings.DiffSettings, compilerInfo_.IR); var leftMarkTask = MarkSectionDiffs(leftDocument.Section, leftText, rightText, diff.OldText, diff.NewText, false, diffFilter, null, leftDiffStats); var rightMarkTask = MarkSectionDiffs(rightDocument.Section, leftText, rightText, diff.NewText, diff.OldText, true, diffFilter, null, rightDiffStats); await Task.WhenAll(leftMarkTask, rightMarkTask); var leftDiffResult = await leftMarkTask; var rightDiffResult = await rightMarkTask; var leftDocumentHost = FindDocumentHost(leftDocument); var rightDocumentHost = FindDocumentHost(rightDocument); await leftDocumentHost.LoadDiffedPassOutput(leftDiffResult); await rightDocumentHost.LoadDiffedPassOutput(rightDiffResult); } private void ScrollToFirstDiff(IRDocument leftDocument, IRDocument rightDocument, DiffMarkingResult leftDiffResult, DiffMarkingResult rightDiffResult) { // Scroll to the first diff. If minor diffs are enabled, scroll to the first // major diff in either the left or right document. var firstLeftDiff = SelectFirstDiff(leftDiffResult); var firstRightDiff = SelectFirstDiff(rightDiffResult); var firstDiff = firstLeftDiff; var firstDiffDocument = leftDocument; if (firstRightDiff != null) { if (firstDiff == null || firstDiff.StartOffset > firstRightDiff.StartOffset) { firstDiff = firstRightDiff; firstDiffDocument = rightDocument; } } if (firstDiff != null) { firstDiffDocument.BringTextOffsetIntoView(firstDiff.StartOffset); } else { // When there are no diffs, scroll both documents to the start. leftDocument.BringTextOffsetIntoView(0); rightDocument.BringTextOffsetIntoView(0); } } private DiffTextSegment SelectFirstDiff(DiffMarkingResult diffResult) { if (diffResult.DiffSegments.Count == 0) { return null; } if (App.Settings.DiffSettings.IdentifyMinorDiffs) { // Pick the first major diff. foreach (var diff in diffResult.DiffSegments) { if (diff.Kind != DiffKind.MinorModification) { return diff; } } return null; } return diffResult.DiffSegments[0]; } private async Task SwitchDiffedDocumentSection(IRTextSection section, IRDocumentHost document, bool redoDiffs = true) { string leftText = null; string rightText = null; IRTextSection newLeftSection = null; IRTextSection newRightSection = null; if (document == sessionState_.SectionDiffState.LeftDocument) { var result = await LoadAndParseSection(section); leftText = result.Text.ToString(); //? TODO: Use Span newLeftSection = section; (rightText, newRightSection) = await SwitchOtherDiffedDocumentSide(section, sessionState_.SectionDiffState.RightDocument.Section, sessionState_.DiffDocument); newRightSection ??= sessionState_.SectionDiffState.RightDocument.Section; } else if (document == sessionState_.SectionDiffState.RightDocument) { var result = await LoadAndParseSection(section); rightText = result.Text.ToString(); //? TODO: Use Span newRightSection = section; (leftText, newLeftSection) = await SwitchOtherDiffedDocumentSide(section, sessionState_.SectionDiffState.LeftDocument.Section, sessionState_.MainDocument); newLeftSection ??= sessionState_.SectionDiffState.LeftDocument.Section; } else { // Document is not part of the diff set. return; } var leftDocument = sessionState_.SectionDiffState.LeftDocument; var rightDocument = sessionState_.SectionDiffState.RightDocument; await EnableDocumentDiffState(sessionState_.SectionDiffState); if (newLeftSection != null) { await UpdateUIAfterSectionSwitch(newLeftSection, leftDocument); } if (newRightSection != null) { await UpdateUIAfterSectionSwitch(newRightSection, rightDocument); } await DiffDocuments(leftDocument.TextView, rightDocument.TextView, leftText, rightText, newLeftSection, newRightSection); if (sessionState_.SectionDiffState.PassOutputVisible) { await DiffDocumentPassOutput(leftDocument.TextView, rightDocument.TextView, sessionState_.SectionDiffState.PassOutputShowBefore); } } private void HandleNoDiffDocuments(IRDocument leftDocument, IRDocument rightDocument) { // No diffs, don't run the differ. leftDocument.RemoveDiffTextSegments(); rightDocument.RemoveDiffTextSegments(); UpdateDiffStatus(new DiffStatistics()); } private async Task<(string, IRTextSection)> SwitchOtherDiffedDocumentSide(IRTextSection section, IRTextSection otherSection, ILoadedDocument otherDocument) { if (sessionState_.DiffDocument != null) { // When two documents are compared, try to pick // the other section from that other document. var diffSection = FindDiffDocumentSection(section, otherDocument); if (diffSection != null) { var result = await LoadAndParseSection(diffSection); return (result.Text.ToString(), diffSection); } return ($"Diff document does not have section {section.Name}", null); } { // Load the text of the other section, but don't reload anything else. var result = await LoadAndParseSection(otherSection); return (result.Text.ToString(), null); //? TODO: Use span } } private IRTextSection FindDiffDocumentSection(IRTextSection section, ILoadedDocument diffDoc) { return SectionPanel.FindDiffDocumentSection(section); } private void UpdateDiffModeButton(bool state) { ignoreDiffModeButtonEvent_ = true; DiffModeButton.IsChecked = state; ignoreDiffModeButtonEvent_ = false; } private void UpdateDiffStatus(DiffStatistics stats) { string text = ""; if (stats.LinesAdded == 0 && stats.LinesDeleted == 0 && stats.LinesModified == 0) { text = "0 diffs"; } else { text = $"A {stats.LinesAdded}, D {stats.LinesDeleted}, M {stats.LinesModified}"; } DiffStatusText.Text = text; } private async Task UpdateDiffedFunction(IRDocument document, DiffMarkingResult diffResult, IRTextSection newSection) { var documentHost = FindDocumentHost(document); await NotifyPanelsOfSectionUnload(document.Section, documentHost, true); // Load new text and function after diffing. await documentHost.LoadDiffedFunction(diffResult, newSection); await NotifyPanelsOfSectionLoad(document.Section, documentHost, true); await GenerateGraphs(newSection, document, false); } private async void DiffModeButton_Unchecked(object sender, RoutedEventArgs e) { if (ignoreDiffModeButtonEvent_) { return; } await ExitDocumentDiffState(); } private void HideDiffsControlsPanel() { UpdateDiffModeButton(false); DiffControlsPanel.Visibility = Visibility.Collapsed; } private void ShowDiffsControlsPanel() { UpdateDiffModeButton(true); DiffControlsPanel.Visibility = Visibility.Visible; } //? TODO: Switch to OptionsPanelHostPopup.Create private void ShowDiffOptionsPanel() { if (diffOptionsVisible_) { return; } double width = Math.Max(DiffOptionsPanel.MinimumWidth, Math.Min(MainGrid.ActualWidth, DiffOptionsPanel.DefaultWidth)); double height = Math.Max(DiffOptionsPanel.MinimumHeight, Math.Min(MainGrid.ActualHeight, DiffOptionsPanel.DefaultHeight)); var position = new Point(230, MainMenu.ActualHeight + 1); diffOptionsPanelHost_ = new OptionsPanelHostPopup(new DiffOptionsPanel(), position, width, height, MainGrid, App.Settings.DiffSettings.Clone(), this); diffOptionsPanelHost_.PanelClosed += DiffOptionsPanel_PanelClosed; diffOptionsPanelHost_.PanelReset += DiffOptionsPanel_PanelReset; diffOptionsPanelHost_.SettingsChanged += DiffOptionsPanel_SettingsChanged; diffOptionsPanelHost_.IsOpen = true; diffOptionsVisible_ = true; } private async Task CloseDiffOptionsPanel() { if (!diffOptionsVisible_) { return; } diffOptionsPanelHost_.IsOpen = false; diffOptionsPanelHost_.PanelClosed -= DiffOptionsPanel_PanelClosed; diffOptionsPanelHost_.PanelReset -= DiffOptionsPanel_PanelReset; diffOptionsPanelHost_.SettingsChanged -= DiffOptionsPanel_SettingsChanged; var newSettings = (UIDiffSettings)diffOptionsPanelHost_.Settings; await HandleNewDiffSettings(newSettings, true); diffOptionsPanelHost_ = null; diffOptionsVisible_ = false; } private async Task HandleNewDiffSettings(UIDiffSettings newSettings, bool commit, bool force = false) { if (force || !newSettings.Equals(App.Settings.DiffSettings)) { bool hasHandlingChanges = App.Settings.DiffSettings.HasDiffHandlingChanges(newSettings); App.Settings.DiffSettings = newSettings; await ReloadDiffSettings(newSettings, hasHandlingChanges); if (commit) { App.SaveApplicationSettings(); } } } private async void DiffOptionsPanel_PanelReset(object sender, EventArgs e) { var newSettings = new UIDiffSettings(); diffOptionsPanelHost_.Settings = newSettings; await HandleNewDiffSettings(newSettings, true); } private async void DiffOptionsPanel_SettingsChanged(object sender, EventArgs e) { var newSettings = (UIDiffSettings)diffOptionsPanelHost_.Settings; if (newSettings != null) { await HandleNewDiffSettings(newSettings, false); // It's possible that the options panel closes before the async method returns. if (diffOptionsPanelHost_ != null) { diffOptionsPanelHost_.Settings = newSettings.Clone(); } } } private async void DiffSettingsButton_Click(object sender, RoutedEventArgs e) { if (diffOptionsVisible_) { await CloseDiffOptionsPanel(); } else { ShowDiffOptionsPanel(); } } private async void DiffOptionsPanel_PanelClosed(object sender, EventArgs e) { await CloseDiffOptionsPanel(); } private async Task DiffSingleDocumentSections(IRDocumentHost doc, IRTextSection section, IRTextSection prevSection) { string prevText = sessionState_.FindLoadedDocument(prevSection).Loader.GetSectionText(prevSection); string currentText = sessionState_.FindLoadedDocument(section).Loader.GetSectionText(section); var diffBuilder = new DocumentDiffBuilder(App.Settings.DiffSettings); var diff = await Task.Run(() => diffBuilder.ComputeDiffs(prevText, currentText)); var diffStats = new DiffStatistics(); var diffFilter = compilerInfo_.DiffFilterProvider?.CreateDiffOutputFilter(); diffFilter.Initialize(App.Settings.DiffSettings, compilerInfo_.IR); var diffResult = await MarkSectionDiffs(section, prevText, currentText, diff.NewText, diff.OldText, true, diffFilter, null, diffStats); await UpdateDiffedFunction(doc.TextView, diffResult, section); DiffStatusText.Text = diffStats.ToString(); } private void PreviousSegmentDiffButton_Click(object sender, RoutedEventArgs e) { if (!IsInDiffMode) { return; } //? TODO: Diff segments from left/right should be combined and sorted by offset, //? right now considers only diff doc on right side. //? TODO: Code here is almost identical to the next case segment case below. var diffResults = sessionState_.SectionDiffState.RightDiffResults; var document = sessionState_.SectionDiffState.RightDocument; if (diffResults.DiffSegments.Count > 0) { int offset = document.TextView.CaretOffset; int index = diffResults.CurrentSegmentIndex; var currentSegment = diffResults.DiffSegments[index]; int currentLine = document.TextView.Document.GetLineByOffset(offset).LineNumber; bool found = false; //? TODO: Should use binary search while (index >= 0) { var candidate = diffResults.DiffSegments[index]; if (candidate.StartOffset < offset) { int line = document.TextView.Document.GetLineByOffset(candidate.StartOffset).LineNumber; if (line < currentLine) { // Skip groups of segments of the same type following one after another in the text // after the first one in the group has been selected. if (candidate.Kind == currentSegment.Kind && line == currentLine - 1) { currentLine = line; currentSegment = candidate; index--; continue; } found = true; break; } } index--; } if (found) { JumpToDiffSegmentAtIndex(index, diffResults, document); } } } private void NextDiffSegmentButton_Click(object sender, RoutedEventArgs e) { if (!IsInDiffMode) { return; } //? TODO: Diff segments from left/right should be combined and sorted by offset, //? right now considers only diff doc on right side. //? TODO: Code here is almost identical to the next case segment case below. var diffResults = sessionState_.SectionDiffState.RightDiffResults; var document = sessionState_.SectionDiffState.RightDocument; if (diffResults.DiffSegments.Count > 0) { int offset = document.TextView.CaretOffset; int index = diffResults.CurrentSegmentIndex; var currentSegment = diffResults.DiffSegments[index]; int currentLine = document.TextView.Document.GetLineByOffset(offset).LineNumber; bool found = false; //? TODO: Should use binary search while (index < diffResults.DiffSegments.Count) { var candidate = diffResults.DiffSegments[index]; if (candidate.StartOffset > offset) { int line = document.TextView.Document.GetLineByOffset(candidate.StartOffset).LineNumber; if (line > currentLine) { // Skip groups of segments of the same type following one after another in the text // after the first one in the group has been selected. if (candidate.Kind == currentSegment.Kind && line == currentLine + 1) { currentLine = line; currentSegment = candidate; index++; continue; } found = true; break; } } index++; } if (found) { JumpToDiffSegmentAtIndex(index, diffResults, document); } } } private async void DiffSwapButton_Click(object sender, RoutedEventArgs e) { await SwapDiffedDocuments(); } private async Task SwapDiffedDocuments() { if (!IsInDiffMode) { return; } var leftDocHost = sessionState_.SectionDiffState.LeftDocument; var rightDocHost = sessionState_.SectionDiffState.RightDocument; var leftSection = leftDocHost.Section; var rightSection = rightDocHost.Section; DiffSwapButton.IsEnabled = false; await ExitDocumentDiffState(false, false); // Swap the section displayed in the documents. await SwitchSection(rightSection, leftDocHost, false); await SwitchSection(leftSection, rightDocHost, false); await EnterDocumentDiffState(leftDocHost, rightDocHost); DiffSwapButton.IsEnabled = true; } private async void ExternalDiffButton_Click(object sender, RoutedEventArgs e) { var newSettings = App.Settings.DiffSettings.Clone(); newSettings.DiffImplementation = newSettings.DiffImplementation == DiffImplementationKind.Internal ? DiffImplementationKind.External : DiffImplementationKind.Internal; await HandleNewDiffSettings(newSettings, false); } private async void PreviousDiffButton_Click(object sender, RoutedEventArgs e) { if (!IsInDiffMode) { return; } var leftSection = sessionState_.SectionDiffState.LeftSection; var rightSection = sessionState_.SectionDiffState.RightSection; int leftIndex = leftSection.Number - 1; int rightIndex = rightSection.Number - 1; if (leftIndex > 0 && rightIndex > 0) { var prevLeftSection = leftSection.ParentFunction.Sections[leftIndex - 1]; var leftArgs = new OpenSectionEventArgs(prevLeftSection, OpenSectionKind.ReplaceCurrent); await OpenDocumentSectionAsync(leftArgs, sessionState_.SectionDiffState.LeftDocument); var prevRightSection = rightSection.ParentFunction.Sections[rightIndex - 1]; var rightArgs = new OpenSectionEventArgs(prevRightSection, OpenSectionKind.ReplaceCurrent); await OpenDocumentSectionAsync(rightArgs, sessionState_.SectionDiffState.RightDocument); } } private async void NextDiffButton_Click(object sender, RoutedEventArgs e) { if (!IsInDiffMode) { return; } var leftSection = sessionState_.SectionDiffState.LeftSection; var rightSection = sessionState_.SectionDiffState.RightSection; int leftIndex = leftSection.Number - 1; int rightIndex = rightSection.Number - 1; if (leftIndex < leftSection.ParentFunction.SectionCount - 1 && rightIndex < rightSection.ParentFunction.SectionCount - 1) { var prevLeftSection = leftSection.ParentFunction.Sections[leftIndex + 1]; var leftArgs = new OpenSectionEventArgs(prevLeftSection, OpenSectionKind.ReplaceCurrent); await OpenDocumentSectionAsync(leftArgs, sessionState_.SectionDiffState.LeftDocument); var prevRightSection = rightSection.ParentFunction.Sections[rightIndex + 1]; var rightArgs = new OpenSectionEventArgs(prevRightSection, OpenSectionKind.ReplaceCurrent); await OpenDocumentSectionAsync(rightArgs, sessionState_.SectionDiffState.RightDocument); } } private void JumpToDiffSegmentAtIndex(int index, DiffMarkingResult diffResults, IRDocumentHost document) { var nextDiff = diffResults.DiffSegments[index]; document.TextView.BringTextOffsetIntoView(nextDiff.StartOffset); document.TextView.SetCaretAtOffset(nextDiff.StartOffset); diffResults.CurrentSegmentIndex = index; } } ================================================ FILE: src/ProfileExplorerUI/MainWindowPanels.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using AvalonDock.Layout; using AvalonDock.Layout.Serialization; using ProfileExplorer.Core; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Panels; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Settings; using ProfileExplorer.UI.Windows; using ProfileExplorer.Core.Session; namespace ProfileExplorer.UI; public partial class MainWindow : Window, IUISession { public void UpdatePanelTitles() { RenameAllPanels(); } public void DisplayFloatingPanel(IToolPanel panel) { var panelHost = DisplayNewPanel(panel, null, DuplicatePanelKind.Floating); panelHost.Host.CanClose = true; panelHost.Host.CanAutoHide = false; panelHost.Host.CanHide = false; RenameAllPanels(); } public void RedrawPanels(params ToolPanelKind[] kinds) { foreach (var (kind, list) in panelHostSet_) { list.ForEach(item => { if (kinds.Length == 0 || kinds.Contains(item.PanelKind)) { item.Panel.OnRedrawPanel(); } }); } } public void PopulateBindMenu(IToolPanel panel, BindMenuItemsArgs args) { foreach (var doc in sessionState_.DocumentHosts) { var menuItem = new BindMenuItem { Header = compilerInfo_.NameProvider.GetSectionName(doc.DocumentHost.Section), ToolTip = doc.DocumentHost.Section.ParentFunction.Name, Tag = doc.DocumentHost.TextView, IsChecked = panel.BoundDocument == doc.DocumentHost.TextView }; args.MenuItems.Add(menuItem); } } public void BindToDocument(IToolPanel panel, BindMenuItem args) { var document = args.Tag as IRDocument; if (panel.BoundDocument == document) { // Unbind on second click. panel.BoundDocument = null; } else { panel.BoundDocument = document; } } public IRDocument FindAssociatedDocument(IToolPanel panel) { return panel.BoundDocument ?? FindActiveDocumentView(); } public IRDocumentHost FindAssociatedDocumentHost(IToolPanel panel) { if (panel.BoundDocument != null) { return FindDocumentHost(panel.BoundDocument); } return FindActiveDocumentHost(); } public void SavePanelState(object stateObject, IToolPanel panel, IRTextSection section, IRDocument document) { //? TODO: Find a way to at least temporarily save state for the two diffed docs //? Issue is that in diff mode a section can have a different FunctionIR depending //? on the other section is compared with if (IsInDiffMode) { if (document == null) { return; } var docHost = FindDocumentHost(document); if (sessionState_.SectionDiffState.IsDiffDocument(docHost)) { sessionState_.SaveDiffModePanelState(stateObject, panel, section); return; } } sessionState_.SavePanelState(stateObject, panel, section); } public object LoadPanelState(IToolPanel panel, IRTextSection section, IRDocument document) { if (IsInDiffMode) { if (document == null) { return null; } var docHost = FindDocumentHost(document); if (sessionState_.SectionDiffState.IsDiffDocument(docHost)) { return sessionState_.LoadDiffModePanelState(panel, section); } } return sessionState_.LoadPanelState(panel, section); } public void DuplicatePanel(IToolPanel panel, DuplicatePanelKind duplicateKind) { var newPanel = CreateNewPanel(panel.PanelKind); if (newPanel != null) { DisplayNewPanel(newPanel, panel, duplicateKind); RenamePanels(newPanel.PanelKind); newPanel.ClonePanel(panel); } } public void RegisterDetachedPanel(DraggablePopup panel) { if (!detachedPanels_.Contains(panel)) { detachedPanels_.Add(panel); } } public void UnregisterDetachedPanel(DraggablePopup panel) { if (panel.IsDetached) { detachedPanels_.Remove(panel); } } public async Task ShowPanel(ToolPanelKind panelKind) { // Panel hosts must be found at runtime because of deserialization. RegisterDefaultToolPanels(false); var panelHost = FindPanelHostForKind(panelKind); if (panelHost != null) { if (panelHost.IsAutoHidden) { panelHost.ToggleAutoHide(); } panelHost.Show(); panelHost.IsActive = true; } return FindPanel(panelKind); } private void RegisterDefaultToolPanels(bool reloadWorkspace = true) { Trace.WriteLine($"Register default tool panels"); RegisterPanel(SectionPanel, SectionPanelHost); RegisterPanel(FlowGraphPanel, FlowGraphPanelHost); RegisterPanel(DominatorTreePanel, DominatorTreePanelHost); // RegisterPanel(PostDominatorTreePanel, PostDominatorTreePanelHost); RegisterPanel(DefinitionPanel, DefinitionPanelHost); RegisterPanel(DeveloperPanel, DeveloperPanelHost); RegisterPanel(SourceFilePanel, SourceFilePanelHost); RegisterPanel(BookmarksPanel, BookmarksPanelHost); RegisterPanel(ReferencesPanel, ReferencesPanelHost); RegisterPanel(NotesPanel, NotesPanelHost); // RegisterPanel(PassOutputPanel, PassOutputHost); RegisterPanel(SearchResultsPanel, SearchResultsPanelHost); // RegisterPanel(ScriptingPanel, ScriptingPanelHost); RegisterPanel(ExpressionGraphPanel, ExpressionGraphPanelHost); RegisterPanel(CallTreePanel, CallTreePanelHost); RegisterPanel(CallerCalleePanel, CallerCalleePanelHost); RegisterPanel(FlameGraphPanel, FlameGraphPanelHost); RegisterPanel(TimelinePanel, TimelinePanelHost); RegisterPanel(HelpPanel, HelpPanelHost); RenameAllPanels(); if (reloadWorkspace) { var defaultWs = App.Settings.WorkspaceOptions.CreateNewActiveWorkspace(); SaveDockLayout(defaultWs.FilePath); PopulateWorkspacesCombobox(); RestoreDockLayout(defaultWs.FilePath); } } private async Task NotifyPanelsOfElementEvent(HandledEventKind eventKind, IRDocument document, Action action) { foreach (var (kind, list) in panelHostSet_) { foreach (var panelHost in list) { var panel = panelHost.Panel; if (!panel.IsPanelEnabled) { continue; } // Accept enabled panels handling the event. if (eventKind != HandledEventKind.None && (panel.HandledEvents & eventKind) == 0) { continue; } // Don't notify panels bound to another document // or with pinned content. if (!ShouldNotifyPanel(panel, document)) { continue; } // Sometimes the selection event is triggered before the // section-switched event, for ex. when clicking directly on // an element in another document, not first on the document // tab header. Ensure that the panel is connected properly. if (panel.IsUnloaded || panel.Document != document) { if (!panel.IsUnloaded) { await panel.OnDocumentSectionUnloaded(panel.Document.Section, panel.Document); } await panel.OnDocumentSectionLoaded(document.Section, document); // After this action, the load/unload events for the panel // will trigger, but since it was done here already, // don't do it again, slows down UI for no reason. //? TODO: Breaks proper switching of Flow Graph // panel.IgnoreNextLoadEvent = true; // panel.IgnoreNextUnloadEvent = true; } action(panel); } } } private void NotifyPanelsOfSessionStart() { ForEachPanel(panel => { panel.OnSessionStart(); }); } private void NotifyPanelsOfSessionEnd() { ForEachPanel(panel => { panel.OnSessionEnd(); panel.BoundDocument = null; }); // Hide other panels that are not dockable. CloseDocumentSearchPanel(); CloseDetachedPanels(); } private void NotifyPanelsOfSessionSave() { ForEachPanel(panel => { panel.OnSessionSave(); }); } private void NotifyDocumentsOfSessionSave() { sessionState_.DocumentHosts.ForEach(document => { document.DocumentHost.OnSessionSave(); }); } private async Task NotifyPanelsOfSectionLoad(IRTextSection section, IRDocumentHost document, bool notifyAll) { ForEachPanel(async panel => { // See comments in NotifyPanelsOfElementEvent about this check. if (panel.IgnoreNextLoadEvent) { panel.IgnoreNextLoadEvent = false; } else if (ShouldNotifyPanel(panel, document.TextView, notifyAll)) { await panel.OnDocumentSectionLoaded(section, document.TextView); } }); } private async Task NotifyPanelsOfSectionUnload(IRTextSection section, IRDocumentHost document, bool notifyAll, bool ignoreBoundPanels = false) { ForEachPanel(async panel => { // See comments in NotifyPanelsOfElementEvent about this check. if (panel.IgnoreNextUnloadEvent) { panel.IgnoreNextUnloadEvent = false; } else if (ShouldNotifyPanel(panel, document.TextView, notifyAll, ignoreBoundPanels)) { await panel.OnDocumentSectionUnloaded(section, document.TextView); } }); } private bool ShouldNotifyPanel(IToolPanel panel, IRDocument document, bool notifyAll = false, bool ignoreBoundPanels = false) { // Don't notify panels bound to another document or with pinned content. // If all panels should be notified, pinning in ignored. if (panel.BoundDocument == null) { if (notifyAll) { return true; } return !panel.HasPinnedContent; } if (ignoreBoundPanels) { return false; } return panel.BoundDocument == document; } private async Task NotifyOfSectionUnload(IRDocumentHost document, bool notifyAll, bool ignoreBoundPanels = false, bool switchingActiveDocument = false) { var section = document.Section; if (section != null) { document.UnloadSection(section, switchingActiveDocument); await NotifyPanelsOfSectionUnload(section, document, notifyAll, ignoreBoundPanels); } } private async Task NotifyPanelsOfElementHighlight(IRHighlightingEventArgs e, IRDocument document) { await NotifyPanelsOfElementEvent(HandledEventKind.ElementHighlighting, document, panel => panel.OnElementHighlighted(e)); } private async Task NotifyPanelsOfElementSelection(IRElementEventArgs e, IRDocument document) { await NotifyPanelsOfElementEvent(HandledEventKind.ElementSelection, document, panel => panel.OnElementSelected(e)); } private void SetupPanelEvents(PanelHostInfo panelHost) { panelHost.Host.Hiding += PanelHost_Hiding; panelHost.Host.Closing += PanelHost_Hiding; switch (panelHost.PanelKind) { case ToolPanelKind.FlowGraph: case ToolPanelKind.DominatorTree: case ToolPanelKind.PostDominatorTree: { var flowGraphPanel = panelHost.Panel as GraphPanel; flowGraphPanel.GraphViewer.BlockSelected += GraphViewer_GraphNodeSelected; flowGraphPanel.GraphViewer.BlockMarked += GraphViewer_BlockMarked; flowGraphPanel.GraphViewer.BlockUnmarked += GraphViewer_BlockUnmarked; flowGraphPanel.GraphViewer.GraphLoaded += GraphViewer_GraphLoaded; break; } case ToolPanelKind.ExpressionGraph: { var flowGraphPanel = panelHost.Panel as GraphPanel; flowGraphPanel.GraphViewer.BlockSelected += GraphViewer_GraphNodeSelected; flowGraphPanel.GraphViewer.GraphLoaded += GraphViewer_GraphLoaded; break; } case ToolPanelKind.CallGraph: { var callGraphPanel = panelHost.Panel as CallGraphPanel; callGraphPanel.GraphViewer.NodeSelected += GraphViewer_NodeSelected; break; } } } private void ResetPanelEvents(PanelHostInfo panelHost) { panelHost.Host.Hiding -= PanelHost_Hiding; panelHost.Host.Closing -= PanelHost_Hiding; switch (panelHost.PanelKind) { case ToolPanelKind.FlowGraph: case ToolPanelKind.DominatorTree: case ToolPanelKind.PostDominatorTree: { var flowGraphPanel = panelHost.Panel as GraphPanel; flowGraphPanel.GraphViewer.BlockSelected -= GraphViewer_GraphNodeSelected; flowGraphPanel.GraphViewer.BlockMarked -= GraphViewer_BlockMarked; flowGraphPanel.GraphViewer.BlockUnmarked -= GraphViewer_BlockUnmarked; flowGraphPanel.GraphViewer.GraphLoaded -= GraphViewer_GraphLoaded; break; } case ToolPanelKind.ExpressionGraph: { var flowGraphPanel = panelHost.Panel as GraphPanel; flowGraphPanel.GraphViewer.BlockSelected -= GraphViewer_GraphNodeSelected; flowGraphPanel.GraphViewer.GraphLoaded -= GraphViewer_GraphLoaded; break; } case ToolPanelKind.CallGraph: { var callGraphPanel = panelHost.Panel as CallGraphPanel; callGraphPanel.GraphViewer.NodeSelected -= GraphViewer_NodeSelected; break; } } } private async void DocumentHost_Closed(object sender, EventArgs e) { if (!(sender is LayoutDocument docHost)) { return; } var docHostInfo = FindDocumentHostPair(docHost); var document = docHostInfo.DocumentHost; // If the document is part of the active diff mode, // exit diff mode before removing it. if (IsDiffModeDocument(document)) { await ExitDocumentDiffState(); } await NotifyOfSectionUnload(document, true); UnbindPanels(docHostInfo.DocumentHost); RenameAllPanels(); ResetDocumentEvents(docHostInfo.DocumentHost); sessionState_.DocumentHosts.Remove(docHostInfo); if (sessionState_.DocumentHosts.Count > 0) { await SetActiveDocument(sessionState_.DocumentHosts[0]); } else { ResetActiveDocument(); } } private async Task SetActiveDocument(DocumentHostInfo newActivePanel, bool updateUI = true) { // Sometimes this is triggered when closing the app after the session was closed. if (!IsSessionStarted) { return; } activeDocumentPanel_ = newActivePanel.HostParent; foreach (var item in sessionState_.DocumentHosts) { item.IsActiveDocument = false; } newActivePanel.IsActiveDocument = true; if (updateUI) { var docHost = newActivePanel.DocumentHost; if (docHost.Section != null) { await SectionPanel.SelectSection(docHost.Section, false); await NotifyPanelsOfSectionLoad(docHost.Section, docHost, false); } } } private void ResetActiveDocument() { activeDocumentPanel_ = null; } private void UnbindPanels(IRDocumentHost document) { foreach (var (kind, list) in panelHostSet_) { foreach (var panelInfo in list) { if (panelInfo.Panel.BoundDocument == document.TextView) { panelInfo.Panel.BoundDocument = null; } } } } private async void DocumentHost_IsActiveChanged(object sender, EventArgs e) { if (!(sender is LayoutDocument docHost)) { return; } if (!IsSessionStarted) { return; // When closing main window, ignore even if triggered. } if (!(docHost.Content is IRDocumentHost document)) { return; } if (docHost.IsSelected) { var activeDocument = FindActiveDocumentHost(); if (activeDocument == document) { return; // Already active one. } if (activeDocument != null) { await NotifyOfSectionUnload(activeDocument, false, true, true); } var hostDocPair = FindDocumentHostPair(document); await SetActiveDocument(hostDocPair); } } private DocumentHostInfo FindDocumentHostPair(IRDocumentHost document) { return sessionState_.DocumentHosts.Find(item => item.DocumentHost == document); } private DocumentHostInfo FindDocumentHostPair(LayoutDocument host) { return sessionState_.DocumentHosts.Find(item => item.Host == host); } private IRDocumentHost FindDocumentHost(IRDocument document) { if (document == null) { return null; } return sessionState_.DocumentHosts.Find(item => item.DocumentHost.TextView == document).DocumentHost; } private IRDocumentHost FindSameSummaryDocumentHost(IRTextSection section) { var summary = section.ParentFunction.ParentSummary; var results = sessionState_.DocumentHosts.FindAll( item => item.DocumentHost.Section != null && item.DocumentHost.Section.ParentFunction.ParentSummary == summary); // Try to pick the active document out of the list. foreach (var result in results) { if (result.IsActiveDocument) { return result.DocumentHost; } } if (results.Count > 0) { return results[0].DocumentHost; } return null; } private IRDocumentHost FindActiveDocumentHost() { if (!IsSessionStarted) { return null; } var result = sessionState_.DocumentHosts.Find(item => item.IsActiveDocument); return result?.DocumentHost; } private IRDocument FindActiveDocumentView() { if (!IsSessionStarted) { return null; } var result = sessionState_.DocumentHosts.Find(item => item.IsActiveDocument); return result?.DocumentHost?.TextView; } private bool IsActiveDocument(IRDocumentHost document) { return FindActiveDocumentHost() == document; } private PanelHostInfo FindActivePanel(ToolPanelKind kind) { return panelHostSet_.TryGetValue(kind, out var list) ? list.Find(item => item.Panel.HasCommandFocus) : null; } private T FindActivePanel(ToolPanelKind kind) where T : class { var panelHost = FindActivePanel(kind); return panelHost?.Panel as T; } private List FindTargetPanels(IRDocument document, ToolPanelKind kind) { var panelList = new List(); if (panelHostSet_.TryGetValue(kind, out var list)) { // Add every panel not bound to another document. foreach (var panelInfo in list) { if (panelInfo.Panel.BoundDocument == null || panelInfo.Panel.BoundDocument == document) { panelList.Add(panelInfo); } } } return panelList; } private PanelHostInfo FindTargetPanel(IRDocument document, ToolPanelKind kind) { if (panelHostSet_.TryGetValue(kind, out var list)) { // Use the panel bound to the document. var boundPanel = list.Find(item => item.Panel.BoundDocument == document); if (boundPanel != null) { return boundPanel; } // Otherwise use, in order of preference: // - the last active panel that is unbound // - the last unbound panel // - the last active panel // - the last panel PanelHostInfo unboundPanelInfo = null; PanelHostInfo commandFocusPanelInfo = null; foreach (var item in list) { if (item.Panel.HasCommandFocus) { if (item.Panel.BoundDocument == null) { return item; } commandFocusPanelInfo = item; } else if (item.Panel.BoundDocument == null) { unboundPanelInfo = item; } } if (unboundPanelInfo != null) { return unboundPanelInfo; } if (commandFocusPanelInfo != null) { return commandFocusPanelInfo; } if (list.Count > 0) { return list[^1]; } } return null; } private T FindTargetPanel(IRDocument document, ToolPanelKind kind) where T : class { var panelInfo = FindTargetPanel(document, kind); return panelInfo?.Panel as T; } private PanelHostInfo FindPanelHost(IToolPanel panel) { if (panelHostSet_.TryGetValue(panel.PanelKind, out var list)) { return list.Find(item => item.Panel == panel); } return null; } private PanelHostInfo FindPanel(LayoutAnchorable panelHost) { foreach (var (kind, list) in panelHostSet_) { var result = list.Find(item => item.Host == panelHost); if (result != null) { return result; } } return null; } private string GetDefaultPanelName(ToolPanelKind kind) { return kind switch { ToolPanelKind.Bookmarks => "Bookmarks", ToolPanelKind.Definition => "Definition", ToolPanelKind.FlowGraph => "Flow Graph", ToolPanelKind.DominatorTree => "Dominator Tree", ToolPanelKind.PostDominatorTree => "Post-Dominator Tree", ToolPanelKind.ExpressionGraph => "Expression Graph", ToolPanelKind.CallGraph => "Call Graph", ToolPanelKind.CallTree => "Call Tree", ToolPanelKind.CallerCallee => "Caller/Callee", ToolPanelKind.FlameGraph => "Flame Graph", ToolPanelKind.Timeline => "Timeline", ToolPanelKind.Developer => "Developer", ToolPanelKind.Notes => "Notes", ToolPanelKind.References => "References", ToolPanelKind.Section => "Summary", ToolPanelKind.Source => "Source File", ToolPanelKind.PassOutput => "Pass Output", ToolPanelKind.SearchResults => "Search Results", ToolPanelKind.Scripting => "Scripting", ToolPanelKind.Help => "Help", _ => "" }; } private void RenamePanels(ToolPanelKind kind) { if (panelHostSet_.TryGetValue(kind, out var list)) { RenamePanels(kind, list); } } private string GetPanelName(ToolPanelKind kind, IToolPanel panel) { string name = GetDefaultPanelName(kind); if (!string.IsNullOrEmpty(panel.TitlePrefix)) { name = $"{panel.TitlePrefix}{name}"; } if (!string.IsNullOrEmpty(panel.TitleSuffix)) { name = $"{name}{panel.TitleSuffix}"; } if (panel.BoundDocument != null) { name = $"{name} - Bound to S{panel.BoundDocument.Section.Number} "; } return name; } private void RenamePanels(ToolPanelKind kind, List list) { if (list.Count == 1) { list[0].Host.Title = GetPanelName(kind, list[0].Panel); list[0].Host.ToolTip = list[0].Panel.TitleToolTip; } else { for (int i = 0; i < list.Count; i++) { string name = GetPanelName(kind, list[i].Panel); list[i].Host.Title = $"{name}:{i + 1}"; list[i].Host.ToolTip = list[i].Panel.TitleToolTip; } } } private void RenameAllPanels() { foreach (var (kind, list) in panelHostSet_) { RenamePanels(kind, list); } } private IToolPanel CreateNewPanel(ToolPanelKind kind) { return kind switch { ToolPanelKind.Definition => new DefinitionPanel(), ToolPanelKind.References => new ReferencesPanel(), ToolPanelKind.Notes => new NotesPanel(), ToolPanelKind.PassOutput => new PassOutputPanel(), ToolPanelKind.FlowGraph => new GraphPanel(), ToolPanelKind.DominatorTree => new GraphPanel(), ToolPanelKind.PostDominatorTree => new GraphPanel(), ToolPanelKind.ExpressionGraph => new ExpressionGraphPanel(), ToolPanelKind.SearchResults => new SearchResultsPanel(), ToolPanelKind.Scripting => new ScriptingPanel(), _ => throw new InvalidOperationException() }; } private T CreateNewPanel(ToolPanelKind kind) where T : class { return CreateNewPanel(kind) as T; } private PanelHostInfo DisplayNewPanel(IToolPanel newPanel, IToolPanel relativePanel, DuplicatePanelKind duplicateKind) { var panelHost = AddNewPanel(newPanel); bool attached = false; switch (duplicateKind) { case DuplicatePanelKind.Floating: { DisplayFloatingWindow(panelHost.Host); attached = true; break; } case DuplicatePanelKind.NewSetDockedLeft: { panelHost.Host.AddToLayout(DockManager, AnchorableShowStrategy.Right); if (relativePanel != null) { var baseHost = FindPanelHost(relativePanel).Host; var baseGroup = baseHost.FindParent(); if (baseGroup == null) { break; } baseGroup.Children.Insert(0, new LayoutAnchorablePane(panelHost.Host)); attached = true; } break; } case DuplicatePanelKind.NewSetDockedRight: { panelHost.Host.AddToLayout(DockManager, AnchorableShowStrategy.Right); if (relativePanel != null) { var baseHost = FindPanelHost(relativePanel).Host; var baseGroup = baseHost.FindParent(); if (baseGroup == null) { break; } baseGroup.Children.Add(new LayoutAnchorablePane(panelHost.Host)); attached = true; } break; } case DuplicatePanelKind.SameSet: { // Insert the new panel on the right of the cloned one. panelHost.Host.AddToLayout(DockManager, AnchorableShowStrategy.Right); var relativePanelHost = FindPanelHost(relativePanel); var relativeLayoutPane = relativePanelHost.Host.FindParent(); if (relativeLayoutPane == null) { break; } int basePaneIndex = relativeLayoutPane.Children.IndexOf(relativePanelHost.Host); relativeLayoutPane.Children.Insert(basePaneIndex + 1, panelHost.Host); attached = true; break; } default: throw new ArgumentOutOfRangeException(nameof(duplicateKind), duplicateKind, null); } // Docking can fail if the target panel is hidden, make it a floating panel. //? TODO: Should try to make the hidden panel visible if (!attached) { panelHost.Host.Float(); } panelHost.Host.IsSelected = true; return panelHost; } private void DisplayFloatingWindow(LayoutContent host) { //? TODO: Use saved position settings host.FloatingLeft = Left + 100; host.FloatingTop = Top + 100; host.FloatingWidth = 800; host.FloatingHeight = 600; var window = DockManager.CreateFloatingWindow(host, false); window.Show(); } private PanelHostInfo AddNewPanel(IToolPanel panel) { return RegisterPanel(panel, new LayoutAnchorable { Content = panel }); } private PanelHostInfo RegisterPanel(IToolPanel panel, LayoutAnchorable host) { var existingHost = FindPanelHost(panel); if (existingHost != null) { return existingHost; } if (!panelHostSet_.TryGetValue(panel.PanelKind, out var list)) { list = new List(); } var panelHost = new PanelHostInfo(panel, host); list.Add(panelHost); panelHostSet_[panel.PanelKind] = list; // Setup events. SetupPanelEvents(panelHost); panel.OnRegisterPanel(); panel.Session = this; // Make it the active panel in the group. SwitchCommandFocusToPanel(panelHost); return panelHost; } private void UnregisterPanel(PanelHostInfo panelHost) { if (panelHostSet_.TryGetValue(panelHost.PanelKind, out var list)) { list.Remove(panelHost); panelHost.Panel.OnUnregisterPanel(); panelHost.Panel.Session = null; } } private void ForEachPanel(ToolPanelKind panelKind, Action action) { if (panelHostSet_.TryGetValue(panelKind, out var list)) { list.ForEach(item => action(item.Panel)); } } private void ForEachPanel(Action action) { foreach (var (kind, list) in panelHostSet_) { list.ForEach(item => action(item.Panel)); } } private async Task ForEachPanelAsync(Func action) { foreach (var (kind, list) in panelHostSet_) { foreach (var item in list) { await action(item.Panel); } } } private void ForEachPanelHost(Action action) { foreach (var (kind, list) in panelHostSet_) { list.ForEach(item => action(item)); } } private void UpdatePanelEnabledState(bool enabled) { ForEachPanelHost(pair => { // Always keep the help panel enabled. if (pair.Panel.PanelKind != ToolPanelKind.Help) { if (enabled) { Utils.EnableControl(pair.Panel as UIElement); } else { Utils.DisableControl(pair.Panel as UIElement, 0.85); } } }); } private void SwitchCommandFocusToPanel(PanelHostInfo panelHost) { var activePanel = FindActivePanel(panelHost.PanelKind); if (activePanel != null) { activePanel.Panel.HasCommandFocus = false; } panelHost.Panel.HasCommandFocus = true; } private void PickCommandFocusPanel(ToolPanelKind kind) { // Pick last panel without pinned content. if (!panelHostSet_.TryGetValue(kind, out var list)) { return; } if (list.Count == 0) { return; } var lastPanel = list.FindLast(item => !item.Panel.HasPinnedContent); if (lastPanel == null) { // If not found, just pick the last panel. lastPanel = list[^1]; } lastPanel.Panel.HasCommandFocus = true; } private void PanelHost_Hiding(object sender, CancelEventArgs e) { var panelHost = sender as LayoutAnchorable; var panelInfo = FindPanel(panelHost); panelInfo.Panel.HasCommandFocus = false; // panelInfo.Panel.IsPanelEnabled = false; UnregisterPanel(panelInfo); ResetPanelEvents(panelInfo); RenamePanels(panelInfo.PanelKind); PickCommandFocusPanel(panelInfo.PanelKind); } private void LayoutAnchorable_IsActiveChanged(object sender, EventArgs e) { if (!(sender is LayoutAnchorable panelHost)) { return; } if (!IsSessionStarted) { return; // When closing main window, ignore even if triggered. } if (!(panelHost.Content is IToolPanel toolPanel)) { return; } if (panelHost.IsActive) { toolPanel.OnActivatePanel(); } else { toolPanel.OnDeactivatePanel(); } } private void LayoutAnchorable_IsSelectedChanged(object sender, EventArgs e) { if (!(sender is LayoutAnchorable panelHost)) { return; } if (!(panelHost.Content is IToolPanel toolPanel)) { return; } if (panelHost.IsSelected) { toolPanel.OnShowPanel(); } else { toolPanel.OnHidePanel(); } } private async Task AddNewDocument(OpenSectionKind kind) { var document = new IRDocumentHost(this); var host = new LayoutDocument { Content = document }; // The document group must be found at runtime since when restoring // the dock layout to a previous state, it creates another layout tree // that is different than the initial layout defined in the XAML file. var documentGroup = DockManager.Layout.Descendents(). OfType().FirstOrDefault(); switch (kind) { case OpenSectionKind.ReplaceCurrent: case OpenSectionKind.NewTab: { if (activeDocumentPanel_ == null) { activeDocumentPanel_ = new LayoutDocumentPane(host); documentGroup.Children.Add(activeDocumentPanel_); } else { activeDocumentPanel_.Children.Add(host); } break; } case OpenSectionKind.NewTabDockLeft: case OpenSectionKind.ReplaceLeft: { activeDocumentPanel_ = new LayoutDocumentPane(host); documentGroup.Children.Insert(0, activeDocumentPanel_); break; } case OpenSectionKind.NewTabDockRight: case OpenSectionKind.ReplaceRight: { activeDocumentPanel_ = new LayoutDocumentPane(host); documentGroup.Children.Add(activeDocumentPanel_); break; } default: { throw new ArgumentOutOfRangeException(nameof(kind), kind, null); } } var documentHost = new DocumentHostInfo(document, host); documentHost.HostParent = activeDocumentPanel_; sessionState_.DocumentHosts.Add(documentHost); await SetActiveDocument(documentHost, false); host.IsActiveChanged += DocumentHost_IsActiveChanged; host.Closed += DocumentHost_Closed; host.IsSelected = true; return documentHost; } private async Task SetupPanels() { NotifyPanelsOfSessionStart(); await SetupSectionPanel(); } private async Task SetupSectionPanel() { if (SectionPanel.MainSummary == null) { SectionPanel.CompilerInfo = compilerInfo_; SectionPanel.Session = this; // Clear stale module summaries from any previous session // before adding the new ones. SectionPanel.ClearModuleSummaries(); foreach (var doc in sessionState_.Documents) { if (doc != sessionState_.MainDocument && doc != sessionState_.DiffDocument) { SectionPanel.AddModuleSummary(doc.Summary); } } await SectionPanel.SetMainSummary(sessionState_.MainDocument.Summary); SectionPanel.MainTitle = sessionState_.MainDocument.ModuleName; SectionPanel.OnSessionStart(); } if (sessionState_.IsInTwoDocumentsDiffMode) { await SectionPanel.SetDiffSummary(sessionState_.DiffDocument.Summary); SectionPanel.DiffTitle = sessionState_.DiffDocument.ModuleName; } if (sessionState_.IsInTwoDocumentsDiffMode) { await ShowSectionPanelDiffs(sessionState_.DiffDocument); } } private bool RestoreDockLayout() { if (App.Settings.WorkspaceOptions.RestoreDefaultActiveWorkspace() || !initialDockLayoutRestored_) { // Initial load and registration of active panel config. var activeWs = App.Settings.WorkspaceOptions.ActiveWorkspace; WorkspaceCombobox.SelectedIndex = activeWs.Order; initialDockLayoutRestored_ = true; return RestoreDockLayout(activeWs.FilePath); } return true; // No change needed. } private bool RestoreDockLayout(string dockLayoutFile) { try { Trace.WriteLine($"Restore dock layout from {dockLayoutFile}"); var serializer = new XmlLayoutSerializer(DockManager); var visiblePanels = new List(); var registeredPanelKinds = new HashSet(); serializer.LayoutSerializationCallback += (s, args) => { if (args.Model is LayoutDocument) { args.Cancel = true; // Don't recreate any document panels. } else { args.Content = args.Content; if (args.Content is not IToolPanel panel) { args.Cancel = true; return; } if (panel.PanelKind == ToolPanelKind.Other) { args.Cancel = true; return; } var panelHost = (LayoutAnchorable)args.Model; panelHost.IsActiveChanged += LayoutAnchorable_IsActiveChanged; panelHost.IsSelectedChanged += LayoutAnchorable_IsSelectedChanged; registeredPanelKinds.Add(panel.PanelKind); if (panelHost.IsVisible && panelHost.IsSelected) { visiblePanels.Add(panel); } switch (panel.PanelKind) { case ToolPanelKind.CallTree: { CallTreePanel = (CallTreePanel)panel; CallTreePanelHost = (LayoutAnchorable)args.Model; RegisterPanel(CallTreePanel, CallTreePanelHost); break; } case ToolPanelKind.CallerCallee: { CallerCalleePanel = (CallerCalleePanel)panel; CallerCalleePanelHost = (LayoutAnchorable)args.Model; RegisterPanel(CallerCalleePanel, CallerCalleePanelHost); break; } case ToolPanelKind.FlameGraph: { FlameGraphPanel = (FlameGraphPanel)panel; FlameGraphPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(FlameGraphPanel, FlameGraphPanelHost); break; } case ToolPanelKind.Timeline: { TimelinePanel = (TimelinePanel)panel; TimelinePanelHost = (LayoutAnchorable)args.Model; RegisterPanel(TimelinePanel, TimelinePanelHost); break; } case ToolPanelKind.Bookmarks: { BookmarksPanel = (BookmarksPanel)panel; BookmarksPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(BookmarksPanel, BookmarksPanelHost); break; } case ToolPanelKind.Definition: { DefinitionPanel = (DefinitionPanel)panel; DefinitionPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(DefinitionPanel, DefinitionPanelHost); break; } case ToolPanelKind.FlowGraph: { FlowGraphPanel = (GraphPanel)panel; FlowGraphPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(FlowGraphPanel, FlowGraphPanelHost); break; } case ToolPanelKind.DominatorTree: { DominatorTreePanel = (DominatorTreePanel)panel; DominatorTreePanelHost = (LayoutAnchorable)args.Model; RegisterPanel(DominatorTreePanel, DominatorTreePanelHost); break; } // case ToolPanelKind.PostDominatorTree: { // PostDominatorTreePanel = (PostDominatorTreePanel)panel; // PostDominatorTreePanelHost = (LayoutAnchorable)args.Model; // RegisterPanel(PostDominatorTreePanel, PostDominatorTreePanelHost); // break; // } case ToolPanelKind.ExpressionGraph: { ExpressionGraphPanel = (ExpressionGraphPanel)panel; ExpressionGraphPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(ExpressionGraphPanel, ExpressionGraphPanelHost); break; } case ToolPanelKind.Developer: { DeveloperPanel = (DeveloperPanel)panel; DeveloperPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(DeveloperPanel, DeveloperPanelHost); break; } case ToolPanelKind.Notes: { NotesPanel = (NotesPanel)panel; NotesPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(NotesPanel, NotesPanelHost); break; } case ToolPanelKind.References: { ReferencesPanel = (ReferencesPanel)panel; ReferencesPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(ReferencesPanel, ReferencesPanelHost); break; } case ToolPanelKind.Section: { SectionPanel = (SectionPanelPair)panel; SectionPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(SectionPanel, SectionPanelHost); break; } case ToolPanelKind.Source: { SourceFilePanel = (SourceFilePanel)panel; SourceFilePanelHost = (LayoutAnchorable)args.Model; RegisterPanel(SourceFilePanel, SourceFilePanelHost); break; } //case ToolPanelKind.PassOutput: { // PassOutputPanel = (PassOutputPanel)panel; // PassOutputHost = (LayoutAnchorable)args.Model; // RegisterPanel(PassOutputPanel, PassOutputHost); // break; //} case ToolPanelKind.SearchResults: { SearchResultsPanel = (SearchResultsPanel)panel; SearchResultsPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(SearchResultsPanel, SearchResultsPanelHost); break; } // case ToolPanelKind.Scripting: { // ScriptingPanel = (ScriptingPanel)panel; // ScriptingPanelHost = (LayoutAnchorable)args.Model; // RegisterPanel(ScriptingPanel, ScriptingPanelHost); // break; // } case ToolPanelKind.Help: { HelpPanel = (HelpPanel)panel; HelpPanelHost = (LayoutAnchorable)args.Model; RegisterPanel(HelpPanel, HelpPanelHost); break; } } } }; // Unregister existing panels. UnregisterAllPanels(); // Load panels from layout file. serializer.Deserialize(dockLayoutFile); // Manually invoke the events, they are not triggered automatically. foreach (var visiblePanel in visiblePanels) { visiblePanel.OnShowPanel(); visiblePanel.OnActivatePanel(); } RegisterNewVersionPanels(registeredPanelKinds); RenameAllPanels(); return true; } catch (Exception ex) { Trace.TraceError($"Failed to load dock layout: {ex}"); return false; } } private void RegisterNewVersionPanels(HashSet registeredPanelKinds) { // When a new panel kind is added in a new version of the app, // the previous dock layout files don't reference it and when restoring // the new panel is not registered properly in the UI. Code below fixes this // by re-adding the panel to the loaded dock layout. var panelKinds = Enum.GetValues(); foreach (var kind in panelKinds) { if (!registeredPanelKinds.Contains(kind)) { var newPanelHost = FindPanelHostForKind(kind); if (newPanelHost != null) { newPanelHost.Parent.RemoveChild(newPanelHost); newPanelHost.AddToLayout(DockManager, AnchorableShowStrategy.Right); } } } } private void UnregisterAllPanels() { var panelList = new List(); foreach (var panelSet in panelHostSet_) { foreach (var panel in panelSet.Value) { panelList.Add(panel); } } foreach (var panel in panelList) { UnregisterPanel(panel); } panelHostSet_.Clear(); } private void ShowDocumentSearchPanel() { if (documentSearchVisible_) { return; } if (!IsSessionStarted || sessionState_.Documents.Count == 0) { // No proper session started yet. return; } var position = new Point(236, MainMenu.ActualHeight + 1); documentSearchPanel_ = new DocumentSearchPanel(position, 800, 500, this, this, sessionState_.Documents[0]); documentSearchPanel_.PopupClosed += DocumentSearchPanel__PopupClosed; documentSearchPanel_.PopupDetached += DocumentSearchPanel__PopupDetached; documentSearchPanel_.IsOpen = true; documentSearchVisible_ = true; } private void DocumentSearchPanel__PopupDetached(object sender, EventArgs e) { RegisterDetachedPanel(documentSearchPanel_); } private void DocumentSearchPanel__PopupClosed(object sender, EventArgs e) { CloseDocumentSearchPanel(); } private void CloseDocumentSearchPanel() { if (!documentSearchVisible_) { return; } if (documentSearchPanel_.IsDetached) { UnregisterDetachedPanel(documentSearchPanel_); } documentSearchPanel_.IsOpen = false; documentSearchPanel_.PopupClosed -= DocumentSearchPanel__PopupClosed; documentSearchPanel_.PopupDetached -= DocumentSearchPanel__PopupDetached; documentSearchPanel_ = null; documentSearchVisible_ = false; } private bool SaveDockLayout() { if (App.Settings.WorkspaceOptions.ActiveWorkspace == null) { App.Settings.WorkspaceOptions.RestoreDefaultActiveWorkspace(); } return SaveDockLayout(App.Settings.WorkspaceOptions.ActiveWorkspace.FilePath); } public bool SaveDockLayout(string dockLayoutFile) { try { var serializer = new XmlLayoutSerializer(DockManager); Utils.TryDeleteFile(dockLayoutFile); serializer.Serialize(dockLayoutFile); return true; } catch (Exception ex) { Trace.TraceError($"Failed to save dock layout: {ex}"); return false; } } private void WorkspaceCombobox_SelectionChanged(object sender, SelectionChangedEventArgs e) { var selectedWs = WorkspaceCombobox.SelectedItem as Workspace; if (selectedWs != null && selectedWs != App.Settings.WorkspaceOptions.ActiveWorkspace) { SaveDockLayout(); // Save current layout before switching. App.Settings.WorkspaceOptions.ActiveWorkspace = selectedWs; RestoreDockLayout(selectedWs.FilePath); } } private void PopulateWorkspacesCombobox() { var list = App.Settings.WorkspaceOptions.Workspaces; WorkspaceCombobox.ItemsSource = new ObservableCollectionRefresh(list); if (App.Settings.WorkspaceOptions.ActiveWorkspace != null) { WorkspaceCombobox.SelectedIndex = App.Settings.WorkspaceOptions.ActiveWorkspace.Order; } } private void WorkspacesButton_OnClick(object sender, RoutedEventArgs e) { ShowWorkspacesWindow(); } private void ShowWorkspacesWindow() { var wsWindow = new WorkspacesWindow(); wsWindow.Owner = this; wsWindow.ShowDialog(); PopulateWorkspacesCombobox(); } private async void ShowPanelMenu_Click(object sender, RoutedEventArgs e) { string panelName = ((MenuItem)sender).Tag as string; var panelKind = Enum.Parse(panelName); await ShowPanel(panelKind); } private LayoutAnchorable FindPanelHostForKind(ToolPanelKind panelKind) { switch (panelKind) { case ToolPanelKind.Section: { return SectionPanelHost; } case ToolPanelKind.Definition: { return DefinitionPanelHost; } case ToolPanelKind.References: { return ReferencesPanelHost; } case ToolPanelKind.Bookmarks: { return SectionPanelHost; } case ToolPanelKind.Source: { return SourceFilePanelHost; } // case ToolPanelKind.PassOutput: { // return PassOutputHost; // } case ToolPanelKind.SearchResults: { return SearchResultsPanelHost; } case ToolPanelKind.Notes: { return NotesPanelHost; } // case ToolPanelKind.Scripting: { // return ScriptingPanelHost; // } case ToolPanelKind.Developer: { return DeveloperPanelHost; } case ToolPanelKind.FlowGraph: { return FlowGraphPanelHost; } case ToolPanelKind.DominatorTree: { return DominatorTreePanelHost; } // case ToolPanelKind.PostDominatorTree: { // return PostDominatorTreePanelHost; // } case ToolPanelKind.ExpressionGraph: { return ExpressionGraphPanelHost; } case ToolPanelKind.CallTree: { return CallTreePanelHost; } case ToolPanelKind.CallerCallee: { return CallerCalleePanelHost; } case ToolPanelKind.FlameGraph: { return FlameGraphPanelHost; } case ToolPanelKind.Timeline: { return TimelinePanelHost; } case ToolPanelKind.Help: { return HelpPanelHost; } default: return null; } } private void OpenLogMenu_Click(object sender, RoutedEventArgs e) { Trace.Flush(); string file = App.GetTraceFilePath(); if (File.Exists(file)) { try { var psi = new ProcessStartInfo(file) { UseShellExecute = true }; Process.Start(psi); } catch (Exception ex) { MessageBox.Show($"Failed to open log file {file}\n{ex.Message}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } else { MessageBox.Show($"No log file found: {file}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Warning); } } private void ResetWorkspaceMenu_Click(object sender, RoutedEventArgs e) { App.Settings.WorkspaceOptions.RestoreDefaultActiveWorkspace(); RestoreDockLayout(); } private void ForceGCMenu_Click(object sender, RoutedEventArgs e) { Trace.WriteLine("Force GC start"); GC.Collect(GC.MaxGeneration, GCCollectionMode.Aggressive, true, true); GC.WaitForPendingFinalizers(); Trace.WriteLine("Force GC end"); Trace.Flush(); } } ================================================ FILE: src/ProfileExplorerUI/MainWindowProfiling.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using ProfileExplorer.Core; using ProfileExplorer.UI.Compilers; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Windows; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Profile.ETW; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Settings; using ProfileExplorer.Core.Profile.Timeline; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.UI.Compilers.ASM; namespace ProfileExplorer.UI; public partial class MainWindow : Window, IUISession { private CancelableTaskInstance updateProfileTask_ = new(); private ProfileData.ProcessingResult allThreadsProfile_; private ProfileFilterState profileFilter_; private OptionsPanelHostPopup markingOptionsPanelPopup_; public bool IsProfileSession => ProfileData != null; public bool HasEnabledMarkedFunctions => MarkingSettings.HasEnabledFunctionMarkings; public bool HasEnabledMarkedModules => MarkingSettings.HasEnabledModuleMarkings; public ProfileData ProfileData => sessionState_?.ProfileData; public ProfileFilterState ProfileFilter { get => profileFilter_; set => profileFilter_ = value; } public async Task LoadProfileData(string profileFilePath, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { Trace.WriteLine($"LoadProfileData: Starting profile data loading for {profileFilePath}"); var sw = Stopwatch.StartNew(); using var provider = new ETWProfileDataProvider(); // Subscribe to events to replace the old session callbacks provider.SetupNewSessionRequested += OnSetupNewSessionRequested; provider.StartNewSessionRequested += OnStartNewSessionRequested; var result = await provider.LoadTraceAsync(profileFilePath, processIds, options, symbolSettings, report, progressCallback, cancelableTask); Trace.WriteLine($"LoadProfileData: LoadTraceAsync completed, result is {(result != null ? "NOT NULL" : "NULL")}"); Trace.WriteLine($"LoadProfileData: IsSessionStarted = {IsSessionStarted}"); if (!IsSessionStarted) { Trace.WriteLine($"LoadProfileData: ERROR - Session not started, returning false"); return false; } if (result != null) { result.Report = report; sessionState_.ProfileData = result; UpdateWindowTitle(); UnloadProfilingDebugInfo(); Trace.WriteLine($"LoadProfileData: Successfully set profile data in session"); } else { Trace.WriteLine($"LoadProfileData: ERROR - LoadTraceAsync returned null result"); } Trace.WriteLine($"Done profile load and setup: {sw}, {sw.ElapsedMilliseconds} ms"); Trace.Flush(); return result != null; } public async Task LoadProfileData(RawProfileData data, List processIds, ProfileDataProviderOptions options, SymbolFileSourceSettings symbolSettings, ProfileDataReport report, ProfileLoadProgressHandler progressCallback, CancelableTask cancelableTask) { var sw = Stopwatch.StartNew(); using var provider = new ETWProfileDataProvider(); // Subscribe to events to replace the old session callbacks provider.SetupNewSessionRequested += OnSetupNewSessionRequested; provider.StartNewSessionRequested += OnStartNewSessionRequested; var result = await provider.LoadTraceAsync(data, processIds, options, symbolSettings, report, progressCallback, cancelableTask); if (!IsSessionStarted) { return false; } if (result != null) { result.Report = report; sessionState_.ProfileData = result; UpdateWindowTitle(); UnloadProfilingDebugInfo(); } Trace.WriteLine($"Done profile load and setup: {sw}, {sw.ElapsedMilliseconds} ms"); Trace.Flush(); return result != null; } public async Task FilterProfileSamples(ProfileFilterState state) { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); SetApplicationProgress(true, double.NaN, "Filtering profiling data"); StartUIUpdate(); // Update the active profile UI. SetActiveProfileFilter(state); var totalSw = Stopwatch.StartNew(); Trace.WriteLine("--------------------------------------------------------\n"); Trace.WriteLine($"Profile filter {state.Filter}, samples {ProfileData.Samples.Count}"); var filterSw = Stopwatch.StartNew(); ProfileData.ProcessingResult result = null; // Profile before filtering. if (state.Filter.IncludesAll && allThreadsProfile_ != null) { // This speeds up going back to the unfiltered profile. Trace.WriteLine("Restore main profile"); result = ProfileData.RestorePreviousProfile(allThreadsProfile_); } else { Trace.WriteLine("Compute new profile"); result = await Task.Run(() => ProfileData.FilterFunctionProfile(state.Filter)); } if (result.Filter.IncludesAll) { Trace.WriteLine("Save main profile"); allThreadsProfile_ = result; } Trace.WriteLine($"ComputeFunctionProfile time: {filterSw.ElapsedMilliseconds} ms"); // Update all profiling panels. var updateSw = Stopwatch.StartNew(); await SectionPanel.RefreshProfile(); await RefreshProfilingPanels(); await ProfileSampleRangeDeselected(); Trace.WriteLine($"RefreshProfile time: {updateSw.ElapsedMilliseconds} ms"); Trace.WriteLine($"FilterProfileSamples time: {totalSw.ElapsedMilliseconds} ms"); Trace.WriteLine("--------------------------------------------------------\n"); ResetApplicationProgress(); StopUIUpdate(); return true; } public async Task RemoveProfileSamplesFilter() { await FilterProfileSamples(new ProfileFilterState()); await ProfileSampleRangeDeselected(); return true; } public async Task OpenProfileFunction(ProfileCallTreeNode node, OpenSectionKind openMode, ProfileSampleFilter instanceFilter = null, IRDocumentHost targetDocument = null) { if (node is not {HasFunction: true}) { return false; } return await OpenProfileFunction(node.Function, openMode, instanceFilter, targetDocument); } public async Task OpenProfileFunction(IRTextFunction function, OpenSectionKind openMode, ProfileSampleFilter instanceFilter = null, IRDocumentHost targetDocument = null) { var args = new OpenSectionEventArgs(function.Sections[0], openMode, targetDocument); var docHost = await SwitchDocumentSectionAsync(args); if (instanceFilter != null) { await docHost.SwitchProfileInstanceAsync(instanceFilter); } return true; } public async Task SwitchActiveProfileFunction(ProfileCallTreeNode node) { if (node is not {HasFunction: true}) { return false; } await SwitchActiveFunction(node.Function); return true; } public async Task OpenProfileSourceFile(ProfileCallTreeNode node, ProfileSampleFilter profileFilter = null) { if (node is not {HasFunction: true}) { return false; } return await OpenProfileSourceFile(node.Function, profileFilter); } public async Task OpenProfileSourceFile(IRTextFunction function, ProfileSampleFilter profileFilter = null) { if (FindPanel(ToolPanelKind.Source) is not SourceFilePanel panel) { panel = await ShowPanel(ToolPanelKind.Source) as SourceFilePanel; } if (panel != null && function.HasSections) { await panel.LoadSourceFile(function.Sections[0], profileFilter); } return true; } public async Task SelectProfileFunctionInPanel(ProfileCallTreeNode node, ToolPanelKind panelKind) { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); switch (panelKind) { case ToolPanelKind.CallTree: { if (FindAndActivatePanel(ToolPanelKind.CallTree) is not CallTreePanel panel) { panel = await ShowPanel(ToolPanelKind.CallTree) as CallTreePanel; } panel?.SelectFunction(node); break; } case ToolPanelKind.FlameGraph: { if (FindAndActivatePanel(ToolPanelKind.FlameGraph) is not FlameGraphPanel panel) { panel = await ShowPanel(ToolPanelKind.FlameGraph) as FlameGraphPanel; } panel?.SelectFunction(node); break; } case ToolPanelKind.Timeline: { if (FindAndActivatePanel(ToolPanelKind.Timeline) is not TimelinePanel panel) { panel = await ShowPanel(ToolPanelKind.Timeline) as TimelinePanel; } if (panel != null) { await SelectFunctionSamples(node, panel); } break; } case ToolPanelKind.Source: { await OpenProfileSourceFile(node); break; } case ToolPanelKind.Section: { if (FindAndActivatePanel(ToolPanelKind.Section) is not SectionPanel panel) { await ShowPanel(ToolPanelKind.Section); } await SwitchActiveProfileFunction(node); break; } default: { throw new InvalidOperationException(); } } return true; } public async Task SelectProfileFunctionInPanel(IRTextFunction func, ToolPanelKind panelKind) { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); switch (panelKind) { case ToolPanelKind.CallTree: { if (FindAndActivatePanel(ToolPanelKind.CallTree) is not CallTreePanel panel) { panel = await ShowPanel(ToolPanelKind.CallTree) as CallTreePanel; } panel?.SelectFunction(func); break; } case ToolPanelKind.FlameGraph: { if (FindAndActivatePanel(ToolPanelKind.FlameGraph) is not FlameGraphPanel panel) { panel = await ShowPanel(ToolPanelKind.FlameGraph) as FlameGraphPanel; } if (panel != null) { await panel.SelectFunction(func); } break; } case ToolPanelKind.Timeline: { if (FindAndActivatePanel(ToolPanelKind.Timeline) is not TimelinePanel panel) { panel = await ShowPanel(ToolPanelKind.Timeline) as TimelinePanel; } if (panel != null) { var nodeList = ProfileData.CallTree.GetSortedCallTreeNodes(func); if (nodeList is {Count: > 0}) { await SelectFunctionSamples(nodeList[0], panel); } } break; } default: { throw new InvalidOperationException(); } } return true; } public async Task ProfileSampleRangeSelected(SampleTimeRangeInfo range) { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); //? TODO: If an event fires during the call tree/sample filtering, //? either ignore it or better run it after the filtering is done if (ProfileData.CallTree == null) { return false; } var funcs = await Task.Run(() => FindFunctionsForSamples(range.StartSampleIndex, range.EndSampleIndex, range.ThreadId, ProfileData)); var sectionPanel = FindPanel(ToolPanelKind.Section) as SectionPanelPair; sectionPanel?.MarkFunctions(funcs.ToList()); var nodes = await Task.Run(() => FindCallTreeNodesForSamples(funcs, ProfileData)); var panel = FindPanel(ToolPanelKind.FlameGraph) as FlameGraphPanel; panel?.MarkFunctions(nodes); return true; } public async Task ProfileFunctionSelected(ProfileCallTreeNode node, ToolPanelKind sourcePanelKind) { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); //? TODO: If an event fires during the call tree/sample filtering, //? either ignore it or better run it after the filtering is done if (ProfileData.CallTree == null) { return false; } if (sourcePanelKind != ToolPanelKind.Section) { await SwitchActiveFunction(node.Function, false); } if (sourcePanelKind != ToolPanelKind.FlameGraph) { if (FindPanel(ToolPanelKind.FlameGraph) is FlameGraphPanel flameGraphPanel) { await flameGraphPanel.SelectFunction(node.Function, false); } } if (sourcePanelKind != ToolPanelKind.CallTree) { var callTreePanel = FindPanel(ToolPanelKind.CallTree) as CallTreePanel; callTreePanel?.SelectFunction(node); } if (sourcePanelKind != ToolPanelKind.CallerCallee) { if (FindPanel(ToolPanelKind.CallerCallee) is CallTreePanel callerCalleePanel) { //? TODO: Make it path-sensitive (show exact instance, not combined?) await callerCalleePanel?.DisplayProfileCallerCalleeTree(node.Function); } } if (FindPanel(ToolPanelKind.Timeline) is TimelinePanel panel) { //? TODO: Select only samples included in this call node, //? right now selects any instance of the func await SelectFunctionSamples(node, panel); } return true; } public async Task MarkProfileFunction(ProfileCallTreeNode node, ToolPanelKind sourcePanelKind, HighlightingStyle style) { if (sourcePanelKind == ToolPanelKind.Timeline) { if (FindPanel(ToolPanelKind.Timeline) is TimelinePanel panel) { var threadSamples = await Task.Run(() => FindFunctionSamples(node, ProfileData)); panel.MarkFunctionSamples(node, threadSamples, style); } } return true; } public async Task ProfileFunctionSelected(IRTextFunction function, ToolPanelKind sourcePanelKind) { if (ProfileData.CallTree == null) { return false; } var funcNodes = ProfileData.CallTree.GetSortedCallTreeNodes(function); if (funcNodes is {Count: > 0}) { await ProfileFunctionSelected(funcNodes[0], sourcePanelKind); } return true; } public async Task ProfileSampleRangeDeselected() { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); var panel = FindPanel(ToolPanelKind.FlameGraph) as FlameGraphPanel; panel?.ClearMarkedFunctions(); var sectionPanel = FindPanel(ToolPanelKind.Section) as SectionPanelPair; sectionPanel?.ClearMarkedFunctions(); return true; } public async Task ProfileFunctionDeselected() { using var cancelableTask = await updateProfileTask_.CancelCurrentAndCreateTaskAsync(); var panel = FindPanel(ToolPanelKind.Timeline) as TimelinePanel; panel?.ClearSelectedFunctionSamples(); var callerCalleePanel = FindPanel(ToolPanelKind.CallerCallee) as CallTreePanel; callerCalleePanel?.Reset(); return true; } public async Task GetDebugInfoProvider(IRTextFunction function) { var loadedDoc = FindLoadedDocument(function); return CompilerInfo.DebugInfoProviderFactory.GetOrCreateDebugInfoProvider(function, loadedDoc); } public async Task FunctionMarkingChanged(ToolPanelKind sourcePanelKind) { if (sourcePanelKind != ToolPanelKind.Section) { if (FindPanel(ToolPanelKind.Section) is SectionPanelPair panel) { await panel.UpdateMarkedFunctions(true); } } if (sourcePanelKind != ToolPanelKind.FlameGraph) { var panel = FindPanel(ToolPanelKind.FlameGraph) as FlameGraphPanel; panel?.UpdateMarkedFunctions(true); } if (sourcePanelKind != ToolPanelKind.CallTree) { if (FindPanel(ToolPanelKind.CallTree) is CallTreePanel panel) { await panel.UpdateMarkedFunctions(true); } } if (sourcePanelKind != ToolPanelKind.CallerCallee) { if (FindPanel(ToolPanelKind.CallerCallee) is CallTreePanel panel) { await panel.UpdateMarkedFunctions(true); } } // Also update any detached profiling popup. foreach (var popup in detachedPanels_) { if (popup is CallTreeNodePopup nodePopup) { nodePopup.UpdateMarkedFunctions(); } } OnPropertyChanged(nameof(HasEnabledMarkedModules)); OnPropertyChanged(nameof(HasEnabledMarkedFunctions)); return true; } private void SetActiveProfileFilter(ProfileFilterState state) { ProfileFilter = state; ProfileFilterStateHost.DataContext = null; ProfileFilterStateHost.DataContext = state; } private void UnloadProfilingDebugInfo() { if (ProfileData == null) { return; } // Free memory used by the debug info by unloading any objects // such as the PDB DIA reader using COM. Task.Run(() => { foreach ((string module, var debugInfo) in ProfileData.ModuleDebugInfo) { debugInfo.Unload(); } }); } private async void LoadProfileExecuted(object sender, ExecutedRoutedEventArgs e) { await LoadProfile(); } private async Task LoadProfile() { var window = new ProfileLoadWindow(this, false); window.Owner = this; bool? result = window.ShowDialog(); if (result.HasValue && result.Value) { await SetupLoadedProfile(); } } private async Task SetupLoadedProfile() { UpdateWindowTitle(); SetApplicationProgress(true, double.NaN, "Loading profiling data"); StartUIUpdate(); ProfileControlsVisible = true; await SetupPanels(); await RefreshProfilingPanels(); StopUIUpdate(); ResetApplicationProgress(); SetOptionalStatus(TimeSpan.FromSeconds(10), "Profile data loaded"); // Check for critical errors like DIA SDK registration failure if (PDBDebugInfoProvider.HasDiaRegistrationError) { await Dispatcher.BeginInvoke(() => { MessageBox.Show(this, $"Symbol resolution failed: {PDBDebugInfoProvider.DiaRegistrationError}\n\n" + "Function names will not be displayed until this is fixed.", "DIA SDK Not Registered", MessageBoxButton.OK, MessageBoxImage.Error); }); } } private async Task RefreshProfilingPanels() { var panelTasks = new List(); if (FindPanel(ToolPanelKind.CallTree) is CallTreePanel panel) { panelTasks.Add(panel.DisplayProfileCallTree()); } if (FindPanel(ToolPanelKind.FlameGraph) is FlameGraphPanel fgPanel) { panelTasks.Add(fgPanel.DisplayFlameGraph()); } if (FindPanel(ToolPanelKind.Timeline) is TimelinePanel timelinePanel) { panelTasks.Add(timelinePanel.DisplayFlameGraph()); } await Task.WhenAll(panelTasks.ToArray()); } private async void RecordProfileExecuted(object sender, ExecutedRoutedEventArgs e) { await RecordProfile(); } private async Task RecordProfile() { var window = new ProfileLoadWindow(this, true); window.Owner = this; bool? result = window.ShowDialog(); if (result.HasValue && result.Value) { await SetupLoadedProfile(); } } private void CanExecuteProfileCommand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = IsSessionStarted && sessionState_.ProfileData != null; e.Handled = true; } private void CanExecuteLoadProfileCommand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = !IsSessionStarted || sessionState_.ProfileData == null; e.Handled = true; } private void ViewProfileReportExecuted(object sender, ExecutedRoutedEventArgs e) { if (ProfileData?.Report != null) { ProfileReportPanel.ShowReportWindow(ProfileData.Report, this); } } private async Task SelectFunctionSamples(ProfileCallTreeNode node, TimelinePanel panel) { var threadSamples = await Task.Run(() => FindFunctionSamples(node, ProfileData)); panel.SelectFunctionSamples(threadSamples); } private Dictionary> FindFunctionSamples(ProfileCallTreeNode node, ProfileData profile) { return FunctionSamplesProcessor.Compute(node, profile, new ProfileSampleFilter()); } private HashSet FindFunctionsForSamples(int sampleStartIndex, int sampleEndIndex, int threadId, ProfileData profile) { var filter = new ProfileSampleFilter(); filter.TimeRange = new SampleTimeRangeInfo(TimeSpan.Zero, TimeSpan.Zero, sampleStartIndex, sampleEndIndex, threadId); if (threadId != -1) { filter.AddThread(threadId); } return FunctionsForSamplesProcessor.Compute(filter, profile); } private List FindCallTreeNodesForSamples(HashSet funcs, ProfileData profile) { //? TODO: If an event fires during the call tree/sample filtering, //? either ignore it or better run it after the filtering is done if (ProfileData.CallTree == null) { return new List(); } var callNodes = new HashSet(funcs.Count); foreach (var func in funcs) { var nodes = profile.CallTree.GetCallTreeNodes(func); if (nodes == null) continue; // Filter out nodes that are not in the call path leading to the function, // meaning that all parents of the node instance must be in the initial set // of functions covered by the samples. foreach (var node in nodes) { var parentNode = node.Caller; bool addNode = true; while (parentNode != null) { if (!funcs.Contains(parentNode.Function)) { addNode = false; break; } parentNode = parentNode.Caller; } if (addNode) { callNodes.Add(node); } } } return callNodes.ToList(); } private void RemoveProfileTimeRangeButton_Click(object sender, RoutedEventArgs e) { ProfileFilter?.RemoveTimeRangeFilter?.Invoke(); } private void RemoveProfileThreadButton_Click(object sender, RoutedEventArgs e) { ProfileFilter?.RemoveThreadFilter?.Invoke(); } private void RemoveProfileAllFiltersButton_Click(object sender, RoutedEventArgs e) { ProfileFilter?.RemoveAllFilters?.Invoke(); } private async void ClearFunctionsButton_Click(object sender, RoutedEventArgs e) { MarkingSettings.FunctionColors.Clear(); await ReloadMarkingSettings(); } private async void ClearModulesButton_Click(object sender, RoutedEventArgs e) { MarkingSettings.ModuleColors.Clear(); await ReloadMarkingSettings(); } private async void MarkingMenu_OnSubmenuOpened(object sender, RoutedEventArgs e) { // Add the saved markings menu items. CreateSavedMarkingMenu(SwitchMarkingsMenu, async markingSet => { MarkingSettings.SwitchMarkingSet(markingSet); await ReloadMarkingSettings(); }); CreateSavedMarkingMenu(AppendMarkingsMenu, async markingSet => { MarkingSettings.AppendMarkingSet(markingSet); await ReloadMarkingSettings(); }); // Add the built-in function markings to the menu, // if not already added, after the title "builtin markings" title. int insertionIndex = 1; foreach (object item in MarkingMenu.Items) { if (item is MenuItem menuItem && menuItem.Name == "BuiltinMarkingsMenu") { break; } insertionIndex++; } if (MarkingMenu.Items[insertionIndex] is not MenuItem stopMenuItem || !stopMenuItem.Tag.Equals("BuiltinMarkingsMenuEnd")) { return; // Already populated. } var builtinMarkings = MarkingSettings.BuiltinMarkingCategories; foreach (var markingSet in builtinMarkings.FunctionColors) { var item = new MenuItem { Header = markingSet.Title, ToolTip = DocumentUtils.FormatLongFunctionName(markingSet.Name), Tag = markingSet }; var colorSelector = new ColorSelector(); var selectorItem = new MenuItem { Header = colorSelector, Tag = markingSet }; colorSelector.ColorSelected += async (o, args) => { var style = markingSet.CloneWithNewColor(args.SelectedColor); MarkingSettings.UseFunctionColors = true; MarkingSettings.AddFunctionColor(style); await ReloadMarkingSettings(); }; item.Items.Add(selectorItem); MarkingMenu.Items.Insert(insertionIndex, item); insertionIndex++; } } private void CreateSavedMarkingMenu(MenuItem menu, Action action) { menu.Items.Clear(); foreach (var markingSet in MarkingSettings.SavedSets) { string tooltip = $"Function markings: {markingSet.FunctionColors.Count}"; tooltip += $"\nModule markings: {markingSet.ModuleColors.Count}"; tooltip += "\nRight-click to remove marking set"; var item = new MenuItem { Header = markingSet.Title, ToolTip = tooltip, Tag = markingSet }; item.Click += (sender, args) => action(markingSet); item.PreviewMouseRightButtonDown += (sender, args) => { MarkingSettings.RemoveMarkingSet(markingSet); menu.IsSubmenuOpen = false; }; menu.Items.Add(item); } } private async Task ReloadMarkingSettings() { // Notify all panels about the marking changes. await FunctionMarkingChanged(ToolPanelKind.Other); } private void SaveMarkingsMenuItem_OnClick(object sender, RoutedEventArgs e) { TextInputWindow input = new("Save marked functions/modules", "Saved marking set name:", "Save", "Cancel"); if (input.Show(out string result, true)) { MarkingSettings.SaveCurrentMarkingSet(result); } } private async void ImportMarkingsMenuItem_OnClick(object sender, RoutedEventArgs e) { if (MarkingSettings.ImportMarkings(this)) { await ReloadMarkingSettings(); } } private void ExportMarkingsMenuItem_OnClick(object sender, RoutedEventArgs e) { MarkingSettings.ExportMarkings(this); } private void EditMarkingsMenu_OnClick(object sender, RoutedEventArgs e) { string filePath = App.GetFunctionMarkingsFilePath(compilerInfo_.CompilerIRName); Utils.OpenExternalFile(filePath); } private async void CategoriesMenu_OnSubmenuOpened(object sender, RoutedEventArgs e) { if (e.OriginalSource is MenuItem menuItem && menuItem.Tag != null) { return; } await ProfilingUtils.CreateFunctionsCategoriesMenu(CategoriesMenu, async (o, args) => { if (o is MenuItem menuItem && menuItem.Tag is IRTextFunction func) { await SwitchActiveFunction(func); } }, null, MarkingSettings, this); } private async void FunctionMenu_OnSubmenuOpened(object sender, RoutedEventArgs e) { await ProfilingUtils.PopulateMarkedFunctionsMenu(FunctionMenu, MarkingSettings, this, e.OriginalSource, ReloadMarkingSettings); } private async void ModuleMenu_OnSubmenuOpened(object sender, RoutedEventArgs e) { await ProfilingUtils.PopulateMarkedModulesMenu(ModuleMenu, MarkingSettings, this, e.OriginalSource, ReloadMarkingSettings); } private async void CopyOverviewMenu_OnClick(object sender, RoutedEventArgs e) { (string html, string plaintext) = await ExportProfilingReportAsHtml(); Utils.CopyHtmlToClipboard(html, plaintext); } private async Task<(string Html, string Plaintext)> ExportProfilingReportAsHtml() { var markings = App.Settings.MarkingSettings.BuiltinMarkingCategories.FunctionColors; var markingCategoryList = await Task.Run(() => ProfilingUtils.CollectMarkedFunctions(markings, false, this)); return ProfilingExporting.ExportProfilingReportAsHtml(markingCategoryList, this, true, 20); } private async void ExportOverviewHtmlMenu_OnClick(object sender, RoutedEventArgs e) { string path = Utils.ShowSaveFileDialog("HTML file|*.html", "*.html|All Files|*.*"); bool success = true; if (!string.IsNullOrEmpty(path)) { try { (string html, _) = await ExportProfilingReportAsHtml(); await File.WriteAllTextAsync(path, html); } catch (Exception ex) { Trace.WriteLine($"Failed to save report to {path}: {ex.Message}"); success = false; } if (!success) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save profiling report to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private async void ExportOverviewMarkdownMenu_OnClick(object sender, RoutedEventArgs e) { string path = Utils.ShowSaveFileDialog("Markdown file|*.md", "*.md|All Files|*.*"); bool success = true; if (!string.IsNullOrEmpty(path)) { try { (_, string plaintext) = await ExportProfilingReportAsHtml(); await File.WriteAllTextAsync(path, plaintext); } catch (Exception ex) { Trace.WriteLine($"Failed to save report to {path}: {ex.Message}"); success = false; } if (!success) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save profiling report to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private async void CopyMarkedFunctionMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.CopyFunctionMarkingsAsHtml(this); } private async void ExportMarkedFunctionsHtmlMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportFunctionMarkingsAsHtmlFile(this); } private async void ExportMarkedFunctionsMarkdownMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportFunctionMarkingsAsMarkdownFile(this); } private async void CopyMarkedModulesMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.CopyModuleMarkingsAsHtml(this); } private async void ExportMarkedModulesHtmlMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportModuleMarkingsAsHtmlFile(this); } private async void ExportMarkedModulesMarkdownMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportModuleMarkingsAsMarkdownFile(this); } private void MarkingSettingsButton_Click(object sender, RoutedEventArgs e) { if (markingOptionsPanelPopup_ != null) { markingOptionsPanelPopup_.ClosePopup(); markingOptionsPanelPopup_ = null; return; } var positionAdjustment = new Point(330, MainMenu.ActualHeight + 1); markingOptionsPanelPopup_ = OptionsPanelHostPopup.Create( MarkingSettings.Clone(), MainGrid, this, async (newSettings, commit) => { if (!newSettings.Equals(MarkingSettings)) { App.Settings.MarkingSettings = newSettings; await ReloadMarkingSettings(); if (commit) { App.SaveApplicationSettings(); } return newSettings.Clone(); } return null; }, () => markingOptionsPanelPopup_ = null, positionAdjustment, true); } // Event handlers for ETWProfileDataProvider events to replace session callbacks private async Task OnSetupNewSessionRequested(ILoadedDocument mainDocument, List otherDocuments, ProfileData profileData) { await Dispatcher.InvokeAsync(async () => { sessionState_.MainDocument = mainDocument; sessionState_.RegisterLoadedDocument(mainDocument); foreach (var loadedDoc in otherDocuments) { sessionState_.RegisterLoadedDocument(loadedDoc); } // For profiling sessions, setup the UI is done // after the profiling window closes. if (profileData == null) { UpdateWindowTitle(); await SetupPanels(); } }); } private async Task OnStartNewSessionRequested(string sessionName, SessionKind sessionKind, ICompilerInfoProvider compilerInfo) { await Dispatcher.InvokeAsync(async () => { UpdateUIBeforeLoadDocument("profile"); // Create the UI compiler info provider using the provided IRMode await SwitchCompilerTarget(compilerInfo); StartSession(sessionName, sessionKind); UpdateUIAfterLoadDocument(); }); } } ================================================ FILE: src/ProfileExplorerUI/MainWindowSession.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection.PortableExecutable; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Graph; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.UI.Compilers; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Query; using ProfileExplorer.Core.Compilers.Architecture; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Binary; using ProfileExplorerUI.Session; using System.Linq; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.UI.Compilers.ASM; using ProfileExplorer.UI.Providers; namespace ProfileExplorer.UI; public partial class MainWindow : Window, IUISession { private SemaphoreSlim SessionLoadCompleted = new(1); public bool SilentMode { get; set; } public ICompilerInfoProvider CompilerInfo => compilerInfo_; public ISectionStyleProvider SectionStyleProvider => sectionStyleProvider_; public IRRemarkProvider RemarkProvider => remarkProvider_; public IBlockFoldingStrategyProvider BlockFoldingStrategyProvider => blockFoldingStrategyProvider_; public ILoadedSectionHandler LoadedSectionHandler => loadedSectionHandler_; public IRDocument CurrentDocument => FindActiveDocumentHost()?.TextView; public bool IsInDiffMode => sessionState_.SectionDiffState.IsEnabled; public bool IsInTwoDocumentsDiffMode => sessionState_.IsInTwoDocumentsDiffMode; public bool IsInTwoDocumentsMode => DiffDocumentSummary != null; public DiffModeInfo DiffModeInfo => sessionState_.SectionDiffState; public IRTextSummary MainDocumentSummary => sessionState_.MainDocument?.Summary; public IRTextSummary DiffDocumentSummary => sessionState_.DiffDocument?.Summary; public bool IsSessionStarted => sessionState_ != null; public IRTextSection CurrentDocumentSection { get { var activeDocument = FindActiveDocumentHost(); return activeDocument?.Section; } } public List OpenDocuments { get { var list = new List(); if (IsSessionStarted) { sessionState_.DocumentHosts.ForEach(doc => list.Add(doc.DocumentHost.TextView)); } return list; } } ICompilerInfoProvider ISession.CompilerInfo => CompilerInfo; public IReadOnlyList Documents => sessionState_.Documents; public IRTextFunction FindFunctionWithId(int funcNumber, Guid summaryId) { return sessionState_.FindFunctionWithId(funcNumber, summaryId); } public async Task OpenSessionDocument(string filePath) { try { await EndSession(); UpdateUIBeforeReadSession(filePath); byte[] data = await File.ReadAllBytesAsync(filePath); var state = await SessionStateManager.DeserializeSession(data); if (state != null) { var loadedDoc = await LoadSessionDocument(state); return loadedDoc; } } catch (Exception ex) { await EndSession(); Trace.TraceError($"Failed to load session, exception: {ex}"); } finally { UpdateUIAfterLoadDocument(); } return null; } public async Task SaveSessionDocument(string filePath) { try { NotifyPanelsOfSessionSave(); NotifyDocumentsOfSessionSave(); sessionState_.Info.IsSaved = true; byte[] data = await sessionState_.SerializeSession().ConfigureAwait(false); if (data != null) { await File.WriteAllBytesAsync(filePath, data).ConfigureAwait(false); SetOptionalStatus(TimeSpan.FromSeconds(10), "Session saved"); return true; } } catch (Exception ex) { SetOptionalStatus(TimeSpan.FromSeconds(10), "Failed to save session", ex.Message, Colors.DarkRed.AsBrush()); Trace.TraceError($"Failed to save session, exception: {ex}"); } return false; } public async Task OpenDocumentSectionAsync(OpenSectionEventArgs args) { return await OpenDocumentSectionAsync(args, args.TargetDocument); } public async Task LoadAndParseSection(IRTextSection section) { return await Task.Run(async () => { var docInfo = sessionState_.FindLoadedDocument(section); // This shouldn't happen if document was loaded properly... if (docInfo == null || docInfo.Loader == null) { Trace.WriteLine($"Failed LoadAndParseSection for function {section.ParentFunction.Name}"); Utils.WaitForDebugger(); return null; } // LAZY BINARY LOADING: If binary isn't loaded yet, try to load it now. // This happens during profiling when binaries are skipped during trace load. if (!docInfo.BinaryFileExists && docInfo.EnsureBinaryLoaded != null) { string moduleName = docInfo.ModuleName ?? section.ParentFunction.ParentSummary?.ModuleName ?? "binary"; Trace.WriteLine($"LoadAndParseSection: Binary not loaded for {section.ParentFunction.Name}, attempting lazy load..."); // Show status in UI while downloading await Dispatcher.InvokeAsync(() => { OptionalStatusText.Text = $"Downloading {moduleName} from symbol server..."; OptionalStatusText.ToolTip = $"Lazy loading binary for disassembly view. This may take a few seconds."; }); bool loaded = await docInfo.EnsureBinaryLoaded().ConfigureAwait(false); Trace.WriteLine($"LoadAndParseSection: Lazy binary load result: {loaded}"); // Clear status after download completes await Dispatcher.InvokeAsync(() => { if (loaded) { OptionalStatusText.Text = $"Downloaded {moduleName}"; } else { OptionalStatusText.Text = $"Failed to download {moduleName}"; } OptionalStatusText.ToolTip = ""; }); } var parsedSection = docInfo.Loader.LoadSection(section); if (parsedSection != null && parsedSection.Function != null) { var funcDebugInfo = ProfileData?.GetFunctionProfile(section.ParentFunction)?.FunctionDebugInfo; var loadedDoc = FindLoadedDocument(section.ParentFunction); await compilerInfo_.AnalyzeLoadedFunction(parsedSection.Function, section, loadedDoc, funcDebugInfo); addressTag_ = parsedSection.Function.GetTag(); return parsedSection; } string placeholderText = "Could not find function code"; var dummyFunc = new FunctionIR(section.ParentFunction.Name); return new ParsedIRTextSection(section, placeholderText.AsMemory(), dummyFunc) { LoadFailed = true }; }); } public async Task ComputeGraphAsync(GraphKind kind, IRTextSection section, IRDocument document, CancelableTask loadTask = null, object options = null) { var graphLayout = GetGraphLayoutCache(kind); loadTask ??= new CancelableTask(); // Required, but client may not care about canceling. return await Task.Run(() => graphLayout.GenerateGraph(document.Function, section, loadTask, options)); } public async Task ReloadDocumentSettings(DocumentSettings newSettings, IRDocument document) { // CompilerInfo no longer exposes ReloadSettings. foreach (var docHostInfo in sessionState_.DocumentHosts) { if (docHostInfo.DocumentHost.TextView != document) { docHostInfo.DocumentHost.Settings = newSettings; await docHostInfo.DocumentHost.ReloadSettings(); } } } public async Task ReloadRemarkSettings(RemarkSettings newSettings, IRDocument document) { foreach (var docHostInfo in sessionState_.DocumentHosts) { if (docHostInfo.DocumentHost.TextView != document) { await docHostInfo.DocumentHost.UpdateRemarkSettings(newSettings); } } } public async Task ReloadSettings() { // Reload UI settings. OnPropertyChanged(nameof(WindowScaling)); // Compiler provider no longer exposes ReloadSettings. if (!IsSessionStarted) { return; } // Reload settings for all open documents views. foreach (var docHostInfo in sessionState_.DocumentHosts) { await docHostInfo.DocumentHost.ReloadSettings(); } // Reload settings for all panels. await ForEachPanelAsync(async (panel) => await panel.OnReloadSettings()); await HandleNewDiffSettings(App.Settings.DiffSettings, false, true); } public Task GetSectionTextAsync(IRTextSection section, IRDocument targetDiffDocument = null) { if (IsInDiffMode && targetDiffDocument != null) { IRDocument diffDocument = null; if (targetDiffDocument == sessionState_.SectionDiffState.LeftDocument.TextView) { diffDocument = sessionState_.SectionDiffState.LeftDocument.TextView; } else if (targetDiffDocument == sessionState_.SectionDiffState.RightDocument.TextView) { diffDocument = sessionState_.SectionDiffState.RightDocument.TextView; } if (diffDocument != null) { return Task.FromResult(diffDocument.Text); } } var docInfo = sessionState_.FindLoadedDocument(section); return Task.Run(() => docInfo.Loader.GetSectionText(section)); } public Task GetSectionOutputTextAsync(IRPassOutput output, IRTextSection section) { var docInfo = sessionState_.FindLoadedDocument(section); return Task.Run(() => docInfo.Loader.GetSectionOutputText(output)); } public Task> GetSectionOutputTextLinesAsync(IRPassOutput output, IRTextSection section) { var docInfo = sessionState_.FindLoadedDocument(section); return Task.Run(() => docInfo.Loader.GetSectionPassOutputTextLines(output)); } public Task GetDocumentTextAsync(IRTextSummary summary) { var docInfo = sessionState_.FindLoadedDocument(summary); return Task.Run(() => docInfo.Loader.GetDocumentOutputText()); } public IToolPanel FindPanel(ToolPanelKind kind) { var panelInfo = FindTargetPanel(null, kind); if (panelInfo != null) { return panelInfo.Panel; } return null; } public void ActivatePanel(IToolPanel panel) { var panelHost = FindPanelHost(panel); if (panelHost != null) { panelHost.Host.Show(); panelHost.Host.IsActive = true; } } public async Task SearchSectionAsync( SearchInfo searchInfo, IRTextSection section, IRDocument document) { var docInfo = sessionState_.FindLoadedDocument(section); var searcher = new SectionTextSearcher(docInfo.Loader); if (searchInfo.SearchAll) { var sections = section.ParentFunction.Sections; var results = await searcher.SearchAsync(searchInfo.SearchedText, searchInfo.SearchKind, sections); var panelInfo = FindTargetPanel(document, ToolPanelKind.SearchResults); var searchPanel = panelInfo.Panel as SearchResultsPanel; searchPanel.UpdateSearchResults(results, searchInfo); if (results.Count > 0) { panelInfo.Host.IsSelected = true; } // Return the results for the section that started the search, if any. var sectionResult = results.Find(item => item.Section == section); return sectionResult ?? new SectionSearchResult(section); } // In diff mode, use the diff text being displayed, which may be different // than the original section text due to diff annotations. if (document.DiffModeEnabled) { return await searcher.SearchSectionWithTextAsync(document.Text, searchInfo.SearchedText, searchInfo.SearchKind, section); } return await searcher.SearchSectionAsync(searchInfo.SearchedText, searchInfo.SearchKind, section); } public bool SwitchToPreviousSection(IRTextSection section, IRDocument document) { var prevSection = GetPreviousSection(section); if (prevSection != null) { var docHost = FindDocumentHost(document); SectionPanel.SwitchToSection(prevSection, docHost); return true; } return false; } public bool SwitchToNextSection(IRTextSection section, IRDocument document) { var nextSection = GetNextSection(section); if (nextSection != null) { var docHost = FindDocumentHost(document); SectionPanel.SwitchToSection(nextSection, docHost); return true; } return false; } public IRTextSection GetNextSection(IRTextSection section) { int index = section.Number - 1; if (index < section.ParentFunction.SectionCount - 1) { return section.ParentFunction.Sections[index + 1]; } return null; } public IRTextSection GetPreviousSection(IRTextSection section) { int index = section.Number - 1; if (index > 0) { return section.ParentFunction.Sections[index - 1]; } return null; } public void SaveDocumentState(object stateObject, IRTextSection section) { if (IsInDiffMode) { //? TODO: Find a way to at least temporarily save state for the two diffed docs //? Issue is that in diff mode a section can have a different FunctionIR depending //? on the other section is compared with if (section == sessionState_.SectionDiffState.LeftSection || section == sessionState_.SectionDiffState.RightSection) { return; } } sessionState_.SaveDocumentState(stateObject, section); } public object LoadDocumentState(IRTextSection section) { if (IsInDiffMode) { if (section == sessionState_.SectionDiffState.LeftSection || section == sessionState_.SectionDiffState.RightSection) { return null; } } return sessionState_.LoadDocumentState(section); } public bool SaveFunctionTaskOptions(FunctionTaskInfo taskInfo, IFunctionTaskOptions options) { byte[] data = FunctionTaskOptionsSerializer.Serialize(options); App.Settings.SaveFunctionTaskOptions(taskInfo, data); return true; } public IFunctionTaskOptions LoadFunctionTaskOptions(FunctionTaskInfo taskInfo) { byte[] data = App.Settings.LoadFunctionTaskOptions(taskInfo); if (data != null) { return FunctionTaskOptionsSerializer.Deserialize(data, taskInfo.OptionsType); } return null; } public void SetApplicationStatus(string text, string tooltip) { SetOptionalStatus(text, tooltip, Brushes.MediumBlue); } public void SetApplicationProgress(bool visible, double percentage, string title = null) { Dispatcher.BeginInvoke(() => { if (visible && !documentLoadProgressVisible_) { Mouse.OverrideCursor = Cursors.AppStarting; ShowProgressBar(title); } else if (!visible) { Mouse.OverrideCursor = null; HideProgressBar(); return; } if (double.IsNaN(percentage)) { DocumentLoadProgressBar.IsIndeterminate = true; } else { DocumentLoadProgressBar.IsIndeterminate = false; percentage = Math.Max(percentage, DocumentLoadProgressBar.Value); DocumentLoadProgressBar.Value = percentage; } }, DispatcherPriority.Render); } public void UpdateDocumentTitles() { foreach (var docHostPair in sessionState_.DocumentHosts) { docHostPair.Host.Title = GetDocumentTitle(docHostPair.DocumentHost, docHostPair.Section); docHostPair.Host.ToolTip = GetDocumentDescription(docHostPair.DocumentHost, docHostPair.Section); } } public async Task SwitchGraphsAsync(GraphPanel graphPanel, IRTextSection section, IRDocument document, Func computeGraphAction) { if (document.Function == null) { return; // Function failed to load, ignore. } using var loadTask = await graphPanel.OnGenerateGraphStart(section); var functionGraph = await Task.Run(() => computeGraphAction(document.Function, section, loadTask)); if (functionGraph != null) { graphPanel.DisplayGraph(functionGraph); graphPanel.OnGenerateGraphDone(loadTask); } else { //? TODO: Handle CFG failure in the UI graphPanel.OnGenerateGraphDone(loadTask, true); Trace.TraceError($"Document {ObjectTracker.Track(document)}: Failed to load CFG"); } } public Task GetRawSectionTextAsync(IRTextSection section, IRDocument targetDiffDocument = null) { var docInfo = sessionState_.FindLoadedDocument(section); return Task.Run(() => docInfo.Loader.GetSectionText(section)); } public Task GetSectionOutputTextAsync(IRTextSection section, bool useOutputBefore) { var output = useOutputBefore ? section.OutputBefore : section.OutputAfter; var docInfo = sessionState_.FindLoadedDocument(section); return Task.Run(() => docInfo.Loader.GetSectionOutputText(output)); } public IToolPanel FindAndActivatePanel(ToolPanelKind kind) { var panelInfo = FindTargetPanel(null, kind); if (panelInfo != null) { panelInfo.Host.IsActive = true; panelInfo.Host.IsSelected = true; return panelInfo.Panel; } return null; } public void ResetApplicationProgress() { SetApplicationProgress(false, double.NaN); } private async Task OpenDocument(string filePath) { ILoadedDocument loadedDoc = null; bool failed = false; bool isProfilingFile = false; if (Path.HasExtension(filePath)) { if (Utils.FileHasExtension(filePath, ".pex")) { loadedDoc = await OpenSessionDocument(filePath); failed = loadedDoc == null; } else if (Utils.IsBinaryFile(filePath)) { loadedDoc = await OpenBinaryDocument(filePath); failed = loadedDoc == null; } else if (Utils.FileHasExtension(filePath, ".etl")) { var profileSession = RecordingSession.FromFile(filePath); var window = new ProfileLoadWindow(this, false, profileSession); window.Owner = this; isProfilingFile = true; bool? result = window.ShowDialog(); failed = !result.HasValue || !result.Value; if (!failed) { await SetupLoadedProfile(); return sessionState_.MainDocument; } } } if (loadedDoc == null && !failed) { loadedDoc = await OpenIRDocument(filePath, filePath, LoadDocument); } if (loadedDoc == null && !isProfilingFile) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to load file {filePath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } return loadedDoc; } private async Task SwitchBinaryCompilerTarget(string filePath) { // Identify compiler target and switch IR mode. var binaryInfo = PEBinaryInfoProvider.GetBinaryFileInfo(filePath); if (binaryInfo == null) { return; } switch (binaryInfo.Architecture) { case Machine.I386: case Machine.Amd64: { switch (binaryInfo.FileKind) { case BinaryFileKind.Native: { await SwitchCompilerTarget("ASM", IRMode.x86_64); break; } } break; } case Machine.Arm: case Machine.Arm64: { switch (binaryInfo.FileKind) { case BinaryFileKind.Native: { await SwitchCompilerTarget("ASM", IRMode.ARM64); break; } } break; } } } private async Task OpenBinaryDocument(string filePath) { await SwitchBinaryCompilerTarget(filePath); var result = await OpenIRDocument(filePath, filePath, LoadBinaryDocument); if (result != null) { SectionPanel.EnterBinaryDisplayMode(); } return result; } private async void OpenDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { await OpenDocument(); } private void OpenDebugExecuted(object sender, ExecutedRoutedEventArgs e) { Utils.ShowOpenFileDialog(CompilerInfo.OpenDebugFileFilter, "*.pdb", "Open debug info file", path => sessionState_.MainDocument.DebugInfoFile = DebugFileSearchResult.Success(path)); } private void OpenDiffDebugExecuted(object sender, ExecutedRoutedEventArgs e) { Utils.ShowOpenFileDialog(CompilerInfo.OpenDebugFileFilter, "*.pdb", "Open debug info file", path => sessionState_.DiffDocument.DebugInfoFile = DebugFileSearchResult.Success(path)); } private void CanExecuteDiffDocumentCommand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = sessionState_ != null && sessionState_.IsInTwoDocumentsDiffMode; e.Handled = true; } private async Task OpenDocument() { await Utils.ShowOpenFileDialogAsync(CompilerInfo.OpenFileFilter, "*.*", "Open file", async path => { var loadedDoc = await OpenDocument(path); if (loadedDoc != null) { AddRecentFile(path); } }); } private async Task InitializeFromLoadedSession(SessionState state, Dictionary idToDocumentMap) { sessionState_.Info.Notes = state.Info.Notes; int index = 0; foreach (var docState in state.Documents) { var summary = sessionState_.Documents[index].Summary; index++; // Reload state of document annotations. foreach (var sectionState in docState.SectionStates) { var section = summary.GetSectionWithId(sectionState.Item1); sessionState_.SaveDocumentState(sectionState.Item2, section); } } // Reload state of panels from the session state. foreach (var docPanelStates in state.DocumentPanelStates) { var loadedDoc = idToDocumentMap[docPanelStates.Key]; var summary = loadedDoc.Summary; foreach (var panelState in docPanelStates.Value) { var section = summary.GetSectionWithId(panelState.Item1); var panelInfo = FindActivePanel(panelState.Item2.PanelKind); sessionState_.SavePanelState(panelState.Item2.StateObject, panelInfo.Panel, section); } } foreach (var panelState in state.GlobalPanelStates) { var panelInfo = FindActivePanel(panelState.PanelKind); sessionState_.SavePanelState(panelState.StateObject, panelInfo.Panel, null); } await SetupPanels(); // Reload sections left open. var idToDocumentHostMap = new Dictionary(); foreach (var openSection in state.OpenSections) { var loadedDoc = idToDocumentMap[openSection.DocumentId]; var section = loadedDoc.Summary.GetSectionWithId(openSection.SectionId); var openKind = OpenSectionKind.NewTab; if (sessionState_.IsInTwoDocumentsDiffMode) { if (loadedDoc == sessionState_.MainDocument) { openKind = OpenSectionKind.NewTabDockLeft; } else if (loadedDoc == sessionState_.DiffDocument) { openKind = OpenSectionKind.NewTabDockRight; } } var args = new OpenSectionEventArgs(section, openKind); var docHost = await OpenDocumentSectionAsync(args); idToDocumentHostMap[openSection.DocumentId] = docHost; } // Enter diff mode if it was active. if (state.SectionDiffState.IsEnabled && state.OpenSections.Count > 1 && idToDocumentHostMap.TryGetValue(state.SectionDiffState.LeftSection.DocumentId, out var leftDocument) && idToDocumentHostMap.TryGetValue(state.SectionDiffState.RightSection.DocumentId, out var rightDocument)) { await EnterDocumentDiffState(leftDocument, rightDocument); // Compare the two files. if (sessionState_.IsInTwoDocumentsDiffMode) { await ShowSectionPanelDiffs(sessionState_.DiffDocument); } } StartAutoSaveTimer(); return sessionState_.MainDocument; } private bool RequestSessionFilePath(bool forceNewFile = false) { if (!forceNewFile && sessionState_.Info.IsSavedFileSession) { return true; // Save over same session file. } string filePath = Utils.ShowSaveFileDialog("Profile Explorer Session File|*.pex", "*.pex"); if (filePath == null) { return false; } sessionState_.Info.FilePath = filePath; sessionState_.Info.Kind = SessionKind.FileSession; UpdateWindowTitle(); return true; } private void StartSession(string filePath, SessionKind sessionKind) { sessionState_ = new SessionStateManager(filePath, sessionKind, compilerInfo_); sessionState_.DocumentChanged += DocumentState_DocumentChangedEvent; sessionState_.ChangeDocumentWatcherState(App.Settings.AutoReloadDocument); documentLoadTask_ = new CancelableTaskInstance(false, SessionState.RegisterCancelableTask, SessionState.UnregisterCancelableTask); ClearGraphLayoutCache(); // Compiler provider no longer exposes ReloadSettings. DiffModeButton.IsEnabled = true; HideStartPage(); } private async Task EndSession(bool showStartPage = true) { await BeginSessionStateChange(); if (!IsSessionStarted) { EndSessionStateChange(); return; } if (autoSaveTimer_ != null) { autoSaveTimer_.Stop(); autoSaveTimer_ = null; } // Wait for any pending tasks to complete. await sessionState_.CancelPendingTasks(); // Close all documents and notify all panels. NotifyPanelsOfSessionEnd(); foreach (var docHostInfo in sessionState_.DocumentHosts) { CloseDocument(docHostInfo); } await ExitDocumentDiffState(true); sessionState_.DocumentChanged -= DocumentState_DocumentChangedEvent; sessionState_.EndSession(); FunctionAnalysisCache.ResetCache(); DiffModeButton.IsEnabled = false; if (showStartPage) { ShowStartPage(); } EndSessionStateChange(); } private void CloseDocument(DocumentHostInfo docHostInfo) { ResetDocumentEvents(docHostInfo.DocumentHost); docHostInfo.HostParent.Children.Remove(docHostInfo.Host); } private async Task OpenIRDocument(string filePath, string modulePath, Func> loadFunc) { try { await EndSession(); await BeginSessionStateChange(); UpdateUIBeforeLoadDocument(filePath); var result = await Task.Run(async () => await loadFunc(filePath, modulePath, Guid.NewGuid(), UpdateIRDocumentLoadProgress)); if (result != null) { await SetupOpenedIRDocument(SessionKind.Default, result); return result; } } catch (Exception ex) { await EndSession(); Trace.TraceError($"Failed to load document: {ex}"); } finally { UpdateUIAfterLoadDocument(); EndSessionStateChange(); } // Failed to start a session. return null; } private async Task BeginSessionStateChange() { // Wait for any running state changes. await SessionLoadCompleted.WaitAsync(); await updateProfileTask_.CancelTaskAndWaitAsync(); loadingDocuments_ = true; documentLoadStartTime_ = DateTime.UtcNow; lastDocumentLoadTime_ = DateTime.UtcNow; } private void EndSessionStateChange() { SessionLoadCompleted.Release(); } private void UpdateIRDocumentLoadProgress(IRSectionReader reader, SectionReaderProgressInfo info) { if (info.IsIndeterminate) { Dispatcher.BeginInvoke(new Action(() => { SetApplicationProgress(true, double.NaN); }), DispatcherPriority.Render); } else if (info.TotalBytes == 0) { Dispatcher.BeginInvoke(new Action(() => { SetApplicationProgress(false, 0); }), DispatcherPriority.Render); return; } // Updating too often slows down the file parsing by about // 20-30% due to Dispatcher.BeginInvoke overhead. var currentTime = DateTime.UtcNow; var diffTime = currentTime - lastDocumentLoadTime_; if (diffTime.TotalMilliseconds < 100) { return; } // Schedule the UI update. Dispatcher.BeginInvoke(new Action(() => { if (!loadingDocuments_) { // It can happen that this code on the dispatchers runs after // the document has already been loaded, so just ignore the events. return; } bool firstTimeShowPanel = false; if (!documentLoadProgressVisible_) { // Progress panel not displayed yet, show it only after a bit of time // passes since most files are small and load instantly. var timeDiff = DateTime.UtcNow - documentLoadStartTime_; if (timeDiff.TotalMilliseconds < 500) { return; } firstTimeShowPanel = true; } double percentage = Math.Ceiling(100 * (info.BytesProcessed / (double)info.TotalBytes)); // If the progress panel is about to be displayed, but most of the file // as been processed already, there's no point in showing it anymore. if (firstTimeShowPanel) { if (percentage > 50) { return; } } SetApplicationProgress(true, percentage); }), DispatcherPriority.Render); } private async Task SetupOpenedIRDocument(SessionKind sessionKind, ILoadedDocument result) { StartSession(result.FilePath, sessionKind); sessionState_.RegisterLoadedDocument(result); sessionState_.MainDocument = result; UpdateUIAfterLoadDocument(); StartAutoSaveTimer(); await SetupPanels(); } private async Task OpenDiffIRDocument(string filePath) { try { var result = await Task.Run(() => LoadDocument(filePath, filePath, Guid.NewGuid(), UpdateIRDocumentLoadProgress)); if (result != null) { await SetupOpenedDiffIRDocument(filePath, result); return true; } } catch (Exception ex) { Trace.TraceError($"Failed to load diff document {filePath}: {ex}"); } UpdateUIAfterLoadDocument(); return false; } private async Task SetupOpenedDiffIRDocument(string diffFilePath, ILoadedDocument result) { sessionState_.RegisterLoadedDocument(result); sessionState_.EnterTwoDocumentDiffMode(result); await SetupPanels(); //await ShowSectionPanelDiffs(result); } private async Task LoadDocument(string filePath, string modulePath, Guid id, ProgressInfoHandler progressHandler) { return await LoadDocument(filePath, modulePath, id, progressHandler, new DocumentSectionLoader(filePath, compilerInfo_.IR)); } private async Task LoadBinaryDocument(string filePath, string modulePath, Guid id, ProgressInfoHandler progressHandler) { return await LoadBinaryDocument(filePath, modulePath, id, null, progressHandler).ConfigureAwait(false); } private async Task LoadBinaryDocument(string filePath, string modulePath, Guid id, IDebugInfoProvider debugInfo, ProgressInfoHandler progressHandler) { var binaryInfo = PEBinaryInfoProvider.GetBinaryFileInfo(filePath); bool isManagedImage = binaryInfo?.IsManagedImage ?? false; var loader = new DisassemblerSectionLoader(filePath, compilerInfo_, debugInfo, true, isManagedImage); var result = await LoadDocument(filePath, modulePath, id, progressHandler, loader); if (result != null) { result.BinaryFile = BinaryFileSearchResult.Success(filePath); if (debugInfo == null) { result.DebugInfo = loader.DebugInfo; result.DebugInfoFile = loader.DebugInfoFile; } } return result; } private async Task LoadDocument(string filePath, string modulePath, Guid id, ProgressInfoHandler progressHandler, IRTextSectionLoader loader) { try { var result = await Task.Run(async () => { var result = new LoadedDocument(filePath, modulePath, id); result.Loader = loader; result.Summary = await result.Loader.LoadDocument(progressHandler); return result; }); return result; } catch (Exception ex) { Trace.TraceError($"Failed to load document {filePath}: {ex}"); return null; } } private async Task LoadDocument(byte[] data, string filePath, string modulePath, Guid id, ProgressInfoHandler progressHandler) { try { var result = new LoadedDocument(filePath, modulePath, id); result.Loader = new DocumentSectionLoader(data, compilerInfo_.IR); result.Summary = await result.Loader.LoadDocument(progressHandler); return result; } catch (Exception ex) { Trace.TraceError($"Failed to load in-memory document: {ex}"); return null; } } private async Task LoadSessionDocument(SessionState state) { try { if (!string.IsNullOrEmpty(state.Info.IRName)) { await SwitchCompilerTarget(state.Info.IRName, state.Info.IRMode); } StartSession(state.Info.FilePath, SessionKind.FileSession); var idToDocumentMap = new Dictionary(); foreach (var docState in state.Documents) { ILoadedDocument result = null; if (docState.DocumentText != null && docState.DocumentText.Length > 0) { result = await Task.Run(() => LoadDocument(docState.DocumentText, docState.FilePath, docState.ModuleName, docState.Id, UpdateIRDocumentLoadProgress)); } else if (docState.BinaryFile != null) { result = await Task.Run(() => LoadBinaryDocument(docState.BinaryFile.FilePath, docState.ModuleName, docState.Id, UpdateIRDocumentLoadProgress)); } else if (!string.IsNullOrEmpty(docState.ModuleName)) { // Fake document used by profiling to represent missing binaries. result = LoadedDocument.CreateDummyDocument(docState.ModuleName, docState.Id); } if (result == null) { UpdateUIAfterLoadDocument(); return null; } // Profiling can add extra dummy functions to a document, restore them. if (docState.FunctionNames != null) { result.AddDummyFunctions(docState.FunctionNames); } sessionState_.RegisterLoadedDocument(result); idToDocumentMap[docState.Id] = result; if (state.IsInTwoDocumentsDiffMode) { if (docState.Id == state.MainDocumentId) { sessionState_.MainDocument = result; } else if (docState.Id == state.DiffDocumentId) { sessionState_.EnterTwoDocumentDiffMode(result); } } else { // Outside of diff mode there can still be multiple documents // loaded with profile sessions, for ex. if (docState.Id == state.MainDocumentId) { sessionState_.MainDocument = result; } } } UpdateUIAfterLoadDocument(); return await InitializeFromLoadedSession(state, idToDocumentMap); } catch (Exception ex) { Trace.TraceError($"Failed to load in-memory document: {ex}"); } UpdateUIAfterLoadDocument(); return null; } private async void SectionPanel_OpenSection(object sender, OpenSectionEventArgs args) { await OpenDocumentSectionAsync(args, args.TargetDocument); } private async Task OpenDocumentSectionAsync(OpenSectionEventArgs args, IRDocumentHost targetDocument = null, bool runExtraTasks = true) { var document = targetDocument; if (args.OpenKind == OpenSectionKind.NewTab || args.OpenKind == OpenSectionKind.NewTabDockLeft || args.OpenKind == OpenSectionKind.NewTabDockRight) { document = (await AddNewDocument(args.OpenKind)).DocumentHost; } else if (args.OpenKind == OpenSectionKind.ReplaceCurrent || args.OpenKind == OpenSectionKind.ReplaceLeft || args.OpenKind == OpenSectionKind.ReplaceRight) { // Try to pick a host from the same module first. document = FindSameSummaryDocumentHost(args.Section); // Otherwise pick the active host, if any, or create a new one. if (document == null && args.OpenKind == OpenSectionKind.ReplaceCurrent) { document = FindActiveDocumentHost(); } if (document == null) { document = (await AddNewDocument(args.OpenKind)).DocumentHost; } } else { throw new InvalidOperationException("Unhandled OpenSectionKind"); } // In diff mode, reload both left/right sections and redo the diffs. if (IsInDiffMode && sessionState_.SectionDiffState.IsDiffDocument(document)) { await SwitchDiffedDocumentSection(args.Section, document); return document; } await SwitchSection(args.Section, document, runExtraTasks); return document; } private async Task SwitchSection(IRTextSection section, IRDocumentHost document, bool runExtraTasks) { Trace.TraceInformation( $"Document {ObjectTracker.Track(document)}: Switch to section ({section.Number}) {section.Name}"); // Wait for any other pending opening tasks to complete, // otherwise the opened document and panels can get out of sync. using var task = await documentLoadTask_.CancelCurrentAndCreateTaskAsync(); await NotifyOfSectionUnload(document, true); ResetDocumentEvents(document); ResetStatusBar(); var delayedAction = UpdateUIBeforeSectionLoad(section, document); // Load section and try to parse it. var result = await LoadAndParseSection(section); if (task.IsCanceled) { return null; } // Handle loading failures. UpdateUIForSectionLoading(result, document); if (result == null) { // Hide any UI that may show due to long-running tasks. UpdateUIAfterSectionLoad(section, document, delayedAction); return null; } // Update UI to reflect new section before starting long-running tasks. await document.LoadSectionMinimal(result); if (task.IsCanceled) { return null; } await NotifyPanelsOfSectionLoad(section, document, true); if (task.IsCanceled) { return null; } SetupDocumentEvents(document); await UpdateUIAfterSectionSwitch(section, document); if (task.IsCanceled) { return null; } // Load both the document and generate graphs in parallel, // since both can be fairly time-consuming for huge functions. var documentTask = document.LoadSection(result); Task graphTask = null; if (runExtraTasks) { graphTask = GenerateGraphs(section, document.TextView); } await documentTask; UpdateUIAfterSectionLoad(section, document, delayedAction); if (graphTask != null) { await graphTask; } return result; } private void UpdateUIForSectionLoading(ParsedIRTextSection result, IRDocumentHost document) { if (result == null || result.Function == null) { Trace.TraceError($"Document {ObjectTracker.Track(document)}: Failed to parse function"); OptionalStatusText.Text = "Failed to parser section IR"; OptionalStatusText.ToolTip = FormatParsingErrors(result, "Section IR parsing errors"); } else if (result.HadParsingErrors) { Trace.TraceWarning($"Document {ObjectTracker.Track(document)}: Parsed function with errors"); OptionalStatusText.Text = "IR parsing issues"; OptionalStatusText.ToolTip = FormatParsingErrors(result, "Section IR parsing errors"); } else { OptionalStatusText.Text = ""; } } private string FormatParsingErrors(ParsedIRTextSection result, string message) { if (result == null || !result.HadParsingErrors) { return ""; } var builder = new StringBuilder(); builder.AppendLine($"{message}: {result.ParsingErrors.Count}"); foreach (var error in result.ParsingErrors) { builder.AppendLine(error.ToString()); } return builder.ToString(); } private async Task GenerateGraphs(IRTextSection section, IRDocument document, bool awaitTasks = true) { var tasks = new[] { GenerateGraphs(GraphKind.FlowGraph, section, document), GenerateGraphs(GraphKind.DominatorTree, section, document), GenerateGraphs(GraphKind.PostDominatorTree, section, document) }; if (awaitTasks) { await Task.WhenAll(tasks); } } private async Task GenerateGraphs(GraphKind graphKind, IRTextSection section, IRDocument document) { var panelKind = graphKind switch { GraphKind.FlowGraph => ToolPanelKind.FlowGraph, GraphKind.DominatorTree => ToolPanelKind.DominatorTree, GraphKind.PostDominatorTree => ToolPanelKind.PostDominatorTree, _ => throw new InvalidOperationException("Unexpected graph kind!") }; var action = GetComputeGraphAction(graphKind); var flowGraphPanels = FindTargetPanels(document, panelKind); foreach (var panelInfo in flowGraphPanels) { await SwitchGraphsAsync((GraphPanel)panelInfo.Panel, section, document, action); } } private Func GetComputeGraphAction( GraphKind graphKind) { return graphKind switch { GraphKind.FlowGraph => ComputeFlowGraph, GraphKind.DominatorTree => ComputeDominatorTree, GraphKind.PostDominatorTree => ComputePostDominatorTree, _ => throw new InvalidOperationException("Unexpected graph kind!") }; } private Func GetComputeGraphAction( ToolPanelKind graphKind) { return graphKind switch { ToolPanelKind.FlowGraph => ComputeFlowGraph, ToolPanelKind.DominatorTree => ComputeDominatorTree, ToolPanelKind.PostDominatorTree => ComputePostDominatorTree, _ => throw new InvalidOperationException("Unexpected graph kind!") }; } private void GraphViewer_GraphNodeSelected(object sender, IRElementEventArgs e) { var panel = ((GraphViewer)sender).HostPanel; var document = FindTargetDocument(panel); document.TextView.HighlightElement(e.Element, HighlighingType.Selected); } private Graph ComputeFlowGraph(FunctionIR function, IRTextSection section, CancelableTask loadTask) { var graphLayout = GetGraphLayoutCache(GraphKind.FlowGraph); return graphLayout.GenerateGraph(function, section, loadTask, (object)null); } private Graph ComputeDominatorTree(FunctionIR function, IRTextSection section, CancelableTask loadTask) { var graphLayout = GetGraphLayoutCache(GraphKind.DominatorTree); return graphLayout.GenerateGraph(function, section, loadTask, (object)null); } private Graph ComputePostDominatorTree(FunctionIR function, IRTextSection section, CancelableTask loadTask) { var graphLayout = GetGraphLayoutCache(GraphKind.PostDominatorTree); return graphLayout.GenerateGraph(function, section, loadTask, (object)null); } private void GraphViewer_BlockUnmarked(object sender, IRElementMarkedEventArgs e) { var panel = ((GraphViewer)sender).HostPanel; var document = FindTargetDocument(panel); document.TextView.UnmarkBlock(e.Element, HighlighingType.Marked); } private void GraphViewer_BlockMarked(object sender, IRElementMarkedEventArgs e) { var panel = ((GraphViewer)sender).HostPanel; var document = FindTargetDocument(panel); document.TextView.MarkBlock(e.Element, e.Style); } private void GraphViewer_GraphLoaded(object sender, EventArgs e) { var panel = ((GraphViewer)sender).HostPanel; var document = FindTargetDocument(panel); document.TextView.PanelContentLoaded(panel); } private void SetupGraphLayoutCache() { graphLayout_ = new Dictionary(); graphLayout_.Add(GraphKind.FlowGraph, new GraphLayoutCache(GraphKind.FlowGraph)); graphLayout_.Add(GraphKind.DominatorTree, new GraphLayoutCache(GraphKind.DominatorTree)); graphLayout_.Add(GraphKind.PostDominatorTree, new GraphLayoutCache(GraphKind.PostDominatorTree)); graphLayout_.Add(GraphKind.ExpressionGraph, new GraphLayoutCache(GraphKind.ExpressionGraph)); } private void ClearGraphLayoutCache() { foreach (var cache in graphLayout_.Values) { cache.ClearCache(); } } private GraphLayoutCache GetGraphLayoutCache(GraphKind kind) { return graphLayout_[kind]; } private DelayedAction UpdateUIBeforeSectionLoad(IRTextSection section, IRDocumentHost document) { var delayedAction = new DelayedAction(); //delayedAction.Start(TimeSpan.FromMilliseconds(500), () => { document.Opacity = 0.5; }); return delayedAction; } private async Task UpdateUIAfterSectionSwitch(IRTextSection section, IRDocumentHost document, DelayedAction delayedAction = null) { var docHostPair = FindDocumentHostPair(document); //? TODO: Can happen if the loading is slow (debug mode?) //? and doc view is closed by user. if (docHostPair == null) { return; } docHostPair.Host.Title = GetDocumentTitle(document, section); docHostPair.Host.ToolTip = GetDocumentDescription(document, section); RenameAllPanels(); // For bound panels. await SectionPanel.SelectSection(section, false); if (delayedAction != null) { UpdateUIAfterSectionLoad(section, document, delayedAction); } } private void UpdateUIAfterSectionLoad(IRTextSection section, IRDocumentHost document, DelayedAction delayedAction) { delayedAction.Cancel(); //document.Opacity = 1; } private IRDocumentHost FindTargetDocument(IToolPanel panel) { if (panel.BoundDocument != null) { return FindDocumentHost(panel.BoundDocument); } return FindActiveDocumentHost(); } private void SetupDocumentEvents(IRDocumentHost document) { document.TextView.ActionPerformed += TextView_ActionPerformed; document.TextView.ElementSelected += TextView_IRElementSelected; document.TextView.ElementHighlighting += TextView_IRElementHighlighting; document.TextView.BlockSelected += TextView_BlockSelected; document.TextView.BookmarkAdded += TextView_BookmarkAdded; document.TextView.BookmarkRemoved += TextView_BookmarkRemoved; document.TextView.BookmarkChanged += TextView_BookmarkChanged; document.TextView.BookmarkSelected += TextView_BookmarkSelected; document.TextView.BookmarkListCleared += TextView_BookmarkListCleared; document.TextView.CaretChanged += TextView_CaretChanged; document.VerticalScrollChanged += DocumentVerticalScrollChanged; document.PassOutputVerticalScrollChanged += DocumentPassOutputVerticalScrollChanged; document.PassOutputVisibilityChanged += Document_PassOutputVisibilityChanged; document.PassOutputShowBeforeChanged += Document_PassOutputShowBeforeChanged; } private void ResetDocumentEvents(IRDocumentHost document) { document.TextView.ElementSelected -= TextView_IRElementSelected; document.TextView.ElementHighlighting -= TextView_IRElementHighlighting; document.TextView.BlockSelected -= TextView_BlockSelected; document.TextView.BookmarkAdded -= TextView_BookmarkAdded; document.TextView.BookmarkRemoved -= TextView_BookmarkRemoved; document.TextView.BookmarkChanged -= TextView_BookmarkChanged; document.TextView.BookmarkSelected -= TextView_BookmarkSelected; document.TextView.BookmarkListCleared -= TextView_BookmarkListCleared; document.TextView.CaretChanged -= TextView_CaretChanged; document.VerticalScrollChanged -= DocumentVerticalScrollChanged; document.PassOutputVerticalScrollChanged -= DocumentPassOutputVerticalScrollChanged; document.PassOutputVisibilityChanged -= Document_PassOutputVisibilityChanged; document.PassOutputShowBeforeChanged -= Document_PassOutputShowBeforeChanged; } private void DocumentVerticalScrollChanged(object sender, (double offset, double offsetChangeAmount) value) { if (!IsInDiffMode || Math.Abs(value.offsetChangeAmount) < double.Epsilon) { return; } var document = sender as IRDocumentHost; var otherDocument = sessionState_.SectionDiffState.GetOtherDocument(document); if (otherDocument != null) { otherDocument.TextView.ScrollToVerticalOffset(value.offset); } } private async void Document_PassOutputShowBeforeChanged(object sender, bool e) { sessionState_.SectionDiffState.PassOutputShowBefore = e; if (!IsInDiffMode) { return; } var document = sender as IRDocumentHost; var otherDocument = sessionState_.SectionDiffState.GetOtherDocument(document); if (otherDocument != null) { otherDocument.PassOutput.ShowBeforeOutput = e; await DiffDocumentPassOutput(); } } private async void Document_PassOutputVisibilityChanged(object sender, bool e) { sessionState_.SectionDiffState.PassOutputVisible = e; if (!IsInDiffMode) { return; } var document = sender as IRDocumentHost; var otherDocument = sessionState_.SectionDiffState.GetOtherDocument(document); if (otherDocument != null) { otherDocument.PassOutputVisible = e; if (e) { await DiffDocumentPassOutput(); } } } private void DocumentPassOutputVerticalScrollChanged(object sender, (double offset, double offsetChangeAmount) value) { if (!IsInDiffMode || Math.Abs(value.offsetChangeAmount) < double.Epsilon) { return; } var document = sender as IRDocumentHost; var otherDocument = sessionState_.SectionDiffState.GetOtherDocument(document); if (otherDocument != null) { otherDocument.PassOutput.TextView.ScrollToVerticalOffset(value.offset); } } private void TextView_CaretChanged(object sender, int caretOffset) { if (!IsInDiffMode) { return; } // Move the caret in the other document to the same position. var document = sender as IRDocument; var docHost = FindDocumentHost(document); if (!sessionState_.SectionDiffState.IsDiffDocument(docHost)) { return; } var otherDocHost = sessionState_.SectionDiffState.GetOtherDocument(docHost); otherDocHost.TextView.SetCaretAtOffset(caretOffset); } private async void TextView_ActionPerformed(object sender, DocumentAction e) { var document = sender as IRDocument; Debug.Assert(document != null); if (e.ActionKind == DocumentActionKind.ShowExpressionGraph) { var section = document.Section; using var loadTask = await ExpressionGraphPanel.OnGenerateGraphStart(section); var graphLayout = GetGraphLayoutCache(GraphKind.ExpressionGraph); var options = App.Settings.ExpressionGraphSettings.GetGraphPrinterOptions(); options.IR = CompilerInfo.IR; var graph = graphLayout.GenerateGraph(e.Element, section, loadTask, options); if (graph != null) { ExpressionGraphPanel.DisplayGraph(graph); ExpressionGraphPanel.OnGenerateGraphDone(loadTask); var panelHost = FindPanelHost(ExpressionGraphPanel).Host; if (!panelHost.IsActive) { panelHost.IsActive = true; } } else { ExpressionGraphPanel.OnGenerateGraphDone(loadTask, true); Trace.TraceError($"Document {ObjectTracker.Track(document)}: Failed to load CFG"); } return; } MirrorElementAction(e.Element, document, (otherElement, otherDocument) => { otherDocument.ExecuteDocumentAction(e.WithNewElement(otherElement)); }); } private async void TextView_BlockSelected(object sender, IRElementEventArgs e) { var document = sender as IRDocument; if (document != null) { await NotifyPanelsOfElementSelection(e, document); } var block = e.Element.ParentBlock; UpdateBlockStatusBar(block); } private void TextView_BookmarkSelected(object sender, SelectedBookmarkInfo e) { var document = sender as IRDocument; var bookmarksPanel = FindTargetPanel(document, ToolPanelKind.Bookmarks); bookmarksPanel.Bookmarks.Refresh(); BookmarkStatus.Text = $"{e.SelectedIndex + 1} / {e.TotalBookmarks}"; } private void TextView_BookmarkListCleared(object sender, EventArgs e) { var document = sender as IRDocument; var bookmarksPanel = FindTargetPanel(document, ToolPanelKind.Bookmarks); bookmarksPanel.Bookmarks.Clear(); } private void TextView_BookmarkRemoved(object sender, Bookmark e) { var document = sender as IRDocument; var bookmarksPanel = FindTargetPanel(document, ToolPanelKind.Bookmarks); bookmarksPanel.Bookmarks.Remove(e); } private void TextView_BookmarkAdded(object sender, Bookmark e) { var document = sender as IRDocument; var bookmarksPanel = FindTargetPanel(document, ToolPanelKind.Bookmarks); bookmarksPanel.Bookmarks.Add(e); } private void TextView_BookmarkChanged(object sender, Bookmark e) { var document = sender as IRDocument; var bookmarksPanel = FindTargetPanel(document, ToolPanelKind.Bookmarks); bookmarksPanel.Bookmarks.Refresh(); } private async void TextView_IRElementHighlighting(object sender, IRHighlightingEventArgs e) { var document = sender as IRDocument; if (document != null) { await NotifyPanelsOfElementHighlight(e, document); } } private async void TextView_IRElementSelected(object sender, IRElementEventArgs e) { if (sender is IRDocument document) { await NotifyPanelsOfElementSelection(e, document); } } private void MirrorElementAction(IRElement element, IRDocument sourceDocument, Action action) { Trace.TraceInformation( $"Mirror action from {ObjectTracker.Track(sourceDocument)} on element {element}"); foreach (var docInfo in sessionState_.DocumentHosts) { var otherDocument = docInfo.DocumentHost.TextView; // Skip if same section or from another function. if (otherDocument == sourceDocument || otherDocument.Section.ParentFunction != sourceDocument.Section.ParentFunction) { continue; } if (element != null) { var finder = new ReferenceFinder(otherDocument.Function); var otherOp = finder.FindEquivalentValue(element); if (otherOp != null) { action(otherOp, otherDocument); continue; } } action(null, otherDocument); } } private void UpdateUIBeforeReadSession(string documentTitle) { if (!string.IsNullOrEmpty(documentTitle)) { Title = $"Profile Explorer - Reading {documentTitle}"; } UpdatePanelEnabledState(false); Utils.DisableControl(StartPage, 0.85); Mouse.OverrideCursor = Cursors.AppStarting; SetApplicationProgress(true, double.NaN, "Loading session"); } private void UpdateUIBeforeLoadDocument(string documentTitle) { if (!string.IsNullOrEmpty(documentTitle)) { Title = $"Profile Explorer - Loading {documentTitle}"; } StartUIUpdate(); } private void StartUIUpdate() { UpdatePanelEnabledState(false); Utils.DisableControl(StartPage, 0.85); Mouse.OverrideCursor = Cursors.AppStarting; } private void StopUIUpdate() { Mouse.OverrideCursor = null; UpdatePanelEnabledState(true); } private void UpdateUIAfterLoadDocument() { StopUIUpdate(); loadingDocuments_ = false; if (sessionState_ != null) { UpdateWindowTitle(); } else { Title = "Profile Explorer - Failed to load file"; UpdatePanelEnabledState(false); } // Hide temporary UI. HideProgressBar(); } private IRDocumentHost FindDocumentWithSection(IRTextSection section) { var result = sessionState_.DocumentHosts.Find(item => item.DocumentHost.Section == section); return result?.DocumentHost; } private async void DocumentState_DocumentChangedEvent(object sender, EventArgs e) { var loadedDoc = (ILoadedDocument)sender; var eventTime = DateTime.UtcNow; // Queue for later, when the application gets focus back. // A lock is needed, since the event can fire concurrently. lock (lockObject_) { changedDocuments_[loadedDoc.FilePath] = eventTime; } if (appIsActivated_) { // The event doesn't run on the main thread, redirect. await Dispatcher.BeginInvoke(new Action(async () => { await HandleChangedDocuments(); })); } } private bool ShowDocumentReloadQuery(string filePath) { if (SilentMode) { return false; } lastDocumentReloadQueryTime_ = DateTime.UtcNow; using var centerForm = new DialogCenteringHelper(this); return MessageBox.Show( $"File {filePath} changed by an external application?\nDo you want to reload?", "Profile Explorer", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No, MessageBoxOptions.DefaultDesktopOnly) == MessageBoxResult.Yes; } private async Task ReloadDocument(string filePath) { if (sessionState_.IsInTwoDocumentsDiffMode) { await CheckedOpenBaseDiffIRDocuments(sessionState_.MainDocument.FilePath, sessionState_.DiffDocument.FilePath); } else { await CheckedOpenDocument(filePath); } } private void StartAutoSaveTimer() { //? TODO: Disabled since saving of profile sessions is also not supported yet. // try { // string filePath = Utils.GetAutoSaveFilePath(); // // if (File.Exists(filePath)) { // File.Delete(filePath); // } // } // catch (Exception) { // Trace.TraceError("Failed to delete autosave file"); // } // // //? TODO: For huge files, autosaving uses a lot of memory. // if (!sessionState_.Info.IsDebugSession) { // try { // long fileSize = new FileInfo(sessionState_.Info.FilePath).Length; // // if (fileSize > SectionReaderBase.MAX_PRELOADED_FILE_SIZE) { // Trace.TraceWarning( // $"Disabling auto-saving for large file: {sessionState_.Info.FilePath}"); // // sessionState_.IsAutoSaveEnabled = false; // return; // } // } // catch (Exception ex) { // Trace.TraceError($"Failed to get auto-saved file size: {ex}"); // } // } // // sessionState_.IsAutoSaveEnabled = true; // autoSaveTimer_ = new DispatcherTimer {Interval = TimeSpan.FromSeconds(300)}; // autoSaveTimer_.Tick += async delegate { await AutoSaveSession().ConfigureAwait(false); }; // autoSaveTimer_.Start(); } private async Task AutoSaveSession() { //? TODO: Disabled since saving of profile sessions is also not supported yet. // if (sessionState_ == null || !sessionState_.IsAutoSaveEnabled) { // return; // } // // string filePath = Utils.GetAutoSaveFilePath(); // bool saved = await SaveSessionDocument(filePath).ConfigureAwait(false); // Trace.TraceInformation($"Auto-saved session: {saved}"); } private void OpenNewDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { if (!App.StartNewApplicationInstance()) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show("Failed to start new Profile Explorer instance", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } private async Task CheckedOpenDocument(string filePath) { var loadedDoc = await OpenDocument(filePath); if (loadedDoc == null) { MessageBox.Show($"Filed to open binary file {filePath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } private async Task CheckedOpenBaseDiffIRDocuments(string baseFilePath, string diffFilePath) { var (baseLoadedDoc, diffLoadedDoc) = await OpenBaseDiffDocuments(baseFilePath, diffFilePath); if (baseLoadedDoc == null || diffLoadedDoc == null) { MessageBox.Show($"Filed to open base/diff binary files {baseFilePath}\nand {diffFilePath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } private async void CloseDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { await EndSession(showStartPage: true); } private async void SaveDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { if (!RequestSessionFilePath()) { return; } string filePath = sessionState_.Info.FilePath; bool loaded = await SaveSessionDocument(filePath); if (!loaded) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save session file {filePath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } private async void SaveAsDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { if (!RequestSessionFilePath(true)) { return; } string filePath = sessionState_.Info.FilePath; bool loaded = await SaveSessionDocument(filePath); if (!loaded) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save session file {filePath}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } private async void ReloadDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { if (sessionState_ != null && !sessionState_.Info.IsFileSession && !sessionState_.Info.IsDebugSession) { await ReloadDocument(sessionState_.Info.FilePath); } } private void AutoReloadDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { if (sessionState_ != null) { App.Settings.AutoReloadDocument = (e.OriginalSource as MenuItem).IsChecked; sessionState_.ChangeDocumentWatcherState(App.Settings.AutoReloadDocument); } } private void CanExecuteDocumentCommand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = IsSessionStarted; e.Handled = true; } private ILoadedDocument FindLoadedDocument(IRTextFunction func) { return sessionState_.FindLoadedDocument(func); } } ================================================ FILE: src/ProfileExplorerUI/Mcp/McpActionExecutor.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Threading; using ProfileExplorer.Mcp; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.ETW; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.IR; namespace ProfileExplorer.UI.Mcp; /// /// Implementation of IMcpActionExecutor that provides Profile Explorer integration for AI agent interactions. /// This connects MCP tools to the actual Profile Explorer UI functionality. /// public class McpActionExecutor : IMcpActionExecutor { private readonly MainWindow mainWindow; private readonly Dispatcher dispatcher; public McpActionExecutor(MainWindow mainWindow) { this.mainWindow = mainWindow ?? throw new ArgumentNullException(nameof(mainWindow)); this.dispatcher = mainWindow.Dispatcher; } public async Task OpenTraceAsync(string profileFilePath, string processIdentifier) { // Mark that MCP automation is active - suppress UI dialogs App.SuppressDialogsForAutomation = true; // Validate file exists first if (!File.Exists(profileFilePath)) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.FileNotFound, ErrorMessage = $"Trace file not found: {profileFilePath}" }; } // Check if the requested trace and process is already loaded var alreadyLoadedResult = await CheckIfTraceAlreadyLoadedAsync(profileFilePath, processIdentifier); if (alreadyLoadedResult != null) { return alreadyLoadedResult; } // Try to parse as a process ID first if (int.TryParse(processIdentifier, out int processId)) { if (processId <= 0) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.UnknownError, ErrorMessage = "Process ID must be a positive integer." }; } return await OpenTraceByProcessIdAsync(profileFilePath, processId); } // If not a number, treat as process name return await OpenTraceByProcessNameAsync(profileFilePath, processIdentifier); } /// /// Checks if the requested trace file and process is already loaded. /// Returns a successful OpenTraceResult if already loaded, or null if not loaded. /// This helps avoid timeout errors when a trace was already loaded but MCP timed out waiting. /// private async Task CheckIfTraceAlreadyLoadedAsync(string profileFilePath, string processIdentifier) { return await dispatcher.InvokeAsync(() => { try { var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; var report = profileData?.Report; if (report == null) { return null; // No profile loaded } // Get the currently loaded trace path string loadedTracePath = report.TraceInfo?.TraceFilePath; if (string.IsNullOrEmpty(loadedTracePath)) { return null; } // Normalize paths for comparison string normalizedRequestedPath = Path.GetFullPath(profileFilePath).ToLowerInvariant(); string normalizedLoadedPath = Path.GetFullPath(loadedTracePath).ToLowerInvariant(); if (normalizedRequestedPath != normalizedLoadedPath) { return null; // Different trace file } // Check if the requested process matches var currentProcess = report.Process; if (currentProcess == null) { return null; } bool processMatches = false; // Check by process ID if (int.TryParse(processIdentifier, out int requestedPid)) { processMatches = currentProcess.ProcessId == requestedPid; } else { // Check by process name (case-insensitive, partial match) processMatches = (currentProcess.Name != null && currentProcess.Name.Contains(processIdentifier, StringComparison.OrdinalIgnoreCase)) || (currentProcess.ImageFileName != null && currentProcess.ImageFileName.Contains(processIdentifier, StringComparison.OrdinalIgnoreCase)); } if (processMatches) { // The requested trace and process is already loaded! return new OpenTraceResult { Success = true, AlreadyLoaded = true, Message = $"Trace and process already loaded (PID: {currentProcess.ProcessId}, Name: {currentProcess.Name})" }; } return null; // Same trace but different process requested } catch (Exception) { return null; // On any error, proceed with normal loading } }); } private async Task OpenTraceByProcessIdAsync(string profileFilePath, int processId) { try { var loadResult = await LoadTraceAsync(profileFilePath); if (!loadResult.Success) { return loadResult.Result; } // Select the process by PID return await SelectProcessByPidAsync(loadResult.ProfileLoadWindow, processId); } catch (Exception ex) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.UnknownError, ErrorMessage = $"Unexpected error: {ex.Message}" }; } } private async Task OpenTraceByProcessNameAsync(string profileFilePath, string processName) { try { // Load the trace and prepare the process list var loadResult = await LoadTraceAsync(profileFilePath); if (!loadResult.Success) { return loadResult.Result; } // Select the process by name return await SelectProcessByNameAsync(loadResult.ProfileLoadWindow, processName); } catch (Exception ex) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.UnknownError, ErrorMessage = $"Unexpected error: {ex.Message}" }; } } private async Task<(bool Success, ProfileExplorer.UI.ProfileLoadWindow ProfileLoadWindow, OpenTraceResult Result)> LoadTraceAsync(string profileFilePath) { // Execute the command in the background since ShowDialog() blocks var task = Task.Run(() => { dispatcher.Invoke(() => AppCommand.LoadProfile.Execute(null, mainWindow)); }); // Wait for the dialog to be created and shown (with timeout) var profileLoadWindow = await WaitForWindowAsync(TimeSpan.FromSeconds(5)); if (profileLoadWindow == null) { var errorResult = new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.UIError, ErrorMessage = "Failed to open profile load dialog window" }; return (false, null, errorResult); } // Step 1: Set the profile file path await dispatcher.InvokeAsync(() => { profileLoadWindow.ProfileFilePath = profileFilePath; }); // Step 2: Trigger the text changed logic to load the process list await dispatcher.InvokeAsync(() => { var textChangedMethod = profileLoadWindow.GetType().GetMethod("ProfileAutocompleteBox_TextChanged", BindingFlags.NonPublic | BindingFlags.Instance); if (textChangedMethod != null) { textChangedMethod.Invoke(profileLoadWindow, new object[] { profileLoadWindow, new RoutedEventArgs() }); } }); // Step 3: Wait for process list to finish loading (with timeout) bool processListLoaded = await WaitForProcessListLoadedAsync(profileLoadWindow, TimeSpan.FromMinutes(2)); if (!processListLoaded) { var errorResult = new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.ProcessListLoadTimeout, ErrorMessage = "Timeout while loading process list from trace file" }; return (false, profileLoadWindow, errorResult); } // Step 4: Additional verification that ItemsSource is actually populated var verificationResult = await WaitForItemsSourceAsync(profileLoadWindow, TimeSpan.FromSeconds(10)); if (!verificationResult) { var errorResult = new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.ProcessListLoadTimeout, ErrorMessage = "Process list failed to load properly" }; return (false, profileLoadWindow, errorResult); } return (true, profileLoadWindow, null); } private async Task SelectProcessByPidAsync(ProfileExplorer.UI.ProfileLoadWindow profileLoadWindow, int processId) { // Step 5: Select the specified process from the process list // Use retry logic in case there are still brief timing issues bool processSelected = false; for (int retryCount = 0; retryCount < 3 && !processSelected; retryCount++) { if (retryCount > 0) { await Task.Delay(500); // Brief delay between retries } processSelected = await dispatcher.InvokeAsync(() => { var processListControl = profileLoadWindow.FindName("ProcessList") as System.Windows.Controls.ListView; if (processListControl?.ItemsSource != null) { try { var processSummaries = processListControl.ItemsSource.Cast().ToList(); var targetProcess = processSummaries.FirstOrDefault(p => p.Process.ProcessId == processId); if (targetProcess != null) { processListControl.SelectedItems.Clear(); processListControl.SelectedItems.Add(targetProcess); // Trigger the selection changed event var selectionChangedMethod = profileLoadWindow.GetType().GetMethod("ProcessList_OnSelectionChanged", BindingFlags.NonPublic | BindingFlags.Instance); if (selectionChangedMethod != null) { var args = new System.Windows.Controls.SelectionChangedEventArgs( System.Windows.Controls.Primitives.Selector.SelectionChangedEvent, new object[0], new object[] { targetProcess }); selectionChangedMethod.Invoke(profileLoadWindow, new object[] { processListControl, args }); } return true; } } catch (Exception) { // If casting or process selection fails, return false return false; } } return false; }); } if (!processSelected) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.ProcessNotFound, ErrorMessage = $"Process with ID {processId} not found in trace file", }; } // Step 6: Execute the profile load (click Load button) await dispatcher.InvokeAsync(() => { var loadButtonClickMethod = profileLoadWindow.GetType().GetMethod("LoadButton_Click", BindingFlags.NonPublic | BindingFlags.Instance); if (loadButtonClickMethod != null) { loadButtonClickMethod.Invoke(profileLoadWindow, new object[] { profileLoadWindow, new RoutedEventArgs() }); } }); // Step 7: Wait for the profile to finish loading bool profileLoadCompleted = await WaitForProfileLoadingCompletedAsync(profileLoadWindow, TimeSpan.FromMinutes(30)); if (!profileLoadCompleted) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.ProfileLoadTimeout, ErrorMessage = "Timeout while waiting for profile loading to complete. The profile may be very large or there may be symbol loading issues." }; } return new OpenTraceResult { Success = true }; } private async Task SelectProcessByNameAsync(ProfileExplorer.UI.ProfileLoadWindow profileLoadWindow, string processName) { // Step 5: Select the specified process by name from the process list bool processSelected = false; for (int retryCount = 0; retryCount < 3 && !processSelected; retryCount++) { if (retryCount > 0) { await Task.Delay(500); // Brief delay between retries } processSelected = await dispatcher.InvokeAsync(() => { var processListControl = profileLoadWindow.FindName("ProcessList") as System.Windows.Controls.ListView; if (processListControl?.ItemsSource != null) { try { var processSummaries = processListControl.ItemsSource.Cast().ToList(); // Look for process by name (case-insensitive, supports partial matching) var targetProcess = processSummaries.FirstOrDefault(p => p.Process.Name != null && p.Process.Name.Contains(processName, StringComparison.OrdinalIgnoreCase)); // If no partial match, try exact match if (targetProcess == null) { targetProcess = processSummaries.FirstOrDefault(p => string.Equals(p.Process.Name, processName, StringComparison.OrdinalIgnoreCase)); } // If still no match, try matching against image file name if (targetProcess == null) { targetProcess = processSummaries.FirstOrDefault(p => p.Process.ImageFileName != null && p.Process.ImageFileName.Contains(processName, StringComparison.OrdinalIgnoreCase)); } if (targetProcess != null) { processListControl.SelectedItems.Clear(); processListControl.SelectedItems.Add(targetProcess); // Trigger the selection changed event var selectionChangedMethod = profileLoadWindow.GetType().GetMethod("ProcessList_OnSelectionChanged", BindingFlags.NonPublic | BindingFlags.Instance); if (selectionChangedMethod != null) { var args = new System.Windows.Controls.SelectionChangedEventArgs( System.Windows.Controls.Primitives.Selector.SelectionChangedEvent, new object[0], new object[] { targetProcess }); selectionChangedMethod.Invoke(profileLoadWindow, new object[] { processListControl, args }); } return true; } } catch (Exception) { // If casting or process selection fails, return false return false; } } return false; }); } if (!processSelected) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.ProcessNotFound, ErrorMessage = $"Process '{processName}' not found in trace file", }; } // Step 6: Execute the profile load (click Load button) await dispatcher.InvokeAsync(() => { var loadButtonClickMethod = profileLoadWindow.GetType().GetMethod("LoadButton_Click", BindingFlags.NonPublic | BindingFlags.Instance); if (loadButtonClickMethod != null) { loadButtonClickMethod.Invoke(profileLoadWindow, new object[] { profileLoadWindow, new RoutedEventArgs() }); } }); // Step 7: Wait for the profile to finish loading bool profileLoadCompleted = await WaitForProfileLoadingCompletedAsync(profileLoadWindow, TimeSpan.FromMinutes(30)); if (!profileLoadCompleted) { return new OpenTraceResult { Success = false, FailureReason = OpenTraceFailureReason.ProfileLoadTimeout, ErrorMessage = "Timeout while waiting for profile loading to complete. The profile may be very large or there may be symbol loading issues." }; } return new OpenTraceResult { Success = true }; } /// /// Waits for a window of type T to appear, with a timeout. /// private async Task WaitForWindowAsync(TimeSpan timeout) where T : Window { var startTime = DateTime.UtcNow; while (DateTime.UtcNow - startTime < timeout) { var window = await dispatcher.InvokeAsync(() => mainWindow.OwnedWindows.OfType().FirstOrDefault()); if (window != null) { return window; } await Task.Delay(100); // Check every 100ms } return null; } /// /// Waits for the process list to finish loading in the ProfileLoadWindow. /// Monitors the IsLoadingProcessList and ShowProcessList properties. /// Also ensures at least 2 processes are loaded to avoid partial loading issues. /// private async Task WaitForProcessListLoadedAsync(ProfileExplorer.UI.ProfileLoadWindow window, TimeSpan timeout) { var startTime = DateTime.UtcNow; const int MinimumProcessCount = 2; // Wait for at least 2 processes to ensure full loading while (DateTime.UtcNow - startTime < timeout) { var (isLoading, showList, hasItemsSource, processCount) = await dispatcher.InvokeAsync(() => { var isLoadingProp = window.GetType().GetProperty("IsLoadingProcessList"); var showListProp = window.GetType().GetProperty("ShowProcessList"); var processListControl = window.FindName("ProcessList") as System.Windows.Controls.ListView; bool isLoading = isLoadingProp?.GetValue(window) as bool? ?? false; bool showList = showListProp?.GetValue(window) as bool? ?? false; bool hasItemsSource = processListControl?.ItemsSource != null; int processCount = 0; if (hasItemsSource) { try { processCount = processListControl.ItemsSource.Cast().Count(); } catch { processCount = 0; hasItemsSource = false; // If we can't cast, treat as not having items source } } return (isLoading, showList, hasItemsSource, processCount); }); // Process list is ready when: // 1. It's not currently loading (IsLoadingProcessList = false) // 2. The process list is shown (ShowProcessList = true) // 3. The ProcessList control has a valid ItemsSource // 4. The ProcessList control has at least the minimum number of processes OR we've waited long enough if (!isLoading && showList && hasItemsSource && (processCount >= MinimumProcessCount || (processCount > 0 && DateTime.UtcNow - startTime > TimeSpan.FromSeconds(10)))) { return true; } // Additional check: If we're not loading but still don't have ItemsSource, // even though ShowProcessList is true, continue waiting as this indicates // the UI update cycle hasn't completed yet if (!isLoading && showList && !hasItemsSource) { // This is likely a timing issue - UI state says ready but ItemsSource not set yet // Continue waiting unless we've been in this state for too long if (DateTime.UtcNow - startTime > TimeSpan.FromSeconds(10)) { return false; // Likely an error occurred - UI says ready but no data } } // If we're not loading and not showing the list, it might indicate an error if (!isLoading && !showList) { // Give it a bit more time in case the state transitions haven't completed if (DateTime.UtcNow - startTime > TimeSpan.FromSeconds(5)) { return false; // Likely an error occurred } } await Task.Delay(200); // Check every 200ms } return false; // Timeout } /// /// Additional verification that ItemsSource is populated. /// This handles edge cases where the main waiting logic completes but ItemsSource is still briefly null. /// private async Task WaitForItemsSourceAsync(ProfileExplorer.UI.ProfileLoadWindow window, TimeSpan timeout) { var startTime = DateTime.UtcNow; while (DateTime.UtcNow - startTime < timeout) { var (hasItemsSource, processCount, isAccessible) = await dispatcher.InvokeAsync(() => { var processListControl = window.FindName("ProcessList") as System.Windows.Controls.ListView; bool hasItemsSource = processListControl?.ItemsSource != null; int processCount = 0; bool isAccessible = false; if (hasItemsSource) { try { // Try to access the items to ensure they're actually available var items = processListControl.ItemsSource.Cast().ToList(); processCount = items.Count; isAccessible = true; } catch { hasItemsSource = false; processCount = 0; isAccessible = false; } } return (hasItemsSource, processCount, isAccessible); }); if (hasItemsSource && processCount > 0 && isAccessible) { return true; } await Task.Delay(50); // Check every 50ms for more responsive verification } return false; // Timeout - ItemsSource never became available } /// /// Waits for the profile loading to complete by monitoring the IsLoadingProfile property. /// This ensures the profile is fully loaded before operations like GetAvailableFunctions can succeed. /// private async Task WaitForProfileLoadingCompletedAsync(ProfileExplorer.UI.ProfileLoadWindow window, TimeSpan timeout) { var startTime = DateTime.UtcNow; // Phase 1: Wait for the profile load dialog to finish while (DateTime.UtcNow - startTime < timeout) { bool isLoadingProfile = await dispatcher.InvokeAsync(() => { var isLoadingProp = window.GetType().GetProperty("IsLoadingProfile"); return isLoadingProp?.GetValue(window) as bool? ?? false; }); // Profile dialog loading is complete when IsLoadingProfile is false if (!isLoadingProfile) { break; } await Task.Delay(500); // Check every 500ms since profile loading can take a long time } // Phase 2: Wait for the main window to have fully loaded profile data with functions // This ensures symbol loading is complete and GetAvailableFunctions will work var remainingTimeout = timeout - (DateTime.UtcNow - startTime); if (remainingTimeout <= TimeSpan.Zero) { return false; // Timeout during dialog loading phase } return await WaitForMainWindowProfileReadyAsync(remainingTimeout); } /// /// Waits for the main window to have a fully loaded profile with functions available. /// This handles the case where symbol loading continues after the profile dialog closes. /// private async Task WaitForMainWindowProfileReadyAsync(TimeSpan timeout) { var startTime = DateTime.UtcNow; while (DateTime.UtcNow - startTime < timeout) { var (isReady, functionCount) = await dispatcher.InvokeAsync(() => { try { var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; var report = profileData?.Report; // Check if we have basic profile data if (report == null || profileData == null) { return (false, 0); } // Check if function list is populated (indicates symbol loading is complete) var sectionPanel = mainWindow.FindName("SectionPanel") as ProfileExplorer.UI.SectionPanelPair ?? mainWindow.FindPanel(ProfileExplorer.UI.ToolPanelKind.Section) as ProfileExplorer.UI.SectionPanelPair; if (sectionPanel?.MainPanel == null) { return (false, 0); } var functionListControl = sectionPanel.MainPanel.FindName("FunctionList") as System.Windows.Controls.ListView; if (functionListControl?.ItemsSource == null) { return (false, 0); } // Count functions to ensure the list is populated int count = 0; foreach (var _ in functionListControl.ItemsSource) { count++; if (count >= 5) break; // We just need to confirm there are functions } return (count > 0, count); } catch { return (false, 0); } }); if (isReady && functionCount > 0) { return true; } await Task.Delay(500); // Check every 500ms } return false; // Timeout } /// /// Helper method to get the section panel and function list control /// private async Task<(ProfileExplorer.UI.SectionPanelPair SectionPanel, System.Windows.Controls.ListView FunctionList)> GetFunctionListControlAsync() { var sectionPanel = await dispatcher.InvokeAsync(() => { return mainWindow.FindName("SectionPanel") as ProfileExplorer.UI.SectionPanelPair ?? mainWindow.FindPanel(ProfileExplorer.UI.ToolPanelKind.Section) as ProfileExplorer.UI.SectionPanelPair; }); if (sectionPanel?.MainPanel == null) { return (null, null); } var functionListControl = await dispatcher.InvokeAsync(() => sectionPanel.MainPanel.FindName("FunctionList") as System.Windows.Controls.ListView); return (sectionPanel, functionListControl); } public async Task GetStatusAsync() { return await dispatcher.InvokeAsync(() => { try { var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; var report = profileData?.Report; // This is the ProfileDataReport with all the info // Check if we have profile data loaded bool isProfileLoaded = profileData != null && report != null; string currentProfilePath = null; int[] loadedProcesses = Array.Empty(); string[] activeFilters = Array.Empty(); ProcessInfo? currentProcess = null; if (isProfileLoaded && report != null) { // Get trace file path and duration from ProfileDataReport.TraceInfo currentProfilePath = report.TraceInfo?.TraceFilePath; // Get process information from ProfileDataReport.Process (main process) if (report.Process != null) { currentProcess = new ProcessInfo { ProcessId = report.Process.ProcessId, Name = report.Process.Name ?? string.Empty, ImageFileName = report.Process.ImageFileName ?? string.Empty, CommandLine = report.Process.CommandLine ?? string.Empty }; } // Get all running processes from ProfileDataReport.RunningProcesses if (report.RunningProcesses?.Count > 0) { loadedProcesses = report.RunningProcesses .Select(p => p.Process.ProcessId) // ProcessSummary.Process.ProcessId .ToArray(); } // Get active filter information from session state var filterList = new List(); var profileFilter = sessionState?.ProfileFilter; if (profileFilter != null) { if (profileFilter.HasFilter) { filterList.Add("Has active filter"); } if (profileFilter.HasThreadFilter) { filterList.Add($"Thread filter: {profileFilter.ThreadFilterText}"); } if (profileFilter.FilteredTime != TimeSpan.Zero) { filterList.Add($"Filtered time: {profileFilter.FilteredTime}"); } } activeFilters = filterList.ToArray(); } return new ProfilerStatus { IsProfileLoaded = isProfileLoaded, CurrentProfilePath = currentProfilePath, LoadedProcesses = loadedProcesses, ActiveFilters = activeFilters, CurrentProcess = currentProcess, LastUpdated = DateTime.UtcNow }; } catch (Exception) { // Return safe defaults if anything goes wrong return new ProfilerStatus { IsProfileLoaded = false, CurrentProfilePath = null, LoadedProcesses = Array.Empty(), ActiveFilters = Array.Empty(), CurrentProcess = null, LastUpdated = DateTime.UtcNow }; } }); } private async Task GetFunctionAssemblyAsync(string functionName) { try { // Step 1: Get the section panel for UI operations var (sectionPanel, functionListControl) = await GetFunctionListControlAsync(); if (sectionPanel == null || functionListControl == null) { return null; } // Step 2: Parse function name - handle "module!function" format string targetModule = null; string targetFuncName = functionName; if (functionName.Contains("!")) { var parts = functionName.Split('!', 2); targetModule = parts[0]; targetFuncName = parts[1]; ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Parsed function name: module={targetModule}, function={targetFuncName}"); } // Step 3: Search through ALL functions in the profile (not just visible list) var foundFunction = await dispatcher.InvokeAsync(() => { var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; if (profileData?.FunctionProfiles == null) { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogWarning("[MCP] No FunctionProfiles available"); return null; } ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Searching through {profileData.FunctionProfiles.Count} functions for '{functionName}'"); // First, try to find in the visible list (for UI operations later) ProfileExplorer.UI.IRTextFunctionEx visibleFuncEx = null; if (functionListControl?.ItemsSource != null) { foreach (var item in functionListControl.ItemsSource) { if (item is ProfileExplorer.UI.IRTextFunctionEx funcEx) { // Match by exact name or by module!function format bool matches = funcEx.ToolTip == functionName || funcEx.ToolTip == targetFuncName || funcEx.Name == targetFuncName; // Also check if module matches when specified if (matches && targetModule != null) { matches = string.Equals(funcEx.ModuleName, targetModule, StringComparison.OrdinalIgnoreCase); } if (matches) { visibleFuncEx = funcEx; ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Found function in visible list: {funcEx.Name} (module: {funcEx.ModuleName})"); break; } } } } // If found in visible list, use that if (visibleFuncEx != null) { return visibleFuncEx; } // Otherwise, search through ALL functions in the profile foreach (var kvp in profileData.FunctionProfiles) { var func = kvp.Key; string funcName = func.Name; string moduleName = func.ModuleName; // Match by function name bool matches = funcName == targetFuncName || funcName.Contains(targetFuncName) || (targetFuncName.Contains("::") && funcName.Contains(targetFuncName.Split("::").Last())); // Also check module when specified if (matches && targetModule != null) { matches = string.Equals(moduleName, targetModule, StringComparison.OrdinalIgnoreCase); } if (matches) { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Found function in profile: {funcName} (module: {moduleName})"); // Create a temporary IRTextFunctionEx wrapper for the found function // We need to get the actual extension from the SectionPanel if possible var funcExtension = sectionPanel.MainPanel.GetFunctionExtension(func); if (funcExtension != null) { return funcExtension; } // If not in extension map, we can still work with the raw function // Return null here and handle below return null; } } ProfileExplorer.Core.Utilities.DiagnosticLogger.LogWarning($"[MCP] Function not found in profile: {functionName}"); return null; }); if (foundFunction == null) { return null; // Function not found } // Step 3.5: LAZY BINARY LOADING - If binary isn't loaded yet, trigger lazy load // This is needed for MCP automation where binaries are loaded on-demand. var lazyLoadResult = await EnsureBinaryLoadedForFunctionAsync(foundFunction.Function); if (lazyLoadResult.HasValue && !lazyLoadResult.Value) { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogWarning($"[MCP] Failed to lazy load binary for function {functionName}"); // Continue anyway - the function may still have assembly data from other sources } else if (lazyLoadResult.HasValue && lazyLoadResult.Value) { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Successfully lazy loaded binary for function {functionName}"); } // Step 4: Verify function has assembly data and trigger double-click var functionFound = await dispatcher.InvokeAsync(() => { try { // Check if the function has assembly data if (!HasAssemblyData(foundFunction)) { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogWarning($"[MCP] Function has no assembly data after lazy load: {functionName}"); return false; // Function found but has no assembly data } // Select the function functionListControl.SelectedItems.Clear(); functionListControl.SelectedItems.Add(foundFunction); functionListControl.ScrollIntoView(foundFunction); // Programmatically trigger the double-click event var method = sectionPanel.MainPanel.GetType().GetMethod("FunctionDoubleClick", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (method != null) { // Create a ListViewItem to simulate the sender var listViewItem = functionListControl.ItemContainerGenerator.ContainerFromItem(foundFunction) as System.Windows.Controls.ListViewItem; if (listViewItem != null) { listViewItem.Content = foundFunction; var mouseEventArgs = new System.Windows.Input.MouseButtonEventArgs( System.Windows.Input.Mouse.PrimaryDevice, Environment.TickCount, System.Windows.Input.MouseButton.Left) { RoutedEvent = System.Windows.Controls.Control.MouseDoubleClickEvent }; method.Invoke(sectionPanel.MainPanel, new object[] { listViewItem, mouseEventArgs }); return true; } } return false; } catch (Exception) { return false; } }); if (!functionFound) { return null; // Function not found in the list } // Add a delay to let the UI process the double-click and open the document await Task.Delay(500); // Increased delay to allow more time for document and timing data loading // Step 4: Wait for the assembly document to be opened var assemblyDocument = await WaitForAssemblyDocumentAsync(TimeSpan.FromSeconds(10)); if (assemblyDocument == null) { return null; // Timeout waiting for assembly document } // Step 4.5: Wait for timing information to be available var timingDataAvailable = await WaitForTimingDataAsync(assemblyDocument, TimeSpan.FromSeconds(15)); // Step 5: Retrieve the assembly content and timing information from the document var assemblyContentWithTiming = await dispatcher.InvokeAsync(() => { var assemblyText = assemblyDocument.TextView.Text; var columnData = assemblyDocument.TextView.ProfileColumnData; ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Extracting timing data - columnData null: {columnData == null}, HasData: {columnData?.HasData ?? false}"); if (columnData == null || !columnData.HasData) { // No timing information available, return just the assembly text ProfileExplorer.Core.Utilities.DiagnosticLogger.LogWarning($"[MCP] No timing data available for assembly"); return assemblyText; } // Extract timing information and combine with assembly text var lines = assemblyText.Split('\n'); var result = new System.Text.StringBuilder(); var function = assemblyDocument.TextView.Function; ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Assembly has {lines.Length} lines, function null: {function == null}"); int elementsFound = 0; int elementsWithTiming = 0; for (int i = 0; i < lines.Length; i++) { var line = lines[i]; // Try to get timing information for this line by finding the IR element // Line numbers in TextLocation are 0-based, but we're iterating 0-based as well IRElement elementAtLine = null; string timePercentage = null; string timeValue = null; if (function != null) { // Find elements that correspond to this line foreach (var block in function.Blocks) { foreach (var tuple in block.Tuples) { if (tuple.TextLocation.Line == i) // Both are 0-based { elementAtLine = tuple; break; } } if (elementAtLine != null) break; } } if (elementAtLine != null) { elementsFound++; var rowValue = columnData.GetValues(elementAtLine); if (rowValue != null) { // Extract Time(%) and Time(ms) information foreach (var columnValue in rowValue.ColumnValues) { var column = columnValue.Key; var value = columnValue.Value; // Check for time percentage column if (column.Title.Contains("Time (%)") || column.ColumnName.Contains("TimePercentage")) { timePercentage = value.Text; } // Check for time value column else if (column.Title.Contains("Time (") || column.ColumnName.Contains("Time")) { timeValue = value.Text; } } if (!string.IsNullOrEmpty(timePercentage) || !string.IsNullOrEmpty(timeValue)) { elementsWithTiming++; } } } // Build the complete line with timing information on the same line result.Append(line); // Append timing information if available, aligned to the right on the same line if (!string.IsNullOrEmpty(timePercentage) || !string.IsNullOrEmpty(timeValue)) { // Calculate padding to align timing info to the right (assuming 100-character width) const int TargetWidth = 100; int currentLength = line.Length; int timingInfoLength = 15; // Approximate length of timing info if (!string.IsNullOrEmpty(timePercentage)) timingInfoLength += timePercentage.Length + 12; // "Time(%): " + value if (!string.IsNullOrEmpty(timeValue)) timingInfoLength += timeValue.Length + 8; // "Time: " + value if (!string.IsNullOrEmpty(timePercentage) && !string.IsNullOrEmpty(timeValue)) timingInfoLength += 2; // ", " int paddingNeeded = Math.Max(2, TargetWidth - currentLength - timingInfoLength); result.Append(new string(' ', paddingNeeded)); result.Append("["); if (!string.IsNullOrEmpty(timePercentage)) { result.Append($"Time(%): {timePercentage}"); } if (!string.IsNullOrEmpty(timeValue)) { if (!string.IsNullOrEmpty(timePercentage)) result.Append(", "); result.Append($"Time: {timeValue}"); } result.Append("]"); } // Add line break only at the end, after timing info is added if (i < lines.Length - 1) result.AppendLine(); } ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Timing extraction complete: {elementsFound} elements found, {elementsWithTiming} with timing data"); return result.ToString(); }); return assemblyContentWithTiming; } catch (Exception) { return null; } } /// /// Waits for a new assembly document to be opened after the function double-click. /// Simplified approach: just wait for any document with assembly content to appear. /// private async Task WaitForAssemblyDocumentAsync(TimeSpan timeout) { var startTime = DateTime.UtcNow; // Simple approach: continuously check all open documents for assembly content while (DateTime.UtcNow - startTime < timeout) { var assemblyDocument = await dispatcher.InvokeAsync(() => { try { if (mainWindow is ProfileExplorer.UI.IUISession session) { var openDocs = session.OpenDocuments; // Check each document for assembly content foreach (var document in openDocs) { if (document?.Text != null && !string.IsNullOrEmpty(document.Text)) { var text = document.Text; // Enhanced assembly detection with more patterns bool hasAssemblyInstructions = text.Contains("mov ") || text.Contains("call ") || text.Contains("ret") || text.Contains("push ") || text.Contains("pop ") || text.Contains("jmp ") || text.Contains("add ") || text.Contains("sub ") || text.Contains("lea ") || text.Contains("cmp ") || text.Contains("test ") || text.Contains("xor ") || text.Contains("and ") || text.Contains("or "); // Also check for register patterns and memory addresses bool hasAssemblyPatterns = text.Contains("rax") || text.Contains("rbx") || text.Contains("rcx") || text.Contains("rdx") || text.Contains("rsp") || text.Contains("rbp") || text.Contains("eax") || text.Contains("ebx") || (text.Contains("[") && text.Contains("]")); // Memory addressing if (hasAssemblyInstructions || hasAssemblyPatterns) { // Found a document with assembly content, find its IRDocumentHost var sessionStateField = mainWindow.GetType().GetField("sessionState_", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); if (sessionStateField?.GetValue(mainWindow) is object sessionState) { var documentHostsProperty = sessionState.GetType().GetProperty("DocumentHosts"); if (documentHostsProperty?.GetValue(sessionState) is System.Collections.IList documentHosts) { foreach (var hostInfo in documentHosts) { var documentHostProperty = hostInfo.GetType().GetProperty("DocumentHost"); var docHost = documentHostProperty?.GetValue(hostInfo) as ProfileExplorer.UI.IRDocumentHost; if (docHost?.TextView == document) { return docHost; } } } } } } } } } catch { // If there's any exception, continue searching } return null; }); if (assemblyDocument != null) { return assemblyDocument; } await Task.Delay(200); // Check every 200ms } return null; // Timeout } /// /// Waits for timing data to be available in the assembly document. /// The ProfileColumnData might not be immediately available after the document opens. /// private async Task WaitForTimingDataAsync(ProfileExplorer.UI.IRDocumentHost documentHost, TimeSpan timeout) { var startTime = DateTime.UtcNow; while (DateTime.UtcNow - startTime < timeout) { var hasTimingData = await dispatcher.InvokeAsync(() => { try { var columnData = documentHost.TextView?.ProfileColumnData; if (columnData != null && columnData.HasData) { // Additionally check if we can actually get timing values from at least one element var function = documentHost.TextView.Function; if (function != null) { // Try to find at least one element with timing data foreach (var block in function.Blocks) { foreach (var tuple in block.Tuples) { var rowValue = columnData.GetValues(tuple); if (rowValue?.ColumnValues != null && rowValue.ColumnValues.Any()) { // Check if any column contains timing information foreach (var columnValue in rowValue.ColumnValues) { var column = columnValue.Key; if (column.Title.Contains("Time") || column.ColumnName.Contains("Time")) { return true; // Found timing data } } } } } } } return false; } catch { return false; } }); if (hasTimingData) { return true; } await Task.Delay(500); // Check every 500ms - timing data loading can take a bit longer } return false; // Timeout - proceed without timing data } public async Task GetFunctionAssemblyToFileAsync(string functionName) { try { // Get the assembly content first string assemblyContent = await GetFunctionAssemblyAsync(functionName); if (assemblyContent == null) { return null; // Function not found } // Get the current process name from the loaded session string processName = await GetCurrentProcessNameAsync(); // Create the tmp directory path string currentDirectory = Directory.GetCurrentDirectory(); string srcPath = Path.GetFullPath(Path.Combine(currentDirectory, "..", "..", "src")); string tmpDirectory = Path.Combine(srcPath, "tmp"); // Ensure the tmp directory exists Directory.CreateDirectory(tmpDirectory); // Sanitize the names for file system compatibility string sanitizedProcessName = SanitizeFileName(processName); string sanitizedFunctionName = SanitizeFileName(functionName); // Create the file name string fileName = $"{sanitizedProcessName}-{sanitizedFunctionName}.asm"; string filePath = Path.Combine(tmpDirectory, fileName); // Write the assembly content to the file await File.WriteAllTextAsync(filePath, assemblyContent); return filePath; } catch { return null; } } public async Task GetAvailableProcessesAsync(string profileFilePath, double? minWeightPercentage = null, int? topCount = null) { // Validate file exists first if (!File.Exists(profileFilePath)) { return new GetAvailableProcessesResult { Success = false, ErrorMessage = $"Trace file not found: {profileFilePath}" }; } try { // Call FindTraceProcesses directly instead of opening the UI window. // This avoids a race condition where the UI's double TextChanged invocation // could cause WaitForProcessListLoadedAsync to read an incomplete intermediate list. using var cancelableTask = new CancelableTask(); var options = App.Settings.ProfileOptions; // Progress callback must be non-null (ETWEventProcessor calls it unconditionally). var processSummaries = await ETWProfileDataProvider.FindTraceProcesses( profileFilePath, options, _ => { }, cancelableTask); if (processSummaries == null || processSummaries.Count == 0) { return new GetAvailableProcessesResult { Success = false, ErrorMessage = "Failed to extract process list from trace file" }; } // Exclude Idle/kernel process and use non-idle percentages for meaningful results. var processes = processSummaries .Where(p => p.Process.ProcessId != ETWEventProcessor.KernelProcessId) .Select(p => new ProcessInfo { ProcessId = p.Process.ProcessId, Name = p.Process.Name ?? string.Empty, ImageFileName = p.Process.ImageFileName, CommandLine = p.Process.CommandLine, Weight = p.Weight, WeightPercentage = p.WeightPercentageExcludingIdle, Duration = p.Duration }).ToArray(); // Apply weight filtering if specified if (minWeightPercentage.HasValue) { if (minWeightPercentage < 0 || minWeightPercentage > 100) { return new GetAvailableProcessesResult { Success = false, ErrorMessage = "minWeightPercentage must be nonnegative, between 0 and 100." }; } processes = processes .Where(p => p.WeightPercentage >= minWeightPercentage.Value) .ToArray(); } // Apply top N filtering if specified if (topCount.HasValue) { if (topCount < 1) { return new GetAvailableProcessesResult { Success = false, ErrorMessage = "topCount must be a positive integer." }; } // Sort by weight percentage descending and take top N if (processes.Length > topCount.Value) { processes = processes .OrderByDescending(p => p.WeightPercentage) .Take(topCount.Value) .ToArray(); } } return new GetAvailableProcessesResult { Success = true, Processes = processes }; } catch (Exception ex) { return new GetAvailableProcessesResult { Success = false, ErrorMessage = $"Unexpected error: {ex.Message}" }; } } /// /// Get the current process name from the loaded session /// private async Task GetCurrentProcessNameAsync() { try { var status = await GetStatusAsync(); // Use the current process information if available if (status.CurrentProcess != null) { if (!string.IsNullOrEmpty(status.CurrentProcess.Name)) { return status.CurrentProcess.Name; } return $"process-{status.CurrentProcess.ProcessId}"; } // Try to extract process name from loaded processes if (status.LoadedProcesses?.Length > 0) { return $"process-{status.LoadedProcesses[0]}"; } // If we have a profile path, try to extract a meaningful name from it if (!string.IsNullOrEmpty(status.CurrentProfilePath)) { string fileName = Path.GetFileNameWithoutExtension(status.CurrentProfilePath); return !string.IsNullOrEmpty(fileName) ? fileName : "trace"; } return "unknown"; } catch { return "unknown"; } } /// /// Sanitize a string to be safe for use as a file name /// private static string SanitizeFileName(string fileName) { if (string.IsNullOrWhiteSpace(fileName)) return "unknown"; // Remove or replace invalid file name characters char[] invalidChars = Path.GetInvalidFileNameChars(); string sanitized = fileName; foreach (char invalidChar in invalidChars) { sanitized = sanitized.Replace(invalidChar, '_'); } // Also replace some common problematic characters sanitized = sanitized.Replace(':', '_') .Replace('<', '_') .Replace('>', '_') .Replace('*', '_') .Replace('?', '_') .Replace('|', '_') .Replace('"', '_'); // Limit length to avoid very long file names if (sanitized.Length > 100) { sanitized = sanitized.Substring(0, 100); } return sanitized; } public async Task GetAvailableFunctionsAsync(FunctionFilter? filter = null) { try { // Check if a profile is currently loaded var status = await GetStatusAsync(); if (!status.IsProfileLoaded) { return new GetAvailableFunctionsResult { Success = false, ErrorMessage = "No profile is currently loaded. Please open a trace file first using OpenTrace." }; } // Extract function information from the currently loaded session var functions = await ExtractFunctionInfoAsync(); if (functions.Length == 0) { return new GetAvailableFunctionsResult { Success = false, ErrorMessage = "No functions found in the currently loaded profile. If you just opened a trace file, " + "please wait for the profile loading to complete (this can take 20+ seconds for large traces) " + "before calling GetAvailableFunctions. The loading includes multiple stages: " + "'Reading Trace' → 'Downloading and loading binaries' → 'Downloading and loading symbols' → " + "'Processing trace samples' → 'Computing Call Tree'." }; } // Apply module filtering if specified if (!string.IsNullOrWhiteSpace(filter?.ModuleName)) { functions = functions .Where(f => !string.IsNullOrEmpty(f.ModuleName) && f.ModuleName.Contains(filter.ModuleName, StringComparison.OrdinalIgnoreCase)) .ToArray(); if (functions.Length == 0) { // Provide helpful error message with available module suggestions var availableModules = (await ExtractFunctionInfoAsync()) .Where(f => !string.IsNullOrEmpty(f.ModuleName)) .Select(f => f.ModuleName!) .Distinct() .OrderBy(m => m) .Take(10) // Show first 10 modules as examples .ToArray(); var modulesSuggestion = availableModules.Length > 0 ? $" Available modules include: {string.Join(", ", availableModules)}{(availableModules.Length == 10 ? ", ..." : "")}" : ""; return new GetAvailableFunctionsResult { Success = false, ErrorMessage = $"No functions found in module '{filter.ModuleName}'. The module name might not exist, be spelled differently, or not be loaded.{modulesSuggestion}" }; } } // Apply self time filtering if specified if (filter?.MinSelfTimePercentage.HasValue == true) { if (filter.MinSelfTimePercentage < 0 || filter.MinSelfTimePercentage > 100) { return new GetAvailableFunctionsResult { Success = false, ErrorMessage = "MinSelfTimePercentage must be between 0 and 100." }; } functions = functions .Where(f => f.SelfTimePercentage >= filter.MinSelfTimePercentage.Value) .ToArray(); } // Apply total time filtering if specified if (filter?.MinTotalTimePercentage.HasValue == true) { if (filter.MinTotalTimePercentage < 0 || filter.MinTotalTimePercentage > 100) { return new GetAvailableFunctionsResult { Success = false, ErrorMessage = "MinTotalTimePercentage must be between 0 and 100." }; } functions = functions .Where(f => f.TotalTimePercentage >= filter.MinTotalTimePercentage.Value) .ToArray(); } // Apply top N filtering if specified if (filter?.TopCount.HasValue == true) { if (filter.TopCount < 1) { return new GetAvailableFunctionsResult { Success = false, ErrorMessage = "TopCount must be a positive integer." }; } // Sort by the chosen metric and take top N if (functions.Length > filter.TopCount.Value) { functions = (filter.SortBySelfTime) ? functions.OrderByDescending(f => f.SelfTimePercentage).Take(filter.TopCount.Value).ToArray() : functions.OrderByDescending(f => f.TotalTimePercentage).Take(filter.TopCount.Value).ToArray(); } } else { // If no topCount specified, still sort the results functions = (filter?.SortBySelfTime ?? true) ? functions.OrderByDescending(f => f.SelfTimePercentage).ToArray() : functions.OrderByDescending(f => f.TotalTimePercentage).ToArray(); } return new GetAvailableFunctionsResult { Success = true, Functions = functions }; } catch (Exception ex) { return new GetAvailableFunctionsResult { Success = false, ErrorMessage = $"Unexpected error: {ex.Message}" }; } } /// /// Extract function information from the currently loaded profile session /// private async Task ExtractFunctionInfoAsync() { try { // Use the shared helper to get the function list control var (sectionPanel, functionListControl) = await GetFunctionListControlAsync(); if (functionListControl?.ItemsSource == null) { return Array.Empty(); } return await dispatcher.InvokeAsync(() => { try { var functionInfos = new List(); // Iterate through the function list and extract information foreach (var item in functionListControl.ItemsSource) { if (item is ProfileExplorer.UI.IRTextFunctionEx functionEx) { var functionInfo = new FunctionInfo { Name = functionEx.Name ?? string.Empty, FullName = functionEx.ToolTip ?? functionEx.Name ?? string.Empty, ModuleName = ExtractModuleName(functionEx), SelfTimePercentage = Math.Round(functionEx.ExclusivePercentage * 100, 4), // Convert fraction to percentage TotalTimePercentage = Math.Round(functionEx.Percentage * 100, 4), // Convert fraction to percentage SelfTime = functionEx.ExclusiveWeight, TotalTime = functionEx.Weight, SourceFile = ExtractSourceFile(functionEx), HasAssembly = HasAssemblyData(functionEx) }; functionInfos.Add(functionInfo); } } // Sort by self time percentage descending (most expensive functions first) return functionInfos .OrderByDescending(f => f.SelfTimePercentage) .ToArray(); } catch { return Array.Empty(); } }); } catch { return Array.Empty(); } } /// /// Extract module name from function information /// private string ExtractModuleName(ProfileExplorer.UI.IRTextFunctionEx functionEx) { try { // Get module name directly from the function if (!string.IsNullOrEmpty(functionEx.ModuleName)) { return functionEx.ModuleName; } // Alternative: extract from full name if it contains module info var fullName = functionEx.ToolTip ?? functionEx.Name ?? string.Empty; if (fullName.Contains("!")) { var parts = fullName.Split('!'); if (parts.Length > 1) { return parts[0]; } } return null; } catch { return null; } } /// /// Extract source file information from function /// private string ExtractSourceFile(ProfileExplorer.UI.IRTextFunctionEx functionEx) { try { // Try to get source file information from debug info var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; if (profileData?.ModuleDebugInfo != null && functionEx.Function != null) { // Look through module debug info for this function foreach (var debugInfo in profileData.ModuleDebugInfo.Values) { var sourceInfo = debugInfo.FindFunctionSourceFilePath(functionEx.Function); if (!sourceInfo.IsUnknown && sourceInfo.HasFilePath) { return sourceInfo.FilePath; } } } return null; } catch { return null; } } /// /// Check if function has assembly data available /// private bool HasAssemblyData(ProfileExplorer.UI.IRTextFunctionEx functionEx) { try { // Check if the function has any sections (indicating code/assembly data) return functionEx.Function?.HasSections ?? false; } catch { return false; } } /// /// Ensures the binary for a function's module is loaded, triggering lazy load if needed. /// Returns: null if no lazy load was needed, true if lazy load succeeded, false if it failed. /// private async Task EnsureBinaryLoadedForFunctionAsync(ProfileExplorer.Core.IRTextFunction function) { try { if (function?.ParentSummary == null) { return null; // Cannot determine module } // Get the document for this function's module var docInfo = await dispatcher.InvokeAsync(() => { return mainWindow.SessionState?.FindLoadedDocument(function.ParentSummary); }); if (docInfo == null) { return null; // Document not found } // Check if lazy loading is needed if (docInfo.BinaryFileExists) { return null; // Binary already loaded, no lazy load needed } if (docInfo.EnsureBinaryLoaded == null) { return null; // No lazy load callback available } // Trigger lazy loading string moduleName = docInfo.ModuleName ?? function.ModuleName ?? "binary"; ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Triggering lazy binary load for module: {moduleName}"); bool loaded = await docInfo.EnsureBinaryLoaded().ConfigureAwait(false); ProfileExplorer.Core.Utilities.DiagnosticLogger.LogInfo($"[MCP] Lazy binary load result for {moduleName}: {loaded}"); return loaded; } catch (Exception ex) { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogError($"[MCP] Error during lazy binary load: {ex.Message}"); return false; } } public async Task GetAvailableBinariesAsync(double? minTimePercentage = null, TimeSpan? minTime = null, int? topCount = null) { try { // Check if a profile is currently loaded var status = await GetStatusAsync(); if (!status.IsProfileLoaded) { return new GetAvailableBinariesResult { Success = false, ErrorMessage = "No profile is currently loaded. Please open a trace file first using OpenTrace.", Binaries = Array.Empty() }; } // Get module data directly from ProfileData CallTree var moduleInfos = await GetModuleDataFromCallTreeAsync(); if (moduleInfos.Length == 0) { return new GetAvailableBinariesResult { Success = false, ErrorMessage = "No module data available. Ensure the profile has finished loading completely.", Binaries = Array.Empty() }; } // Slice ModuleEx into BinaryInfo var binaryInfos = moduleInfos.Select(module => { var binaryInfo = new BinaryInfo { Name = module.Name ?? string.Empty, FullPath = ExtractModuleFullPath(module.Name), TimePercentage = Math.Round(module.ExclusivePercentage, 4), Time = module.ExclusiveWeight, BinaryFileMissing = module.BinaryFileMissing, DebugFileMissing = module.DebugFileMissing }; // Log binary info for diagnostics ProfileExplorer.Core.Utilities.DiagnosticLogger.LogDebug($"[MCP-BinaryInfo] Module: {binaryInfo.Name}, BinaryMissing: {binaryInfo.BinaryFileMissing}, DebugMissing: {binaryInfo.DebugFileMissing}"); return binaryInfo; }).ToArray(); // Apply filtering var filteredBinaries = binaryInfos; if (minTimePercentage.HasValue) { filteredBinaries = filteredBinaries .Where(b => b.TimePercentage >= minTimePercentage.Value) .ToArray(); } if (minTime.HasValue) { filteredBinaries = filteredBinaries .Where(b => b.Time >= minTime.Value) .ToArray(); } // Sort by time percentage descending filteredBinaries = filteredBinaries .OrderByDescending(b => b.TimePercentage) .ToArray(); // Apply top count filter if specified if (topCount.HasValue) { filteredBinaries = filteredBinaries .Take(topCount.Value) .ToArray(); } return new GetAvailableBinariesResult { Success = true, Binaries = filteredBinaries }; } catch (Exception ex) { return new GetAvailableBinariesResult { Success = false, ErrorMessage = $"Error retrieving binaries: {ex.Message}", Binaries = Array.Empty() }; } } /// /// Get module data directly from SessionState.ProfileData (same source as UI) /// private async Task GetModuleDataFromCallTreeAsync() { try { return await dispatcher.InvokeAsync(() => { try { var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; if (profileData?.ModuleWeights == null || profileData.Modules == null) { return Array.Empty(); } var moduleInfos = new List(); // Extract module information directly from ProfileData (same logic as LoadFunctionProfile) foreach (var pair in profileData.ModuleWeights) { var module = profileData.Modules[pair.Key]; double weightPercentage = profileData.ScaleModuleWeight(pair.Value); // Get module status for additional info var moduleStatus = profileData.Report?.GetModuleStatus(module.ModuleName); var moduleInfo = new ProfileExplorer.UI.ModuleEx { Name = module.ModuleName, ExclusivePercentage = weightPercentage * 100.0, // convert 0.abcd decimal to ab.cd percent ExclusiveWeight = pair.Value, Status = moduleStatus, DebugFileMissing = moduleStatus != null ? !moduleStatus.HasDebugInfoLoaded : false, }; moduleInfos.Add(moduleInfo); } return moduleInfos.OrderByDescending(m => m.ExclusivePercentage).ToArray(); } catch { return Array.Empty(); } }); } catch { return Array.Empty(); } } /// /// Extract full path for a module if available /// private string ExtractModuleFullPath(string moduleName) { try { var sessionState = mainWindow.SessionState; var profileData = sessionState?.ProfileData; if (profileData?.Modules != null) { // Look for a module with matching name var module = profileData.Modules.FirstOrDefault(m => string.Equals(m.Value.ModuleName, moduleName, StringComparison.OrdinalIgnoreCase) || Path.GetFileName(m.Value.FilePath).Equals(moduleName, StringComparison.OrdinalIgnoreCase)); return module.Value?.FilePath; } return null; } catch { return null; } } } ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/CallTreeOptionsPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/DocumentOptionsPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Media; using System.Xml; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.UI.OptionsPanels; public partial class DocumentOptionsPanel : OptionsPanelBase { private const string DocumentStylesFilePath = @"documentStyles.xml"; private bool syntaxEditPanelVisible_; private List syntaxHighlightingColors_; private DocumentColorStyle syntaxHighlightingStyle_; private List syntaxFiles_; private SyntaxFileInfo selectedSyntaxFile_; private DocumentSettings settings_; public DocumentOptionsPanel() { InitializeComponent(); } public override double DefaultHeight => 470; public bool SyntaxFileChanged { get; set; } public override void Initialize(FrameworkElement parent, SettingsBase settings, IUISession session) { base.Initialize(parent, settings, session); settings_ = (DocumentSettings)Settings; ProfilingOptionsPanel.DataContext = settings_.ProfileMarkerSettings; SourceOptionsPanel.DataContext = settings_.SourceMarkerSettings; ReloadSyntaxHighlightingList(); } public override void OnSettingsChanged(object newSettings) { settings_ = (DocumentSettings)newSettings; ProfilingOptionsPanel.DataContext = null; ProfilingOptionsPanel.DataContext = settings_.ProfileMarkerSettings; SourceOptionsPanel.DataContext = null; SourceOptionsPanel.DataContext = settings_.SourceMarkerSettings; ReloadSyntaxHighlightingList(); } public override void PanelClosing() { SyntaxFileChanged = UpdateSyntaxHighlightingStyle(); } public override void PanelResetting() { syntaxHighlightingStyle_ = null; syntaxHighlightingColors_ = null; } public override void PanelAfterReset() { if (syntaxEditPanelVisible_) { ShowSyntaxEditPanel(null); } } private void ReloadSyntaxHighlightingList() { syntaxFiles_ = App.ReloadSyntaxHighlightingFiles(App.Session.CompilerInfo.CompilerIRName); selectedSyntaxFile_ = App.GetSyntaxHighlightingFileInfo(settings_.SyntaxHighlightingName, App.Session.CompilerInfo.CompilerIRName); // Unbind the combobox event while loading the list // so that it doesn't change the selected syntax file. IRSyntaxCombobox.SelectionChanged -= IRSyntaxCombobox_SelectionChanged; IRSyntaxCombobox.ItemsSource = new CollectionView(syntaxFiles_); IRSyntaxCombobox.SelectedItem = selectedSyntaxFile_; IRSyntaxCombobox.SelectionChanged += IRSyntaxCombobox_SelectionChanged; } protected override void NotifySettingsChanged() { SyntaxFileChanged = DataContext != null && UpdateSyntaxHighlightingStyle(); base.NotifySettingsChanged(); } private void StyleButton_Click(object sender, RoutedEventArgs e) { try { var docStyles = LoadDocumentStyles(DocumentStylesFilePath); StyleContextMenu.Items.Clear(); foreach (var style in docStyles) { var menuItem = new MenuItem(); menuItem.Header = style.Name; menuItem.Tag = style; menuItem.Click += StyleContextMenuItem_Click; StyleContextMenu.Items.Add(menuItem); } if (Parent is OptionsPanelHostPopup popup) { popup.StaysOpen = true; StyleContextMenu.Closed += StyleContextMenu_Closed; } StyleContextMenu.IsOpen = true; } catch (Exception ex) { Trace.TraceError($"Failed to load style document XML: {ex}"); } } private void StyleContextMenu_Closed(object sender, RoutedEventArgs e) { var popup = Parent as OptionsPanelHostPopup; popup.StaysOpen = false; } private void StyleContextMenuItem_Click(object sender, RoutedEventArgs e) { var style = ((MenuItem)sender).Tag as DocumentColorStyle; ApplyDocumentStyle(style); } private void ApplyDocumentStyle(DocumentColorStyle style) { settings_.BackgroundColor = style.Colors["BackgroundColor"]; settings_.AlternateBackgroundColor = style.Colors["AlternateBackgroundColor"]; settings_.MarginBackgroundColor = style.Colors["MarginBackgroundColor"]; settings_.BlockSeparatorColor = style.Colors["BlockSeparatorColor"]; settings_.TextColor = style.Colors["TextColor"]; settings_.SelectedValueColor = style.Colors["SelectedValueColor"]; settings_.DefinitionValueColor = style.Colors["DefinitionValueColor"]; settings_.UseValueColor = style.Colors["UseValueColor"]; settings_.BorderColor = style.Colors["BorderColor"]; DataContext = null; DataContext = settings_; NotifySettingsChanged(); } private void PopulateSyntaxHighlightingColorPickers(DocumentColorStyle style) { syntaxHighlightingStyle_ = style; syntaxHighlightingColors_ = new List(); foreach (var pair in style.Colors) { syntaxHighlightingColors_.Add(new ColorPickerInfo(pair.Key, pair.Value)); } SyntaxHighlightingColorPickers.ItemsSource = new CollectionView(syntaxHighlightingColors_); } private bool UpdateSyntaxHighlightingStyle() { if (selectedSyntaxFile_ == null) { return false; // Happens if there are no syntax files found. } return CreateSyntaxHighlightingStyle(selectedSyntaxFile_.Path, selectedSyntaxFile_.Path); } private bool CreateSyntaxHighlightingStyle(string inputFile, string outputFile) { if (syntaxHighlightingStyle_ == null) { return false; } foreach (var info in syntaxHighlightingColors_) { syntaxHighlightingStyle_.Colors[info.Name] = info.Value; } string newSyntaxFile = App.GetSyntaxHighlightingFilePath(outputFile, App.Session.CompilerInfo.CompilerIRName); ApplySyntaxHighlightingStyles(inputFile, newSyntaxFile, syntaxHighlightingStyle_); return true; } private DocumentColorStyle ApplySyntaxHighlightingStyles(string stylePath, string outputStylePath = null, DocumentColorStyle replacementStyles = null) { var xmlDoc = new XmlDocument(); xmlDoc.Load(stylePath); var root = xmlDoc.DocumentElement; string name = root.Attributes.GetNamedItem("name").InnerText; var docStyle = new DocumentColorStyle(name); foreach (XmlNode node in root.ChildNodes) { if (node.Name != "Color") { continue; } string colorName = node.Attributes.GetNamedItem("name").InnerText; var colorNode = node.Attributes.GetNamedItem("foreground"); if (replacementStyles != null) { if (!replacementStyles.Colors.ContainsKey(colorName)) { continue; } var newColor = replacementStyles.Colors[colorName]; colorNode.Value = $"#{newColor.R:X2}{newColor.G:X2}{newColor.B:X2}"; } else { docStyle.Colors[colorName] = Utils.ColorFromString(colorNode.InnerText); } } if (outputStylePath != null) { xmlDoc.Save(outputStylePath); } return docStyle; } private List LoadDocumentStyles(string stylePath) { //? TODO: This should be a JSOn doc, easier to read and same foramt as other settings var xmlDoc = new XmlDocument(); xmlDoc.Load(stylePath); var docStyles = new List(); var styles = xmlDoc.SelectNodes("/SyntaxDefinitions/SyntaxDefinition"); foreach (XmlNode style in styles) { string name = style.Attributes.GetNamedItem("name").InnerText; var docStyle = new DocumentColorStyle(name); docStyles.Add(docStyle); foreach (XmlNode color in style.ChildNodes) { string colorName = color.Attributes.GetNamedItem("name").InnerText; string colorValue = color.Attributes.GetNamedItem("background").InnerText; docStyle.Colors[colorName] = Utils.ColorFromString(colorValue); } } return docStyles; } private void SyntaxEditButton_Click(object sender, RoutedEventArgs e) { if (!syntaxEditPanelVisible_) { ShowSyntaxEditPanel(null); } else { HideSyntaxEditPanel(); } } private void ShowSyntaxEditPanel(string filePath, bool force = false) { if (syntaxEditPanelVisible_ && !force) { return; } filePath ??= App.GetSyntaxHighlightingFilePath(selectedSyntaxFile_); var compilerStyle = ApplySyntaxHighlightingStyles(filePath); PopulateSyntaxHighlightingColorPickers(compilerStyle); SyntaxHighlightingPanel.Visibility = Visibility.Visible; SyntaxEditButton.IsChecked = true; syntaxEditPanelVisible_ = true; } private void HideSyntaxEditPanel(bool reset = false) { if (!syntaxEditPanelVisible_) { return; } SyntaxHighlightingPanel.Visibility = Visibility.Collapsed; SyntaxEditButton.IsChecked = false; syntaxEditPanelVisible_ = false; if (reset) { syntaxHighlightingStyle_ = null; } } private void IRSyntaxCombobox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (IRSyntaxCombobox.SelectedItem != null) { bool syntaxPanelVisible = syntaxEditPanelVisible_; HideSyntaxEditPanel(); selectedSyntaxFile_ = (SyntaxFileInfo)IRSyntaxCombobox.SelectedItem; settings_.SyntaxHighlightingName = selectedSyntaxFile_.Name; if (syntaxPanelVisible) { ShowSyntaxEditPanel(selectedSyntaxFile_.Path); } } } private void OpenSyntaxStyleButton_Click(object sender, RoutedEventArgs e) { string path = App.GetCompilerSettingsDirectoryPath(App.Session.CompilerInfo.CompilerIRName); App.OpenSettingsFolder(path); } private void EditSyntaxFileButton_Click(object sender, RoutedEventArgs e) { string path = selectedSyntaxFile_.Path; App.LaunchSettingsFileEditor(path); } private void ResetSyntaxStyleButton_Click(object sender, RoutedEventArgs e) { // Try to restore the internal syntax file. using var centerForm = new DialogCenteringHelper(Parent); if (MessageBox.Show("Do you want to reset syntax highlighting style?", "Profile Explorer", MessageBoxButton.YesNo, MessageBoxImage.Question) != MessageBoxResult.Yes) { return; } string path = App.GetInternalSyntaxHighlightingFilePath(selectedSyntaxFile_.Name, App.Session.CompilerInfo.CompilerIRName); if (path != null) { ShowSyntaxEditPanel(path, true); UpdateSyntaxHighlightingStyle(); } } private void ReloadSyntaxStyleButton_Click(object sender, RoutedEventArgs e) { ReloadSyntaxHighlightingList(); } private void CloneSyntaxFileButton_Click(object sender, RoutedEventArgs e) { } private class DocumentColorStyle { public DocumentColorStyle(string name) { Name = name; Colors = new Dictionary(); } public string Name { get; set; } public Dictionary Colors { get; set; } } private class ColorPickerInfo { public ColorPickerInfo(string name, Color value) { Name = name; Value = value; } public string Name { get; set; } public Color Value { get; set; } } } ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/DocumentProfilingOptionsPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/FunctionMarkingOptionsPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using ProfileExplorer.UI.Windows; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.UI.OptionsPanels; public partial class FunctionMarkingOptionsPanel : OptionsPanelBase { private FunctionMarkingSettings settings_; public FunctionMarkingOptionsPanel() { InitializeComponent(); ModulePaletteSelector.PalettesSource = ColorPalette.GradientBuiltinPalettes; } public override double DefaultHeight => 550; public override double DefaultWidth => 400; public override void Initialize(FrameworkElement parent, SettingsBase settings, IUISession session) { base.Initialize(parent, settings, session); settings_ = (FunctionMarkingSettings)Settings; ReloadModuleList(); ReloadFunctionList(); ReloadMarkingsList(); } public override void OnSettingsChanged(object newSettings) { settings_ = (FunctionMarkingSettings)newSettings; ReloadModuleList(); ReloadFunctionList(); ReloadMarkingsList(); } private void ReloadModuleList() { var list = new ObservableCollectionRefresh(settings_.ModuleColors); ModuleList.ItemsSource = list; } private void ReloadFunctionList() { var list = new ObservableCollectionRefresh(settings_.FunctionColors); FunctionList.ItemsSource = list; } private void ReloadMarkingsList() { var list = new ObservableCollectionRefresh(settings_.SavedSets); MarkingsList.ItemsSource = list; } private void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (sender is TextBox textBox) { Utils.SelectTextBoxListViewItem(textBox, ModuleList); } } private void ModuleRemove_Click(object sender, RoutedEventArgs e) { if (ModuleList.SelectedItem is FunctionMarkingStyle pair) { settings_.ModuleColors.Remove(pair); ReloadModuleList(); NotifySettingsChanged(); } } private void ModuleAdd_Click(object sender, RoutedEventArgs e) { settings_.ModuleColors.Add(new FunctionMarkingStyle("", Colors.White)); ReloadModuleList(); NotifySettingsChanged(); Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, () => { Utils.SelectEditableListViewItem(ModuleList, settings_.ModuleColors.Count - 1); }); } private void ClearModule_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to clear the list?", this) == MessageBoxResult.Yes) { settings_.ModuleColors.Clear(); ReloadModuleList(); NotifySettingsChanged(); } } private void ClearFunction_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to clear the list?", this) == MessageBoxResult.Yes) { settings_.FunctionColors.Clear(); ReloadFunctionList(); NotifySettingsChanged(); } } private void FunctionRemove_Click(object sender, RoutedEventArgs e) { if (FunctionList.SelectedItem is FunctionMarkingStyle pair) { settings_.FunctionColors.Remove(pair); ReloadFunctionList(); NotifySettingsChanged(); } } private void FunctionAdd_Click(object sender, RoutedEventArgs e) { settings_.FunctionColors.Add(new FunctionMarkingStyle("", Colors.White)); ReloadFunctionList(); NotifySettingsChanged(); Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, () => { Utils.SelectEditableListViewItem(FunctionList, settings_.FunctionColors.Count - 1); }); } private void MarkingClear_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to clear the list?", this) == MessageBoxResult.Yes) { settings_.SavedSets.Clear(); ReloadMarkingsList(); NotifySettingsChanged(); } } private void MarkingRemove_Click(object sender, RoutedEventArgs e) { if (MarkingsList.SelectedItem is FunctionMarkingSet set) { settings_.SavedSets.Remove(set); ReloadMarkingsList(); NotifySettingsChanged(); } } private void MarkingImport_Click(object sender, RoutedEventArgs e) { if (settings_.ImportMarkings(this)) { ReloadMarkingsList(); ReloadFunctionList(); ReloadModuleList(); NotifySettingsChanged(); } } private void MarkingExport_Click(object sender, RoutedEventArgs e) { settings_.ExportMarkings(this); } private void MarkingSave_Click(object sender, RoutedEventArgs e) { TextInputWindow input = new("Save marked functions/modules", "Saved marking set name:", "Save", "Cancel"); if (input.Show(out string result, true)) { settings_.SaveCurrentMarkingSet(result); ReloadMarkingsList(); } } private void MarkingLoad_Click(object sender, RoutedEventArgs e) { if (MarkingsList.SelectedItem is FunctionMarkingSet set) { settings_.AppendMarkingSet(set); NotifySettingsChanged(); } } private void MarkingCheckBox_Changed(object sender, RoutedEventArgs e) { NotifySettingsChanged(); } } ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/GeneralOptionsPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/RemarkOptionsPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.UI.OptionsPanels; public partial class RemarkOptionsPanel : OptionsPanelBase { public const double LeftMargin = 200; private List kindCheckboxes_; private List categoryCheckboxes_; public RemarkOptionsPanel() { InitializeComponent(); kindCheckboxes_ = new List(); kindCheckboxes_.Add(OptimizationCheckbox); kindCheckboxes_.Add(AnalysisCheckbox); kindCheckboxes_.Add(StandardCheckbox); kindCheckboxes_.Add(VerboseCheckbox); kindCheckboxes_.Add(TraceCheckbox); } public override void Initialize(FrameworkElement parent, SettingsBase settings, IUISession session) { base.Initialize(parent, settings, session); PopulateCategoryList(); } private void SetCheckboxesState(List list, bool state) { list.ForEach(item => item.IsChecked = state); } private bool PopulateCategoryList() { var remarkSettings = (RemarkSettings)DataContext; categoryCheckboxes_ = new List(); bool initialLoad = !remarkSettings.HasCategoryFilters; var categories = App.Session.RemarkProvider.RemarkCategories; if (categories == null) { using var centerForm = new DialogCenteringHelper(Parent); MessageBox.Show("Failed to load remark settings file,\ncheck JSON for any syntax errors!", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); return false; } CategoriesList.Children.Clear(); foreach (var category in categories) { if (!string.IsNullOrEmpty(category.Title)) { var checkbox = new CheckBox(); checkbox.Content = category.Title; checkbox.Margin = new Thickness(0, 0, 0, 2); if (category.AddTextMark) { checkbox.Background = ColorBrushes.GetBrush(category.TextMarkBorderColor); } else if (category.AddLeftMarginMark) { checkbox.Background = ColorBrushes.GetBrush(category.MarkColor); } if (initialLoad) { checkbox.IsChecked = true; } else if (remarkSettings.CategoryFilter.TryGetValue(category.Title, out bool state)) { checkbox.IsChecked = state; } checkbox.Tag = category; checkbox.Checked += Checkbox_CheckedChanged; checkbox.Unchecked += Checkbox_CheckedChanged; CategoriesList.Children.Add(checkbox); categoryCheckboxes_.Add(checkbox); } } return true; } private void Checkbox_CheckedChanged(object sender, RoutedEventArgs e) { UpdateCategoryFilter(); NotifySettingsChanged(); } private void UpdateCategoryFilter() { var remarkSettings = (RemarkSettings)DataContext; remarkSettings.CategoryFilter = new Dictionary(); foreach (var checkbox in categoryCheckboxes_) { var category = (RemarkCategory)checkbox.Tag; remarkSettings.CategoryFilter[category.Title] = checkbox.IsChecked.HasValue && checkbox.IsChecked.Value; } } private void SetAllKindCheckboxesButton_Click(object sender, RoutedEventArgs e) { SetCheckboxesState(kindCheckboxes_, true); } private void ResetAllKindCheckboxesButton_Click(object sender, RoutedEventArgs e) { SetCheckboxesState(kindCheckboxes_, false); } private void EditButton_Click(object sender, RoutedEventArgs e) { string settingsPath = App.GetRemarksDefinitionFilePath(App.Session.CompilerInfo.CompilerIRName); App.LaunchSettingsFileEditor(settingsPath); } private void SetAllCategoryCheckboxesButton_Click(object sender, RoutedEventArgs e) { SetCheckboxesState(categoryCheckboxes_, true); } private void ResetAllCategoryCheckboxesButton_Click(object sender, RoutedEventArgs e) { SetCheckboxesState(categoryCheckboxes_, false); } private void ReloadButton_Click(object sender, RoutedEventArgs e) { PopulateCategoryList(); } } ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/SectionOptionsPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/SourceFileOptionsPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.UI.OptionsPanels; public partial class SourceFileOptionsPanel : OptionsPanelBase { private SourceFileSettings settings_; public SourceFileOptionsPanel() { InitializeComponent(); } public override double DefaultHeight => 450; public override double DefaultWidth => 400; public override void Initialize(FrameworkElement parent, SettingsBase settings, IUISession session) { base.Initialize(parent, settings, session); settings_ = (SourceFileSettings)Settings; ProfilingOptionsPanel.DataContext = settings_.ProfileMarkerSettings; ReloadMappedPathsList(); ReloadExcludedPathsList(); } public override void OnSettingsChanged(object newSettings) { settings_ = (SourceFileSettings)newSettings; ProfilingOptionsPanel.DataContext = null; ProfilingOptionsPanel.DataContext = settings_.ProfileMarkerSettings; } private void ReloadMappedPathsList() { var mappings = new List>(); foreach (var pair in settings_.FinderSettings.SourceMappings) { mappings.Add(pair); } var list = new ObservableCollectionRefresh>(mappings); MappedPathsList.ItemsSource = list; } private void ReloadExcludedPathsList() { var list = new ObservableCollectionRefresh(settings_.FinderSettings.DisabledSourceMappings); ExcludedPathsList.ItemsSource = list; } private void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (sender is TextBox textBox) { Utils.SelectTextBoxListViewItem(textBox, ExcludedPathsList); e.Handled = true; } } private void RemoveMappedPath_Click(object sender, RoutedEventArgs e) { if (MappedPathsList.SelectedItem is KeyValuePair pair) { settings_.FinderSettings.SourceMappings.Remove(pair.Key); ReloadMappedPathsList(); } } private void ClearMappedPath_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to clear the list?", this) == MessageBoxResult.Yes) { settings_.FinderSettings.SourceMappings.Clear(); ReloadMappedPathsList(); } } private void AddExcludedPath_Click(object sender, RoutedEventArgs e) { settings_.FinderSettings.DisabledSourceMappings.Add(""); ReloadExcludedPathsList(); // Wait for the UI to update Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, () => { Utils.SelectEditableListViewItem(ExcludedPathsList, settings_.FinderSettings.DisabledSourceMappings.Count - 1); }); } private void ClearExcludedPath_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to clear the list?", this) == MessageBoxResult.Yes) { settings_.FinderSettings.DisabledSourceMappings.Clear(); ReloadExcludedPathsList(); } } private void RemoveExcludedPath_Click(object sender, RoutedEventArgs e) { if (ExcludedPathsList.SelectedItem is string path) { settings_.FinderSettings.DisabledSourceMappings.Remove(path); ReloadExcludedPathsList(); } } } ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/SymbolOptionsPanel.xaml ================================================  Symbol configuration help ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/SymbolOptionsPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.ComponentModel; using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Navigation; using System.Windows.Threading; using Microsoft.Win32; using ProfileExplorer.UI.Compilers; using ProfileExplorer.UI.Controls; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Settings; namespace ProfileExplorer.UI.OptionsPanels; public partial class SymbolOptionsPanel : OptionsPanelBase, INotifyPropertyChanged { private SymbolFileSourceSettings symbolSettings_; public SymbolOptionsPanel() { InitializeComponent(); } public event PropertyChangedEventHandler PropertyChanged; public override void Initialize(FrameworkElement parent, SettingsBase settings, IUISession session) { base.Initialize(parent, settings, session); symbolSettings_ = (SymbolFileSourceSettings)Settings; ReloadSymbolPathsList(); } public override void OnSettingsChanged(object newSettings) { symbolSettings_ = (SymbolFileSourceSettings)newSettings; } private void ClearRejectedButton_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to remove all excluded binaries and symbols?", this) == MessageBoxResult.Yes) { symbolSettings_.ClearRejectedFiles(); ReloadSymbolPathsList(); } } private void RemoveRejectedBinariesButton_Click(object sender, RoutedEventArgs e) { foreach (object item in RejectedBinariesList.SelectedItems) { symbolSettings_.RejectedBinaryFiles.Remove(item as BinaryFileDescriptor); } ReloadSettings(); } private void ClearRejectedBinariesButton_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to remove all excluded binaries?", this) == MessageBoxResult.Yes) { symbolSettings_.RejectedBinaryFiles.Clear(); ReloadSymbolPathsList(); } } private void RemoveRejectedSymbolsButton_Click(object sender, RoutedEventArgs e) { foreach (object item in RejectedSymbolsList.SelectedItems) { symbolSettings_.RejectedSymbolFiles.Remove(item as SymbolFileDescriptor); } ReloadSymbolPathsList(); } private void ClearRejectedSymbolsButton_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to remove all excluded symbols?", this) == MessageBoxResult.Yes) { symbolSettings_.RejectedSymbolFiles.Clear(); ReloadSymbolPathsList(); } } private void SymbolPathBrowseButton_Click(object sender, RoutedEventArgs e) { var listViewItem = Utils.FocusParentListViewItem(sender as Control, SymbolPathsList); var textBox = Utils.FindChild(listViewItem); using var centerForm = new DialogCenteringHelper(this); var dialog = new OpenFolderDialog(); dialog.Title = "Select symbols directory"; if (dialog.ShowDialog() == true) { textBox.Text = dialog.FolderName; UpdateSymbolPath(textBox); } } private void ClearSymbolCacheButton_Click(object sender, RoutedEventArgs e) { if (Utils.ShowYesNoMessageBox("Do you want to remove all cached symbol files?", this) == MessageBoxResult.Yes) { symbolSettings_.ClearSymbolFileCache(); ReloadSettings(); } } private void OpenSymbolCacheButton_Click(object sender, RoutedEventArgs e) { Utils.OpenExplorerAtFile(symbolSettings_.SymbolCacheDirectoryPath); } private void SymbolPath_LostFocus(object sender, RoutedEventArgs e) { var textBox = sender as FileSystemTextBox; UpdateSymbolPath(textBox); } private void SymbolPath_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { var textBox = sender as FileSystemTextBox; UpdateSymbolPath(textBox); } } private void SymbolPath_OnDropDownClosed(object sender, RoutedPropertyChangedEventArgs e) { var textBox = sender as FileSystemTextBox; UpdateSymbolPath(textBox); } private void UpdateSymbolPath(FileSystemTextBox textBox) { if (textBox == null) { return; } object item = textBox.DataContext; int index = symbolSettings_.SymbolPaths.IndexOf(item as string); if (index == -1) { return; } // Update list with the new text. string newSymbolPath = Utils.RemovePathQuotes(textBox.Text); textBox.Text = newSymbolPath; if (symbolSettings_.SymbolPaths[index] != newSymbolPath) { symbolSettings_.SymbolPaths[index] = newSymbolPath; ReloadSymbolPathsList(); } } private void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (sender is FileSystemTextBox textBox) { Utils.SelectTextBoxListViewItem(textBox, SymbolPathsList); } } private void AddPrivateSymbolServer_OnClick(object sender, RoutedEventArgs e) { symbolSettings_.AddSymbolServer(usePrivateServer: true); ReloadSymbolPathsList(); } private void AddPublicSymbolServer_OnClick(object sender, RoutedEventArgs e) { symbolSettings_.AddSymbolServer(usePrivateServer: false); ReloadSymbolPathsList(); } private void AddSymbolPathButton_Click(object sender, RoutedEventArgs e) { symbolSettings_.SymbolPaths.Add(""); ReloadSymbolPathsList(); // Wait for the UI to update Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, () => { Utils.SelectEditableListViewItem(SymbolPathsList, symbolSettings_.SymbolPaths.Count - 1); }); } private void RemoveSymbolPathButton_Click(object sender, RoutedEventArgs e) { foreach (object item in SymbolPathsList.SelectedItems) { string symbolPath = item as string; symbolSettings_.SymbolPaths.Remove(symbolPath); } ReloadSymbolPathsList(); } private void MoveSymbolPathUpButton_Click(object sender, RoutedEventArgs e) { if (SymbolPathsList.SelectedItems.Count != 1) { return; // Only remove if there is exactly one item selected } if (SymbolPathsList.SelectedIndex == 0) { return; // Cannot move an item up if it is already at the top of the list } int selectedIndex = SymbolPathsList.SelectedIndex; string selectedItem = SymbolPathsList.SelectedItem as string; symbolSettings_.SymbolPaths.RemoveAt(selectedIndex); symbolSettings_.SymbolPaths.Insert(selectedIndex - 1, selectedItem); ReloadSymbolPathsList(); } private void MoveSymbolPathDownButton_Click(object sender, RoutedEventArgs e) { if (SymbolPathsList.SelectedItems.Count != 1) { return; // Only remove if there is exactly one item selected } if (SymbolPathsList.SelectedIndex == SymbolPathsList.Items.Count - 1) { return; // Cannot move an item down if it is already at the bottom of the list } int selectedIndex = SymbolPathsList.SelectedIndex; string selectedItem = SymbolPathsList.SelectedItem as string; symbolSettings_.SymbolPaths.RemoveAt(selectedIndex); symbolSettings_.SymbolPaths.Insert(selectedIndex + 1, selectedItem); ReloadSymbolPathsList(); } private void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e) { Process.Start(new ProcessStartInfo(e.Uri.AbsoluteUri) { UseShellExecute = true }); } private void ReloadSymbolPathsList() { var list = new ObservableCollectionRefresh(symbolSettings_.SymbolPaths); SymbolPathsList.ItemsSource = list; var binariesList = symbolSettings_.RejectedBinaryFiles.ToList(); binariesList.Sort((a, b) => string.Compare(a.ImageName, b.ImageName, StringComparison.OrdinalIgnoreCase)); RejectedBinariesList.ItemsSource = binariesList; var symbolList = symbolSettings_.RejectedSymbolFiles.ToList(); symbolList.Sort((a, b) => string.Compare(a.FileName, b.FileName, StringComparison.OrdinalIgnoreCase)); RejectedSymbolsList.ItemsSource = symbolList; // Force refresh of count bindings since HashSet doesn't notify on changes. var dc = DataContext; DataContext = null; DataContext = dc; } public void OnPropertyChange(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } private void ResetFilterModuleSamplesButton_Click(object sender, RoutedEventArgs e) { symbolSettings_.LowSampleModuleCutoff = SymbolFileSourceSettings.DefaultLowSampleModuleCutoff; ReloadSettings(); } } ================================================ FILE: src/ProfileExplorerUI/OptionsPanels/TimelineOptionsPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/BookmarksPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.UI.Controls; namespace ProfileExplorer.UI; public static class BookmarkCommand { public static readonly RoutedUICommand JumpToBookmark = new("Untitled", "JumpToBookmark", typeof(BookmarksPanel)); public static readonly RoutedUICommand RemoveBookmark = new("Untitled", "RemoveBookmark", typeof(BookmarksPanel)); public static readonly RoutedUICommand RemoveAllBookmarks = new("Untitled", "RemoveAllBookmarks", typeof(BookmarksPanel)); public static readonly RoutedUICommand MarkBookmark = new("Untitled", "MarkBookmark", typeof(BookmarksPanel)); public static readonly RoutedUICommand UnmarkBookmark = new("Untitled", "UnmarkBookmark", typeof(BookmarksPanel)); } public partial class BookmarksPanel : ToolPanelControl { private ObservableCollectionRefresh bookmarks_; private IRDocumentPopupInstance previewPopup_; public BookmarksPanel() { InitializeComponent(); ResetBookmarks(); SetupPreviewPopup(); } public ObservableCollectionRefresh Bookmarks => bookmarks_; public override ToolPanelKind PanelKind => ToolPanelKind.Bookmarks; public void InitializeForDocument(IRDocument document) { Document = document; } private void TextBox_TextChanged(object sender, TextChangedEventArgs e) { var bookmark = ((TextBox)sender).DataContext as Bookmark; Document.BookmarkInfoChanged(bookmark); } private void SetupPreviewPopup() { if (previewPopup_ != null) { previewPopup_.UnregisterHoverEvents(); previewPopup_ = null; } previewPopup_ = new IRDocumentPopupInstance(App.Settings.GetElementPreviewPopupSettings(ToolPanelKind.Bookmarks), Session); previewPopup_.SetupHoverEvents(BookmarkList, HoverPreview.HoverDuration, () => { var hoveredItem = Utils.FindPointedListViewItem(BookmarkList); if (hoveredItem?.DataContext is Bookmark bookmark) { return PreviewPopupArgs.ForDocument(Document, bookmark.Element, BookmarkList, $"Bookmark {bookmark.Text}"); } return null; }); } private void TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e) { var textBox = e.OriginalSource as TextBox; textBox?.SelectAll(); } private void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { if (sender is TextBox textbox && !textbox.IsKeyboardFocusWithin) { if (e.OriginalSource.GetType().Name == "TextBoxView") { e.Handled = true; textbox.Focus(); } } } private void CheckBox_Checked(object sender, RoutedEventArgs e) { var bookmark = ((CheckBox)sender).DataContext as Bookmark; Document.BookmarkInfoChanged(bookmark); } private void CheckBox_Unchecked(object sender, RoutedEventArgs e) { var bookmark = ((CheckBox)sender).DataContext as Bookmark; Document.BookmarkInfoChanged(bookmark); } private void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var bookmark = ((ListViewItem)sender).DataContext as Bookmark; Document.JumpToBookmark(bookmark); bookmarks_.Refresh(); } private void JumpToBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { var bookmark = e.Parameter as Bookmark; Document.JumpToBookmark(bookmark); bookmarks_.Refresh(); } private void RemoveBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { var bookmark = e.Parameter as Bookmark; Document.RemoveBookmark(bookmark); bookmarks_.Refresh(); } private void RemoveAllBookmarksExecuted(object sender, ExecutedRoutedEventArgs e) { Document.RemoveAllBookmarks(); bookmarks_.Refresh(); } private void MarkBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { SetSelectedBookmarkStyle(Utils.GetSelectedColorStyle(e.Parameter as SelectedColorEventArgs, ColorPens.GetPen(Colors.Silver))); } private void UnmarkBookmarkExecuted(object sender, ExecutedRoutedEventArgs e) { SetSelectedBookmarkStyle(null); } private void SetSelectedBookmarkStyle(HighlightingStyle style) { if (!(BookmarkList.SelectedItem is Bookmark bookmark)) { return; } bookmark.Style = style; Document.BookmarkInfoChanged(bookmark); bookmarks_.Refresh(); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } public override async Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document) { InitializeForDocument(document); IsPanelEnabled = Document != null; } public override async Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { ResetBookmarks(); } private void ResetBookmarks() { bookmarks_ = new ObservableCollectionRefresh(); BookmarkList.ItemsSource = bookmarks_; } public override void OnSessionEnd() { base.OnSessionEnd(); ResetBookmarks(); } } ================================================ FILE: src/ProfileExplorerUI/Panels/CallGraphPanel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using ProfileExplorer.Core.Session; namespace ProfileExplorer.UI; public class CallGraphPanel : GraphPanel { public CallGraphPanel() { } public CallGraphPanel(IUISession session) { Session = session; } public override ToolPanelKind PanelKind => ToolPanelKind.CallGraph; } ================================================ FILE: src/ProfileExplorerUI/Panels/CallerCalleePanel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.UI.Profile; public class CallerCalleePanel : CallTreePanel { public CallerCalleePanel() { } public CallerCalleePanel(IUISession session) { Session = session; } public override ToolPanelKind PanelKind => ToolPanelKind.CallerCallee; } ================================================ FILE: src/ProfileExplorerUI/Panels/DefinitionPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/DefinitionPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI; public class DefinitionPanelState { public int CaretOffset; public IRElement DefinedOperand; public bool HasPinnedContent; public double HorizontalOffset; public double VerticalOffset; } public partial class DefinitionPanel : ToolPanelControl { private IRElement definedOperand_; private CancelableTaskInstance loadTask_; public DefinitionPanel() { InitializeComponent(); loadTask_ = new CancelableTaskInstance(false); } public override ToolPanelKind PanelKind => ToolPanelKind.Definition; public override HandledEventKind HandledEvents => HandledEventKind.ElementSelection; public override bool HasPinnedContent { get => FixedToolbar.IsPinned; set => FixedToolbar.IsPinned = value; } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private void PanelToolbarTray_DuplicateClicked(object sender, DuplicateEventArgs e) { Session.DuplicatePanel(this, e.Kind); } private void PanelToolbarTray_PinnedChanged(object sender, PinEventArgs e) { HasPinnedContent = e.IsPinned; } public override void OnElementSelected(IRElementEventArgs e) { SwitchSelectedElement(e.Element, e.Document); } private void SwitchSelectedElement(IRElement element, IRDocument document) { if (HasPinnedContent) { return; } if (Document == null || !(element is OperandIR op)) { return; } if (op.IsLabelAddress) { SwitchDefinitionElement(op, op.BlockLabelValue); return; } var refFinder = DocumentUtils.CreateReferenceFinder(Document.Function, Session, App.Settings.DocumentSettings); var defOp = refFinder.FindSingleDefinition(element); if (defOp != null && defOp != op) { SwitchDefinitionElement(op, defOp); return; } SymbolName.Text = ""; } private void SwitchDefinitionElement(OperandIR op, IRElement defOp) { //? TODO: Go through the NameProvider SymbolName.Text = op.GetText(Document.SectionText).ToString(); TextView.MarkElementWithDefaultStyle(defOp); TextView.BringElementIntoView(defOp); definedOperand_ = op; } public override async Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (TextView.Section == section) { return; } await TextView.InitializeFromDocument(document, false, null, false); Document = document; if (Session.LoadPanelState(this, section, document) is DefinitionPanelState savedState) { SwitchSelectedElement(savedState.DefinedOperand, document); TextView.SetCaretAtOffset(savedState.CaretOffset); TextView.ScrollToHorizontalOffset(savedState.HorizontalOffset); TextView.ScrollToVerticalOffset(savedState.VerticalOffset); HasPinnedContent = savedState.HasPinnedContent; } else { TextView.SetCaretAtOffset(0); TextView.ScrollToHorizontalOffset(0); TextView.ScrollToVerticalOffset(0); HasPinnedContent = false; } } public override async Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (TextView.Section != section) { return; } if (definedOperand_ != null) { var savedState = new DefinitionPanelState(); savedState.DefinedOperand = definedOperand_; savedState.VerticalOffset = TextView.VerticalOffset; savedState.HorizontalOffset = TextView.HorizontalOffset; savedState.CaretOffset = TextView.CaretOffset; savedState.HasPinnedContent = HasPinnedContent; Session.SavePanelState(savedState, this, section, Document); ResetDefinedOperand(); } TextView.UnloadDocument(); Document = null; } private void ResetDefinedOperand() { definedOperand_ = null; SymbolName.Text = ""; } public override void OnSessionEnd() { base.OnSessionEnd(); ResetDefinedOperand(); TextView.UnloadDocument(); } public override async void ClonePanel(IToolPanel sourcePanel) { var defPanel = sourcePanel as DefinitionPanel; await TextView.InitializeFromDocument(defPanel.TextView); } } ================================================ FILE: src/ProfileExplorerUI/Panels/DeveloperPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/DeveloperPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using System.IO; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Parser; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI; public partial class DeveloperPanel : ToolPanelControl { private DispatcherTimer logFileTimer_; private string previousLogFileText_; public DeveloperPanel() { InitializeComponent(); } public override ToolPanelKind PanelKind => ToolPanelKind.Developer; public override HandledEventKind HandledEvents => HandledEventKind.ElementSelection; private async void Button_Click(object sender, RoutedEventArgs e) { ErrorList.Visibility = Visibility.Collapsed; TextView.Visibility = Visibility.Visible; if (Session.CurrentDocument != null) { var printer = new IRPrinter(Session.CurrentDocument.Function); await TextView.SetText(printer.Print(), Utils.LoadSyntaxHighlightingFile(App.GetInternalIRSyntaxHighlightingFilePath())); } else { await TextView.SetText("No document opened"); } } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async void Button_Click_1(object sender, RoutedEventArgs e) { ErrorList.Visibility = Visibility.Visible; TextView.Visibility = Visibility.Collapsed; if (Session.CurrentDocument != null) { var section = Session.CurrentDocument.Section; var loader = Session.SessionState.FindLoadedDocument(section).Loader; var loadedSection = loader.TryGetLoadedSection(section); if (loadedSection != null && loadedSection.HadParsingErrors) { ErrorList.ItemsSource = loadedSection.ParsingErrors; } else { ErrorList.ItemsSource = null; } } else { await TextView.SetText("No document opened"); } } private void ErrorList_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 1) { var error = e.AddedItems[0] as IRParsingError; var document = Session.FindAssociatedDocument(this); document.MarkTextRange(error.Location.Offset, 1, Colors.IndianRed); document.SetCaretAtOffset(error.Location.Offset); document.BringTextOffsetIntoView(error.Location.Offset); } } public override async void OnElementSelected(IRElementEventArgs e) { var builder = new StringBuilder(); builder.AppendLine(e.Element.ToString()); if (e.Element.Tags != null) { builder.AppendLine($"{e.Element.Tags.Count} tags:"); foreach (var tag in e.Element.Tags) { builder.AppendLine($" - {tag.ToString().Indent(4)}"); } } await TextView.SetText(builder.ToString()); } private async void ButtonBase_OnClick(object sender, RoutedEventArgs e) { ErrorList.Visibility = Visibility.Collapsed; TextView.Visibility = Visibility.Visible; await ReloadLogFile(); } private async Task ReloadLogFile() { string traceFile = App.GetTraceFilePath(); if (File.Exists(traceFile)) { try { Trace.Flush(); using var stream = new FileStream(traceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using var streamReader = new StreamReader(stream); string text = await streamReader.ReadToEndAsync(); if (text != previousLogFileText_) { await TextView.SetText(text); TextView.ScrollToEnd(); previousLogFileText_ = text; } } catch (Exception ex) { await TextView.SetText($"Failed to load log file: {ex.Message}"); } } } private async void ToggleButton_OnChecked(object sender, RoutedEventArgs e) { StopLogFileTimer(); logFileTimer_ = new DispatcherTimer(); logFileTimer_.Interval = TimeSpan.FromMilliseconds(500); logFileTimer_.Tick += async (o, args) => await ReloadLogFile(); logFileTimer_.Start(); } private void ToggleButton_OnUnchecked(object sender, RoutedEventArgs e) { StopLogFileTimer(); } private void StopLogFileTimer() { if (logFileTimer_ != null) { logFileTimer_.Stop(); logFileTimer_ = null; } } public override void OnSessionStart() { base.OnSessionStart(); TextView.Session = Session; } } ================================================ FILE: src/ProfileExplorerUI/Panels/DocumentSearchPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/DocumentSearchPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using ProfileExplorer.Core; using ProfileExplorer.Core.Session; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.Utilities; using ProfileExplorerUI.Session; namespace ProfileExplorer.UI.Panels; public partial class DocumentSearchPanel : DraggablePopup { private IUISession session_; private ILoadedDocument document_; private CancelableTask searchTask_; private SearchInfo searchInfo_; private DocumentSearchInfo data_; public DocumentSearchPanel(Point position, double width, double height, UIElement referenceElement, IUISession session, ILoadedDocument document) { InitializeComponent(); Initialize(position, width, height, referenceElement); PanelResizeGrip.ResizedControl = this; data_ = new DocumentSearchInfo(); DataContext = data_; session_ = session; document_ = document; SetupSearchPanel(); SetupResultsPanel(); } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public override bool ShouldStartDragging(MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && SearchPanelHost.IsMouseOver) { DetachPanel(); return true; } return false; } private void SetupResultsPanel() { ResultsPanel.HideToolbarTray = true; ResultsPanel.HideSearchedText = true; ResultsPanel.OpenSection += ResultsPanel_OpenSection; } private void SetupSearchPanel() { searchInfo_ = new SearchInfo { ShowSearchAllButton = false, ShowNavigationSection = false }; SearchPanel.SearchChanged += SearchPanel_SearchChanged; SearchPanel.Show(searchInfo_); } private async void ResultsPanel_OpenSection(object sender, OpenSectionEventArgs e) { await session_.SwitchDocumentSectionAsync(e); } private async void SearchPanel_SearchChanged(object sender, SearchInfo e) { string searchedText = e.SearchedText; if (searchedText.Length < 2) { ResultsPanel.ClearSearchResults(); ResultsPanel.OptionalText = ""; return; } var results = await UpdateSearchPanel(searchedText); if (results != null) { // Update UI if search was not cancelled. ResultsPanel.Session = session_; ResultsPanel.UpdateSearchResults(results, new SearchInfo()); // Update result details. var functions = new HashSet(); int sectionCount = 0; foreach (var result in results) { if (result.Results.Count > 0) { sectionCount++; functions.Add(result.Section.ParentFunction); } } ResultsPanel.OptionalText = $"Functions: {functions.Count} Sections: {sectionCount}"; } } private async Task> UpdateSearchPanel(string searchedText) { // Create a task that can be used later to cancel the search // if another letter is being pressed. var searchTask = new CancelableTask(); lock (this) { if (searchTask_ != null) { searchTask_.Cancel(); } searchTask_ = searchTask; } var docInfo = document_; var searcherOptions = new SectionTextSearcherOptions { SearchBeforeOutput = false, KeepSectionText = false, // Reduces memory usage for large files. UseRawSectionText = true // Speeds up reading large sections. }; var searcher = new SectionTextSearcher(docInfo.Loader, searcherOptions); var list = new List(); foreach (var func in docInfo.Summary.Functions) { list.AddRange(func.Sections); } // Start the search on another thread., var results = await searcher.SearchAsync(searchedText, searchInfo_.SearchKind, list, searchTask_); if (searchTask.IsCanceled) { return null; } searchTask.Complete(); lock (this) { if (searchTask_ == searchTask) { searchTask_ = null; } } return results; } private void DetachPanel() { if (IsDetached) { return; } DetachPopup(); StaysOpen = true; data_.IsPanelDetached = true; } private void PinPanelButton_Click(object sender, RoutedEventArgs e) { DetachPanel(); } private void ClosePanelButton_Click(object sender, RoutedEventArgs e) { ClosePopup(); } private class DocumentSearchInfo : INotifyPropertyChanged { private bool panelDetached_; public int FunctionCount { get; set; } public int SectionCount { get; set; } public int InstanceCount { get; set; } public long Duration { get; set; } public bool IsPanelDetached { get => panelDetached_; set { if (panelDetached_ != value) { panelDetached_ = value; NotifyPropertyChanged(nameof(IsPanelDetached)); } } } public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ================================================ FILE: src/ProfileExplorerUI/Panels/DominatorTreePanel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.UI; public class DominatorTreePanel : GraphPanel { public override ToolPanelKind PanelKind => ToolPanelKind.DominatorTree; } ================================================ FILE: src/ProfileExplorerUI/Panels/ExpressionGraphPanel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. namespace ProfileExplorer.UI; public class ExpressionGraphPanel : GraphPanel { public override ToolPanelKind PanelKind => ToolPanelKind.ExpressionGraph; } ================================================ FILE: src/ProfileExplorerUI/Panels/FunctionCodeStatistics.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.UI; public class FunctionCodeStatistics { public long Size { get; set; } public int Instructions { get; set; } public int Loads { get; set; } public int Stores { get; set; } public int Branches { get; set; } public int Calls { get; set; } public int Callers { get; set; } public int IndirectCalls { get; set; } public int Callees { get; set; } public int OpcodeHash { get; set; } public static FunctionCodeStatistics Compute(FunctionIR function, ICompilerIRInfo irInfo) { var stats = new FunctionCodeStatistics(); var metadataTag = function.GetTag(); if (metadataTag != null) { stats.Size = metadataTag.FunctionSize; } foreach (var instr in function.AllInstructions) { stats.Instructions++; //? TODO: Add hash for branch targets, other diff registers, etc - configurable with options if (instr.Opcode != null) { stats.OpcodeHash = HashCode.Combine(stats.OpcodeHash, instr.Opcode.GetHashCode()); } else if (!instr.OpcodeText.IsEmpty) { stats.OpcodeHash = HashCode.Combine(stats.OpcodeHash, instr.OpcodeText.ToString().GetHashCode()); } if (instr.IsBranch || instr.IsGoto || instr.IsSwitch) { stats.Branches++; } if (irInfo.IsLoadInstruction(instr)) { stats.Loads++; } if (irInfo.IsStoreInstruction(instr)) { stats.Stores++; } if (irInfo.IsCallInstruction(instr)) { if (irInfo.GetCallTarget(instr) == null) { stats.IndirectCalls++; } stats.Calls++; } } return stats; } public bool ComputeDiff(FunctionCodeStatistics other) { Size = other.Size - Size; Instructions = other.Instructions - Instructions; Loads = other.Loads - Loads; Stores = other.Stores - Stores; Branches = other.Branches - Branches; Calls = other.Calls - Calls; Callers = other.Callers - Callers; IndirectCalls = other.IndirectCalls - IndirectCalls; Callees = other.Callees - Callees; return Size != 0 || Instructions != 0 || Loads != 0 || Stores != 0 || Branches != 0 || Calls != 0 || Callers != 0 || IndirectCalls != 0 || Callees != 0; } public void Add(FunctionCodeStatistics other) { Size = other.Size + Size; Instructions = other.Instructions + Instructions; Loads = other.Loads + Loads; Stores = other.Stores + Stores; Branches = other.Branches + Branches; Calls = other.Calls + Calls; Callers = other.Callers + Callers; IndirectCalls = other.IndirectCalls + IndirectCalls; Callees = other.Callees + Callees; OpcodeHash = HashCode.Combine(OpcodeHash, other.OpcodeHash); } public override string ToString() { return $"Size: {Size}\n" + $"Instructions: {Instructions}\n" + $"Loads: {Loads}\n" + $"Stores: {Stores}\n" + $"Branches: {Branches}\n" + $"Calls: {Calls}\n" + $"Callers: {Callers}\n" + $"IndirectCalls: {IndirectCalls}\n" + $"Callees: {Callees}"; } } ================================================ FILE: src/ProfileExplorerUI/Panels/GraphCommand.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows.Input; namespace ProfileExplorer.UI; public static class GraphCommand { public static readonly RoutedCommand GraphFitWidth = new("GraphFitWidth", typeof(GraphPanel)); public static readonly RoutedCommand GraphResetWidth = new("GraphResetWidth", typeof(GraphPanel)); public static readonly RoutedCommand GraphFitAll = new("GraphFitAll", typeof(GraphPanel)); public static readonly RoutedCommand GraphZoomIn = new("GraphZoomIn", typeof(GraphPanel)); public static readonly RoutedCommand GraphZoomOut = new("GraphZoomOut", typeof(GraphPanel)); public static readonly RoutedCommand MarkBlock = new("MarkBlock", typeof(GraphPanel)); public static readonly RoutedCommand MarkPredecessors = new("MarkPredecessors", typeof(GraphPanel)); public static readonly RoutedCommand MarkSuccessors = new("MarkSuccessors", typeof(GraphPanel)); public static readonly RoutedCommand MarkGroup = new("MarkGroup", typeof(GraphPanel)); public static readonly RoutedCommand MarkLoop = new("MarkLoop", typeof(GraphPanel)); public static readonly RoutedCommand MarkLoopNest = new("MarkLoopNest", typeof(GraphPanel)); public static readonly RoutedCommand MarkDominators = new("MarkDominators", typeof(GraphPanel)); public static readonly RoutedCommand MarkPostDominators = new("MarkPostDominators", typeof(GraphPanel)); public static readonly RoutedCommand MarkDominanceFrontier = new("MarkDominanceFrontier", typeof(GraphPanel)); public static readonly RoutedCommand MarkPostDominanceFrontier = new("MarkPostDominanceFrontier", typeof(GraphPanel)); public static readonly RoutedCommand ClearMarked = new("ClearMarked", typeof(GraphPanel)); public static readonly RoutedCommand ClearAllMarked = new("ClearAllMarked", typeof(GraphPanel)); public static readonly RoutedCommand SelectQueryBlock1 = new("SelectQueryBlock1", typeof(GraphPanel)); public static readonly RoutedCommand SelectQueryBlock2 = new("SelectQueryBlock2", typeof(GraphPanel)); public static readonly RoutedCommand SwapQueryBlocks = new("SwapQueryBlocks", typeof(GraphPanel)); public static readonly RoutedCommand CloseQueryPanel = new("CloseQueryPanel", typeof(GraphPanel)); public static readonly RoutedCommand ShowReachablePath = new("ShowReachablePath", typeof(GraphPanel)); } ================================================ FILE: src/ProfileExplorerUI/Panels/GraphPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/GraphPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Diagnostics; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Graph; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Panels; using ProtoBuf; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.IR.Tags; namespace ProfileExplorer.UI; // ScrollViewer that ignores click events so they get passed // to the hosted control, allowing for dragging the graphs for ex. public class ScrollViewerClickable : ScrollViewer { protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { Keyboard.Focus(this); } protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { } protected override void OnMouseRightButtonDown(MouseButtonEventArgs e) { Keyboard.Focus(this); } protected override void OnMouseRightButtonUp(MouseButtonEventArgs e) { } } [ProtoContract] public class GraphPanelState { [ProtoMember(3)] public double HorizontalOffset; [ProtoMember(2)] public double VerticalOffset; [ProtoMember(1)] public double ZoomLevel; } public partial class GraphPanel : ToolPanelControl { private const double FastPanOffset = 80; private const double FastZoomFactor = 4; private const double MaxZoomLevel = 2.0; private const double MinZoomLevel = 0.25; private const double PanOffset = 20; private const double ZoomAdjustment = 0.05; private const double HorizontalViewMargin = 50; private const double VerticalViewMargin = 100; private bool delayFitSize_; private bool delayRestoreState_; private bool dragging_; private Point draggingStart_; private Point draggingViewStart_; private Graph graph_; private OptionsPanelHostPopup optionsPanelPopup_; private GraphNode hoveredNode_; private bool ignoreNextHover_; private CancelableTaskInstance loadTask_; private IRDocumentPopup previewPopup_; private GraphQueryInfo queryInfo_; private bool queryPanelVisible_; private DelayedAction removeHoveredAction_; private bool restoredState_; public GraphPanel() { InitializeComponent(); GraphViewer.HostPanel = this; GraphViewer.MaxZoomLevel = MaxZoomLevel; SetupEvents(); //? TODO: No context menu for expr graph yet, don't show CFG one. if (PanelKind == ToolPanelKind.ExpressionGraph) { GraphViewer.ContextMenu = null; } SetupCommands(); } public IRElement SelectedElement { get => GraphViewer.SelectedElement; set { GraphViewer.SelectElement(value); if (!HasPinnedContent && Settings.BringNodesIntoView) { BringIntoView(value); } } } public IRTextSection Section => Document?.Section; public override ToolPanelKind PanelKind => ToolPanelKind.FlowGraph; public override HandledEventKind HandledEvents => HandledEventKind.ElementSelection | HandledEventKind.ElementHighlighting; public GraphSettings Settings => PanelKind == ToolPanelKind.ExpressionGraph ? App.Settings.ExpressionGraphSettings : App.Settings.FlowGraphSettings; public void BringIntoView(IRElement element) { var node = GraphViewer.FindElementNode(element); if (node == null) { return; } var position = GraphViewer.GetNodePosition(node); double offsetX = GraphHost.HorizontalOffset; double offsetY = GraphHost.VerticalOffset; if (position.X < offsetX || position.X > offsetX + GraphHost.ActualWidth) { GraphHost.ScrollToHorizontalOffset(Math.Max(0, position.X - HorizontalViewMargin)); } if (position.Y < offsetY || position.Y > offsetY + GraphHost.ActualHeight) { GraphHost.ScrollToVerticalOffset(Math.Max(0, position.Y - VerticalViewMargin)); } } public void DisplayGraph(Graph graph) { graph_ = graph; GraphViewer.ShowGraph(graph, Session.CompilerInfo); FitGraphIntoView(); if (delayRestoreState_) { Dispatcher.BeginInvoke(() => LoadSavedState(), DispatcherPriority.Render); } HasPinnedContent = false; EnablePanel(); } public void HideGraph() { if (graph_ == null) { return; } GraphViewer.HideGraph(); Document = null; graph_ = null; hoveredNode_ = null; DisablePanel(); } private void Highlight(IRHighlightingEventArgs info) { if (!Settings.SyncMarkedNodes && info.Type == HighlighingType.Marked) { return; } GraphViewer.Highlight(info); } public void InitializeFromDocument(IRDocument document) { #if DEBUG Trace.TraceInformation( $"Graph panel {ObjectTracker.Track(this)}: initialize with doc {ObjectTracker.Track(document)}"); #endif Document = document; } public async Task OnGenerateGraphStart(IRTextSection section) { var animation = new DoubleAnimation(0.25, TimeSpan.FromSeconds(0.5)); animation.BeginTime = TimeSpan.FromSeconds(1); GraphViewer.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); LongOperationView.Opacity = 0.0; LongOperationView.Visibility = Visibility.Visible; var animation2 = new DoubleAnimation(1.0, TimeSpan.FromSeconds(0.5)); animation2.BeginTime = TimeSpan.FromSeconds(2); LongOperationView.BeginAnimation(OpacityProperty, animation2, HandoffBehavior.SnapshotAndReplace); return await CreateGraphLoadTask(); } public void OnGenerateGraphDone(CancelableTask task, bool failed = false) { if (!failed) { GraphHost.ScrollToHorizontalOffset(0); GraphHost.ScrollToVerticalOffset(0); var animation = new DoubleAnimation(1.0, TimeSpan.FromSeconds(0.2)); GraphViewer.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); } var animation2 = new DoubleAnimation(0, TimeSpan.FromSeconds(0.2)); animation2.Completed += Animation2_Completed; LongOperationView.BeginAnimation(OpacityProperty, animation2, HandoffBehavior.SnapshotAndReplace); CompleteGraphLoadTask(task); } public void RemoveHighlighting(IRElement element) { var node = GraphViewer.FindElementNode(element); if (node != null) { GraphViewer.ResetMarkedNode(node, element); } } public void RemoveAllHighlighting(HighlighingType type) { GraphViewer.ResetHighlightedNodes(type); } private void SetupEvents() { GraphViewer.BlockSelected += GraphViewer_BlockSelected; PreviewMouseWheel += GraphPanel_PreviewMouseWheel; PreviewMouseLeftButtonDown += GraphPanel_PreviewMouseLeftButtonDown; PreviewMouseRightButtonDown += GraphPanel_PreviewMouseRightButtonDown; MouseLeftButtonDown += GraphPanel_MouseLeftButtonDown; MouseLeftButtonUp += GraphPanel_MouseLeftButtonUp; MouseMove += GraphPanel_MouseMove; MouseLeave += GraphPanel_MouseLeave; PreviewKeyDown += GraphPanel_PreviewKeyDown; GraphHost.ScrollChanged += GraphHost_ScrollChanged; var hover = new MouseHoverLogic(this); hover.MouseHover += Hover_MouseHover; hover.MouseHoverStopped += Hover_MouseHoverStopped; } private void GraphPanel_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var position = e.GetPosition(GraphViewer); hoveredNode_ = GraphViewer.FindPointedNode(position); if (hoveredNode_ != null) { // Select A/B nodes in the query panel. if (Keyboard.IsKeyDown(Key.A) || Keyboard.IsKeyDown(Key.NumPad1) || Keyboard.IsKeyDown(Key.D1)) { SelectQueryBlock1Executed(this, null); e.Handled = true; return; } if (Keyboard.IsKeyDown(Key.B) || Keyboard.IsKeyDown(Key.NumPad2) || Keyboard.IsKeyDown(Key.D2)) { SelectQueryBlock2Executed(this, null); e.Handled = true; return; } Focus(); } else { GraphViewer.ResetHighlightedNodes(HighlighingType.Selected); GraphViewer.ResetHighlightedNodes(HighlighingType.Hovered); } } private void GraphPanel_PreviewMouseRightButtonDown(object sender, MouseButtonEventArgs e) { hoveredNode_ = GraphViewer.FindPointedNode(e.GetPosition(GraphViewer)); if (hoveredNode_ != null) { Focus(); } } private void FitGraphIntoView() { var viewBounds = GetGraphBounds(); if (Math.Abs(viewBounds.Width) < double.Epsilon || Math.Abs(viewBounds.Height) < double.Epsilon) { // Panel is not visible, set the graph size when it becomes visible. delayFitSize_ = true; } else if (!restoredState_) { GraphViewer.FitWidthToSize(viewBounds); delayFitSize_ = false; } } private Size GetGraphBounds() { return new Size(Math.Max(0, RenderSize.Width - SystemParameters.VerticalScrollBarWidth), RenderSize.Height); } private async Task CreateGraphLoadTask() { return await loadTask_.CancelCurrentAndCreateTaskAsync(); } private void CompleteGraphLoadTask(CancelableTask task) { loadTask_.CompleteTask(); } private void AddCommand(RoutedCommand command, ExecutedRoutedEventHandler handler) { var binding = new CommandBinding(command); binding.Executed += handler; CommandBindings.Add(binding); } private void AdjustZoom(double value) { if (Utils.IsShiftModifierActive()) { value *= FastZoomFactor; } SetZoom(GraphViewer.ZoomLevel + value); } private void Animation2_Completed(object sender, EventArgs e) { LongOperationView.Visibility = Visibility.Collapsed; } private Size AvailableGraphSize() { return new Size(GraphHost.RenderSize.Width - SystemParameters.VerticalScrollBarWidth - SystemParameters.BorderWidth * 2, GraphHost.RenderSize.Height); } private void Button_MouseDown(object sender, MouseButtonEventArgs e) { AdjustZoom(-ZoomAdjustment); } private void Button_MouseDown_1(object sender, MouseButtonEventArgs e) { AdjustZoom(ZoomAdjustment); } private void ClearAllMarkedExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.ResetAllMarkedNodes(); } private void ClearMarkedExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.ResetSelectedNode(); } private void ExecuteGraphFitAll(object sender, ExecutedRoutedEventArgs e) { GraphViewer.FitToSize(AvailableGraphSize()); } private void ExecuteGraphFitWidth(object sender, ExecutedRoutedEventArgs e) { GraphViewer.FitWidthToSize(AvailableGraphSize()); } private void ExecuteGraphResetWidth(object sender, ExecutedRoutedEventArgs e) { GraphViewer.ZoomLevel = 1; } private void ExecuteGraphZoomIn(object sender, ExecutedRoutedEventArgs e) { AdjustZoom(ZoomAdjustment); } private void ExecuteGraphZoomOut(object sender, ExecutedRoutedEventArgs e) { AdjustZoom(-ZoomAdjustment); } private double GetPanOffset() { return Utils.IsKeyboardModifierActive() ? FastPanOffset : PanOffset; } private HighlightingStyle GetSelectedColorStyle(ExecutedRoutedEventArgs e) { return Utils.GetSelectedColorStyle(e.Parameter as SelectedColorEventArgs, GraphViewer.DefaultBoldPen); } private void GraphHost_ScrollChanged(object sender, ScrollChangedEventArgs e) { HidePreviewPopup(); } private void GraphPanel_MouseLeave(object sender, MouseEventArgs e) { HidePreviewPopupDelayed(); } private void GraphPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // Start dragging the graph only if the click starts inside the scroll area, // excluding the scroll bars, and it in an empty spot. var point = e.GetPosition(GraphHost); Focus(); if (point.X < 0 || point.Y < 0 || point.X >= GraphHost.ViewportWidth || point.Y >= GraphHost.ViewportHeight) { return; } //? TODO: Also don't handle if over query panel var pointedNode = GraphViewer.FindPointedNode(e.GetPosition(GraphViewer)); if (pointedNode != null) { return; } StartMouseDragging(e); e.Handled = true; } private void StartMouseDragging(MouseButtonEventArgs e) { HidePreviewPopup(); dragging_ = true; draggingStart_ = e.GetPosition(GraphHost); draggingViewStart_ = new Point(GraphHost.HorizontalOffset, GraphHost.VerticalOffset); Cursor = Cursors.SizeAll; CaptureMouse(); } private void GraphPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (dragging_) { dragging_ = false; Cursor = Cursors.Arrow; ReleaseMouseCapture(); e.Handled = true; } } private void GraphPanel_MouseMove(object sender, MouseEventArgs e) { if (dragging_) { var offset = draggingViewStart_ - (e.GetPosition(GraphHost) - draggingStart_); GraphHost.ScrollToHorizontalOffset(offset.X); GraphHost.ScrollToVerticalOffset(offset.Y); e.Handled = true; } } private void GraphPanel_PreviewKeyDown(object sender, KeyEventArgs e) { double offsetX = GraphHost.HorizontalOffset; double offsetY = GraphHost.VerticalOffset; switch (e.Key) { case Key.Right: { offsetX += GetPanOffset(); e.Handled = true; break; } case Key.Left: { offsetX -= GetPanOffset(); e.Handled = true; break; } case Key.Up: { offsetY -= GetPanOffset(); e.Handled = true; break; } case Key.Down: { offsetY += GetPanOffset(); e.Handled = true; break; } case Key.OemPlus: case Key.Add: { if (Utils.IsControlModifierActive()) { AdjustZoom(ZoomAdjustment); e.Handled = true; } return; } case Key.OemMinus: case Key.Subtract: { if (Utils.IsControlModifierActive()) { e.Handled = true; AdjustZoom(-ZoomAdjustment); } return; } } if (e.Handled) { HidePreviewPopup(); GraphHost.ScrollToHorizontalOffset(offsetX); GraphHost.ScrollToVerticalOffset(offsetY); } } private void GraphPanel_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { if (!Utils.IsKeyboardModifierActive()) { return; } SetZoom(GraphViewer.ZoomLevel * Math.Abs(1 + e.Delta / 1000.0)); e.Handled = true; } private void GraphViewer_BlockSelected(object sender, IRElementEventArgs e) { ignoreNextHover_ = true; } private void HidePreviewPopup(bool force = false) { if (previewPopup_ != null && (force || !previewPopup_.IsMouseOver)) { previewPopup_.ClosePopup(); previewPopup_ = null; } } private async void Hover_MouseHover(object sender, MouseEventArgs e) { if (!Settings.ShowPreviewPopup || Settings.ShowPreviewPopupWithModifier && !Utils.IsKeyboardModifierActive()) { return; } if (ignoreNextHover_) { // Don't show the block preview if the user jumped to it. ignoreNextHover_ = false; return; } var node = GraphViewer.FindPointedNode(e.GetPosition(GraphViewer)); if (node?.NodeInfo.ElementData != null) { await ShowPreviewPopup(node); hoveredNode_ = node; } } private void Hover_MouseHoverStopped(object sender, MouseEventArgs e) { HidePreviewPopupDelayed(); } private void HidePreviewPopupDelayed() { removeHoveredAction_ = DelayedAction.StartNew(() => { if (removeHoveredAction_ != null) { removeHoveredAction_ = null; HidePreviewPopup(); } }); ignoreNextHover_ = false; } private void MarkBlockExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.MarkSelectedNode(GetSelectedColorStyle(e)); } private void MarkGroupExecuted(object sender, ExecutedRoutedEventArgs e) { var style = GetSelectedColorStyle(e); GraphViewer.MarkSelectedNode(style); GraphViewer.MarkSelectedNodeSuccessors(style); GraphViewer.MarkSelectedNodePredecessors(style); } private void MarkLoopExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.MarkSelectedNodeLoop(GetSelectedColorStyle(e)); } private void MarkLoopNestExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.MarkSelectedNodeLoopNest(GetSelectedColorStyle(e)); } private void MarkPredecessorsExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.MarkSelectedNodePredecessors(GetSelectedColorStyle(e)); } private void MarkSuccessorsExecuted(object sender, ExecutedRoutedEventArgs e) { GraphViewer.MarkSelectedNodeSuccessors(GetSelectedColorStyle(e)); } private async void MarkDominatorsExecuted(object sender, ExecutedRoutedEventArgs e) { await GraphViewer.MarkSelectedNodeDominatorsAsync(GetSelectedColorStyle(e)).ConfigureAwait(true); } private async void MarkPostDominatorsExecuted(object sender, ExecutedRoutedEventArgs e) { await GraphViewer.MarkSelectedNodePostDominatorsAsync(GetSelectedColorStyle(e)).ConfigureAwait(true); } private async void MarkDominanceFrontierExecuted(object sender, ExecutedRoutedEventArgs e) { await GraphViewer.MarkSelectedNodeDominanceFrontierAsync(GetSelectedColorStyle(e)).ConfigureAwait(true); } private async void MarkPostDominanceFrontierExecuted(object sender, ExecutedRoutedEventArgs e) { await GraphViewer.MarkSelectedNodePostDominanceFrontierAsync(GetSelectedColorStyle(e)).ConfigureAwait(true); } private void SelectQueryBlock1Executed(object sender, ExecutedRoutedEventArgs e) { if (hoveredNode_ != null) { if (hoveredNode_.NodeInfo.ElementData is BlockIR block) { SetQueryBlock1(block); } } } private void SelectQueryBlock2Executed(object sender, ExecutedRoutedEventArgs e) { if (hoveredNode_ != null) { if (hoveredNode_.NodeInfo.ElementData is BlockIR block) { SetQueryBlock2(block); } } } private async void SwapQueryBlocksExecuted(object sender, ExecutedRoutedEventArgs e) { if (!queryPanelVisible_) { return; } queryInfo_.SwapBlocks(); await UpdateQueryResult(); } private void CloseQueryPanelExecuted(object sender, ExecutedRoutedEventArgs e) { HideQueryPanel(); } private async void ShowReachablePathExecuted(object sender, ExecutedRoutedEventArgs e) { if (queryPanelVisible_ && queryInfo_.Reaches) { var cache = FunctionAnalysisCache.Get(Document.Function); var pathBlocks = (await cache.GetReachabilityAsync()).FindPath(queryInfo_.Block1, queryInfo_.Block2); foreach (var block in pathBlocks) { GraphViewer.Mark(block, Colors.Gold); } } } private void PanelToolbarTray_DuplicateClicked(object sender, DuplicateEventArgs e) { Session.DuplicatePanel(this, e.Kind); } private void PanelToolbarTray_PinnedChanged(object sender, PinEventArgs e) { HasPinnedContent = e.IsPinned; } private void PanelToolbarTray_SettingsClicked(object sender, EventArgs e) { ShowOptionsPanel(); } private async void SetQueryBlock1(BlockIR block) { ShowQueryPanel(); if (queryInfo_.Block1 != block) { queryInfo_.Block1 = block; queryInfo_.Block1Name = Utils.MakeBlockDescription(block); await UpdateQueryResult(); } } private async void SetQueryBlock2(BlockIR block) { ShowQueryPanel(); if (queryInfo_.Block2 != block) { queryInfo_.Block2 = block; queryInfo_.Block2Name = Utils.MakeBlockDescription(block); await UpdateQueryResult(); } } private async Task UpdateQueryResult() { QueryPanel.DataContext = null; if (queryInfo_.Block1 != null && queryInfo_.Block2 != null) { var cache = FunctionAnalysisCache.Get(Document.Function); await cache.CacheAll(); queryInfo_.Dominates = (await cache.GetDominatorsAsync()).Dominates(queryInfo_.Block1, queryInfo_.Block2); queryInfo_.PostDominates = (await cache.GetPostDominatorsAsync()).Dominates(queryInfo_.Block1, queryInfo_.Block2); queryInfo_.Reaches = (await cache.GetReachabilityAsync()).Reaches(queryInfo_.Block1, queryInfo_.Block2); } QueryPanel.DataContext = queryInfo_; } private void ShowQueryPanel() { if (queryPanelVisible_) { return; } queryInfo_ = new GraphQueryInfo(); QueryPanel.DataContext = queryInfo_; QueryPanel.Visibility = Visibility.Visible; queryPanelVisible_ = true; } private void HideQueryPanel() { if (!queryPanelVisible_) { return; } QueryPanel.DataContext = null; QueryPanel.Visibility = Visibility.Collapsed; queryPanelVisible_ = false; } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } if (PanelKind == ToolPanelKind.ExpressionGraph) { optionsPanelPopup_ = OptionsPanelHostPopup.Create( Settings.Clone(), GraphHost, Session, async (newSettings, commit) => { if (!newSettings.Equals(Settings)) { App.Settings.ExpressionGraphSettings = newSettings; ReloadSettings(); if (commit) { App.SaveApplicationSettings(); } } return newSettings.Clone(); }, () => optionsPanelPopup_ = null); } else { optionsPanelPopup_ = OptionsPanelHostPopup.Create( Settings.Clone(), GraphHost, Session, async (newSettings, commit) => { if (!newSettings.Equals(Settings)) { App.Settings.FlowGraphSettings = newSettings; ReloadSettings(); if (commit) { App.SaveApplicationSettings(); } } return newSettings.Clone(); }, () => optionsPanelPopup_ = null); } } private void SetupCommands() { AddCommand(GraphCommand.MarkBlock, MarkBlockExecuted); AddCommand(GraphCommand.MarkPredecessors, MarkPredecessorsExecuted); AddCommand(GraphCommand.MarkSuccessors, MarkSuccessorsExecuted); AddCommand(GraphCommand.MarkDominators, MarkDominatorsExecuted); AddCommand(GraphCommand.MarkPostDominators, MarkPostDominatorsExecuted); AddCommand(GraphCommand.MarkDominanceFrontier, MarkDominanceFrontierExecuted); AddCommand(GraphCommand.MarkPostDominanceFrontier, MarkPostDominanceFrontierExecuted); AddCommand(GraphCommand.MarkGroup, MarkGroupExecuted); AddCommand(GraphCommand.MarkLoop, MarkLoopExecuted); AddCommand(GraphCommand.MarkLoopNest, MarkLoopNestExecuted); AddCommand(GraphCommand.ClearMarked, ClearMarkedExecuted); AddCommand(GraphCommand.ClearAllMarked, ClearAllMarkedExecuted); AddCommand(GraphCommand.SelectQueryBlock1, SelectQueryBlock1Executed); AddCommand(GraphCommand.SelectQueryBlock2, SelectQueryBlock2Executed); AddCommand(GraphCommand.SwapQueryBlocks, SwapQueryBlocksExecuted); AddCommand(GraphCommand.CloseQueryPanel, CloseQueryPanelExecuted); AddCommand(GraphCommand.ShowReachablePath, ShowReachablePathExecuted); } private void SetZoom(double value) { double currentZoom = GraphViewer.ZoomLevel; double centerX = GraphHost.ViewportWidth / 2; double centerY = GraphHost.ViewportHeight / 2; double offsetX = (GraphHost.HorizontalOffset + centerX) / currentZoom; double offsetY = (GraphHost.VerticalOffset + centerY) / currentZoom; double zoom = value; zoom = Math.Min(Math.Max(MinZoomLevel, zoom), MaxZoomLevel); GraphViewer.ZoomLevel = zoom; UpdateLayout(); GraphHost.ScrollToHorizontalOffset(offsetX * zoom - centerX); GraphHost.ScrollToVerticalOffset(offsetY * zoom - centerY); } private async Task ShowPreviewPopup(GraphNode node) { if (previewPopup_ != null) { if (hoveredNode_ == node) { return; } HidePreviewPopup(); } if (node == null) { return; } if (removeHoveredAction_ != null) { removeHoveredAction_.Cancel(); removeHoveredAction_ = null; } var position = Mouse.GetPosition(GraphHost).AdjustForMouseCursor(); previewPopup_ = await IRDocumentPopup.CreateNew(Document, node.NodeInfo.ElementData, position, GraphHost, App.Settings. GetElementPreviewPopupSettings(ToolPanelKind.FlowGraph), "Block "); previewPopup_.PopupDetached += Popup_PopupDetached; previewPopup_.ShowPopup(); } private void Popup_PopupDetached(object sender, EventArgs e) { var popup = (IRDocumentPopup)sender; if (popup == previewPopup_) { previewPopup_ = null; // Prevent automatic closing. } } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async void CancelButton_Click(object sender, RoutedEventArgs e) { await loadTask_.CancelTaskAndWaitAsync(); } private void QueryPanel_MouseEnter(object sender, MouseEventArgs e) { var animation = new DoubleAnimation(1, TimeSpan.FromSeconds(0.1)); QueryPanel.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); } private void QueryPanel_MouseLeave(object sender, MouseEventArgs e) { var animation = new DoubleAnimation(0.5, TimeSpan.FromSeconds(0.3)); QueryPanel.BeginAnimation(OpacityProperty, animation, HandoffBehavior.SnapshotAndReplace); } private void PanelToolbarTray_BindMenuItemSelected(object sender, BindMenuItem e) { Session.BindToDocument(this, e); } private void PanelToolbarTray_BindMenuOpen(object sender, BindMenuItemsArgs e) { Session.PopulateBindMenu(this, e); } public override void OnRegisterPanel() { IsPanelEnabled = false; ReloadSettings(); } public override void OnRedrawPanel() { GraphViewer.RedrawCurrentGraph(); } public override async Task OnReloadSettings() { ReloadSettings(); } private void ReloadSettings() { GraphViewer.Settings = Settings; GraphHost.Background = ColorBrushes.GetBrush(Settings.BackgroundColor); } public override async Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document) { var previousSection = Document?.Section; InitializeFromDocument(document); if (document.DuringSectionLoading) { #if DEBUG Trace.TraceInformation( $"Graph panel {ObjectTracker.Track(this)}: Ignore graph reload during section switch"); #endif delayRestoreState_ = !restoredState_; return; } //? TODO: Implement switching for expressions if (PanelKind == ToolPanelKind.ExpressionGraph || PanelKind == ToolPanelKind.CallGraph) { HideGraph(); return; } if (section != null && section != previousSection) { // User switched between two sections, reload the proper graph. delayRestoreState_ = !delayRestoreState_; await Session.SwitchGraphsAsync(this, section, document); return; } if (!restoredState_) { delayRestoreState_ = true; } else { Dispatcher.BeginInvoke(() => LoadSavedState(), DispatcherPriority.Render); } } public override void OnSessionStart() { base.OnSessionStart(); loadTask_ = new CancelableTaskInstance(false, Session.SessionState.RegisterCancelableTask, Session.SessionState.UnregisterCancelableTask); } public override void OnSessionEnd() { base.OnSessionEnd(); HideGraph(); } private void LoadSavedState() { //? TODO: This can happen for the expression graph, which does not support switching. if (Document == null) { return; } byte[] data = Session.LoadPanelState(this, Document.Section) as byte[]; var state = UIStateSerializer.Deserialize(data, Document.Function); if (state != null) { SetZoom(state.ZoomLevel); GraphHost.ScrollToHorizontalOffset(state.HorizontalOffset); GraphHost.ScrollToVerticalOffset(state.VerticalOffset); restoredState_ = true; } else { GraphHost.ScrollToHorizontalOffset(0); GraphHost.ScrollToVerticalOffset(0); restoredState_ = false; } delayRestoreState_ = false; } public override async Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { if (Section != section) { return; } HidePreviewPopup(true); HideQueryPanel(); DisablePanel(); restoredState_ = false; var state = new GraphPanelState(); state.ZoomLevel = GraphViewer.ZoomLevel; state.HorizontalOffset = GraphHost.HorizontalOffset; state.VerticalOffset = GraphHost.VerticalOffset; byte[] data = UIStateSerializer.Serialize(state, document.Function); Session.SavePanelState(data, this, section); // Clear references to IR objects that would keep the previous function alive. #if DEBUG Trace.TraceInformation($"Graph panel {ObjectTracker.Track(this)}: unloaded doc {ObjectTracker.Track(Document)}"); #endif Document = null; graph_ = null; hoveredNode_ = null; } private void EnablePanel() { IsPanelEnabled = true; Utils.EnableControl(GraphHost); Utils.EnableControl(ToolbarHost); } private void DisablePanel() { Utils.DisableControl(ToolbarHost); Utils.DisableControl(GraphHost, 0.5); IsPanelEnabled = false; } public override void OnElementSelected(IRElementEventArgs e) { if (!Settings.SyncSelectedNodes) { return; } if (e.Element is BlockIR block) { SelectedElement = block; } } public override void OnElementHighlighted(IRHighlightingEventArgs e) { if (!Settings.SyncSelectedNodes) { return; } if (e.Action == HighlightingEventAction.ReplaceHighlighting || e.Action == HighlightingEventAction.AppendHighlighting) { Highlight(e); } else if (e.Action == HighlightingEventAction.RemoveHighlighting) { if (e.Element != null) { RemoveHighlighting(e.Element); } else { RemoveAllHighlighting(e.Type); } } } public override void OnActivatePanel() { if (delayFitSize_ && GraphViewer.IsGraphLoaded) { FitGraphIntoView(); } } public override async void ClonePanel(IToolPanel sourcePanel) { var sourceGraphPanel = sourcePanel as GraphPanel; InitializeFromDocument(sourceGraphPanel.Document); // Rebuild the graph, otherwise the visual nodes // point to the same instance. var newGraph = await Session.ComputeGraphAsync(sourceGraphPanel.graph_.Kind, Section, Document); DisplayGraph(newGraph); } private class BlockTooltipInfo { public BlockTooltipInfo(BlockIR block) { PredecessorCount = block.Predecessors.Count; SuccessorCount = block.Successors.Count; var loopTag = block.GetTag(); if (loopTag != null) { InLoop = true; LoopNesting = loopTag.NestingLevel; LoopBlocks = loopTag.Loop.Blocks.Count; NestedLoops = loopTag.Loop.NestedLoops.Count; } } public bool InLoop { get; set; } public int LoopBlocks { get; set; } public int LoopNesting { get; set; } public int NestedLoops { get; set; } public int PredecessorCount { get; set; } public int SuccessorCount { get; set; } } private async void PanelToolbarTray_OnHelpClicked(object sender, EventArgs e) { await HelpPanel.DisplayPanelHelp(PanelKind, Session); } } class GraphQueryInfo { public BlockIR Block1 { get; set; } public BlockIR Block2 { get; set; } public string Block1Name { get; set; } public string Block2Name { get; set; } public bool Dominates { get; set; } public bool PostDominates { get; set; } public bool Reaches { get; set; } public bool ControlDependent { get; set; } public bool OnDomFrontier { get; set; } public void SwapBlocks() { var tempBlock = Block1; string tempBlockName = Block1Name; Block1 = Block2; Block1Name = Block2Name; Block2 = tempBlock; Block2Name = tempBlockName; } } ================================================ FILE: src/ProfileExplorerUI/Panels/HelpPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/HelpPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using Microsoft.Web.WebView2.Core; namespace ProfileExplorer.UI.Panels; public class HelpTopic { public string Title { get; set; } public string URL { get; set; } public List SubTopics { get; set; } } public class HelpIndex { public HelpIndex() { Topics = new List(); PanelTopics = new Dictionary(); } public List Topics { get; set; } public Dictionary PanelTopics { get; set; } public HelpTopic HomeTopic { get; set; } public static HelpIndex DeserializeFromFile(string filePath) { if (UIJsonUtils.DeserializeFromFile(filePath, out HelpIndex index)) { return index; } return new HelpIndex(); } public static HelpIndex Deserialize(string text) { if (UIJsonUtils.Deserialize(text, out HelpIndex index)) { return index; } return new HelpIndex(); } } public partial class HelpPanel : ToolPanelControl { private HelpIndex helpIndex_; private HelpTopic currentTopic_; private SemaphoreSlim loadingTopic_; private bool browserInitialized_; private Window videoWindow_; private Window previewWindow_; private string previewUrl_; public HelpPanel() { loadingTopic_ = new SemaphoreSlim(1); InitializeComponent(); } public override ToolPanelKind PanelKind => ToolPanelKind.Help; public override async void OnActivatePanel() { await Initialize(); } public override async void OnShowPanel() { await Initialize(); } private async Task Initialize() { base.OnActivatePanel(); await loadingTopic_.WaitAsync(); if (currentTopic_ == null) { await LoadHomeTopic(); } loadingTopic_.Release(); } private async Task DownloadHelpIndex() { // Download index file from web location. if (helpIndex_ != null) { return true; } try { using var client = new HttpClient(); using var response = await client.GetAsync(App.GetHelpIndexFilePath()); if (response.IsSuccessStatusCode) { string contents = await response.Content.ReadAsStringAsync(); helpIndex_ = HelpIndex.Deserialize(contents); if (helpIndex_ != null) { TopicsTree.ItemsSource = helpIndex_.Topics; } } else { Trace.WriteLine($"Failed to download file: {response.ReasonPhrase}"); } } catch (Exception ex) { Trace.WriteLine($"Failed to download file: {ex.Message}"); } return helpIndex_ != null; } public async Task LoadHomeTopic() { if (await DownloadHelpIndex()) { await NavigateToTopic(helpIndex_.HomeTopic); } } public async Task LoadPanelHelp(ToolPanelKind kind) { if (await DownloadHelpIndex()) { if (helpIndex_.PanelTopics.TryGetValue(kind, out var topic)) { await NavigateToTopic(topic); } } } public static async Task DisplayPanelHelp(ToolPanelKind kind, IUISession session) { if (await session.ShowPanel(ToolPanelKind.Help) is HelpPanel panel) { await panel.LoadPanelHelp(kind); } } private async Task NavigateToTopic(HelpTopic topic) { if (topic != null && !string.IsNullOrEmpty(topic.URL)) { TopicTextBox.Text = topic.Title; currentTopic_ = topic; await NavigateToURL(App.GetHelpFilePath(topic.URL)); } } private async Task InitializeBrowser() { if (browserInitialized_) { return; } // Place cache files in the settings directory. browserInitialized_ = true; var webView2Environment = await CoreWebView2Environment.CreateAsync(null, App.GetSettingsDirectoryPath()); try { await Browser.EnsureCoreWebView2Async(webView2Environment); if (Browser.CoreWebView2 == null) { Trace.WriteLine("Failed to initialize WebView2 control in HelpPanel."); return; } } catch (Exception ex) { Trace.WriteLine($"Failed to initialize WebView2 control in HelpPanel: {ex.Message}"); return; } // Handle a video/image entering full-screen mode // by making a new maximized window to which the browser control // is moved. When exiting full-screen mode, the browser is moved // back to the panel and the window is closed. Browser.CoreWebView2.ContainsFullScreenElementChanged += (sender, args) => { if (Browser.CoreWebView2.ContainsFullScreenElement) { videoWindow_ = new Window(); videoWindow_.WindowState = WindowState.Maximized; videoWindow_.WindowStyle = WindowStyle.None; videoWindow_.ResizeMode = ResizeMode.NoResize; videoWindow_.ShowInTaskbar = false; BrowserHost.Children.Remove(Browser); videoWindow_.Content = Browser; videoWindow_.Show(); } else { if (videoWindow_ != null) { videoWindow_.Content = null; videoWindow_.Close(); BrowserHost.Children.Add(Browser); } } }; Browser.NavigationStarting += (sender, args) => { // Update current topic when navigating to a new page. foreach (var topic in helpIndex_.Topics) { if (args.Uri.Contains(topic.URL.Replace('\\', '/'), StringComparison.OrdinalIgnoreCase)) { TopicTextBox.Text = topic.Title; currentTopic_ = topic; break; } } }; // Force light mode for the WebView2 control for now // screenshots don't look good in dark mode. Browser.CoreWebView2.Profile.PreferredColorScheme = CoreWebView2PreferredColorScheme.Light; Browser.ZoomFactor = 0.9; } private async Task NavigateToURL(string url) { await InitializeBrowser(); if (Browser.Source != null) { Browser.Stop(); } Browser.Source = new Uri(url); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async void TopicsTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) { if (sender is TreeView treeView && treeView.SelectedItem is HelpTopic selectedTopic) { await NavigateToTopic(selectedTopic); } TopicsTreePopup.IsOpen = false; } private void TopicsTextbox_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (TopicsTreePopup.IsOpen) { TopicsTreePopup.IsOpen = false; return; } TopicsTreePopup.Placement = PlacementMode.Relative; TopicsTreePopup.PlacementTarget = TopicTextBox; TopicsTreePopup.VerticalOffset = TopicTextBox.ActualHeight; TopicsTreePopup.Height = TopicsTree.Height; TopicsTreePopup.Width = TopicTextBox.Width; TopicsTreePopup.IsOpen = true; } private void TopicsTextbox_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { TopicsTreePopup.IsOpen = false; } private void Browser_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e) { if (Browser.CoreWebView2 == null) { return; } Browser.CoreWebView2.NewWindowRequested += Browser_NewWindowRequested; } private void Browser_NewWindowRequested(object sender, CoreWebView2NewWindowRequestedEventArgs e) { try { if (e.Uri.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || e.Uri.EndsWith(".gif", StringComparison.OrdinalIgnoreCase) || e.Uri.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) || e.Uri.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase)) { if (previewWindow_ != null) { // Second click on same image closes current preview. bool showPreview = previewUrl_ != e.Uri; CloseImagePreview(); if (!showPreview) { e.Handled = true; return; } } // Try to parse out an initial popup size from the image name. if (!TryExtractImageSize(e.Uri, out int width, out int height)) { width = 800; height = 600; } width = (int)Math.Min(width, SystemParameters.PrimaryScreenWidth - 50); height = (int)Math.Min(height, SystemParameters.PrimaryScreenHeight - 50); ShowImagePreview(e.Uri, width, height); } else { // Open in new external browser window. var psi = new ProcessStartInfo() { FileName = e.Uri, UseShellExecute = true }; Process.Start(psi); } e.Handled = true; } catch (Exception ex) { Trace.WriteLine($"Failed to start external browser: {ex.Message}"); } } private void ShowImagePreview(string url, int width, int height) { var window = new Window(); window.WindowStyle = WindowStyle.None; window.WindowStartupLocation = WindowStartupLocation.CenterOwner; window.ResizeMode = ResizeMode.CanResizeWithGrip; var browser = new Image(); browser.Source = new BitmapImage(new Uri(url)); browser.HorizontalAlignment = HorizontalAlignment.Stretch; browser.VerticalAlignment = VerticalAlignment.Stretch; browser.Stretch = Stretch.Uniform; window.Content = browser; window.Width = width; window.Height = height; window.Owner = Application.Current.MainWindow; window.PreviewMouseDown += (sender, args) => { CloseImagePreview(); }; window.PreviewKeyDown += (sender, args) => { switch (args.Key) { case Key.Escape: case Key.Space: case Key.Back: { CloseImagePreview(); break; } } }; previewWindow_ = window; previewUrl_ = url; window.Show(); } private void CloseImagePreview() { if (previewWindow_ != null) { previewWindow_.Close(); previewWindow_ = null; previewUrl_ = null; } } private bool TryExtractImageSize(string url, out int width, out int height) { // Try parse file_widthxheight.extension, like file_800x600.gif. width = height = 0; int start = url.LastIndexOf('_'); int end = url.LastIndexOf('.'); if (start == -1 || end <= start) { return false; } int middle = url.IndexOf('x', start); if (middle == -1) { return false; } return int.TryParse(url.Substring(start + 1, middle - start - 1), out width) && int.TryParse(url.Substring(middle + 1, end - middle - 1), out height); } private void ZoomInButton_Click(object sender, RoutedEventArgs e) { Browser.ZoomFactor = Math.Min(4, Browser.ZoomFactor + 0.1); } private void ZoomOutButton_Click(object sender, RoutedEventArgs e) { Browser.ZoomFactor = Math.Max(0.5, Browser.ZoomFactor - 0.1); } private async void HomeButton_Click(object sender, RoutedEventArgs e) { await LoadHomeTopic(); } private void BackButton_Click(object sender, RoutedEventArgs e) { Browser.GoBack(); } private async void ExternalButton_Click(object sender, RoutedEventArgs e) { try { string helpURL = null; if (currentTopic_ != null) { // Open current topic if loaded. helpURL = App.GetHelpFilePath(currentTopic_.URL); } else if (await DownloadHelpIndex()) { helpURL = App.GetHelpFilePath(helpIndex_.HomeTopic.URL); } if (!string.IsNullOrEmpty(helpURL)) { var psi = new ProcessStartInfo() { FileName = helpURL, UseShellExecute = true }; Process.Start(psi); } } catch (Exception ex) { Trace.WriteLine($"Failed to start external browser: {ex.Message}"); } } } ================================================ FILE: src/ProfileExplorerUI/Panels/IToolPanel.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Threading.Tasks; using ProfileExplorer.Core; namespace ProfileExplorer.UI; public enum ToolPanelKind { Section, References, Notes, Definition, Bookmarks, Source, FlowGraph, DominatorTree, PostDominatorTree, ExpressionGraph, CallGraph, CallTree, CallerCallee, FlameGraph, Timeline, PassOutput, SearchResults, Remarks, Scripting, Developer, Help, Other } [Flags] public enum HandledEventKind { None, ElementSelection, ElementHighlighting } public interface IToolPanel { ToolPanelKind PanelKind { get; } string TitlePrefix { get; } string TitleSuffix { get; } string TitleToolTip { get; } HandledEventKind HandledEvents { get; } bool SavesStateToFile { get; } bool IsUnloaded { get; } IUISession Session { get; set; } IRDocument Document { get; set; } IRDocument BoundDocument { get; set; } bool IsPanelEnabled { get; set; } bool HasCommandFocus { get; set; } bool HasPinnedContent { get; set; } bool IgnoreNextLoadEvent { get; set; } bool IgnoreNextUnloadEvent { get; set; } void OnRegisterPanel(); void OnUnregisterPanel(); void OnShowPanel(); void OnHidePanel(); void OnActivatePanel(); void OnDeactivatePanel(); void OnRedrawPanel(); void OnSessionStart(); void OnSessionEnd(); void OnSessionSave(); Task OnReloadSettings(); Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document); Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document); void OnElementSelected(IRElementEventArgs e); void OnElementHighlighted(IRHighlightingEventArgs e); void ClonePanel(IToolPanel basePanel); } ================================================ FILE: src/ProfileExplorerUI/Panels/ModuleReport.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core; namespace ProfileExplorer.UI; public class ValueStatistics { public List> Values; public double Average { get; set; } public long Median { get; set; } public long Min { get; set; } public long Max { get; set; } public int MaxDistributionFactor => (int)Math.Ceiling(Math.Log10(Max)); public override string ToString() { return $"Average: {Average}\n" + $"Median: {Median}\n" + $"Min: {Min}\n" + $"Max: {Max}\n"; } public int GetGroupSize(int factor) { return Math.Max(1, (int)Math.Pow(10, Math.Round(Math.Log10(Max)) - factor)); } public List ComputeDistribution(int factor) { var list = new List(); int groupSize = GetGroupSize(factor); var range = new DistributionRange(0, 0, groupSize - 1); int total = 0; foreach (var value in Values) { int rangeIndex = (int)(value.Item2 / groupSize); if (rangeIndex != range.Index) { list.Add(range); range = new DistributionRange(rangeIndex, rangeIndex * groupSize, (rangeIndex + 1) * groupSize - 1); } range.Count++; range.Values.Add(value); total++; } if (range.Count > 0) { list.Add(range); } foreach (var item in list) { item.Percentage = (double)item.Count / total; } return list; } public class Generator { private List> values_ = new(); private long total_; private long min_ = long.MaxValue; private long max_ = long.MinValue; public void Add(long value, IRTextFunction func) { values_.Add(new Tuple(func, value)); total_ += value; min_ = Math.Min(min_, value); max_ = Math.Max(max_, value); } public ValueStatistics Compute(int count) { var stats = new ValueStatistics(); if (count == 0 || values_.Count == 0) { return stats; } values_.Sort((a, b) => a.Item2.CompareTo(b.Item2)); stats.Values = values_; stats.Average = (double)total_ / count; stats.Median = values_[values_.Count / 2].Item2; stats.Min = min_; stats.Max = max_; return stats; } } public class DistributionRange { public DistributionRange(int index, int rangeStart, int rangeEnd) { Index = index; RangeStart = rangeStart; RangeEnd = rangeEnd; Values = new List>(); } public int Index { get; set; } public int RangeStart { get; set; } public int RangeEnd { get; set; } public int Count { get; set; } public double Percentage { get; set; } public List> Values { get; set; } } } public class FunctionGroupStatistics { public FunctionGroupStatistics(IDictionary functions) { Functions = functions; Total = new FunctionCodeStatistics(); } public IDictionary Functions { get; set; } public FunctionCodeStatistics Total { get; set; } public ValueStatistics Size { get; set; } public ValueStatistics Instructions { get; set; } public ValueStatistics Calls { get; set; } public ValueStatistics Callers { get; set; } public override string ToString() { return $"Totals: {Total}\n" + $"Size: {Size}\n" + $"Instructions: {Instructions}\n" + $"Calls: {Calls}\n" + $"Callers: {Callers}\n"; } } public class ModuleReport { public ModuleReport(IDictionary functionStatisticsMap) { StatisticsMap = functionStatisticsMap; Statistics = new FunctionGroupStatistics(functionStatisticsMap); SingleCallerFunctions = new List(); LeafFunctions = new List(); InstructionsDistribution = new Dictionary>(); CallsDistribution = new Dictionary>(); CallersDistribution = new Dictionary>(); } public ICollection Functions => StatisticsMap.Keys; public int FunctionCount => StatisticsMap.Count; public IDictionary StatisticsMap { get; set; } public FunctionGroupStatistics Statistics { get; set; } public List SingleCallerFunctions { get; set; } public List LeafFunctions { get; set; } public Dictionary> InstructionsDistribution { get; set; } public Dictionary> CallsDistribution { get; set; } public Dictionary> CallersDistribution { get; set; } public double SingleCallerPercentage => FunctionCount > 0 ? (double)SingleCallerFunctions.Count / FunctionCount : 0; public double LeafPercentage => FunctionCount > 0 ? (double)LeafFunctions.Count / FunctionCount : 0; public void Generate() { foreach (var pair in StatisticsMap) { var func = pair.Key; var stats = pair.Value; AddToDistribution(stats.Instructions, func, InstructionsDistribution); AddToDistribution(stats.Calls, func, CallsDistribution); AddToDistribution(stats.Callers, func, CallersDistribution); if (stats.Callers == 1) { SingleCallerFunctions.Add(func); } if (stats.Calls == 0) { LeafFunctions.Add(func); } } ComputeStatistics(); } public List>> ComputeHistogram(int step) { return null; } public void ComputeStatistics() { Statistics = ComputeGroupStatistics(StatisticsMap); } public FunctionGroupStatistics ComputeGroupStatistics( List values) { var dict = new Dictionary(); foreach (var func in values) { dict[func] = StatisticsMap[func]; } return ComputeGroupStatistics(dict); } public FunctionGroupStatistics ComputeGroupStatistics( IDictionary values) { var groupStats = new FunctionGroupStatistics(values); var calls = new ValueStatistics.Generator(); var callers = new ValueStatistics.Generator(); var size = new ValueStatistics.Generator(); var instrs = new ValueStatistics.Generator(); int functions = 0; foreach (var pair in values) { var func = pair.Key; var stats = pair.Value; groupStats.Total.Add(stats); calls.Add(stats.Calls, func); callers.Add(stats.Callers, func); size.Add(stats.Size, func); instrs.Add(stats.Instructions, func); functions++; } groupStats.Calls = calls.Compute(functions); groupStats.Callers = callers.Compute(functions); groupStats.Size = size.Compute(functions); groupStats.Instructions = instrs.Compute(functions); return groupStats; } public override string ToString() { return $"Functions: {Functions}\n" + $"Statistics: {Statistics}\n" + $"SingleCallerFunctions: {SingleCallerFunctions.Count}\n" + $"LeafFunctions: {LeafFunctions.Count}"; } private void AddToDistribution(int times, IRTextFunction function, Dictionary> map) { if (!map.TryGetValue(times, out var list)) { list = new List(); map[times] = list; } list.Add(function); } } ================================================ FILE: src/ProfileExplorerUI/Panels/ModuleReportPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/ReferencesPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.Core.Controls; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProtoBuf; namespace ProfileExplorer.UI; public static class ReferenceCommand { public static readonly RoutedUICommand JumpToReference = new("Untitled", "JumpToReference", typeof(ReferencesPanel)); public static readonly RoutedUICommand CopyToClipboard = new("Untitled", "CopyToClipboard", typeof(ReferencesPanel)); public static readonly RoutedUICommand MarkReference = new("Untitled", "MarkReference", typeof(ReferencesPanel)); public static readonly RoutedUICommand UnmarkReference = new("Untitled", "UnmarkReference", typeof(ReferencesPanel)); } public class ReferenceSummary { public int SSACount { get; set; } public int LoadCount { get; set; } public int StoreCount { get; set; } public int AddressCount { get; set; } } public class ReferenceInfo { //? TODO: Should match editor font, not be hardcoded //? Needs to listen to DocumentSettings event change to update font used too private static readonly FontFamily PreviewFont = new("Consolas"); private OperandIR operand_; private ReadOnlyMemory documentText_; private string previewText_; private TextBlock preview_; public ReferenceInfo(int index, OperandIR operand, Reference info, ReadOnlyMemory documentText) { Index = index; Info = info; operand_ = operand; documentText_ = documentText; } public Reference Info { get; set; } public int Index { get; set; } public int Line => Info.Element.TextLocation.Line; public string Block => Utils.MakeBlockDescription(Info.Element.ParentBlock); public string Kind { get { return Info.Kind switch { ReferenceKind.Address => "Address", ReferenceKind.Load => "Load", ReferenceKind.Store => "Store", ReferenceKind.SSA => "SSA use", _ => "" }; } } public TextBlock Preview { get { CreateOnDemandPreview(); return preview_; } } public string PreviewText { get { CreateOnDemandPreview(); return previewText_; } } private static (TextBlock, string) CreatePreviewTextBlock(OperandIR operand, Reference reference, ReadOnlyMemory documentText) { // Mark every instance of the symbol name in the preview text (usually an instr). string text = GeneratePreviewText(reference, documentText); string symbolName = Utils.GetSymbolName(operand); int index = 0; var textBlock = new TextBlock(); textBlock.FontFamily = PreviewFont; textBlock.Foreground = Brushes.Black; textBlock.Margin = new Thickness(0, 2, 0, 0); if (string.IsNullOrEmpty(symbolName)) { textBlock.Inlines.Add(text); return (textBlock, text); } while (index < text.Length) { int symbolIndex = text.IndexOf(symbolName, index, StringComparison.Ordinal); if (symbolIndex == -1) { break; } // Append any text before the symbol name. if (index < symbolIndex) { textBlock.Inlines.Add(text.Substring(index, symbolIndex - index)); } textBlock.Inlines.Add(new Run(symbolName) { FontWeight = FontWeights.Bold }); index = symbolIndex + symbolName.Length; } // Append remaining text at the end. if (index < text.Length) { textBlock.Inlines.Add(text.Substring(index, text.Length - index)); } return (textBlock, text); } private static string GeneratePreviewText(Reference reference, ReadOnlyMemory documentText) { return DocumentUtils.GenerateElementPreviewText(reference.Element, documentText); } private void CreateOnDemandPreview() { if (preview_ == null) { (preview_, previewText_) = CreatePreviewTextBlock(operand_, Info, documentText_); } } } [ProtoContract] public class ReferencePanelState { [ProtoMember(2)] public bool IsFindAll; [ProtoMember(3)] public bool HasPinnedContent; [ProtoMember(4)] public ReferenceKind FilterKind; [ProtoMember(1)] private IRElementReference elementRef_; public IRElement Element { get => elementRef_; set => elementRef_ = value; } } public partial class ReferencesPanel : ToolPanelControl, INotifyPropertyChanged { private ReadOnlyMemory documentText_; private IRElement element_; private ReferenceKind filterKind_; private bool ignoreNextElement_; private IRDocumentPopup previewPopup_; private DelayedAction removeHoveredAction_; private List referenceList_; private ListCollectionView referenceListView_; private ReferenceSummary referenceSummary_; private IRTextSection section_; public ReferencesPanel() { InitializeComponent(); DataContext = this; MouseLeave += OnMouseLeave; //? TODO: Replace with PopupHoverPreview var hover = new MouseHoverLogic(this); hover.MouseHover += Hover_MouseHover; hover.MouseHoverStopped += Hover_MouseHoverStopped; } public ReferenceKind FilterKind { get => filterKind_; set { if (filterKind_ != value) { filterKind_ = value; OnPropertyChange(nameof(FilterKind)); OnPropertyChange(nameof(ShowLoad)); OnPropertyChange(nameof(ShowStore)); OnPropertyChange(nameof(ShowAddress)); OnPropertyChange(nameof(ShowSSA)); referenceListView_?.Refresh(); } } } public ReferenceSummary ReferenceSummary { get => referenceSummary_; set { if (referenceSummary_ != value) { referenceSummary_ = value; OnPropertyChange(nameof(LoadCount)); OnPropertyChange(nameof(StoreCount)); OnPropertyChange(nameof(AddressCount)); OnPropertyChange(nameof(SSACount)); } } } public int LoadCount => referenceSummary_?.LoadCount ?? 0; public int StoreCount => referenceSummary_?.StoreCount ?? 0; public int AddressCount => referenceSummary_?.AddressCount ?? 0; public int SSACount => referenceSummary_?.SSACount ?? 0; public bool ShowLoad { get => filterKind_.HasFlag(ReferenceKind.Load); set => SetFilterFlag(ReferenceKind.Load, value); } public bool ShowStore { get => filterKind_.HasFlag(ReferenceKind.Store); set => SetFilterFlag(ReferenceKind.Store, value); } public bool ShowAddress { get => filterKind_.HasFlag(ReferenceKind.Address); set => SetFilterFlag(ReferenceKind.Address, value); } public bool ShowSSA { get => filterKind_.HasFlag(ReferenceKind.SSA); set => SetFilterFlag(ReferenceKind.SSA, value); } public IRElement Element { get => element_; set { if (ignoreNextElement_) { ignoreNextElement_ = false; return; } var operand = FindReferenceOperand(value); if (element_ != operand) { if (operand != null && HasPinnedContent) { return; // Keep pinned element. } element_ = operand; FindAllReferences(operand, true, false); } } } public override ToolPanelKind PanelKind => ToolPanelKind.References; public override HandledEventKind HandledEvents => HandledEventKind.ElementSelection; public override bool HasPinnedContent { get => FixedToolbar.IsPinned; set => FixedToolbar.IsPinned = value; } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChange(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public bool FindAllReferences(IRElement element, bool alwaysShowSSAUses, bool pinElement = true) { if (element is not OperandIR operand) { ResetReferenceListView(); return false; } //? TODO: There should be an option to pick default behavior for SSA values //? - if SSA def, show only SSA uses //? - or always show all refs // Enabled the filters. // if (alwaysShowSSAUses) { // FilterKind |= ReferenceKind.SSA; // } FilterKind = ReferenceKind.Address | ReferenceKind.Load | ReferenceKind.Store; var refFinder = new ReferenceFinder(Document.Function); var operandRefs = refFinder.FindAllReferences(operand); UpdateReferenceListView(operand, operandRefs); FixedToolbar.IsPinned = pinElement; return operandRefs.Count > 0; } public void InitializeFromDocument(IRDocument document) { if (Document != document || section_ != document.Section) { Document = document; documentText_ = document.SectionText; // Cache text. section_ = document.Section; Element = null; } } private OperandIR FindReferenceOperand(IRElement value) { // Only operands can have references. // For instrs. use the first destination operand. if (value is OperandIR operand) { return operand; } if (value is InstructionIR instr && instr.Destinations.Count > 0) { return instr.Destinations[0]; } return null; } private bool FilterReferenceList(object value) { var refInfo = value as ReferenceInfo; return filterKind_.HasFlag(refInfo.Info.Kind); } private void UpdateReferenceListView(OperandIR operand, List operandRefs) { referenceList_ = new List(operandRefs.Count); var summary = new ReferenceSummary(); int index = 1; // Sort based on the ref. element text offset. operandRefs.Sort((a, b) => a.Element.TextLocation.Offset - b.Element.TextLocation.Offset); foreach (var reference in operandRefs) { referenceList_.Add(new ReferenceInfo(index, operand, reference, documentText_)); index++; switch (reference.Kind) { case ReferenceKind.Address: summary.AddressCount++; break; case ReferenceKind.Load: summary.LoadCount++; break; case ReferenceKind.Store: summary.StoreCount++; break; case ReferenceKind.SSA: summary.SSACount++; break; default: throw new ArgumentOutOfRangeException(); } } referenceListView_ = new ListCollectionView(referenceList_); referenceListView_.Filter = FilterReferenceList; ReferenceList.ItemsSource = referenceListView_; ReferenceSummary = summary; if (operand != null) { SymbolName.Text = Utils.GetSymbolName(operand); } else { SymbolName.Text = ""; } } private void ResetReferenceListView() { section_ = null; element_ = null; HasPinnedContent = false; ReferenceList.ItemsSource = null; ReferenceSummary = null; SymbolName.Text = ""; } private void ComboBox_Loaded(object sender, RoutedEventArgs e) { if (sender is ComboBox control) { Utils.PatchComboBoxStyle(control); } } private void JumpToReferenceExecuted(object sender, ExecutedRoutedEventArgs e) { var refInfo = e.Parameter as ReferenceInfo; JumpToReference(refInfo); } private void MarkReferenceExecuted(object sender, ExecutedRoutedEventArgs e) { if (ReferenceList.SelectedItem is ReferenceInfo refInfo) { var color = ((SelectedColorEventArgs)e.Parameter).SelectedColor; Document.MarkElement(refInfo.Info.Element, color); } } private void UnmarkReferenceExecuted(object sender, ExecutedRoutedEventArgs e) { var refInfo = ReferenceList.SelectedItem as ReferenceInfo; if (refInfo != null) { Document.ClearMarkedElement(refInfo.Info.Element); } } private void CopyToClipboardExecuted(object sender, ExecutedRoutedEventArgs e) { if (referenceList_ == null) { return; } var sb = new StringBuilder(); sb.AppendLine($"References for symbol: {SymbolName.Text}"); sb.AppendLine($" SSA uses: {referenceSummary_.SSACount}"); sb.AppendLine($" Load uses: {referenceSummary_.LoadCount}"); sb.AppendLine($" Store uses: {referenceSummary_.StoreCount}"); sb.AppendLine($" Address uses: {referenceSummary_.AddressCount}"); foreach (var refInfo in referenceList_) { sb.AppendLine($"# {refInfo.Index}: {refInfo.Kind}, block {refInfo.Block}"); sb.AppendLine($" {refInfo.PreviewText}"); } Clipboard.SetText(sb.ToString()); } private void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var refInfo = ((ListViewItem)sender).DataContext as ReferenceInfo; JumpToReference(refInfo); } private void JumpToReference(ReferenceInfo refInfo) { ignoreNextElement_ = true; Document.SelectElement(refInfo.Info.Element); Document.BringElementIntoView(refInfo.Info.Element); } private async Task ShowPreviewPopup(IRElement element, UIElement relativeElement) { if (previewPopup_ != null) { if (previewPopup_.PreviewedElement == element) { return; } HidePreviewPopup(true); } if (removeHoveredAction_ != null) { removeHoveredAction_.Cancel(); removeHoveredAction_ = null; } var position = Mouse.GetPosition(relativeElement).AdjustForMouseCursor(); previewPopup_ = await IRDocumentPopup.CreateNew(Document, element, position, relativeElement, App.Settings.GetElementPreviewPopupSettings( ToolPanelKind.References), "Use of "); previewPopup_.PopupDetached += Popup_PopupDetached; previewPopup_.ShowPopup(); } private void HidePreviewPopup(bool force = false) { if (previewPopup_ != null && (force || !previewPopup_.IsMouseOver)) { previewPopup_.ClosePopup(); previewPopup_ = null; } } private void Popup_PopupDetached(object sender, EventArgs e) { var popup = (IRDocumentPopup)sender; if (popup == previewPopup_) { previewPopup_ = null; // Prevent automatic closing. } } private void OnMouseLeave(object sender, MouseEventArgs e) { HidePreviewPopup(); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private void PanelToolbarTray_SettingsClicked(object sender, EventArgs e) { MessageBox.Show("TODO"); } private void PanelToolbarTray_PinnedChanged(object sender, PinEventArgs e) { HasPinnedContent = e.IsPinned; } private void PanelToolbarTray_DuplicateClicked(object sender, DuplicateEventArgs e) { Session.DuplicatePanel(this, e.Kind); } private void FixedToolbar_BindMenuOpen(object sender, BindMenuItemsArgs e) { Session.PopulateBindMenu(this, e); } private void FixedToolbar_BindMenuItemSelected(object sender, BindMenuItem e) { Session.BindToDocument(this, e); } private bool SetFilterFlag(ReferenceKind flag, bool value) { if (value && !FilterKind.HasFlag(flag)) { FilterKind |= flag; return true; } if (!value && FilterKind.HasFlag(flag)) { FilterKind &= ~flag; return true; } return false; } private async void Hover_MouseHover(object sender, MouseEventArgs e) { var hoveredItem = Utils.FindPointedListViewItem(ReferenceList); if (hoveredItem != null) { var refInfo = (ReferenceInfo)hoveredItem.DataContext; await ShowPreviewPopup(refInfo.Info.Element, hoveredItem); } } private void Hover_MouseHoverStopped(object sender, MouseEventArgs e) { HidePreviewPopupDelayed(); } private void HidePreviewPopupDelayed() { removeHoveredAction_ = DelayedAction.StartNew(() => { if (removeHoveredAction_ != null) { removeHoveredAction_ = null; HidePreviewPopup(); } }); } public override async Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document) { if (section == section_) { return; } InitializeFromDocument(document); object data = Session.LoadPanelState(this, section, document); var state = UIStateSerializer.Deserialize(data, document.Function); if (state != null) { FindAllReferences(state.Element, !state.IsFindAll); HasPinnedContent = state.HasPinnedContent; FilterKind = state.FilterKind; } else { ResetReferenceListView(); } IsPanelEnabled = document != null; } public override async Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { if (element_ == null || section_ != section) { return; } var state = new ReferencePanelState(); state.Element = Element; state.HasPinnedContent = HasPinnedContent; state.FilterKind = FilterKind; byte[] data = UIStateSerializer.Serialize(state, document.Function); Session.SavePanelState(data, this, section, Document); ResetReferenceListView(); Document = null; } public override void OnSessionEnd() { ResetReferenceListView(); base.OnSessionEnd(); } public override void OnElementSelected(IRElementEventArgs e) { Element = e.Element; } public override void ClonePanel(IToolPanel sourcePanel) { var sourceRefPanel = sourcePanel as ReferencesPanel; Document = sourceRefPanel.Document; documentText_ = sourceRefPanel.documentText_; IsPanelEnabled = Document != null; } } ================================================ FILE: src/ProfileExplorerUI/Panels/ScriptingPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/ScriptingPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using ICSharpCode.AvalonEdit.CodeCompletion; using ICSharpCode.AvalonEdit.Editing; using Microsoft.CodeAnalysis; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Scripting; namespace ProfileExplorer.UI; public static class ScriptingCommand { public static readonly RoutedUICommand ExecuteScript = new("Untitled", "ExecuteScript", typeof(BookmarksPanel)); } public class CompletionWindowEx : CompletionWindow { public CompletionWindowEx(TextArea textArea) : base(textArea) { } public void SetInitialWidth(double width) { Width = Math.Clamp(width, 100, TextArea.ActualWidth); } public void SetStartOffset(TextArea textArea) { StartOffset = EndOffset = textArea.Caret.Offset; } public void AdjustStartOffset(string currentWord) { StartOffset -= currentWord.Length; } public void PreselectItem(string text) { CompletionList.IsFiltering = false; // Disable filtering to still show complete list. CompletionList.SelectItem(text); CompletionList.ScrollIntoView(CompletionList.SelectedItem); } } public partial class ScriptingPanel : ToolPanelControl { private const int SyntaxErrorHighlightingDelay = 1; private static readonly string InitialScript = string.Join(Environment.NewLine, "using System;", "using System.Collections.Generic;", "using System.Windows.Media;", "using ProfileExplorer.Core;", "using ProfileExplorer.Core.IR;", "using ProfileExplorer.Core.Analysis;", "using ProfileExplorer.UI;", "using ProfileExplorer.UI.Scripting;", "\n", "public class Script {", " // s: provides script interaction with Profile Explorer (text output, marking, etc.)", " public bool Execute(ScriptSession s) {", " // Write C#-based script here.", " return true;", " }", "}"); private CompletionWindowEx completionWindow_; private int currentAutocompleteHash_; private ScriptAutoComplete autoComplete_; private ElementHighlighter errorHighlighter_; private DelayedAction errorHighlightingAction_; private List errorDiagnostics_; private ToolTip errorTooltip_; public ScriptingPanel() { InitializeComponent(); autoComplete_ = new ScriptAutoComplete(); errorHighlighter_ = new ElementHighlighter(HighlighingType.Marked); TextView.TextArea.TextEntered += TextArea_TextEntered; TextView.TextArea.KeyUp += TextArea_KeyUp; TextView.MouseHover += TextView_MouseHover; TextView.MouseHoverStopped += TextView_MouseHoverStopped; TextView.TextArea.TextView.BackgroundRenderers.Add(errorHighlighter_); } public override ToolPanelKind PanelKind => ToolPanelKind.Scripting; private void TextView_MouseHoverStopped(object sender, MouseEventArgs e) { if (errorTooltip_ != null) { errorTooltip_.IsOpen = false; errorTooltip_ = null; e.Handled = true; } } private void TextView_MouseHover(object sender, MouseEventArgs e) { if (errorDiagnostics_ == null) { return; } var position = TextView.TextArea.TextView.GetPositionFloor(e.GetPosition(TextView.TextArea.TextView) + TextView.TextArea.TextView.ScrollOffset); if (!position.HasValue) { return; } var logicalPosition = position.Value.Location; int offset = TextView.Document.GetOffset(logicalPosition); foreach (var error in errorDiagnostics_) { if (offset >= error.Location.SourceSpan.Start && offset <= error.Location.SourceSpan.End) { errorTooltip_ = new ToolTip(); errorTooltip_.Closed += ErrorTooltip__Closed; errorTooltip_.PlacementTarget = TextView; errorTooltip_.Content = new TextBlock { Text = error.ToString(), TextWrapping = TextWrapping.Wrap }; errorTooltip_.IsOpen = true; e.Handled = true; break; } } } private void ErrorTooltip__Closed(object sender, RoutedEventArgs e) { if (errorTooltip_ != null) { errorTooltip_.IsOpen = false; } } private async void TextArea_KeyUp(object sender, KeyEventArgs e) { if (e.Key == Key.Back || e.Key == Key.Delete) { ClearSyntaxErrorHighlighting(); e.Handled = true; await HandleTextChange(TextView.Text, ""); } } private async Task HandleTextChange(string text, string changedText) { //? TODO: More efficient ways of getting the text // https://stackoverflow.com/questions/39422126/whats-the-right-way-to-update-roslyns-document-while-typing // https://stackoverflow.com/questions/39421668/whats-the-most-efficient-way-to-use-roslyns-completionsevice-when-typing // Get the list of autocomplete items. int position = TextView.CaretOffset; string word = ScriptAutoComplete.GetCurrentWord(text, position - 1); var results = await autoComplete_.GetSuggestionsAsync(text, position, changedText); if (results.Count == 0) { HideAutocompleteBox(); } // If it's the same list as before, keep the current autocomplete box. int hash = ComputeAutcompleteHash(results); if (hash == currentAutocompleteHash_) { return; } currentAutocompleteHash_ = hash; ShowAutocompleteBox(results, word); } private void ShowAutocompleteBox(List results, string word) { // Reuse the existing auto-complete box if still visible, removes UI flickering // that happens if a new box is always created to replace the old one. bool newWindow = false; if (completionWindow_ == null) { completionWindow_ = new CompletionWindowEx(TextView.TextArea); newWindow = true; } else { completionWindow_.CompletionList.CompletionData.Clear(); completionWindow_.SetStartOffset(TextView.TextArea); } // Make the box wide enough to avoid horizontal scrolling. string longestText = results.OrderByDescending(s => s.Text.Length).First().Text; completionWindow_.SetInitialWidth(longestText.Length * 10); // Populate window and check if an item is preferred and should be preselected. string preferredItem = null; foreach (var item in results) { completionWindow_.CompletionList.CompletionData.Add(item); if (item.IsPreferred) { preferredItem = item.Text; } } // Offset the start position so that the current word gets replaced // when a suggestion is selected. completionWindow_.AdjustStartOffset(word); if (preferredItem != null) { completionWindow_.PreselectItem(preferredItem); } else { // Preselect first result if there was no preferred item. string firstItem = results.First().Text; if (firstItem.StartsWith(word, StringComparison.OrdinalIgnoreCase)) { completionWindow_.PreselectItem(firstItem); } } if (newWindow) { completionWindow_.Closed += delegate { completionWindow_ = null; currentAutocompleteHash_ = 0; }; completionWindow_.CloseAutomatically = false; completionWindow_.Show(); } } private async void TextArea_TextEntered(object sender, TextCompositionEventArgs e) { ClearSyntaxErrorHighlighting(); e.Handled = true; string text = TextView.Text; string changedText = e.Text; await HandleTextChange(text, changedText).ConfigureAwait(false); if (changedText == ".") { return; } // Start a task that checks for syntax errors after a delay. if (errorHighlightingAction_ != null) { errorHighlightingAction_.Cancel(); errorHighlightingAction_ = null; } var action = new DelayedAction(); errorHighlightingAction_ = action; await action.Start(TimeSpan.FromSeconds(SyntaxErrorHighlightingDelay), async () => { var errors = await autoComplete_.GetSourceErrorsAsync(text); errorDiagnostics_ = errors; await Dispatcher.BeginInvoke((Action)(() => { ClearSyntaxErrorHighlighting(); var group = new HighlightedElementGroup(new HighlightingStyle(Colors.Red, 0.1, ColorPens.GetPen(Colors.Red))); foreach (var error in errors) { if (error.Location.SourceSpan.Length > 0) { //? TODO: Have a highlighter that doesn't need making dummy IR elements... var element = CreateDummyElement(error.Location.SourceSpan.Start, error.Location.SourceSpan.Length); group.Add(element); } } errorHighlighter_.Add(group); TextView.TextArea.TextView.Redraw(); })); }); } private void ClearSyntaxErrorHighlighting() { errorHighlighter_.Clear(); TextView.TextArea.TextView.Redraw(); } private IRElement CreateDummyElement(int offset, int length) { int line = TextView.Document.GetLineByOffset(offset).LineNumber; var location = new TextLocation(offset, line, 0); return new IRElement(location, length); } private int ComputeAutcompleteHash(List sortedData) { int hash = 0; foreach (var item in sortedData) { hash = hash * 31 + item.Text.GetHashCode(); } return hash; } private void HideAutocompleteBox() { if (completionWindow_ != null) { completionWindow_.Close(); completionWindow_ = null; } } private async void ExecuteScriptExecuted(object sender, ExecutedRoutedEventArgs e) { var document = Session.FindAssociatedDocument(this); string userCode = TextView.Text.Trim(); var scriptSession = new ScriptSession(document, Session); var script = new Script(userCode); try { var sw = Stopwatch.StartNew(); string outputText = ""; bool result = await script.ExecuteAsync(scriptSession); sw.Stop(); if (!result) { if (script.ScriptException != null) { outputText += $"Failed to run script: {script.ScriptException}"; } } else { //? TODO: Long-running scripts need a way to update text before this outputText = string.Join(Environment.NewLine, $"Script result: {script.ScriptResult}", $"Script completed in {sw.ElapsedMilliseconds} ms", "----------------------------------------\n", $"{scriptSession.OutputText}"); } OutputTextView.Text = outputText; foreach (var pair in scriptSession.MarkedElements) { document.MarkElement(pair.Item1, pair.Item2); } } catch (Exception ex) { OutputTextView.Text = $"Failed to run script: {ex}"; } } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } public override void OnSessionStart() { base.OnSessionStart(); TextView.Text = InitialScript; } public override void OnActivatePanel() { base.OnActivatePanel(); Task.Run(() => Script.WarmUp()); Task.Run(() => ScriptAutoComplete.WarmUp()); } } ================================================ FILE: src/ProfileExplorerUI/Panels/SearchResultsPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/SearchResultsPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI; public static class SearchResultsCommand { public static readonly RoutedUICommand JumpToNext = new("Untitled", "JumpToNext", typeof(SearchResultsPanel)); public static readonly RoutedUICommand JumpToPrevious = new("Untitled", "JumpToPrevious", typeof(SearchResultsPanel)); public static readonly RoutedUICommand JumpToNextSection = new("Untitled", "JumpToNextSection", typeof(SearchResultsPanel)); public static readonly RoutedUICommand JumpToPreviousSection = new("Untitled", "JumpToPreviousSection", typeof(SearchResultsPanel)); public static readonly RoutedUICommand JumpToSelected = new("Untitled", "JumpToSelected", typeof(SearchResultsPanel)); public static readonly RoutedUICommand OpenInNewTab = new("Open section in new tab", "OpenInNewTab", typeof(SearchResultsPanel)); public static readonly RoutedUICommand OpenLeft = new("Open section in new tab", "OpenLeft", typeof(SearchResultsPanel)); public static readonly RoutedUICommand OpenRight = new("Open section in new tab", "OpenRight", typeof(SearchResultsPanel)); } public class SearchResultInfo { public delegate Task SectionTextDelegate(SearchResultKind resultKind, IRTextSection section); public enum SearchResultKind { SectionResult, BeforeOutputResult, AfterOutputResult } private static readonly FontFamily PreviewFont = new("Consolas"); private bool isMarked_; private TextBlock preview_; private Brush textColor_; private SectionTextDelegate getSectionText_; public SearchResultInfo(SearchResultKind resultkind, int index, TextSearchResult result, IRTextSection section, IUISession session, SectionTextDelegate getSectionText) { ResultKind = resultkind; Index = index; Result = result; Section = section; Session = session; getSectionText_ = getSectionText; } public SearchResultKind ResultKind { get; set; } public int Index { get; set; } public TextSearchResult Result { get; set; } public IRTextSection Section { get; set; } public IUISession Session { get; set; } public string FunctionName => Section.ParentFunction.FormatFunctionName(Session); public TextBlock Preview { get { if (preview_ != null) { return preview_; } preview_ = new TextBlock(); preview_.FontFamily = PreviewFont; preview_.Foreground = Brushes.Black; preview_.Margin = new Thickness(0, 2, 0, 0); // Load text on-demand and extract the line with the result. //? TODO: use NotifyTask https://stackoverflow.com/a/48217792 string sectionText = getSectionText_(ResultKind, Section).Result; (int startOffset, int endOffset) = ExtractTextLine(sectionText); // Append text before search result. if (startOffset < Result.Offset) { preview_.Inlines.Add(sectionText.Substring(startOffset, Result.Offset - startOffset)); } // Append search result. preview_.Inlines.Add(new Run(sectionText.Substring(Result.Offset, Result.Length)) { FontWeight = FontWeights.Bold, Background = Brushes.Khaki }); // Append text after search result. int afterResultOffset = Result.Offset + Result.Length; if (endOffset > afterResultOffset) { preview_.Inlines.Add(sectionText.Substring(afterResultOffset, endOffset - afterResultOffset)); } return preview_; } } public string SectionName { get { string name = Session.CompilerInfo.NameProvider.GetSectionName(Section); return $"({Section.Number}) {name}"; } } public Brush TextColor => textColor_; public bool IsMarked { get { if (isMarked_) { return true; } if (Session.SectionStyleProvider.IsMarkedSection(Section, out var markedName)) { isMarked_ = true; textColor_ = ColorBrushes.GetBrush(markedName.TextColor); } return isMarked_; } } private bool IsNewLine(char value) { return value == '\n' || value == '\r'; } private (int, int) ExtractTextLine(string sectionText) { // Extract the whole line containing the search result. int startOffset = Result.Offset; int endOffset = Result.Offset + Result.Length; while (startOffset > 0) { if (IsNewLine(sectionText[startOffset])) { startOffset++; // Don't include the newline itself. break; } startOffset--; } while (endOffset < sectionText.Length) { if (IsNewLine(sectionText[endOffset])) { endOffset--; break; } endOffset++; } return (startOffset, endOffset); } } public partial class SearchResultsPanel : ToolPanelControl, INotifyPropertyChanged { private SearchInfo searchInfo_; private List searchResults_; private Dictionary searchResultsMap_; private IRTextSection previousSection_; private string previousSectionText_; private string previousSectionBeforeOutput_; private string previousSectionAfterOutput_; private bool hideToolbarTray_; private bool hideSearchedText_; private string optionalText_; private CancelableTaskInstance loadTask_; public SearchResultsPanel() { InitializeComponent(); DataContext = this; loadTask_ = new CancelableTaskInstance(false); } public bool HideToolbarTray { get => hideToolbarTray_; set { if (hideToolbarTray_ != value) { hideToolbarTray_ = value; NotifyPropertyChanged(nameof(HideToolbarTray)); } } } public bool HideSearchedText { get => hideSearchedText_; set { if (hideSearchedText_ != value) { hideSearchedText_ = value; NotifyPropertyChanged(nameof(HideSearchedText)); } } } public string OptionalText { get => optionalText_; set { if (optionalText_ != value) { optionalText_ = value; NotifyPropertyChanged(nameof(OptionalText)); } } } public override ToolPanelKind PanelKind => ToolPanelKind.SearchResults; public event PropertyChangedEventHandler PropertyChanged; public event EventHandler OpenSection; public void NotifyPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async void ListViewItem_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var searchResult = ((ListViewItem)sender).DataContext as SearchResultInfo; await JumpToSearchResult(searchResult); } private async Task JumpToSearchResult(SearchResultInfo result) { // If the document is in the middle of switching a section // from the previous jump, wait for it to complete, otherwise // the document text can get out of sync and assert. using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); var documentHost = Session.FindAssociatedDocumentHost(this); if (documentHost == null) { // Document may have been closed in the meantime. var args = new OpenSectionEventArgs(result.Section, OpenSectionKind.NewTabDockLeft); documentHost = await Session.SwitchDocumentSectionAsync(args); } if (!documentHost.HasSameSearchResultSection(result.Section)) { var searchResults = searchResultsMap_[result.Section]; await documentHost.SwitchSearchResultsAsync(searchResults, result.Section, searchInfo_); } documentHost.JumpToSearchResult(result.Result, result.Index - 1); } private async Task JumpToSelectedSearchResult() { await JumpToSearchResult(ResultList.Items[ResultList.SelectedIndex] as SearchResultInfo); } private async void JumpToSelectedExecuted(object sender, ExecutedRoutedEventArgs e) { var result = e.Parameter as SearchResultInfo; await JumpToSearchResult(result); e.Handled = true; } private async void JumpToNextExecuted(object sender, ExecutedRoutedEventArgs e) { if (ResultList.SelectedIndex < ResultList.Items.Count - 1) { ResultList.SelectedIndex++; ResultList.ScrollIntoView(ResultList.SelectedItem); await JumpToSelectedSearchResult(); e.Handled = true; } } private async void JumpToPreviousExecuted(object sender, ExecutedRoutedEventArgs e) { if (ResultList.SelectedIndex > 0) { ResultList.SelectedIndex--; ResultList.ScrollIntoView(ResultList.SelectedItem); await JumpToSelectedSearchResult(); e.Handled = true; } } private async void JumpToNextSectionExecuted(object sender, ExecutedRoutedEventArgs e) { int index = ResultList.SelectedIndex; if (index < 0) { index = 0; } if (index < ResultList.Items.Count - 1) { var startSection = searchResults_[index].Section; for (++index; index < ResultList.Items.Count; index++) { var section = searchResults_[index].Section; if (section != startSection) { ResultList.SelectedItem = searchResults_[index]; ResultList.ScrollIntoView(ResultList.SelectedItem); await JumpToSelectedSearchResult(); e.Handled = true; break; } } } } private async void JumpToPreviousSectionExecuted(object sender, ExecutedRoutedEventArgs e) { int index = ResultList.SelectedIndex; if (index > 0) { var startSection = searchResults_[index].Section; for (--index; index >= 0; index--) { var section = searchResults_[index].Section; if (section != startSection) { ResultList.SelectedItem = searchResults_[index]; ResultList.ScrollIntoView(ResultList.SelectedItem); await JumpToSelectedSearchResult(); e.Handled = true; break; } } } } private async void OpenInNewTabExecuted(object sender, ExecutedRoutedEventArgs e) { var result = e.Parameter as SearchResultInfo; if (result != null) { OpenSection?.Invoke(this, new OpenSectionEventArgs(result.Section, OpenSectionKind.NewTab)); await JumpToSearchResult(result); } } private async void OpenLeftExecuted(object sender, ExecutedRoutedEventArgs e) { var result = e.Parameter as SearchResultInfo; if (result != null) { OpenSection?.Invoke(this, new OpenSectionEventArgs(result.Section, OpenSectionKind.NewTabDockLeft)); await JumpToSearchResult(result); } } private async void OpenRightExecuted(object sender, ExecutedRoutedEventArgs e) { var result = e.Parameter as SearchResultInfo; if (result != null) { OpenSection?.Invoke(this, new OpenSectionEventArgs(result.Section, OpenSectionKind.NewTabDockRight)); await JumpToSearchResult(result); } } public override async Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { await base.OnDocumentSectionUnloaded(section, document); ResetSectionTextCache(); } public void UpdateSearchResults(List results, SearchInfo searchInfo) { searchResults_ = new List(8192); searchResultsMap_ = new Dictionary(results.Count); searchInfo_ = searchInfo; foreach (var sectionResult in results) { searchResultsMap_[sectionResult.Section] = sectionResult; int index = 1; foreach (var result in sectionResult.Results) { AddSearchResult(sectionResult, index, result, SearchResultInfo.SearchResultKind.SectionResult); index++; } if (sectionResult.BeforeOutputResults != null) { foreach (var result in sectionResult.BeforeOutputResults) { AddSearchResult(sectionResult, index, result, SearchResultInfo.SearchResultKind.BeforeOutputResult); index++; } } if (sectionResult.AfterOutputResults != null) { foreach (var result in sectionResult.AfterOutputResults) { AddSearchResult(sectionResult, index, result, SearchResultInfo.SearchResultKind.AfterOutputResult); index++; } } } UpdateResultList(searchInfo.SearchedText, searchResults_); ResetSectionTextCache(); } private void AddSearchResult(SectionSearchResult sectionResult, int index, TextSearchResult result, SearchResultInfo.SearchResultKind resultKind) { var resultInfo = new SearchResultInfo(resultKind, index++, result, sectionResult.Section, Session, GetSectionText); searchResults_.Add(resultInfo); } private async Task GetSectionText(SearchResultInfo.SearchResultKind resultKind, IRTextSection section) { switch (resultKind) { case SearchResultInfo.SearchResultKind.SectionResult: { if (previousSection_ == section && previousSectionText_ != null) { return previousSectionText_; } string text = await Session.GetSectionTextAsync(section).ConfigureAwait(false); previousSection_ = section; previousSectionText_ = text; return text; } case SearchResultInfo.SearchResultKind.BeforeOutputResult: { if (previousSection_ == section && previousSectionBeforeOutput_ != null) { return previousSectionBeforeOutput_; } string text = await Session.GetSectionOutputTextAsync(section.OutputBefore, section).ConfigureAwait(false); previousSection_ = section; previousSectionBeforeOutput_ = text; return text; } case SearchResultInfo.SearchResultKind.AfterOutputResult: { if (previousSection_ == section && previousSectionAfterOutput_ != null) { return previousSectionAfterOutput_; } string text = await Session.GetSectionOutputTextAsync(section.OutputAfter, section).ConfigureAwait(false); previousSection_ = section; previousSectionAfterOutput_ = text; return text; } } return string.Empty; } private void ResetSectionTextCache() { previousSection_ = null; previousSectionText_ = null; previousSectionBeforeOutput_ = null; previousSectionAfterOutput_ = null; } public void ClearSearchResults() { UpdateResultList("", new List()); } private void UpdateResultList(string searchedText, List searchResults) { searchResults_ = searchResults; ResultList.ItemsSource = new ListCollectionView(searchResults_); ResultNumberText.Text = searchResults_.Count.ToString(); SearchedText.Text = searchedText; if (ResultList.Items.Count > 0) { ResultList.ScrollIntoView(ResultList.Items[0]); } } public override void OnSessionEnd() { base.OnSessionEnd(); ClearSearchResults(); } } ================================================ FILE: src/ProfileExplorerUI/Panels/SectionPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/SectionPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Web; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using ClosedXML.Excel; using HtmlAgilityPack; using ProfileExplorer.Core; using ProfileExplorer.Core.Analysis; using ProfileExplorer.UI.Compilers; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Panels; using ProfileExplorer.UI.Profile; using ProtoBuf; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Document.Renderers.Highlighters; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Profile.Data; using PerformanceCounter = ProfileExplorer.Core.Profile.Data.PerformanceCounter; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Compilers.ASM; using ProfileExplorer.Core.Diff; namespace ProfileExplorer.UI; public enum OpenSectionKind { ReplaceCurrent, ReplaceLeft, ReplaceRight, NewTab, NewTabDockLeft, NewTabDockRight } public enum SectionFieldKind { Number, Name, Blocks } public enum FunctionFieldKind { Name, AlternateName, Sections, Module, Optional, Optional2, StatisticSize, StatisticInstructions, StatisticLoads, StatisticStores, StatisticBranches, StatisticCalls, StatisticCallees, StatisticCallers, StatisticIndirectCalls, StatisticDiff, PerformanceCounter } public enum ChildFunctionFieldKind { Name, AlternateName, Time, Children } public enum ModuleFieldKind { Name, Time } //? TODo; Commands can be defined in code-behind with the RelayCommand pattern, //? will remove this and a lot of other Xaml code // https://www.c-sharpcorner.com/UploadFile/20c06b/icommand-and-relaycommand-in-wpf/ // https://stackoverflow.com/questions/19573380/pass-different-commandparameters-to-same-command-using-relaycommand-wpf // https://stackoverflow.com/questions/1361350/keyboard-shortcuts-in-wpf //? https://stackoverflow.com/questions/13826504/how-do-you-bind-a-command-to-a-menuitem-wpf public static class Command { public static readonly RoutedUICommand ClearTextbox = new("Clear text", "ClearTextbox", typeof(SectionPanel)); public static readonly RoutedUICommand Open = new("Open section", "Open", typeof(SectionPanel)); public static readonly RoutedUICommand OpenInNewTab = new("Open section in new tab", "OpenInNewTab", typeof(SectionPanel)); public static readonly RoutedUICommand OpenLeft = new("Open section in new tab", "OpenLeft", typeof(SectionPanel)); public static readonly RoutedUICommand OpenRight = new("Open section in new tab", "OpenRight", typeof(SectionPanel)); public static readonly RoutedUICommand OpenSideBySide = new("Open section in new tab", "OpenSideBySide", typeof(SectionPanel)); public static readonly RoutedUICommand DiffSideBySide = new("Open section in new tab", "DiffSideBySide", typeof(SectionPanel)); public static readonly RoutedUICommand DiffWithOtherDocument = new("Open section in new tab", "DiffWithOtherDocument", typeof(SectionPanel)); public static readonly RoutedUICommand SyncDiffedDocuments = new("Untitled", "SyncDiffedDocuments", typeof(SectionPanel)); public static readonly RoutedUICommand ToggleTag = new("Toggle tag", "ToggleTag", typeof(SectionPanel)); public static readonly RoutedUICommand PreviousSection = new("Untitled", "PreviousSection", typeof(SectionPanel)); public static readonly RoutedUICommand NextSection = new("Untitled", "NextSection", typeof(SectionPanel)); public static readonly RoutedUICommand FocusSearch = new("Untitled", "FocusSearch", typeof(SectionPanel)); public static readonly RoutedUICommand CopySectionText = new("Untitled", "CopySectionText", typeof(SectionPanel)); public static readonly RoutedUICommand SaveSectionText = new("Untitled", "SaveSectionText", typeof(SectionPanel)); public static readonly RoutedUICommand SaveFunctionText = new("Untitled", "SaveFunctionText", typeof(SectionPanel)); public static readonly RoutedUICommand CopyFunctionText = new("Untitled", "CopyFunctionText", typeof(SectionPanel)); public static readonly RoutedUICommand OpenDocumentInEditor = new("Untitled", "OpenDocumentInEditor", typeof(SectionPanel)); public static readonly RoutedUICommand OpenDocumentInNewInstance = new("Untitled", "OpenDocumentInNewInstance", typeof(SectionPanel)); public static readonly RoutedUICommand DisplayCallGraph = new("Untitled", "DisplayCallGraph", typeof(SectionPanel)); public static readonly RoutedUICommand DisplayPartialCallGraph = new("Untitled", "DisplayPartialCallGraph", typeof(SectionPanel)); public static readonly RoutedUICommand CopyFunctionName = new("Untitled", "CopyFunctionName", typeof(SectionPanel)); public static readonly RoutedUICommand CopyDemangledFunctionName = new("Untitled", "CopyDemangledFunctionName", typeof(SectionPanel)); public static readonly RoutedUICommand ExportFunctionList = new("Untitled", "ExportFunctionList", typeof(SectionPanel)); public static readonly RoutedUICommand ExportModuleList = new("Untitled", "ExportModuleList", typeof(SectionPanel)); public static readonly RoutedUICommand CopyFunctionDetails = new("Untitled", "CopyFunctionDetails", typeof(SectionPanel)); public static readonly RoutedUICommand ExportFunctionListHtml = new("Untitled", "ExportFunctionListHtml", typeof(SectionPanel)); public static readonly RoutedUICommand ExportFunctionListMarkdown = new("Untitled", "ExportFunctionListMarkdown", typeof(SectionPanel)); } public class OpenSectionEventArgs : EventArgs { public OpenSectionEventArgs(IRTextSection section, OpenSectionKind kind, IRDocumentHost targetDocument = null) { Section = section; OpenKind = kind; TargetDocument = targetDocument; } public IRTextSection Section { get; set; } public OpenSectionKind OpenKind { get; set; } public IRDocumentHost TargetDocument { get; set; } } public class DiffModeEventArgs : EventArgs { public bool IsWithOtherDocument { get; set; } public OpenSectionEventArgs Left { get; set; } public OpenSectionEventArgs Right { get; set; } } public class DisplayCallGraphEventArgs : EventArgs { public DisplayCallGraphEventArgs(IRTextSummary summary, IRTextSection section, bool buildPartialGraph) { Summary = summary; Section = section; BuildPartialGraph = buildPartialGraph; } public IRTextSummary Summary { get; set; } public IRTextSection Section { get; set; } public bool BuildPartialGraph { get; set; } } public class IRTextDiffBaseEx { protected DiffKind diffKind_; public IRTextDiffBaseEx(DiffKind diffKind) { diffKind_ = diffKind; } public bool IsInsertionDiff => diffKind_ == DiffKind.Insertion; public bool IsDeletionDiff => diffKind_ == DiffKind.Deletion; public bool IsModificationDiff => diffKind_ == DiffKind.Modification || diffKind_ == DiffKind.MinorModification; public bool IsPlaceholderDiff => diffKind_ == DiffKind.Placeholder; public bool HasDiffs => diffKind_ == DiffKind.Modification; public Brush NewSectionBrush => ColorBrushes.GetBrush(App.Settings.SectionSettings.NewSectionColor); public Brush MissingSectionBrush => ColorBrushes.GetBrush(App.Settings.SectionSettings.MissingSectionColor); public Brush ChangedSectionBrush => ColorBrushes.GetBrush(App.Settings.SectionSettings.ChangedSectionColor); } public class IRTextSectionEx : IRTextDiffBaseEx, INotifyPropertyChanged { private bool isSelected_; private bool isTagged_; private Thickness borderThickness_; private Brush borderBrush_; private string name_; private bool isDiffFromPrevious_; private bool isMarked_; public IRTextSectionEx(IRTextSection section, int index) : base(DiffKind.None) { Section = section; Index = index; } public IRTextSectionEx(IRTextSection section, DiffKind diffKind, string name, int index) : base(diffKind) { Section = section; Name = name; Index = index; } public int Index { get; set; } public IRTextSection Section { get; set; } public Thickness BorderThickness { get => borderThickness_; set { borderThickness_ = value; OnPropertyChanged(nameof(BorderThickness)); } } public bool HasBeforeBorder => BorderThickness.Top != 0; public bool HasAfterBorder => BorderThickness.Bottom != 0; public Brush BorderBrush { get => borderBrush_; set { borderBrush_ = value; OnPropertyChanged(nameof(BorderBrush)); } } public string Name { get => name_; set { name_ = value; OnPropertyChanged(nameof(Name)); } } public DiffKind SectionDiffKind { get => diffKind_; set { diffKind_ = value; OnPropertyChanged(nameof(IsInsertionDiff)); OnPropertyChanged(nameof(IsDeletionDiff)); OnPropertyChanged(nameof(IsPlaceholderDiff)); OnPropertyChanged(nameof(HasDiffs)); } } public bool IsTagged { get => isTagged_; set { isTagged_ = value; OnPropertyChanged(nameof(IsTagged)); } } public bool IsDiffFromPrevious { get => isDiffFromPrevious_; set { isDiffFromPrevious_ = value; OnPropertyChanged(nameof(IsDiffFromPrevious)); } } public bool IsSelected { get => isSelected_; set { isSelected_ = value; OnPropertyChanged(nameof(IsSelected)); } } public bool IsMarked { get => isMarked_; set { isMarked_ = value; OnPropertyChanged(nameof(IsMarked)); } } public Brush TextColor { get; set; } public Brush BackColor { get; set; } public bool LowerIdenticalToPreviousOpacity { get; set; } public string NumberString => Section != null ? Section.Number.ToString() : ""; public string BlockCountString => Section != null ? Section.BlockCount.ToString() : ""; public int Number => Section?.Number ?? 0; public int BlockCount => Section?.BlockCount ?? 0; public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } } public class PerformanceCounterSetEx { public PerformanceCounterSetEx(int count) { Counters = new List(count); } public List Counters { get; set; } public string this[int perfCounterId] => FindCounterLabel(perfCounterId); public string FindCounterLabel(int perfCounterId) { int index = Counters.FindIndex(item => item.CounterId == perfCounterId); return index != -1 ? Counters[index].Label : null; } public double FindCounterValue(int perfCounterId) { int index = Counters.FindIndex(item => item.CounterId == perfCounterId); return index != -1 ? Counters[index].Value : 0; } public void Add(PerformanceCounterValueEx counterEx) { Counters.Add(counterEx); } public class PerformanceCounterValueEx { public int CounterId { get; set; } public double Value { get; set; } public string Label { get; set; } } } public class IRTextFunctionEx : IRTextDiffBaseEx, INotifyPropertyChanged { private string functionName_; private FunctionNameFormatter funcNameFormatter_; private bool isMarked_; public IRTextFunctionEx(IRTextFunction function, int index, FunctionNameFormatter funcNameFormatter) : base(DiffKind.None) { Function = function; Index = index; funcNameFormatter_ = funcNameFormatter; Statistics = new FunctionCodeStatistics(); } public virtual string Name { get { if (functionName_ != null) { return functionName_; // Cached. } functionName_ = Function.Name; if (funcNameFormatter_ != null) { functionName_ = funcNameFormatter_(functionName_); } return functionName_; } set => functionName_ = value; } public string ToolTip => DocumentUtils.FormatLongFunctionName(Name); public int Index { get; set; } public IRTextFunction Function { get; set; } public string ModuleName => Function.ModuleName; public TimeSpan Weight { get; set; } public TimeSpan ExclusiveWeight { get; set; } public string AlternateName { get; set; } public double ExclusivePercentage { get; set; } public double Percentage { get; set; } public bool IsMarked { get => isMarked_; set { isMarked_ = value; OnPropertyChanged(nameof(IsMarked)); } } public Brush TextColor { get; set; } public Brush BackColor { get; set; } public Brush BackColor2 { get; set; } public Brush ModuleBackColor { get; set; } public Brush FunctionBackColor { get; set; } public int SectionCount => Function.SectionCount; public FunctionCodeStatistics Statistics { get; set; } public FunctionCodeStatistics DiffStatistics { get; set; } public PerformanceCounterSetEx Counters { get; set; } public DiffKind FunctionDiffKind { get => diffKind_; set { diffKind_ = value; OnPropertyChanged(nameof(IsInsertionDiff)); OnPropertyChanged(nameof(IsDeletionDiff)); OnPropertyChanged(nameof(IsPlaceholderDiff)); OnPropertyChanged(nameof(HasDiffs)); } } public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyname) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname)); } } public class ModuleEx { public bool IsAllEntry { get; set; } public string Name { get; set; } public Brush BackColor { get; set; } public double ExclusivePercentage { get; set; } public TimeSpan ExclusiveWeight { get; set; } public bool BinaryFileMissing => Status != null ? !Status.IsBinaryAvailableOrPending : false; public bool DebugFileMissing { get; set; } public ProfileDataReport.ModuleStatus Status { get; set; } } [ProtoContract] public class SectionPanelState { [ProtoMember(1)] public List AnnotatedSections; [ProtoMember(2)] public int SelectedFunctionNumber; [ProtoMember(3)] public int SelectedSectionNumber; public SectionPanelState() { AnnotatedSections = new List(); } } public partial class SectionPanel : ToolPanelControl, INotifyPropertyChanged { public static readonly DependencyProperty BottomSectionToolbarProperty = DependencyProperty.Register("BottomSectionToolbar", typeof(bool), typeof(SectionPanel), new PropertyMetadata(false, OnBottomSectionToolbarPropertyChanged)); public static readonly DependencyProperty FunctionPartVisibleProperty = DependencyProperty.Register("FunctionPartVisible", typeof(bool), typeof(SectionPanel), new PropertyMetadata(true, OnFunctionPartVisiblePropertyChanged)); public static readonly DependencyProperty HideToolbarsProperty = DependencyProperty.Register("HideToolbars", typeof(bool), typeof(SectionPanel), new PropertyMetadata(false, OnHideToolbarsPropertyChanged)); private static IValueConverter DiffValueConverter = new FunctionDiffValueConverter(); private static IValueConverter DiffKindConverter = new FunctionDiffKindConverter(); private static OptionalColumn[] StatisticsColumns = { OptionalColumn.Binding("Statistics.Instructions", "InstructionsHeader", "Instrs{0}", "Instruction number{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.Size", "SizeHeader", "Size{0}", "Function size in bytes{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.Loads", "LoadsHeader", "Loads{0}", "Number of instructions reading memory{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.Stores", "StoresHeader", "Stores{0}", "Number of instructions writing memory{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.Branches", "BranchesHeader", "Branches{0}", "Number of branch/jump instructions{0}", DiffValueConverter) }; private static OptionalColumn[] CallStatisticsColumns = { OptionalColumn.Binding("Statistics.Callees", "CalleesHeader", "Callees{0}", "Number of unique called functions{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.Callers", "CallersHeader", "Callers{0}", "Number of unique caller functions{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.Calls", "CallsHeader", "Calls{0}", "Number of call instructions{0}", DiffValueConverter), OptionalColumn.Binding("Statistics.IndirectCalls", "IndirectCallsHeader", "IndirectCalls{0}", "Number of indirect/virtual call instructions{0}", DiffValueConverter) }; private static OptionalColumn[] StatisticsDiffColumns = { OptionalColumn.Binding("FunctionDiffKind", "DiffHeader", "Diff", "Difference kind (only in left/right document or modified)", DiffKindConverter) }; private HashSet annotatedSections_; private IRTextFunction currentFunction_; private string documentTitle_; private bool isDiffModeEnabled_; private bool syncDiffedDocuments_; private bool isFunctionListVisible_; private bool isSectionListVisible_; private bool useProfileCallTree_; private UISectionSettings settings_; private IRTextSummary summary_; private IRTextSummary otherSummary_; private List sections_; private List functions_; private List moduleSummaries_; private bool sectionExtensionComputed_; private Dictionary sectionExtMap_; private Dictionary functionExtMap_; private ScrollViewer sectionsScrollViewer_; private OptionsPanelHostPopup optionsPanelPopup_; private GridViewColumnValueSorter functionValueSorter_; private GridViewColumnValueSorter sectionValueSorter_; private GridViewColumnValueSorter moduleValueSorter_; private ConcurrentDictionary callGraphCache_; private ModuleReport moduleReport_; private CancelableTaskInstance statisticsTask_; private CancelableTaskInstance callGraphTask_; private ConcurrentDictionary functionStatMap_; private ModuleEx activeModuleFilter_; private bool filterTagged_; private bool filterDiffFromPrevious_; private string optionalDataColumnName_; private bool optionalDataColumnVisible_; private string optionalDataColumnName2_; private bool optionalDataColumnVisible2_; private bool alternateNameColumnVisible_; private bool childTimeColumnVisible_; private bool showChildren_; private bool showSections_; private bool profileControlsVisible_; private bool sectionCountColumnVisible_; private bool moduleControlsVisible_; private CallTreeNodePopup funcBacktracePreviewPopup_; private PopupHoverPreview preview_; private List modules_; private FunctionMarkingSettings initialMarkingSettings_; private TextSearcher nameSearcher_; public SectionPanel() { InitializeComponent(); sections_ = new List(); moduleSummaries_ = new List(); sectionExtMap_ = new Dictionary(); functionExtMap_ = new Dictionary(); annotatedSections_ = new HashSet(); IsFunctionListVisible = true; IsSectionListVisible = false; ShowSections = false; SectionCountColumnVisible = true; SyncDiffedDocuments = true; MainGrid.DataContext = this; settings_ = App.Settings.SectionSettings; functionValueSorter_ = new GridViewColumnValueSorter(FunctionList, name => name switch { "FunctionColumnHeader" => FunctionFieldKind.Name, "AlternateNameColumnHeader" => FunctionFieldKind.AlternateName, "SectionsColumnHeader" => FunctionFieldKind.Sections, "FunctionModuleColumnHeader" => FunctionFieldKind.Module, "OptionalColumnHeader" => FunctionFieldKind.Optional, "OptionalColumnHeader2" => FunctionFieldKind.Optional2, "SizeHeader" => FunctionFieldKind.StatisticSize, "LoadsHeader" => FunctionFieldKind.StatisticLoads, "StoresHeader" => FunctionFieldKind.StatisticStores, "InstructionsHeader" => FunctionFieldKind. StatisticInstructions, "BranchesHeader" => FunctionFieldKind.StatisticBranches, "CallsHeader" => FunctionFieldKind.StatisticCalls, "CallersHeader" => FunctionFieldKind.StatisticCallers, "CalleesHeader" => FunctionFieldKind.StatisticCallees, "IndirectCallsHeader" => FunctionFieldKind. StatisticIndirectCalls, "DiffHeader" => FunctionFieldKind.StatisticDiff, _ => FunctionFieldKind.PerformanceCounter }, (x, y, field, direction, tag) => { var functionX = x as IRTextFunctionEx; var functionY = y as IRTextFunctionEx; switch (field) { case FunctionFieldKind.Sections: { int result = functionY.SectionCount - functionX.SectionCount; return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.Name: { int result = string.Compare( functionY.Name, functionX.Name, StringComparison.OrdinalIgnoreCase); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.AlternateName: { int result = string.Compare( functionY.AlternateName, functionX.AlternateName, StringComparison.OrdinalIgnoreCase); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.Module: { int result = string.Compare( functionY.ModuleName, functionX.ModuleName, StringComparison.OrdinalIgnoreCase); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.Optional: { int result = functionY.ExclusiveWeight.CompareTo( functionX.ExclusiveWeight); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.Optional2: { int result = functionY.Weight.CompareTo(functionX.Weight); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticSize: { int result = functionY.Statistics.Size.CompareTo( functionX.Statistics.Size); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticInstructions: { int result = functionY.Statistics.Instructions.CompareTo( functionX.Statistics.Instructions); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticLoads: { int result = functionY.Statistics.Loads.CompareTo( functionX.Statistics.Loads); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticStores: { int result = functionY.Statistics.Stores.CompareTo( functionX.Statistics.Stores); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticBranches: { int result = functionY.Statistics.Branches.CompareTo( functionX.Statistics.Branches); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticCalls: { int result = functionY.Statistics.Calls.CompareTo( functionX.Statistics.Calls); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticCallees: { int result = functionY.Statistics.Callees.CompareTo( functionX.Statistics.Callees); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticCallers: { int result = functionY.Statistics.Callers.CompareTo( functionX.Statistics.Callers); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticIndirectCalls: { int result = functionY.Statistics.IndirectCalls.CompareTo( functionX.Statistics.IndirectCalls); return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.StatisticDiff: { int result = 0; if (functionY.FunctionDiffKind != functionX.FunctionDiffKind) { if (functionY.IsDeletionDiff || functionX.IsInsertionDiff) { result = -1; } else if (functionY.IsInsertionDiff || functionX.IsDeletionDiff) { result = 1; } else if (functionY.IsModificationDiff) { result = -1; } else if (functionX.IsModificationDiff) { result = 1; } else { result = string.Compare( functionY.Name, functionX.Name, StringComparison.Ordinal); } } else { result = string.Compare( functionY.Name, functionX.Name, StringComparison.Ordinal); } return direction == ListSortDirection.Ascending ? -result : result; } case FunctionFieldKind.PerformanceCounter: { if (tag is PerformanceCounter counter) { int result = 0; if (functionX.Counters != null && functionY.Counters != null) { double valueX = functionX.Counters.FindCounterValue(counter.Id); double valueY = functionY.Counters.FindCounterValue(counter.Id); result = valueX.CompareTo(valueY); } else if (functionY.Counters == null && functionX.Counters != null) { result = 1; } else if (functionX.Counters == null && functionY.Counters != null) { result = -1; } return direction == ListSortDirection.Ascending ? -result : result; } return 0; } default: throw new ArgumentOutOfRangeException(); } }); sectionValueSorter_ = new GridViewColumnValueSorter(SectionList, name => name switch { "NumberColumnHeader" => SectionFieldKind.Number, "NameColumnHeader" => SectionFieldKind.Name, "BlocksColumnHeader" => SectionFieldKind.Blocks, _ => throw new ArgumentOutOfRangeException() }, (x, y, field, direction, tag) => { var sectionX = x as IRTextSectionEx; var sectionY = y as IRTextSectionEx; switch (field) { case SectionFieldKind.Number: { int result = sectionY.Number - sectionX.Number; return direction == ListSortDirection.Ascending ? -result : result; } case SectionFieldKind.Name: { int result = string.Compare( sectionY.Name, sectionX.Name, StringComparison.Ordinal); return direction == ListSortDirection.Ascending ? -result : result; } case SectionFieldKind.Blocks: { int result = sectionY.BlockCount - sectionX.BlockCount; return direction == ListSortDirection.Ascending ? -result : result; } default: throw new ArgumentOutOfRangeException(); } }); moduleValueSorter_ = new GridViewColumnValueSorter(ModulesList, name => name switch { "ModuleColumnHeader" => ModuleFieldKind.Name, _ => throw new ArgumentOutOfRangeException() }, (x, y, field, direction, tag) => { var moduleX = x as ModuleEx; var moduleY = y as ModuleEx; switch (field) { case ModuleFieldKind.Name: { // Always sort modules by time. int result = moduleY.ExclusiveWeight.CompareTo(moduleX.ExclusiveWeight); return direction == ListSortDirection.Ascending ? -result : result; } default: throw new ArgumentOutOfRangeException(); } }); } public FunctionMarkingSettings MarkingSettings => App.Settings.MarkingSettings; //? TODO: Replace all other commands with RelayCommand. public RelayCommand SelectFunctionCallTreeCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.CallTree); }); public RelayCommand SelectFunctionFlameGraphCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.FlameGraph); }); public RelayCommand SelectFunctionTimelineCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.Timeline); }); public RelayCommand PreviewFunctionCommand => new(async obj => { if (obj is IRTextFunctionEx funcEx) { var brush = GetMarkedNodeColor(funcEx); await IRDocumentPopupInstance.ShowPreviewPopup(funcEx.Function, "", FunctionList, Session, null, false, brush); } }); public RelayCommand CopyAllFunctionsCommand => new(async obj => { CopyFunctionListAsHtml(true); }); public bool BottomSectionToolbar { get => (bool)GetValue(BottomSectionToolbarProperty); set => SetValue(BottomSectionToolbarProperty, value); } public bool FunctionPartVisible { get => (bool)GetValue(FunctionPartVisibleProperty); set => SetValue(FunctionPartVisibleProperty, value); } public bool HideToolbars { get => (bool)GetValue(HideToolbarsProperty); set => SetValue(HideToolbarsProperty, value); } public bool IsFunctionListVisible { get => isFunctionListVisible_; set { if (isFunctionListVisible_ != value) { isFunctionListVisible_ = value; OnPropertyChanged(); } } } public bool IsSectionListVisible { get => isSectionListVisible_; set { if (isSectionListVisible_ != value) { isSectionListVisible_ = value; OnPropertyChanged(); } } } public string DocumentTitle { get => documentTitle_; set { if (documentTitle_ != value) { documentTitle_ = value; OnPropertyChanged(); } } } public bool IsDiffModeEnabled { get => isDiffModeEnabled_; set { if (isDiffModeEnabled_ != value) { isDiffModeEnabled_ = value; OnPropertyChanged(); } } } public bool SyncDiffedDocuments { get => syncDiffedDocuments_; set { if (syncDiffedDocuments_ != value) { syncDiffedDocuments_ = value; OnPropertyChanged(); SyncDiffedDocumentsChanged?.Invoke(this, value); } } } public bool FilterTagged { get => filterTagged_; set { if (filterTagged_ != value) { filterTagged_ = value; OnPropertyChanged(); RefreshSectionList(); } } } public bool FilterDiffFromPrevious { get => filterDiffFromPrevious_; set { if (filterDiffFromPrevious_ != value) { filterDiffFromPrevious_ = value; OnPropertyChanged(); RefreshSectionList(); } } } public bool UseProfileCallTree { get => useProfileCallTree_; set { if (useProfileCallTree_ != value) { useProfileCallTree_ = value; OnPropertyChanged(); OnPropertyChanged(nameof(UseIRCallTree)); } } } public bool UseIRCallTree { get => !useProfileCallTree_; set { if (useProfileCallTree_ == value) { useProfileCallTree_ = !value; OnPropertyChanged(nameof(UseProfileCallTree)); OnPropertyChanged(); } } } public bool SyncSourceFile { get => settings_.SyncSourceFile; set { if (value != settings_.SyncSourceFile) { settings_.SyncSourceFile = value; OnPropertyChanged(); } } } public bool SyncSelection { get => settings_.SyncSelection; set { if (value != settings_.SyncSelection) { settings_.SyncSelection = value; OnPropertyChanged(); } } } //? TODO: Remember column width, order public double SelfTimeColumnWidth => settings_ is {AppendTimeToSelfColumn: true} ? 140 : 60; public double TotalTimeColumnWidth => settings_ is {AppendTimeToTotalColumn: true} ? 140 : 60; public IRTextSummary Summary { get => summary_; set { if (value != summary_) { summary_ = value; sectionExtensionComputed_ = false; } } } public IRTextSummary OtherSummary { get => otherSummary_; set { if (value != otherSummary_) { otherSummary_ = value; } } } public bool IsInTwoDocumentsMode => Session != null && Session.IsInTwoDocumentsMode; public string OptionalDataColumnName { get => optionalDataColumnName_; set { if (optionalDataColumnName_ != value) { optionalDataColumnName_ = value; OnPropertyChanged(); } } } public bool OptionalDataColumnVisible { get => optionalDataColumnVisible_; set { if (optionalDataColumnVisible_ != value) { optionalDataColumnVisible_ = value; OnPropertyChanged(); } } } public string OptionalDataColumnName2 { get => optionalDataColumnName2_; set { if (optionalDataColumnName2_ != value) { optionalDataColumnName2_ = value; OnPropertyChanged(); } } } public bool OptionalDataColumnVisible2 { get => optionalDataColumnVisible2_; set { if (optionalDataColumnVisible2_ != value) { optionalDataColumnVisible2_ = value; OnPropertyChanged(); } } } public bool AlternateNameColumnVisible { get => alternateNameColumnVisible_; set { if (alternateNameColumnVisible_ != value) { alternateNameColumnVisible_ = value; OnPropertyChanged(); } } } public bool ChildTimeColumnVisible { get => childTimeColumnVisible_; set { if (childTimeColumnVisible_ != value) { childTimeColumnVisible_ = value; OnPropertyChanged(); } } } public bool ShowModules { get => settings_.ShowModulePanel; set { if (settings_.ShowModulePanel != value) { settings_.ShowModulePanel = value; OnPropertyChanged(); ResizeFunctionFilter(FunctionToolbar.RenderSize.Width); } } } public bool ShowChildren { get => showChildren_; set { if (showChildren_ != value) { showChildren_ = value; if (showChildren_) { ShowSections = false; IsSectionListVisible = true; } else { IsSectionListVisible = false; } OnPropertyChanged(nameof(ShowSections)); OnPropertyChanged(); OnPropertyChanged(nameof(IsSectionListVisible)); ResizeFunctionFilter(FunctionToolbar.RenderSize.Width); } } } public bool ShowSections { get => showSections_; set { if (showSections_ != value) { showSections_ = value; if (showSections_) { ShowChildren = false; IsSectionListVisible = true; } else { IsSectionListVisible = false; } OnPropertyChanged(); OnPropertyChanged(nameof(ShowChildren)); OnPropertyChanged(nameof(IsSectionListVisible)); ResizeFunctionFilter(FunctionToolbar.RenderSize.Width); } } } public bool ProfileControlsVisible { get => profileControlsVisible_; set { if (profileControlsVisible_ != value) { profileControlsVisible_ = value; OnPropertyChanged(); } } } public bool SectionCountColumnVisible { get => sectionCountColumnVisible_; set { if (sectionCountColumnVisible_ != value) { sectionCountColumnVisible_ = value; OnPropertyChanged(); } } } public bool ModuleControlsVisible { get => moduleControlsVisible_; set { if (moduleControlsVisible_ != value) { moduleControlsVisible_ = value; OnPropertyChanged(); } } } public IRTextFunction CurrentFunction => currentFunction_; public bool HasAnnotatedSections => annotatedSections_.Count > 0; public ICompilerInfoProvider CompilerInfo { get; set; } public override ToolPanelKind PanelKind => ToolPanelKind.Section; public override bool SavesStateToFile => true; public List Sections { get => sections_; set { if (sections_ != value) { sections_ = value; foreach (var sectionEx in sections_) { if (sectionEx.Section != null) { sectionExtMap_[sectionEx.Section] = sectionEx; } } UpdateSectionListView(); } } } public UISectionSettings Settings { get => settings_; set => settings_ = value; } public RelayCommand MarkModuleCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; MarkSelectedNodes(obj, (node, color) => markingSettings.AddModuleColor(node.ModuleName, color)); markingSettings.UseModuleColors = true; await UpdateMarkedFunctions(); }); public RelayCommand MarkFunctionCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; MarkSelectedNodes(obj, (node, color) => { if (settings_.ShowDemangledNames) { markingSettings.AddFunctionColor(node.AlternateName, color); } else { markingSettings.AddFunctionColor(node.Name, color); } }); markingSettings.UseFunctionColors = true; await UpdateMarkedFunctions(); }); public event PropertyChangedEventHandler PropertyChanged; public event EventHandler FunctionSwitched; public event EventHandler OpenSection; public event EventHandler EnterDiffMode; public event EventHandler SectionListScrollChanged; public event EventHandler SyncDiffedDocumentsChanged; public event EventHandler DisplayCallGraph; private Brush GetMarkedNodeColor(IRTextFunctionEx node) { return App.Settings.MarkingSettings. GetMarkedNodeBrush(node.Name, node.ModuleName); } private static void OnBottomSectionToolbarPropertyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as SectionPanel; bool placeBottom = (bool)e.NewValue; if (placeBottom) { source.FunctionPartVisible = false; var row0 = source.SectionGrid.RowDefinitions[0]; var row1 = source.SectionGrid.RowDefinitions[1]; double row0Value = row0.Height.Value; var row0Type = row0.Height.GridUnitType; source.SectionGrid.RowDefinitions[0].Height = new GridLength(row1.Height.Value, row1.Height.GridUnitType); source.SectionGrid.RowDefinitions[1].Height = new GridLength(row0Value, row0Type); Grid.SetRow(source.SectionList, 0); Grid.SetRow(source.SectionToolbarGrid, 1); // Hide the settings button. source.FixedToolbar.Visibility = Visibility.Collapsed; source.SectionToolbarGrid.ColumnDefinitions[1].Width = new GridLength(0); } } private static void OnFunctionPartVisiblePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as SectionPanel; bool visible = (bool)e.NewValue; if (visible) { source.FunctionPart.Visibility = Visibility.Visible; } else { //? TODO: Can be moved to XAML, similar to RemarkPanel.xaml source.MainGrid.ColumnDefinitions[0].Width = new GridLength(0, GridUnitType.Pixel); source.MainGrid.ColumnDefinitions[1].Width = new GridLength(0, GridUnitType.Pixel); source.MainGrid.ColumnDefinitions[2].Width = new GridLength(1, GridUnitType.Star); } } private static void OnHideToolbarsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var source = d as SectionPanel; bool hide = (bool)e.NewValue; if (hide) { source.SectionToolbarGrid.Visibility = Visibility.Collapsed; source.SectionGrid.RowDefinitions[0].Height = new GridLength(0, GridUnitType.Pixel); } } public void SetSectionAnnotationState(IRTextSection section, bool hasAnnotations) { if (!settings_.MarkAnnotatedSections) { return; } if (!sectionExtMap_.ContainsKey(section)) { return; } var sectionExt = sectionExtMap_[section]; if (hasAnnotations) { sectionExt.IsTagged = true; annotatedSections_.Add(sectionExt); } else if (annotatedSections_.Contains(sectionExt)) { sectionExt.IsTagged = false; annotatedSections_.Remove(sectionExt); } } public void SelectSection(IRTextSection section, bool focus = true, bool force = false) { SetupSectionList(section.ParentFunction, force); var sectionEx = GetSectionExtension(section); SectionList.SelectedItem = sectionEx; if (sectionEx != null) { MarkCurrentSection(sectionEx); BringIntoViewSelectedListItem(SectionList, focus); } } public void AddModuleSummary(IRTextSummary summary) { if (!moduleSummaries_.Contains(summary)) { moduleSummaries_.Add(summary); sectionExtensionComputed_ = false; } } public void ClearModuleSummaries() { moduleSummaries_.Clear(); sectionExtensionComputed_ = false; } public bool HasSummary(IRTextSummary summary) { return summary == summary_ || moduleSummaries_.Contains(summary); } public IRTextSummary FindModuleSummary(string name) { if (summary_.ModuleName == name) { return summary_; } return moduleSummaries_.Find(item => item.ModuleName == name); } public void RegisterSectionListScrollEvent() { if (sectionsScrollViewer_ != null) { return; } // The internal ScrollViewer is not created until items are added, // this is the reason the event is registered in the constructor. sectionsScrollViewer_ = Utils.FindChild(SectionList); if (sectionsScrollViewer_ != null) { sectionsScrollViewer_.ScrollChanged += SectionsScrollViewer__ScrollChanged; } } public async Task Update(bool force = false, bool analyzeFunctions = true) { if (summary_ != null) { await SetupFunctionList(force); } } public async Task ResetUI() { await ResetStatistics(); ResetSectionPanel(); } public async Task SetupFunctionList(bool force = false, bool analyzeFunctions = true) { if (summary_ == null) { await ResetUI(); return; } // Create mappings between each section and their UI counterpart. if (!SetupSectionExtensions(force)) { await ResetUI(); return; } // Create mappings between each function and their UI counterparts. // In two-document diff mode, also add entries for functions that are found // only in the left or in the right document and mark them as diffs. functions_ = SetupFunctionExtensions(); // Prepare UI. await SetupFunctionListUI(); // Attach additional data to the UI. await LoadFunctionProfile(); RestoreListViewColumnsState(); await UpdateMarkedFunctions(true); if (analyzeFunctions) { await RunFunctionAnalysis(); } } public async Task UpdateMarkedFunctions(bool externalCall = false) { if (functions_ != null) { UpdateMarkedFunctionsImpl(); if (!externalCall) { await Session.FunctionMarkingChanged(PanelKind); } } } private void UpdateMarkedFunctionsImpl() { var fgSettings = App.Settings.MarkingSettings; foreach (var f in functions_) { f.ModuleBackColor = null; f.FunctionBackColor = null; } foreach (var module in modules_) { module.BackColor = null; } if (!fgSettings.UseAutoModuleColors && !fgSettings.UseModuleColors && !fgSettings.UseFunctionColors) { RefreshFunctionList(false); return; } foreach (var funcEx in functions_) { if (fgSettings.UseModuleColors && fgSettings.GetModuleBrush(funcEx.ModuleName, out var brush)) { funcEx.ModuleBackColor = brush; } else if (fgSettings.UseAutoModuleColors) { funcEx.ModuleBackColor = fgSettings.GetAutoModuleBrush(funcEx.ModuleName); } if (fgSettings.UseFunctionColors && fgSettings.GetFunctionColor(funcEx.Name, out var color)) { funcEx.FunctionBackColor = color.AsBrush(); } } foreach (var module in modules_) { if (module.IsAllEntry) { continue; } if (fgSettings.UseModuleColors && fgSettings.GetModuleBrush(module.Name, out var brush)) { module.BackColor = brush; } else if (fgSettings.UseAutoModuleColors) { module.BackColor = fgSettings.GetAutoModuleBrush(module.Name); } } RefreshFunctionList(false); RefreshModuleList(); } public List CreateSectionsExtension(bool force = false) { if (!SetupSectionExtensions(force)) { return new List(); } var sections = new List(); int sectionIndex = 0; if (currentFunction_ == null) { return sections; } foreach (var section in currentFunction_.Sections) { #if DEBUG if (!sectionExtMap_.ContainsKey(section)) { Utils.WaitForDebugger(); } #endif var sectionEx = sectionExtMap_[section]; sectionEx = new IRTextSectionEx(section, sectionEx.Index); sectionEx.Name = CompilerInfo.NameProvider.GetSectionName(section, false); sectionExtMap_[section] = sectionEx; sections.Add(sectionEx); if (Session.SectionStyleProvider.IsMarkedSection(section, out var markedName)) { if (settings_.ColorizeSectionNames) { sectionEx.IsMarked = true; sectionEx.TextColor = ColorBrushes.GetBrush(markedName.TextColor); } else { sectionEx.IsMarked = false; } if (settings_.ShowSectionSeparators) { ApplySectionBorder(sectionEx, sectionIndex, markedName, sections); } else sectionEx.BorderThickness = new Thickness(); if (settings_.UseNameIndentation && markedName.IndentationLevel > 0) { ApplySectionNameIndentation(sectionEx, markedName); } } else { sectionEx.IsMarked = false; sectionEx.BorderThickness = new Thickness(); } sectionEx.SectionDiffKind = DiffKind.None; sectionEx.LowerIdenticalToPreviousOpacity = sectionIndex > 0 && settings_.LowerIdenticalToPreviousOpacity; sectionIndex++; } return sections; } public void DiffSelectedSection() { if (SectionList.SelectedItem != null) { var sectionEx = SectionList.SelectedItem as IRTextSectionEx; var args = new DiffModeEventArgs { IsWithOtherDocument = true, Left = new OpenSectionEventArgs(sectionEx.Section, OpenSectionKind.NewTabDockLeft) }; EnterDiffMode?.Invoke(this, args); } } public void RefreshSectionList() { if (SectionList.ItemsSource == null) { return; } nameSearcher_ = null; ((ListCollectionView)SectionList.ItemsSource).Refresh(); if (SectionList.Items.Count > 0) { SectionList.ScrollIntoView(SectionList.Items[0]); } } public void RefreshFunctionList(bool scrollToFirst = true) { if (FunctionList.ItemsSource == null) { return; } nameSearcher_ = null; ((ListCollectionView)FunctionList.ItemsSource).Refresh(); if (scrollToFirst && FunctionList.Items.Count > 0) { FunctionList.ScrollIntoView(FunctionList.Items[0]); } } public void RefreshModuleList(bool scrollToFirst = true) { if (ModulesList.ItemsSource == null) { return; } nameSearcher_ = null; ((ListCollectionView)ModulesList.ItemsSource).Refresh(); } public bool SwitchToSection(int offset, IRDocumentHost targetDocument = null) { int newIndex = SectionList.SelectedIndex + offset; while (newIndex >= 0 && newIndex < SectionList.Items.Count) { var section = Sections[newIndex]; if (!section.IsPlaceholderDiff) { // Not a diff mode placeholder, switch. SwitchToSection(section, targetDocument); return true; } // Go left or right to find first real section. if (offset > 0) { newIndex++; } else { newIndex--; } } return false; } public void SwitchToSection(IRTextSectionEx section, IRDocumentHost targetDocument = null) { SectionList.SelectedItem = section; SectionList.ScrollIntoView(SectionList.SelectedItem); OpenSectionImpl(section, OpenSectionKind.ReplaceCurrent, targetDocument); } public void SwitchToSection(IRTextSection section, IRDocumentHost targetDocument = null) { SwitchToSection(Sections.Find(item => item.Section == section), targetDocument); } public void ScrollSectionList(double offset) { RegisterSectionListScrollEvent(); sectionsScrollViewer_?.ScrollToVerticalOffset(offset); } public async Task WaitForStatistics() { await statisticsTask_.WaitForTaskAsync(); } public async Task ShowModuleReport() { if (functionStatMap_ == null) { await ComputeFunctionStatistics(functions_); await WaitForStatistics(); if (functionStatMap_ == null) { return; } } moduleReport_ = new ModuleReport(functionStatMap_); moduleReport_.Generate(); var panel = new ModuleReportPanel(Session); panel.TitleSuffix = "Function report"; panel.ShowReport(moduleReport_, summary_); Session.DisplayFloatingPanel(panel); } public void AddCountersFunctionListColumns(bool addDiffColumn, string titleSuffix = "", string tooltipSuffix = "", double columnWidth = double.NaN) { OptionalColumn.RemoveListViewColumns(FunctionList, header => header.Tag is PerformanceCounter); var counters = Session.ProfileData.SortedPerformanceCounters; for (int i = 0; i < counters.Count; i++) { var counter = counters[i]; if (!ProfileDocumentMarker.IsPerfCounterVisible(counter)) { continue; } if (!settings_.ShowPerformanceCounterColumns && !counter.IsMetric || !settings_.ShowPerformanceMetricColumns && counter.IsMetric) { continue; } string name = $"{ProfileDocumentMarker.ShortenPerfCounterName(counter.Name)}"; string tooltip = /*counter?.Config?.Description != null ? $"{counter.Config.Description}" : */ $"{counter.Name}"; int insertionIndex = -1; // Insert before the demangled func name column. if (AlternateNameColumnVisible) { insertionIndex = OptionalColumn.FindListViewColumnIndex("AlternateNameColumnHeader", FunctionList); } var gridColumn = OptionalColumn.AddListViewColumn(FunctionList, OptionalColumn.Binding( $"Counters[{counter.Id}]", $"PerfCounters{i}", name, tooltip), functionValueSorter_, "", " counter", true, insertionIndex); gridColumn.Header.Tag = counter; } } public void AddStatisticsFunctionListColumns(bool addDiffColumn, string titleSuffix = "", string tooltipSuffix = "", double columnWidth = double.NaN) { OptionalColumn.RemoveListViewColumns(FunctionList, StatisticsColumns, functionValueSorter_); OptionalColumn.RemoveListViewColumns(FunctionList, CallStatisticsColumns, functionValueSorter_); OptionalColumn.RemoveListViewColumns(FunctionList, StatisticsDiffColumns, functionValueSorter_); // Insert before the demangled func name column. int insertionIndex = -1; if (AlternateNameColumnVisible) { insertionIndex = OptionalColumn.FindListViewColumnIndex("AlternateNameColumnHeader", FunctionList); } var list = OptionalColumn.AddListViewColumns(FunctionList, StatisticsColumns, functionValueSorter_, titleSuffix, tooltipSuffix, addDiffColumn, insertionIndex); insertionIndex = insertionIndex != -1 ? insertionIndex + list.Count : -1; if (settings_.IncludeCallGraphStatistics) { var list2 = OptionalColumn.AddListViewColumns(FunctionList, CallStatisticsColumns, functionValueSorter_, titleSuffix, tooltipSuffix, addDiffColumn, insertionIndex); insertionIndex = insertionIndex != -1 ? insertionIndex + list2.Count : -1; } if (addDiffColumn) { OptionalColumn.AddListViewColumns(FunctionList, StatisticsDiffColumns, functionValueSorter_, null, null, false, insertionIndex); } } public void MarkFunctions(List list) { foreach (var func in list) { if (functionExtMap_.TryGetValue(func, out var funcEx)) { funcEx.IsMarked = true; } } } public void ClearMarkedFunctions() { foreach (var funcEx in functionExtMap_.Values) { funcEx.IsMarked = false; } } protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private async Task SelectFunctionInPanel(object target, ToolPanelKind panelKind) { if (target is IRTextFunctionEx funcEx) { await Session.SelectProfileFunctionInPanel(funcEx.Function, panelKind); } } private void BringIntoViewSelectedListItem(ListView list, bool focus) { list.ScrollIntoView(list.SelectedItem); if (focus) { var item = list.ItemContainerGenerator.ContainerFromItem(list.SelectedItem) as ListViewItem; item?.Focus(); } } private void SectionsScrollViewer__ScrollChanged(object sender, ScrollChangedEventArgs e) { SectionListScrollChanged?.Invoke(this, e.VerticalOffset); } private void SetDemangledFunctionNames(List functions) { if (!Session.CompilerInfo.NameProvider.IsDemanglingSupported || !Session.CompilerInfo.NameProvider.IsDemanglingEnabled) { AlternateNameColumnVisible = false; // Clear the cached names. foreach (var funcEx in functions) { funcEx.Name = null; } return; } // Set mangled name as alternate. foreach (var funcEx in functions) { funcEx.AlternateName = funcEx.Function.Name; } AlternateNameColumnVisible = settings_.ShowMangleNamesColumn; } private async Task LoadFunctionProfile() { var profile = Session.ProfileData; if (profile == null) { OptionalDataColumnVisible = false; OptionalDataColumnVisible2 = false; return; } var modulesEx = new List(); foreach (var pair in profile.ModuleWeights) { double weightPercentage = profile.ScaleModuleWeight(pair.Value); var moduleInfo = new ModuleEx { Name = profile.Modules[pair.Key].ModuleName, ExclusivePercentage = weightPercentage, ExclusiveWeight = pair.Value }; // Set warnings for missing binary/debug files. var moduleStatus = profile.Report?.GetModuleStatus(profile.Modules[pair.Key].ModuleName); if (moduleStatus != null) { moduleInfo.Status = moduleStatus; moduleInfo.DebugFileMissing = !moduleStatus.HasDebugInfoLoaded; // Log the module status for debugging ProfileExplorer.Core.Utilities.DiagnosticLogger.LogDebug($"[UI-ModuleStatus] Module {moduleInfo.Name}: BinaryLoaded={moduleStatus.HasBinaryLoaded}, LazyLoadPending={moduleStatus.State == ProfileExplorer.Core.Profile.Data.ModuleLoadState.LazyLoadPending}, DebugInfoLoaded={moduleStatus.HasDebugInfoLoaded}"); ProfileExplorer.Core.Utilities.DiagnosticLogger.LogDebug($"[UI-ModuleStatus] Module {moduleInfo.Name}: BinaryFileMissing={moduleInfo.BinaryFileMissing}, DebugFileMissing={moduleInfo.DebugFileMissing}"); } else { ProfileExplorer.Core.Utilities.DiagnosticLogger.LogWarning($"[UI-ModuleStatus] No module status found for {moduleInfo.Name}"); } modulesEx.Add(moduleInfo); } // Add one entry to represent all modules. double allWeightPercentage = profile.ScaleFunctionWeight(profile.ProfileWeight); var allModules = new ModuleEx { Name = "All", IsAllEntry = true, ExclusivePercentage = allWeightPercentage, ExclusiveWeight = profile.ProfileWeight }; modulesEx.Add(allModules); var modulesFilter = new ListCollectionView(modulesEx); ModulesList.ItemsSource = modulesFilter; moduleValueSorter_.SortByField(ModuleFieldKind.Name); ModulesList.SelectedItem = allModules; modules_ = modulesEx; OptionalDataColumnVisible = true; OptionalDataColumnName = "Time (self)"; OptionalDataColumnVisible2 = true; OptionalDataColumnName2 = "Time (total)"; var markerOptions = App.Settings.DocumentSettings.ProfileMarkerSettings; bool hasPerfCounters = false; // Add the profile info and column data to each function. hasPerfCounters = await Task.Run(() => PrepareFunctionProfile(functions_, profile, markerOptions)); if (hasPerfCounters) { // Wait for all other columns to be added to the UI first // before adding the counter columns, which are relative to other // columns, such as the mangled name. Dispatcher.BeginInvoke(() => { AddCountersFunctionListColumns(false); }, DispatcherPriority.ContextIdle); } functionValueSorter_.SortByField(FunctionFieldKind.Optional); ProfileControlsVisible = true; ModuleControlsVisible = true; IsFunctionListVisible = false; IsFunctionListVisible = true; SectionCountColumnVisible = false; ShowSections = false; UseProfileCallTree = true; // Update column visibility and state. GridViewColumnVisibility.UpdateListView(FunctionList); Utils.ScrollToFirstListViewItem(FunctionList); SetupStackFunctionHoverPreview(); } private static bool PrepareFunctionProfile(List functions, ProfileData profile, ProfileDocumentMarkerSettings markerOptions) { bool hasPerfCounters = false; foreach (var funcEx in functions) { var funcProfile = profile.GetFunctionProfile(funcEx.Function); if (funcProfile != null) { double exclusivePercentage = profile.ScaleFunctionWeight(funcProfile.ExclusiveWeight); funcEx.ExclusivePercentage = exclusivePercentage; funcEx.ExclusiveWeight = funcProfile.ExclusiveWeight; funcEx.BackColor = markerOptions.PickBrushForPercentage(exclusivePercentage); double percentage = profile.ScaleFunctionWeight(funcProfile.Weight); funcEx.Percentage = percentage; funcEx.Weight = funcProfile.Weight; funcEx.BackColor2 = markerOptions.PickBrushForPercentage(percentage); if (funcProfile.HasPerformanceCounters) { hasPerfCounters = true; var counters = funcProfile.ComputeFunctionTotalCounters(); funcEx.Counters = new PerformanceCounterSetEx(counters.Count); // Add values for metrics first. foreach (var counter in profile.SortedPerformanceCounters) { if (counter.IsMetric) { var counterEx = new PerformanceCounterSetEx.PerformanceCounterValueEx {CounterId = counter.Id}; var metric = counter as PerformanceMetric; counterEx.Value = metric.ComputeMetric(counters, out long _, out long _); counterEx.Label = ProfileDocumentMarker.FormatPerformanceMetric(counterEx.Value, metric); funcEx.Counters.Add(counterEx); } } foreach (var counter in counters.Counters) { var counterInfo = profile.GetPerformanceCounter(counter.CounterId); if (!counterInfo.IsMetric) { var counterEx = new PerformanceCounterSetEx.PerformanceCounterValueEx {CounterId = counter.CounterId}; counterEx.Value = counter.Value; counterEx.Label = ProfileDocumentMarker.FormatPerformanceCounter(counter.Value, counterInfo); funcEx.Counters.Add(counterEx); } } } } else { funcEx.ExclusiveWeight = TimeSpan.Zero; funcEx.Weight = TimeSpan.Zero; } } return hasPerfCounters; } private void SetupStackFunctionHoverPreview() { if (preview_ != null) { preview_.Unregister(); preview_ = null; } preview_ = new PopupHoverPreview( FunctionList, TimeSpan.FromMilliseconds(settings_.CallStackPopupDuration), (mousePoint, previewPoint) => { if (!settings_.ShowCallStackPopup) { return null; } var element = FunctionList.GetObjectAtPoint(mousePoint); if (element == null || element.Content is not IRTextFunctionEx funcEx) { return null; } var nodeList = Session.ProfileData.CallTree.GetSortedCallTreeNodes(funcEx.Function); if (nodeList is not {Count: > 0}) { return null; } // Show popup for hottest call stack. var callNode = nodeList[0]; if (funcBacktracePreviewPopup_ != null) { funcBacktracePreviewPopup_.UpdatePosition(previewPoint, FunctionList); } else { funcBacktracePreviewPopup_ = new CallTreeNodePopup( callNode, null, previewPoint, FunctionList, Session); } //? TODO: Max backtrace depth 10 should be a a global profiling option funcBacktracePreviewPopup_.ShowBackTrace(callNode, 10, Session.CompilerInfo.NameProvider.FormatFunctionName); return funcBacktracePreviewPopup_; }, (mousePoint, popup) => true, popup => { Session.RegisterDetachedPanel(popup); funcBacktracePreviewPopup_ = null; }); } private List SetupFunctionExtensions() { var functionsEx = new List(); int index = 0; if (otherSummary_ != null) { foreach (var function in summary_.Functions) { //? TODO: Use CreateFunctionExtensions var funcEx = new IRTextFunctionEx(function, index++, Session.CompilerInfo.NameProvider.FormatFunctionName); functionExtMap_[function] = funcEx; functionsEx.Add(funcEx); if (otherSummary_.FindFunction(function) == null) { // Function missing in right document (removed). funcEx.FunctionDiffKind = DiffKind.Deletion; } } foreach (var function in otherSummary_.Functions) { if (summary_.FindFunction(function) == null) { // Function missing in left document (new). var funcEx = new IRTextFunctionEx(function, index++, Session.CompilerInfo.NameProvider.FormatFunctionName); functionExtMap_[function] = funcEx; functionsEx.Add(funcEx); funcEx.FunctionDiffKind = DiffKind.Insertion; } } } else { // Single document mode. CreateFunctionExtensions(summary_, functionsEx); foreach (var moduleSummary in moduleSummaries_) { CreateFunctionExtensions(moduleSummary, functionsEx); } } SetDemangledFunctionNames(functionsEx); return functionsEx; } private async Task SetupFunctionListUI() { if (!FunctionPartVisible) { return; } // Set up the filter used to search the list. var functionFilter = new ListCollectionView(functions_); functionFilter.Filter = FilterFunctionList; FunctionList.ItemsSource = functionFilter; SectionList.ItemsSource = null; if (summary_.Functions.Count == 1) { await SelectFunction(summary_.Functions[0]); } } private async Task RunFunctionAnalysis() { if (settings_.ComputeStatistics) { await ComputeFunctionStatistics(functions_); } } private void CreateFunctionExtensions(IRTextSummary summary, List functionsEx) { foreach (var func in summary.Functions) { if (!functionExtMap_.TryGetValue(func, out var funcEx)) { funcEx = new IRTextFunctionEx(func, functionsEx.Count, Session.CompilerInfo.NameProvider.FormatFunctionName); functionExtMap_[func] = funcEx; } else { funcEx.Index = functionsEx.Count; } functionsEx.Add(funcEx); } } private void ResetSectionPanel() { SectionCountColumnVisible = true; ProfileControlsVisible = false; ModuleControlsVisible = false; SectionList.ItemsSource = null; FunctionList.ItemsSource = null; otherSummary_ = null; currentFunction_ = null; moduleReport_ = null; sections_.Clear(); sectionExtMap_.Clear(); annotatedSections_.Clear(); functions_?.Clear(); modules_?.Clear(); sectionExtensionComputed_ = false; SectionList.UpdateLayout(); FunctionList.UpdateLayout(); } private async Task ResetStatistics() { Trace.WriteLine($"Cancel stats at {DateTime.Now}, ticks {Environment.TickCount64}"); if (statisticsTask_ != null) { await statisticsTask_.CancelTaskAndWaitAsync(); } //Utils.WaitForDebugger(true); Trace.WriteLine($"Done cancel stats at {DateTime.Now}, ticks {Environment.TickCount64}"); callGraphCache_ = null; functionStatMap_ = null; } private bool SetupSectionExtensions(bool force = false) { if (sectionExtensionComputed_ && !force) { return true; } if (summary_ == null) { return false; } sectionExtMap_.Clear(); annotatedSections_.Clear(); SetupSectionExtensions(summary_); foreach (var moduleSummary in moduleSummaries_) { SetupSectionExtensions(moduleSummary); } sectionExtensionComputed_ = true; return true; } private void SetupSectionExtensions(IRTextSummary summary) { foreach (var func in summary.Functions) { CreateSectionExtensions(func); } } private void CreateSectionExtensions(IRTextFunction func) { int index = 0; foreach (var section in func.Sections) { if (!sectionExtMap_.ContainsKey(section)) { var sectionEx = new IRTextSectionEx(section, index++); sectionExtMap_[section] = sectionEx; } } } private void SetupSectionList(IRTextFunction function, bool force = false) { if (function != null && function.Equals(currentFunction_) && !force) { return; } currentFunction_ = function; FunctionList.SelectedItem = function; Sections = CreateSectionsExtension(); FunctionSwitched?.Invoke(this, currentFunction_); } private void ApplySectionBorder(IRTextSectionEx sectionEx, int sectionIndex, MarkedSectionName markedName, List sections) { // Don't show the border for the first and last sections in the list, // and if there is a before-border following an after-border. bool useBeforeBorder = sectionIndex > 0 && !sections[sectionIndex - 1].HasAfterBorder; bool useAfterBorder = sectionIndex < currentFunction_.Sections.Count - 1; sectionEx.BorderThickness = new Thickness(0, useBeforeBorder ? markedName.BeforeSeparatorWeight : 0, 0, useAfterBorder ? markedName.AfterSeparatorWeight : 0); sectionEx.BorderBrush = ColorBrushes.GetBrush(markedName.SeparatorColor); } private void ApplySectionNameIndentation(IRTextSectionEx sectionEx, MarkedSectionName markedName) { int level = markedName.IndentationLevel; var builder = new StringBuilder(sectionEx.Name.Length + level * settings_.IndentationAmount); while (level > 0) { builder.Append(' ', settings_.IndentationAmount); level--; } builder.Append(sectionEx.Name); sectionEx.Name = builder.ToString(); } private void UpdateSectionListView() { var sectionFilter = new ListCollectionView(sections_); sectionFilter.Filter = FilterSectionList; SectionList.ItemsSource = sectionFilter; if (SectionList.Items.Count > 0) { SectionList.SelectedItem = SectionList.Items[0]; SectionList.ScrollIntoView(SectionList.SelectedItem); } RegisterSectionListScrollEvent(); } private bool FilterFunctionList(object value) { var functionEx = (IRTextFunctionEx)value; if (activeModuleFilter_ != null) { if (functionEx.ModuleName != activeModuleFilter_.Name) { return false; } } // Don't filter with less than 2 letters. string text = FunctionFilter.Text.Trim(); if (text.Length < 2) { return true; } if (nameSearcher_ == null) { nameSearcher_ = new TextSearcher(text, !App.Settings.SectionSettings.FunctionSearchCaseSensitive); } // Search the function name. if (nameSearcher_.Includes(functionEx.Name)) { return true; } // Search the demangled name. return !string.IsNullOrEmpty(functionEx.AlternateName) && nameSearcher_.Includes(functionEx.AlternateName); } private bool FilterSectionList(object value) { var section = (IRTextSectionEx)value; if (section.IsSelected) { return true; } if (FilterTagged && !section.IsTagged) { return false; } if (FilterDiffFromPrevious && !section.IsDiffFromPrevious) { return false; } string text = SectionFilter.Text.Trim(); return text.Length <= 0 || (App.Settings.SectionSettings.SectionSearchCaseSensitive ? section.Name.Contains(text, StringComparison.Ordinal) : section.Name.Contains(text, StringComparison.OrdinalIgnoreCase)); } private void ExecuteClearTextbox(object sender, ExecutedRoutedEventArgs e) { ((TextBox)e.Parameter).Text = string.Empty; } private void OpenExecuted(object sender, ExecutedRoutedEventArgs e) { if (SectionList.SelectedItems.Count == 2) { OpenSideBySideExecuted(sender, e); return; } if (GetCommandTargetSection(e) is { } section) { OpenSectionImpl(section, OpenSectionKind.ReplaceCurrent); } } private void OpenInNewTabExecuted(object sender, ExecutedRoutedEventArgs e) { if (SectionList.SelectedItems.Count == 2) { DiffSideBySideExecuted(sender, e); return; } if (GetCommandTargetSection(e) is { } section) { OpenSectionImpl(section, OpenSectionKind.NewTab); } } private void OpenLeftExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetCommandTargetSection(e) is { } section) { OpenSectionImpl(section, OpenSectionKind.NewTabDockLeft); } } private void OpenRightExecuted(object sender, ExecutedRoutedEventArgs e) { if (GetCommandTargetSection(e) is { } section) { OpenSectionImpl(section, OpenSectionKind.NewTabDockRight); } } private IRTextSectionEx GetCommandTargetSection(ExecutedRoutedEventArgs e) { var section = e.Parameter as IRTextSectionEx; if (e.Parameter is IRTextFunctionEx functionEx) { section = GetSectionExtension(functionEx.Function.Sections[0]); } return section; } private void OpenSideBySideExecuted(object sender, ExecutedRoutedEventArgs e) { if (SectionList.SelectedItems.Count == 2) { var leftSection = SectionList.SelectedItems[0] as IRTextSectionEx; var rightSection = SectionList.SelectedItems[1] as IRTextSectionEx; OpenSectionImpl(leftSection, OpenSectionKind.NewTabDockLeft); OpenSectionImpl(rightSection, OpenSectionKind.NewTabDockRight); } } private void OpenSideBySideCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = SectionList.SelectedItems.Count == 2; e.Handled = true; } private void DiffWithOtherDocumentCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = IsDiffModeEnabled; e.Handled = true; } private void SyncDiffedDocumentsExecuted(object sender, ExecutedRoutedEventArgs e) { e.Handled = true; } private void DiffSideBySideExecuted(object sender, ExecutedRoutedEventArgs e) { var leftSectionEx = SectionList.SelectedItems[0] as IRTextSectionEx; var rightSectionEx = SectionList.SelectedItems[1] as IRTextSectionEx; var args = new DiffModeEventArgs { Left = new OpenSectionEventArgs(leftSectionEx.Section, OpenSectionKind.NewTabDockLeft), Right = new OpenSectionEventArgs(rightSectionEx.Section, OpenSectionKind.NewTabDockRight) }; EnterDiffMode?.Invoke(this, args); } private void DiffWithOtherDocumentExecuted(object sender, ExecutedRoutedEventArgs e) { var sectionEx = SectionList.SelectedItems[0] as IRTextSectionEx; DiffWithOtherSection(sectionEx); } private void DiffWithOtherSection(IRTextSectionEx sectionEx) { var args = new DiffModeEventArgs {IsWithOtherDocument = true, Left = new OpenSectionEventArgs(sectionEx.Section, OpenSectionKind.NewTabDockLeft)}; EnterDiffMode?.Invoke(this, args); } private void ToggleTagExecuted(object sender, ExecutedRoutedEventArgs e) { var section = e.Parameter as IRTextSectionEx; if (section != null) { section.IsTagged = !section.IsTagged; } } private void FocusSearchExecuted(object sender, ExecutedRoutedEventArgs e) { FunctionFilter.Focus(); FunctionFilter.SelectAll(); } private async void FunctionList_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 1) { await SelectFunction(((IRTextFunctionEx)FunctionList.SelectedItem).Function); } if (FunctionList.SelectedItems.Count > 1) { var selectedNodes = new List(); foreach (object item in FunctionList.SelectedItems) { if (item is IRTextFunctionEx funcEx) { selectedNodes.Add(Session.ProfileData.CallTree.GetCombinedCallTreeNode(funcEx.Function)); } } var weightSum = ProfileCallTree.CombinedCallTreeNodesWeight(selectedNodes); double weightPercentage = Session.ProfileData.ScaleFunctionWeight(weightSum); string text = $"Selected {FunctionList.SelectedItems.Count}: {weightPercentage.AsPercentageString()} ({weightSum.AsMillisecondsString()})"; Session.SetApplicationStatus(text, "Sum of time for the selected functions"); } } private (TimeSpan Weight, TimeSpan ExclusiveWeight) ComputeSelectedFunctionsWeight() { var weight = TimeSpan.Zero; var exclusiveWeight = TimeSpan.Zero; foreach (var functionEx in FunctionList.SelectedItems.Cast()) { weight += functionEx.Weight; exclusiveWeight += functionEx.ExclusiveWeight; } return (weight, exclusiveWeight); } private void SectionFilter_TextChanged(object sender, TextChangedEventArgs e) { SectionList.Focus(); RefreshSectionList(); SectionFilter.Focus(); } private void FunctionFilter_TextChanged(object sender, TextChangedEventArgs e) { FunctionList.Focus(); RefreshFunctionList(); FunctionFilter.Focus(); } private void SectionDoubleClick(object sender, MouseButtonEventArgs e) { var sectionEx = ((ListViewItem)sender).Content as IRTextSectionEx; OpenSectionImpl(sectionEx); } private void OpenSectionImpl(IRTextSection section) { OpenSectionImpl(GetSectionExtension(section)); } private void OpenSectionImpl(IRTextSectionEx sectionEx) { if (Session.IsInTwoDocumentsDiffMode) { DiffWithOtherSection(sectionEx); } else { bool inNewTab = (Keyboard.Modifiers & ModifierKeys.Control) != 0 || (Keyboard.Modifiers & ModifierKeys.Shift) != 0; OpenSectionImpl(sectionEx, inNewTab ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent); } } private void OpenSectionImpl(IRTextSectionEx value, OpenSectionKind kind, IRDocumentHost targetDocument = null) { if (OpenSection != null && value.Section != null) { MarkCurrentSection(value); OpenSection(this, new OpenSectionEventArgs(value.Section, kind, targetDocument)); } } private void PreviousButton_Click(object sender, RoutedEventArgs e) { SwitchToSection(-1); } private void NextButton_Click(object sender, RoutedEventArgs e) { SwitchToSection(1); } private void MarkCurrentSection(IRTextSectionEx section) { foreach (var item in sections_) { item.IsSelected = false; } section.IsSelected = true; } private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = true; e.Handled = true; } private void PreviousSectionExecuted(object sender, ExecutedRoutedEventArgs e) { SwitchToSection(-1); e.Handled = true; } private void NextSectionExecuted(object sender, ExecutedRoutedEventArgs e) { SwitchToSection(1); e.Handled = true; } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async Task ComputeConsecutiveSectionDiffs() { if (!settings_.MarkSectionsIdenticalToPrevious || sections_.Count < 2) { return; } // Make a list of all section pairs like [i - 1, i] and diff each one. // Note that when comparing two documents side-by-side, some of the sections // may be placeholders that don't have a real section behind, those must be ignored. var comparedSections = new List<(IRTextSection, IRTextSection)>(); int prevIndex = -1; for (int i = 0; i < sections_.Count; i++) { if (sections_[i].Section == null) { continue; } if (prevIndex != -1) { comparedSections.Add((sections_[prevIndex].Section, sections_[i].Section)); } prevIndex = i; } //? TODO: Pass the LoadedDocument to the panel, not Summary. var loader = Session.SessionState.FindLoadedDocument(Summary).Loader; var diffBuilder = new DocumentDiffBuilder(App.Settings.DiffSettings); var cancelableTask = new CancelableTask(); var results = await diffBuilder.AreSectionsDifferent(comparedSections, loader, loader, Session.CompilerInfo, true, cancelableTask); foreach (var result in results) { if (result.HasDiffs) { var diffSection = GetSectionExtension(result.RightSection); diffSection.IsDiffFromPrevious = true; } } } private void FixedToolbar_SettingsClicked(object sender, EventArgs e) { ShowOptionsPanel(); } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } optionsPanelPopup_ = OptionsPanelHostPopup.Create( Settings.Clone(), FunctionList, Session, async (newSettings, commit) => { if (!newSettings.Equals(Settings)) { await HandleNewSettings(newSettings, commit); } return newSettings.Clone(); }, () => optionsPanelPopup_ = null); } public override Task OnReloadSettings() { return HandleNewSettings(App.Settings.SectionSettings, false, true); } private async Task HandleNewSettings(UISectionSettings newSettings, bool commit, bool force = false) { if (commit) { App.Settings.SectionSettings = newSettings; App.SaveApplicationSettings(); } if (force || !newSettings.Equals(settings_) || !MarkingSettings.Equals(initialMarkingSettings_)) { bool updateFunctionList = newSettings.HasFunctionListChanges(settings_); App.Settings.SectionSettings = newSettings; settings_ = newSettings; if (updateFunctionList) { CompilerInfo.NameProvider.SettingsChanged(); await SetupFunctionList(); } SetupSectionList(currentFunction_, true); RefreshSectionList(); await ComputeConsecutiveSectionDiffs(); if (ProfileControlsVisible) { SetupStackFunctionHoverPreview(); OnPropertyChanged(nameof(SyncSelection)); OnPropertyChanged(nameof(SyncSourceFile)); OnPropertyChanged(nameof(ShowModules)); } await UpdateMarkedFunctions(); initialMarkingSettings_ = MarkingSettings.Clone(); } } private async void CopySectionTextExecuted(object sender, ExecutedRoutedEventArgs e) { if (e.Parameter is IRTextSectionEx sectionEx) { string text = await Session.GetSectionTextAsync(sectionEx.Section); Clipboard.SetText(text); } } private async void SaveSectionTextExecuted(object sender, ExecutedRoutedEventArgs e) { if (!(e.Parameter is IRTextSectionEx sectionEx)) { return; } string path = Utils.ShowSaveFileDialog("IR text|*.txt", "*.txt|All Files|*.*"); if (!string.IsNullOrEmpty(path)) { try { string text = await Session.GetSectionTextAsync(sectionEx.Section); await File.WriteAllTextAsync(path, text); } catch (Exception ex) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save IR text file {path}: {ex.Message}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private async void SaveFunctionTextExecuted(object sender, ExecutedRoutedEventArgs e) { if (!(e.Parameter is IRTextFunctionEx functionEx)) { return; } string path = Utils.ShowSaveFileDialog("IR text|*.txt", "*.txt|All Files|*.*"); if (!string.IsNullOrEmpty(path)) { try { await using var writer = new StreamWriter(path); await CombineFunctionText(functionEx.Function, writer); } catch (Exception ex) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save IR text file {path}: {ex.Message}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private async Task CombineFunctionText(IRTextFunction function, TextWriter writer) { foreach (var section in function.Sections) { string text = await Session.GetSectionTextAsync(section); if (section.OutputBefore != null) { string beforeText = await Session.GetSectionOutputTextAsync(section.OutputBefore, section); await writer.WriteLineAsync(beforeText); } await writer.WriteLineAsync(text); } } private void CopyFunctionNameExecuted(object sender, ExecutedRoutedEventArgs e) { string text = ""; foreach (IRTextFunctionEx func in FunctionList.SelectedItems) { if (!string.IsNullOrEmpty(text)) { text += Environment.NewLine; } text += Session.CompilerInfo.NameProvider.GetFunctionName(func.Function); } Clipboard.SetText(text); } private void CopyDemangledFunctionNameExecuted(object sender, ExecutedRoutedEventArgs e) { string text = ""; foreach (IRTextFunctionEx func in FunctionList.SelectedItems) { if (!string.IsNullOrEmpty(text)) { text += Environment.NewLine; } text += Session.CompilerInfo.NameProvider.FormatFunctionName(func.Function); } Clipboard.SetText(text); } private void DisplayCallGraphExecuted(object sender, ExecutedRoutedEventArgs e) { if (e.Parameter is IRTextSectionEx sectionEx) { DisplayCallGraph?.Invoke(this, new DisplayCallGraphEventArgs(Summary, sectionEx.Section, false)); } } private IRTextFunction GetSelectedFunction(ExecutedRoutedEventArgs e) { if (e.Parameter is IRTextFunctionEx funcEx) { return funcEx.Function; } if (e.Parameter is IRTextSectionEx sectionEx) { return sectionEx.Section.ParentFunction; } return null; } private void DisplayPartialCallGraphExecuted(object sender, ExecutedRoutedEventArgs e) { if (e.Parameter is IRTextSectionEx sectionEx) { DisplayCallGraph?.Invoke(this, new DisplayCallGraphEventArgs(Summary, sectionEx.Section, true)); } } private void ToolBar_SizeChanged(object sender, SizeChangedEventArgs e) { ResizeFunctionFilter(e.NewSize.Width); } private void ResizeFunctionFilter(double width) { //? TODO: Hacky way to resize the function search textbox in the toolbar //? when the toolbar gets smaller - couldn't find another way to do this in WPF... double reservedWidth = 20; if (profileControlsVisible_) { reservedWidth += 120; } if (moduleControlsVisible_) { reservedWidth += 80; } FunctionFilterGrid.Width = Math.Max(1, width - reservedWidth); } private async void FunctionDoubleClick(object sender, MouseButtonEventArgs e) { await OpenFunction(sender); } private async Task OpenFunction(object sender) { // A double-click on the +/- icon doesn't have an actual node selected. var functionEx = ((ListViewItem)sender).Content as IRTextFunctionEx; if (functionEx != null) { await SelectFunction(functionEx.Function); if (functionEx.SectionCount > 0) { OpenSectionImpl(functionEx.Function.Sections[0]); } } } private async Task ComputeFunctionStatistics(List functions) { Trace.TraceInformation("ComputeFunctionStatistics: start"); using var cancelableTask = await statisticsTask_.CancelCurrentAndCreateTaskAsync(); if (functionStatMap_ == null || functionStatMap_.Count < functions.Count) { functionStatMap_ = await ComputeFunctionStatisticsImpl(functions, cancelableTask); if (cancelableTask.IsCanceled) { return; } } foreach (var pair in functionStatMap_) { var functionEx = GetFunctionExtension(pair.Key); functionEx.Statistics = pair.Value; } Trace.TraceInformation("ComputeFunctionStatistics: done"); statisticsTask_.CompleteTask(); AddStatisticsFunctionListColumns(addDiffColumn: false); RefreshFunctionList(); Session.SetApplicationProgress(false, double.NaN); } private async Task> ComputeFunctionStatisticsImpl(List functions, CancelableTask cancelableTask) { var functionStatMap = new ConcurrentDictionary(); if (functions.Count == 0) { return functionStatMap; } callGraphCache_ ??= new ConcurrentDictionary(); Session.SetApplicationProgress(true, double.NaN, "Computing statistics"); // If call graph not requested, don't waste time with called function names. foreach (var loadedDoc in Session.SessionState.Documents) { if (loadedDoc.Loader is DisassemblerSectionLoader disasmLoader) { disasmLoader.ResolveCallTargetNames = settings_.IncludeCallGraphStatistics; } } if (settings_.IncludeCallGraphStatistics) { var summaries = new List(); summaries.Add(summary_); summaries.AddRange(moduleSummaries_); var cgTasks = new List(); var cgTaskScheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, 8); var cgTaskFactory = new TaskFactory(cgTaskScheduler.ConcurrentScheduler); foreach (var summary in summaries) { cgTasks.Add(cgTaskFactory.StartNew(async () => { try { if (cancelableTask.IsCanceled) { return; } await GenerateCallGraph(summary); } catch (Exception ex) { Trace.WriteLine($"Failed to compute call graph: {ex.Message}"); } }, cancelableTask.Token)); } await Task.WhenAll(cgTasks.ToArray()); } var tasks = new List(); var taskScheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, 16); var taskFactory = new TaskFactory(taskScheduler.ConcurrentScheduler); foreach (var function in functions) { if (function.SectionCount == 0) { continue; } if (cancelableTask.IsCanceled) { break; } tasks.Add(taskFactory.StartNew(async () => { try { if (cancelableTask.IsCanceled) { return; } var section = function.Function.Sections[0]; var summary = function.Function.ParentSummary; CallGraph callGraph = null; if (settings_.IncludeCallGraphStatistics) { callGraph = await GenerateCallGraph(summary); } var loadedDoc = Session.SessionState.FindLoadedDocument(summary); var sectionStats = ComputeFunctionStatistics(section, loadedDoc.Loader, callGraph); if (sectionStats != null) { functionStatMap.TryAdd(function.Function, sectionStats); } } catch (Exception ex) { Trace.WriteLine($"Failed to compute func statistics: {ex.Message}"); } }, cancelableTask.Token)); } await Task.WhenAll(tasks.ToArray()); if (cancelableTask.IsCanceled) { // Complete only now after all tasks were canceled, // otherwise the session ending would move on and break the tasks still executing. cancelableTask.Complete(); } foreach (var loadedDoc in Session.SessionState.Documents) { if (loadedDoc.Loader is DisassemblerSectionLoader disasmLoader) { disasmLoader.ResolveCallTargetNames = true; } } Session.SetApplicationProgress(false, double.NaN); return functionStatMap; } private FunctionCodeStatistics ComputeFunctionStatistics(IRTextSection section, IRTextSectionLoader loader, CallGraph callGraph) { var result = loader.LoadSection(section); if (result == null) { return null; } var stats = FunctionCodeStatistics.Compute(result.Function, Session.CompilerInfo.IR); if (callGraph != null) { var node = callGraph.FindNode(section.ParentFunction); if (node != null) { stats.Callees = node.UniqueCalleeCount; stats.Callers = node.UniqueCallerCount; } } return stats; } private void ModuleDoubleClick(object sender, MouseButtonEventArgs e) { SwitchModule(sender); } private void ModulesList_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (ModulesList.SelectedItem is ModuleEx moduleEx) { SelectModule(moduleEx); } } private void SelectModule(ModuleEx moduleEx) { if (moduleEx != null) { ClearMarkedFunctions(); if (!moduleEx.IsAllEntry) { var summary = FindModuleSummary(moduleEx.Name); if (summary != null) { MarkFunctions(summary.Functions); } } } } private void SwitchModule(object sender) { var moduleEx = ((ListViewItem)sender).Content as ModuleEx; if (moduleEx != null) { ApplyModuleFilter(moduleEx); ClearMarkedFunctions(); } } private void ApplyModuleFilter(ModuleEx moduleEx) { if (moduleEx.IsAllEntry) { activeModuleFilter_ = null; } else { activeModuleFilter_ = moduleEx; } RefreshFunctionList(); } private void ExportFunctionListExecuted(object sender, ExecutedRoutedEventArgs e) { string path = Utils.ShowSaveFileDialog("Excel Worksheets|*.xlsx", "*.xlsx|All Files|*.*"); if (!string.IsNullOrEmpty(path)) { try { ExportFunctionListAsExcelFile(path); } catch (Exception ex) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save function list to {path}: {ex.Message}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private string ExportFunctionListAsMarkdown(List list) { var sb = new StringBuilder(); string header = "| Function | Module |"; string separator = "|----------|--------|"; if (profileControlsVisible_) { header += " Time (ms) | Time (%) | Time incl (ms) | Time incl (%) |"; separator += "-----------|----------|----------------|---------------|"; } if (alternateNameColumnVisible_) { header += " Mangled name |"; separator += "--------------|"; } sb.AppendLine(header); sb.AppendLine(separator); foreach (var func in list) { if (profileControlsVisible_) { sb.Append($"| {func.Name} | {func.ModuleName} " + $"| {func.ExclusiveWeight.TotalMilliseconds} " + $"| {func.ExclusivePercentage.AsPercentageString(2, false)} " + $"| {func.Weight.TotalMilliseconds} " + $"| {func.Percentage.AsPercentageString(2, false)} |"); } else { sb.Append($"| {func.Name} | {func.ModuleName} |"); } if (alternateNameColumnVisible_) { sb.AppendLine($" {func.AlternateName} |"); } else { sb.AppendLine(); } } return sb.ToString(); } private HtmlNode ExportFunctionListAsHtml(List list) { string TableStyle = @"border-collapse:collapse;border-spacing:0;"; string HeaderStyle = @"background-color:#D3D3D3;white-space:nowrap;text-align:left;vertical-align:top;border-color:black;border-style:solid;border-width:1px;overflow:hidden;padding:2px 2px;font-family:Arial, sans-serif;"; string CellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:300px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;"; var doc = new HtmlDocument(); var table = doc.CreateElement("table"); table.SetAttributeValue("style", TableStyle); var thead = doc.CreateElement("thead"); var tbody = doc.CreateElement("tbody"); var tr = doc.CreateElement("tr"); var th = doc.CreateElement("th"); th.InnerHtml = "Function"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = "Module"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); thead.AppendChild(tr); if (profileControlsVisible_) { th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Time (ms)"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Time (%)"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Tine incl (ms)"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Time incl (%)"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); } if (alternateNameColumnVisible_) { th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Mangled name"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); } table.AppendChild(thead); foreach (var func in list) { tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(func.Name); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(func.ModuleName); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); if (profileControlsVisible_) { string backColor = Utils.BrushToString(func.BackColor); string colorAttr = backColor != null ? $";background-color:{backColor}" : ""; td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{func.ExclusiveWeight.TotalMilliseconds}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{func.ExclusivePercentage.AsPercentageString(2, false)}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{func.Weight.TotalMilliseconds}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{func.Percentage.AsPercentageString(2, false)}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); } if (alternateNameColumnVisible_) { td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(func.AlternateName); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); } tbody.AppendChild(tr); } table.AppendChild(tbody); doc.DocumentNode.AppendChild(table); return doc.DocumentNode; } private void CopyFunctionListAsHtml(bool allFunctions) { var doc = new HtmlDocument(); List funcList = null; if (allFunctions) { funcList = functions_; } else { funcList = new List(); foreach (object item in FunctionList.SelectedItems) { funcList.Add((IRTextFunctionEx)item); } } doc.DocumentNode.AppendChild(ExportFunctionListAsHtml(funcList)); var writer = new StringWriter(); doc.Save(writer); // Also save as Markdown so that it can be pasted in plain text editors. string plainText = ExportFunctionListAsMarkdown(funcList); Utils.CopyHtmlToClipboard(writer.ToString(), plainText); } private async Task ExportFunctionListAsHtmlFile(string filePath) { try { var funcList = (ListCollectionView)FunctionList.ItemsSource; var doc = new HtmlDocument(); doc.DocumentNode.AppendChild(ExportFunctionListAsHtml(funcList.ToList())); var writer = new StringWriter(); doc.Save(writer); await File.WriteAllTextAsync(filePath, writer.ToString()); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to export to HTML file: {filePath}, {ex.Message}"); return false; } } private async Task ExportFunctionListAsMarkdownFile(string filePath) { try { var funcList = (ListCollectionView)FunctionList.ItemsSource; string text = ExportFunctionListAsMarkdown(funcList.ToList()); await File.WriteAllTextAsync(filePath, text); return true; } catch (Exception ex) { Trace.WriteLine($"Failed to export to Markdown file: {filePath}, {ex.Message}"); return false; } } private void ExportFunctionListAsExcelFile(string filePath) { var wb = new XLWorkbook(); var ws = wb.Worksheets.Add("Functions"); int rowId = 1; // First row is for the table column names. int maxLineLength = 0; var funcList = (ListCollectionView)FunctionList.ItemsSource; foreach (IRTextFunctionEx func in funcList) { rowId++; ws.Cell(rowId, 1).Value = func.Name; ws.Cell(rowId, 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left; maxLineLength = Math.Max(func.Name.Length, maxLineLength); ws.Cell(rowId, 2).Value = func.ModuleName; if (profileControlsVisible_) { int columnId = 3; ws.Cell(rowId, columnId + 0).Value = $"{func.ExclusiveWeight.TotalMilliseconds}"; ws.Cell(rowId, columnId + 1).Value = $"{func.ExclusivePercentage.AsPercentageString(2, false, "")}"; ws.Cell(rowId, columnId + 2).Value = $"{func.Weight.TotalMilliseconds}"; ws.Cell(rowId, columnId + 3).Value = $"{func.Percentage.AsPercentageString(2, false, "")}"; if (func.BackColor != null && func.BackColor is SolidColorBrush colorBrush) { var color = XLColor.FromArgb(colorBrush.Color.A, colorBrush.Color.R, colorBrush.Color.G, colorBrush.Color.B); ws.Cell(rowId, 1).Style.Fill.BackgroundColor = color; ws.Cell(rowId, 2).Style.Fill.BackgroundColor = color; ws.Cell(rowId, columnId + 0).Style.Fill.BackgroundColor = color; ws.Cell(rowId, columnId + 1).Style.Fill.BackgroundColor = color; ws.Cell(rowId, columnId + 2).Style.Fill.BackgroundColor = color; ws.Cell(rowId, columnId + 3).Style.Fill.BackgroundColor = color; } if (alternateNameColumnVisible_) { ws.Cell(rowId, columnId + 4).Value = func.AlternateName; } } } var firstCell = ws.Cell(1, 1); var lastCell = ws.LastCellUsed(); var range = ws.Range(firstCell.Address, lastCell.Address); var table = range.CreateTable(); table.Theme = XLTableTheme.None; foreach (var cell in table.HeadersRow().Cells()) { if (cell.Address.ColumnNumber == 1) { cell.Value = "Function"; } else if (cell.Address.ColumnNumber == 2) { cell.Value = "Module"; } else if (profileControlsVisible_ && cell.Address.ColumnNumber - 3 <= 3) { switch (cell.Address.ColumnNumber - 3) { case 0: { cell.Value = "Time (ms)"; break; } case 1: { cell.Value = "Time (%)"; break; } case 2: { cell.Value = "Time incl (ms)"; break; } case 3: { cell.Value = "Time incl (%)"; break; } } } else if (alternateNameColumnVisible_) { cell.Value = "Mangled name"; } cell.Style.Font.Bold = true; cell.Style.Fill.BackgroundColor = XLColor.LightGray; } for (int i = 1; i <= 1; i++) { ws.Column(i).AdjustToContents((double)1, Math.Min(50, maxLineLength)); } for (int i = 2; i <= lastCell.Address.ColumnNumber; i++) { ws.Column(i).AdjustToContents(); } wb.SaveAs(filePath); } private void OpenDocumentInNewInstanceExecuted(object sender, ExecutedRoutedEventArgs e) { var loadedDoc = Session.SessionState.FindLoadedDocument(Summary); if (!App.StartNewApplicationInstance(loadedDoc.FilePath)) { MessageBox.Show("Failed to start new application instance", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } private void OpenDocumentInEditorExecuted(object sender, ExecutedRoutedEventArgs e) { var loadedDoc = Session.SessionState.FindLoadedDocument(Summary); if (!Utils.OpenExternalFile(loadedDoc.FilePath)) { MessageBox.Show("Failed to open document", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Error); } } private async void CopyFunctionTextExecuted(object sender, ExecutedRoutedEventArgs e) { if (!(e.Parameter is IRTextFunctionEx functionEx)) { return; } using var writer = new StringWriter(); await CombineFunctionText(functionEx.Function, writer); Clipboard.SetText(writer.ToString()); } private void ModuleWarningImage_MouseUp(object sender, MouseButtonEventArgs e) { var moduleEx = ModulesList.SelectedItem as ModuleEx; ProfileReportPanel.ShowReportWindow(Session.ProfileData.Report, Session, moduleEx?.Status); } public IRTextSectionEx GetSectionExtension(IRTextSection section) { if (sectionExtMap_.TryGetValue(section, out var secitonEx)) { return secitonEx; } CreateSectionExtensions(section.ParentFunction); return sectionExtMap_[section]; } public IRTextFunctionEx GetFunctionExtension(IRTextFunction function) { if (functionExtMap_.TryGetValue(function, out var functionEx)) { return functionEx; } if (IsDiffModeEnabled && function.ParentSummary == otherSummary_) { //? TODO: Add name mapping using dictionary foreach (var pair in functionExtMap_) { if (pair.Key.Name == function.Name) { return pair.Value; } } } Utils.WaitForDebugger(); throw new InvalidOperationException(); } public override async void OnSessionStart() { base.OnSessionStart(); statisticsTask_ = new CancelableTaskInstance(false, Session.SessionState.RegisterCancelableTask, Session.SessionState.UnregisterCancelableTask); callGraphTask_ = new CancelableTaskInstance(false, Session.SessionState.RegisterCancelableTask, Session.SessionState.UnregisterCancelableTask); object data = Session.LoadPanelState(this, null); if (data != null) { var state = UIStateSerializer.Deserialize(data); foreach (int sectionId in state.AnnotatedSections) { var section = summary_.GetSectionWithId(sectionId); var sectionExt = GetSectionExtension(section); sectionExt.IsTagged = true; annotatedSections_.Add(sectionExt); } if (state.SelectedFunctionNumber > 0 && state.SelectedFunctionNumber < summary_.Functions.Count) { await SelectFunction(summary_.Functions[state.SelectedFunctionNumber]); BringIntoViewSelectedListItem(FunctionList, false); } } // Reset search filters. FunctionFilter.Text = ""; SectionFilter.Text = ""; } public async Task SelectFunction(IRTextFunction function, bool handleProfiling = true) { if (function.Equals(currentFunction_)) { return; } SetupSectionList(function); var funcEx = GetFunctionExtension(function); FunctionList.SelectedItem = funcEx; FunctionList.ScrollIntoView(FunctionList.SelectedItem); RefreshSectionList(); if (handleProfiling && profileControlsVisible_) { var funcProfile = Session.ProfileData.GetFunctionProfile(function); if (funcProfile != null) { if (SyncSelection) { await Session.ProfileFunctionSelected(function, ToolPanelKind.Section); } if (SyncSourceFile) { await Session.OpenProfileSourceFile(function); } } else { await Session.ProfileFunctionDeselected(); } } await ComputeConsecutiveSectionDiffs(); } private async Task<(CallGraph, CallGraphNode)> GenerateFunctionCallGraph( IRTextSummary summary, IRTextFunction function) { var callGraph = await GenerateCallGraph(summary); var callGraphNode = callGraph.FindNode(function); return (callGraph, callGraphNode); } private async Task GenerateCallGraph(IRTextSummary summary) { if (callGraphCache_.TryGetValue(summary, out var callGraph)) { return callGraph; } Session.SetApplicationProgress(true, double.NaN, "Generating call graph"); using var cancelableTask = await callGraphTask_.CancelCurrentAndCreateTaskAsync(); var loadedDoc = Session.SessionState.FindLoadedDocument(summary); callGraph = new CallGraph(summary, loadedDoc.Loader, Session.CompilerInfo.IR); await Task.Run(() => callGraph.Execute(null, cancelableTask)); if (!cancelableTask.IsCanceled) { // Cache the call graph, can be expensive to compute. callGraphCache_.TryAdd(summary, callGraph); } cancelableTask.Complete(); Session.SetApplicationProgress(false, 0); return callGraph; } //private async Task CreateCallTree(IRTextFunction function) { // var (_, callGraphNode) = await GenerateFunctionCallGraph(function.ParentSummary, function); // CallGraphNode otherNode = null; // if (otherSummary_ != null) { // var otherFunction = otherSummary_.GetOrCreateFunction(function); // if (otherFunction != null) { // (_, otherNode) = await GenerateFunctionCallGraph(otherSummary_, otherFunction); // } // } // var visitedNodes = new HashSet(); // var rootNode = new ChildFunctionEx(ChildFunctionExKind.CallTreeNode); // rootNode.Children = new List(); // if (callGraphNode != null) { // CreateCallTree(callGraphNode, otherNode, function, rootNode, visitedNodes); // } // return rootNode; //} //private void CreateCallTree(CallGraphNode node, CallGraphNode otherNode, // IRTextFunction function, ChildFunctionEx parentNode, // HashSet visitedNodes) { // visitedNodes.Add(node); // if (node.HasCallers) { // //? TODO: Sort on top of the list // var callerInfo = CreateCallTreeChild(node, function); // callerInfo.FunctionName = "Callers"; // callerInfo.IsMarked = true; // parentNode.Children.Add(callerInfo); // foreach (var callerNode in node.UniqueCallers) { // var callerFunc = function.ParentSummary.GetOrCreateFunction(callerNode.FunctionName); // if (callerFunc == null) // continue; // var callerNodeEx = CreateCallTreeChild(callerNode, callerFunc); // callerInfo.Children.Add(callerNodeEx); // } // } // foreach (var calleeNode in node.UniqueCallees) { // var childFunc = function.ParentSummary.GetOrCreateFunction(calleeNode.FunctionName); // if (childFunc == null) continue; // // Create node and attach statistics if available. // var childNode = CreateCallTreeChild(calleeNode, childFunc); // parentNode.Children.Add(childNode); // var otherCalleeNode = otherNode?.FindCallee(calleeNode); // if (otherSummary_ != null && otherCalleeNode == null) { // // Missing in right. // childNode.TextColor = ColorBrushes.GetBrush(settings_.NewSectionColor); // childNode.IsMarked = true; // } // if (calleeNode.HasCallees && !visitedNodes.Contains(calleeNode)) { // childNode.Children = new List(); // CreateCallTree(calleeNode, otherCalleeNode, childFunc, childNode, visitedNodes); // if (childNode.IsMarked && parentNode != null) { // parentNode.IsMarked = true; // } // } // } // // Sort children, since that is not yet supported by the TreeListView control. // parentNode.Children.Sort((a, b) => { // // Ensure the callers node is placed first. // if (b.Time > a.Time) { // return 1; // } // else if (b.Time < a.Time) { // return -1; // } // return string.Compare(b.FunctionName, a.FunctionName, StringComparison.Ordinal); // }); //} //private FunctionCodeStatistics GetFunctionStatistics(IRTextFunction function) { // var functionEx = GetFunctionExtension(function); // return functionEx.Statistics; //} //private ChildFunctionEx CreateCallTreeChild(CallGraphNode childNode, IRTextFunction childFunc) { // var childInfo = new ChildFunctionEx(ChildFunctionExKind.CallTreeNode) { // Function = childFunc, // FunctionName = childNode.FunctionName, // TextColor = Brushes.Black, // BackColor = ColorBrushes.GetBrush(Colors.Transparent), // Children = new List(), // }; // return childInfo; //} public override void OnSessionSave() { base.OnSessionSave(); var state = new SectionPanelState(); state.AnnotatedSections = annotatedSections_.ToList(item => item.Section.Id); state.SelectedFunctionNumber = FunctionList.SelectedItem != null ? ((IRTextFunctionEx)FunctionList.SelectedItem).Function.Number : 0; byte[] data = UIStateSerializer.Serialize(state); Session.SavePanelState(data, this, null); } public override async void OnSessionEnd() { base.OnSessionEnd(); await ResetUI(); //? TODO: Make OnSessionEnd async } public void SaveListViewColumnsState() { settings_.FunctionListColumns.SaveColumnsState(FunctionList); settings_.SectionListColumns.SaveColumnsState(SectionList); settings_.ModuleListColumns.SaveColumnsState(ModulesList); } public void RestoreListViewColumnsState() { settings_.FunctionListColumns.RestoreColumnsState(FunctionList); settings_.SectionListColumns.RestoreColumnsState(SectionList); settings_.ModuleListColumns.RestoreColumnsState(ModulesList); } private async void PanelToolbarTray_OnHelpClicked(object sender, EventArgs e) { await HelpPanel.DisplayPanelHelp(PanelKind, Session); } private void SectionPreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { var sectionEx = ((ListViewItem)sender).Content as IRTextSectionEx; OpenSectionImpl(sectionEx); e.Handled = true; } } private async void FunctionPreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { await OpenFunction(sender); } } private void ModulePreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Return) { SwitchModule(sender); } } private void CopyFunctionDetailsExecuted(object sender, ExecutedRoutedEventArgs e) { CopyFunctionListAsHtml(false); } private async void ExportFunctionListHtmlExecuted(object sender, ExecutedRoutedEventArgs e) { string path = Utils.ShowSaveFileDialog("HTML file|*.html", "*.html|All Files|*.*"); bool success = true; if (!string.IsNullOrEmpty(path)) { try { success = await ExportFunctionListAsHtmlFile(path); } catch (Exception ex) { Trace.WriteLine($"Failed to save function list to {path}: {ex.Message}"); } if (!success) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save function list to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private async void ExportFunctionListMarkdownExecuted(object sender, ExecutedRoutedEventArgs e) { string path = Utils.ShowSaveFileDialog("Markdown file|*.md", "*.md|All Files|*.*"); bool success = true; if (!string.IsNullOrEmpty(path)) { try { success = await ExportFunctionListAsMarkdownFile(path); } catch (Exception ex) { Trace.WriteLine($"Failed to save function list to {path}: {ex.Message}"); } if (!success) { using var centerForm = new DialogCenteringHelper(this); MessageBox.Show($"Failed to save function list to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } private async void CopyMarkedFunctionMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.CopyFunctionMarkingsAsHtml(Session); } private async void ExportMarkedFunctionsHtmlMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportFunctionMarkingsAsHtmlFile(Session); } private async void ExportMarkedFunctionsMarkdownMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportFunctionMarkingsAsMarkdownFile(Session); } private async void CopyMarkedModulesMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.CopyModuleMarkingsAsHtml(Session); } private async void ExportMarkedModulesHtmlMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportModuleMarkingsAsHtmlFile(Session); } private async void ExportMarkedModulesMarkdownMenu_OnClick(object sender, RoutedEventArgs e) { await ProfilingExporting.ExportModuleMarkingsAsMarkdownFile(Session); } private void ScrollUpButton_OnClick(object sender, RoutedEventArgs e) { if (FunctionList.Items is {Count: > 0}) { FunctionList.ScrollIntoView(FunctionList.Items[0]); } } public void EnterBinaryDisplayMode() { IsFunctionListVisible = false; IsFunctionListVisible = true; SectionCountColumnVisible = false; ShowModules = false; ShowSections = false; } private void MarkSelectedNodes(object obj, Action action) { if (obj is SelectedColorEventArgs e) { foreach (IRTextFunctionEx funcEx in FunctionList.SelectedItems) { action(funcEx, e.SelectedColor); } } } private sealed class FunctionDiffKindConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is DiffKind diffKind) { return diffKind switch { DiffKind.Insertion => "Diff only", DiffKind.Deletion => "Base only", DiffKind.Modification => "Modified", DiffKind.MinorModification => "Modified", _ => "" }; } return ""; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } private sealed class FunctionDiffValueConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value is int intValue) { if (intValue > 0) { return $"+{intValue}"; } if (intValue == 0) { return $" {intValue}"; } } else if (value is long longValue) { if (longValue > 0) { return $"+{longValue}"; } if (longValue == 0) { return $" {longValue}"; } } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return null; } } } ================================================ FILE: src/ProfileExplorerUI/Panels/SectionPanelPair.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/SectionPanelPair.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.Core.Diff; using ProfileExplorer.Core.Document.Renderers.Highlighters; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI; public partial class SectionPanelPair : ToolPanelControl { private bool diffModeEnabled_; public SectionPanelPair() { InitializeComponent(); DiffPanel.Visibility = Visibility.Collapsed; MainGrid.ColumnDefinitions[1].Width = new GridLength(0, GridUnitType.Pixel); MainGrid.ColumnDefinitions[2].Width = new GridLength(0, GridUnitType.Pixel); MainPanel.OpenSection += MainPanel_OpenSection; MainPanel.EnterDiffMode += MainPanel_EnterDiffMode; MainPanel.SyncDiffedDocumentsChanged += MainPanel_SyncDiffedDocumentsChanged; MainPanel.FunctionSwitched += DiffPanel_FunctionSwitched; MainPanel.SectionListScrollChanged += MainPanel_SectionListScrollChanged; MainPanel.DisplayCallGraph += MainPanel_DisplayCallGraph; DiffPanel.OpenSection += MainPanel_OpenSection; DiffPanel.EnterDiffMode += MainPanel_EnterDiffMode; DiffPanel.FunctionSwitched += DiffPanel_FunctionSwitched; DiffPanel.SectionListScrollChanged += MainPanel_SectionListScrollChanged; DiffPanel.SyncDiffedDocumentsChanged += MainPanel_SyncDiffedDocumentsChanged; DiffPanel.DisplayCallGraph += MainPanel_DisplayCallGraph; } public ICompilerInfoProvider CompilerInfo { get => MainPanel.CompilerInfo; set { MainPanel.CompilerInfo = value; DiffPanel.CompilerInfo = value; } } public bool HasAnnotatedSections => MainPanel.HasAnnotatedSections || DiffPanel.HasAnnotatedSections; public bool SyncDiffedDocuments => MainPanel.SyncDiffedDocuments; public IRTextSummary MainSummary => MainPanel.Summary; public IRTextSummary DiffSummary => DiffPanel.Summary; public string MainTitle { get => MainPanel.DocumentTitle; set => MainPanel.DocumentTitle = value; } public string DiffTitle { get => DiffPanel.DocumentTitle; set => DiffPanel.DocumentTitle = value; } public override ToolPanelKind PanelKind => ToolPanelKind.Section; public override bool SavesStateToFile => true; public override IUISession Session { get => MainPanel.Session; set { MainPanel.Session = value; DiffPanel.Session = value; } } public event EventHandler OpenSection; public event EventHandler EnterDiffMode; public event EventHandler SyncDiffedDocumentsChanged; public event EventHandler DisplayCallGraph; public async Task RefreshModuleSummaries() { await MainPanel.Update(); } public async Task RefreshProfile() { await MainPanel.Update(true, false); } public async Task SetMainSummary(IRTextSummary summary, bool updateFunctionList = false) { if (MainPanel.Summary == summary && !updateFunctionList) { return; } MainPanel.Summary = summary; if (summary != null) { if (updateFunctionList) { await MainPanel.SetupFunctionList(); } await Update(); } } public async Task SetDiffSummary(IRTextSummary summary) { if (DiffPanel.Summary == summary) { return; } DiffPanel.Summary = summary; if (!diffModeEnabled_) { MainGrid.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star); MainGrid.ColumnDefinitions[1].Width = new GridLength(2, GridUnitType.Pixel); MainGrid.ColumnDefinitions[2].Width = new GridLength(1, GridUnitType.Star); MainPanel.IsDiffModeEnabled = true; DiffPanel.IsDiffModeEnabled = true; DiffPanel.Visibility = Visibility.Visible; MainPanel.OtherSummary = summary; DiffPanel.FunctionPartVisible = false; DiffPanel.OtherSummary = MainSummary; diffModeEnabled_ = true; } else if (summary == null) { MainGrid.ColumnDefinitions[0].Width = new GridLength(1, GridUnitType.Star); MainGrid.ColumnDefinitions[1].Width = new GridLength(0, GridUnitType.Pixel); MainGrid.ColumnDefinitions[2].Width = new GridLength(0, GridUnitType.Star); MainPanel.IsDiffModeEnabled = false; DiffPanel.IsDiffModeEnabled = false; MainPanel.IsFunctionListVisible = true; DiffPanel.Visibility = Visibility.Collapsed; // Restore original section list, without diff placeholders/annotations. if (MainPanel.Summary != null) { // If there was a prev. failure, may not be set up. MainPanel.Sections = MainPanel.CreateSectionsExtension(true); } diffModeEnabled_ = false; } if (summary != null) { await Update(); } } public async Task Update() { await MainPanel.Update(); await DiffPanel.Update(); } public void AddModuleSummary(IRTextSummary summary) { MainPanel.AddModuleSummary(summary); } public void ClearModuleSummaries() { MainPanel.ClearModuleSummaries(); } public async Task RefreshDocumentsDiffs() { if (MainPanel.CurrentFunction == null) { return; } await SwitchPanelDiffFunction(MainPanel.CurrentFunction, DiffPanel); } public void SetSectionAnnotationState(IRTextSection section, bool hasAnnotations) { SelectSectionPanel(section).SetSectionAnnotationState(section, hasAnnotations); } public async Task SelectSection(IRTextSection section, bool handleProfiling = true, bool focus = true) { await SelectFunction(section.ParentFunction, handleProfiling); SelectSectionPanel(section).SelectSection(section, focus); } public async Task SelectFunction(IRTextFunction function, bool handleProfiling = true) { await MainPanel.SelectFunction(function, handleProfiling); if (DiffPanel.IsDiffModeEnabled) { await DiffPanel.SelectFunction(function, handleProfiling); } } public void DiffSelectedSection() { MainPanel.DiffSelectedSection(); } public void SwitchToSection(IRTextSection section, IRDocumentHost targetDocument = null) { SelectSectionPanel(section).SwitchToSection(section, targetDocument); } public IRTextSection FindDiffDocumentSection(IRTextSection section) { if (!diffModeEnabled_) { return null; } var panel = SelectSectionPanel(section); var otherPanel = panel == MainPanel ? DiffPanel : MainPanel; int sectionIndex = panel.Sections.FindIndex(item => item.Section == section); if (sectionIndex == -1) { return null; } var otherSection = otherPanel.Sections[sectionIndex]; if (!otherSection.IsPlaceholderDiff) { return otherSection.Section; } while (sectionIndex > 0) { sectionIndex--; otherSection = otherPanel.Sections[sectionIndex]; if (!otherSection.IsPlaceholderDiff) { return otherSection.Section; } } return otherSection.Section; } public override void OnSessionStart() { MainPanel.OnSessionStart(); DiffPanel.OnSessionStart(); } public override void OnSessionEnd() { SetMainSummary(null).Wait(); SetDiffSummary(null).Wait(); MainPanel.SaveListViewColumnsState(); MainPanel.OnSessionEnd(); //? TODO: Await, make OnSessionEnd async DiffPanel.OnSessionEnd(); } public override async Task OnReloadSettings() { MainPanel.OnReloadSettings(); DiffPanel.OnReloadSettings(); } public void EnterBinaryDisplayMode() { // Update UI for viewing a binary, similar to profiling mode. MainPanel.EnterBinaryDisplayMode(); DiffPanel.EnterBinaryDisplayMode(); } public async Task AnalyzeDocumentDiffs() { Trace.TraceInformation("AnalyzeDocumentDiffs: waiting"); await MainPanel.WaitForStatistics(); await DiffPanel.WaitForStatistics(); Trace.TraceInformation("AnalyzeDocumentDiffs: start"); var comparedSections = new List<(IRTextSection, IRTextSection)>(); var comparedFuncts = new List(); Session.SetApplicationProgress(true, double.NaN, "Computing document diffs"); foreach (var function in MainSummary.Functions) { var functionEx = MainPanel.GetFunctionExtension(function); if (functionEx.IsDeletionDiff || functionEx.IsInsertionDiff) { functionEx.Statistics.ComputeDiff(functionEx.Statistics); // Consider as no diff. continue; } var otherFunctionEx = DiffPanel.GetFunctionExtension(function); var otherFunction = otherFunctionEx.Function; //? TODO: With multiple, which should be compared? Probably all of them, but expensive if (function.SectionCount > 0 && otherFunction.SectionCount > 0) { comparedSections.Add((function.Sections[0], otherFunction.Sections[0])); comparedFuncts.Add(functionEx); } functionEx.Statistics.ComputeDiff(otherFunctionEx.Statistics); } var results = await ComputeSectionIRDiffs(comparedSections); for (int i = 0; i < comparedFuncts.Count; i++) { if (results[i].HasDiffs) { comparedFuncts[i].FunctionDiffKind = DiffKind.Modification; } } MainPanel.AddStatisticsFunctionListColumns(true, " (D)", " delta", 55); MainPanel.RefreshFunctionList(); Session.SetApplicationProgress(false, double.NaN); Trace.TraceInformation("AnalyzeDocumentDiffs: done"); } public async Task ShowModuleReport() { await MainPanel.ShowModuleReport(); } public void MarkFunctions(List list) { MainPanel.MarkFunctions(list); } public void ClearMarkedFunctions() { MainPanel.ClearMarkedFunctions(); } private void MainPanel_SectionListScrollChanged(object sender, double offset) { // When using the grid splitter to resize the left/right panels, // the event gets called for some reason with a 0 offset and // the current vertical offset gets reset. //? TODO: Ignoring 0 offset causes other scroll issues, likely fix is to ignore //? the event between grid splitter mouse down and up events. if (SyncDiffedDocuments) { var otherPanel = PickOtherPanel(sender); if (otherPanel.Summary != null && diffModeEnabled_) { otherPanel.ScrollSectionList(offset); } } } private SectionPanel PickOtherPanel(object sender) { var panel = sender as SectionPanel; return panel == MainPanel ? DiffPanel : MainPanel; } private async void DiffPanel_FunctionSwitched(object sender, IRTextFunction func) { var otherPanel = PickOtherPanel(sender); if (otherPanel.Summary != null && diffModeEnabled_) { await SwitchPanelDiffFunction(func, otherPanel); } } private async Task SwitchPanelDiffFunction(IRTextFunction func, SectionPanel otherPanel) { var otherFunc = otherPanel.Summary.FindFunction(func.Name); if (otherFunc != null) { await otherPanel.SelectFunction(otherFunc); } await ComputePanelSectionDiff(); } private void MainPanel_EnterDiffMode(object sender, DiffModeEventArgs e) { if (e.IsWithOtherDocument) { var panel = sender as SectionPanel; var otherSection = FindDiffDocumentSection(e.Left.Section); if (panel == MainPanel) { e.Left.OpenKind = OpenSectionKind.ReplaceLeft; e.Right = new OpenSectionEventArgs(otherSection, OpenSectionKind.ReplaceRight); } else { e.Right = e.Left; e.Right.OpenKind = OpenSectionKind.ReplaceRight; e.Left = new OpenSectionEventArgs(otherSection, OpenSectionKind.ReplaceLeft); } } EnterDiffMode?.Invoke(sender, e); } private void MainPanel_SyncDiffedDocumentsChanged(object sender, bool e) { SyncDiffedDocumentsChanged?.Invoke(this, e); PickOtherPanel(sender).SyncDiffedDocuments = e; } private void MainPanel_DisplayCallGraph(object sender, DisplayCallGraphEventArgs e) { DisplayCallGraph?.Invoke(this, e); } private void MainPanel_OpenSection(object sender, OpenSectionEventArgs e) { if (e.OpenKind == OpenSectionKind.ReplaceCurrent && diffModeEnabled_) { if (sender == MainPanel) { e.OpenKind = OpenSectionKind.ReplaceLeft; } else if (sender == DiffPanel) { e.OpenKind = OpenSectionKind.ReplaceRight; } } OpenSection?.Invoke(sender, e); } private async Task ComputePanelSectionDiff() { var baseExtList = MainPanel.CreateSectionsExtension(); var diffExtList = DiffPanel.CreateSectionsExtension(); var (baseList, diffList) = ComputeSectionNameListDiff(baseExtList, diffExtList); MainPanel.Sections = baseList; DiffPanel.Sections = diffList; var results = await ComputeSectionIRDiffs(baseList, diffList); DocumentDiffResult firstDiffResult = null; foreach (var result in results) { if (result.HasDiffs) { var baseSection = MainPanel.GetSectionExtension(result.LeftSection); var diffSection = DiffPanel.GetSectionExtension(result.RightSection); baseSection.SectionDiffKind = DiffKind.Modification; diffSection.SectionDiffKind = DiffKind.Modification; firstDiffResult ??= result; } } // Scroll to the first diff section. if (firstDiffResult != null) { // Force scrolling to happen after other layout updates, // otherwise the section lists scroll back to offset 0 // on the next layout update, looks like a WPF bug... Dispatcher.Invoke(() => { MainPanel.SelectSection(firstDiffResult.LeftSection, false); DiffPanel.SelectSection(firstDiffResult.RightSection, false); }, DispatcherPriority.Background); } } private SectionPanel SelectSectionPanel(IRTextSection section) { var summary = section.ParentFunction.ParentSummary; if (MainPanel.HasSummary(summary)) { return MainPanel; } if (DiffPanel.HasSummary(summary)) { return DiffPanel; } return null; } private (List, List) ComputeSectionNameListDiff( List baseList, List diffList) { int[,] m = new int[baseList.Count + 1, diffList.Count + 1]; int x; int y; for (x = 1; x <= baseList.Count; x++) { for (y = 1; y <= diffList.Count; y++) { var baseSection = baseList[x - 1]; var diffSection = diffList[y - 1]; if (baseSection.Name == diffSection.Name) { m[x, y] = m[x - 1, y - 1] + 1; } else { m[x, y] = Math.Max(m[x, y - 1], m[x - 1, y]); } } } int index = 0; var newBaseList = new List(baseList.Count); var newDiffList = new List(diffList.Count); x = baseList.Count; y = diffList.Count; while (!(x == 0 && y == 0)) { if (x > 0 && y > 0) { var baseSection = baseList[x - 1]; var diffSection = diffList[y - 1]; if (baseSection.Name == diffSection.Name) { // Found in both diff and base. newBaseList.Add(baseSection); newDiffList.Add(diffSection); x--; y--; continue; } } if (y > 0 && (x == 0 || m[x, y - 1] >= m[x - 1, y])) { // Found in diff, missing in base. var diffSection = diffList[y - 1]; newDiffList.Add( new IRTextSectionEx(diffSection.Section, DiffKind.Insertion, diffSection.Name, index++)); var placeholderSection = new IRTextSection(diffSection.Section.ParentFunction, "", IRPassOutput.Empty); newBaseList.Add(new IRTextSectionEx(placeholderSection, DiffKind.Placeholder, "", index++)); y--; } else if (x > 0 && (y == 0 || m[x, y - 1] < m[x - 1, y])) { // Not found in diff, removed from base. var baseSection = baseList[x - 1]; newBaseList.Add(new IRTextSectionEx(baseSection.Section, DiffKind.Deletion, baseSection.Name, index++)); var placeholderSection = new IRTextSection(baseSection.Section.ParentFunction, "", IRPassOutput.Empty); newDiffList.Add(new IRTextSectionEx(placeholderSection, DiffKind.Placeholder, "", index++)); x--; } else { Debug.Assert(false); } } newBaseList.Reverse(); newDiffList.Reverse(); return (newBaseList, newDiffList); } private async Task> ComputeSectionIRDiffs( List baseSections, List diffSections) { var comparedSections = new List<(IRTextSection, IRTextSection)>(); for (int i = 0; i < baseSections.Count; i++) { if (baseSections[i].SectionDiffKind == DiffKind.None && diffSections[i].SectionDiffKind == DiffKind.None) { comparedSections.Add((baseSections[i].Section, diffSections[i].Section)); } } //? TODO: Pass the LoadedDocument to the panel, not Summary. return await ComputeSectionIRDiffs(comparedSections); } private async Task> ComputeSectionIRDiffs( List<(IRTextSection, IRTextSection)> comparedSections) { var baseLoader = Session.SessionState.FindLoadedDocument(MainPanel.Summary).Loader; var diffLoader = Session.SessionState.FindLoadedDocument(DiffPanel.Summary).Loader; var diffBuilder = new DocumentDiffBuilder(App.Settings.DiffSettings); var cancelableTask = new CancelableTask(); return await diffBuilder.AreSectionsDifferent(comparedSections, baseLoader, diffLoader, Session.CompilerInfo, true, cancelableTask); } public async Task UpdateMarkedFunctions(bool externalCall) { await MainPanel.UpdateMarkedFunctions(externalCall); await DiffPanel.UpdateMarkedFunctions(externalCall); } } ================================================ FILE: src/ProfileExplorerUI/Panels/SourceFilePanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/SourceFilePanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Panels; using ProfileExplorer.UI.Profile; using ProfileExplorer.UI.Profile.Document; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Binary; namespace ProfileExplorer.UI; public partial class SourceFilePanel : ToolPanelControl, INotifyPropertyChanged { private SourceFileFinder sourceFileFinder_; private IRTextSection section_; private IRElement syncedElement_; private bool sourceFileLoaded_; private IRTextFunction sourceFileFunc_; private string sourceFilePath_; private SourceStackFrame currentInlinee_; private OptionsPanelHostPopup optionsPanelPopup_; private SourceFileSettings settings_; private bool disableInlineeComboboxEvents_; private IRDocument associatedDocument_; private string inlineeText_; private CancelableTaskInstance loadTask_; public SourceFilePanel() { InitializeComponent(); DataContext = this; SetupEvents(); loadTask_ = new CancelableTaskInstance(false); } public override ToolPanelKind PanelKind => ToolPanelKind.Source; public override HandledEventKind HandledEvents => HandledEventKind.ElementSelection; public bool HasInlinees => InlineeComboBox.Items.Count > 0; public override IUISession Session { get => base.Session; set { base.Session = value; ProfileTextView.Session = value; if (value != null) { Settings = App.Settings.SourceFileSettings; } } } public SourceFileSettings Settings { get => settings_; set { settings_ = value; ReloadSourceFileFinder(settings_.FinderSettings); OnPropertyChanged(); if (settings_.SyncStyleWithDocument) { // Patch the settings with the document settings. var clone = settings_.Clone(); clone.FontName = App.Settings.DocumentSettings.FontName; clone.FontSize = App.Settings.DocumentSettings.FontSize; clone.BackgroundColor = App.Settings.DocumentSettings.BackgroundColor; clone.TextColor = App.Settings.DocumentSettings.TextColor; ProfileTextView.Initialize(clone); } else { ProfileTextView.Initialize(settings_); } } } public string InlineeText { get => inlineeText_; set { inlineeText_ = value; OnPropertyChanged(); } } public bool SourceFileLoaded { get => sourceFileLoaded_; set { sourceFileLoaded_ = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; private void SetupEvents() { ProfileTextView.LineSelected += (s, line) => { if (settings_.SyncLineWithDocument) { associatedDocument_?.SelectElementsOnSourceLine(line, currentInlinee_); } }; } private void ReloadSourceFileFinder(SourceFileFinderSettings settings) { sourceFileFinder_ = new SourceFileFinder(Session); sourceFileFinder_.LoadSettings(settings); } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private void InlineeComboBox_Loaded(object sender, RoutedEventArgs e) { if (sender is ComboBox control) { Utils.PatchComboBoxStyle(control); } } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private string BrowseSourceFile() { return Utils.ShowOpenFileDialog( "C/C++ source files|*.c;*.cpp;*.cc;*.cxx;*.h;*.hpp;*.hxx;*.hh|.NET source files|*.cs;*.vb|All Files|*.*", string.Empty); } private void SetPanelName(string path) { if (!string.IsNullOrEmpty(path)) { TitleSuffix = $" - {Utils.TryGetFileName(path)}"; TitleToolTip = path; } else { TitleSuffix = ""; TitleToolTip = null; } Session.UpdatePanelTitles(); } private async void OpenButton_Click(object sender, RoutedEventArgs e) { string path = BrowseSourceFile(); if (path != null) { var sourceInfo = new SourceFileDebugInfo(path, path); if (await ProfileTextView.LoadSourceFile(sourceInfo, section_)) { HandleLoadedSourceFile(sourceInfo, section_.ParentFunction); } } } private async void InlineeCombobox_SelectionChanged(object sender, SelectionChangedEventArgs e) { // Handling of inlinees not handled quite right, disable for now. // if (InlineeComboBox.SelectedItem != null && // !disableInlineeComboboxEvents_) { // UpdateInlineeText(); // var inlinee = (SourceStackFrame)InlineeComboBox.SelectedItem; // // if (InlineeComboBox.SelectedIndex > 0 && // await LoadInlineeSourceFile(inlinee)) { // return; // } // // // If failing to load inlinee, load main source file instead. // currentInlinee_ = null; // await LoadSourceFileForFunction(section_.ParentFunction, ProfileTextView.ProfileFilter); // } } private void InlineUpButton_Click(object sender, RoutedEventArgs e) { if (InlineeComboBox.ItemsSource != null && InlineeComboBox.SelectedIndex > 0) { InlineeComboBox.SelectedIndex--; UpdateInlineeText(); } } private void InlineDownButton_Click(object sender, RoutedEventArgs e) { if (InlineeComboBox.ItemsSource != null && InlineeComboBox.SelectedIndex < ((ListCollectionView)InlineeComboBox.ItemsSource).Count - 1) { InlineeComboBox.SelectedIndex++; UpdateInlineeText(); } } private void UpdateInlineeText() { int total = ((ListCollectionView)InlineeComboBox.ItemsSource).Count; InlineeText = $"{InlineeComboBox.SelectedIndex + 1}/{total}"; } private async void ResetButton_Click(object sender, RoutedEventArgs e) { // Re-enable source mapper if it was disabled before. if (Utils.ShowYesNoMessageBox("Do you want to reset all file mappings and exclusions?", this) == MessageBoxResult.No) { return; } sourceFileFinder_.Reset(); sourceFileFinder_.SaveSettings(settings_.FinderSettings); await ReloadSourceFile(); } private async void ClearAllFileExclusions_Click(object sender, RoutedEventArgs e) { // Re-enable source mapper if it was disabled before. if (Utils.ShowYesNoMessageBox("Do you want to remove all local file mapping exclusions?", this) == MessageBoxResult.No) { return; } sourceFileFinder_.ResetDisabledMappings(); sourceFileFinder_.SaveSettings(settings_.FinderSettings); await ReloadSourceFile(); } private async void ClearFileExclusion_Click(object sender, RoutedEventArgs e) { sourceFileFinder_.ResetDisabledMappings(sourceFilePath_); sourceFileFinder_.SaveSettings(settings_.FinderSettings); await ReloadSourceFile(); } private async Task ReloadSourceFile() { if (section_ == null) { return; } SourceFileLoaded = false; // Force a reload. await LoadSourceFileForFunction(section_.ParentFunction, null); } private void SourceFile_CopyPath(object sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(sourceFilePath_)) { Clipboard.SetText(sourceFilePath_); } } private void SourceFile_Open(object sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(sourceFilePath_)) { Utils.OpenExternalFile(sourceFilePath_); } } private void SourceFile_Show(object sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(sourceFilePath_)) { Utils.OpenExplorerAtFile(sourceFilePath_); } } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } FrameworkElement relativeControl = ProfileTextView; optionsPanelPopup_ = OptionsPanelHostPopup.Create( settings_.Clone(), relativeControl, Session, async (newSettings, commit) => { if (!newSettings.Equals(settings_)) { App.Settings.SourceFileSettings = newSettings; Settings = newSettings; await ReloadSourceFile(); if (commit) { App.SaveApplicationSettings(); } return settings_.Clone(); } return null; }, () => optionsPanelPopup_ = null); } public async Task LoadSourceFile(IRTextSection section, ProfileSampleFilter profileFilter = null, IRDocument associatedDocument = null, bool restoreState = false) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (section_ != null && section_.Equals(section)) { return; } Utils.EnableControl(this); section_ = section; associatedDocument_ = associatedDocument; await LoadSourceFileForFunction(section_.ParentFunction, profileFilter, restoreState); } public override async Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document) { await base.OnDocumentSectionLoaded(section, document); await LoadSourceFile(section, null, document, true); } private async Task LoadSourceFileForFunction(IRTextFunction function, ProfileSampleFilter profileFilter = null, bool restoreState = false) { if (!ShouldReloadFunction(function, profileFilter)) { return true; } // Get the associated source file from the debug info if available, // since it also includes the start line number. var (sourceInfo, failureReason) = await sourceFileFinder_.FindLocalSourceFile(function); sourceFileFinder_.SaveSettings(settings_.FinderSettings); byte[] data = Session.LoadPanelState(this, section_) as byte[]; var state = UIStateSerializer.Deserialize(data); if (!sourceInfo.IsUnknown && failureReason == SourceFileFinder.FailureReason.None && await ProfileTextView.LoadSourceFile(sourceInfo, section_, profileFilter, null, state)) { HandleLoadedSourceFile(sourceInfo, function); return true; } await HandleMissingSourceFile(sourceInfo, failureReason); return false; } private async Task LoadSourceFileForInlinee(SourceStackFrame inlinee, ProfileSampleFilter profileFilter = null) { if (!ShouldReloadInlinee(inlinee, profileFilter)) { return true; } // Get the associated source file from the debug info if available, // since it also includes the start line number. var inlineeSourceInfo = new SourceFileDebugInfo(inlinee.FilePath, inlinee.FilePath); var (sourceInfo, failureReason) = await sourceFileFinder_.FindLocalSourceFile(inlineeSourceInfo); sourceFileFinder_.SaveSettings(settings_.FinderSettings); if (!sourceInfo.IsUnknown && failureReason == SourceFileFinder.FailureReason.None && await ProfileTextView.LoadSourceFile(sourceInfo, section_, profileFilter, inlinee)) { HandleLoadedSourceFile(sourceInfo, null); return true; } await HandleMissingSourceFile(sourceInfo, failureReason); return false; } private bool ShouldReloadFunction(IRTextFunction function, ProfileSampleFilter profileFilter) { if (!SourceFileLoaded) { return true; } if (sourceFileFunc_ != function) { return true; } return HasProfileFilterChange(profileFilter); } private bool ShouldReloadInlinee(SourceStackFrame inlinee, ProfileSampleFilter profileFilter) { if (!SourceFileLoaded || currentInlinee_ == null) { return true; } if (!currentInlinee_.HasSameFunction(inlinee)) { return true; } return HasProfileFilterChange(profileFilter); } private bool HasProfileFilterChange(ProfileSampleFilter profileFilter) { if (profileFilter != null) { return !profileFilter.Equals(ProfileTextView.ProfileFilter); } else { // Filter is being removed. return ProfileTextView.ProfileFilter != null; } } private void HandleLoadedSourceFile(SourceFileDebugInfo sourceInfo, IRTextFunction function) { SetPanelName(sourceInfo.OriginalFilePath); SourceFileLoaded = true; sourceFileFunc_ = function; sourceFilePath_ = sourceInfo.FilePath; } private async Task HandleMissingSourceFile(SourceFileDebugInfo sourceInfo, SourceFileFinder.FailureReason reason) { string failureText = reason switch { SourceFileFinder.FailureReason.DebugInfoNotFound => "Could not find debug info for function.", SourceFileFinder.FailureReason.MappingDisabled => """ Mapping to local file path disabled for current file. To re-enable mapping, use the Reset button -> Clear File Exclusion option. """, _ => "Could not find local copy of source file." }; await ProfileTextView.HandleMissingSourceFile(failureText); SetPanelName(""); SourceFileLoaded = false; sourceFileFunc_ = null; // Saved failed source file path for resetting exclusions. sourceFilePath_ = sourceInfo.FilePath; } public override async Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { if (section_ != section) { return; } using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); ProfileTextView.SaveSectionState(this); await base.OnDocumentSectionUnloaded(section, document); await ResetState(); Utils.DisableControl(this); } private async Task ResetState() { ResetInlinee(); await ProfileTextView.Reset(); section_ = null; SourceFileLoaded = false; sourceFileFunc_ = null; currentInlinee_ = null; associatedDocument_ = null; InlineeComboBox.ItemsSource = null; OnPropertyChanged(nameof(HasInlinees)); } public override async void OnElementSelected(IRElementEventArgs e) { if (!SourceFileLoaded) { return; } //Trace.WriteLine($"Selected element: {element_}"); syncedElement_ = e.Element; var instr = syncedElement_.ParentInstruction; var tag = instr?.GetTag(); if (tag != null) { // Handling of inlinees not handled quite right, disable for now. // // if (tag.HasInlinees && // settings_.SyncLineWithDocument && // settings_.SyncInlineeWithDocument) { // // Display deepest inlinee instead, if that fails // // then it falls back to loading the function's source below. // if (!await LoadInlineeSourceFile(tag)) { // InlineeComboBox.SelectedIndex = 0; // First item means "no inlinee". // } // // return; // } // else { // ResetInlinee(); // } if (await LoadSourceFileForFunction(section_.ParentFunction, ProfileTextView.ProfileFilter)) { if (settings_.SyncLineWithDocument) { ProfileTextView.SelectLine(tag.Line); } } } } private async Task LoadInlineeSourceFile(SourceLocationTag tag) { var selectedInlinee = PopulateInlineePicker(tag); return await LoadInlineeSourceFile(selectedInlinee); } private SourceStackFrame PopulateInlineePicker(SourceLocationTag tag) { disableInlineeComboboxEvents_ = true; var inlinees = tag.InlineesReversed; // Add an entry that means "no inlinee" in the front. inlinees.Insert(0, new SourceStackFrame("No Inlinee", "", 0, 0)); InlineeComboBox.ItemsSource = new ListCollectionView(inlinees); OnPropertyChanged(nameof(HasInlinees)); var selectedInlinee = inlinees[^1]; InlineeComboBox.SelectedItem = selectedInlinee; disableInlineeComboboxEvents_ = false; UpdateInlineeText(); return selectedInlinee; } private void ResetInlinee() { InlineeComboBox.ItemsSource = null; currentInlinee_ = null; OnPropertyChanged(nameof(HasInlinees)); } public async Task LoadInlineeSourceFile(SourceStackFrame inlinee) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (inlinee == currentInlinee_) { return true; } bool fileLoaded = await LoadSourceFileForInlinee(inlinee); if (fileLoaded) { ProfileTextView.SelectLine(inlinee.Line); } currentInlinee_ = inlinee; return fileLoaded; } public override async void OnSessionEnd() { base.OnSessionEnd(); await ResetState(); //? TODO: Make OnSessionEnd async ProfileTextView.SetSourceText("", ""); } private async void PanelToolbarTray_OnHelpClicked(object sender, EventArgs e) { await HelpPanel.DisplayPanelHelp(PanelKind, Session); } private void PanelToolbarTray_OnSettingsClicked(object sender, EventArgs e) { ShowOptionsPanel(); } public override async Task OnReloadSettings() { sourceFileFinder_.SaveSettings(settings_.FinderSettings); Settings = App.Settings.SourceFileSettings; } private async void CopySelectedLinesAsHtmlExecuted(object sender, ExecutedRoutedEventArgs e) { await ProfileTextView.CopySelectedLinesAsHtml(); } private async void OpenPopupButton_Click(object sender, RoutedEventArgs e) { if (ProfileTextView.Section == null) { return; //? TODO: Button should rather be disabled } await IRDocumentPopupInstance.ShowPreviewPopup(ProfileTextView.Section.ParentFunction, "", this, Session, ProfileTextView.ProfileFilter, true); } private async void InlineeButton_OnClick(object sender, RoutedEventArgs e) { // Load main function if inlinee syncing gets disabled. if (!settings_.SyncInlineeWithDocument && section_ != null) { await LoadSourceFileForFunction(section_.ParentFunction, ProfileTextView.ProfileFilter); } } private void CollapseAssemblyButton_Click(object sender, RoutedEventArgs e) { ProfileTextView.CollapseBlockFoldings(); } private void ExpandAssemblyButton_Click(object sender, RoutedEventArgs e) { ProfileTextView.ExpandBlockFoldings(); } private async void ToggleButton_Click(object sender, RoutedEventArgs e) { await OnReloadSettings(); await ReloadSourceFile(); } } ================================================ FILE: src/ProfileExplorerUI/Panels/StartPagePanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/StartPagePanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; namespace ProfileExplorer.UI.Panels; public partial class StartPagePanel : UserControl { public StartPagePanel() { InitializeComponent(); } public event EventHandler OpenRecentDocument; public event EventHandler> OpenRecentDiffDocuments; public event EventHandler OpenRecentProfileSession; public event EventHandler OpenFile; public event EventHandler CompareFiles; public event EventHandler ClearRecentDocuments; public event EventHandler ClearRecentDiffDocuments; public event EventHandler ClearRecentProfileSessions; public event EventHandler LoadProfile; public event EventHandler RecordProfile; public void ReloadFileList() { RecentFilesListBox.ItemsSource = new ListCollectionView(App.Settings.RecentFiles); RecentFilesListBox.Visibility = App.Settings.RecentFiles.Count > 0 ? Visibility.Visible : Visibility.Collapsed; RecentDiffFilesListBox.ItemsSource = new ListCollectionView(App.Settings.RecentComparedFiles); RecentDiffFilesListBox.Visibility = App.Settings.RecentComparedFiles.Count > 0 ? Visibility.Visible : Visibility.Collapsed; var profileSettings = App.Settings.ProfileOptions; var sessionList = new List(); foreach (var prevSession in profileSettings.PreviousLoadedSessions) { sessionList.Add(new RecordingSession(prevSession, true)); } RecentProfilesListBox.ItemsSource = new ListCollectionView(sessionList); RecentProfilesListBox.Visibility = profileSettings.PreviousLoadedSessions.Count > 0 ? Visibility.Visible : Visibility.Collapsed; } private void RecentFilesListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { InvokeOpenRecentDocument(); e.Handled = true; } private void RecentFilesListBox_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { InvokeOpenRecentDocument(); e.Handled = true; } } private void RecentProfilesListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { InvokeOpenRecentProfileSession(); e.Handled = true; } private void RecentProfilesListBox_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { InvokeOpenRecentProfileSession(); e.Handled = true; } } private void RecentDiffFilesListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e) { InvokeOpenRecentDiffDocuments(); e.Handled = true; } private void RecentDiffFilesListBox_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Enter) { InvokeOpenRecentDiffDocuments(); e.Handled = true; } } private void InvokeOpenRecentDocument() { if (RecentFilesListBox.SelectedItem != null) { OpenRecentDocument?.Invoke(this, (string)RecentFilesListBox.SelectedItem); } } private void InvokeOpenRecentDiffDocuments() { if (RecentDiffFilesListBox.SelectedItem != null) { OpenRecentDiffDocuments?.Invoke(this, (Tuple)RecentDiffFilesListBox.SelectedItem); } } private void InvokeOpenRecentProfileSession() { if (RecentProfilesListBox.SelectedItem != null) { OpenRecentProfileSession?.Invoke(this, (RecordingSession)RecentProfilesListBox.SelectedItem); } } private void TextBlock_MouseDown(object sender, MouseButtonEventArgs e) { App.InstallExtension(); } private void TextBlock_MouseDown_1(object sender, MouseButtonEventArgs e) { App.OpenDocumentation(); } private void OpenFileButton_Click(object sender, RoutedEventArgs e) { OpenFile?.Invoke(this, null); } private void OpenBaseDiffFilesButton_Click(object sender, RoutedEventArgs e) { CompareFiles?.Invoke(this, null); } private void ClearButton_Click(object sender, RoutedEventArgs e) { ClearRecentDocuments?.Invoke(this, null); } private void ClearSessionsButton_Click(object sender, RoutedEventArgs e) { ClearRecentProfileSessions?.Invoke(this, null); } private void ClearDiffButton_Click(object sender, RoutedEventArgs e) { ClearRecentDiffDocuments?.Invoke(this, null); } private void TextSearch_Populating(object sender, PopulatingEventArgs e) { var box = (AutoCompleteBox)sender; box.ItemsSource = null; box.ItemsSource = App.Settings.RecentFiles; box.PopulateComplete(); } private void TextSearch_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) { TextSearch.Text = ""; } else if (e.Key == Key.Enter) { RecentFilesListBox.SelectedItem = TextSearch.Text; InvokeOpenRecentDocument(); } } private void ProfileTextSearch_Populating(object sender, PopulatingEventArgs e) { var box = (AutoCompleteBox)sender; box.ItemsSource = null; box.ItemsSource = App.Settings.ProfileOptions.PreviousLoadedSessions; box.PopulateComplete(); } private void ProfileTextSearch_KeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Escape) { TextSearch.Text = ""; } else if (e.Key == Key.Enter) { RecentProfilesListBox.SelectedItem = TextSearch.Text; InvokeOpenRecentProfileSession(); } } private void RemoveButton_OnClick(object sender, RoutedEventArgs e) { if (((Button)sender).DataContext is string item) { App.Settings.RemoveRecentFile(item); ReloadFileList(); } } private void DiffRemoveButton_OnClick(object sender, RoutedEventArgs e) { if (((Button)sender).DataContext is Tuple item) { App.Settings.RemoveRecentComparedFiles(item); ReloadFileList(); } } private void RemoveProfileButton_OnClick(object sender, RoutedEventArgs e) { if (((Button)sender).DataContext is RecordingSession session) { App.Settings.RemoveLoadedProfileSession(session.Report); ReloadFileList(); } } private void RecordProfileButton_Click(object sender, RoutedEventArgs e) { RecordProfile?.Invoke(this, null); } private void LoadProfileButton_Click(object sender, RoutedEventArgs e) { LoadProfile?.Invoke(this, null); } } ================================================ FILE: src/ProfileExplorerUI/Panels/ToolPanelControl.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Threading.Tasks; using System.Windows.Controls; using ProfileExplorer.Core; namespace ProfileExplorer.UI; public class ToolPanelControl : UserControl, IToolPanel { public virtual ToolPanelKind PanelKind => ToolPanelKind.Other; public virtual string TitlePrefix { get; set; } public virtual string TitleSuffix { get; set; } public virtual string TitleToolTip { get; set; } public virtual HandledEventKind HandledEvents => HandledEventKind.None; public virtual IRDocument Document { get; set; } public virtual IRDocument BoundDocument { get; set; } public virtual IUISession Session { get; set; } public virtual bool SavesStateToFile => false; public virtual bool IsUnloaded => Document == null; public virtual bool IsPanelEnabled { get; set; } public virtual bool HasCommandFocus { get; set; } public virtual bool HasPinnedContent { get; set; } public virtual bool IgnoreNextLoadEvent { get; set; } public virtual bool IgnoreNextUnloadEvent { get; set; } public virtual void OnRegisterPanel() { IsPanelEnabled = true; } public virtual void OnUnregisterPanel() { } public virtual void OnElementSelected(IRElementEventArgs e) { } public virtual void OnElementHighlighted(IRHighlightingEventArgs e) { } public virtual Task OnReloadSettings() { return Task.CompletedTask; } public async virtual Task OnDocumentSectionLoaded(IRTextSection section, IRDocument document) { Document = document; } public async virtual Task OnDocumentSectionUnloaded(IRTextSection section, IRDocument document) { Document = null; } public virtual void OnActivatePanel() { } public virtual void OnDeactivatePanel() { } public virtual void OnRedrawPanel() { } public virtual void OnHidePanel() { } public virtual void OnShowPanel() { } public virtual void ClonePanel(IToolPanel basePanel) { } public virtual void OnSessionStart() { Utils.EnableControl(this); } public virtual void OnSessionSave() { } public virtual void OnSessionEnd() { Document = null; Utils.DisableControl(this, 0.75); } public virtual void OnDocumentLoaded(IRDocument document) { } } ================================================ FILE: src/ProfileExplorerUI/Panels/ValueStatisticPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Panels/ValueStatisticPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using ProfileExplorer.Core; namespace ProfileExplorer.UI; public partial class ValueStatisticPanel : UserControl { private ValueStatistics valueStats_; private int factor_; public ValueStatisticPanel() { InitializeComponent(); factor_ = 1; } public event EventHandler> RangeSelected; private void Expander_Expanded(object sender, RoutedEventArgs e) { valueStats_ = (ValueStatistics)DataContext; FactorSlider.Maximum = valueStats_.MaxDistributionFactor; UpdateDistribution(factor_); } private void UpdateDistribution(int factor) { var distribList = valueStats_.ComputeDistribution(factor); DistributionList.ItemsSource = new ListCollectionView(distribList); GroupSizeLabel.Text = valueStats_.GetGroupSize(factor).ToString(); } private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { if (valueStats_ != null) { factor_ = (int)e.NewValue; UpdateDistribution(factor_); } } private void DistributionList_SelectionChanged(object sender, SelectionChangedEventArgs e) { var range = DistributionList.SelectedItem as ValueStatistics.DistributionRange; if (range == null) { return; } var funcList = new List(range.Values.Count); foreach (var value in range.Values) { funcList.Add(value.Item1); } range.Values.Sort((a, b) => { int result = a.Item2.CompareTo(b.Item2); if (result != 0) { return result; } return a.Item1.Name.CompareTo(b.Item1.Name); }); RangeSelected?.Invoke(this, funcList); } } ================================================ FILE: src/ProfileExplorerUI/Profile/CallTreeNodePanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/CallTreeNodePanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using OxyPlot; using OxyPlot.Annotations; using OxyPlot.Axes; using OxyPlot.Series; using OxyPlot.Wpf; using ProfileExplorer.Core; using ProfileExplorer.UI.Controls; using PlotCommands = OxyPlot.PlotCommands; using VerticalAlignment = System.Windows.VerticalAlignment; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI.Profile; public interface IFunctionProfileInfoProvider { List GetBacktrace(ProfileCallTreeNode node); (List, List Modules) GetTopFunctionsAndModules(ProfileCallTreeNode node); } public class ProfileCallTreeNodeEx : BindableObject { public ProfileCallTreeNodeEx(ProfileCallTreeNode callTreeNode) { CallTreeNode = callTreeNode; } public ProfileCallTreeNode CallTreeNode { get; } public string FunctionName { get; set; } public string FullFunctionName { get; set; } public string ModuleName { get; set; } public double Percentage { get; set; } public double ExclusivePercentage { get; set; } public bool IsMarked { get; set; } public TimeSpan Weight => CallTreeNode.Weight; public TimeSpan ExclusiveWeight => CallTreeNode.ExclusiveWeight; } public class ThreadListItem { public int ThreadId { get; set; } public string Title { get; set; } public string ToolTip { get; set; } public string WeightToolTip { get; set; } public TimeSpan Weight { get; set; } public TimeSpan ExclusiveWeight { get; set; } public double Percentage { get; set; } public double ExclusivePercentage { get; set; } public Brush Background { get; set; } } public partial class CallTreeNodePanel : ToolPanelControl, INotifyPropertyChanged { private const int MaxFunctionNameLength = 100; private const int MaxModuleNameLength = 50; private ProfileCallTreeNodeEx nodeEx_; private int nodeInstanceIndex_; private List instanceNodes_; private IFunctionProfileInfoProvider funcInfoProvider_; private bool histogramVisible_; private ProfileCallTreeNodeEx instancesNode_; private ProfileCallTreeNodeEx averageNode_; private ProfileCallTreeNodeEx mediansNode_; private int funcInstancesCount_; private int currentInstanceIndex_; private bool showDetails_; private bool showInstanceNavigation_; private bool useSelfTimeHistogram_; private CallTreeNodeSettings settings_; private bool enableSingleNodeActions_; public CallTreeNodePanel() { InitializeComponent(); SetupEvents(); DataContext = this; CallTreeNode = null; } public override IUISession Session { get => base.Session; set { base.Session = value; BacktraceList.Session = value; FunctionList.Session = value; ModuleList.Session = value; ModuleFunctionList.Session = value; CategoryList.Session = value; CategoryFunctionList.Session = value; InstancesList.Session = value; } } public CallTreeNodeSettings Settings { get => settings_; set { settings_ = value; BacktraceList.Settings = value; FunctionList.Settings = value; ModuleList.Settings = value; ModuleFunctionList.Settings = value; CategoryList.Settings = value; CategoryFunctionList.Settings = value; InstancesList.Settings = value; BacktraceList.RestoreColumnsState(settings_.StackListColumns); FunctionList.RestoreColumnsState(settings_.FunctionListColumns); ModuleList.RestoreColumnsState(settings_.ModuleListColumns); ModuleFunctionList.RestoreColumnsState(settings_.ModuleFunctionListColumns); CategoryList.RestoreColumnsState(settings_.CategoryListColumns); CategoryFunctionList.RestoreColumnsState(settings_.CategoryFunctionListColumns); InstancesList.RestoreColumnsState(settings_.InstanceListColumns); OnPropertyChanged(nameof(HistogramInstanceBrush)); OnPropertyChanged(nameof(HistogramAverageBrush)); OnPropertyChanged(nameof(HistogramMedianBrush)); if (IsHistogramExpanded) { InvokeSetupInstancesHistogram(); } } } public bool IsInstancesExpanded { get => settings_ is {ExpandInstances: true}; set { settings_.ExpandInstances = value; OnPropertyChanged(); } } public bool IsHistogramExpanded { get => settings_ is {ExpandHistogram: true}; set { settings_.ExpandHistogram = value; OnPropertyChanged(); } } public bool IsThreadsListExpanded { get => settings_ is {ExpandThreads: true}; set { settings_.ExpandThreads = value; OnPropertyChanged(); } } public ProfileCallTreeNodeEx CallTreeNode { get => nodeEx_; set { SetField(ref nodeEx_, value); if (value != null) { Utils.EnableControl(this); } else { Utils.DisableControl(this); } } } public Brush HistogramInstanceBrush => settings_?.HistogramCurrentColor.AsBrush(); public Brush HistogramAverageBrush => settings_?.HistogramAverageColor.AsBrush(); public Brush HistogramMedianBrush => settings_?.HistogramMedianColor.AsBrush(); public ProfileCallTreeNodeEx InstancesNode { get => instancesNode_; set => SetField(ref instancesNode_, value); } public ProfileCallTreeNodeEx AverageNode { get => averageNode_; set => SetField(ref averageNode_, value); } public ProfileCallTreeNodeEx MedianNode { get => mediansNode_; set => SetField(ref mediansNode_, value); } public int FunctionInstancesCount { get => funcInstancesCount_; set => SetField(ref funcInstancesCount_, value); } public int CurrentInstanceIndex { get => currentInstanceIndex_; set => SetField(ref currentInstanceIndex_, value); } public bool ShowDetails { get => showDetails_; set { SetField(ref showDetails_, value); OnPropertyChanged(nameof(ShowInstanceNavigation)); } } public bool ShowInstanceNavigation { get => showInstanceNavigation_ && showDetails_; set => SetField(ref showInstanceNavigation_, value); } public bool UseSelfTimeHistogram { get => useSelfTimeHistogram_; set { if (SetField(ref useSelfTimeHistogram_, value)) { SetupInstancesHistogram(instanceNodes_, CallTreeNode.CallTreeNode, useSelfTimeHistogram_); } } } public bool EnableSingleNodeActions { get => enableSingleNodeActions_; set => SetField(ref enableSingleNodeActions_, value); } public RelayCommand ExcludeThreadCommand => new(async obj => { if (((FrameworkElement)obj).DataContext is ThreadListItem threadItem) { await ApplyThreadFilterAction(threadItem, ThreadActivityAction.ExcludeThread); } }); public RelayCommand ExcludeSameNameThreadCommand => new(async obj => { if (((FrameworkElement)obj).DataContext is ThreadListItem threadItem) { await ApplyThreadFilterAction(threadItem, ThreadActivityAction.ExcludeSameNameThread); } }); public RelayCommand FilterToThreadCommand => new(async obj => { if (((FrameworkElement)obj).DataContext is ThreadListItem threadItem) { await ApplyThreadFilterAction(threadItem, ThreadActivityAction.FilterToThread); } }); public RelayCommand FilterToSameNameThreadCommand => new(async obj => { if (((FrameworkElement)obj).DataContext is ThreadListItem threadItem) { await ApplyThreadFilterAction(threadItem, ThreadActivityAction.FilterToSameNameThread); } }); public RelayCommand PreviewFunctionCommand => new(async obj => { if (((FrameworkElement)obj).DataContext is ThreadListItem threadItem && instancesNode_.CallTreeNode != null) { var filter = new ProfileSampleFilter(threadItem.ThreadId); await IRDocumentPopupInstance.ShowPreviewPopup(instancesNode_.CallTreeNode.Function, "", ThreadsExpander, Session, filter); } }); public RelayCommand OpenFunctionCommand => new(async obj => { var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await OpenFunction(obj, mode); }); public RelayCommand OpenFunctionInNewTabCommand => new(async obj => { await OpenFunction(obj, OpenSectionKind.NewTab); }); public RelayCommand MarkModuleCommand => new(async obj => { if (obj is SelectedColorEventArgs e) { if (CallTreeNode.CallTreeNode is ProfileCallTreeGroupNode groupNode) { foreach (var node in groupNode.Nodes) { MarkModule(node.ModuleName, e.SelectedColor); } } else { MarkModule(CallTreeNode.CallTreeNode.ModuleName, e.SelectedColor); } } }); public RelayCommand MarkFunctionCommand => new(async obj => { if (obj is SelectedColorEventArgs e) { if (CallTreeNode.CallTreeNode is ProfileCallTreeGroupNode groupNode) { foreach (var node in groupNode.Nodes) { string funcName = node.FormatFunctionName(Session); MarkFunction(funcName, e.SelectedColor); } } else { string funcName = CallTreeNode.CallTreeNode.FormatFunctionName(Session); MarkFunction(funcName, e.SelectedColor); } } }); public event PropertyChangedEventHandler PropertyChanged; public event EventHandler NodeInstanceChanged; public event EventHandler BacktraceNodeClick; public event EventHandler BacktraceNodeDoubleClick; public event EventHandler InstanceNodeClick; public event EventHandler InstanceNodeDoubleClick; public event EventHandler FunctionNodeClick; public event EventHandler FunctionNodeDoubleClick; public event EventHandler ModuleNodeClick; public event EventHandler ModuleNodeDoubleClick; public event EventHandler> NodesSelected; public event EventHandler MarkingChanged; public void SaveListColumnSettings() { BacktraceList.SaveColumnsState(settings_.StackListColumns); FunctionList.SaveColumnsState(settings_.FunctionListColumns); ModuleList.SaveColumnsState(settings_.ModuleListColumns); ModuleFunctionList.SaveColumnsState(settings_.ModuleFunctionListColumns); CategoryList.SaveColumnsState(settings_.CategoryListColumns); CategoryFunctionList.SaveColumnsState(settings_.CategoryFunctionListColumns); InstancesList.SaveColumnsState(settings_.InstanceListColumns); } public void Show(ProfileCallTreeNodeEx nodeEx) { CallTreeNode = nodeEx; } public async Task ShowWithDetailsAsync(ProfileCallTreeNode node) { await ShowWithDetailsAsync(SetupNodeExtension(node, Session)); } public async Task ShowWithDetailsAsync(ProfileCallTreeNodeEx node) { CallTreeNode = node; await ShowDetailsAsync(); } public async Task ShowDetailsAsync() { ModuleFunctionList.Reset(); CategoryFunctionList.Reset(); await SetupInstanceInfo(CallTreeNode.CallTreeNode); ShowDetails = true; var markings = App.Settings.MarkingSettings.BuiltinMarkingCategories.FunctionColors; var task1 = Task.Run(() => funcInfoProvider_.GetBacktrace(CallTreeNode.CallTreeNode)); var task2 = Task.Run(() => funcInfoProvider_.GetTopFunctionsAndModules(CallTreeNode.CallTreeNode)); var task4 = Task.Run(() => ProfilingUtils.CollectMarkedFunctions(markings, false, Session, CallTreeNode.CallTreeNode)); BacktraceList.ShowFunctions(await task1); var (funcList, moduleList) = await task2; FunctionList.ShowFunctions(funcList, settings_.FunctionListViewFilter); ModuleList.ShowModules(moduleList); CategoryList.ShowCategories(await task4); ModuleList.SelectFirstItem(); CategoryList.SelectFirstItem(); } public void Initialize(IUISession session, IFunctionProfileInfoProvider funcInfoProvider) { Session = session; Settings = App.Settings.CallTreeNodeSettings; funcInfoProvider_ = funcInfoProvider; } public void UpdateMarkedFunctions() { BacktraceList.UpdateMarkedFunctions(); FunctionList.UpdateMarkedFunctions(); BacktraceList.UpdateMarkedFunctions(); InstancesList.UpdateMarkedFunctions(); ModuleList.UpdateMarkedFunctions(); ModuleFunctionList.UpdateMarkedFunctions(); CategoryList.UpdateMarkedFunctions(); CategoryFunctionList.UpdateMarkedFunctions(); } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private void SetupEvents() { BacktraceList.NodeClick += (sender, node) => BacktraceNodeClick?.Invoke(sender, node); BacktraceList.NodeDoubleClick += (sender, node) => BacktraceNodeDoubleClick?.Invoke(sender, node); BacktraceList.MarkingChanged += (sender, args) => MarkingChanged?.Invoke(sender, args); FunctionList.NodeClick += (sender, node) => FunctionNodeClick?.Invoke(sender, node); FunctionList.NodeDoubleClick += (sender, node) => FunctionNodeDoubleClick?.Invoke(sender, node); FunctionList.MarkingChanged += (sender, args) => MarkingChanged?.Invoke(sender, args); InstancesList.NodeClick += (sender, node) => InstanceNodeClick?.Invoke(sender, node); InstancesList.NodeDoubleClick += (sender, node) => InstanceNodeDoubleClick?.Invoke(sender, node); InstancesList.MarkingChanged += (sender, args) => MarkingChanged?.Invoke(sender, args); ModuleList.NodeClick += (sender, node) => ModuleNodeClick?.Invoke(sender, node); ModuleList.NodeDoubleClick += (sender, node) => ModuleNodeDoubleClick?.Invoke(sender, node); ModuleList.ModuleClick += (sender, moduleInfo) => UpdateModuleFunctions(moduleInfo); ModuleList.MarkingChanged += (sender, args) => MarkingChanged?.Invoke(sender, args); ModuleFunctionList.NodeClick += (sender, node) => FunctionNodeClick?.Invoke(sender, node); ModuleFunctionList.NodeDoubleClick += (sender, node) => FunctionNodeDoubleClick?.Invoke(sender, node); ModuleFunctionList.MarkingChanged += (sender, args) => MarkingChanged?.Invoke(sender, args); CategoryList.CategoryClick += (sender, category) => UpdateCategoryFunctions(category); CategoryFunctionList.NodeClick += (sender, node) => FunctionNodeClick?.Invoke(sender, node); CategoryFunctionList.NodeDoubleClick += (sender, node) => FunctionNodeDoubleClick?.Invoke(sender, node); CategoryFunctionList.MarkingChanged += (sender, args) => MarkingChanged?.Invoke(sender, args); } private void UpdateCategoryFunctions(FunctionMarkingCategory category) { CategoryFunctionList.ShowFunctions(category.SortedFunctions, settings_.FunctionListViewFilter); } private void UpdateModuleFunctions(ModuleProfileInfo moduleInfo) { ModuleFunctionList.ShowFunctions(moduleInfo.Functions, settings_.FunctionListViewFilter); } private async Task SetupInstanceInfo(ProfileCallTreeNode node) { var callTree = Session.ProfileData.CallTree; var groupNode = node as ProfileCallTreeGroupNode; // Collect all instances associated with the node's function. // With multiple nodes selected, the node is a ProfileCallTreeGroupNode, // combine the instances of all functions in the group to get the list. if (groupNode != null) { instanceNodes_ = await Task.Run(() => { // For a node group, combine the instances for each node. var instanceNodes = new List(); var handledFuncts = new HashSet(); foreach (var n in groupNode.Nodes) { if (handledFuncts.Add(n.Function)) { instanceNodes.AddRange(callTree.GetSortedCallTreeNodes(n.Function)); } } return instanceNodes; }); } else { instanceNodes_ = callTree.GetSortedCallTreeNodes(node.Function); } if (instanceNodes_.Count == 0) { ShowInstanceNavigation = false; return; } // Create the node that sums up all selected nodes. ProfileCallTreeNode combinedNode = null; if (groupNode != null) { // With multiple nodes selected, the node is a ProfileCallTreeGroupNode, // the instances of all functions in the group are already combined. combinedNode = groupNode; } else { combinedNode = await Task.Run(() => callTree.GetCombinedCallTreeNode(node.Function)); } InstancesNode = SetupNodeExtension(combinedNode, Session); FunctionInstancesCount = instanceNodes_.Count; // Show all instances. InstancesList.ShowFunctions(instanceNodes_); ShowInstanceNavigation = instanceNodes_.Count > 1; EnableSingleNodeActions = groupNode == null; // Setup instance navigation controls. if (groupNode == null) { nodeInstanceIndex_ = instanceNodes_.FindIndex(instanceNode => instanceNode == node); } else { nodeInstanceIndex_ = 0; } CurrentInstanceIndex = nodeInstanceIndex_ + 1; // Show average time. var averageNode = instanceNodes_[0].Clone(); averageNode.Weight = combinedNode.Weight / instanceNodes_.Count; averageNode.ExclusiveWeight = combinedNode.ExclusiveWeight / instanceNodes_.Count; var averageNodeEx = SetupNodeExtension(averageNode, Session); averageNodeEx.Percentage = Session.ProfileData.ScaleFunctionWeight(averageNodeEx.Weight); averageNodeEx.ExclusivePercentage = Session.ProfileData.ScaleFunctionWeight(averageNodeEx.ExclusiveWeight); AverageNode = averageNodeEx; // Show median time. var medianNode = instanceNodes_[instanceNodes_.Count / 2]; var medianNodeEx = SetupNodeExtension(medianNode, Session); medianNodeEx.Percentage = Session.ProfileData.ScaleFunctionWeight(medianNodeEx.Weight); medianNodeEx.ExclusivePercentage = Session.ProfileData.ScaleFunctionWeight(medianNodeEx.ExclusiveWeight); MedianNode = medianNodeEx; SetupThreadList(node); InstancesExpander.IsExpanded = settings_.ExpandInstances; HistogramExpander.IsExpanded = settings_.ExpandHistogram; ThreadsExpander.IsExpanded = settings_.ExpandThreads; if (settings_.ExpandHistogram) { InvokeSetupInstancesHistogram(); } } private void SetupThreadList(ProfileCallTreeNode node) { var threadList = node.SortedByWeightPerThreadWeights; var itemsList = new List(); foreach (var item in threadList) { var threadInfo = Session.ProfileData.FindThread(item.ThreadId); var backColor = App.Settings.TimelineSettings. GetThreadBackgroundColors(threadInfo, item.ThreadId).Margin; // Compute thread percentage relative to selected node instance. double threadPercentage = node.Weight.Ticks > 0 ? (double)item.Values.Weight.Ticks / node.Weight.Ticks : 0; double selfThreadPercentage = node.ExclusiveWeight.Ticks > 0 ? (double)item.Values.ExclusiveWeight.Ticks / node.ExclusiveWeight.Ticks : 0; itemsList.Add(new ThreadListItem() { ThreadId = item.ThreadId, Title = $"{item.ThreadId}", ToolTip = threadInfo != null ? threadInfo.Name : null, WeightToolTip = $"{threadPercentage.AsPercentageString()} of instance time\n" + $"{selfThreadPercentage.AsPercentageString()} of instance self time", Background = backColor, Weight = item.Values.Weight, ExclusiveWeight = item.Values.ExclusiveWeight, Percentage = Session.ProfileData.ScaleFunctionWeight(item.Values.Weight), ExclusivePercentage = Session.ProfileData.ScaleFunctionWeight(item.Values.ExclusiveWeight) }); } ThreadList.ItemsSource = itemsList; } private void SetupInstancesHistogram(List nodes, ProfileCallTreeNode currentNode, bool useSelfTime) { if (useSelfTime) { SetupInstancesHistogramImpl(nodes, currentNode, node => node.ExclusiveWeight); } else { SetupInstancesHistogramImpl(nodes, currentNode, node => node.Weight); } } private void SetupInstancesHistogramImpl(List nodes, ProfileCallTreeNode currentNode, Func selectWeight) { nodes = new List(nodes); nodes.Sort((a, b) => selectWeight(a).CompareTo(selectWeight(b))); const double maxBinCount = 20; var maxWeight = selectWeight(nodes[^1]); var minWeight = selectWeight(nodes[0]); var delta = maxWeight - minWeight; long weightPerBin = (long)Math.Ceiling(delta.Ticks / maxBinCount); double maxHeight = InstanceHistogramHost.ActualHeight; // Partition nodes into bins. var bins = new List<(TimeSpan Weight, TimeSpan TotalWeight, int StartIndex, int Count)>(); var binWeight = selectWeight(nodes[0]); var binTotalWeight = binWeight; int binStartIndex = 0; int binCount = 1; for (int i = 1; i < nodes.Count; i++) { var node = nodes[i]; if ((selectWeight(node) - binWeight).Ticks > weightPerBin) { bins.Add((binWeight, binTotalWeight, binStartIndex, binCount)); binWeight = selectWeight(node); binTotalWeight = binWeight; binStartIndex = i; binCount = 1; } else { binTotalWeight += selectWeight(node); binCount++; } } bins.Add((binWeight, binTotalWeight, binStartIndex, binCount)); // Add each bin to the graph. var model = new PlotModel(); var series = new HistogramSeries(); series.FillColor = OxyColors.WhiteSmoke; series.StrokeThickness = 0.5; OxyColor ColorFromArgb(Color color) { return OxyColor.FromArgb(color.A, color.R, color.G, color.B); } foreach (var bin in bins) { if (bin.Count == 0) { continue; } long start = bin.Weight.Ticks; long end = (bin.Weight + TimeSpan.FromTicks(weightPerBin)).Ticks; var barColor = ColorFromArgb(settings_.HistogramBarColor); var item = new BinHistogramItem(start, end, bin.Count, bin.Count, barColor) { Count = bin.Count, TotalWeight = bin.TotalWeight, AverageWeight = TimeSpan.FromTicks(bin.TotalWeight.Ticks / bin.Count), Nodes = nodes.GetRange(bin.StartIndex, bin.Count) }; series.Items.Add(item); } series.LabelFormatString = "{3}"; series.LabelMargin = 2; series.MouseDown += (sender, e) => { if (e.HitTestResult.Item is BinHistogramItem binItem) { NodesSelected?.Invoke(this, binItem.Nodes); } }; model.Series.Add(series); // Setup horizontal axis. var weightAxis = new LinearAxis(); weightAxis.Position = AxisPosition.Bottom; weightAxis.TickStyle = TickStyle.None; if (delta.TotalSeconds <= 1) { weightAxis.LabelFormatter = value => TimeSpan.FromTicks((long)value).AsMillisecondsString(); } else { weightAxis.LabelFormatter = value => TimeSpan.FromTicks((long)value).AsSecondsString(); } weightAxis.MinimumPadding = 0; weightAxis.MinimumDataMargin = 6; weightAxis.IsPanEnabled = false; weightAxis.IsZoomEnabled = false; model.Axes.Add(weightAxis); // Setup vertical axis. var countAxis = new LinearAxis(); countAxis.Position = AxisPosition.Right; countAxis.TickStyle = TickStyle.None; countAxis.Title = "Instances"; countAxis.StringFormat = " "; countAxis.IsPanEnabled = false; countAxis.IsZoomEnabled = false; countAxis.MinimumPadding = 0; countAxis.MaximumDataMargin = 20; model.Axes.Add(countAxis); // Add line for current instance. void AddLineAnnotation(double value, OxyColor color, LineStyle lineStyle) { var line = new LineAnnotation(); line.Type = LineAnnotationType.Vertical; line.X = value; line.StrokeThickness = 2; line.Color = color; line.LineStyle = lineStyle; model.Annotations.Add(line); } void AddPointAnnotation(double value, OxyColor color) { var point = new PointAnnotation(); point.Shape = MarkerType.Diamond; point.X = value; point.Fill = color; model.Annotations.Add(point); } AddPointAnnotation(currentNode.Weight.Ticks, ColorFromArgb(settings_.HistogramCurrentColor)); // Add lines for median and average time. double average = nodes.Average(node => node.Weight.Ticks); AddLineAnnotation(average, ColorFromArgb(settings_.HistogramAverageColor), LineStyle.Dot); long median = nodes[nodes.Count / 2].Weight.Ticks; AddLineAnnotation(median, ColorFromArgb(settings_.HistogramMedianColor), LineStyle.Dot); var plotView = new PlotView(); plotView.Model = model; model.IsLegendVisible = false; plotView.VerticalContentAlignment = VerticalAlignment.Center; plotView.Width = InstanceHistogramHost.ActualWidth; plotView.Height = InstanceHistogramHost.ActualHeight; plotView.MinHeight = plotView.Height; model.PlotAreaBorderThickness = new OxyThickness(0, 0, 0, 0.5); plotView.Background = InstanceHistogramHost.Background; // Override tooltip. plotView.Controller = new PlotController(); plotView.Controller.UnbindMouseDown(OxyMouseButton.Left); plotView.Controller.BindMouseEnter(PlotCommands.HoverSnapTrack); object tooltipTemplate = Application.Current.FindResource("HistogramTooltipTemplate"); plotView.DefaultTrackerTemplate = (ControlTemplate)tooltipTemplate; InstanceHistogramHost.Children.Clear(); InstanceHistogramHost.Children.Add(plotView); histogramVisible_ = true; } public static ProfileCallTreeNodeEx SetupNodeExtension(ProfileCallTreeNode node, IUISession session) { if (node == null) { return null; } var nameProvider = session.CompilerInfo.NameProvider; var moduleMap = new Dictionary(); var functionMap = new Dictionary(); var fullFunctionMap = new Dictionary(); string moduleNames = null; string functionNames = null; string fullFunctionNames = null; if (node is ProfileCallTreeGroupNode groupNode) { foreach (var n in groupNode.Nodes) { moduleMap.AccumulateValue(n.FormatModuleName(nameProvider.FormatFunctionName, MaxModuleNameLength), 1); functionMap.AccumulateValue(n.FormatFunctionName(nameProvider.FormatFunctionName, MaxFunctionNameLength), 1); fullFunctionMap.AccumulateValue(n.FormatFunctionName(nameProvider.FormatFunctionName), 1); } moduleNames = GenerateNameListText(moduleMap, "\n"); functionNames = GenerateNameListText(functionMap, "\n"); fullFunctionNames = GenerateNameListText(fullFunctionMap, "\n"); } else { moduleNames = node.FormatModuleName(nameProvider.FormatFunctionName, MaxModuleNameLength); functionNames = node.FormatFunctionName(nameProvider.FormatFunctionName, MaxFunctionNameLength); fullFunctionNames = node.FormatFunctionName(nameProvider.FormatFunctionName); } var nodeEx = new ProfileCallTreeNodeEx(node) { FullFunctionName = fullFunctionNames, FunctionName = functionNames, ModuleName = moduleNames, Percentage = session.ProfileData.ScaleFunctionWeight(node.Weight), ExclusivePercentage = session.ProfileData.ScaleFunctionWeight(node.ExclusiveWeight) }; return nodeEx; } private static string GenerateNameListText(Dictionary nameMap, string separator) { var nameList = nameMap.ToList(); nameList.Sort((a, b) => string.Compare(a.Item1, b.Item1, StringComparison.Ordinal)); var sb = new StringBuilder(); foreach (var pair in nameList) { if (pair.Item2 > 1) { sb.Append($"{pair.Item2} x {pair.Item1}{separator}"); } else { sb.Append($"{pair.Item1}{separator}"); } } return sb.ToString().Trim(); } private async void PreviousInstanceButton_Click(object sender, RoutedEventArgs e) { if (nodeInstanceIndex_ > 0) { int index = Utils.IsKeyboardModifierActive() ? 0 : nodeInstanceIndex_ - 1; var node = instanceNodes_[index]; NodeInstanceChanged?.Invoke(this, node); await ShowWithDetailsAsync(node); } } private async void NextInstanceButton_Click(object sender, RoutedEventArgs e) { if (nodeInstanceIndex_ < FunctionInstancesCount - 1) { int index = Utils.IsKeyboardModifierActive() ? FunctionInstancesCount - 1 : nodeInstanceIndex_ + 1; var node = instanceNodes_[index]; NodeInstanceChanged?.Invoke(this, node); await ShowWithDetailsAsync(node); } } private void HistogramHost_Expanded(object sender, RoutedEventArgs e) { if (!histogramVisible_ && instanceNodes_ != null) { InvokeSetupInstancesHistogram(); } } private void InvokeSetupInstancesHistogram() { // Create the histogram on the next render pass, // after the host has been expanded, otherwise some computations assert. Dispatcher.BeginInvoke(() => { if (instanceNodes_ != null) { SetupInstancesHistogram(instanceNodes_, CallTreeNode.CallTreeNode, useSelfTimeHistogram_); } }, DispatcherPriority.Render); } public void Reset() { Utils.DisableControl(this); } private async void ThreadListItem_MouseDown(object sender, MouseButtonEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && e.ClickCount >= 2) { var threadItem = ((FrameworkElement)sender).DataContext as ThreadListItem; await ApplyThreadFilterAction(threadItem, ThreadActivityAction.FilterToThread); } } private async Task ApplyThreadFilterAction(ThreadListItem threadItem, ThreadActivityAction action) { if (Session.FindPanel(ToolPanelKind.Timeline) is TimelinePanel timelinePanel && threadItem != null) { await timelinePanel.ApplyThreadFilterAction(threadItem.ThreadId, action); } } private void ThreadContextMenuButton_Click(object sender, RoutedEventArgs e) { Utils.ShowContextMenu(sender as FrameworkElement, this); } private async Task OpenFunction(object obj, OpenSectionKind openMode) { if (((FrameworkElement)obj).DataContext is ThreadListItem threadItem && instancesNode_.CallTreeNode != null) { var filter = new ProfileSampleFilter(threadItem.ThreadId); await Session.OpenProfileFunction(instancesNode_.CallTreeNode, openMode, filter); } } private void CopyModuleButton_OnClick(object sender, RoutedEventArgs e) { Clipboard.SetText(instancesNode_.ModuleName); } private void CopyFUnctionButton_OnClick(object sender, RoutedEventArgs e) { Clipboard.SetText(instancesNode_.FullFunctionName); } private async void PreviewButton_OnClick(object sender, RoutedEventArgs e) { await IRDocumentPopupInstance.ShowPreviewPopup(instancesNode_.CallTreeNode.Function, "", ThreadsExpander, Session); } private async void OpenButton_OnClick(object sender, RoutedEventArgs e) { await Session.OpenProfileFunction(instancesNode_.CallTreeNode, OpenSectionKind.NewTab); } private void MarkModuleButton_OnClick(object sender, RoutedEventArgs e) { Utils.ShowContextMenu(sender as FrameworkElement, this); } private void MarkModule(string module, Color color) { var markingSettings = App.Settings.MarkingSettings; markingSettings.UseModuleColors = true; markingSettings.AddModuleColor(module, color); MarkingChanged?.Invoke(this, EventArgs.Empty); } private void MarkFunction(string function, Color color) { var markingSettings = App.Settings.MarkingSettings; markingSettings.UseFunctionColors = true; markingSettings.AddFunctionColor(function, color); MarkingChanged?.Invoke(this, EventArgs.Empty); } public class BinHistogramItem : HistogramItem { public BinHistogramItem(double rangeStart, double rangeEnd, double area, int count) : base( rangeStart, rangeEnd, area, count) { } public BinHistogramItem(double rangeStart, double rangeEnd, double area, int count, OxyColor color) : base( rangeStart, rangeEnd, area, count, color) { } public new int Count { get; set; } public TimeSpan AverageWeight { get; set; } public TimeSpan TotalWeight { get; set; } public List Nodes { get; set; } } } ================================================ FILE: src/ProfileExplorerUI/Profile/CallTreeNodePopup.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/CallTreeNodePopup.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.UI.Controls; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.UI.Profile; public partial class CallTreeNodePopup : DraggablePopup, INotifyPropertyChanged { internal const double DefaultTextSize = 12; private const int MaxPreviewNameLength = 80; private const double InitialWidth = 450; private const double InitialHeight = 400; private const double MaxPopupWidth = 800; private const double MinPopupWidth = 300; private Typeface defaultTextFont_; private bool showResizeGrip_; private bool canExpand_; private bool showBacktraceView_; private ProfileCallTreeNodeEx nodeEx_; private string title_; private string titleTooltipText_; private string descriptionText_; public CallTreeNodePopup(ProfileCallTreeNode node, IFunctionProfileInfoProvider funcInfoProvider, Point position, UIElement referenceElement, IUISession session, bool canExpand = true) { InitializeComponent(); Initialize(position, referenceElement); PanelResizeGrip.ResizedControl = this; //? TODO: Use GetTextTypeface everywhere instead of hardcoding fonts defaultTextFont_ = Utils.GetTextTypeface(TitleTextBlock); Session = session; CanExpand = canExpand; PanelHost.ShowInstanceNavigation = false; PanelHost.Settings = App.Settings.CallTreeNodeSettings; PanelHost.Initialize(session, funcInfoProvider); FunctionListView.Session = Session; FunctionListView.Settings = App.Settings.CallTreeNodeSettings; UpdateNode(node); SetupEvents(); DataContext = this; } public double WindowScaling => App.Settings.GeneralSettings.WindowScaling; public IUISession Session { get; set; } public ProfileCallTreeNodeEx CallTreeNode { get => nodeEx_; set { SetField(ref nodeEx_, value); OnPropertyChanged(nameof(TitleText)); OnPropertyChanged(nameof(TitleTooltipText)); OnPropertyChanged(nameof(DescriptionText)); } } public bool ShowResizeGrip { get => showResizeGrip_; set => SetField(ref showResizeGrip_, value); } public bool CanExpand { get => canExpand_; set => SetField(ref canExpand_, value); } public bool ShowSimpleView { get => showBacktraceView_; set => SetField(ref showBacktraceView_, value); } public string TitleText { get => CallTreeNode != null ? CallTreeNode.FunctionName : title_; set => SetField(ref title_, value); } public string TitleTooltipText { get => CallTreeNode != null ? CallTreeNode.FullFunctionName : titleTooltipText_; set => SetField(ref titleTooltipText_, value); } public string DescriptionText { get => CallTreeNode != null ? CallTreeNode.ModuleName : descriptionText_; set { SetField(ref descriptionText_, value); OnPropertyChanged(nameof(HasDescriptionText)); } } public bool HasDescriptionText => !string.IsNullOrEmpty(DescriptionText); public event PropertyChangedEventHandler PropertyChanged; private void SetupEvents() { FunctionListView.NodeClick += async (sender, treeNode) => { await Session.ProfileFunctionSelected(treeNode, ToolPanelKind.Other); }; FunctionListView.NodeDoubleClick += async (sender, treeNode) => { var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await Session.OpenProfileFunction(treeNode, mode); }; PanelHost.MarkingChanged += (sender, args) => UpdateMarkingUI(); FunctionListView.MarkingChanged += (sender, args) => UpdateMarkingUI(); } private void UpdateMarkingUI() { Session.FunctionMarkingChanged(ToolPanelKind.Other); } protected override void SetPanelAccentColor(Color color) { ToolbarPanel.Background = ColorBrushes.GetBrush(color); PanelBorder.BorderBrush = ColorBrushes.GetBrush(color); } public void ShowBackTrace(ProfileCallTreeNode node, int maxLevel, FunctionNameFormatter nameFormatter) { UpdateNode(node); // Set title. var list = new List(); while (node != null && maxLevel-- > 0) { list.Add(node); node = node.Caller; } ShowSimpleView = true; UpdatePopupWidth(MeasureMaxTextWidth(list, nameFormatter)); FunctionListView.ShowSimpleList(list); } public void ShowFunctions(List list, FunctionNameFormatter nameFormatter) { ShowSimpleView = true; UpdatePopupWidth(MeasureMaxTextWidth(list, nameFormatter)); FunctionListView.ShowSimpleList(list); } public void UpdateNode(ProfileCallTreeNode node) { CallTreeNode = CallTreeNodePanel.SetupNodeExtension(node, Session); if (!ShowSimpleView) { PanelHost.Show(CallTreeNode); } } public override bool ShouldStartDragging(MouseButtonEventArgs e) { base.ShouldStartDragging(e); if (e.LeftButton == MouseButtonState.Pressed && ToolbarPanel.IsMouseOver) { if (!IsDetached) { DetachPopup(); } return true; } return false; } public override async void DetachPopup() { base.DetachPopup(); await ExpandDetailsPanel(); } protected override void OnClosed(EventArgs e) { base.OnClosed(e); PanelHost.SaveListColumnSettings(); } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private double MeasureMaxTextWidth(List list, FunctionNameFormatter nameFormatter) { double maxTextWidth = 0; foreach (var node in list) { string funcName = node.FormatFunctionName(nameFormatter, MaxPreviewNameLength); var textSize = Utils.MeasureString(funcName, defaultTextFont_, DefaultTextSize); maxTextWidth = Math.Max(maxTextWidth, textSize.Width); } return maxTextWidth; } private void UpdatePopupWidth(double maxTextWidth) { double margin = SystemParameters.VerticalScrollBarWidth; Width = Math.Max(MinPopupWidth, Math.Min(maxTextWidth, MaxPopupWidth)); // Leave some space for the vertical scroll bar // to avoid having a horizontal one by default. FunctionListView.FunctionColumnWidth = Math.Max(MinPopupWidth - 2 * margin, Width - 2 * margin); } private void CloseButton_Click(object sender, RoutedEventArgs e) { Session.UnregisterDetachedPanel(this); ClosePopup(); } private void ExpandButton_OnClick(object sender, RoutedEventArgs e) { DetachPopup(); } private async Task ExpandDetailsPanel() { if (!ShowSimpleView) { await PanelHost.ShowDetailsAsync(); } MinWidth = InitialWidth; Width = Math.Max(Width, InitialWidth); Height = Math.Max(Height, InitialHeight); ShowResizeGrip = true; CanExpand = false; } public void UpdateMarkedFunctions() { FunctionListView.UpdateMarkedFunctions(); PanelHost.UpdateMarkedFunctions(); } } ================================================ FILE: src/ProfileExplorerUI/Profile/CallTreePanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/CallTreePanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using Aga.Controls.Tree; using ProfileExplorer.Core; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Panels; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.UI.Profile; public enum CallTreeListItemKind { Root, ChildrenPlaceholder, CallerNode, CalleeNode, CallTreeNode, Header } //? TODO: Replace all with RelayCommand pattern. public static class CallTreeCommand { public static readonly RoutedCommand ExpandHottestCallPath = new("ExpandHottestCallPath", typeof(FrameworkElement)); public static readonly RoutedCommand ExpandCallPath = new("ExpandCallPath", typeof(FrameworkElement)); public static readonly RoutedCommand CollapseCallPath = new("CollapseCallPath", typeof(FrameworkElement)); public static readonly RoutedCommand SelectFunction = new("SelectFunction", typeof(FrameworkElement)); public static readonly RoutedCommand OpenFunction = new("OpenFunction", typeof(FrameworkElement)); public static readonly RoutedCommand OpenFunctionInNewTab = new("OpenFunctionInNewTab", typeof(FrameworkElement)); public static readonly RoutedCommand FocusSearch = new("FocusSearch", typeof(FrameworkElement)); public static readonly RoutedCommand ClearSearch = new("ClearSearch", typeof(FrameworkElement)); public static readonly RoutedCommand PreviousSearchResult = new("PreviousSearchResult", typeof(FrameworkElement)); public static readonly RoutedCommand NextSearchResult = new("NextSearchResult", typeof(FrameworkElement)); public static readonly RoutedCommand GoBack = new("GoBack", typeof(FrameworkElement)); public static readonly RoutedCommand CollapseNodes = new("CollapseNodes", typeof(FrameworkElement)); // FlameGraph specific commands. public static readonly RoutedCommand EnlargeNode = new("EnlargeNode", typeof(FrameworkElement)); public static readonly RoutedCommand ChangeRootNode = new("ChangeRootNode", typeof(FrameworkElement)); public static readonly RoutedCommand MarkAllInstances = new("MarkAllInstances", typeof(FrameworkElement)); public static readonly RoutedCommand MarkInstance = new("MarkInstance", typeof(FrameworkElement)); public static readonly RoutedCommand ClearMarkedNodes = new("ClearMarkedNodes", typeof(FrameworkElement)); // Timeline specific commands. public static readonly RoutedCommand RemoveFilters = new("RemoveFilters", typeof(FrameworkElement)); public static readonly RoutedCommand RemoveThreadFilters = new("RemoveThreadFilters", typeof(FrameworkElement)); public static readonly RoutedCommand RemoveAllFilters = new("RemoveAllFilters", typeof(FrameworkElement)); } public class CallTreeListItem : SearchableProfileItem, ITreeModel { private string cacheFunctionName_; private Brush functionBackColor_; private Brush moduleBackColor_; public CallTreeListItem(CallTreeListItemKind kind, CallTreePanel owner, FunctionNameFormatter funcNameFormatter = null) : base(funcNameFormatter) { Children = new List(); Kind = kind; Owner = owner; } public CallTreePanel Owner { get; set; } public IRTextFunction Function { get; set; } public ProfileCallTreeNode CallTreeNode { get; set; } public Brush TextColor { get; set; } public Brush BackColor { get; set; } public Brush BackColor2 { get; set; } public Brush FunctionBackColor { get => functionBackColor_; set => SetAndNotify(ref functionBackColor_, value); } public Brush ModuleBackColor { get => moduleBackColor_; set => SetAndNotify(ref moduleBackColor_, value); } public CallTreeListItem Parent { get; set; } public List Children { get; set; } public long Time { get; set; } public CallTreeListItemKind Kind { get; set; } public bool HasCallTreeNode => CallTreeNode?.Function != null; public override TimeSpan Weight => HasCallTreeNode ? CallTreeNode.Weight : TimeSpan.Zero; public override TimeSpan ExclusiveWeight => HasCallTreeNode ? CallTreeNode.ExclusiveWeight : TimeSpan.Zero; public override string ModuleName => CallTreeNode is {HasFunction: true} ? CallTreeNode.ModuleName : null; public bool HasAnyChildren => Children is {Count: > 0}; public override string FunctionName { get { string name = base.FunctionName; if (Kind != CallTreeListItemKind.Header) { if (cacheFunctionName_ == null) { cacheFunctionName_ = $"{name} ({Percentage.AsPercentageString()})"; } return cacheFunctionName_; } return name; } set => base.FunctionName = value; } public TreeNode TreeNode { get; set; } // Associated UI tree node. public IEnumerable GetChildren(object node) { if (node == null) { return Children; } var parentNode = (CallTreeListItem)node; return parentNode.Children; } public bool HasChildren(object node) { if (node == null) return false; var parentNode = (CallTreeListItem)node; return parentNode.Children != null && parentNode.Children.Count > 0; } public void AddChild(CallTreeListItem child) { Children ??= new List(); Children.Add(child); } public void ClearChildren() { Children = null; } protected override string GetFunctionName() { return CallTreeNode is {HasFunction: true} ? CallTreeNode.FunctionName : null; } protected override bool ShouldPrependModule() { return Kind != CallTreeListItemKind.Header && Owner.Settings.PrependModuleToFunction; } } public partial class CallTreePanel : ToolPanelControl, IFunctionProfileInfoProvider, INotifyPropertyChanged { public static readonly DependencyProperty ShowToolbarProperty = DependencyProperty.Register("ShowToolbar", typeof(bool), typeof(CallTreePanel)); private IRTextFunction function_; private PopupHoverPreview nodeHoverPreview_; private ProfileCallTree callTree_; private CallTreeListItem callTreeEx_; private List searchResultNodes_; private int searchResultIndex_; private CallTreeSettings settings_; private CancelableTaskInstance searchTask_; private Stack stateStack_; private Dictionary callTreeNodeToNodeExMap_; private bool ignoreNextSelectionEvent_; private bool showSearchSection_; private string searchResultText_; private OptionsPanelHostPopup optionsPanelPopup_; private CancelableTaskInstance loadTask_; private double profileDurationReciprocal_; public CallTreePanel() { InitializeComponent(); Settings = PanelKind == ToolPanelKind.CallTree ? App.Settings.CallTreeSettings : App.Settings.CallerCalleeSettings; searchTask_ = new CancelableTaskInstance(false); callTreeNodeToNodeExMap_ = new Dictionary(); stateStack_ = new Stack(); loadTask_ = new CancelableTaskInstance(false); DataContext = this; SetupEvents(); } public CallTreeSettings Settings { get => settings_; set { settings_ = value; settings_.TreeListColumns.RestoreColumnsState(CallTreeList); SetupPreviewPopup(); OnPropertyChanged(); } } public FunctionMarkingSettings MarkingSettings => App.Settings.MarkingSettings; //? TODO: Replace all other commands with RelayCommand. public RelayCommand SelectFunctionCallTreeCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.CallTree); }); public RelayCommand SelectFunctionFlameGraphCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.FlameGraph); }); public RelayCommand SelectFunctionTimelineCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.Timeline); }); public RelayCommand SelectFunctionSourceCommand => new(async obj => { await SelectFunctionInPanel(obj, ToolPanelKind.Source); }); public RelayCommand CopyFunctionNameCommand => new(async obj => { if (CallTreeList.SelectedItem is TreeNode node && node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { string text = Session.CompilerInfo.NameProvider.GetFunctionName(item.Function); Clipboard.SetText(text); } }); public RelayCommand CopyDemangledFunctionNameCommand => new(async obj => { if (CallTreeList.SelectedItem is TreeNode node && node.Tag is CallTreeListItem item) { var options = FunctionNameDemanglingOptions.Default; string text = Session.CompilerInfo.NameProvider.DemangleFunctionName(item.Function, options); Clipboard.SetText(text); } }); public RelayCommand CopyFunctionDetailsCommand => new(async obj => { if (CallTreeList.SelectedItems.Count > 0) { var funcList = new List(); foreach (TreeNode node in CallTreeList.SelectedItems) { if (node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { funcList.Add(item); } } SearchableProfileItem.CopyFunctionListAsHtml(funcList); } }); public RelayCommand PreviewFunctionCommand => new(async obj => { if (CallTreeList.SelectedItem is TreeNode node && node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { var brush = GetMarkedNodeColor(item); await IRDocumentPopupInstance.ShowPreviewPopup(item.Function, "", CallTreeList, Session, null, false, brush); } }); public RelayCommand PreviewFunctionInstanceCommand => new(async obj => { if (CallTreeList.SelectedItem is TreeNode node && node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { var filter = new ProfileSampleFilter(item.CallTreeNode); var brush = GetMarkedNodeColor(item); await IRDocumentPopupInstance.ShowPreviewPopup(item.Function, "", CallTreeList, Session, filter, false, brush); } }); public RelayCommand OpenInstanceCommand => new(async obj => { if (CallTreeList.SelectedItem is TreeNode node) { if (node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await OpenFunctionInstance(item, mode); } } }); public RelayCommand OpenInstanceInNewTabCommand => new(async obj => { if (CallTreeList.SelectedItem is TreeNode node) { if (node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { await OpenFunctionInstance(item, OpenSectionKind.NewTab); } } }); public ProfileCallTree CallTree { get => callTree_; set { SetField(ref callTree_, value); if (Session?.ProfileData == null) { return; } profileDurationReciprocal_ = 1.0 / Session.ProfileData.ProfileWeight.Ticks; OnPropertyChanged(nameof(HasCallTree)); } } public bool IsCallerCalleePanel => PanelKind == ToolPanelKind.CallerCallee; public bool HasCallTree => callTree_ != null; public bool ShowSearchSection { get => showSearchSection_; set { if (showSearchSection_ != value) { showSearchSection_ = value; OnPropertyChanged(); } } } public string SearchResultText { get => searchResultText_; set { if (searchResultText_ != value) { searchResultText_ = value; OnPropertyChanged(); } } } public bool HasPreviousState => stateStack_.Count > 0; public RelayCommand MarkModuleCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; MarkSelectedNodes(obj, (node, color) => { if (node.HasCallTreeNode) { markingSettings.AddModuleColor(node.ModuleName, color); } }); markingSettings.UseModuleColors = true; await UpdateMarkedFunctions(); }); public RelayCommand MarkFunctionCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; MarkSelectedNodes(obj, (node, color) => { if (node.HasCallTreeNode) { markingSettings.AddFunctionColor(node.FunctionName, color); } }); markingSettings.UseFunctionColors = true; await UpdateMarkedFunctions(); }); public List GetBacktrace(ProfileCallTreeNode node) { return callTree_.GetBacktrace(node); } public (List, List Modules) GetTopFunctionsAndModules( ProfileCallTreeNode node) { return callTree_.GetTopFunctionsAndModules(node); } public event PropertyChangedEventHandler PropertyChanged; private Brush GetMarkedNodeColor(CallTreeListItem node) { return App.Settings.MarkingSettings. GetMarkedNodeBrush(node.FunctionName, node.ModuleName); } private async Task UpdateCallTree() { callTreeEx_ = null; if (IsCallerCalleePanel) { await DisplayProfileCallerCalleeTree(function_); } else { await DisplayProfileCallTree(); } } private static void SortCallTreeNodes(CallTreeListItem node) { // Sort children in descending order, // since that is not yet supported by the TreeListView control. if (!node.HasAnyChildren) { return; } node.Children.Sort((a, b) => { int result = b.Time.CompareTo(a.Time); return result != 0 ? result : string.Compare(a.FunctionName, b.FunctionName, StringComparison.Ordinal); }); } private static void ExpandPathToNode(CallTreeListItem nodeEx, bool markPathNodes) { // Expansion must be done starting from the root node, // because the TreeNode is created on-demand by the control // when a node is expanded, so walk parents recursively. if (nodeEx.Parent != null) { ExpandPathToNode(nodeEx.Parent, markPathNodes); } if (nodeEx.TreeNode != null) { nodeEx.TreeNode.IsExpanded = true; nodeEx.IsMarked = markPathNodes; } } public async Task DisplayProfileCallTree() { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (callTreeEx_ != null) { Reset(); } CallTree = Session.ProfileData.CallTree; callTreeEx_ = await Task.Run(() => CreateProfileCallTree()); CallTreeList.Model = callTreeEx_; await UpdateMarkedFunctionsNoLock(true); if (settings_.ExpandHottestPath) { ExpandHottestFunctionPath(); } } public async Task DisplayProfileCallerCalleeTree(IRTextFunction function) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); function_ = function; ignoreNextSelectionEvent_ = true; // Prevent deselection even to be triggered. CallTree = Session.ProfileData.CallTree; callTreeEx_ = await Task.Run(() => CreateProfileCallerCalleeTree(function)); CallTreeList.Model = callTreeEx_; await UpdateMarkedFunctionsNoLock(true); ExpandCallTreeTop(); ignoreNextSelectionEvent_ = false; } public void Reset() { CallTreeList.Model = null; function_ = null; CallTree = null; callTreeEx_ = null; callTreeNodeToNodeExMap_.Clear(); stateStack_.Clear(); OnPropertyChanged(nameof(HasPreviousState)); } public void SelectFunction(IRTextFunction function) { var nodeList = callTree_.GetSortedCallTreeNodes(function); if (nodeList != null && nodeList.Count > 0) { SelectFunction(nodeList[0], false); } } public void SelectFunction(ProfileCallTreeNode node, bool markPath = true) { if (node is ProfileCallTreeGroupNode nodeGroup) { foreach (var groupNode in nodeGroup.Nodes) { SelectFunction(groupNode, markPath); return; //? TODO: Should it select everything instead? } } if (!callTreeNodeToNodeExMap_.TryGetValue(node, out var nodeEx)) { return; } ExpandPathToNode(nodeEx, markPath); BringIntoView(nodeEx); if (CallTreeList.SelectedItem != nodeEx.TreeNode) { ignoreNextSelectionEvent_ = true; CallTreeList.SelectedItem = nodeEx.TreeNode; } } protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private async Task SelectFunctionInPanel(object target, ToolPanelKind panelKind) { if (target is TreeNode node) { var item = node.Tag as CallTreeListItem; if (item?.CallTreeNode != null) { await Session.SelectProfileFunctionInPanel(item.CallTreeNode, panelKind); } } } private void SetupEvents() { CallTreeList.NodeExpanded += CallTreeOnNodeExpanded; PreviewMouseDown += OnPreviewMouseDown; SetupPreviewPopup(); } private async void OnPreviewMouseDown(object sender, MouseButtonEventArgs e) { if (IsCallerCalleePanel && e.ChangedButton == MouseButton.XButton1) { e.Handled = true; await RestorePreviousState(); return; } } private void SetupPreviewPopup() { if (nodeHoverPreview_ != null) { nodeHoverPreview_.Unregister(); nodeHoverPreview_ = null; } if (!settings_.ShowNodePopup) { return; } nodeHoverPreview_ = new PopupHoverPreview(CallTreeList, TimeSpan.FromMilliseconds(settings_.NodePopupDuration), (mousePoint, previewPoint) => { var element = (UIElement)CallTreeList.GetObjectAtPoint( mousePoint); if (element is not TreeListItem treeItem) { return null; } var funcNode = treeItem.Node?.Tag as CallTreeListItem; var callNode = funcNode?.CallTreeNode; if (callNode is {HasFunction: true}) { // If popup already opened for this node reuse the instance. if (nodeHoverPreview_.PreviewPopup is CallTreeNodePopup popup) { popup.UpdatePosition(previewPoint, CallTreeList); popup.UpdateNode(callNode); return popup; } return new CallTreeNodePopup( callNode, this, previewPoint, CallTreeList, Session); } return null; }, (mousePoint, popup) => true, popup => { if (popup.IsDetached) { Session.RegisterDetachedPanel(popup); } }); } private void CallTreeOnNodeExpanded(object sender, TreeNode node) { if (node.Tag is not CallTreeListItem funcNode) { return; } // If children not populated yet, there is a single dummy node. if (funcNode.HasAnyChildren && funcNode.Children.Count == 1 && funcNode.Children[0].Kind == CallTreeListItemKind.ChildrenPlaceholder) { var callNode = funcNode.CallTreeNode; var visitedNodes = new HashSet(); // Remove the dummy node and add the real children. // If the children have children on their own, new dummy nodes will be used. funcNode.ClearChildren(); CallTreeListItem firstNodeEx = null; if (funcNode.Kind == CallTreeListItemKind.CalleeNode && callNode.HasChildren) { foreach (var childNode in callNode.Children) { firstNodeEx ??= CreateProfileCallTree(childNode, funcNode, funcNode.Kind, visitedNodes); } } else if (funcNode.Kind == CallTreeListItemKind.CallerNode && callNode.HasCallers) { foreach (var childNode in callNode.Callers) { firstNodeEx = CreateProfileCallTree(childNode, funcNode, funcNode.Kind, visitedNodes); } } if (firstNodeEx != null) { BringIntoView(firstNodeEx); } } } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private Func PickPercentageFunction(TimeSpan totalWeight) { return weight => weight.Ticks / (double)totalWeight.Ticks; } private void BringIntoView(CallTreeListItem nodeEx) { if (nodeEx.TreeNode != null) { CallTreeList.ScrollIntoView(nodeEx.TreeNode); } } private List GetCallTreeNodes(IRTextFunction function, ProfileCallTree callTree) { if (settings_.CombineInstances) { var combinedNode = callTree.GetCombinedCallTreeNode(function); return combinedNode == null ? null : new List {combinedNode}; } return callTree.GetCallTreeNodes(function); } private ProfileCallTreeNode GetChildCallTreeNode(ProfileCallTreeNode childNode, ProfileCallTreeNode parentNode, ProfileCallTree callTree) { if (settings_.CombineInstances) { return callTree.GetCombinedCallTreeNode(childNode.Function, parentNode); } return childNode; } private CallTreeListItem CreateProfileCallerCalleeTree(IRTextFunction function) { var visitedNodes = new HashSet(); var rootNode = new CallTreeListItem(CallTreeListItemKind.Root, this); rootNode.Children = new List(); var nodeList = GetCallTreeNodes(function, callTree_); if (nodeList == null) { return null; } int index = 1; var combinedWeight = callTree_.GetCombinedCallTreeNodeWeight(function); foreach (var instance in nodeList) { bool isSelf = nodeList.Count == 1; string name = isSelf ? "Function" : $"Function instance {index++}"; string funcName = Session.CompilerInfo.NameProvider.FormatFunctionName(instance.Function); if (isSelf && !string.IsNullOrEmpty(funcName)) { name = funcName; } var percentageFunc = PickPercentageFunction(combinedWeight); var instanceNode = CreateProfileCallTreeInstance(name, instance, percentageFunc); if (isSelf) { instanceNode.Time = long.MaxValue; // Ensure Self is on top. } rootNode.AddChild(instanceNode); if (instance.HasCallers) { // Percentage relative to entire profile for callers. var callersNode = CreateProfileCallTreeHeader(CallTreeListItemKind.Header, "Callers", 2); if (nodeList.Count > 1) { instanceNode.AddChild(callersNode); } else { rootNode.AddChild(callersNode); } foreach (var callerNode in instance.Callers) { CreateProfileCallTree(callerNode, callersNode, instanceNode, CallTreeListItemKind.CallerNode, visitedNodes); } visitedNodes.Clear(); } if (instance.HasChildren) { // Percentage relative to current function callers. //percentageFunc = PickPercentageFunction(instance.Weight); var (childrenWeight, childrentExcWeight) = instance.ChildrenWeight; var childrenNode = CreateProfileCallTreeHeader("Calling", childrenWeight, childrentExcWeight, percentageFunc, 1); if (nodeList.Count > 1) { instanceNode.AddChild(childrenNode); } else { rootNode.AddChild(childrenNode); } foreach (var childNode in instance.Children) { CreateProfileCallTree(childNode, childrenNode, instanceNode, CallTreeListItemKind.CalleeNode, visitedNodes, percentageFunc); } visitedNodes.Clear(); } SortCallTreeNodes(instanceNode); } SortCallTreeNodes(rootNode); return rootNode; } private CallTreeListItem CreateProfileCallTree() { var visitedNodes = new HashSet(); var rootNode = new CallTreeListItem(CallTreeListItemKind.Root, this); rootNode.Children = new List(); foreach (var node in callTree_.RootNodes) { visitedNodes.Clear(); CreateProfileCallTree(node, rootNode, CallTreeListItemKind.CallTreeNode, visitedNodes); } SortCallTreeNodes(rootNode); return rootNode; } private CallTreeListItem CreateProfileCallTree(ProfileCallTreeNode node, CallTreeListItem parentNodeEx, CallTreeListItemKind kind, HashSet visitedNodes, Func percentageFunc = null) { return CreateProfileCallTree(node, parentNodeEx, parentNodeEx, kind, visitedNodes, percentageFunc); } private CallTreeListItem CreateProfileCallTree(ProfileCallTreeNode node, CallTreeListItem parentNodeEx, CallTreeListItem actualParentNode, CallTreeListItemKind kind, HashSet visitedNodes, Func percentageFunc = null) { bool newFunc = visitedNodes.Add(node); var nodeEx = CreateProfileCallTreeChild(node, kind, percentageFunc, parentNodeEx); parentNodeEx.AddChild(nodeEx); if (!newFunc) { return nodeEx; // Recursion in the call graph. } if (kind == CallTreeListItemKind.CalleeNode) { //? TODO: This is still not quite right, the selected nodes //? should be found on a path that has the current stack frame as a prefix in theirs. //? actualParentNode is just the last in that list node = GetChildCallTreeNode(node, actualParentNode.CallTreeNode, callTree_); nodeEx.CallTreeNode = node; } else if (kind == CallTreeListItemKind.CallerNode) { node = GetChildCallTreeNode(node, null, callTree_); nodeEx.CallTreeNode = node; } switch (kind) { case CallTreeListItemKind.CallTreeNode when node.HasChildren: { foreach (var childNode in node.Children) { CreateProfileCallTree(childNode, nodeEx, nodeEx, kind, visitedNodes, percentageFunc); } SortCallTreeNodes(nodeEx); break; } case CallTreeListItemKind.CalleeNode when node.HasChildren: { // For caller-callee mode, use a placeholder than when the tree gets expanded, // gets replaced by the real callee nodes. var dummyChildNode = CreateProfileCallTreeHeader(CallTreeListItemKind.ChildrenPlaceholder, "Placeholder", 0); dummyChildNode.CallTreeNode = node; nodeEx.AddChild(dummyChildNode); break; } case CallTreeListItemKind.CallerNode when node.HasCallers: { // For caller-callee mode, use a placeholder than when tree gets expanded, // gets replaced by the real caller (backtrace) nodes. var dummyChildNode = CreateProfileCallTreeHeader(CallTreeListItemKind.ChildrenPlaceholder, "Placeholder", 0); dummyChildNode.CallTreeNode = node; nodeEx.AddChild(dummyChildNode); break; } } visitedNodes.Remove(node); return nodeEx; } private void ExpandCallTreeTop() { if (CallTreeList.Nodes.Count > 0) { foreach (var childNode in CallTreeList.Nodes) { childNode.IsExpanded = true; } } } private double ComputeNodePercentage(TimeSpan weight, Func percentageFunc) { if (percentageFunc != null) { return percentageFunc(weight); } return weight.Ticks * profileDurationReciprocal_; } private CallTreeListItem CreateProfileCallTreeChild(ProfileCallTreeNode node, CallTreeListItemKind kind, Func percentageFunc, CallTreeListItem parentNodeEx = null) { double weightPercentage = ComputeNodePercentage(node.Weight, percentageFunc); double exclusiveWeightPercentage = ComputeNodePercentage(node.ExclusiveWeight, percentageFunc); var result = new CallTreeListItem(kind, this, Session.CompilerInfo.NameProvider.FormatFunctionName) { Function = node.Function, ModuleName = node.ModuleName, Time = node.Weight.Ticks, CallTreeNode = node, Parent = parentNodeEx, Percentage = weightPercentage, ExclusivePercentage = exclusiveWeightPercentage, TextColor = Brushes.Black, BackColor = App.Settings.DocumentSettings.ProfileMarkerSettings.PickBrushForPercentage(weightPercentage), BackColor2 = App.Settings.DocumentSettings.ProfileMarkerSettings.PickBrushForPercentage(exclusiveWeightPercentage) }; callTreeNodeToNodeExMap_[node] = result; return result; } private CallTreeListItem CreateProfileCallTreeHeader(string name, TimeSpan weight, TimeSpan exclusiveWeight, Func percentageFunc, int priority) { double weightPercentage = ComputeNodePercentage(weight, percentageFunc); double exclusiveWeightPercentage = ComputeNodePercentage(exclusiveWeight, percentageFunc); return new CallTreeListItem(CallTreeListItemKind.Header, this) { CallTreeNode = new ProfileCallTreeNode(null, null) {Weight = weight, ExclusiveWeight = exclusiveWeight}, Time = TimeSpan.MaxValue.Ticks - priority, FunctionName = name, Percentage = weightPercentage, ExclusivePercentage = exclusiveWeightPercentage, TextColor = Brushes.Black, BackColor = App.Settings.DocumentSettings.ProfileMarkerSettings.PickBrushForPercentage(weightPercentage), BackColor2 = App.Settings.DocumentSettings.ProfileMarkerSettings.PickBrushForPercentage(exclusiveWeightPercentage), IsMarked = true }; } private CallTreeListItem CreateProfileCallTreeHeader(CallTreeListItemKind kind, string name, int priority) { return new CallTreeListItem(kind, this) {Time = TimeSpan.MaxValue.Ticks - priority, FunctionName = name, TextColor = Brushes.Black, IsMarked = true}; } private CallTreeListItem CreateProfileCallTreeInstance(string name, ProfileCallTreeNode node, Func percentageFunc) { var result = CreateProfileCallTreeChild(node, CallTreeListItemKind.Header, percentageFunc); result.FunctionName = name; result.IsMarked = true; return result; } private async void ChildDoubleClick(object sender, MouseButtonEventArgs e) { var item = ((ListViewItem)sender).Content as CallTreeListItem; if (item != null) { if (!Utils.IsAltModifierActive()) { var openMode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await OpenFunction(item, openMode); } else { await SwitchFunction(item); if (IsCallerCalleePanel) { await DisplayProfileCallerCalleeTree(item.Function); } } } } private void ExpandHottestFunctionPath() { if (CallTreeList.Nodes.Count > 0) { ExpandHottestFunctionPath(CallTreeList.Nodes[0]); } } private void UnmarkAllFunctions() { foreach (var funcEx in callTreeNodeToNodeExMap_.Values) { funcEx.IsMarked = false; } } private void ExpandHottestFunctionPath(TreeNode node) { UnmarkAllFunctions(); ExpandHottestFunctionPathImpl(node); } private void ExpandHottestFunctionPathImpl(TreeNode node, int depth = 0) { var item = node.Tag as CallTreeListItem; item.IsMarked = true; if (node.HasChildren && depth <= 10) { node.IsExpanded = true; ExpandHottestFunctionPathImpl(node.Nodes[0], depth + 1); } } private void CollapseAllFunctionPaths() { foreach (var node in CallTreeList.Nodes) { CollapseFunctionPath(node); } } private void CollapseFunctionPath(TreeNode node) { foreach (var child in node.Nodes) { CollapseFunctionPath(child); } node.IsExpanded = false; } private void ExpandCallPathExecuted(object sender, ExecutedRoutedEventArgs e) { if (CallTreeList.SelectedItem is TreeNode node) { // Expand hottest path starting with the node. ExpandHottestFunctionPath(node); } else { // Expand hottest path in the tree. ExpandHottestFunctionPath(); } } private void ExpandHottestCallPathExecuted(object sender, ExecutedRoutedEventArgs e) { // Expand hottest path in the tree. ExpandHottestFunctionPath(); } private void CollapseCallPathExecuted(object sender, ExecutedRoutedEventArgs e) { if (CallTreeList.SelectedItem is TreeNode node) { CollapseFunctionPath(node); } } private async void SelectFunctionExecuted(object sender, ExecutedRoutedEventArgs e) { if (CallTreeList.SelectedItem is TreeNode node) { if (node.Tag is CallTreeListItem {HasCallTreeNode: true} item) { await SwitchFunction(item); if (IsCallerCalleePanel) { await DisplayProfileCallerCalleeTree(item.Function); } } } } private async void OpenFunctionExecuted(object sender, ExecutedRoutedEventArgs e) { if (CallTreeList.SelectedItem is TreeNode node) { var item = node.Tag as CallTreeListItem; var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await OpenFunction(item, mode); } } private async void OpenFunctionInNewTab(object sender, ExecutedRoutedEventArgs e) { if (CallTreeList.SelectedItem is TreeNode node) { var item = node.Tag as CallTreeListItem; await OpenFunction(item, OpenSectionKind.NewTab); } } private async void GoBackExecuted(object sender, ExecutedRoutedEventArgs e) { await RestorePreviousState(); } private async Task OpenFunction(CallTreeListItem item, OpenSectionKind openMode) { if (item.HasCallTreeNode) { await Session.OpenProfileFunction(item.CallTreeNode, openMode); } } private async Task OpenFunctionInstance(CallTreeListItem item, OpenSectionKind openMode) { if (item.HasCallTreeNode) { var filter = new ProfileSampleFilter(item.CallTreeNode); await Session.OpenProfileFunction(item.CallTreeNode, openMode, filter); } } private async Task SwitchFunction(CallTreeListItem item) { if (item.HasCallTreeNode) { if (function_ != null) { stateStack_.Push(function_); OnPropertyChanged(nameof(HasPreviousState)); } await Session.SwitchActiveProfileFunction(item.CallTreeNode); } } private async void FunctionFilter_TextChanged(object sender, TextChangedEventArgs e) { string text = FunctionFilter.Text.Trim(); await SearchCallTree(text); } private async Task SearchCallTree(string text) { using var cancelableTask = await searchTask_.CancelCurrentAndCreateTaskAsync(); if (searchResultNodes_ != null) { // Clear previous search results. foreach (var node in searchResultNodes_) { node.SearchResult = null; node.ResetCachedName(); } } if (text.Length > 1) { searchResultNodes_ = new List(); var searcher = new TextSearcher(text, !App.Settings.SectionSettings.FunctionSearchCaseSensitive); await Task.Run(() => SearchCallTree(text, callTreeEx_, searcher, searchResultNodes_)); if (cancelableTask.IsCanceled) { return; } foreach (var node in searchResultNodes_) { node.ResetCachedName(); } searchResultIndex_ = -1; SelectNextSearchResult(); ShowSearchSection = true; } else { searchResultNodes_ = null; ShowSearchSection = false; } } private void UpdateSearchResultText() { SearchResultText = searchResultNodes_ is {Count: > 0} ? $"{searchResultIndex_ + 1} / {searchResultNodes_.Count}" : "Not found"; } private void SearchCallTree(string text, CallTreeListItem node, TextSearcher searcher, List matchingNodes) { var result = searcher.FirstIndexOf(node.FunctionName); if (result.HasValue) { node.SearchResult = result; matchingNodes.Add(node); } foreach (var child in node.Children) { SearchCallTree(text, child, searcher, matchingNodes); } } private void FocusSearchExecuted(object sender, ExecutedRoutedEventArgs e) { FunctionFilter.Focus(); FunctionFilter.SelectAll(); } private void ClearSearchExecuted(object sender, ExecutedRoutedEventArgs e) { ((TextBox)e.Parameter).Text = string.Empty; } private async void CallTree_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (ignoreNextSelectionEvent_) { ignoreNextSelectionEvent_ = false; return; } if (CallTreeList.SelectedItem is TreeNode node && node.Tag is CallTreeListItem funcEx && funcEx.HasCallTreeNode) { if (settings_.SyncSourceFile) { // Load the source file and scroll to the hottest line. await Session.OpenProfileSourceFile(funcEx.CallTreeNode); } if (settings_.SyncSelection) { await Session.ProfileFunctionSelected(funcEx.CallTreeNode, PanelKind); } } else if (CallTreeList.SelectedItem == null && settings_.SyncSelection) { await Session.ProfileFunctionDeselected(); } } private async Task RestorePreviousState() { if (stateStack_.TryPop(out var prevFunc)) { await Session.SwitchActiveFunction(prevFunc); OnPropertyChanged(nameof(HasPreviousState)); } } private void PreviousSearchResultExecuted(object sender, ExecutedRoutedEventArgs e) { SelectPreviousSearchResult(); } private void NextSearchResultExecuted(object sender, ExecutedRoutedEventArgs e) { SelectNextSearchResult(); } private void SelectPreviousSearchResult() { if (searchResultNodes_ != null && searchResultIndex_ > 0) { searchResultIndex_--; UpdateSearchResultText(); SelectFunction(searchResultNodes_[searchResultIndex_].CallTreeNode); } } private void SelectNextSearchResult() { if (searchResultNodes_ != null && searchResultIndex_ < searchResultNodes_.Count - 1) { searchResultIndex_++; UpdateSearchResultText(); SelectFunction(searchResultNodes_[searchResultIndex_].CallTreeNode); } } private void CollapseNodesExecuted(object sender, ExecutedRoutedEventArgs e) { CollapseAllFunctionPaths(); ExpandHottestFunctionPath(); } private async void PanelToolbarTray_OnHelpClicked(object sender, EventArgs e) { await HelpPanel.DisplayPanelHelp(PanelKind, Session); } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } //? TODO: Redesign settings change detection, doesn't work well //? when a panel shows multiple settings objects. var initialMarkingSettings = MarkingSettings.Clone(); FrameworkElement relativeControl = CallTreeList; optionsPanelPopup_ = OptionsPanelHostPopup.Create( settings_.Clone(), relativeControl, Session, async (newSettings, commit) => { if (!newSettings.Equals(settings_) || !initialMarkingSettings.Equals(MarkingSettings)) { Settings = newSettings; if (IsCallerCalleePanel) { App.Settings.CallerCalleeSettings = newSettings; } else { App.Settings.CallTreeSettings = newSettings; } await UpdateCallTree(); await UpdateMarkedFunctions(); if (commit) { App.SaveApplicationSettings(); } initialMarkingSettings = MarkingSettings.Clone(); return settings_.Clone(); } return null; }, () => optionsPanelPopup_ = null); } public override async Task OnReloadSettings() { Settings = PanelKind == ToolPanelKind.CallTree ? App.Settings.CallTreeSettings : App.Settings.CallerCalleeSettings; } private void PanelToolbarTray_OnSettingsClicked(object sender, EventArgs e) { ShowOptionsPanel(); } private async void ToggleButton_Click(object sender, RoutedEventArgs e) { await UpdateCallTree(); await UpdateMarkedFunctions(); } private void MarkSelectedNodes(object obj, Action action) { if (obj is SelectedColorEventArgs e) { foreach (TreeNode node in CallTreeList.SelectedItems) { if (node.Tag is CallTreeListItem item) { action(item, e.SelectedColor); } } } } public async Task UpdateMarkedFunctions(bool externalCall = false) { using var task = await loadTask_.WaitAndCreateTaskAsync(); await UpdateMarkedFunctionsNoLock(externalCall); } private async Task UpdateMarkedFunctionsNoLock(bool externalCall) { if (callTreeNodeToNodeExMap_ != null) { UpdateMarkedFunctionsImpl(); if (!externalCall) { await Session.FunctionMarkingChanged(PanelKind); } } } private void UpdateMarkedFunctionsImpl() { var fgSettings = App.Settings.MarkingSettings; foreach (var f in callTreeNodeToNodeExMap_.Values) { f.ModuleBackColor = null; f.FunctionBackColor = null; } if (!fgSettings.UseAutoModuleColors && !fgSettings.UseModuleColors && !fgSettings.UseFunctionColors) { return; } foreach (var item in callTreeNodeToNodeExMap_.Values) { if (fgSettings.UseModuleColors && fgSettings.GetModuleBrush(item.ModuleName, out var brush)) { item.ModuleBackColor = brush; } else if (fgSettings.UseAutoModuleColors) { item.ModuleBackColor = fgSettings.GetAutoModuleBrush(item.ModuleName); } if (fgSettings.UseFunctionColors && fgSettings.GetFunctionColor(item.FunctionName, out var color)) { item.FunctionBackColor = color.AsBrush(); } } } #region IToolPanel public override ToolPanelKind PanelKind => ToolPanelKind.CallTree; public override bool SavesStateToFile => false; public override void OnSessionEnd() { base.OnSessionEnd(); Settings.TreeListColumns.SaveColumnsState(CallTreeList.View as GridView); Reset(); } #endregion } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/DocumentColumns.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/Document/DocumentColumns.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using ICSharpCode.AvalonEdit.Folding; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI.Document; public partial class DocumentColumns : UserControl, INotifyPropertyChanged { private TextViewSettingsBase settings_; private OptionalColumnSettings columnSettings_; private List profileDataRows_; private List<(GridViewColumnHeader Header, GridViewColumn Column)> profileColumnHeaders_; private double columnsListItemHeight_; private ListCollectionView profileRowCollection_; private List<(int StartOffset, int EndOffset)> foldedTextRegions_; private int rowFilterIndex_; private IRDocument associatedDocument_; private OptionsPanelHostPopup optionsPanelPopup_; private Dictionary profileDataRowsMap_; public DocumentColumns() { InitializeComponent(); profileColumnHeaders_ = new List<(GridViewColumnHeader Header, GridViewColumn Column)>(); profileDataRows_ = new List(); foldedTextRegions_ = new List<(int StartOffset, int EndOffset)>(); profileDataRowsMap_ = new Dictionary(); } public double ColumnsListItemHeight { get => columnsListItemHeight_; set { if (Math.Abs(columnsListItemHeight_ - value) > double.Epsilon) { columnsListItemHeight_ = value; OnPropertyChanged(); } } } public TextViewSettingsBase Settings { get => settings_; set => settings_ = value; } public OptionalColumnSettings ColumnSettings { get => columnSettings_; set => columnSettings_ = value; } public bool UseSmallerFontSize { get; set; } public double TextFontSize => UseSmallerFontSize ? settings_.FontSize - 1 : settings_.FontSize; public event PropertyChangedEventHandler PropertyChanged; public event EventHandler ScrollChanged; public event EventHandler RowSelected; public event EventHandler RowHoverStart; public event EventHandler RowHoverStop; public event EventHandler ColumnSettingsChanged; public void SelectRow(int index) { if (index >= 0 && ColumnsList.Items.Count > index) { ColumnsList.SelectedIndex = index; } } public void Reset() { // Unregister column header event handlers. foreach (var columnHeader in profileColumnHeaders_) { columnHeader.Header.MouseLeftButtonDown -= ColumnHeaderOnClick; columnHeader.Header.MouseDoubleClick -= ColumnHeaderOnDoubleClick; columnHeader.Header.MouseRightButtonUp -= ColumnHeaderOnRightClick; columnHeader.Header.MouseRightButtonUp -= ColumnSettingsClickHandler; } OptionalColumn.RemoveListViewColumns(ColumnsList); ColumnsList.ItemsSource = null; profileColumnHeaders_.Clear(); foldedTextRegions_.Clear(); } public async Task Display(IRDocumentColumnData columnData, IRDocument associatedDocument) { Reset(); // Remove any existing columns. UpdateColumnsList(); if (!columnData.HasData) { return; } associatedDocument_ = associatedDocument; var function = associatedDocument.Function; int rowCount = associatedDocument.LineCount; // Make a row for each line of the associated document, // with each row having cells in case there is associated profile data. var elementValueList = await Task.Run(() => { var elementValueList = new List(function.TupleCount); var oddBackColor = settings_.AlternateBackgroundColor.AsBrush(); var blockSeparatorColor = settings_.ShowBlockSeparatorLine ? settings_.BlockSeparatorColor.AsBrush() : null; var font = new FontFamily(settings_.FontName); double fontSize = TextFontSize; var comparer = new IRDocumentColumnData.ColumnComparer(); Dictionary dummyCells = new(comparer); Dictionary separatorDummyCells = new(comparer); // Since many cells (and often entire rows) are empty, // re-use the same cells to speed up processing. ElementColumnValue MakeDummyCell(bool hasSeparator) { var columnValue = new ElementColumnValue(""); columnValue.TextFont = font; columnValue.TextSize = fontSize; return columnValue; } ElementColumnValue GetDummyCell(OptionalColumn column, bool hasSeparator) { return hasSeparator ? separatorDummyCells[column] : dummyCells[column]; } ElementRowValue MakeDummyRow(bool hasSeparator, Brush backColor = null) { var row = new ElementRowValue(null) { BackColor = backColor, BorderBrush = blockSeparatorColor }; foreach (var column in columnData.Columns) { var cell = MakeDummyCell(hasSeparator); row.ColumnValues[column] = cell; columnData.AddColumnValue(cell, column); if (hasSeparator) { separatorDummyCells[column] = cell; } else { dummyCells[column] = cell; } } if (hasSeparator) { row.BorderThickness = new Thickness(0, 0, 0, 1); row.BorderBrush = blockSeparatorColor; } SetValueBorder(row); return row; } void SetValueBorder(ElementRowValue row) { foreach (var value in row.Values) { value.BorderBrush = blockSeparatorColor; value.BorderThickness = new Thickness(1, 0, 1, 0); } } var dummyRow = MakeDummyRow(false); var separatorDummyRow = MakeDummyRow(true); var oddDummyRow = MakeDummyRow(false, oddBackColor); var oddSeparatorDummyRow = MakeDummyRow(true, oddBackColor); int prevLine = -1; bool prevIsOddBlock = false; void AddDummyRows(int count, bool isOddBlock) { for (int i = 0; i < count; i++) { elementValueList.Add(isOddBlock ? oddDummyRow : dummyRow); } } // Go through the blocks and each tuple in the block // and either create a row with profile data or use a dummy row. profileDataRows_ = new List(); foreach (var block in function.SortedBlocks) { bool isOddBlock = block.HasOddIndexInFunction; for (int i = 0; i < block.Tuples.Count; i++) { var tuple = block.Tuples[i]; int currentLine = tuple.TextLocation.Line; bool isSeparatorLine = settings_.ShowBlockSeparatorLine && block.IndexInFunction < function.BlockCount - 1 && i == block.TupleCount - 1; // Add dummy empty list view lines to match document text. if (currentLine > prevLine + 1) { AddDummyRows(currentLine - prevLine - 1, isOddBlock); } // Check if there is any data associated with the element. // Have the row match the background color used in the doc. var rowValues = columnData.GetValues(tuple); if (rowValues != null) { rowValues.BorderBrush = blockSeparatorColor; if (rowValues.BackColor == null && isOddBlock) { rowValues.BackColor = oddBackColor; } foreach (var columnValue in rowValues.ColumnValues) { columnValue.Value.TextFont = font; columnValue.Value.TextSize = fontSize; } // Add dummy cells for the missing ones, needed for column separators. if (rowValues.ColumnValues.Count != columnData.Columns.Count) { foreach (var column in columnData.Columns) { if (!rowValues.Columns.Contains(column)) { rowValues.ColumnValues[column] = GetDummyCell(column, isSeparatorLine); } } } // Add a separator line at the bottom of the current row // if the next instr. is found in another block. if (isSeparatorLine) { rowValues.BorderBrush = blockSeparatorColor; rowValues.BorderThickness = new Thickness(0, 0, 0, 1); } SetValueBorder(rowValues); profileDataRows_.Add(rowValues); profileDataRowsMap_[tuple] = rowValues; } else { // No data at all, use an empty row. if (isSeparatorLine) { rowValues = isOddBlock ? oddSeparatorDummyRow : separatorDummyRow; } else { rowValues = isOddBlock ? oddDummyRow : dummyRow; } } elementValueList.Add(rowValues); prevLine = currentLine; } prevIsOddBlock = isOddBlock; } // Add empty lines at the end to match document, // otherwise scrolling can get out of sync. if (rowCount != prevLine + 1) { AddDummyRows(rowCount - prevLine, prevIsOddBlock); } return elementValueList; }); // Handle clicks on the column headers. var sortedColumns = columnSettings_.FilterAndSortColumns(columnData.Columns); profileColumnHeaders_ = OptionalColumn.AddListViewColumns(ColumnsList, sortedColumns); foreach (var columnHeader in profileColumnHeaders_) { columnHeader.Header.MouseLeftButtonDown += ColumnHeaderOnClick; columnHeader.Header.MouseDoubleClick += ColumnHeaderOnDoubleClick; columnHeader.Header.MouseRightButtonUp += ColumnHeaderOnRightClick; columnHeader.Header.MouseRightButtonUp += ColumnSettingsClickHandler; } // Display the columns. profileRowCollection_ = new ListCollectionView(elementValueList); profileRowCollection_.Filter += ProfileListRowFilter; UpdateColumnWidths(); ColumnsList.ItemsSource = profileRowCollection_; UpdateColumnsList(); } public ElementRowValue GetRowValue(IRElement element) { return profileDataRowsMap_.GetValueOrDefault(element); } private void ColumnSettingsClickHandler(object sender, RoutedEventArgs e) { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } var columnHeader = (GridViewColumnHeader)sender; var column = (OptionalColumn)columnHeader.Tag; optionsPanelPopup_ = OptionsPanelHostPopup.Create( column.Style.Clone(), columnHeader, null, async (newSettings, commit) => { if (!newSettings.Equals(column.Style)) { column.Style = newSettings; ColumnSettingsChanged?.Invoke(this, column); if (commit) { columnSettings_.AddColumnStyle(column, newSettings); App.SaveApplicationSettings(); } return newSettings.Clone(); } if (commit) { columnSettings_.AddColumnStyle(column, newSettings); App.SaveApplicationSettings(); } return null; }, () => optionsPanelPopup_ = null, new Point(0, columnHeader.ActualHeight - 1)); } public void BuildColumnsVisibilityMenu(IRDocumentColumnData columnData, MenuItem menu, Action columnsChanged) { // Add the columns at the end of the menu, // keeping the original items. var defaultItems = DocumentUtils.SaveDefaultMenuItems(menu); menu.Items.Clear(); foreach (var column in columnData.Columns) { var item = new MenuItem { Header = column.Title, Tag = column, IsCheckable = true, IsChecked = column.IsVisible, StaysOpenOnClick = true, Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }; item.Checked += (sender, args) => { if (sender is MenuItem menuItem && menuItem.Tag is OptionalColumn column) { column.IsVisible = menuItem.IsChecked; columnSettings_.SetColumnVisibility(column, menuItem.IsChecked); columnsChanged(); } }; item.Unchecked += (sender, args) => { if (sender is MenuItem menuItem && menuItem.Tag is OptionalColumn column) { column.IsVisible = menuItem.IsChecked; columnSettings_.SetColumnVisibility(column, menuItem.IsChecked); columnsChanged(); } }; defaultItems.Add(item); } DocumentUtils.RestoreDefaultMenuItems(menu, defaultItems); } public void SetupFoldedTextRegions(IEnumerable regions) { // Used to sync the visible rows with the folding // that can be applied on blocks in the associated document. foldedTextRegions_.Clear(); foreach (var region in regions) { if (region.IsFolded) { foldedTextRegions_.Add((region.StartOffset, region.EndOffset)); } } foldedTextRegions_.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset)); rowFilterIndex_ = 0; profileRowCollection_.Refresh(); } public void HandleTextRegionFolded(FoldingSection section) { HandleTextRegionFolded((section.StartOffset, section.EndOffset)); } public void HandleTextRegionFolded((int StartOffset, int EndOffset) section) { if (foldedTextRegions_.Contains(section)) { return; } foldedTextRegions_.Add(section); foldedTextRegions_.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset)); rowFilterIndex_ = 0; profileRowCollection_.Refresh(); } public void HandleTextRegionUnfolded(FoldingSection section) { HandleTextRegionUnfolded((section.StartOffset, section.EndOffset)); } public void HandleTextRegionUnfolded((int StartOffset, int EndOffset) section) { foldedTextRegions_.Remove(section); rowFilterIndex_ = 0; profileRowCollection_.Refresh(); } private bool ProfileListRowFilter(object item) { // Filter out rows to keep in sync with the collapsed // block foldings in the associated document. foreach (var range in foldedTextRegions_) { var startLine = associatedDocument_.GetLineByOffset(range.StartOffset); var endLine = associatedDocument_.GetLineByOffset(range.EndOffset); if (startLine.LineNumber - 1 > rowFilterIndex_) { break; // Early stop in sorted range list. } if (rowFilterIndex_ >= startLine.LineNumber && rowFilterIndex_ < endLine.LineNumber) { rowFilterIndex_++; return false; } } rowFilterIndex_++; return true; } public void UpdateColumnWidths() { if (profileDataRows_ == null || profileColumnHeaders_ == null) { return; } var maxColumnTextSize = new Dictionary(); var maxColumnExtraSize = new Dictionary(); var font = new FontFamily(settings_.FontName); double fontSize = TextFontSize; double maxBarWidth = settings_.ProfileMarkerSettings.MaxPercentageBarWidth; const double columnMargin = 8; foreach (var rowValues in profileDataRows_) { foreach (var columnValue in rowValues.ColumnValues) { columnValue.Value.TextFont = font; columnValue.Value.TextSize = fontSize; // Remember the max text length for each column // to later set the MinWidth for alignment. maxColumnTextSize.CollectMaxValue(columnValue.Key, columnValue.Value.Text.Length); if (columnValue.Value.ShowPercentageBar || columnValue.Value.ShowIcon) { double extraColumnWidth = columnMargin; if (columnValue.Value.ShowPercentageBar) { extraColumnWidth += columnValue.Value.ValuePercentage * maxBarWidth; } if (columnValue.Value.ShowIcon) { // Width of the icon is at most the height of the row. extraColumnWidth += ColumnsListItemHeight + columnMargin; } maxColumnExtraSize.CollectMaxValue(columnValue.Key, extraColumnWidth); } } } // Set the MinWidth of the text for each cell. foreach (var pair in maxColumnTextSize) { var columnContentSize = Utils.MeasureString((int)pair.Value, settings_.FontName, TextFontSize); double columnWidth = columnContentSize.Width + columnMargin; maxColumnTextSize[pair.Key] = Math.Ceiling(columnWidth); // Also set the initial width of each column header. // For the header, consider image and percentage bar too. if (maxColumnExtraSize.TryGetValue(pair.Key, out double extraSize)) { columnWidth += extraSize; } if (columnWidth == 0 && columnSettings_.RemoveEmptyColumns) { pair.Key.IsVisible = false; } else { var columnTitleSize = Utils.MeasureString(pair.Key.Title, settings_.FontName, TextFontSize); var gridColumn = profileColumnHeaders_.Find(item => item.Header.Tag.Equals(pair.Key)); if (gridColumn.Column == null || gridColumn.Header == null) { continue; } columnWidth = Math.Max(columnWidth, columnTitleSize.Width + columnMargin); gridColumn.Header.Width = columnWidth; gridColumn.Column.Width = columnWidth; } //Trace.WriteLine($"Column width {columnWidth} for {pair.Key.ColumnName}"); } foreach (var row in profileDataRows_) { foreach (var columnValue in row.ColumnValues) { columnValue.Value.MinTextWidth = maxColumnTextSize[columnValue.Key]; } } } public void ScrollToVerticalOffset(double offset) { // Sync scrolling with the optional columns. var columnScrollViewer = Utils.FindChild(ColumnsList); if (columnScrollViewer != null) { columnScrollViewer.ScrollToVerticalOffset(offset); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } public void UpdateColumnsList() { ColumnsList.Background = settings_.BackgroundColor.AsBrush(); ColumnsList.Background = ColorBrushes.GetBrush(settings_.BackgroundColor); ColumnsListItemHeight = Utils.MeasureString("0123456789ABCXYZ!?|()", settings_.FontName, TextFontSize).Height; } private void ColumnHeaderOnClick(object sender, RoutedEventArgs e) { if (((GridViewColumnHeader)sender).Tag is OptionalColumn column && column.HeaderClickHandler != null) { column.HeaderClickHandler(column, (GridViewColumnHeader)sender); UpdateColumnWidths(); e.Handled = true; } } private void ColumnHeaderOnRightClick(object sender, RoutedEventArgs e) { if (((GridViewColumnHeader)sender).Tag is OptionalColumn column && column.HeaderRightClickHandler != null) { column.HeaderRightClickHandler(column, (GridViewColumnHeader)sender); UpdateColumnWidths(); e.Handled = true; } } private void ColumnHeaderOnDoubleClick(object sender, RoutedEventArgs e) { if (((GridViewColumnHeader)sender).Tag is OptionalColumn column && column.HeaderDoubleClickHandler != null) { column.HeaderDoubleClickHandler(column, (GridViewColumnHeader)sender); UpdateColumnWidths(); e.Handled = true; } } private void ColumnsList_ScrollChanged(object sender, ScrollChangedEventArgs e) { if (Math.Abs(e.VerticalChange) < double.Epsilon) { return; } ScrollChanged?.Invoke(this, e); } private void ColumnsList_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { if (ColumnsList.SelectedItem != null) { RowSelected?.Invoke(this, ColumnsList.SelectedIndex); } } private void ListViewItem_MouseEnter(object sender, MouseEventArgs e) { if (sender is ListViewItem {DataContext: ElementRowValue row}) { RowHoverStart?.Invoke(this, row); } } private void ListViewItem_MouseLeave(object sender, MouseEventArgs e) { if (sender is ListViewItem {DataContext: ElementRowValue row}) { RowHoverStop?.Invoke(this, row); } } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/InlineAssemblyHelpers.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Collections.Generic; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Folding; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.UI.Document; namespace ProfileExplorer.UI.Profile.Document; // A custom line margin that overrides the default one, with support // for block folding - the lines part of a block folding are not numbered. sealed class SourceLineNumberMargin : LineNumberMargin { private IRDocument textView_; private SourceLineProfileResult sourceLineProfileResult_; static SourceLineNumberMargin() { DefaultStyleKeyProperty.OverrideMetadata(typeof(SourceLineNumberMargin), new FrameworkPropertyMetadata(typeof(SourceLineNumberMargin))); } public SourceLineNumberMargin(IRDocument textView, SourceLineProfileResult sourceLineProfileResult) { textView_ = textView; sourceLineProfileResult_ = sourceLineProfileResult; } protected override void OnRender(DrawingContext drawingContext) { var textView = TextView; var renderSize = RenderSize; if (textView == null || !textView.VisualLinesValid) { return; } var foreground = textView_.LineNumbersForeground; foreach (var line in textView.VisualLines) { int lineNumber = line.FirstDocumentLine.LineNumber; if (sourceLineProfileResult_ != null) { if (lineNumber < sourceLineProfileResult_.SourceLineResult.FirstLineIndex) { // Line numbers before function start are unchanged. } else if (lineNumber > sourceLineProfileResult_.SourceLineResult.LastLineIndex + sourceLineProfileResult_.AssemblyLineCount) { // For lines after function end, subtract the assembly line count. lineNumber -= sourceLineProfileResult_.AssemblyLineCount; } else if (sourceLineProfileResult_.LineToOriginalLineMap.TryGetValue(lineNumber, out int mappedLine)) { lineNumber = mappedLine; } else { // Don't show line numbers for inline assembly. continue; } } var text = DocumentUtils.CreateFormattedText(this, lineNumber.ToString(), typeface, emSize, foreground); double y = line.GetTextLineVisualYPosition(line.TextLines[0], VisualYPosition.TextTop); drawingContext.DrawText(text, new Point(renderSize.Width - text.Width, y - textView.VerticalOffset)); } } } // Creates block foldings for the specified ranges, used to display // the foldings for inline assembly sections in the source code document. sealed class RangeFoldingStrategy : IBlockFoldingStrategy { private List<(int StartOffset, int EndOffset)> ranges_; private bool defaultClosed_; public RangeFoldingStrategy(List<(int StartOffset, int EndOffset)> ranges, bool defaultClosed = false) { ranges_ = ranges; defaultClosed_ = defaultClosed; } public void UpdateFoldings(FoldingManager manager, TextDocument document) { var newFoldings = CreateNewFoldings(document); manager.UpdateFoldings(newFoldings, -1); } private IEnumerable CreateNewFoldings(TextDocument document) { foreach (var range in ranges_) { yield return new NewFolding(range.StartOffset, range.EndOffset) { DefaultClosed = defaultClosed_ }; } } } // Changes the style of a range of text in IRDocument. sealed class RangeColorizer : DocumentColorizingTransformer { private List<(int StartOffset, int EndOffset)> ranges_; private Brush textColor_; private Brush backColor_; private Typeface typeface_; private CompareRanges comparer_; public RangeColorizer(List<(int StartOffset, int EndOffset)> ranges, Brush textColor, Brush backColor = null, Typeface typeface = null) { ranges_ = ranges; textColor_ = textColor; backColor_ = backColor; typeface_ = typeface; comparer_ = new CompareRanges(); ranges.Sort((a, b) => a.CompareTo(b)); } protected override void ColorizeLine(DocumentLine line) { if (line.Length == 0) { return; } var query = (line.Offset, line.EndOffset); int result = ranges_.BinarySearch(query, comparer_); if (result >= 0) { var range = ranges_[result]; if (line.Offset < range.StartOffset || line.Offset > range.EndOffset) { return; } int start = line.Offset > range.StartOffset ? line.Offset : range.StartOffset; int end = range.EndOffset > line.EndOffset ? line.EndOffset : range.EndOffset; ChangeLinePart(start, end, element => { if (textColor_ != null) { element.TextRunProperties.SetForegroundBrush(textColor_); } if (backColor_ != null) { element.TextRunProperties.SetBackgroundBrush(backColor_); } if (typeface_ != null) { element.TextRunProperties.SetTypeface(typeface_); } }); } } private class CompareRanges : IComparer<(int StartOffset, int EndOffset)> { public int Compare((int StartOffset, int EndOffset) x, (int StartOffset, int EndOffset) y) { if (x.EndOffset < y.StartOffset) { return -1; } else if (x.StartOffset > y.EndOffset) { return 1; } return 0; } } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfileDocumentMarker.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Utilities; using ProfileExplorer.UI.Document; using TextLocation = ProfileExplorer.Core.TextLocation; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core.Profile.CallTree; using PerformanceCounter = ProfileExplorer.Core.Profile.Data.PerformanceCounter; namespace ProfileExplorer.UI.Profile; //? TODO: Use better names for members public record SourceLineProfileResult( FunctionProcessingResult Result, SourceLineProcessingResult SourceLineResult, FunctionIR Function, Dictionary LineToElementMap, Dictionary LineToOriginalLineMap, Dictionary OriginalLineToLineMap, List<(int StartOffset, int EndOffset)> AssemblyRanges, int AssemblyLineCount); public class InlineeListItem { public InlineeListItem(SourceStackFrame frame) { InlineeFrame = frame; ElementWeights = new List<(IRElement Element, TimeSpan Weight)>(); } public SourceStackFrame InlineeFrame { get; set; } public ProfileCallTreeNode CallTreeNode { get; set; } public TimeSpan Weight { get; set; } public TimeSpan ExclusiveWeight { get; set; } public double Percentage { get; set; } public double ExclusivePercentage { get; set; } public List<(IRElement Element, TimeSpan Weight)> ElementWeights { get; } public List SortedElements { get { ElementWeights.Sort((a, b) => b.Weight.CompareTo(a.Weight)); return ElementWeights.ConvertAll(item => item.Element); } } } public class ProfileDocumentMarker { private static readonly string ProfileOverlayTag = "ProfileTag"; // Templates for the time columns defining the style. public static readonly OptionalColumn TimeColumnDefinition = OptionalColumn.Template("[TimeHeader]", "TimePercentageColumnValueTemplate", "TimeHeader", "Time (ms)", "Instruction time", null, 50.0, "TimeColumnHeaderTemplate"); public static readonly OptionalColumn TimePercentageColumnDefinition = OptionalColumn.Template("[TimePercentageHeader]", "TimePercentageColumnValueTemplate", "TimePercentageHeader", "Time (%)", "Instruction time percentage relative to function time", null, 50.0, "TimeColumnHeaderTemplate"); //? TODO: Should be customizable (at least JSON if not UI) //? TODO: Each column setting should have the abbreviation private static readonly (string, string)[] PerfCounterNameReplacements = { ("Instruction", "Instr"), ("Misprediction", "Mispred") }; private FunctionProfileData profile_; private ProfileData globalProfile_; private ProfileDocumentMarkerSettings settings_; private OptionalColumnSettings columnSettings_; private ICompilerInfoProvider irInfo_; public ProfileDocumentMarker(FunctionProfileData profile, ProfileData globalProfile, ProfileDocumentMarkerSettings settings, OptionalColumnSettings columnSettings, ICompilerInfoProvider ir) { profile_ = profile; globalProfile_ = globalProfile; settings_ = settings; columnSettings_ = columnSettings; irInfo_ = ir; } public OptionalColumn TimeColumnTemplate() { string timeUnit = settings_.ValueUnit switch { ProfileDocumentMarkerSettings.ValueUnitKind.Second => "sec", ProfileDocumentMarkerSettings.ValueUnitKind.Millisecond => "ms", ProfileDocumentMarkerSettings.ValueUnitKind.Microsecond => "µs", ProfileDocumentMarkerSettings.ValueUnitKind.Nanosecond => "ns", _ => throw new ArgumentOutOfRangeException() }; TimeColumnDefinition.Title = $"Time ({timeUnit})"; TimeColumnDefinition.Style = columnSettings_.GetColumnStyle(TimeColumnDefinition) ?? OptionalColumnSettings.DefaultTimeColumnStyle; return TimeColumnDefinition; } public OptionalColumn TimePercentageColumnTemplate() { TimePercentageColumnDefinition.Style = columnSettings_.GetColumnStyle(TimePercentageColumnDefinition) ?? OptionalColumnSettings.DefaultTimePercentageColumnStyle; return TimePercentageColumnDefinition; } public OptionalColumn CounterColumnTemplate(PerformanceCounter counter, int index) { var column = OptionalColumn.Template($"[CounterHeader{counter.Id}]", "TimePercentageColumnValueTemplate", $"CounterHeader{counter.Id}", $"{ShortenPerfCounterName(counter.Name)}", /*counterInfo?.Config?.Description != null ? $"{counterInfo.Config.Description}" :*/ $"{counter.Name}", null, 50, "TimeColumnHeaderTemplate"); column.Style = columnSettings_.GetColumnStyle(column); if (column.Style == null) { column.Style = counter.IsMetric ? OptionalColumnSettings.DefaultMetricsColumnStyle(index) : OptionalColumnSettings.DefaultCounterColumnStyle(index); } return column; } public static bool IsPerfCounterVisible(PerformanceCounter counter) { //? TODO: Use a filter list from options return counter.Name != "Timer"; } public static string FormatPerformanceMetric(double value, PerformanceMetric metric) { if (value == 0) { return ""; } return metric.Config.IsPercentage ? value.AsPercentageString() : $"{value:F2}"; } public static string FormatPerformanceCounter(long value, PerformanceCounter counter) { if (counter.Frequency >= 1000) { double valueK = (double)(value * counter.Frequency) / 1000; return $"{valueK:n0} K"; } return $"{value * counter.Frequency}"; } public static string ShortenPerfCounterName(string name) { foreach (var replacement in PerfCounterNameReplacements) { int index = name.LastIndexOf(replacement.Item1, StringComparison.Ordinal); if (index != -1) { string suffix = ""; if (index + replacement.Item1.Length < name.Length) { suffix = name.Substring(index + replacement.Item1.Length); } return name.Substring(0, index) + replacement.Item2 + suffix; } } return name; } public async Task Mark(IRDocument document, FunctionIR function, IRTextFunction textFunction) { IRDocumentColumnData columnData = null; var metadataTag = function.GetTag(); bool hasInstrOffsetMetadata = metadataTag != null && metadataTag.OffsetToElementMap.Count > 0; if (hasInstrOffsetMetadata) { document.SuspendUpdate(); var result = await Task.Run(() => profile_.Process(function, irInfo_.IR)); columnData = await MarkProfiledElements(result, function, document); document.ProfileProcessingResult = result; document.ProfileColumnData = columnData; // Remove any overlays from a previous marking. foreach (var block in function.Blocks) { document.RemoveElementOverlays(block, ProfileOverlayTag); } foreach (var tuple in function.AllTuples) { document.RemoveElementOverlays(tuple, ProfileOverlayTag); } MarkProfiledBlocks(result.BlockSampledElements, document, false); MarkCallSites(document, function, textFunction, metadataTag, null, false); document.ResumeUpdate(); } return columnData; } public async Task MarkSourceLines(IRDocument document, SourceLineProfileResult processingResult) { document.ProfileColumnData = await MarkProfiledElements(processingResult.Result, processingResult.Function, document); return document.ProfileColumnData; } public async Task PrepareSourceLineProfile(FunctionProfileData profile, IRDocument document, SourceLineProcessingResult sourceProcResult, ParsedIRTextSection parsedSection = null) { var sourceLineWeights = sourceProcResult.SourceLineWeightList; if (sourceLineWeights.Count == 0) { return null; } // Check for cases where instead of the source code smth. like // a source server authentication failure response is displayed. if (sourceProcResult.FirstLineIndex > document.LineCount && sourceProcResult.LastLineIndex > document.LineCount) { return null; } //? TODO: Pretty hacky approach that makes a fake function //? with IR elements to represent each source line. var ids = IRElementId.NewFunctionId(); var dummyFunc = new FunctionIR(); var dummyBlock = new BlockIR(ids.NewBlock(0), 0, dummyFunc); dummyFunc.Blocks.Add(dummyBlock); dummyFunc.AssignBlockIndices(); var processingResult = new FunctionProcessingResult(); var lineToElementMap = new Dictionary(); var lineToOriginalLineMap = new Dictionary(); var originalLineToLineMap = new Dictionary(); var assemblyRanges = new List<(int StartOffset, int EndOffset)>(); TupleIR MakeDummyTuple(TextLocation textLocation, DocumentLine documentLine) { var tupleIr = new TupleIR(ids.NextTuple(), TupleKind.Other, dummyBlock); tupleIr.TextLocation = textLocation; tupleIr.TextLength = documentLine.Length; dummyBlock.Tuples.Add(tupleIr); return tupleIr; } // If assembly should be inserted after each source line, // precompute the list of instructions mapping to each line. FunctionProcessingResult.SampledElementsToLineMapping instrToLineMap = null; if (parsedSection != null) { instrToLineMap = await Task.Run(() => { var funcProcResult = profile.Process(parsedSection.Function, irInfo_.IR); if (funcProcResult != null) { return funcProcResult.BuildSampledElementsToLineMapping(profile, parsedSection); } return null; }); } // For each source line, accumulate the weight of all instructions // mapped to that line, for both samples and performance counters. int lastLine = Math.Min(sourceProcResult.LastLineIndex, document.LineCount); int inserted = 0; document.SuspendUpdate(); for (int lineNumber = sourceProcResult.FirstLineIndex; lineNumber <= lastLine; lineNumber++) { var documentLine = document.GetLineByNumber(lineNumber + inserted); var location = new TextLocation(documentLine.Offset, lineNumber + inserted - 1, 0); var dummyTuple = MakeDummyTuple(location, documentLine); lineToElementMap[lineNumber + inserted] = dummyTuple; lineToOriginalLineMap[lineNumber + inserted] = lineNumber; originalLineToLineMap[lineNumber] = lineNumber + inserted; if (sourceProcResult.SourceLineWeight.TryGetValue(lineNumber, out var lineWeight)) { processingResult.SampledElements.Add((dummyTuple, lineWeight)); } if (sourceProcResult.SourceLineCounters.TryGetValue(lineNumber, out var counters)) { processingResult.CounterElements.Add((dummyTuple, counters)); } // Insert assembly instructions for each source line. if (dummyTuple == null || instrToLineMap == null || !instrToLineMap.SampledElements.TryGetValue(lineNumber, out var lineInstrs)) { continue; } var instrLine = document.GetLineByNumber(lineNumber + inserted); int rangeStart = instrLine.EndOffset; int rangeEnd = instrLine.EndOffset; foreach (var pair in lineInstrs) { var instr = pair.Element; var instrWeight = pair.Profile.Weight; var instrCounters = pair.Profile.Counters; string instrText = parsedSection.Text.Slice(instr.TextLocation.Offset, instr.TextLength).ToString(); document.Document.Insert(instrLine.EndOffset, $"\n{instrText.TrimEnd()}"); inserted++; instrLine = document.GetLineByNumber(lineNumber + inserted); rangeEnd = instrLine.EndOffset; location = new TextLocation(instrLine.Offset, lineNumber + inserted - 1, 0); dummyTuple = MakeDummyTuple(location, instrLine); lineToElementMap[lineNumber + inserted] = dummyTuple; if (instrWeight != TimeSpan.Zero) { processingResult.SampledElements.Add((dummyTuple, instrWeight)); } if (instrCounters != null) { processingResult.CounterElements.Add((dummyTuple, instrCounters)); } } assemblyRanges.Add((rangeStart, rangeEnd)); } document.ResumeUpdate(); processingResult.SortSampledElements(); // Used for ordering. processingResult.FunctionCountersValue = sourceProcResult.FunctionCountersValue; document.ProfileProcessingResult = processingResult; return new SourceLineProfileResult(processingResult, sourceProcResult, dummyFunc, lineToElementMap, lineToOriginalLineMap, originalLineToLineMap, assemblyRanges, inserted); } public List GenerateInlineeList(FunctionProcessingResult result) { // Group the sample elements by the deepest inlinee they originate from. // This computes the total time per inlinee and a list of elements associated with it. var inlineeMap = new Dictionary(); foreach (var pair in result.SampledElements) { var element = pair.Item1; if (!element.TryGetTag(out SourceLocationTag sourceTag) || !sourceTag.HasInlinees) { continue; } for (int i = 0; i < sourceTag.Inlinees.Count; i++) { var inlinee = sourceTag.Inlinees[i]; if (string.IsNullOrEmpty(inlinee.Function)) { continue; } if (!inlineeMap.TryGetValue(inlinee.Function, out var inlineeItem)) { inlineeItem = new InlineeListItem(inlinee); inlineeMap[inlinee.Function] = inlineeItem; } inlineeItem.Weight += pair.Item2; inlineeItem.ElementWeights.Add((element, pair.Item2)); if (i == 0) { inlineeItem.ExclusiveWeight += pair.Item2; } } } // Sort by decreasing weight. var inlineeList = inlineeMap.ToValueList(); inlineeList.Sort((a, b) => b.ExclusiveWeight.CompareTo(a.ExclusiveWeight)); return inlineeList; } public static void UpdateColumnStyle(OptionalColumn column, IRDocumentColumnData columnData, FunctionIR function, IRDocument document, ProfileDocumentMarkerSettings settings, OptionalColumnSettings columnSettings) { #if DEBUG Trace.WriteLine($"Update column {column.ColumnName}, is main column: {column.IsMainColumn}"); #endif column.IsVisible = columnSettings.IsColumnVisible(column); var elementColorPairs = new List>(function.TupleCount); var cells = columnData.ColumnValues.GetValueOrNull(column); // Empty columns don't have any values, ignore. if (cells != null) { foreach (var value in cells) { value.BackColor = settings.PickDefaultBackColor(column); } } foreach (var tuple in function.AllTuples) { var value = columnData.GetColumnValue(tuple, column); if (value == null) continue; int order = value.ValueOrder; double percentage = value.ValuePercentage; if (value.CanShowBackgroundColor) { var color = settings.PickBackColor(column, order, percentage); if (column.IsMainColumn && percentage >= settings.ElementWeightCutoff) { elementColorPairs.Add(new ValueTuple(tuple, color)); } // Don't override initial back color if no color is picked, // mostly done for perf metrics column which have an initial back color. if (!color.IsTransparent()) { value.BackColor = color; } } value.TextColor = settings.PickTextColor(column, order, percentage); value.TextWeight = settings.PickTextWeight(column, order, percentage); if (value.CanShowIcon) { value.Icon = settings.PickIcon(column, value.ValueOrder, value.ValuePercentage).Icon; } value.ShowPercentageBar = value.CanShowPercentageBar && // Disabled per value settings.ShowPercentageBar(column, value.ValueOrder, value.ValuePercentage); value.PercentageBarBackColor = settings.PickPercentageBarColor(column); value.PercentageBarMaxWidth = settings.MaxPercentageBarWidth; } // Mark the elements themselves with a color. if (column.IsMainColumn && document != null) { document.ClearInstructionMarkers(); if (settings.MarkElements) { document.MarkElements(elementColorPairs); } } } public void MarkCallSites(IRDocument document, FunctionIR function, IRTextFunction textFunction, SourceLineProfileResult processingResult) { var metadataTag = function.GetTag(); bool hasInstrOffsetMetadata = metadataTag != null && metadataTag.OffsetToElementMap.Count > 0; if (hasInstrOffsetMetadata) { MarkCallSites(document, function, textFunction, metadataTag, processingResult); } } private void MarkCallSites(IRDocument document, FunctionIR function, IRTextFunction textFunction, AssemblyMetadataTag metadataTag, SourceLineProfileResult processingResult = null, bool suspendUpdates = true) { // Mark indirect call sites and list the hottest call targets. // Useful especially for virtual function calls. var callTree = globalProfile_.CallTree; if (callTree == null || !settings_.MarkCallTargets) { return; } var overlayMap = new Dictionary List, bool HasIndirectCalls)>(); var node = callTree.GetCombinedCallTreeNode(textFunction); if (node == null || !node.HasCallSites) { return; } foreach (var callsite in node.CallSites.Values) { if (!FunctionProfileData.TryFindElementForOffset(metadataTag, callsite.RVA - profile_.FunctionDebugInfo.RVA, irInfo_.IR, out var element)) { continue; } //Trace.WriteLine($"Found CS for elem at RVA {callsite.RVA}, weight {callsite.Weight}: {element}"); var instr = element as InstructionIR; if (instr == null || !irInfo_.IR.IsCallInstruction(instr)) continue; // Mark direct, known call targets with a different icon. var callTarget = irInfo_.IR.GetCallTarget(instr); bool isDirectCall = callTarget is {HasName: true} && !callTarget.HasTag(); // When annotating a source file, map the instruction to the // fake tuple used the represent the source line. if (processingResult != null) { if (!instr.TryGetTag(out SourceLocationTag sourceTag)) { continue; // Couldn't map for some reason, ignore. } // With assembly lines, source line numbers are shifted. int sourceLine = sourceTag.Line; if (processingResult.OriginalLineToLineMap.TryGetValue(sourceTag.Line, out int mappedLine)) { sourceLine = mappedLine; } if (!processingResult.LineToElementMap.TryGetValue(sourceLine, out element)) { continue; // Couldn't map for some reason, ignore. } } // Collect call targets and override the weight // to include only the weight at this call site. if (!overlayMap.TryGetValue(element, out var pair)) { pair = new ValueTuple, bool>(); pair.List = new List(); overlayMap[element] = pair; } // Mark if any of the calls are indirect. if (!isDirectCall) { pair.HasIndirectCalls = true; overlayMap[element] = pair; // Update dictionary, since pair is a value type. } foreach (var target in callsite.SortedTargets) { var callsiteNode = new ProfileCallTreeGroupNode(target.Node, target.Weight); pair.List.Add(callsiteNode); } } // Add the overlays to the document. var indirectIcon = IconDrawing.FromIconResource("ExecuteIconColor"); var directIcon = IconDrawing.FromIconResource("ExecuteIcon"); var overlayListMap = new Dictionary>(); if (suspendUpdates) { document.SuspendUpdate(); } foreach (var (element, pair) in overlayMap) { var color = App.Settings.DocumentSettings.BackgroundColor; if (element.ParentBlock != null && !element.ParentBlock.HasEvenIndexInFunction) { color = App.Settings.DocumentSettings.AlternateBackgroundColor; } var icon = pair.HasIndirectCalls ? indirectIcon : directIcon; var overlay = document.RegisterIconElementOverlay(element, icon, 16, 16); overlay.Tag = ProfileOverlayTag; overlay.Background = color.AsBrush(); overlay.IsLabelPinned = false; overlay.AllowLabelEditing = false; overlay.UseLabelBackground = true; overlay.ShowBackgroundOnMouseOverOnly = true; overlay.ShowBorderOnMouseOverOnly = true; overlay.AlignmentX = HorizontalAlignment.Left; overlay.MarginY = 2; overlayListMap[overlay] = pair.List; if (element is InstructionIR instr) { // Place before the call opcode. int lineOffset = instr.OpcodeLocation.Offset - instr.TextLocation.Offset; overlay.MarginX = Utils.MeasureString(lineOffset, Utils.GetTextTypeface(document), document.FontSize).Width - 20; } } // Show a popup on hover with the list of call targets. SetupCallSiteHoverPreview(overlayListMap, document); if (suspendUpdates) { document.ResumeUpdate(); } } private void SetupCallSiteHoverPreview(Dictionary> overlayListMap, IRDocument document) { // The overlay hover preview is somewhat of a hack, // since the hover event is fired over the entire document, // but the popup should be shown only if mouse is over the overlay. var view = document as UIElement; CallTreeNodePopup popup = null; (IElementOverlay Overlay, List List) hoveredOverlay = (null, null); // Create a single hover handler for all overlays. var preview = new PopupHoverPreview( view, HoverPreview.HoverDuration, (mousePoint, previewPoint) => { if (hoveredOverlay.Overlay == null) { return null; // Nothing actually hovered. } if (popup == null) { var dummy = new DummyFunctionProfileInfoProvider(); popup = new CallTreeNodePopup(null, dummy, previewPoint, view, document.Session); popup.TitleText = "Call Targets"; } else { popup.UpdatePosition(previewPoint, view); } popup.ShowFunctions(hoveredOverlay.List, irInfo_.NameProvider.FormatFunctionName); return popup; }, (mousePoint, popup) => true, popup => { document.Session.RegisterDetachedPanel(popup); }); foreach (var pair in overlayListMap) { pair.Key.OnHover += (sender, e) => { hoveredOverlay.Overlay = sender as IElementOverlay; hoveredOverlay.List = overlayListMap[hoveredOverlay.Overlay]; }; pair.Key.OnHoverEnd += (sender, e) => { preview.HideDelayed(); hoveredOverlay = (null, null); }; } document.RegisterHoverPreview(preview); } private void MarkProfiledBlocks(List<(BlockIR, TimeSpan)> blockWeights, IRDocument document, bool suspendUpdates) { if (!settings_.MarkBlocks) { return; } if (suspendUpdates) { document.SuspendUpdate(); } double overlayHeight = document.DefaultLineHeight; var blockPen = ColorPens.GetPen(settings_.BlockOverlayBorderColor, settings_.BlockOverlayBorderThickness); for (int i = 0; i < blockWeights.Count; i++) { var block = blockWeights[i].Item1; var weight = blockWeights[i].Item2; double weightPercentage = profile_.ScaleWeight(weight); var icon = settings_.PickIconForOrder(i, weightPercentage); var color = settings_.PickBackColorForPercentage(weightPercentage); if (color.IsTransparent()) { // Match the background color of the corresponding text line. color = block.HasEvenIndexInFunction ? App.Settings.DocumentSettings.BackgroundColor.AsBrush() : App.Settings.DocumentSettings.AlternateBackgroundColor.AsBrush(); } bool markOnFlowGraph = settings_.IsSignificantValue(i, weightPercentage); string label = $"{weightPercentage.AsTrimmedPercentageString()}"; string tooltip = settings_.FormatWeightValue(weight); var overlay = document.RegisterIconElementOverlay(block, icon, 0, overlayHeight, label, tooltip); overlay.Tag = ProfileOverlayTag; overlay.Background = color; overlay.Border = blockPen; overlay.IsLabelPinned = true; overlay.AllowLabelEditing = false; overlay.UseLabelBackground = true; overlay.ShowBackgroundOnMouseOverOnly = false; overlay.ShowBorderOnMouseOverOnly = false; overlay.AlignmentX = HorizontalAlignment.Left; overlay.MarginX = -1; overlay.Padding = 2; (overlay.TextColor, overlay.TextWeight) = settings_.PickBlockOverlayStyle(i, weightPercentage); // Mark the block itself with a color. document.MarkBlock(block, color, markOnFlowGraph); if (settings_.MarkBlocksInFlowGraph && weightPercentage > settings_.ElementWeightCutoff) { block.AddTag(GraphNodeTag.MakeColor(weightPercentage.AsTrimmedPercentageString(), ((SolidColorBrush)color).Color, ((SolidColorBrush)overlay.TextColor).Color, ((SolidColorBrush)overlay.TextColor).Color, i < 3 || weightPercentage >= 0.1)); // Bold text for >10%. } } if (suspendUpdates) { document.ResumeUpdate(); } } private async Task MarkProfiledElements(FunctionProcessingResult result, FunctionIR function, IRDocument document) { // Add a time column. var elements = result.SampledElements; var columnData = new IRDocumentColumnData(function.InstructionCount); var percentageColumn = columnData.AddColumn(TimePercentageColumnTemplate()); var timeColumn = columnData.AddColumn(TimeColumnTemplate()); percentageColumn.IsMainColumn = true; await Task.Run(() => { for (int i = 0; i < elements.Count; i++) { var element = elements[i].Item1; var weight = elements[i].Item2; double weightPercentage = profile_.ScaleWeight(weight); string label = settings_.FormatWeightValue(weight); string percentageLabel = weightPercentage.AsTrimmedPercentageString(); var columnValue = new ElementColumnValue(label, weight.Ticks, weightPercentage, i); var percentageColumnValue = new ElementColumnValue(percentageLabel, weight.Ticks, weightPercentage, i); columnValue.ToolTip = percentageLabel; percentageColumnValue.ToolTip = label; columnData.AddValue(percentageColumnValue, element, percentageColumn); var valueGroup = columnData.AddValue(columnValue, element, timeColumn); //? valueGroup.BackColor = Brushes.Bisque; } }); // Handle performance counter columns. var counterElements = result.CounterElements; if (counterElements.Count == 0) { SetupColumnHeaderEvents(function, document, columnData); return columnData; } var perfCounters = globalProfile_.SortedPerformanceCounters; var counterColumns = new OptionalColumn[perfCounters.Count]; var counterSortMap = new List>(); await Task.Run(() => { // Add a column for each counter. for (int k = 0; k < perfCounters.Count; k++) { CreatePerfCounterColumn(function, document, columnData, perfCounters, counterColumns, k); } // Build lists, sort lists by value, then go over lists and assign ValueOrder. for (int k = 0; k < perfCounters.Count; k++) { counterSortMap.Add(new List(counterElements.Count)); } for (int i = 0; i < counterElements.Count; i++) { var element = counterElements[i].Item1; var counterSet = counterElements[i].Item2; for (int k = 0; k < perfCounters.Count; k++) { var counter = perfCounters[k]; long value = 0; double valuePercentage = 0; string label = ""; string tooltip = null; bool isValueBasedMetric = false; if (counter.IsMetric) { var metric = counter as PerformanceMetric; valuePercentage = metric.ComputeMetric(counterSet, out long baseValue, out long relativeValue); // Don't show metrics for counters with few hits, // they tend to be the ones that are the most inaccurate. double metricBasePercentage = result.ScaleCounterValue(baseValue, metric.BaseCounter); if (metricBasePercentage > 0.01) { label = FormatPerformanceMetric(valuePercentage, metric); value = (long)(valuePercentage * 10000); isValueBasedMetric = !metric.Config.IsPercentage; tooltip = "Per instruction"; } else { valuePercentage = 0; } } else { value = counterSet.FindCounterValue(counter); if (value == 0) { continue; } valuePercentage = result.ScaleCounterValue(value, counter); label = valuePercentage.AsTrimmedPercentageString(); tooltip = FormatPerformanceCounter(value, counter); } //? TODO: Could have a config for all/per-counter to pick % or value as label //var label = $"{value * counter.Interval}"; var columnValue = new ElementColumnValue(label, value, valuePercentage, i, tooltip); columnValue.ValuePercentage = valuePercentage; columnValue.CanShowPercentageBar = !isValueBasedMetric && valuePercentage >= settings_.ElementWeightCutoff; columnData.AddValue(columnValue, element, counterColumns[k]); var counterValueList = counterSortMap[k]; counterValueList.Add(new CounterSortHelper(columnValue, value)); } } }); // Sort the counters from each column in decreasing order, // then assign the ValueOrder for each counter based on the sorting index. for (int k = 0; k < perfCounters.Count; k++) { var counterValueList = counterSortMap[k]; counterValueList.Sort((a, b) => -a.Value.CompareTo(b.Value)); for (int i = 0; i < counterValueList.Count; i++) { counterValueList[i].ColumnValue.ValueOrder = i; } } SetupColumnHeaderEvents(function, document, columnData); return columnData; } public void UpdateColumnStyles(IRDocumentColumnData columnData, FunctionIR function, IRDocument document) { document.SuspendUpdate(); foreach (var column in columnData.Columns) { UpdateColumnStyle(column, columnData, function, document, settings_, columnSettings_); } document.ResumeUpdate(); } private void SetupColumnHeaderEvents(FunctionIR function, IRDocument document, IRDocumentColumnData columnData) { foreach (var column in columnData.Columns) { column.HeaderClickHandler += ColumnHeaderClickHandler(document, function, columnData); } } private void CreatePerfCounterColumn(FunctionIR function, IRDocument document, IRDocumentColumnData columnData, List perfCounters, OptionalColumn[] counterColumns, int k) { var counterInfo = perfCounters[k]; counterColumns[k] = CounterColumnTemplate(counterInfo, k); counterColumns[k].IsVisible = IsPerfCounterVisible(counterInfo); counterColumns[k].PerformanceCounter = counterInfo; columnData.AddColumn(counterColumns[k]); } private OptionalColumnEventHandler ColumnHeaderClickHandler(IRDocument document, FunctionIR function, IRDocumentColumnData columnData) { return (column, columnHeader) => { var currentMainColumn = columnData.MainColumn; if (column == currentMainColumn) { return; } if (currentMainColumn != null) { currentMainColumn.IsMainColumn = false; UpdateColumnStyle(currentMainColumn, columnData, function, document, settings_, columnSettings_); } column.IsMainColumn = true; UpdateColumnStyle(column, columnData, function, document, settings_, columnSettings_); }; } private class DummyFunctionProfileInfoProvider : IFunctionProfileInfoProvider { public List GetBacktrace(ProfileCallTreeNode node) { return new List(); } public (List, List Modules) GetTopFunctionsAndModules( ProfileCallTreeNode node) { return new ValueTuple, List>(); } public List GetTopModules(ProfileCallTreeNode node) { return new List(); } } private struct CounterSortHelper { public ElementColumnValue ColumnValue; public long Value; public CounterSortHelper(ElementColumnValue columnValue, long value) { ColumnValue = columnValue; Value = value; } } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfileHistoryManager.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Profile; using ProfileExplorer.Core.Profile.Processing; namespace ProfileExplorer.UI; public class ProfileHistoryManager { private Stack prevFunctionsStack_; private Stack nextFunctionsStack_; private bool ignoreNextSaveFunctionState_; private Func saveStateHandler_; private Action stateChangeHandler_; public ProfileHistoryManager(Func saveStateHandler, Action stateChangeHandler) { prevFunctionsStack_ = new Stack(); nextFunctionsStack_ = new Stack(); saveStateHandler_ = saveStateHandler; stateChangeHandler_ = stateChangeHandler; } public bool HasNextStates => nextFunctionsStack_.Count > 0; public bool HasPreviousStates => prevFunctionsStack_.Count > 0; public Stack PreviousFunctions => prevFunctionsStack_; public Stack NextFunctions => nextFunctionsStack_; public void SaveCurrentState() { SaveCurrentFunctionState(prevFunctionsStack_); } public ProfileFunctionState PopPreviousState() { if (prevFunctionsStack_.Count == 0) { return null; } // Save current function in the forward history. var state = prevFunctionsStack_.Pop(); SaveCurrentFunctionState(nextFunctionsStack_); ignoreNextSaveFunctionState_ = true; stateChangeHandler_(); return state; } public ProfileFunctionState PopNextState() { if (nextFunctionsStack_.Count == 0) { return null; } // Save current function in the backward history. var state = nextFunctionsStack_.Pop(); SaveCurrentFunctionState(prevFunctionsStack_); ignoreNextSaveFunctionState_ = true; stateChangeHandler_(); return state; } private void SaveCurrentFunctionState(Stack stack) { if (ignoreNextSaveFunctionState_) { // Don't add to the history the function // from which the going back action was started. ignoreNextSaveFunctionState_ = false; } else { var state = saveStateHandler_(); if (state == null) { return; } // Don't duplicate the state. if (stack.Count == 0 || !stack.Peek().Equals(state)) { stack.Push(state); stateChangeHandler_(); } } } public void RevertToState(ProfileFunctionState state) { // Add the current state in the next stack, // plus all stats from the previous stack up to selected state. SaveCurrentFunctionState(nextFunctionsStack_); while (prevFunctionsStack_.Peek() != state) { var skippedState = prevFunctionsStack_.Pop(); nextFunctionsStack_.Push(skippedState); } prevFunctionsStack_.Pop(); ignoreNextSaveFunctionState_ = true; stateChangeHandler_(); } public void ClearPreviousStates() { prevFunctionsStack_.Clear(); } public void ClearNextStates() { nextFunctionsStack_.Clear(); } public void Reset() { prevFunctionsStack_.Clear(); nextFunctionsStack_.Clear(); ignoreNextSaveFunctionState_ = false; } } public class ProfileFunctionState { public ProfileFunctionState(IRTextSection section, FunctionIR function, ReadOnlyMemory text, ProfileSampleFilter profileFilter) { Section = section; Function = function; Text = text; ProfileFilter = profileFilter; } public IRTextSection Section { get; set; } public FunctionIR Function { get; set; } public ReadOnlyMemory Text { get; set; } public ProfileSampleFilter ProfileFilter { get; set; } public TimeSpan Weight { get; set; } public ParsedIRTextSection ParsedSection => new(Section, Text, Function); protected bool Equals(ProfileFunctionState other) { return Equals(Section, other.Section); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() != GetType()) return false; return Equals((ProfileFunctionState)obj); } public override int GetHashCode() { return Section != null ? Section.GetHashCode() : 0; } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfileIRDocument.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfileIRDocument.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Threading; using ICSharpCode.AvalonEdit.Folding; using ICSharpCode.AvalonEdit.Highlighting; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.SourceParser; using ProfileExplorer.UI.Document; using ProtoBuf; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Binary; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.CallTree; namespace ProfileExplorer.UI.Profile.Document; public partial class ProfileIRDocument : UserControl, INotifyPropertyChanged { private List<(IRElement, TimeSpan)> profileElements_; private int profileElementIndex_; private SourceLineProcessingResult sourceProcessingResult_; private SourceLineProfileResult sourceProfileResult_; private bool columnsVisible_; private bool ignoreNextCaretEvent_; private bool disableCaretEvent_; private bool selectedLines_; private ReadOnlyMemory originalSourceText_; private ReadOnlyMemory sourceText_; private bool hasProfileInfo_; private Brush selectedLineBrush_; private TextViewSettingsBase settings_; private ProfileDocumentMarker profileMarker_; private bool isPreviewDocument_; private bool isSourceFileDocument_; private ProfileSampleFilter profileFilter_; private CancelableTaskInstance loadTask_; private SourceCodeLanguage sourceLanguage_; private ProfileHistoryManager historyManager_; private RangeColorizer assemblyColorizer_; private SourceStackFrame inlinee_; private bool ignoreNextRowSelectedEvent_; private MenuItem[] viewMenuItems_; public ProfileIRDocument() { InitializeComponent(); UpdateDocumentStyle(); SetupEvents(); ShowPerformanceCounterColumns = true; ShowPerformanceMetricColumns = true; DataContext = this; loadTask_ = new CancelableTaskInstance(false); profileFilter_ = new ProfileSampleFilter(); historyManager_ = new ProfileHistoryManager(() => new ProfileFunctionState(TextView.Section, TextView.Function, TextView.SectionText, profileFilter_), () => { FunctionHistoryChanged?.Invoke(this, EventArgs.Empty); }); viewMenuItems_ = new[] { ViewMenuItem1, ViewMenuItem2, ViewMenuItem3 }; } public IUISession Session { get; set; } public IRTextSection Section => TextView.Section; public ProfileSampleFilter ProfileFilter { get => profileFilter_; set { if (value == null) { profileFilter_ = new ProfileSampleFilter(); } else { profileFilter_ = value.Clone(); // Clone to detect changes later. } UpdateProfileFilterUI(); ProfilingUtils.SyncInstancesMenuWithFilter(InstancesMenu, profileFilter_); ProfilingUtils.SyncThreadsMenuWithFilter(ThreadsMenu, profileFilter_); } } public bool HasProfileInfo { get => hasProfileInfo_; set => SetField(ref hasProfileInfo_, value); } public bool UseCompactProfilingColumns { get; set; } public bool ShowPerformanceCounterColumns { get; set; } public bool ShowPerformanceMetricColumns { get; set; } public bool UseSmallerFontSize { get => ProfileColumns.UseSmallerFontSize; set => ProfileColumns.UseSmallerFontSize = value; } public bool ColumnsVisible { get => columnsVisible_; set => SetField(ref columnsVisible_, value); } public bool IsPreviewDocument { get => isPreviewDocument_; set => SetField(ref isPreviewDocument_, value); } public bool IsSourceFileDocument { get => isSourceFileDocument_; set => SetField(ref isSourceFileDocument_, value); } public Brush SelectedLineBrush { get => selectedLineBrush_; set => SetField(ref selectedLineBrush_, value); } public bool HasPreviousFunctions => historyManager_.HasPreviousStates; public bool HasNextFunctions => historyManager_.HasNextStates; public bool HasProfileInstanceFilter => profileFilter_ is {HasInstanceFilter: true}; public bool HasProfileThreadFilter => profileFilter_ is {HasThreadFilter: true}; public RelayCommand CopyDocumentCommand => new(async obj => { await CopyAllLinesAsHtml(); }); public event PropertyChangedEventHandler PropertyChanged; private void SetupEvents() { TextView.CaretChanged += TextView_CaretChanged; TextView.TextArea.TextView.ScrollOffsetChanged += TextViewOnScrollOffsetChanged; TextView.TextArea.SelectionChanged += TextAreaOnSelectionChanged; ProfileColumns.ScrollChanged += ProfileColumns_ScrollChanged; ProfileColumns.RowSelected += ProfileColumns_RowSelected; TextView.TextRegionFolded += TextViewOnTextRegionFolded; TextView.TextRegionUnfolded += TextViewOnTextRegionUnfolded; TextView.PreviewMouseDown += TextView_PreviewMouseDown; TextView.PreviewMouseUp += TextView_PreviewMouseUp; TextView.FunctionCallOpen += TextViewOnFunctionCallOpen; PreviewKeyDown += TextView_PreviewKeyDown; Loaded += (sender, args) => { // Due to WPF layout update quirks, when the document is displayed // in a popup that was just created, redo some UI actions once loaded. if (TextView.IsLoaded) { if (settings_.ProfileMarkerSettings.JumpToHottestElement) { JumpToHottestProfiledElement(true); } TextView.Redraw(); } }; } private async void TextView_PreviewKeyDown(object sender, KeyEventArgs e) { if (e.Key == Key.Back) { if (Utils.IsKeyboardModifierActive()) { await LoadNextSection(); } else { await LoadPreviousSection(); } } else if (e.Key == Key.C && Utils.IsControlModifierActive()) { // Override Ctrl+C to copy instruction details instead of just text, // but not if Shift/Alt key is also pressed, copy plain text then. if (!Utils.IsAltModifierActive() && !Utils.IsShiftModifierActive() && !TextView.HandleOverlayKeyPress(e)) { // Send to overlays first. await CopySelectedLinesAsHtml(); e.Handled = true; } } else if (e.Key == Key.H && Utils.IsControlModifierActive()) { JumpToHottestProfiledElement(); } else if (e.Key == Key.F2) { if (Utils.IsShiftModifierActive()) { JumpToProfiledElement(1); } else { JumpToProfiledElement(-1); } } } private async void TextView_PreviewMouseDown(object sender, MouseButtonEventArgs e) { // Handle the back/forward mouse buttons // to navigate through the function history. if (e.ChangedButton == MouseButton.XButton1) { e.Handled = true; await LoadPreviousSection(); } else if (e.ChangedButton == MouseButton.XButton2) { e.Handled = true; await LoadNextSection(); } else if (e.ChangedButton == MouseButton.Left) { // Disable selecting the assembly lines associated with the source line // during a selection of multiple lines. disableCaretEvent_ = true; selectedLines_ = false; } } private async void TextView_PreviewMouseUp(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Left) { if (!selectedLines_) { // No multi-line selection was done, // select assembly lines associated with the source line. HighlightElementsOnSelectedLine(); } disableCaretEvent_ = false; selectedLines_ = false; } } public async Task LoadPreviousSection() { var state = historyManager_.PopPreviousState(); if (state != null) { await LoadPreviousSectionState(state); } } public async Task LoadNextSection() { var state = historyManager_.PopNextState(); if (state != null) { await LoadPreviousSectionState(state); } } private async Task LoadPreviousSectionState(ProfileFunctionState state) { await LoadAssembly(state.ParsedSection, state.ProfileFilter); } private async void TextViewOnFunctionCallOpen(object sender, IRTextSection targetSection) { var targetFunc = targetSection.ParentFunction; ProfileSampleFilter targetFilter = null; if (profileFilter_ is {IncludesAll: false}) { targetFilter = profileFilter_.CloneForCallTarget(targetFunc); } historyManager_.ClearNextStates(); // Reset forward history. var parsedSection = await Session.LoadAndParseSection(targetFunc.Sections[0]); if (parsedSection != null) { await LoadAssembly(parsedSection, targetFilter); } } public event EventHandler TitlePrefixChanged; public event EventHandler TitleSuffixChanged; public event EventHandler DescriptionPrefixChanged; public event EventHandler DescriptionSuffixChanged; public event EventHandler LoadedFunctionChanged; public event EventHandler LineSelected; public event EventHandler FunctionHistoryChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } public async Task LoadAssembly(ParsedIRTextSection parsedSection, ProfileSampleFilter profileFilter = null) { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (TextView.IsLoaded && !IsSourceFileDocument) { historyManager_.SaveCurrentState(); } ResetInstance(); IsSourceFileDocument = false; await TextView.LoadSection(parsedSection); // Apply profile filter if needed. ProfileFilter = profileFilter; bool success = true; if (!parsedSection.LoadFailed) { if (profileFilter is {IncludesAll: false}) { success = await LoadAssemblyProfileInstance(parsedSection); } else { success = await LoadAssemblyProfile(parsedSection); } } else { success = false; } if (!success) { await HideProfile(); return false; } LoadedFunctionChanged?.Invoke(this, parsedSection); return true; } private async Task HideProfile() { HasProfileInfo = false; ColumnsVisible = false; ResetProfilingMenus(); } private void ResetProfilingMenus() { DocumentUtils.RemoveNonDefaultMenuItems(ProfileElementsMenu); DocumentUtils.RemoveNonDefaultMenuItems(InstancesMenu); DocumentUtils.RemoveNonDefaultMenuItems(ThreadsMenu); DocumentUtils.RemoveNonDefaultMenuItems(InlineesMenu); } private async Task LoadAssemblyProfile(ParsedIRTextSection parsedSection, bool reloadFilterMenus = true) { var funcProfile = Session.ProfileData?.GetFunctionProfile(parsedSection.ParentFunction); if (funcProfile == null) { return false; } await MarkAssemblyProfile(parsedSection, funcProfile); CreateProfileElementMenus(funcProfile); if (reloadFilterMenus) { CreateProfileFilterMenus(parsedSection.Section, funcProfile); } return true; } private void CreateProfileElementMenus(FunctionProfileData funcProfile) { if (TextView.ProfileProcessingResult != null) { if (!isSourceFileDocument_) { var inlineeList = profileMarker_.GenerateInlineeList(TextView.ProfileProcessingResult); ProfilingUtils.CreateInlineesMenu(InlineesMenu, Section, inlineeList, funcProfile, InlineeMenuItem_OnClick, settings_, Session); } CreateProfileElementMenu(funcProfile, TextView.ProfileProcessingResult); } } private async Task LoadAssemblyProfileInstance(ParsedIRTextSection parsedSection, bool reloadFilterMenus = true) { UpdateProfileFilterUI(); var instanceProfile = await ComputeInstanceProfile(); var funcProfile = instanceProfile.GetFunctionProfile(parsedSection.ParentFunction); if (funcProfile == null) { return false; } await MarkAssemblyProfile(parsedSection, funcProfile); CreateProfileElementMenus(funcProfile); if (reloadFilterMenus) { CreateProfileFilterMenus(parsedSection.Section, funcProfile); } return true; } private async Task ComputeInstanceProfile() { return await LongRunningAction.Start( async () => await Task.Run(() => Session.ProfileData. ComputeProfile(Session.ProfileData, profileFilter_, false)), TimeSpan.FromMilliseconds(500), "Filtering function instance", this, Session); } private async Task LoadSourceFileProfileInstance(IRTextSection section, bool reloadFilterMenus = true, bool jumpToHottestLine = true) { UpdateProfileFilterUI(); var instanceProfile = await ComputeInstanceProfile(); var funcProfile = instanceProfile.GetFunctionProfile(section.ParentFunction); if (funcProfile == null) { return false; } if (!await MarkSourceFileProfile(section, funcProfile, jumpToHottestLine)) { return false; } CreateProfileElementMenus(funcProfile); if (reloadFilterMenus) { CreateProfileFilterMenus(section, funcProfile); } return true; } private async Task MarkAssemblyProfile(ParsedIRTextSection parsedSection, FunctionProfileData funcProfile) { ResetInstanceProfiling(); profileMarker_ = new ProfileDocumentMarker(funcProfile, Session.ProfileData, settings_.ProfileMarkerSettings, settings_.ColumnSettings, Session.CompilerInfo); await profileMarker_.Mark(TextView, parsedSection.Function, parsedSection.ParentFunction); if (settings_.ProfileMarkerSettings.JumpToHottestElement) { JumpToHottestProfiledElement(true); } UpdateProfileFilterUI(); UpdateProfileDescription(funcProfile); await UpdateProfilingColumns(); } private void UpdateProfileFilterUI() { OnPropertyChanged(nameof(HasProfileInstanceFilter)); OnPropertyChanged(nameof(HasProfileThreadFilter)); } private void UpdateProfileDescription(FunctionProfileData funcProfile) { DescriptionPrefixChanged?.Invoke(this, ProfilingUtils. CreateProfileFunctionDescription(funcProfile, settings_.ProfileMarkerSettings, Session)); TitlePrefixChanged?.Invoke(this, ProfilingUtils. CreateProfileFilterTitle(profileFilter_, Session)); DescriptionSuffixChanged?.Invoke(this, ProfilingUtils. CreateProfileFilterDescription(profileFilter_, Session)); } private string MakeSyntaxNodePreviewText(string text, int maxLength) { if (string.IsNullOrEmpty(text)) { return ""; } // Extract until either a new line or the max length is reached. int i = 0; while (i < text.Length && text[i] != '\n') { i++; } i = Math.Min(i, maxLength); if (i == 0) return null; if (i <= text.Length) { return text.Substring(0, i).Trim(); } else { return $"{text.Substring(0, i)}...".Trim(); } } private List PrepareSourceSyntaxTree(string sourceText, SourceLineProcessingResult sourceProcessingResult, SourceLineProfileResult sourceProfileResult, SourceCodeLanguage sourceLanguage) { var parser = new SourceCodeParser(sourceLanguage); var tree = parser.Parse(sourceText); if (tree == null) return null; var funcTreeNoe = tree.FindFunctionNode(sourceProcessingResult.FirstLineIndex); if (funcTreeNoe == null) { Trace.WriteLine($"Couldn't find function in the syntax tree at line {sourceProcessingResult.FirstLineIndex}"); return null; } // Trace.WriteLine("-------------------------------------------"); // Trace.WriteLine("Source Syntax Tree:"); // Trace.WriteLine($"{funcTreeNoe.Print()}"); var profileNodes = new List(); var profileNodeMap = new Dictionary(); funcTreeNoe.WalkNodes((node, depth) => { IRElement startElement = null; var weight = TimeSpan.Zero; var counters = new PerformanceCounterValueSet(); List elements = new(); // Collect the elements for the source lines that are part of the node // and accumulate the weight of the source lines. int startLine = node.Start.Line; int endLine = node.End.Line; // For if statements, the syntax node covers the line range // of any any other nested if/else statements, but here consider // only the lines in the "then" part of the if statement. if (node.Kind == SourceSyntaxNodeKind.If) { var elseNode = node.GetChildOfKind(SourceSyntaxNodeKind.Else); if (elseNode != null) { var thenNode = node.GetChildOfKind(SourceSyntaxNodeKind.Compound); if (thenNode != null) { endLine = thenNode.End.Line; node.End = thenNode.End; } else { endLine = elseNode.Start.Line; node.End = elseNode.Start; } } } // Accumulate profile values in range. for (int line = startLine; line <= endLine; line++) { int mappedLine = MapFromOriginalSourceLineNumber(line); if (sourceProfileResult.LineToElementMap.TryGetValue(mappedLine, out var element)) { startElement ??= element; elements.Add(element); if (sourceProcessingResult.SourceLineWeight.TryGetValue(line, out var w)) { weight += w; } if (sourceProcessingResult.SourceLineCounters.TryGetValue(line, out var c)) { counters.Add(c); } } } // Create a profile node for the syntax node, // except for nodes that are not interesting. ProfileSourceSyntaxNode profileNode = null; if (startElement != null && node.Kind != SourceSyntaxNodeKind.Compound && node.Kind != SourceSyntaxNodeKind.Condition && node.Kind != SourceSyntaxNodeKind.Other) { profileNode = new ProfileSourceSyntaxNode(node) { Weight = weight, Counters = counters, StartElement = startElement, Elements = elements }; // Connect node to the parent (because some nodes are skipped, // parent may not be the direct parent from the syntax tree). var parentNode = node.ParentNode; while (parentNode != null) { if (profileNodeMap.TryGetValue(parentNode, out var nodeParent)) { profileNode.Parent = nodeParent; profileNode.Level = nodeParent.Level + 1; break; } parentNode = parentNode.ParentNode; } profileNodes.Add(profileNode); profileNodeMap[node] = profileNode; } // Distinguish between the body and the whole statement // by recording the weight of the body part too. if (profileNode != null && node.ParentNode != null && profileNodeMap.TryGetValue(node.ParentNode, out var parent)) { if (node.ParentNode.Kind == SourceSyntaxNodeKind.If || node.ParentNode.Kind == SourceSyntaxNodeKind.ElseIf) { if (node.Kind == SourceSyntaxNodeKind.Condition) { parent.ConditionWeight = weight; parent.BodyWeight = parent.Weight - weight; } } if (node.ParentNode.Kind == SourceSyntaxNodeKind.Else) { // Replace an else { if } pair with an IfElse statement. if (node.Kind == SourceSyntaxNodeKind.If) { node.Kind = SourceSyntaxNodeKind.ElseIf; node.Start = node.ParentNode.Start; // Include the "else" text. profileNode.Level = parent.Level; profileNodeMap.Remove(node.ParentNode); profileNodes.Remove(parent); } } else if (node.ParentNode.Kind == SourceSyntaxNodeKind.Else) { if (node.Kind == SourceSyntaxNodeKind.Else) { parent.BodyWeight = weight; } } else if (node.ParentNode.Kind == SourceSyntaxNodeKind.Loop) { if (node.Kind == SourceSyntaxNodeKind.Condition) { parent.ConditionWeight = weight; } else if (node.Kind == SourceSyntaxNodeKind.Compound) { parent.BodyWeight = weight; } } } return true; }); return profileNodes; } private int MapFromOriginalSourceLineNumber(int line) { // Map from original line to adjusted line with assembly. if (sourceProfileResult_ != null) { if (sourceProfileResult_.OriginalLineToLineMap.TryGetValue(line, out int mappedLine)) { return mappedLine; } return -1; // Line is assembly. } return line; } private int MapToOriginalSourceLineNumber(int line) { // Map from original line to adjusted line with assembly. if (sourceProfileResult_ != null) { if (sourceProfileResult_.LineToOriginalLineMap.TryGetValue(line, out int mappedLine)) { return mappedLine; } return -1; // Line is assembly. } return line; } public async Task LoadSourceFile(SourceFileDebugInfo sourceInfo, IRTextSection section, ProfileSampleFilter profileFilter = null, SourceStackFrame inlinee = null, SourceFileState previousState = null) { try { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); ResetInstance(); IsSourceFileDocument = true; string text = await File.ReadAllTextAsync(sourceInfo.FilePath); SetSourceText(text, sourceInfo.FilePath); // Apply profile filter if needed. ProfileFilter = profileFilter; inlinee_ = inlinee; ignoreNextCaretEvent_ = true; bool success = true; // When applying profile, jump to hottest line // only if the vertical offset is 0. double horizontalOffset = 0; double verticalOffset = 0; if (previousState != null) { horizontalOffset = previousState.HorizontalOffset; verticalOffset = previousState.VerticalOffset; } bool jumpToHottestLine = verticalOffset < double.Epsilon; if (profileFilter is {IncludesAll: false}) { success = await LoadSourceFileProfileInstance(section); } else { success = await LoadSourceFileProfile(section, true, jumpToHottestLine); } if (!success) { await HideProfile(); return true; // Only profile part failed, keep text. } //? TODO: Is panel is not visible, scroll doesn't do anything, //? should be executed again when panel is activated. if (previousState != null && !jumpToHottestLine) { if (previousState.AssemblyFoldingStates != null) { RestoreFoldingsState(previousState.AssemblyFoldingStates); } Dispatcher.BeginInvoke(() => { TextView.ScrollToHorizontalOffset(horizontalOffset); TextView.ScrollToVerticalOffset(verticalOffset); }, DispatcherPriority.Render); } else if (!settings_.ProfileMarkerSettings.JumpToHottestElement) { (int firstSourceLineIndex, int lastSourceLineIndex) = await DocumentUtils.FindFunctionSourceLineRange(section.ParentFunction, TextView); if (firstSourceLineIndex != 0) { SelectLine(firstSourceLineIndex); } } return true; } catch (Exception ex) { Trace.TraceError($"Failed to load source file {sourceInfo.FilePath}: {ex.Message}"); Trace.TraceError(ex.StackTrace); Trace.Flush(); return false; } } public async Task HandleMissingSourceFile(string failureText) { string text = "Failed to load source file."; if (!string.IsNullOrEmpty(failureText)) { text += $"\n{failureText}"; } TextView.UnloadDocument(); SetSourceText(text, ""); await HideProfile(); } private async Task LoadSourceFileProfile(IRTextSection section, bool reloadFilterMenus = true, bool jumpToHottestLine = true) { var funcProfile = Session.ProfileData?.GetFunctionProfile(section.ParentFunction); if (funcProfile == null) { return false; } if (!await MarkSourceFileProfile(section, funcProfile, jumpToHottestLine)) { return false; } if (reloadFilterMenus) { CreateProfileFilterMenus(section, funcProfile); } return true; } private void CreateProfileFilterMenus(IRTextSection section, FunctionProfileData funcProfile) { ProfilingUtils.CreateInstancesMenu(InstancesMenu, section, funcProfile, InstanceMenuItem_OnClick, InstanceMenuItem_OnRightClick, settings_, Session); ProfilingUtils.CreateThreadsMenu(ThreadsMenu, section, funcProfile, ThreadMenuItem_OnClick, settings_, Session); ProfilingUtils.SyncInstancesMenuWithFilter(InstancesMenu, profileFilter_); ProfilingUtils.SyncThreadsMenuWithFilter(ThreadsMenu, profileFilter_); } private async Task MarkSourceFileProfile(IRTextSection section, FunctionProfileData funcProfile, bool jumpToHottestLine = true) { ResetInstanceProfiling(); profileMarker_ = new ProfileDocumentMarker(funcProfile, Session.ProfileData, settings_.ProfileMarkerSettings, settings_.ColumnSettings, Session.CompilerInfo); // Accumulate the instruction weight for each source line. var sourceLineProfileResult = await Task.Run(async () => { var debugInfo = await Session.GetDebugInfoProvider(section.ParentFunction).ConfigureAwait(false); return funcProfile.ProcessSourceLines(debugInfo, Session.CompilerInfo.IR, inlinee_); }); // Clear markers when switching between ASM/source modes. if (TextView.IsLoaded) { TextView.ClearInstructionMarkers(); } // Insert assembly lines corresponding to each source code line, // grouped as a code folding that can be hidden. bool showAssemblyLines = ((SourceFileSettings)settings_).ShowInlineAssembly; bool showSourceStatements = ((SourceFileSettings)settings_).ShowSourceStatements; ParsedIRTextSection parsedSection = null; if (showAssemblyLines) { // In case of changing the instance, start again from // the original source code text when inserting the assembly lines. TextView.Text = originalSourceText_.ToString(); sourceText_ = originalSourceText_; parsedSection = await Session.LoadAndParseSection(section); } // Create a dummy FunctionIR that has fake tuples representing each // source line, with the profiling data attached to the tuples. var processingResult = await profileMarker_. PrepareSourceLineProfile(funcProfile, TextView, sourceLineProfileResult, parsedSection); if (processingResult == null) { return false; } sourceProcessingResult_ = sourceLineProfileResult; sourceProfileResult_ = processingResult; // Parse the source code to get the syntax tree nodes. List syntaxNodes = null; if (showSourceStatements) { syntaxNodes = await Task.Run(() => PrepareSourceSyntaxTree(sourceText_.ToString(), sourceLineProfileResult, processingResult, sourceLanguage_)); } // Replace the text after the assembly lines were inserted. if (showAssemblyLines) { sourceText_ = TextView.Text.AsMemory(); } // Load the dummy section with the source lines. var dummyParsedSection = new ParsedIRTextSection(section, sourceText_, processingResult.Function); await TextView.LoadSection(dummyParsedSection, true); CreateProfileElementMenus(funcProfile); // Annotate the source lines with the profiling data based on the code statements. if (syntaxNodes != null) { await MarkSourceFileStructure(syntaxNodes, processingResult, originalSourceText_, section.ParentFunction); } TextView.SuspendUpdate(); await profileMarker_.MarkSourceLines(TextView, processingResult); // Annotate call sites next to source lines by parsing the actual section // and mapping back the call sites to the dummy elements representing the source lines. if (parsedSection != null) { profileMarker_.MarkCallSites(TextView, parsedSection.Function, section.ParentFunction, processingResult); } TextView.ResumeUpdate(); if (syntaxNodes != null) { PatchSourceStructureRows(syntaxNodes, funcProfile); } if (jumpToHottestLine && settings_.ProfileMarkerSettings.JumpToHottestElement) { JumpToHottestProfiledElement(true); } UpdateProfileFilterUI(); UpdateProfileDescription(funcProfile); await UpdateProfilingColumns(); if (showAssemblyLines) { SetupSourceAssembly(processingResult); } return true; } private async Task MarkSourceFileStructure(List nodes, SourceLineProfileResult sourceProfileResult, ReadOnlyMemory sourceText, IRTextFunction function) { var profileItems = new List(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings_.ProfileMarkerSettings; var funcProfile = Session.ProfileData.GetFunctionProfile(function); double maxWidth = 0; OutlineMenu.Items.Clear(); foreach (var node in nodes) { MarkSourceSyntaxNode(node, sourceProfileResult, funcProfile, markerSettings); // Build outline menu. double weightPercentage = funcProfile.ScaleWeight(node.Weight); if (!markerSettings.IsVisibleValue(weightPercentage)) { continue; } // Append | chars for alignment based on node level. string nesting = ""; for (int i = 0; i < node.Level - 1; i++) { nesting += " \u250A "; } int CountDigits(int number) { int count = 1; while (number >= 10) { count++; number /= 10; } return count; } // Append node start line number. string line = node.Kind != SourceSyntaxNodeKind.Function ? node.Start.Line.ToString() : ""; line = line.PadRight(CountDigits(TextView.LineCount)); string nodeText = null; if (node.SyntaxNode.Kind == SourceSyntaxNodeKind.Function) { nodeText = function.FormatFunctionName(Session); } else { nodeText = node.SyntaxNode.GetText(sourceText); } string preview = MakeSyntaxNodePreviewText(nodeText, 50); string title = $"{line} {nesting}{node.GetTextIcon()} {preview}"; string tooltip = nodeText; string nodeTitle = $"({markerSettings.FormatWeightValue(node.Weight)})"; var value = new ProfileMenuItem(nodeTitle, node.Weight.Ticks, weightPercentage) { PrefixText = title, ToolTip = tooltip, ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = node.Kind != SourceSyntaxNodeKind.Function ? markerSettings.PickTextWeight(weightPercentage) : FontWeights.Normal, PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; node.SetTextStyle(value); var item = new MenuItem { Tag = node, Header = value, IsEnabled = node.Kind != SourceSyntaxNodeKind.Function, HeaderTemplate = valueTemplate, Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }; // Set mouse events for jump and hover. item.Click += (sender, args) => { if (sender is MenuItem menuItem && menuItem.Tag is ProfileSourceSyntaxNode syntaxNode) { TextView.SelectLine(syntaxNode.StartElement.TextLocation.Line + 1); } }; item.MouseEnter += (sender, args) => { if (sender is MenuItem menuItem && menuItem.Tag is ProfileSourceSyntaxNode syntaxNode) { SelectSyntaxNodeLineRange(syntaxNode); } }; item.MouseLeave += (sender, args) => { TextView.ClearSelectedElements(); }; profileItems.Add(value); OutlineMenu.Items.Add(item); double width = Utils.MeasureString(title, settings_.FontName, settings_.FontSize).Width; maxWidth = Math.Max(width, maxWidth); } foreach (var value in profileItems) { value.MinTextWidth = maxWidth; } } private void MarkSourceSyntaxNode(ProfileSourceSyntaxNode node, SourceLineProfileResult sourceProfileResult, FunctionProfileData funcProfile, ProfileDocumentMarkerSettings markerSettings) { if (!node.IsMarkedNode || node.StartElement == null) return; // Show statement time in the columns, but only if // it doesn't replace a large enough value already associated with the line. int existingIndex = sourceProfileResult.Result.SampledElements.FindIndex((item) => item.Item1 == node.StartElement); bool replaceOnlyInsignificant = ((SourceFileSettings)settings_).ReplaceInsignificantSourceStatements; bool failedReplaceAttempt = false; bool mark = true; if (existingIndex != -1) { var existingWeight = sourceProfileResult.Result.SampledElements[existingIndex].Item2; double existingWeightPercentage = funcProfile.ScaleWeight(existingWeight); mark = !replaceOnlyInsignificant || // Always replace. !markerSettings.IsVisibleValue(existingWeightPercentage, 2.0); failedReplaceAttempt = !mark; if (mark) { sourceProfileResult.Result.SampledElements.RemoveAt(existingIndex); sourceProfileResult.Result.CounterElements.RemoveAll((item) => item.Item1 == node.StartElement); } } if (mark) { node.ShowInDocumentColumns = true; sourceProfileResult.Result.SampledElements.Add((node.StartElement, node.Weight)); if (node.Counters is {Count: > 0}) { sourceProfileResult.Result.CounterElements.Add((node.StartElement, node.Counters)); } } bool showStatementOverlays = ((SourceFileSettings)settings_).ShowSourceStatementsOnMargin; if (showStatementOverlays || failedReplaceAttempt && replaceOnlyInsignificant) { CreateFileStructureOverlay(node, funcProfile, markerSettings); } } private void CreateFileStructureOverlay(ProfileSourceSyntaxNode node, FunctionProfileData funcProfile, ProfileDocumentMarkerSettings markerSettings) { double weightPercentage = funcProfile.ScaleWeight(node.Weight); var color = App.Settings.DocumentSettings.BackgroundColor; if (node.StartElement.ParentBlock != null && !node.StartElement.ParentBlock.HasEvenIndexInFunction) { color = App.Settings.DocumentSettings.AlternateBackgroundColor; } string label = $"{node.GetKindText()}: {weightPercentage.AsPercentageString()} ({node.Weight.AsMillisecondsString()})"; string overalyTooltip = node.GetTooltip(funcProfile); var overlay = TextView.RegisterIconElementOverlay(node.StartElement, node.GetIcon(), 16, 16, label, overalyTooltip, true); overlay.Tag = node; overlay.Background = color.AsBrush(); overlay.IsLabelPinned = false; overlay.AllowLabelEditing = false; overlay.UseLabelBackground = true; overlay.ShowBackgroundOnMouseOverOnly = true; overlay.ShowBorderOnMouseOverOnly = true; overlay.AlignmentX = HorizontalAlignment.Left; overlay.MarginY = 2; (overlay.TextColor, overlay.TextWeight) = markerSettings.PickBlockOverlayStyle(weightPercentage); overlay.OnHover += (s, e) => { if (node.Elements != null) { SelectSyntaxNodeLineRange(node); } }; overlay.OnHoverEnd += (sender, args) => { TextView.ClearSelectedElements(); }; if (node.StartElement is InstructionIR instr) { // Place before the call opcode. int lineOffset = instr.OpcodeLocation.Offset - instr.TextLocation.Offset; overlay.MarginX = Utils.MeasureString(lineOffset, Utils.GetTextTypeface(TextView), TextView.FontSize).Width - 20; } } private void PatchSourceStructureRows(List nodes, FunctionProfileData funcProfile) { // Override icons and tooltips for each row that corresponds // to a source code statement like for/if. var sourceColumnData = TextView.ProfileColumnData; if (sourceColumnData.GetColumn(ProfileDocumentMarker.TimePercentageColumnDefinition) is var timeColumn) { foreach (var node in nodes) { if (node.StartElement == null || !node.IsMarkedNode || !node.ShowInDocumentColumns) { continue; } var row = sourceColumnData.GetValues(node.StartElement); if (row == null) continue; foreach (var pair in row.ColumnValues) { bool showIcon = Equals(pair.Key, timeColumn); var cell = pair.Value; if (showIcon) { // Override default icon. cell.Icon = node.GetIcon()?.Icon; } cell.CanShowIcon = false; // Disable auto-icon. cell.ToolTip = node.GetTooltip(funcProfile); cell.CanShowPercentageBar = false; cell.CanShowBackgroundColor = false; row.Tag = node; } } } // Select statement line range when hovering over the column cell. ProfileColumns.RowHoverStart += (sender, value) => { if (value.Tag is ProfileSourceSyntaxNode node) { SelectSyntaxNodeLineRange(node); } }; ProfileColumns.RowHoverStop += (sender, value) => { TextView.ClearSelectedElements(); }; } private void SelectSyntaxNodeLineRange(ProfileSourceSyntaxNode node) { var selectionColor = ColorBrushes.GetTransparentBrush(settings_.SelectedValueColor, 0.5); TextView.SelectElementsInLineRange(node.Start.Line, node.End.Line, MapFromOriginalSourceLineNumber); } private void SetupSourceAssembly(SourceLineProfileResult processingResult) { // Replace the default line number left margin with one // that doesn't number the assembly lines, to keep same line numbers // with the original source file. var lineNumbers = new SourceLineNumberMargin(TextView, processingResult); TextView.SetupCustomLineNumbers(lineNumbers); // Create the block foldings for each source line and its assembly section. bool defaultClosed = !((SourceFileSettings)settings_).AutoExpandInlineAssembly; SetupSourceAssemblyFolding(defaultClosed); // Change the text color of the assembly section to be the same // (the source syntax highlighting may mark some ASM opcodes for ex). var asmFont = new Typeface(TextView.FontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal); assemblyColorizer_ = new RangeColorizer(processingResult.AssemblyRanges, ((SourceFileSettings)settings_).AssemblyTextColor.AsBrush(), ((SourceFileSettings)settings_).AssemblyBackColor.AsBrush(), asmFont); TextView.RegisterTextTransformer(assemblyColorizer_); } private void SetupSourceAssemblyFolding(bool defaultClosed) { FoldingElementGenerator.TextBrush = ColorBrushes.Transparent; var foldingStrategy = new RangeFoldingStrategy(sourceProfileResult_.AssemblyRanges, defaultClosed); var foldings = TextView.SetupCustomBlockFolding(foldingStrategy); // Sync the initial folding status in the columns with the document. ProfileColumns.SetupFoldedTextRegions(foldings); } private List SaveFoldingsState() { var foldings = TextView.BlockFoldings; var list = new List(); if (foldings != null) { foreach (var folding in foldings) { list.Add(folding.IsFolded); } } return list; } private void RestoreFoldingsState(List foldingStates) { var foldings = TextView.BlockFoldings; if (foldings == null) { return; } int index = 0; foreach (var folding in foldings) { if (index == foldingStates.Count) { break; } folding.IsFolded = foldingStates[index]; index++; } // Sync the initial folding status in the columns with the document. ProfileColumns.SetupFoldedTextRegions(foldings); } public void SaveSectionState(IToolPanel panel) { var state = new SourceFileState { HorizontalOffset = TextView.HorizontalOffset, VerticalOffset = TextView.VerticalOffset, AssemblyFoldingStates = SaveFoldingsState() }; byte[] data = UIStateSerializer.Serialize(state); Session.SavePanelState(data, panel, Section); } private async Task ApplyProfileFilter() { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); if (isSourceFileDocument_) { if (profileFilter_ is {IncludesAll: false}) { await LoadSourceFileProfileInstance(TextView.Section, false); } else { await LoadSourceFileProfile(TextView.Section, false); } } else { var parsedSection = new ParsedIRTextSection(TextView.Section, TextView.SectionText, TextView.Function); if (profileFilter_ is {IncludesAll: false}) { await LoadAssemblyProfileInstance(parsedSection, false); } else { await LoadAssemblyProfile(parsedSection, false); } } } private async Task UpdateProfilingColumns() { var sourceColumnData = TextView.ProfileColumnData; ColumnsVisible = sourceColumnData is {HasData: true}; if (ColumnsVisible) { if (UseCompactProfilingColumns) { // Use compact mode that shows only the time column. if (sourceColumnData.GetColumn(ProfileDocumentMarker.TimeColumnDefinition) is var timeColumn) { timeColumn.Style.ShowIcon = OptionalColumnStyle.PartVisibility.Never; } if (sourceColumnData.GetColumn(ProfileDocumentMarker.TimePercentageColumnDefinition) is var timePercColumn) { timePercColumn.IsVisible = false; } } // Hide perf counter columns. if (!ShowPerformanceCounterColumns || !ShowPerformanceMetricColumns) { foreach (var column in sourceColumnData.Columns) { if (!ShowPerformanceCounterColumns && column.IsPerformanceCounter || !ShowPerformanceMetricColumns && column.IsPerformanceMetric) { column.IsVisible = false; } } } ResetViewMenuItemEvents(); ProfileColumns.Reset(); ProfileColumns.Settings = settings_; ProfileColumns.ColumnSettings = settings_.ColumnSettings; await ProfileColumns.Display(sourceColumnData, TextView); profileMarker_.UpdateColumnStyles(sourceColumnData, TextView.Function, TextView); ProfileColumns.UpdateColumnWidths(); profileElements_ = TextView.ProfileProcessingResult.SampledElements; UpdateHighlighting(); // Add the columns to the View menu. ProfileColumns.BuildColumnsVisibilityMenu(sourceColumnData, ProfileViewMenu, async () => { await UpdateProfilingColumns(); }); SetViewMenuItemEvents(); } else { ProfileColumns.Reset(); } HasProfileInfo = true; } private void SetViewMenuItemEvents() { foreach (var item in viewMenuItems_) { item.Checked += ViewMenuItem_OnCheckedChanged; item.Unchecked += ViewMenuItem_OnCheckedChanged; } } private void ResetViewMenuItemEvents() { foreach (var item in viewMenuItems_) { item.Checked -= ViewMenuItem_OnCheckedChanged; item.Unchecked -= ViewMenuItem_OnCheckedChanged; } } private void CreateProfileElementMenu(FunctionProfileData funcProfile, FunctionProcessingResult result) { var list = new List(result.SampledElements.Count); double maxWidth = 0; ProfileElementsMenu.Items.Clear(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings_.ProfileMarkerSettings; int order = 0; int index = 0; foreach (var (element, weight) in result.SampledElements) { // For source files, don't include assembly line elements. if (isSourceFileDocument_ && !IsSourceLine(element.TextLocation.Line + 1)) { index++; continue; } double weightPercentage = funcProfile.ScaleWeight(weight); if (!markerSettings.IsVisibleValue(order++, weightPercentage)) { break; } string text = $"({markerSettings.FormatWeightValue(weight)})"; string prefixText; if (isSourceFileDocument_) { prefixText = element.GetText(TextView.SectionText).ToString(); prefixText = prefixText.Trim().TrimToLength(80); } else { prefixText = DocumentUtils.GenerateElementPreviewText(element, TextView.SectionText, 50); } int line = MapToOriginalSourceLineNumber(element.TextLocation.Line + 1); var value = new ProfileMenuItem(text, weight.Ticks, weightPercentage) { Element = element, PrefixText = prefixText, ToolTip = $"Line {line}", ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, Tag = index, HeaderTemplate = valueTemplate }; item.Click += (sender, args) => { var menuItem = (MenuItem)sender; JumpToProfiledElementAt((int)menuItem.Tag); }; ProfileElementsMenu.Items.Add(item); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(prefixText, ref maxWidth, ProfileElementsMenu); list.Add(value); index++; } foreach (var value in list) { value.MinTextWidth = maxWidth; } } public void SetSourceText(string text, string filePath) { disableCaretEvent_ = true; // Changing the text triggers the caret event twice. IHighlightingDefinition highlightingDef = null; switch (Utils.GetFileExtension(filePath).ToLowerInvariant()) { case ".c": case ".cpp": case ".cxx": case ".c++": case ".cc": case ".cp": case ".h": case ".hh": case ".hpp": case ".hxx": case ".inl": case ".ixx": { highlightingDef = HighlightingManager.Instance.GetDefinition("C++"); sourceLanguage_ = SourceCodeLanguage.Cpp; break; } case ".cs": { highlightingDef = HighlightingManager.Instance.GetDefinition("C#"); sourceLanguage_ = SourceCodeLanguage.CSharp; break; } case ".rs": { //? TODO: Rust syntax highlighting highlightingDef = HighlightingManager.Instance.GetDefinition("C++"); sourceLanguage_ = SourceCodeLanguage.Rust; break; } } TextView.Text = text; TextView.SyntaxHighlighting = highlightingDef; sourceText_ = text.AsMemory(); originalSourceText_ = sourceText_; disableCaretEvent_ = false; } private void ProfileColumns_ScrollChanged(object sender, ScrollChangedEventArgs e) { if (Math.Abs(e.VerticalChange) < double.Epsilon) { return; } TextView.ScrollToVerticalOffset(e.VerticalOffset); } private void UpdateDocumentStyle() { var settings = App.Settings.DocumentSettings; TextView.Background = ColorBrushes.GetBrush(settings.BackgroundColor); TextView.Foreground = ColorBrushes.GetBrush(settings.TextColor); TextView.FontFamily = new FontFamily(settings.FontName); TextView.FontSize = settings.FontSize; } private void JumpToProfiledElementExecuted(object sender, ExecutedRoutedEventArgs e) { if (!HasProfileElements()) { return; } profileElementIndex_ = 0; JumpToProfiledElement(profileElements_[profileElementIndex_].Item1); } private bool HasProfileElements() { return ColumnsVisible && profileElements_ is {Count: > 0}; } private bool HasProfileElement(int offset) { return ColumnsVisible && profileElements_ != null && profileElementIndex_ + offset >= 0 && profileElementIndex_ + offset < profileElements_.Count; } private void JumpToNextProfiledElementExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToProfiledElement(-1); } private void JumpToPreviousProfiledElementExecuted(object sender, ExecutedRoutedEventArgs e) { JumpToProfiledElement(1); } public void JumpToHottestProfiledElement(bool onLoad = false) { Dispatcher.BeginInvoke(() => { if (onLoad) { // Don't select the associated document instructions // when jumping during the source file load. ignoreNextCaretEvent_ = true; } JumpToProfiledElement(0); }, DispatcherPriority.Background); } private void JumpToProfiledElement(int offset) { if (!HasProfileElement(offset)) { return; } profileElementIndex_ += offset; JumpToProfiledElement(profileElements_[profileElementIndex_].Item1); } private void JumpToProfiledElement(IRElement element) { TextView.SetCaretAtElement(element); double offset = TextView.TextArea.TextView.VerticalOffset; SyncColumnsVerticalScrollOffset(offset); } private void JumpToProfiledElementAt(int index) { profileElementIndex_ = index; JumpToProfiledElement(0); } private void JumpToNextProfiledElementCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = HasProfileElement(-1); } private void JumpToPreviousProfiledElementCanExecute(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = HasProfileElement(1); } private void TextView_CaretChanged(object sender, int e) { if (!TextView.IsLoaded) { return; // Event still triggered when unloading document, ignore. } if (columnsVisible_) { ignoreNextRowSelectedEvent_ = true; var line = TextView.Document.GetLineByOffset(TextView.TextArea.Caret.Offset); ProfileColumns.SelectRow(line.LineNumber - 1); } if (ignoreNextCaretEvent_) { ignoreNextCaretEvent_ = false; return; } if (disableCaretEvent_) { return; } HighlightElementsOnSelectedLine(); } private void HighlightElementsOnSelectedLine() { var line = TextView.Document.GetLineByOffset(TextView.CaretOffset); if (line != null) { // With assembly lines, source line numbers are shifted. if (sourceProfileResult_ != null) { if (sourceProfileResult_.LineToOriginalLineMap. TryGetValue(line.LineNumber, out int originalLineNumber)) { LineSelected?.Invoke(this, originalLineNumber); } return; // One of the assembly lines, ignore. } LineSelected?.Invoke(this, line.LineNumber); } } public void SelectLine(int line) { ignoreNextCaretEvent_ = true; int mappedLine = MapFromOriginalSourceLineNumber(line); if (mappedLine != -1) { TextView.SelectLine(mappedLine); } } private bool IsSourceLine(int line) { return sourceProfileResult_ == null || sourceProfileResult_.LineToOriginalLineMap.ContainsKey(line); } public async Task Reset() { using var task = await loadTask_.CancelCurrentAndCreateTaskAsync(); ResetProfilingMenus(); ResetInstance(); ProfileFilter = new ProfileSampleFilter(); historyManager_.Reset(); originalSourceText_ = null; } private void ResetInstance() { ResetInstanceProfiling(); TextView.UnloadDocument(); sourceText_ = null; inlinee_ = null; } private void ResetInstanceProfiling() { ProfileColumns.Reset(); profileElements_ = null; sourceProcessingResult_ = null; sourceProfileResult_ = null; if (assemblyColorizer_ != null) { TextView.UnregisterTextTransformer(assemblyColorizer_); TextView.UninstallBlockFolding(); assemblyColorizer_ = null; } } private void TextViewOnScrollOffsetChanged(object? sender, EventArgs e) { // Sync scrolling with the optional columns. double offset = TextView.TextArea.TextView.VerticalOffset; SyncColumnsVerticalScrollOffset(offset); } private void SyncColumnsVerticalScrollOffset(double offset) { // Sync scrolling with the optional columns. if (columnsVisible_) { ProfileColumns.ScrollToVerticalOffset(offset); } } private void UpdateHighlighting() { TextView.TextArea.TextView.Redraw(); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } public async Task ReloadSettings() { Initialize(settings_); await UpdateProfilingColumns(); } public void Initialize(TextViewSettingsBase settings) { settings_ = settings; Background = settings_.BackgroundColor.AsBrush(); ProfileViewMenu.DataContext = settings_.ColumnSettings; TextView.Initialize(settings, Session); TextView.FontFamily = new FontFamily(settings_.FontName); if (settings_ is SourceFileSettings sourceSettings && !sourceSettings.ShowInlineAssembly) { TextView.UninstallCustomLineNumbers(true); } if (UseSmallerFontSize) { TextView.FontSize = settings_.FontSize - 1; } else { TextView.FontSize = settings_.FontSize; } } private async void ViewMenuItem_OnCheckedChanged(object sender, RoutedEventArgs e) { await UpdateProfilingColumns(); } private async void ExportSourceExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the source file/function failed to load. } if (isSourceFileDocument_) { await DocumentExporting.ExportSourceToExcelFile(TextView, MapToOriginalSourceLineNumber, MapFromOriginalSourceLineNumber); } else { await DocumentExporting.ExportToExcelFile(TextView, DocumentExporting.ExportFunctionAsHtmlFile); } } private async void ExportSourceHtmlExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the source file/function failed to load. } if (isSourceFileDocument_) { await DocumentExporting.ExportSourceToHtmlFile(TextView, MapToOriginalSourceLineNumber, MapFromOriginalSourceLineNumber); } else { await DocumentExporting.ExportToHtmlFile(TextView, DocumentExporting.ExportFunctionAsHtmlFile); } } private async void ExportSourceMarkdownExecuted(object sender, ExecutedRoutedEventArgs e) { if (!TextView.IsLoaded) { return; // Happens when the source file/function failed to load. } if (isSourceFileDocument_) { await DocumentExporting.ExportSourceToMarkdownFile(TextView, MapToOriginalSourceLineNumber, MapFromOriginalSourceLineNumber); } else { await DocumentExporting.ExportToMarkdownFile(TextView, DocumentExporting.ExportFunctionAsMarkdownFile); } } private async void CopySelectedLinesAsHtmlExecuted(object sender, ExecutedRoutedEventArgs e) { await CopySelectedLinesAsHtml(); } public async Task CopySelectedLinesAsHtml() { if (!TextView.IsLoaded) { return; // Happens when the source file/function failed to load. } if (isSourceFileDocument_) { await DocumentExporting.CopySelectedSourceLinesAsHtml(TextView, MapToOriginalSourceLineNumber, MapFromOriginalSourceLineNumber); } else { await DocumentExporting.CopySelectedLinesAsHtml(TextView); } } public async Task CopyAllLinesAsHtml() { if (!TextView.IsLoaded) { return; // Happens when the source file/function failed to load. } if (isSourceFileDocument_) { await DocumentExporting.CopyAllSourceLinesAsHtml(TextView, MapToOriginalSourceLineNumber, MapFromOriginalSourceLineNumber); } else { await DocumentExporting.CopyAllLinesAsHtml(TextView); } } private async void InstanceMenuItem_OnClick(object sender, RoutedEventArgs e) { ProfilingUtils.HandleInstanceMenuItemChanged(sender as MenuItem, InstancesMenu, profileFilter_); await ApplyProfileFilter(); } private void InstanceMenuItem_OnRightClick(object sender, MouseButtonEventArgs e) { if (sender is MenuItem menuItem) { if (menuItem.Tag is ProfileCallTreeNode node) { Session.SelectProfileFunctionInPanel(node, ToolPanelKind.FlameGraph); Session.SelectProfileFunctionInPanel(node, ToolPanelKind.CallTree); e.Handled = true; } } } private async void ThreadMenuItem_OnClick(object sender, RoutedEventArgs e) { ProfilingUtils.HandleThreadMenuItemChanged(sender as MenuItem, ThreadsMenu, profileFilter_); await ApplyProfileFilter(); } private void ProfileColumns_RowSelected(object sender, int line) { if (ignoreNextRowSelectedEvent_) { ignoreNextRowSelectedEvent_ = false; return; } TextView.SelectLine(line + 1); } private void TextAreaOnSelectionChanged(object sender, EventArgs e) { if (Section == null) { return; // Nothing loaded, ignore. } // For source files, compute the sum of the selected lines time. int startLine = TextView.TextArea.Selection.StartPosition.Line; int endLine = TextView.TextArea.Selection.EndPosition.Line; var funcProfile = Session.ProfileData?.GetFunctionProfile(Section.ParentFunction); if (sourceProcessingResult_ == null) { if (funcProfile == null || !ProfilingUtils.ComputeAssemblyWeightInRange(startLine, endLine, TextView.Function, funcProfile, out var weightSum, out int count)) { Session.SetApplicationStatus(""); return; } double weightPercentage = funcProfile.ScaleWeight(weightSum); string text = $"Selected {count}: {weightPercentage.AsPercentageString()} ({weightSum.AsMillisecondsString()})"; Session.SetApplicationStatus(text, "Sum of time for the selected instructions"); selectedLines_ = true; } else { if (funcProfile == null || !ProfilingUtils.ComputeSourceWeightInRange(startLine, endLine, sourceProcessingResult_, sourceProfileResult_, out var weightSum, out int count)) { Session.SetApplicationStatus(""); return; } double weightPercentage = funcProfile.ScaleWeight(weightSum); string text = $"Selected {count}: {weightPercentage.AsPercentageString()} ({weightSum.AsMillisecondsString()})"; Session.SetApplicationStatus(text, "Sum of time for the selected source lines"); selectedLines_ = true; } } private void TextViewOnTextRegionUnfolded(object sender, FoldingSection e) { ProfileColumns.HandleTextRegionUnfolded(e); } private void TextViewOnTextRegionFolded(object sender, FoldingSection e) { ProfileColumns.HandleTextRegionFolded(e); } public async Task SwitchProfileInstanceAsync(ProfileSampleFilter instanceFilter) { ProfileFilter = instanceFilter; await ApplyProfileFilter(); } private async void InlineeMenuItem_OnClick(object sender, RoutedEventArgs e) { var inlinee = ((MenuItem)sender)?.Tag as InlineeListItem; if (inlinee != null && inlinee.ElementWeights is {Count: > 0}) { // Sort by weight and bring the hottest element into view. var elements = inlinee.SortedElements; TextView.SelectElements(elements); TextView.BringElementIntoView(elements[0]); } } private void CopySelectedTextExecuted(object sender, ExecutedRoutedEventArgs e) { TextView.Copy(); } public void ExpandBlockFoldings() { SetupSourceAssemblyFolding(false); } public void CollapseBlockFoldings() { SetupSourceAssemblyFolding(true); } [ProtoContract] public class SourceFileState { [ProtoMember(1)] public double HorizontalOffset; [ProtoMember(2)] public double VerticalOffset; [ProtoMember(3)] public List AssemblyFoldingStates; } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfileMenuItem.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System.Windows; using System.Windows.Media; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI.Profile.Document; public class ProfileMenuItem : BindableObject { private Thickness borderThickness_; private Brush borderBrush_; private string text_; private string prefixText_; private double minTextWidth_; private string toolTip_; private Brush textColor_; private Brush backColor_; private bool showPercentageBar_; private Brush percentageBarBackColor__; private double percentageBarBorderThickness_; private Brush percentageBarBorderBrush_; private FontWeight textWeight_; private double textSize_; private FontFamily textFont_; public ProfileMenuItem(string text, long value = 0, double valueValuePercentage = 0.0) { Text = text; Value = value; ValuePercentage = valueValuePercentage; TextWeight = FontWeights.Normal; TextColor = Brushes.Black; } public IRElement Element { get; set; } public long Value { get; set; } public double ValuePercentage { get; set; } public Thickness BorderThickness { get => borderThickness_; set => SetAndNotify(ref borderThickness_, value); } public Brush BorderBrush { get => borderBrush_; set => SetAndNotify(ref borderBrush_, value); } public string Text { get => text_; set => SetAndNotify(ref text_, value); } public string PrefixText { get => prefixText_; set => SetAndNotify(ref prefixText_, value); } public double MinTextWidth { get => minTextWidth_; set => SetAndNotify(ref minTextWidth_, value); } public string ToolTip { get => toolTip_; set => SetAndNotify(ref toolTip_, value); } public Brush TextColor { get => textColor_; set => SetAndNotify(ref textColor_, value); } public Brush BackColor { get => backColor_; set => SetAndNotify(ref backColor_, value); } public bool ShowPercentageBar { get => showPercentageBar_; set => SetAndNotify(ref showPercentageBar_, value); } public Brush PercentageBarBackColor { get => percentageBarBackColor__; set => SetAndNotify(ref percentageBarBackColor__, value); } public double PercentageBarBorderThickness { get => percentageBarBorderThickness_; set => SetAndNotify(ref percentageBarBorderThickness_, value); } public Brush PercentageBarBorderBrush { get => percentageBarBorderBrush_; set => SetAndNotify(ref percentageBarBorderBrush_, value); } public FontWeight TextWeight { get => textWeight_; set => SetAndNotify(ref textWeight_, value); } public double TextSize { get => textSize_; set => SetAndNotify(ref textSize_, value); } public FontFamily TextFont { get => textFont_; set => SetAndNotify(ref textFont_, value); } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfileSourceSyntaxNode.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using System.Windows; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.SourceParser; namespace ProfileExplorer.UI.Profile.Document; public class ProfileSourceSyntaxNode { private static readonly IconDrawing LoopIcon; private static readonly IconDrawing ThenIcon; private static readonly IconDrawing ElseIcon; private static readonly IconDrawing SwitchCaseIcon; private static readonly IconDrawing SwitchIcon; static ProfileSourceSyntaxNode() { LoopIcon = IconDrawing.FromIconResource("LoopIcon"); ThenIcon = IconDrawing.FromIconResource("ThenArrowIcon"); ElseIcon = IconDrawing.FromIconResource("ElseArrowIcon"); SwitchIcon = IconDrawing.FromIconResource("SwitchArrowIcon"); SwitchCaseIcon = IconDrawing.FromIconResource("SwitchCaseArrowIcon"); } public ProfileSourceSyntaxNode(SourceSyntaxNode syntaxNode) { SyntaxNode = syntaxNode; Weight = TimeSpan.Zero; Start = syntaxNode.Start; End = syntaxNode.End; } public SourceSyntaxNode SyntaxNode { get; set; } public int Level { get; set; } public ProfileSourceSyntaxNode Parent { get; set; } public IRElement StartElement { get; set; } public List Elements { get; set; } public TimeSpan Weight { get; set; } public TimeSpan BodyWeight { get; set; } public TimeSpan ConditionWeight { get; set; } public PerformanceCounterValueSet Counters { get; set; } public bool ShowInDocumentColumns { get; set; } public SourceSyntaxNodeKind Kind => SyntaxNode.Kind; public TextLocation Start { get; set; } public TextLocation End { get; set; } public int Length => End.Offset - Start.Offset; public bool IsMarkedNode => SyntaxNode.Kind == SourceSyntaxNodeKind.If || SyntaxNode.Kind == SourceSyntaxNodeKind.Else || SyntaxNode.Kind == SourceSyntaxNodeKind.ElseIf || SyntaxNode.Kind == SourceSyntaxNodeKind.Loop || SyntaxNode.Kind == SourceSyntaxNodeKind.Switch || SyntaxNode.Kind == SourceSyntaxNodeKind.SwitchCase; public IconDrawing GetIcon() { return Kind switch { SourceSyntaxNodeKind.Loop => LoopIcon, SourceSyntaxNodeKind.If => ThenIcon, SourceSyntaxNodeKind.Else => ElseIcon, SourceSyntaxNodeKind.ElseIf => ElseIcon, SourceSyntaxNodeKind.Switch => SwitchIcon, SourceSyntaxNodeKind.SwitchCase => SwitchCaseIcon, _ => null }; } public string GetTextIcon() { return Kind switch { SourceSyntaxNodeKind.Loop => "\u2B6F", SourceSyntaxNodeKind.If => "\u2BA7", SourceSyntaxNodeKind.Else => "\u2BA6", SourceSyntaxNodeKind.ElseIf => "\u2BA7", SourceSyntaxNodeKind.Switch => "\u21C9", SourceSyntaxNodeKind.SwitchCase => "\u2BA3", _ => "" }; } public string GetKindText() { return Kind switch { SourceSyntaxNodeKind.Loop => "Loop", SourceSyntaxNodeKind.If => "If", SourceSyntaxNodeKind.Else => "Else", SourceSyntaxNodeKind.ElseIf => "Else If", SourceSyntaxNodeKind.Switch => "Switch", SourceSyntaxNodeKind.SwitchCase => "Switch Case", SourceSyntaxNodeKind.Call => "Call", _ => "" }; } public void SetTextStyle(ProfileMenuItem value) { if (Kind == SourceSyntaxNodeKind.Loop) { value.TextColor = Brushes.DarkGreen; value.TextWeight = FontWeights.Bold; } else if (Kind == SourceSyntaxNodeKind.If || Kind == SourceSyntaxNodeKind.Else || Kind == SourceSyntaxNodeKind.ElseIf) { value.TextColor = Brushes.DarkBlue; value.TextWeight = FontWeights.SemiBold; } } public string GetTooltip(FunctionProfileData funcProfile) { var tooltip = new StringBuilder(); tooltip.Append($"{GetKindText()} statement"); tooltip.Append($"\nWeight: {funcProfile.ScaleWeight(Weight).AsPercentageString()}"); tooltip.Append($" ({Weight.AsMillisecondsString()})"); if ((SyntaxNode.Kind == SourceSyntaxNodeKind.If || SyntaxNode.Kind == SourceSyntaxNodeKind.Loop) && ConditionWeight != TimeSpan.Zero && BodyWeight != TimeSpan.Zero) { tooltip.Append($"\n Condition: {funcProfile.ScaleWeight(ConditionWeight).AsPercentageString()}"); tooltip.Append($" ({ConditionWeight.AsMillisecondsString()})"); tooltip.Append($"\n Body: {funcProfile.ScaleWeight(BodyWeight).AsPercentageString()}"); tooltip.Append($" ({BodyWeight.AsMillisecondsString()})"); } return tooltip.ToString(); } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfilingExporting.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Web; using System.Windows; using HtmlAgilityPack; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Session; namespace ProfileExplorer.UI.Profile; public static class ProfilingExporting { private static HtmlNode ExportFunctionListAsHtmlTable(List list, HtmlDocument doc, ISession session) { var itemList = new List(); var markerOptions = App.Settings.DocumentSettings.ProfileMarkerSettings; foreach (var node in list) { if (!node.HasFunction) { continue; } var item = ProfileListViewItem.From(node, session.ProfileData, session.CompilerInfo.NameProvider.FormatFunctionName, null); item.FunctionBackColor = markerOptions.PickBrushForPercentage(item.ExclusivePercentage); itemList.Add(item); } return ExportFunctionListAsHtmlTable(itemList, doc); } public static HtmlNode ExportFunctionListAsHtmlTable(List list, HtmlDocument doc) { string TableStyle = @"border-collapse:collapse;border-spacing:0;"; string HeaderStyle = @"background-color:#D3D3D3;white-space:nowrap;text-align:left;vertical-align:top;border-color:black;border-style:solid;border-width:1px;overflow:hidden;padding:2px 2px;font-family:Arial, sans-serif;"; string CellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:300px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;"; var markingSettings = App.Settings.DocumentSettings.ProfileMarkerSettings; var table = doc.CreateElement("table"); table.SetAttributeValue("style", TableStyle); var thead = doc.CreateElement("thead"); var tbody = doc.CreateElement("tbody"); var tr = doc.CreateElement("tr"); var th = doc.CreateElement("th"); th.InnerHtml = "Function"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = "Module"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); thead.AppendChild(tr); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode($"Time ({markingSettings.ValueUnitSuffix})"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Time (%)"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode($"Tine incl ({markingSettings.ValueUnitSuffix})"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = HttpUtility.HtmlEncode("Time incl (%)"); th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); table.AppendChild(thead); foreach (var node in list) { tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(node.FunctionName); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(node.ModuleName); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); // Use a background color if defined. string colorAttr = ""; if (node is ProfileListViewItem listViewItem) { string backColor = Utils.BrushToString(listViewItem.FunctionBackColor); colorAttr = backColor != null ? $";background-color:{backColor}" : ""; } td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{node.ExclusiveWeight.TotalMilliseconds}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{node.ExclusivePercentage.AsPercentageString()}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{node.Weight.TotalMilliseconds}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode($"{node.Percentage.AsPercentageString()}"); td.SetAttributeValue("style", $"{CellStyle}{colorAttr}"); tr.AppendChild(td); tbody.AppendChild(tr); } table.AppendChild(tbody); return table; } private static string ExportFunctionListAsMarkdownTable(List list, ISession session) { var itemList = new List(); var nameFormatter = session.CompilerInfo.NameProvider; foreach (var node in list) { if (!node.HasFunction) { continue; } itemList.Add(ProfileListViewItem.From(node, session.ProfileData, session.CompilerInfo.NameProvider.FormatFunctionName, null)); } return ExportFunctionListAsMarkdownTable(itemList); } public static string ExportFunctionListAsMarkdownTable(List list) { var markingSettings = App.Settings.DocumentSettings.ProfileMarkerSettings; var sb = new StringBuilder(); string header = "| Function | Module |"; string separator = "|----------|--------|"; header += $" Time ({markingSettings.ValueUnitSuffix}) | Time (%) | Time incl ({markingSettings.ValueUnitSuffix}) | Time incl (%) |"; separator += "-----------|----------|----------------|---------------|"; sb.AppendLine(header); sb.AppendLine(separator); foreach (var func in list) { sb.Append($"| {func.FunctionName} | {func.ModuleName} " + $"| {func.ExclusiveWeight.TotalMilliseconds} " + $"| {func.ExclusivePercentage.AsPercentageString()} " + $"| {func.Weight.TotalMilliseconds} " + $"| {func.Percentage.AsPercentageString()} |\n"); } return sb.ToString(); } public static (string Html, string Plaintext) ExportProfilingReportAsHtml(List markingCategoryList, ISession session, bool includeHottestFunctions, int hotFuncLimit = 20, bool includeCategoriesTable = true, bool includeOverview = true, bool isCategoryList = true) { string TableStyle = @"border-collapse:collapse;border-spacing:0;"; string HeaderStyle = @"background-color:#D3D3D3;white-space:nowrap;text-align:left;vertical-align:top;border-color:black;border-style:solid;border-width:1px;overflow:hidden;padding:2px 2px;font-family:Arial, sans-serif;"; string CellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:300px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;"; string PatternCellStyle = @"text-align:left;vertical-align:top;word-wrap:break-word;max-width:500px;overflow:hidden;padding:2px 2px;border-color:black;border-style:solid;border-width:1px;font-family:Arial, sans-serif;"; var doc = new HtmlDocument(); var sb = new StringBuilder(); var markingSettings = App.Settings.DocumentSettings.ProfileMarkerSettings; if (includeCategoriesTable) { if (includeOverview) { ExportTraceOverviewAsHtml(session, doc, sb); } AppendTitleParagraph(includeHottestFunctions ? "Categories Summary" : "Markings Summary", doc); var table = doc.CreateElement("table"); table.SetAttributeValue("style", TableStyle); var thead = doc.CreateElement("thead"); var tbody = doc.CreateElement("tbody"); var tr = doc.CreateElement("tr"); var th = doc.CreateElement("th"); string title = isCategoryList ? "Category" : "Marking"; th.InnerHtml = title; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = $"Time ({markingSettings.ValueUnitSuffix})"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = "Time (%)"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); thead.AppendChild(tr); table.AppendChild(thead); string header = $"| {title} | Time ({markingSettings.ValueUnitSuffix}) | Time (%) |"; string separator = "|----------|--------|--------|"; sb.AppendLine(header); sb.AppendLine(separator); foreach (var category in markingCategoryList) { if (category.Weight == TimeSpan.Zero && !includeOverview) { continue; } tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(category.Marking.TitleOrName); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(category.Weight.TotalMilliseconds); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(category.Percentage.AsPercentageString()); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); tbody.AppendChild(tr); sb.AppendLine( $"| {category.Marking.TitleOrName} | {category.Weight.TotalMilliseconds} | {category.Percentage.AsPercentageString()} |"); } table.AppendChild(tbody); doc.DocumentNode.AppendChild(table); AppendHtmlNewLine(doc, sb); } if (includeHottestFunctions) { // Add a table with the hottest functions overall. var hottestFuncts = new List(); var funcList = session.ProfileData.GetSortedFunctions(); string funcTitle = $"Hottest {hotFuncLimit} Functions"; AppendTitleParagraph(funcTitle, doc, sb); foreach (var pair in funcList.Take(hotFuncLimit)) { hottestFuncts.Add(session.ProfileData.CallTree.GetCombinedCallTreeNode(pair.Item1)); } var hotFuncTable = ExportFunctionListAsHtmlTable(hottestFuncts, doc, session); doc.DocumentNode.AppendChild(hotFuncTable); sb.AppendLine(); sb.AppendLine(ExportFunctionListAsMarkdownTable(hottestFuncts, session)); } // Add a table for each category. foreach (var category in markingCategoryList) { if (category.SortedFunctions.Count == 0) { continue; } string time = markingSettings.FormatWeightValue(category.Weight); string percentage = category.Percentage.AsPercentageString(); AppendHtmlNewLine(doc); AppendTitleParagraph(category.Marking.TitleOrName, doc, sb); AppendParagraph($"Time: {time} ({percentage})", doc, sb); var table = ExportFunctionListAsHtmlTable(category.SortedFunctions, doc, session); doc.DocumentNode.AppendChild(table); sb.AppendLine(); string plainText = ExportFunctionListAsMarkdownTable(category.SortedFunctions, session); sb.AppendLine(plainText); } if (includeCategoriesTable) { AppendHtmlNewLine(doc, sb); AppendTitleParagraph(includeHottestFunctions ? "Categories Definitions" : "Markings Definitions", doc); var table = doc.CreateElement("table"); table.SetAttributeValue("style", TableStyle); var thead = doc.CreateElement("thead"); var tbody = doc.CreateElement("tbody"); var tr = doc.CreateElement("tr"); string title = isCategoryList ? "Category" : "Marking"; var th = doc.CreateElement("th"); th.InnerHtml = title; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); th = doc.CreateElement("th"); th.InnerHtml = "Pattern"; th.SetAttributeValue("style", HeaderStyle); tr.AppendChild(th); thead.AppendChild(tr); table.AppendChild(thead); string header = $"| {title} | Pattern |"; string separator = "|----------|--------|"; sb.AppendLine(header); sb.AppendLine(separator); foreach (var category in markingCategoryList) { if (category.Weight == TimeSpan.Zero && !includeOverview) { continue; } tr = doc.CreateElement("tr"); var td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(category.Marking.TitleOrName); td.SetAttributeValue("style", CellStyle); tr.AppendChild(td); td = doc.CreateElement("td"); td.InnerHtml = HttpUtility.HtmlEncode(category.Marking.Name); td.SetAttributeValue("style", PatternCellStyle); tr.AppendChild(td); tbody.AppendChild(tr); sb.AppendLine($"| {category.Marking.TitleOrName} | {category.Marking.Name} |"); } table.AppendChild(tbody); doc.DocumentNode.AppendChild(table); } var writer = new StringWriter(); doc.Save(writer); return (writer.ToString(), sb.ToString()); } private static void ExportTraceOverviewAsHtml(ISession session, HtmlDocument doc, StringBuilder sb) { var report = session.ProfileData.Report; if (report != null) { AppendTitleParagraph("Overview", doc, sb); AppendParagraph($"Trace File: {report.TraceInfo.TraceFilePath}", doc, sb); AppendParagraph($"Trace Duration: {report.TraceInfo.ProfileDuration}", doc, sb); AppendParagraph($"Process Name: {report.Process.Name}", doc, sb); AppendParagraph($"Process Id: {report.Process.ProcessId}", doc, sb); AppendParagraph($"Total Time: {session.ProfileData.TotalWeight}", doc, sb); AppendParagraph($"Total Time (ms): {session.ProfileData.TotalWeight.AsMillisecondsString(2, "")}", doc, sb); AppendHtmlNewLine(doc, sb); } } private static void AppendParagraph(string text, HtmlDocument doc, StringBuilder sb = null) { string SubtitleStyle = @"margin:5;text-align:left;font-family:Arial, sans-serif;font-size:14px;margin-top:0em"; var paragraph = doc.CreateElement("p"); paragraph.InnerHtml = HttpUtility.HtmlEncode(text); paragraph.SetAttributeValue("style", SubtitleStyle); doc.DocumentNode.AppendChild(paragraph); if (sb != null) { sb.AppendLine($"{text} "); } } private static void AppendTitleParagraph(string text, HtmlDocument doc, StringBuilder sb = null) { string TitleStyle = @"margin:5;text-align:left;font-family:Arial, sans-serif;font-weight:bold;font-size:16px;margin-top:0em"; var paragraph = doc.CreateElement("p"); paragraph.InnerHtml = HttpUtility.HtmlEncode(text); paragraph.SetAttributeValue("style", TitleStyle); doc.DocumentNode.AppendChild(paragraph); if (sb != null) { sb.AppendLine($"**{text}** "); } } private static void AppendHtmlNewLine(HtmlDocument doc, StringBuilder sb = null) { var newLineParagraph = doc.CreateElement("p"); newLineParagraph.InnerHtml = " "; newLineParagraph.SetAttributeValue("style", "margin:5;"); doc.DocumentNode.AppendChild(newLineParagraph); if (sb != null) { sb.AppendLine(" "); } } public static async Task CopyFunctionMarkingsAsHtml(ISession session) { (string html, string plaintext) = await ExportFunctionMarkingsAsHtml(session); Utils.CopyHtmlToClipboard(html, plaintext); } public static void CopyFunctionMarkingsAsHtml(List markings, ISession session) { (string html, string plaintext) = ExportFunctionMarkingsAsHtml(markings, session); Utils.CopyHtmlToClipboard(html, plaintext); } private static (string Html, string Plaintext) ExportFunctionMarkingsAsHtml(List markings, ISession session) { return ExportProfilingReportAsHtml(markings, session, false, 0, true, false, true); } private static async Task<(string html, string plaintext)> ExportFunctionMarkingsAsHtml(ISession session) { var markingCategoryList = await Task.Run(() => ProfilingUtils.CollectMarkedFunctions( App.Settings.MarkingSettings.FunctionColors, false, session)); return ExportProfilingReportAsHtml(markingCategoryList, session, false, 0, true, false, false); } private static async Task<(string html, string plaintext)> ExportModuleMarkingsAsHtml(ISession session) { var markingCategoryList = await Task.Run>(() => ProfilingUtils. CreateModuleMarkingCategories( App.Settings.MarkingSettings, session)); return ExportProfilingReportAsHtml(markingCategoryList, session, false, 0, true, false, false); } public static async Task ExportFunctionMarkingsAsHtmlFile(ISession session) { (string html, _) = await ExportFunctionMarkingsAsHtml(session); await ExportFunctionMarkingsAsHtmlFile(html, session); } private static async Task ExportFunctionMarkingsAsHtmlFile(string text, ISession session) { string path = Utils.ShowSaveFileDialog("HTML file|*.html", "*.html|All Files|*.*"); bool success = true; if (!string.IsNullOrEmpty(path)) { try { await File.WriteAllTextAsync(path, text); } catch (Exception ex) { Trace.WriteLine($"Failed to save marked functions report to {path}: {ex.Message}"); success = false; } if (!success) { using var centerForm = new DialogCenteringHelper(Application.Current.MainWindow); MessageBox.Show($"Failed to save marked functions report to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } public static async Task ExportFunctionMarkingsAsMarkdownFile(ISession session) { (_, string plaintext) = await ExportFunctionMarkingsAsHtml(session); await ExportFunctionMarkingsAsMarkdownFile(plaintext, session); } private static async Task ExportFunctionMarkingsAsMarkdownFile(string text, ISession session) { string path = Utils.ShowSaveFileDialog("Markdown file|*.md", "*.md|All Files|*.*"); bool success = true; if (!string.IsNullOrEmpty(path)) { try { await File.WriteAllTextAsync(path, text); } catch (Exception ex) { Trace.WriteLine($"Failed to save marked functions report to {path}: {ex.Message}"); success = false; } if (!success) { using var centerForm = new DialogCenteringHelper(Application.Current.MainWindow); MessageBox.Show($"Failed to save marked functions report to {path}", "Profile Explorer", MessageBoxButton.OK, MessageBoxImage.Exclamation); } } } public static async Task ExportFunctionMarkingsAsHtmlFile(List categories, ISession session) { (string html, _) = ExportFunctionMarkingsAsHtml(categories, session); await ExportFunctionMarkingsAsHtmlFile(html, session); } public static async Task ExportFunctionMarkingsAsMarkdownFile(List categories, ISession session) { (_, string plaintext) = ExportFunctionMarkingsAsHtml(categories, session); await ExportFunctionMarkingsAsMarkdownFile(plaintext, session); } public static async Task CopyModuleMarkingsAsHtml(ISession session) { (string html, string plaintext) = await ExportModuleMarkingsAsHtml(session); Utils.CopyHtmlToClipboard(html, plaintext); } public static async Task ExportModuleMarkingsAsHtmlFile(ISession session) { (string html, _) = await ExportModuleMarkingsAsHtml(session); await ExportFunctionMarkingsAsHtmlFile(html, session); } public static async Task ExportModuleMarkingsAsMarkdownFile(ISession session) { (_, string plaintext) = await ExportModuleMarkingsAsHtml(session); await ExportFunctionMarkingsAsMarkdownFile(plaintext, session); } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/ProfilingUtils.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.IR; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Utilities; using ProfileExplorer.UI.Document; using ProfileExplorer.UI.Profile.Document; using ProfileExplorer.Core.Session; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.UI.Profile; public record FunctionMarkingCategory( FunctionMarkingStyle Marking, TimeSpan Weight, double Percentage, ProfileCallTreeNode HottestFunction, List SortedFunctions) { public virtual bool Equals(FunctionMarkingCategory other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Equals(Marking, other.Marking) && Weight.Equals(other.Weight) && Equals(HottestFunction, other.HottestFunction) && SortedFunctions.AreEqual(other.SortedFunctions); } } public static class ProfilingUtils { public static void CreateInstancesMenu(MenuItem menu, IRTextSection section, FunctionProfileData funcProfile, RoutedEventHandler menuClickHandler, MouseButtonEventHandler menuRightClickHandler, TextViewSettingsBase settings, ISession session) { var defaultItems = DocumentUtils.SaveDefaultMenuItems(menu); var profileItems = new List(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings.ProfileMarkerSettings; int order = 0; double maxWidth = 0; var nodes = session.ProfileData.CallTree.GetSortedCallTreeNodes(section.ParentFunction); int maxCallers = nodes.Count >= 2 ? CommonParentCallerIndex(nodes[0], nodes[1]) : int.MaxValue; foreach (var node in nodes) { double weightPercentage = funcProfile.ScaleWeight(node.Weight); if (!markerSettings.IsVisibleValue(order++, weightPercentage) || !node.HasCallers) { break; } (string title, string tooltip) = GenerateInstancePreviewText(node, session, maxCallers); string text = $"({markerSettings.FormatWeightValue(node.Weight)})"; var value = new ProfileMenuItem(text, node.Weight.Ticks, weightPercentage) { PrefixText = title, ToolTip = tooltip, ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, IsCheckable = true, StaysOpenOnClick = true, Tag = node, HeaderTemplate = valueTemplate, Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }; item.Click += menuClickHandler; if (menuRightClickHandler != null) { item.PreviewMouseRightButtonUp += menuRightClickHandler; } defaultItems.Add(item); profileItems.Add(value); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(title, ref maxWidth, menu); } foreach (var value in profileItems) { value.MinTextWidth = maxWidth; } menu.Items.Clear(); DocumentUtils.RestoreDefaultMenuItems(menu, defaultItems); } public static void CreateThreadsMenu(MenuItem menu, IRTextSection section, FunctionProfileData funcProfile, RoutedEventHandler menuClickHandler, TextViewSettingsBase settings, ISession session) { var defaultItems = DocumentUtils.SaveDefaultMenuItems(menu); var profileItems = new List(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings.ProfileMarkerSettings; var timelineSettings = App.Settings.TimelineSettings; double maxWidth = 0; var node = session.ProfileData.CallTree.GetCombinedCallTreeNode(section.ParentFunction); foreach (var thread in node.SortedByWeightPerThreadWeights) { double weightPercentage = funcProfile.ScaleWeight(thread.Values.Weight); var threadInfo = session.ProfileData.FindThread(thread.ThreadId); var backColor = timelineSettings.GetThreadBackgroundColors(threadInfo, thread.ThreadId).Margin; string text = $"({markerSettings.FormatWeightValue(thread.Values.Weight)})"; string tooltip = threadInfo is {HasName: true} ? threadInfo.Name : null; string title = !string.IsNullOrEmpty(tooltip) ? $"{thread.ThreadId} ({tooltip})" : $"{thread.ThreadId}"; var value = new ProfileMenuItem(text, node.Weight.Ticks, weightPercentage) { PrefixText = title, ToolTip = tooltip, ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, IsCheckable = true, StaysOpenOnClick = true, Tag = thread.ThreadId, Background = backColor, HeaderTemplate = valueTemplate, Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }; item.Click += menuClickHandler; defaultItems.Add(item); profileItems.Add(value); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(title, ref maxWidth, menu); } foreach (var value in profileItems) { value.MinTextWidth = maxWidth; } menu.Items.Clear(); DocumentUtils.RestoreDefaultMenuItems(menu, defaultItems); } public static void CreateInlineesMenu(MenuItem menu, IRTextSection section, List inlineeList, FunctionProfileData funcProfile, RoutedEventHandler menuClickHandler, TextViewSettingsBase settings, ISession session) { var defaultItems = DocumentUtils.SaveDefaultMenuItems(menu); var profileItems = new List(); var valueTemplate = (DataTemplate)Application.Current.FindResource("ProfileMenuItemValueTemplate"); var markerSettings = settings.ProfileMarkerSettings; int order = 0; double maxWidth = 0; // Compute time spent in non-inlinee parts. var inlineeWeightSum = TimeSpan.Zero; foreach (var node in inlineeList) { inlineeWeightSum += node.ExclusiveWeight; } var nonInlineeWeight = funcProfile.Weight - inlineeWeightSum; double nonInlineeWeightPercentage = funcProfile.ScaleWeight(nonInlineeWeight); string nonInlineeText = $"({markerSettings.FormatWeightValue(nonInlineeWeight)})"; var nonInlineeValue = new ProfileMenuItem(nonInlineeText, nonInlineeWeight.Ticks, nonInlineeWeightPercentage) { PrefixText = "Non-Inlinee Code", ToolTip = "Time for code not originating from an inlined function", ShowPercentageBar = markerSettings.ShowPercentageBar(nonInlineeWeightPercentage), TextWeight = markerSettings.PickTextWeight(nonInlineeWeightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; profileItems.Add(nonInlineeValue); if (defaultItems.Count > 0 && defaultItems[0] is MenuItem nonInlineeItem) { nonInlineeItem.Header = nonInlineeValue; nonInlineeItem.HeaderTemplate = valueTemplate; } foreach (var node in inlineeList) { double weightPercentage = funcProfile.ScaleWeight(node.ExclusiveWeight); if (!markerSettings.IsVisibleValue(order++, weightPercentage)) { break; } string title = node.InlineeFrame.Function.FormatFunctionName(session, 80); string text = $"({markerSettings.FormatWeightValue(node.ExclusiveWeight)})"; string tooltip = $"File {Utils.TryGetFileName(node.InlineeFrame.FilePath)}:{node.InlineeFrame.Line}\n"; tooltip += CreateInlineeFunctionDescription(node, funcProfile, settings.ProfileMarkerSettings, session); tooltip += $"\n\nFile path: {node.InlineeFrame.FilePath}"; tooltip += $"\nFunction: {node.InlineeFrame.Function.FormatFunctionName(session)}"; var value = new ProfileMenuItem(text, node.ExclusiveWeight.Ticks, weightPercentage) { PrefixText = title, ToolTip = tooltip, ShowPercentageBar = markerSettings.ShowPercentageBar(weightPercentage), TextWeight = markerSettings.PickTextWeight(weightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var item = new MenuItem { Header = value, Tag = node, HeaderTemplate = valueTemplate, Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }; item.Click += menuClickHandler; defaultItems.Add(item); profileItems.Add(value); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(title, ref maxWidth, menu); } // If no items were added (besides "Non-Inlinee Code"), // add an entry about there being no significant inlinees. if (profileItems.Count == 1) { defaultItems.Add(new MenuItem() { Header = "No significant inlined functions", IsHitTestVisible = false, Tag = true, // Give it a tag so it can be removed later. Style = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle") }); } foreach (var value in profileItems) { value.MinTextWidth = maxWidth; } menu.Items.Clear(); DocumentUtils.RestoreDefaultMenuItems(menu, defaultItems); } public static async Task PopulateMarkedModulesMenu(MenuItem menu, FunctionMarkingSettings settings, IUISession session, object triggerObject, Func changedHandler) { if (IsTopLevelSubmenu(triggerObject)) return; await CreateMarkedModulesMenu(menu, async (o, args) => { if (args.Source is MenuItem menuItem) { if (menuItem.Tag is FunctionMarkingStyle style) { style.IsEnabled = menuItem.IsChecked; if (style.IsEnabled) { settings.UseModuleColors = true; } await changedHandler(); } else if (menuItem.Tag is IRTextFunction func) { // Click on submenu with individual functions. await session.SwitchActiveFunction(func); } } }, (o, args) => { if (args.Source is MenuItem menuItem) { var style = menuItem.Tag as FunctionMarkingStyle; settings.ModuleColors.Remove(style); menu.IsSubmenuOpen = false; changedHandler(); } }, settings, session); } public static async Task PopulateMarkedFunctionsMenu(MenuItem menu, FunctionMarkingSettings settings, IUISession session, object triggerObject, Func changedHandler) { if (IsTopLevelSubmenu(triggerObject)) return; await CreateMarkedFunctionsMenu(menu, async (o, args) => { if (args.Source is MenuItem menuItem) { if (menuItem.Tag is FunctionMarkingStyle style) { style.IsEnabled = menuItem.IsChecked; if (style.IsEnabled) { settings.UseFunctionColors = true; } await changedHandler(); } else if (menuItem.Tag is IRTextFunction func) { // Click on submenu with individual functions. await session.SwitchActiveFunction(func); } } }, (o, args) => { if (args.Source is MenuItem menuItem) { var style = menuItem.Tag as FunctionMarkingStyle; settings.FunctionColors.Remove(style); menu.IsSubmenuOpen = false; changedHandler(); } }, settings, session); } private static bool IsTopLevelSubmenu(object triggerObject) { // The OnSubmenuOpened event is triggered not only for the top-level menu, // but also for any submenus added from code-behind. Those need to be ignored // because otherwise the entire menu gets created below again, and it also gets hidden. if (triggerObject is not MenuItem triggerMenu || triggerMenu.Tag != null) { return true; } return false; } public static async Task CreateMarkedModulesMenu(MenuItem menu, MouseButtonEventHandler menuClickHandler, MouseButtonEventHandler menuRightClickHandler, FunctionMarkingSettings settings, ISession session) { var categories = await CreateModuleMarkingCategories(settings, session); CreateCategoriesMenu(categories, menu, false, menuClickHandler, menuRightClickHandler, session); } public static async Task> CreateModuleMarkingCategories( FunctionMarkingSettings settings, ISession session) { var sortedModules = new List<(FunctionMarkingStyle Module, TimeSpan Weight)>(); foreach (var moduleStyle in settings.ModuleColors) { var moduleWeight = session.ProfileData.FindModulesWeight(name => moduleStyle.NameMatches(name)); sortedModules.Add((moduleStyle, moduleWeight)); } sortedModules.Sort((a, b) => a.Weight.CompareTo(b.Weight)); var moduleFuncs = await Task.Run(() => CollectModuleSortedFunctions(session, 10)); var categories = new List(); foreach (var pair in sortedModules) { double weightPercentage = session.ProfileData.ScaleModuleWeight(pair.Weight); var functs = moduleFuncs.GetValueOrNull(pair.Module.Name); var hottestFunc = functs?.Count > 0 ? functs[0] : null; var category = new FunctionMarkingCategory(pair.Module, pair.Weight, weightPercentage, hottestFunc, functs); categories.Add(category); } categories.Sort((a, b) => b.Weight.CompareTo(a.Weight)); return categories; } public static async Task CreateMarkedFunctionsMenu(MenuItem menu, MouseButtonEventHandler menuClickHandler, MouseButtonEventHandler menuRightClickHandler, FunctionMarkingSettings settings, ISession session) { await CreateMarkedFunctionsMenu(menu, false, menuClickHandler, menuRightClickHandler, settings.FunctionColors, session); } public static async Task CreateFunctionsCategoriesMenu(MenuItem menu, MouseButtonEventHandler menuClickHandler, MouseButtonEventHandler menuRightClickHandler, FunctionMarkingSettings settings, ISession session) { await CreateMarkedFunctionsMenu(menu, true, menuClickHandler, menuRightClickHandler, settings.BuiltinMarkingCategories.FunctionColors, session); } public static List CollectMarkedFunctions(List markings, bool isCategoriesMenu, ISession session, ProfileCallTreeNode startNode = null) { // Collect functions across all markings to compute the "Unmarked" weight. var markingCategoryList = new List(); object lockObject = new(); var tasks = new List(); foreach (var marking in markings) { tasks.Add(Task.Run(() => { // Find all functions matching the marked name. There can be multiple // since the same func. name may be used in multiple modules, // and also because the name matching may use Regex. var funcNodeList = new List(); var funcMap = new Dictionary>(); if (startNode == null) { CollectGlobalMarkedFunctions(marking, funcNodeList, funcMap, session); } else { CollectCallTreeMarkedFunctions(marking, startNode, funcNodeList, funcMap, session); } // Combine all marked functions to obtain the proper total weight. var weight = ProfileCallTree.CombinedCallTreeNodesWeight(funcNodeList); double weightPercentage = session.ProfileData.ScaleFunctionWeight(weight); var funcList = new List(); foreach (var pair in funcMap) { funcList.Add(ProfileCallTree.CombinedCallTreeNodes(pair.Value, false)); } funcList.Sort((a, b) => b.Weight.CompareTo(a.Weight)); var hottestFunc = funcList.Count > 0 ? funcList[0] : null; lock (lockObject) { markingCategoryList.Add(new FunctionMarkingCategory(marking, weight, weightPercentage, hottestFunc, funcList)); } })); } // Sort markings by weight in decreasing order. Task.WaitAll(tasks.ToArray()); markingCategoryList.Sort((a, b) => b.Weight.CompareTo(a.Weight)); if (isCategoriesMenu) { // Compute the "Unmarked" weight and add it as the last entry. var allFuncNodeList = new List(); foreach (var category in markingCategoryList) { allFuncNodeList.AddRange(category.SortedFunctions); } var categoriesWeight = ProfileCallTree.CombinedCallTreeNodesWeight(allFuncNodeList); var otherWeight = session.ProfileData.TotalWeight - categoriesWeight; double otherWeightPercentage = session.ProfileData.ScaleFunctionWeight(otherWeight); var uncategorizedMarking = new FunctionMarkingCategory( new FunctionMarkingStyle("Other functions not covered by categories", Colors.Transparent, "Uncategorized"), otherWeight, otherWeightPercentage, null, null); markingCategoryList.Add(uncategorizedMarking); } return markingCategoryList; } private static void CollectCallTreeMarkedFunctions(FunctionMarkingStyle marking, ProfileCallTreeNode startNode, List funcNodeList, Dictionary> funcNodeMap, ISession session) { var nameProvider = session.CompilerInfo.NameProvider; var visited = new HashSet(); var queue = new Queue(); queue.Enqueue(startNode); while (queue.Count > 0) { var node = queue.Dequeue(); #if DEBUG Debug.Assert(!visited.Contains(node), "Cycle detected in call tree"); visited.Add(node); #endif if (marking.NameMatches(nameProvider.FormatFunctionName(node.Function.Name))) { funcNodeList.Add(node); // Per-category list. var instanceNodeList = funcNodeMap.GetOrAddValue(node.Function); instanceNodeList.Add(node); } if (node.HasChildren) { foreach (var child in node.Children) { queue.Enqueue(child); } } } } private static void CollectGlobalMarkedFunctions(FunctionMarkingStyle marking, List funcNodeList, Dictionary> funcNodeMap, ISession session) { var nameProvider = session.CompilerInfo.NameProvider; foreach (var loadedDoc in session.Documents) { if (loadedDoc.Summary == null) { continue; } var matchingFuncList = loadedDoc.Summary.FindFunctions(name => marking.NameMatches( nameProvider.FormatFunctionName(name))); foreach (var func in matchingFuncList) { var nodeList = session.ProfileData.CallTree.GetCallTreeNodes(func); if (nodeList != null) { funcNodeList.AddRange(nodeList); // Per-category list. } funcNodeMap[func] = nodeList; } } } private static Dictionary> CollectModuleSortedFunctions(ISession session, int maxFunctsPerModule) { var functs = session.ProfileData.GetSortedFunctions(); var moduleFuncs = new Dictionary>(); // Pick top N function per module, in exclusive weight order. foreach (var pair in functs) { var func = pair.Item1; var list = moduleFuncs.GetOrAddValue(func.ModuleName); if (list.Count < maxFunctsPerModule) { list.Add(session.ProfileData.CallTree.GetCombinedCallTreeNode(func)); } } // Sort functions by weight in decreasing order. foreach (var pair in moduleFuncs) { pair.Value.Sort((a, b) => b.ExclusiveWeight.CompareTo(a.ExclusiveWeight)); } return moduleFuncs; } private static int CommonParentCallerIndex(ProfileCallTreeNode a, ProfileCallTreeNode b) { int index = 0; do { index++; a = a.Caller; b = b.Caller; } while (a != b && a != null && b != null); return index; } public static (string Short, string Long) GenerateInstancePreviewText(ProfileCallTreeNode node, ISession session, int maxCallers = int.MaxValue) { return GenerateInstancePreviewText(node, maxCallers, 80, 25, 1000, 50, session); } private static (string Short, string Long) GenerateInstancePreviewText(ProfileCallTreeNode node, int maxCallers, int maxLength, int maxSingleLength, int maxCompleteLength, int maxCompleteLineLength, ISession session) { const string Separator = " \ud83e\udc70 "; // Arrow character. var sb = new StringBuilder(); var completeSb = new StringBuilder(); var nameProvider = session.CompilerInfo.NameProvider; int remaining = maxLength; int completeRemaining = maxCompleteLength; int completeLineRemaining = maxCompleteLineLength; int index = 0; node = node.Caller; completeSb.AppendLine("Right-click to select instance in Flame Graph and Call Tree\n"); while (node != null) { // Build the shorter title stack trace. if (index < maxCallers && remaining > 0) { int maxNameLength = Math.Min(remaining, maxSingleLength); string name = node.FormatFunctionName(nameProvider.FormatFunctionName, maxNameLength); remaining -= name.Length; if (index == 0) { sb.Append(name); } else { sb.Append($"{Separator}{name}"); } } // Build the longer tooltip stack trace. if (completeRemaining > 0) { int maxNameLength = Math.Min(completeRemaining, maxSingleLength); string name = node.FormatFunctionName(nameProvider.FormatFunctionName, maxNameLength); if (index == 0) { completeSb.Append(name); } else { completeSb.Append($"{Separator}{name}"); } completeRemaining -= name.Length; completeLineRemaining -= name.Length; if (completeLineRemaining < 0) { completeSb.Append("\n"); completeLineRemaining = maxCompleteLineLength; } } node = node.Caller; index++; } return (sb.ToString().Trim(), completeSb.ToString().Trim()); } public static void HandleInstanceMenuItemChanged(MenuItem menuItem, MenuItem menu, ProfileSampleFilter instanceFilter) { if (menuItem.Tag is ProfileCallTreeNode node) { instanceFilter ??= new ProfileSampleFilter(); if (menuItem.IsChecked) { instanceFilter.AddInstance(node); } else { instanceFilter.RemoveInstance(node); } } else { instanceFilter.ClearInstances(); UncheckMenuItems(menu, menuItem); } } public static void HandleThreadMenuItemChanged(MenuItem menuItem, MenuItem menu, ProfileSampleFilter instanceFilter) { if (menuItem.Tag is int threadId) { instanceFilter ??= new ProfileSampleFilter(); if (menuItem.IsChecked) { instanceFilter.AddThread(threadId); } else { instanceFilter.RemoveThread(threadId); } } else { instanceFilter.ClearThreads(); UncheckMenuItems(menu, menuItem); } } public static void SyncThreadsMenuWithFilter(MenuItem menu, ProfileSampleFilter instanceFilter) { foreach (object item in menu.Items) { if (item is MenuItem menuItem && menuItem.Tag is int threadId) { menuItem.IsChecked = instanceFilter != null && instanceFilter.IncludesThread(threadId); } } } public static string CreateProfileFilterTitle(ProfileSampleFilter instanceFilter, ISession session) { if (instanceFilter == null) { return ""; } return !instanceFilter.IncludesAll ? "Instance: " : ""; } public static string CreateProfileFilterDescription(ProfileSampleFilter instanceFilter, ISession session) { if (instanceFilter == null) { return ""; } var sb = new StringBuilder("\n"); if (instanceFilter.HasInstanceFilter) { sb.AppendLine("\nInstances included:"); foreach (var node in instanceFilter.FunctionInstances) { sb.AppendLine($" - {GenerateInstancePreviewText(node, session).Short}"); } } if (instanceFilter.HasThreadFilter) { sb.AppendLine("\nThreads included:"); foreach (int threadId in instanceFilter.ThreadIds) { var threadInfo = session.ProfileData.FindThread(threadId); string threadName = threadInfo is {HasName: true} ? threadInfo.Name : null; if (!string.IsNullOrEmpty(threadName)) { sb.AppendLine($" - {threadId} ({threadName})"); } else { sb.AppendLine($" - {threadId}"); } } } return sb.ToString().Trim(); } public static string CreateProfileFunctionDescription(FunctionProfileData funcProfile, ProfileDocumentMarkerSettings settings, ISession session) { return CreateProfileDescription(funcProfile.Weight, funcProfile.ExclusiveWeight, settings, session.ProfileData.ScaleFunctionWeight); } public static string CreateInlineeFunctionDescription(InlineeListItem inlinee, FunctionProfileData funcProfile, ProfileDocumentMarkerSettings settings, ISession session) { return CreateProfileDescription(inlinee.Weight, inlinee.ExclusiveWeight, settings, funcProfile.ScaleWeight); } public static string CreateProfileDescription(TimeSpan weight, TimeSpan exclusiveWeight, ProfileDocumentMarkerSettings settings, Func weightFunc) { double weightPerc = weightFunc(weight); double exclusiveWeightPerc = weightFunc(exclusiveWeight); string weightText = $"{weightPerc.AsPercentageString()} ({settings.FormatWeightValue(weight)})"; string exclusiveWeightText = $"{exclusiveWeightPerc.AsPercentageString()} ({settings.FormatWeightValue(exclusiveWeight)})"; return $"Total time: {weightText}\nSelf time: {exclusiveWeightText}"; } public static void SyncInstancesMenuWithFilter(MenuItem menu, ProfileSampleFilter instanceFilter) { foreach (object item in menu.Items) { if (item is MenuItem menuItem && menuItem.Tag is ProfileCallTreeNode node) { menuItem.IsChecked = instanceFilter != null && instanceFilter.IncludesInstance(node); } } } public static async Task CreateMarkedFunctionsMenu(MenuItem menu, bool isCategoriesMenu, MouseButtonEventHandler menuClickHandler, MouseButtonEventHandler menuRightClickHandler, List markings, ISession session) { // Collect all marked functions and their weight by category. var markingCategoryList = await Task.Run(() => CollectMarkedFunctions(markings, isCategoriesMenu, session)); CreateCategoriesMenu(markingCategoryList, menu, isCategoriesMenu, menuClickHandler, menuRightClickHandler, session); } private static void CreateCategoriesMenu(List temp, MenuItem menu, bool isCategoriesMenu, MouseButtonEventHandler menuClickHandler, MouseButtonEventHandler menuRightClickHandler, ISession session) { var defaultItems = DocumentUtils.SaveDefaultMenuItems(menu); var profileItems = new List(); int separatorIndex = !isCategoriesMenu ? defaultItems.FindIndex(item => item is Separator) : -1; var markerSettings = App.Settings.DocumentSettings.ProfileMarkerSettings; var categoriesValueTemplate = (DataTemplate)Application.Current. FindResource("CategoriesProfileMenuItemValueTemplate"); var checkableValueTemplate = (DataTemplate)Application.Current. FindResource("CheckableProfileMenuItemValueTemplate"); var submenuStyle = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle2"); var menuStyle = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle"); double maxWidth = 0; foreach (var category in temp) { string text = $"({markerSettings.FormatWeightValue(category.Weight)})"; string title = null; string tooltip = null; if (isCategoriesMenu) { title = category.Marking.TitleOrName; tooltip = DocumentUtils.FormatLongFunctionName(category.Marking.Name); } else { tooltip = "Right-click to remove function marking"; title = category.Marking.Name.TrimToLength(80); if (category.Marking.HasTitle && category.Marking.IsRegex) { title = $"{category.Marking.Title.TrimToLength(40)} ({title.TrimToLength(40)}) (Regex)"; } else { if (category.Marking.HasTitle) { title = $"{category.Marking.Title} ({title})"; } if (category.Marking.IsRegex) { title = $"{title} (Regex)"; } } } var value = new ProfileMenuItem(text, category.Weight.Ticks, category.Percentage) { PrefixText = title, ToolTip = tooltip, ShowPercentageBar = markerSettings.ShowPercentageBar(category.Percentage), TextWeight = markerSettings.PickTextWeight(category.Percentage), PercentageBarBackColor = category.HottestFunction != null ? markerSettings.PercentageBarBackColor.AsBrush() : (Brush)Application.Current.FindResource("ProfileUncategorizedBrush"), BackColor = !isCategoriesMenu ? category.Marking.Color.AsBrush() : ColorBrushes.Transparent }; var item = new MenuItem { IsChecked = !isCategoriesMenu && category.Marking.IsEnabled, StaysOpenOnClick = true, Header = value, Tag = !isCategoriesMenu ? category.Marking : category.HottestFunction ?? new object(), HeaderTemplate = !isCategoriesMenu ? checkableValueTemplate : categoriesValueTemplate, Style = category.SortedFunctions is {Count: > 0} ? submenuStyle : menuStyle }; if (menuClickHandler != null) { item.PreviewMouseLeftButtonUp += menuClickHandler; } if (menuRightClickHandler != null) { item.PreviewMouseRightButtonDown += menuRightClickHandler; } item.PreviewMouseLeftButtonDown += (o, args) => { if (!isCategoriesMenu && args.Source is MenuItem menuItem && menuItem.Tag is FunctionMarkingStyle) { menuItem.IsChecked = !menuItem.IsChecked; } }; // Create a submenu with the sorted functions // part of the marking/category. if (category.SortedFunctions is {Count: > 0}) { CreateFunctionsSubmenu(category.SortedFunctions, item, menuClickHandler, session); } defaultItems.Insert(++separatorIndex, item); profileItems.Add(value); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(title, ref maxWidth, menu); } foreach (var item in profileItems) { item.MinTextWidth = maxWidth; } // Populate the menu. menu.Items.Clear(); DocumentUtils.RestoreDefaultMenuItems(menu, defaultItems); } private static void CreateFunctionsSubmenu(List functions, MenuItem parentMenuItem, MouseButtonEventHandler menuClickHandler, ISession session) { var markerSettings = App.Settings.DocumentSettings.ProfileMarkerSettings; var valueTemplate = (DataTemplate)Application.Current. FindResource("ProfileMenuItemValueTemplate"); var menuStyle = (Style)Application.Current.FindResource("SubMenuItemHeaderStyle"); var profileSubItems = new List(); double subitemMaxWidth = 0; int order = 0; foreach (var node in functions) { double funcWeightPercentage = session.ProfileData.ScaleFunctionWeight(node.Weight); double exclFuncWeightPercentage = session.ProfileData.ScaleFunctionWeight(node.ExclusiveWeight); string funcText = $"({markerSettings.FormatWeightValue(node.Weight)})"; // Stop once the weight is too small to be significant. if (!markerSettings.IsVisibleValue(order++, funcWeightPercentage)) { break; } string tooltip = $"Exclusive Weight: {exclFuncWeightPercentage.AsPercentageString()} ({markerSettings.FormatWeightValue(node.ExclusiveWeight)})\n"; tooltip += $"Weight: {funcWeightPercentage.AsPercentageString()} ({markerSettings.FormatWeightValue(node.Weight)})\n"; tooltip += $"Module: {node.ModuleName}"; if (node is ProfileCallTreeGroupNode groupNode) { tooltip += $"\nInstances: {groupNode.Nodes.Count}"; } var funcValue = new ProfileMenuItem(funcText, node.Weight.Ticks, funcWeightPercentage) { PrefixText = node.Function.FormatFunctionName(session, 60), ToolTip = tooltip, ShowPercentageBar = markerSettings.ShowPercentageBar(funcWeightPercentage), TextWeight = markerSettings.PickTextWeight(funcWeightPercentage), PercentageBarBackColor = markerSettings.PercentageBarBackColor.AsBrush() }; var nodeItem = new MenuItem { Header = funcValue, Tag = node.Function, HeaderTemplate = valueTemplate, Style = menuStyle }; if (menuClickHandler != null) { nodeItem.PreviewMouseLeftButtonUp += menuClickHandler; } parentMenuItem.Items.Add(nodeItem); profileSubItems.Add(funcValue); // Make sure percentage rects are aligned. Utils.UpdateMaxMenuItemWidth(funcValue.PrefixText, ref subitemMaxWidth, nodeItem); } foreach (var subItem in profileSubItems) { subItem.MinTextWidth = subitemMaxWidth; } } private static void UncheckMenuItems(MenuItem menu, MenuItem excludedItem) { foreach (object item in menu.Items) { if (item is MenuItem menuItem && menuItem != excludedItem) { menuItem.IsChecked = false; } } } public static bool ComputeAssemblyWeightInRange(int startLine, int endLine, FunctionIR function, FunctionProfileData funcProfile, out TimeSpan weightSum, out int count) { var metadataTag = function.GetTag(); bool hasInstrOffsetMetadata = metadataTag != null && metadataTag.OffsetToElementMap.Count > 0; if (!hasInstrOffsetMetadata) { weightSum = TimeSpan.Zero; count = 0; return false; } weightSum = TimeSpan.Zero; count = 0; if (startLine > endLine) { // Happens when selecting bottom-up. (startLine, endLine) = (endLine, startLine); } foreach (var tuple in function.AllTuples) { if (tuple.TextLocation.Line >= startLine && tuple.TextLocation.Line <= endLine) { if (metadataTag.ElementToOffsetMap.TryGetValue(tuple, out long offset) && funcProfile.InstructionWeight.TryGetValue(offset, out var weight)) { weightSum += weight; count++; } } } return count > 1; } public static bool ComputeSourceWeightInRange(int startLine, int endLine, SourceLineProcessingResult profileResult, SourceLineProfileResult processingResult, out TimeSpan weightSum, out int count) { weightSum = TimeSpan.Zero; count = 0; if (startLine > endLine) { // Happens when selecting bottom-up. (startLine, endLine) = (endLine, startLine); } for (int i = startLine; i <= endLine; i++) { int line = i; // With assembly lines, source line numbers are shifted. if (processingResult != null) { if (processingResult.LineToOriginalLineMap.TryGetValue(line, out int mappedLine)) { line = mappedLine; } else continue; } if (profileResult.SourceLineWeight.TryGetValue(line, out var weight)) { weightSum += weight; } count++; // Also count lines without weight. } return count > 1; } } ================================================ FILE: src/ProfileExplorerUI/Profile/Document/SourceDocumentMarker.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Media; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Rendering; using ProfileExplorer.Core.IR; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.IR.Tags; using ProfileExplorer.Core.Providers; using ProfileExplorer.Core; using System.CodeDom.Compiler; namespace ProfileExplorer.UI.Profile; public class SourceDocumentMarker { private const int FunctionNameMaxLength = 80; private static readonly string SourceOverlayTag = "SourceTag"; private SourceDocumentMarkerSettings settings_; private ICompilerIRInfo irInfo_; private INameProvider nameProvider_; public SourceDocumentMarker(SourceDocumentMarkerSettings settings, ICompilerInfoProvider compilerInfo) { settings_ = settings; irInfo_ = compilerInfo.IR; nameProvider_ = compilerInfo.NameProvider ; } public async Task Mark(IRDocument document, FunctionIR function) { if (!settings_.AnnotateSourceLines && !settings_.AnnotateInlinees) { return; } var overlays = new List(function.InstructionCount); var inlineeOverlays = new List(function.InstructionCount); var lineLengths = new List(function.InstructionCount); var lineToOperandMap = new Dictionary(); document.SuspendUpdate(); await Task.Run(() => { // Cache the strings generated for each line and inlinee frame. string lineNumberTooltip = null; var inlineeLineNumberMap = new Dictionary(); var inlineeFrameMap = new Dictionary(); foreach (var instr in function.AllInstructions) { if (settings_.MarkCallTargets) { MarkCallInstruction(instr, document, lineToOperandMap); } // Annotate right-hand side with source line and inlinee info. var tag = instr.GetTag(); if (tag == null) { continue; } if (tag.Line != 0 && settings_.AnnotateSourceLines) { if (!inlineeLineNumberMap.TryGetValue(tag.Line, out string label)) { label = $"{tag.Line}"; inlineeLineNumberMap[tag.Line] = label; } if (lineNumberTooltip == null) { string fileName = Utils.TryGetFileName(tag.FilePath); lineNumberTooltip = $"Line number for file {fileName}\nFile path: {tag.FilePath}"; } var overlay = document.RegisterIconElementOverlay(instr, null, 16, 0, label, lineNumberTooltip); overlay.Tag = SourceOverlayTag; overlay.IsLabelPinned = true; overlay.AllowLabelEditing = false; overlay.TextColor = settings_.SourceLineTextColor.AsBrush(); overlay.Background = settings_.SourceLineBackColor.AsBrush(); overlays.Add(overlay); lineLengths.Add(instr.TextLength); } if (tag.HasInlinees && settings_.AnnotateInlinees) { var sb = new StringBuilder(); var tooltipSb = new StringBuilder(); tooltipSb.AppendLine("Inlined functions"); tooltipSb.AppendLine("name:line (file) in calling order:\n"); var inlinees = tag.Inlinees; inlineeOverlays.EnsureCapacity(inlineeOverlays.Count + inlinees.Count); for (int k = 0; k < inlinees.Count; k++) { var inlinee = inlinees[inlinees.Count - k - 1]; // Append backwards. if (!inlineeFrameMap.TryGetValue(inlinee, out var inlineeText)) { string inlineeName = nameProvider_.FormatFunctionName(inlinee.Function); inlineeText = new ValueTuple(); inlineeText.Title = $"{inlineeName}:{inlinees[k].Line}"; inlineeText.Tooltip = MakeInlineeTooltip(inlineeName, inlinee.Line, inlinee.FilePath, k); inlineeFrameMap[inlinee] = inlineeText; } sb.Append(inlineeText.Title); tooltipSb.AppendLine(inlineeText.Tooltip); if (k != inlinees.Count - 1) { sb.Append(" | "); } } // MakeInlineeTooltip(funcName, tag.Line, null, tag.Inlinees.Count, tooltipSb); var inlineeOverlay = document.RegisterIconElementOverlay(instr, null, 16, 0, sb.ToString().Trim(), tooltipSb.ToString().Trim()); inlineeOverlay.Tag = SourceOverlayTag; inlineeOverlay.TextColor = settings_.InlineeOverlayTextColor.AsBrush(); inlineeOverlay.Background = settings_.SourceLineBackColor.AsBrush(); inlineeOverlay.IsLabelPinned = true; inlineeOverlay.AllowLabelEditing = false; inlineeOverlays.Add(inlineeOverlay); } } lineLengths.Sort(); }); // Place the line numbers on a column aligned with most instrs. var settings = App.Settings.DocumentSettings; const double lengthPercentile = 0.9; // Consider length of most lines. const int overlayMargin = 10; // Distance from instruction end. const int inlineeOverlayMargin = 30; int percentileLength = lineLengths.Count > 0 ? lineLengths[(int)Math.Floor(lineLengths.Count * lengthPercentile)] : 0; double columnPosition = Utils.MeasureString(percentileLength, settings.FontName, settings.FontSize).Width; // Adjust position of all overlays. foreach (var overlay in overlays) { double position = Math.Max(settings_.VirtualColumnPosition, columnPosition); overlay.VirtualColumn = position + overlayMargin; } foreach (var overlay in inlineeOverlays) { double position = Math.Max(settings_.VirtualColumnPosition, columnPosition); overlay.VirtualColumn = position + overlayMargin + inlineeOverlayMargin; } if (settings_.MarkCallTargets) { var callTypeFace = new Typeface(document.FontFamily, document.FontStyle, FontWeights.Bold, document.FontStretch); var colorizer = new OperandColorizer(lineToOperandMap, settings_.CallTargetTextColor.AsBrush(), settings_.CallTargetBackColor.AsBrush(), callTypeFace); document.RegisterTextTransformer(colorizer); } document.ResumeUpdate(); } private void MarkCallInstruction(InstructionIR instr, IRDocument document, Dictionary lineToOperandMap) { if (irInfo_.IsCallInstruction(instr) && irInfo_.GetCallTarget(instr) is OperandIR callTargetOp && callTargetOp.HasName) { // Mark only functions whose code is available in the session. if (DocumentUtils.FindCallTargetSection(callTargetOp, document.Section, document.Session) != null) { lineToOperandMap[instr.TextLocation.Line] = callTargetOp; } } } //? Currently calls are marked only with profiling data, here could be a mode //? that instead uses only the IR to mark calls. //private void MarkCallInstruction(InstructionIR instr, IRDocument document) { // if (irInfo_.IR.IsCallInstruction(instr) && // irInfo_.IR.GetCallTarget(instr) is OperandIR callTargetOp && // callTargetOp.HasName) { // var icon = IconDrawing.FromIconResource("ExecuteIcon"); // var overlay = document.RegisterIconElementOverlay(instr, icon, 16, 16); // overlay.IsLabelPinned = false; // overlay.UseLabelBackground = true; // overlay.AlignmentX = System.Windows.HorizontalAlignment.Left; // // Place before the call opcode. // int lineOffset = lineOffset = instr.OpcodeLocation.Offset - instr.TextLocation.Offset; // overlay.MarginX = Utils.MeasureString(lineOffset, App.Settings.DocumentSettings.FontName, // App.Settings.DocumentSettings.FontSize).Width - 20; // overlay.MarginY = 1; // } //} private string MakeInlineeTooltip(string inlineeName, int inlineeLine, string inlineeFilePath, int index) { string inlineeFileName = Utils.TryGetFileName(inlineeFilePath); inlineeName = inlineeName.TrimToLength(FunctionNameMaxLength); if (!string.IsNullOrEmpty(inlineeFileName)) { return $"{inlineeName}:{inlineeLine} ({inlineeFileName})"; } else { return $"{inlineeName}:{inlineeLine}"; } } // Use to mark the call target function names. public sealed class OperandColorizer : DocumentColorizingTransformer { private Dictionary lineToOperandMap_; private Brush textColor_; private Brush backColor_; private Typeface typeface_; public OperandColorizer(Dictionary lineToOperandMap, Brush textColor, Brush backColor, Typeface typeface = null) { lineToOperandMap_ = lineToOperandMap; textColor_ = textColor; backColor_ = backColor; typeface_ = typeface; } protected override void ColorizeLine(DocumentLine line) { if (line.Length == 0) { return; } if (!lineToOperandMap_.TryGetValue(line.LineNumber - 1, out var operand)) { return; } int start = operand.TextLocation.Offset; int end = start + operand.TextLength; if (start < line.Offset || end > line.EndOffset) { return; } ChangeLinePart(start, end, element => { element.TextRunProperties.SetTextDecorations(TextDecorations.Underline); if (textColor_ != null) { element.TextRunProperties.SetForegroundBrush(textColor_); } if (backColor_ != null) { element.TextRunProperties.SetBackgroundBrush(backColor_); } if (typeface_ != null) { element.TextRunProperties.SetTypeface(typeface_); } }); } } } ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraph.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Media; using ProfileExplorer.Core; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.UI.Profile; public class FlameGraphNode : SearchableProfileItem, IEquatable { internal const double DefaultMargin = 4; internal const double ExtraValueMargin = 20; internal const double MinVisibleRectWidth = 4; internal const double RecomputeVisibleRectWidth = MinVisibleRectWidth * 4; internal const double MinVisibleWidth = 1; internal const int MaxTextParts = 3; public FlameGraphNode(ProfileCallTreeNode callTreeNode, TimeSpan weight, int depth, FunctionNameFormatter funcNameFormatter) : base(funcNameFormatter) { CallTreeNode = callTreeNode; Weight = weight; Depth = depth; } public virtual bool IsGroup => false; public ProfileCallTreeNode CallTreeNode { get; } public FlameGraphRenderer Owner { get; set; } public FlameGraphNode Parent { get; set; } public List Children { get; set; } public TimeSpan ChildrenWeight { get; set; } public int Depth { get; set; } public HighlightingStyle Style { get; set; } public Brush TextColor { get; set; } public Brush ModuleTextColor { get; set; } public Brush WeightTextColor { get; set; } public Brush PercentageTextColor { get; set; } public Rect Bounds { get; set; } public double PercentageTextPosition { get; set; } public uint RenderVersion { get; set; } public bool IsDummyNode { get; set; } public bool IsHidden { get; set; } public bool HasFunction => CallTreeNode != null; public bool HasChildren => Children is {Count: > 0}; public IRTextFunction Function => CallTreeNode?.Function; public TimeSpan StartTime { get; set; } public TimeSpan EndTime { get; set; } public TimeSpan Duration => EndTime - StartTime; public override string ModuleName => CallTreeNode is {HasFunction: true} ? CallTreeNode.ModuleName : null; public bool IsDummyNodeOrChild { get { if (IsDummyNode) { return true; } var node = Parent; while (node != null) { if (node.IsDummyNode) { return true; } node = node.Parent; } return false; } } public bool Equals(FlameGraphNode other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return Equals(CallTreeNode, other.CallTreeNode); } public static bool operator ==(FlameGraphNode left, FlameGraphNode right) { return Equals(left, right); } public static bool operator !=(FlameGraphNode left, FlameGraphNode right) { return !Equals(left, right); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((FlameGraphNode)obj); } public override int GetHashCode() { return CallTreeNode != null ? CallTreeNode.GetHashCode() : 0; } protected override string GetFunctionName() { return CallTreeNode is {HasFunction: true} ? CallTreeNode.FunctionName : null; } } public sealed class FlameGraphGroupNode : FlameGraphNode { public FlameGraphGroupNode(FlameGraphNode parentNode, int startIndex, int replacedNodeCount, TimeSpan weight, int depth) : base(null, weight, depth, null) { Parent = parentNode; ReplacedStartIndex = startIndex; ReplacedNodeCount = replacedNodeCount; } public override bool IsGroup => true; public int ReplacedNodeCount { get; } public int ReplacedStartIndex { get; } public int ReplacedEndIndex => ReplacedStartIndex + ReplacedNodeCount; } public sealed class FlameGraph { private FlameGraphNode rootNode_; private TimeSpan rootWeight_; private TimeSpan profileStartTime_; private TimeSpan profileEndTime_; private double rootWeightReciprocal_; private double rootDurationReciprocal_; private double profileDurationReciprocal_; private FunctionNameFormatter nameFormatter_; public FlameGraph(ProfileCallTree callTree, FunctionNameFormatter nameFormatter) { CallTree = callTree; nameFormatter_ = nameFormatter; } public ProfileCallTree CallTree { get; set; } public FlameGraphNode RootNode { get => rootNode_; set { rootNode_ = value; if (rootNode_.Duration.Ticks != 0) { rootDurationReciprocal_ = 1.0 / rootNode_.Duration.Ticks; profileDurationReciprocal_ = 1.0 / (profileEndTime_ - profileStartTime_).Ticks; } } } public TimeSpan RootWeight { get => rootWeight_; set { rootWeight_ = value; if (rootWeight_.Ticks != 0) { rootWeightReciprocal_ = 1.0 / rootWeight_.Ticks; } } } public List GetNodes(ProfileCallTreeNode node) { var list = new List(); AppendNodes(node, list); return list; } public void AppendNodes(ProfileCallTreeNode node, List resultList) { if (!node.IsGroup) { if (node.Tag is FlameGraphNode fgNode) { resultList.Add(fgNode); } return; } var groupNode = node as ProfileCallTreeGroupNode; foreach (var childNode in groupNode.Nodes) { if (childNode.Tag is FlameGraphNode fgNode) { resultList.Add(fgNode); } } } public FlameGraphNode GetFlameGraphNode(ProfileCallTreeNode callNode) { return callNode.Tag as FlameGraphNode; } public List SearchNodes(string text, bool caseInsensitive) { var nodes = new List(); var searcher = new TextSearcher(text, caseInsensitive); SearchNodesImpl(RootNode, text, searcher, nodes); // Sort the nodes by weight, descending. nodes.Sort((a, b) => b.Weight.CompareTo(a.Weight)); return nodes; } private void SearchNodesImpl(FlameGraphNode node, string text, TextSearcher searcher, List nodes) { if (node.HasFunction) { var result = searcher.FirstIndexOf(node.FunctionName); if (result.HasValue) { node.SearchResult = result; nodes.Add(node); } } if (node.HasChildren) { foreach (var child in node.Children) { SearchNodesImpl(child, text, searcher, nodes); } } } public void ResetSearchResults(List nodes) { foreach (var node in nodes) { node.SearchResult = null; } } public List GetNodesInTimeRange(TimeSpan startTime, TimeSpan endTime) { var nodes = new List(); GetNodesInTimeRangeImpl(RootNode, startTime, endTime, nodes); return nodes; } public void Build(ProfileCallTreeNode rootNode) { if (rootNode == null) { // Make a dummy root node that hosts all real root nodes. RootWeight = CallTree.TotalRootNodesWeight; var flameNode = CreateFlameGraphNode(null, RootWeight, 0); RootNode = Build(flameNode, CallTree.RootNodes, 0); } else { // Root node overriden (consider only a call tree subset). RootWeight = rootNode.Weight; var flameNode = CreateFlameGraphNode(rootNode, rootNode.Weight, 0); RootNode = Build(flameNode, rootNode.Children, 0); } } public double ScaleWeight(FlameGraphNode node) { return node.Weight.Ticks * rootWeightReciprocal_; } public double ScaleExclusiveWeight(FlameGraphNode node) { return node.ExclusiveWeight.Ticks * rootWeightReciprocal_; } public double ScaleStartTime(TimeSpan time) { return (time.Ticks - profileStartTime_.Ticks) * profileDurationReciprocal_; } public double ScaleStartTime(FlameGraphNode node) { if (node.CallTreeNode != null) { return (node.StartTime.Ticks - profileStartTime_.Ticks) * profileDurationReciprocal_; } return (node.StartTime.Ticks - RootNode.StartTime.Ticks) * rootDurationReciprocal_; } public double ScaleDuration(FlameGraphNode node) { if (node.CallTreeNode != null) { return (node.EndTime.Ticks - node.StartTime.Ticks) * profileDurationReciprocal_; } return (node.EndTime.Ticks - node.StartTime.Ticks) * rootDurationReciprocal_; } public double InverseScaleWeight(TimeSpan weight) { return (double)RootWeight.Ticks / weight.Ticks; } private void GetNodesInTimeRangeImpl(FlameGraphNode node, TimeSpan startTime, TimeSpan endTime, List nodes) { if (node.StartTime >= endTime || node.EndTime <= startTime) { return; } if (node.HasFunction) { nodes.Add(node); } if (node.HasChildren) { foreach (var child in node.Children) { GetNodesInTimeRangeImpl(child, startTime, endTime, nodes); } } } private void AddSample(FlameGraphNode rootNode, ProfileSample sample, ResolvedProfileStack stack) { var node = rootNode; int depth = 0; for (int k = stack.FrameCount - 1; k >= 0; k--) { var resolvedFrame = stack.StackFrames[k]; if (resolvedFrame.FrameDetails.Function == null) { continue; } FlameGraphNode targetNode = null; if (node.HasChildren) { for (int i = node.Children.Count - 1; i >= 0; i--) { var child = node.Children[i]; if (!child.CallTreeNode.Function.Equals(resolvedFrame.FrameDetails.Function)) { break; // Last func is different, stop and start a new stack. } if (sample.Time - child.EndTime < TimeSpan.FromMilliseconds(100)) { targetNode = child; // Also start a new stack if nothing executed for a while. } break; } } if (targetNode == null) { var callNode = new ProfileCallTreeNode(resolvedFrame.FrameDetails.DebugInfo, resolvedFrame.FrameDetails.Function, null, node.CallTreeNode); targetNode = new FlameGraphNode(callNode, TimeSpan.Zero, depth, nameFormatter_); node.Children ??= new List(); node.Children.Add(targetNode); targetNode.StartTime = sample.Time; targetNode.EndTime = sample.Time + sample.Weight; targetNode.Parent = node; } else { targetNode.StartTime = TimeSpan.FromTicks(Math.Min(targetNode.StartTime.Ticks, sample.Time.Ticks)); targetNode.EndTime = TimeSpan.FromTicks(Math.Max(targetNode.EndTime.Ticks, sample.Time.Ticks + sample.Weight.Ticks)); } if (k > 0) { node.ChildrenWeight += sample.Weight; } else { node.Weight += sample.Weight; } targetNode.Weight += sample.Weight; node = targetNode; depth++; } } private FlameGraphNode Build(FlameGraphNode flameNode, ICollection children, int depth) { if (children == null || children.Count == 0) { return flameNode; } var sortedChildren = new List(children.Count); var childrenWeight = TimeSpan.Zero; foreach (var child in children) { sortedChildren.Add(child); childrenWeight += child.Weight; } // Place nodes left to right based on weight, heaviest first. sortedChildren.Sort((a, b) => b.Weight.CompareTo(a.Weight)); flameNode.Children = new List(children.Count); flameNode.ChildrenWeight = childrenWeight; foreach (var child in sortedChildren) { var childFlameNode = CreateFlameGraphNode(child, child.Weight, depth + 1); var childNode = Build(childFlameNode, child.Children, depth + 1); childNode.Parent = flameNode; flameNode.Children.Add(childNode); child.Tag = childFlameNode; // Quick mapping between call tree and flame graph node. } return flameNode; } private FlameGraphNode CreateFlameGraphNode(ProfileCallTreeNode callTreeNode, TimeSpan weight, int depth) { var flameNode = new FlameGraphNode(callTreeNode, weight, depth, nameFormatter_); if (callTreeNode != null) { flameNode.ExclusiveWeight = callTreeNode.ExclusiveWeight; flameNode.Percentage = ScaleWeight(flameNode); flameNode.ExclusivePercentage = ScaleExclusiveWeight(flameNode); } else { // For the root node, exclusive time is 0% and inclusive 100%. flameNode.Percentage = 1; } return flameNode; } //? TODO: Timeline not implemented // public void BuildTimeline(ProfileData data, int threadId) { // Trace.WriteLine($"Timeline Samples: {data.Samples.Count}"); // data.Samples.Sort((a, b) => a.Sample.Time.CompareTo(b.Sample.Time)); // // var flameNode = CreateFlameGraphNode(null, RootWeight, 0); // flameNode.StartTime = TimeSpan.MaxValue; // flameNode.EndTime = TimeSpan.MinValue; // // if (data.Samples.Count > 0) { // profileStartTime_ = data.Samples[0].Sample.Time; // profileEndTime_ = data.Samples[^1].Sample.Time; // } // // foreach (var (sample, stack) in data.Samples) { // if (threadId != -1 && stack.Context.ThreadId != threadId) { // continue; // } // // AddSample(flameNode, sample, stack); // // flameNode.StartTime = TimeSpan.FromTicks(Math.Min(flameNode.StartTime.Ticks, sample.Time.Ticks)); // flameNode.EndTime = // TimeSpan.FromTicks(Math.Max(flameNode.EndTime.Ticks, sample.Time.Ticks + sample.Weight.Ticks)); // flameNode.Weight = flameNode.EndTime - flameNode.StartTime + sample.Weight; // } // // //flameNode.Duration = flameNode.EndTime - flameNode.StartTime; // RootNode = flameNode; // RootWeight = flameNode.Weight; // } public void Dump(FlameGraphNode node, int level = 0) { Trace.Write(new string(' ', level * 2)); Trace.WriteLine($"{node.CallTreeNode?.FunctionName} | {node.Depth} | {node.Weight.TotalMilliseconds}"); if (node.Weight.Ticks == 0) { Trace.WriteLine("=> no weight"); } if (node.HasChildren) { foreach (var child in node.Children) { Dump(child, level + 1); } } if (level < 1) { Trace.WriteLine("=============================================="); } else if (level < 2) { Trace.WriteLine("----------------------"); } } } ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphHost.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphHost.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.UI.Controls; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.UI.Profile; public partial class FlameGraphHost : UserControl, IFunctionProfileInfoProvider, INotifyPropertyChanged { private const double ZoomAmount = 1200; private const double ScrollWheelZoomAmount = 800; private const double TimePerFrame = 1000.0 / 60; // ~16.6ms per frame at 60Hz. private const double FastPanOffset = 1000; private const double DefaultPanOffset = 100; private const double ZoomAnimationDuration = TimePerFrame * 8; private const double EnlargeAnimationDuration = TimePerFrame * 10; private const double ScrollWheelZoomAnimationDuration = TimePerFrame * 4; private Stack stateStack_; private ProfileCallTree callTree_; private bool dragging_; private Point draggingStart_; private Point draggingViewStart_; private double endOffsetX_; private FlameGraphNode enlargedNode_; private bool ignoreScrollEvent_; private double initialOffsetX_; private double initialWidth_; private DateTime lastWheelZoomTime_; private FlameGraphNode rootNode_; private FlameGraphSettings settings_; private bool showNodePanel_; private PopupHoverPreview nodeHoverPreview_; private DoubleAnimation widthAnimation_; private DoubleAnimation zoomAnimation_; private double zoomPointX_; private bool enableSingleNodeActions_; private List<(ProfileCallTreeNode Node, HighlightingStyle Style)> unmatchedMarkedNodes_; public FlameGraphHost() { InitializeComponent(); settings_ = App.Settings.FlameGraphSettings; stateStack_ = new Stack(); SetupEvents(); DataContext = this; ShowNodePanel = true; } public IUISession Session { get; set; } public FlameGraph FlameGraph => GraphViewer.FlameGraph; public List SelectedNodes => GraphViewer.SelectedNodes; public bool UseAnimations => App.Settings.GeneralSettings.UseAnimations; public bool EnableSingleNodeActions { get => enableSingleNodeActions_; set => SetField(ref enableSingleNodeActions_, value); } public RelayCommand SelectFunctionCallTreeCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.CallTree); }); public RelayCommand SelectFunctionTimelineCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.Timeline); }); public RelayCommand SelectFunctionSourceCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.Source); }); public RelayCommand CopyFunctionNameCommand => new(async obj => { string text = ""; foreach (var node in SelectedNodes) { if (!string.IsNullOrEmpty(text)) { text += Environment.NewLine; } if (node.HasFunction) { text += Session.CompilerInfo.NameProvider.GetFunctionName(node.Function); } } Clipboard.SetText(text); }); public RelayCommand CopyDemangledFunctionNameCommand => new(async obj => { string text = ""; foreach (var node in SelectedNodes) { if (!string.IsNullOrEmpty(text)) { text += Environment.NewLine; } if (node.HasFunction) { text += Session.CompilerInfo.NameProvider.FormatFunctionName(node.Function); } } Clipboard.SetText(text); }); public RelayCommand CopyFunctionDetailsCommand => new(async obj => { if (SelectedNodes.Count > 0) { var funcList = new List(); foreach (var item in SelectedNodes) { if (item.HasFunction) { funcList.Add(item); } } SearchableProfileItem.CopyFunctionListAsHtml(funcList); } }); public RelayCommand MarkInstanceCommand => new(async obj => { MarkSelectedNodes(obj, (node, color) => GraphViewer.MarkNode(node, GraphViewer.MarkedColoredNodeStyle(color))); }); public RelayCommand MarkAllInstancesCommand => new(async obj => { MarkSelectedNodes( obj, (node, color) => MarkFunctionInstances(node.Function, GraphViewer.MarkedColoredNodeStyle(color))); }); public RelayCommand MarkModuleCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; MarkSelectedNodes(obj, (node, color) => markingSettings.AddModuleColor(node.ModuleName, color)); markingSettings.UseModuleColors = true; SettingsUpdated(settings_); MarkingChanged?.Invoke(this, EventArgs.Empty); }); public RelayCommand MarkFunctionCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; MarkSelectedNodes(obj, (node, color) => markingSettings.AddFunctionColor(node.FunctionName, color)); markingSettings.UseFunctionColors = true; SettingsUpdated(settings_); MarkingChanged?.Invoke(this, EventArgs.Empty); }); public RelayCommand MarkTimelineCommand => new(async obj => { if (obj is SelectedColorEventArgs e && GraphViewer.SelectedNode is {HasFunction: true}) { GraphViewer.MarkNode(GraphViewer.SelectedNode, GraphViewer.MarkedColoredNodeStyle(e.SelectedColor)); await Session.MarkProfileFunction(GraphViewer.SelectedNode.CallTreeNode, ToolPanelKind.Timeline, GraphViewer.MarkedColoredNodeStyle(e.SelectedColor)); } }); public RelayCommand PreviewFunctionCommand => new(async obj => { if (GraphViewer.SelectedNode is {HasFunction: true}) { var brush = GetMarkedNodeColor(GraphViewer.SelectedNode); await IRDocumentPopupInstance.ShowPreviewPopup(GraphViewer.SelectedNode.Function, "", GraphViewer, Session, null, false, brush); } }); public RelayCommand PreviewFunctionInstanceCommand => new(async obj => { if (GraphViewer.SelectedNode is {HasFunction: true}) { var filter = new ProfileSampleFilter(GraphViewer.SelectedNode.CallTreeNode); var brush = GetMarkedNodeColor(GraphViewer.SelectedNode); await IRDocumentPopupInstance.ShowPreviewPopup(GraphViewer.SelectedNode.Function, "", GraphViewer, Session, filter, false, brush); } }); public RelayCommand OpenInstanceCommand => new(async obj => { if (GraphViewer.SelectedNode is {HasFunction: true}) { var filter = new ProfileSampleFilter(GraphViewer.SelectedNode.CallTreeNode); var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await Session.OpenProfileFunction(GraphViewer.SelectedNode.CallTreeNode, mode, filter); } }); public RelayCommand OpenInstanceInNewTabCommand => new(async obj => { if (GraphViewer.SelectedNode is {HasFunction: true}) { var filter = new ProfileSampleFilter(GraphViewer.SelectedNode.CallTreeNode); await Session.OpenProfileFunction(GraphViewer.SelectedNode.CallTreeNode, OpenSectionKind.NewTab, filter); } }); public bool ShowNodePanel { get => showNodePanel_; set => SetField(ref showNodePanel_, value); } private double GraphAreaWidth => Math.Max(0, GraphHost.ActualWidth - SystemParameters.VerticalScrollBarWidth); private double GraphAreaHeight => GraphHost.ViewportHeight; private Rect GraphArea => new(0, 0, GraphAreaWidth, GraphAreaHeight); private Rect GraphVisibleArea => new(GraphHost.HorizontalOffset, GraphHost.VerticalOffset, GraphAreaWidth, GraphAreaHeight); private Rect GraphHostBounds => new(0, 0, GraphHost.ActualWidth, GraphHost.ActualHeight); private double GraphZoomRatio => GraphViewer.MaxGraphWidth / GraphAreaWidth; private double CenterZoomPointX => GraphHost.HorizontalOffset + GraphAreaWidth / 2; private double PanOffset => Utils.IsKeyboardModifierActive() ? FastPanOffset : DefaultPanOffset; public List GetBacktrace(ProfileCallTreeNode node) { return callTree_.GetBacktrace(node); } public (List, List Modules) GetTopFunctionsAndModules( ProfileCallTreeNode node) { return callTree_.GetTopFunctionsAndModules(node); } public event PropertyChangedEventHandler PropertyChanged; private void MarkSelectedNodes(object obj, Action action) { if (obj is SelectedColorEventArgs e) { foreach (var node in SelectedNodes) { if (node.HasFunction) { action(node, e.SelectedColor); } } } } private Brush GetMarkedNodeColor(FlameGraphNode node) { if (node is not {HasFunction: true}) { return null; } return App.Settings.MarkingSettings. GetMarkedNodeBrush(node.FunctionName, node.ModuleName); } public event EventHandler MarkingChanged; public event EventHandler NodeSelected; public event EventHandler NodesDeselected; public event EventHandler HorizontalOffsetChanged; public event EventHandler MaxWidthChanged; public event EventHandler RootNodeChanged; public event EventHandler RootNodeCleared; private static double Lerp(double start, double end, double progress) { return start + (end - start) * progress; } public async Task InitializeFlameGraph(ProfileCallTree callTree) { List<(ProfileCallTreeNode Node, HighlightingStyle Style)> markedNodes = null; if (GraphViewer.IsInitialized) { markedNodes = new List<(ProfileCallTreeNode Node, HighlightingStyle Style)>(); GraphViewer.SaveFixedMarkedNodes(markedNodes); // Combined nodes currently marked in instance N-1 of the call tree, // with nodes marked from a previous call tree instance N-2... which // could not be associated with flame graph nodes because they were filtered out. if (unmatchedMarkedNodes_ != null) { markedNodes.AddRange(unmatchedMarkedNodes_); } Reset(); } callTree_ = callTree; if (callTree_ != null) { await GraphViewer.Initialize(callTree, GraphArea, settings_, Session); ResetWidth(); if (markedNodes != null) { unmatchedMarkedNodes_ = GraphViewer.RestoreFixedMarkedNodes(markedNodes, callTree); } } } public async Task InitializeTimeline(ProfileCallTree callTree, int threadId) { //? TODO: Timeline-style view not used yet. if (GraphViewer.IsInitialized) { Reset(); } callTree_ = callTree; if (callTree != null && !GraphViewer.IsInitialized) { await GraphViewer.Initialize(callTree, GraphArea, settings_, Session, true, threadId); } } public void Redraw() { GraphViewer.Redraw(); } private void HostOnKeyUp(object sender, KeyEventArgs e) { if (Utils.IsControlModifierActive()) { Cursor = Cursors.Arrow; } } private void BringNodeIntoView(FlameGraphNode node, bool fitSize) { if (node.IsDummyNodeOrChild) { // If the node is not visible at all and has no bounds computed, // adjust the zoom first to make the node visible, then scroll to it. EnlargeNodeIntoView(node); } var bounds = GraphViewer.ComputeNodeBounds(node); var graphArea = GraphVisibleArea; DoubleAnimation animation1 = null; DoubleAnimation animation2 = null; if (bounds.Left < graphArea.Left || bounds.Right > graphArea.Right) { //? TODO: If node is outside on the right, increase offset to show it all animation1 = ScrollToHorizontalOffset(bounds.Left); } if (bounds.Top < graphArea.Top || bounds.Bottom > graphArea.Bottom) { animation2 = ScrollToVerticalOffset(bounds.Top); } if (fitSize) { switch ((animation1 != null, animation2 != null)) { case (true, true): case (true, false): { animation1.Completed += (sender, e) => EnlargeNodeIntoView(node); break; } case (false, true): { animation2.Completed += (sender, e) => EnlargeNodeIntoView(node); break; } default: { EnlargeNodeIntoView(node); break; } } } if (UseAnimations) { animation1?.BeginAnimation(FlameGraphHorizontalOffsetProperty, animation1, HandoffBehavior.SnapshotAndReplace); animation2?.BeginAnimation(FlameGraphVerticalOffsetProperty, animation2, HandoffBehavior.SnapshotAndReplace); } } public void SetHorizontalOffset(double offset) { if (!GraphViewer.IsInitialized) { return; } ignoreScrollEvent_ = true; GraphHost.ScrollToHorizontalOffset(offset); } public async Task ChangeRootNode(FlameGraphNode node, bool saveState = true) { // Update the undo stack. if (saveState) { SaveCurrentState(FlameGraphStateKind.ChangeRootNode); } ResetHighlightedNodes(); SetHorizontalOffset(0); rootNode_ = node; await GraphViewer.Initialize(GraphViewer.FlameGraph.CallTree, node.CallTreeNode, GraphHostBounds, settings_, Session); GraphViewer.RestoreFixedMarkedNodes(); if (node.HasFunction) { RootNodeChanged?.Invoke(this, node); } } public async Task RestorePreviousState() { if (!stateStack_.TryPop(out var state)) { return; } switch (state.Kind) { case FlameGraphStateKind.EnlargeNode: { // IF there is no node the root node should be selected. var node = state.Node ?? GraphViewer.FlameGraph.RootNode; await EnlargeNode(node, false, state.VerticalOffset, state.HorizontalOffset); break; } case FlameGraphStateKind.ChangeRootNode: { RootNodeCleared?.Invoke(this, EventArgs.Empty); await ChangeRootNode(state.Node, false); GraphViewer.RestoreFixedMarkedNodes(); break; } default: { SetMaxWidth(state.MaxGraphWidth); GraphHost.ScrollToHorizontalOffset(state.HorizontalOffset); GraphHost.ScrollToVerticalOffset(state.VerticalOffset); break; } } } public void SetMaxWidth(double maxWidth, double duration = ZoomAnimationDuration) { if (!GraphViewer.IsInitialized) { return; } if (Math.Abs(maxWidth - GraphViewer.MaxGraphWidth) < double.Epsilon) { return; } if (UseAnimations) { var animation = new DoubleAnimation(GraphViewer.MaxGraphWidth, maxWidth, TimeSpan.FromMilliseconds(duration)); animation.Completed += (sender, args) => { widthAnimation_ = null; MaxWidthChanged?.Invoke(this, GraphViewer.MaxGraphWidth); }; widthAnimation_ = animation; BeginAnimation(FlameGraphWidthProperty, animation, HandoffBehavior.SnapshotAndReplace); } else { CancelWidthAnimation(); GraphViewer.UpdateMaxWidth(maxWidth); MaxWidthChanged?.Invoke(this, GraphViewer.MaxGraphWidth); } } public void ResetWidth() { // Hack due to possible WPF bug that forces a re-layout of the flame graph // so that the scroll bars are displayed if needed. Dispatcher.Invoke(() => { GraphViewer.InvalidateMeasure(); GraphViewer.InvalidateVisual(); // If there is a vertical scroll bar, resize the flame graph to fit // the view and not show a horizontal scroll bar initially. Dispatcher.Invoke(() => { ResetWidthImpl(); }, DispatcherPriority.ContextIdle); }, DispatcherPriority.Normal); } private void ResetWidthImpl() { if (!GraphViewer.IsInitialized) { return; } SetMaxWidth(GraphAreaWidth); ScrollToVerticalOffset(0); ScrollToHorizontalOffset(0); ResetHighlightedNodes(); } public void ZoomIn() { ZoomIn(CenterZoomPointX); } public void ZoomOut() { ZoomOut(CenterZoomPointX); } private async Task NavigateToParentNode() { if (enlargedNode_ != null && enlargedNode_.Parent != null) { SelectNode(enlargedNode_.Parent); await EnlargeNode(enlargedNode_.Parent); } else if (rootNode_ != null && rootNode_.Parent != null) { await ChangeRootNode(rootNode_.Parent); } } public void Reset() { callTree_ = null; ScrollToOffsets(0, 0); if (!GraphViewer.IsInitialized) { return; } ResetHighlightedNodes(); GraphViewer.Reset(); } public void SelectNode(FlameGraphNode node, bool fitSize = false, bool bringIntoView = true) { GraphViewer.SelectNode(node); if (bringIntoView) { BringNodeIntoView(node, fitSize); } } public void SelectNode(ProfileCallTreeNode node, bool fitSize = false, bool bringIntoView = true) { if (!GraphViewer.IsInitialized) { return; } var fgNode = GraphViewer.SelectNode(node); if (bringIntoView) { BringNodeIntoView(fgNode, fitSize); } } public void SelectNodes(List nodes, bool fitSize = false, bool bringIntoView = true) { if (!GraphViewer.IsInitialized) { return; } var fgNodes = GraphViewer.SelectNodes(nodes); if (bringIntoView && fgNodes.Count > 0) { BringNodeIntoView(fgNodes[0], fitSize); } } public void MarkFunctions(List nodes, HighlightingStyle style) { if (!GraphViewer.IsInitialized) { return; } GraphViewer.MarkNodes(nodes, style, false); } public void MarkFunctionInstances(IRTextFunction func, HighlightingStyle style) { if (!GraphViewer.IsInitialized) { return; } var nodes = callTree_.GetCallTreeNodes(func); GraphViewer.MarkNodes(nodes, style, true); } public void ClearMarkedFunctions(bool clearFixedNodes = false) { if (!GraphViewer.IsInitialized) { return; } GraphViewer.ResetMarkedNodes(clearFixedNodes); if (clearFixedNodes) { unmatchedMarkedNodes_ = null; } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private async Task SelectFunctionInPanel(ToolPanelKind panelKind) { if (GraphViewer.SelectedNode is {HasFunction: true}) { await Session.SelectProfileFunctionInPanel(GraphViewer.SelectedNode.CallTreeNode, panelKind); } } private void SetupEvents() { GraphHost.SizeChanged += (sender, args) => { if (GraphViewer.IsInitialized && args.NewSize.Width > GraphViewer.MaxGraphWidth) { SetMaxWidth(args.NewSize.Width); } }; // Setup events for the flame graph area. GraphHost.PreviewMouseWheel += OnPreviewMouseWheel; MouseLeftButtonDown += OnMouseLeftButtonDown; MouseLeftButtonUp += OnMouseLeftButtonUp; MouseRightButtonDown += OnMouseRightButtonDown; MouseDoubleClick += OnMouseDoubleClick; MouseMove += OnMouseMove; MouseDown += OnMouseDown; // Handles back button. KeyDown += HostOnKeyDown; KeyUp += HostOnKeyUp; SetupPreviewPopup(); } private void SetupPreviewPopup() { if (nodeHoverPreview_ != null) { nodeHoverPreview_.Unregister(); nodeHoverPreview_ = null; } if (!settings_.ShowNodePopup) { return; } nodeHoverPreview_ = new PopupHoverPreview(GraphViewer, TimeSpan.FromMilliseconds(settings_.NodePopupDuration), (mousePoint, previewPoint) => { var pointedNode = GraphViewer.FindPointedNode(mousePoint); var callNode = pointedNode?.CallTreeNode; if (callNode != null) { // If popup already opened for this node reuse the instance. if (nodeHoverPreview_.PreviewPopup is CallTreeNodePopup popup) { popup.UpdatePosition(previewPoint, GraphViewer); } else { popup = new CallTreeNodePopup( callNode, this, previewPoint, GraphViewer, Session); } popup.UpdateNode(callNode); return popup; } return null; }, (mousePoint, popup) => { if (popup is CallTreeNodePopup previewPopup) { // Hide if not over the same node anymore. var pointedNode = GraphViewer.FindPointedNode(mousePoint); return previewPopup.CallTreeNode.CallTreeNode != pointedNode?.CallTreeNode; } return true; }, popup => { Session.RegisterDetachedPanel(popup); }); } private void HidePreviewPopup() { if (nodeHoverPreview_ != null) { nodeHoverPreview_.Hide(); } } private async void OnMouseDown(object sender, MouseButtonEventArgs e) { if (e.ChangedButton == MouseButton.Middle && e.ButtonState == MouseButtonState.Pressed) { // Select the node under the mouse cursor first, then expand. var point = e.GetPosition(GraphViewer); var node = GraphViewer.FindPointedNode(point); if (node != null && node != GraphViewer.SelectedNode) { SelectNode(node, false, false); } await EnlargeNode(GraphViewer.SelectedNode); e.Handled = true; } else if (e.ChangedButton == MouseButton.XButton1 && e.ButtonState == MouseButtonState.Pressed) { await RestorePreviousState(); e.Handled = true; } } private async void OnMouseDoubleClick(object sender, MouseButtonEventArgs e) { if (IsMouseOutsideViewport(e)) { return; } var point = e.GetPosition(GraphViewer); var pointedNode = GraphViewer.FindPointedNode(point); if (pointedNode != null) { await HandleOpenFunctionAction(pointedNode); e.Handled = true; } else { double zoomPointX = e.GetPosition(GraphViewer).X; if (Utils.IsShiftModifierActive()) { ZoomOut(zoomPointX, false); e.Handled = true; } else { ZoomIn(zoomPointX, false); e.Handled = true; } } } private async Task OpenFunction(FlameGraphNode node) { await OpenFunction(node.CallTreeNode); } private async Task OpenFunction(ProfileCallTreeNode node) { if (node is {HasFunction: true} && node.Function.HasSections) { var openMode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await Session.OpenProfileFunction(node, openMode); } } private DoubleAnimation ScrollToHorizontalOffset(double offset, double duration = ZoomAnimationDuration) { if (UseAnimations) { var animation = new DoubleAnimation(GraphHost.HorizontalOffset, offset, TimeSpan.FromMilliseconds(duration)); BeginAnimation(FlameGraphHorizontalOffsetProperty, animation, HandoffBehavior.SnapshotAndReplace); return animation; } else { GraphHost.ScrollToHorizontalOffset(offset); return null; } } private DoubleAnimation ScrollToVerticalOffset(double offset, double duration = ZoomAnimationDuration) { if (UseAnimations) { var animation1 = new DoubleAnimation(GraphHost.VerticalOffset, offset, TimeSpan.FromMilliseconds(duration)); BeginAnimation(FlameGraphVerticalOffsetProperty, animation1, HandoffBehavior.SnapshotAndReplace); return animation1; } else { GraphHost.ScrollToVerticalOffset(offset); return null; } } private void EnlargeNodeIntoView(FlameGraphNode node) { // Adjust the zoom level so that the node is at least MinNodeWidth large. const double MinNodeWidth = 20; var bounds = GraphViewer.ComputeNodeBounds(node); double zoomX = 0; if (bounds.Width < MinNodeWidth) { zoomX = MinNodeWidth - bounds.Width; } else if (bounds.Width > GraphAreaWidth) { zoomX = GraphAreaWidth - bounds.Width; } else { return; } double zoomPointX = bounds.Left; double nodeRatio = GraphViewer.FlameGraph.InverseScaleWeight(node.Weight); double zoomAmount = zoomX * nodeRatio; AdjustZoom(zoomAmount, zoomPointX, UseAnimations, ZoomAnimationDuration); } private async Task EnlargeNode(FlameGraphNode node, bool saveState = true, double verticalOffset = double.NaN, double horizontalOffset = double.NaN) { if (node == null) { return; } if (Utils.IsAltModifierActive()) { await ChangeRootNode(node); return; } // Update the undo stack. if (saveState) { SaveCurrentState(FlameGraphStateKind.EnlargeNode); } // How wide the entire graph needs to be so that the node fils the view. double ratio = GraphViewer.FlameGraph.InverseScaleWeight(node.Weight); double newMaxWidth = GraphAreaWidth * ratio; double prevRatio = GraphViewer.MaxGraphWidth / GraphAreaWidth; double offsetRatio = prevRatio > 0 ? ratio / prevRatio : ratio; enlargedNode_ = node; initialWidth_ = newMaxWidth; initialOffsetX_ = GraphHost.HorizontalOffset; endOffsetX_ = GraphViewer.ComputeNodeBounds(node).X * offsetRatio; if (!double.IsNaN(horizontalOffset)) { endOffsetX_ = horizontalOffset; } SetMaxWidth(newMaxWidth, EnlargeAnimationDuration); if (UseAnimations) { var horizontalAnim = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(EnlargeAnimationDuration)); BeginAnimation(FlameGraphEnlargeNodeProperty, horizontalAnim, HandoffBehavior.SnapshotAndReplace); } else { GraphHost.ScrollToHorizontalOffset(endOffsetX_); } if (!double.IsNaN(verticalOffset)) { if (UseAnimations) { var verticalAnim = new DoubleAnimation(GraphHost.VerticalOffset, verticalOffset, TimeSpan.FromMilliseconds(EnlargeAnimationDuration)); BeginAnimation(FlameGraphVerticalOffsetProperty, verticalAnim, HandoffBehavior.SnapshotAndReplace); } else { GraphHost.ScrollToVerticalOffset(verticalOffset); } } } private void SaveCurrentState(FlameGraphStateKind changeKind) { var state = new FlameGraphState { Kind = changeKind, MaxGraphWidth = GraphViewer.MaxGraphWidth, HorizontalOffset = GraphHost.HorizontalOffset, VerticalOffset = GraphHost.VerticalOffset }; switch (changeKind) { case FlameGraphStateKind.EnlargeNode: { state.Node = enlargedNode_; break; } case FlameGraphStateKind.ChangeRootNode: { state.Node = GraphViewer.FlameGraph.RootNode; break; } } stateStack_.Push(state); } private void ResetHighlightedNodes() { GraphViewer.ResetNodeHighlighting(); } private void OnMouseMove(object sender, MouseEventArgs e) { if (dragging_) { var offset = draggingViewStart_ - (e.GetPosition(GraphHost) - draggingStart_); GraphHost.ScrollToHorizontalOffset(offset.X); GraphHost.ScrollToVerticalOffset(offset.Y); CaptureMouse(); e.Handled = true; } } private async void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { if (dragging_) { EndMouseDragging(); e.Handled = true; // Don't deselect nodes if dragging was done. var draggingEnd = e.GetPosition(GraphHost); var draggingDistance = draggingEnd - draggingStart_; if (Math.Abs(draggingDistance.X) > double.Epsilon || Math.Abs(draggingDistance.Y) > double.Epsilon) { return; } } HandleNodeSelection(e); } private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { // Start dragging the graph only if the click starts inside the scroll area, // excluding the scroll bars, and it in an empty spot. if (IsMouseOutsideViewport(e)) { return; } HidePreviewPopup(); var pointedNode = GraphViewer.FindPointedNode(e.GetPosition(GraphViewer)); if (pointedNode == null) { StartMouseDragging(e); e.Handled = true; } } private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e) { HidePreviewPopup(); HandleNodeSelection(e); } private bool HandleNodeSelection(MouseButtonEventArgs e) { if (IsMouseOutsideViewport(e)) { return false; } var pointedNode = GraphViewer.FindPointedNode(e.GetPosition(GraphViewer)); if (pointedNode == null) { GraphViewer.ClearSelection(); // Click outside graph is captured here. NodesDeselected?.Invoke(this, EventArgs.Empty); EnableSingleNodeActions = SelectedNodes.Count < 2; return false; } else { NodeSelected?.Invoke(this, pointedNode); EnableSingleNodeActions = SelectedNodes.Count < 2; return true; } } private void StartMouseDragging(MouseButtonEventArgs e) { HidePreviewPopup(); dragging_ = true; draggingStart_ = e.GetPosition(GraphHost); draggingViewStart_ = new Point(GraphHost.HorizontalOffset, GraphHost.VerticalOffset); Cursor = Cursors.SizeAll; } private bool IsMouseOutsideViewport(MouseButtonEventArgs e) { var point = e.GetPosition(GraphHost); return point.X < 0 || point.Y < 0 || point.X >= GraphHost.ViewportWidth || point.Y >= GraphHost.ViewportHeight; } private async void HostOnKeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.Return: { if (GraphViewer.SelectedNode != null) { await HandleOpenFunctionAction(GraphViewer.SelectedNode); e.Handled = true; } break; } case Key.Space: { await EnlargeNode(GraphViewer.SelectedNode); e.Handled = true; break; } case Key.Left: { ScrollToRelativeOffsets(-PanOffset, 0); e.Handled = true; break; } case Key.Right: { ScrollToRelativeOffsets(PanOffset, 0); e.Handled = true; break; } case Key.Up: { if (Utils.IsControlModifierActive()) { await NavigateToParentNode(); } else { ScrollToRelativeOffsets(0, -PanOffset); } e.Handled = true; break; } case Key.Down: { if (Utils.IsControlModifierActive()) { await NavigateToChildNode(); } else { ScrollToRelativeOffsets(0, PanOffset); } e.Handled = true; break; } case Key.OemPlus: case Key.Add: { if (Utils.IsControlModifierActive()) { ZoomIn(CenterZoomPointX); e.Handled = true; } break; } case Key.OemMinus: case Key.Subtract: { if (Utils.IsControlModifierActive()) { ZoomOut(CenterZoomPointX); e.Handled = true; } break; } case Key.D0: case Key.NumPad0: { if (Utils.IsControlModifierActive()) { ResetWidth(); e.Handled = true; } break; } case Key.Back: { await RestorePreviousState(); e.Handled = true; break; } } if (e.Handled) { HidePreviewPopup(); } } private async Task HandleOpenFunctionAction(FlameGraphNode node) { if (Utils.IsAltModifierActive()) { if (Utils.IsShiftModifierActive()) { // Ctrl+Shift+action => preview function instance. PreviewFunctionInstanceCommand.Execute(node); } else { // Ctrl+Shift+action => preview function. PreviewFunctionCommand.Execute(node); } } else { // action => open function. // Shift+action => open function instance. if (Utils.IsShiftModifierActive()) { OpenInstanceInNewTabCommand.Execute(node); } else { await OpenFunction(node); } } } private void ScrollToRelativeOffsets(double adjustmentX, double adjustmentY) { double offsetX = GraphHost.HorizontalOffset; double offsetY = GraphHost.VerticalOffset; ScrollToOffsets(offsetX + adjustmentX, offsetY + adjustmentY); } private void ScrollToOffsets(double offsetX, double offsetY) { GraphHost.ScrollToHorizontalOffset(offsetX); GraphHost.ScrollToVerticalOffset(offsetY); } private void CancelWidthAnimation() { if (widthAnimation_ != null) { widthAnimation_.BeginTime = null; BeginAnimation(FlameGraphWidthProperty, widthAnimation_); widthAnimation_ = null; } } private void CancelZoomAnimation() { if (zoomAnimation_ != null) { zoomAnimation_.BeginTime = null; BeginAnimation(FlameGraphWidthProperty, zoomAnimation_); zoomAnimation_ = null; } } private void AdjustMaxWidth(double amount, double duration = ZoomAnimationDuration) { double newWidth = Math.Max(GraphAreaWidth, GraphViewer.MaxGraphWidth + amount); SetMaxWidth(newWidth, duration); } private void OnPreviewMouseWheel(object sender, MouseWheelEventArgs e) { HidePreviewPopup(); if (Utils.IsShiftModifierActive()) { // Turn vertical scrolling into horizontal scrolling. GraphHost.ScrollToHorizontalOffset(GraphHost.HorizontalOffset - e.Delta); e.Handled = true; return; } if (!(Utils.IsKeyboardModifierActive() || e.LeftButton == MouseButtonState.Pressed || e.RightButton == MouseButtonState.Pressed)) { // Zoom when Ctrl/Alt/Shift or left mouse button are pressed. return; } // Cancel ongoing dragging operation. if (dragging_) { EndMouseDragging(); } // Disable animation if scrolling without interruption. var time = DateTime.UtcNow; var timeElapsed = time - lastWheelZoomTime_; bool animate = UseAnimations && timeElapsed.TotalMilliseconds > ScrollWheelZoomAnimationDuration; double amount = ScrollWheelZoomAmount * GraphZoomRatio; // Keep step consistent. double step = amount * Math.CopySign(1 + e.Delta / 1000.0, e.Delta); double zoomPointX = e.GetPosition(GraphViewer).X; AdjustZoom(step, zoomPointX, animate, ScrollWheelZoomAnimationDuration); lastWheelZoomTime_ = time; e.Handled = true; } private void EndMouseDragging() { dragging_ = false; Cursor = Cursors.Arrow; ReleaseMouseCapture(); } private void AdjustZoom(double step, double zoomPointX, bool animate, double duration = 0.0) { double initialWidth = GraphViewer.MaxGraphWidth; double initialOffsetX = GraphHost.HorizontalOffset; AdjustMaxWidth(step, duration); // Maintain the zoom point under the mouse by adjusting the horizontal offset. if (UseAnimations) { zoomPointX_ = zoomPointX; initialWidth_ = initialWidth; initialOffsetX_ = initialOffsetX; var animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(duration)); animation.Completed += (sender, args) => { zoomAnimation_ = null; }; zoomAnimation_ = animation; BeginAnimation(FlameGraphZoomProperty, animation, HandoffBehavior.SnapshotAndReplace); } else { CancelWidthAnimation(); CancelZoomAnimation(); AdjustGraphOffset(zoomPointX, initialWidth, initialOffsetX); } } private void AdjustGraphOffset(double zoomPointX, double initialWidth, double initialOffsetX) { double zoom = GraphViewer.MaxGraphWidth / initialWidth; double offsetAdjustment = initialOffsetX / zoom + zoomPointX; GraphHost.ScrollToHorizontalOffset(offsetAdjustment * zoom - zoomPointX); } private void AdjustEnlargedNodeOffset(double progress) { double offset = Lerp(initialOffsetX_, endOffsetX_, progress); GraphHost.ScrollToHorizontalOffset(offset); } private void AdjustZoomPointOffset(double progress) { double zoom = GraphViewer.MaxGraphWidth / initialWidth_; double offsetAdjustment = initialOffsetX_ / zoom + zoomPointX_; GraphHost.ScrollToHorizontalOffset(offsetAdjustment * zoom - zoomPointX_); } private void ExecuteGraphZoomIn(object sender, ExecutedRoutedEventArgs e) { ZoomIn(CenterZoomPointX); } private void ZoomIn(double zoomPointX, bool considerSelectedNode = true) { if (considerSelectedNode && GraphViewer.SelectedNode != null) { var bounds = GraphViewer.ComputeNodeBounds(GraphViewer.SelectedNode); zoomPointX = bounds.Left + bounds.Width / 2; } AdjustZoom(ZoomAmount * GraphZoomRatio, zoomPointX, UseAnimations, ZoomAnimationDuration); } private void ExecuteGraphZoomOut(object sender, ExecutedRoutedEventArgs e) { ZoomOut(CenterZoomPointX); } private void ZoomOut(double zoomPointX, bool considerSelectedNode = true) { if (considerSelectedNode && GraphViewer.SelectedNode != null) { var bounds = GraphViewer.ComputeNodeBounds(GraphViewer.SelectedNode); zoomPointX = bounds.Left + bounds.Width / 2; } AdjustZoom(-ZoomAmount * (GraphZoomRatio * 0.5), zoomPointX, UseAnimations, ZoomAnimationDuration); } private void GraphHost_OnScrollChanged(object sender, ScrollChangedEventArgs e) { if (!GraphViewer.IsInitialized) { return; } GraphViewer.UpdateVisibleArea(GraphVisibleArea); if (!ignoreScrollEvent_) { HorizontalOffsetChanged?.Invoke(this, GraphHost.HorizontalOffset); } else { ignoreScrollEvent_ = false; } } private async Task NavigateToChildNode() { if (enlargedNode_ != null && enlargedNode_.HasChildren) { GraphViewer.SelectNode(enlargedNode_.Children[0]); await EnlargeNode(enlargedNode_.Children[0]); } else if (rootNode_ != null && rootNode_.HasChildren) { await ChangeRootNode(rootNode_.Children[0]); } } private async void SelectFunctionExecuted(object sender, ExecutedRoutedEventArgs e) { await SelectFunctionInPanel(ToolPanelKind.Section); } private async void OpenFunctionExecuted(object sender, ExecutedRoutedEventArgs e) { await OpenFunction(GraphViewer.SelectedNode, OpenSectionKind.ReplaceCurrent); } private async Task OpenFunction(FlameGraphNode node, OpenSectionKind openMode) { if (node is {HasFunction: true}) { await Session.OpenProfileFunction(node.CallTreeNode, openMode); } } private async void OpenFunctionInNewTab(object sender, ExecutedRoutedEventArgs e) { await OpenFunction(GraphViewer.SelectedNode, OpenSectionKind.NewTab); } private async void ChangeRootNodeExecuted(object sender, ExecutedRoutedEventArgs e) { if (GraphViewer.SelectedNode != null) { await ChangeRootNode(GraphViewer.SelectedNode); } } private void MarkAllInstancesExecuted(object sender, ExecutedRoutedEventArgs e) { if (GraphViewer.SelectedNode != null && GraphViewer.SelectedNode.HasFunction) { MarkFunctionInstances(GraphViewer.SelectedNode.Function, GraphViewer.MarkedNodeStyle); } } private void MarkInstanceExecuted(object sender, ExecutedRoutedEventArgs e) { if (GraphViewer.SelectedNode != null && GraphViewer.SelectedNode.HasFunction) { GraphViewer.MarkNode(GraphViewer.SelectedNode, GraphViewer.MarkedNodeStyle); } } private void ClearMarkedNodesExecuted(object sender, ExecutedRoutedEventArgs e) { ClearMarkedFunctions(true); } private async void EnlargeNodeExecuted(object sender, ExecutedRoutedEventArgs e) { if (GraphViewer.SelectedNode != null) { await EnlargeNode(GraphViewer.SelectedNode); } } public async Task ClearRootNode() { // Undo all states until a root node change is found. while (stateStack_.TryPop(out var state)) { if (state.Kind == FlameGraphStateKind.ChangeRootNode) { RootNodeCleared?.Invoke(this, EventArgs.Empty); GraphViewer.RestoreFixedMarkedNodes(); await ChangeRootNode(state.Node, false); // May enable a previous root node. break; } } } public void SettingsUpdated(FlameGraphSettings value) { settings_ = value; GraphViewer.SettingsUpdated(value); SetupPreviewPopup(); } public void ClearSelection() { GraphViewer.ClearSelection(); } private enum FlameGraphStateKind { Default, EnlargeNode, ChangeRootNode } private class FlameGraphState { public FlameGraphStateKind Kind { get; set; } public FlameGraphNode Node { get; set; } public double MaxGraphWidth { get; set; } public double HorizontalOffset { get; set; } public double VerticalOffset { get; set; } } #region Animation support public static DependencyProperty FlameGraphWidthProperty = DependencyProperty.Register(nameof(FlameGraphWidth), typeof(double), typeof(FlameGraphHost), new PropertyMetadata(0.0, FlameGraphWidthChanged)); public static DependencyProperty FlameGraphZoomProperty = DependencyProperty.Register(nameof(FlameGraphOffset), typeof(double), typeof(FlameGraphHost), new PropertyMetadata(0.0, FlameGraphOffsetChanged)); public static DependencyProperty FlameGraphEnlargeNodeProperty = DependencyProperty.Register(nameof(FlameGraphEnlargeNodeProperty), typeof(double), typeof(FlameGraphHost), new PropertyMetadata(0.0, FlameGraphOffsetChanged)); public static DependencyProperty FlameGraphHorizontalOffsetProperty = DependencyProperty.Register(nameof(FlameGraphHorizontalOffset), typeof(double), typeof(FlameGraphHost), new PropertyMetadata(0.0, FlameGraphHorizontalOffsetChanged)); public static DependencyProperty FlameGraphVerticalOffsetProperty = DependencyProperty.Register(nameof(FlameGraphVerticalOffset), typeof(double), typeof(FlameGraphHost), new PropertyMetadata(0.0, FlameGraphVerticalOffsetChanged)); private static void FlameGraphWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is FlameGraphHost panel) { panel.FlameGraphWidth = (double)e.NewValue; } } private static void FlameGraphOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is FlameGraphHost panel) { if (e.Property == FlameGraphZoomProperty) { panel.AdjustZoomPointOffset((double)e.NewValue); } else { panel.AdjustEnlargedNodeOffset((double)e.NewValue); } } } private static void FlameGraphVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is FlameGraphHost panel) { panel.GraphHost.ScrollToVerticalOffset((double)e.NewValue); } } private static void FlameGraphHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is FlameGraphHost panel) { panel.GraphHost.ScrollToHorizontalOffset((double)e.NewValue); } } public double FlameGraphWidth { get => GraphViewer.MaxGraphWidth; set { GraphViewer.UpdateMaxWidth(value); MaxWidthChanged?.Invoke(this, value); } } public double FlameGraphOffset { get => 0; set { } } public double FlameGraphVerticalOffset { get => 0; set { } } public double FlameGraphHorizontalOffset { get => 0; set { } } #endregion } ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphPanel.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphPanel.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Threading; using ProfileExplorer.Core; using ProfileExplorer.UI.OptionsPanels; using ProfileExplorer.UI.Panels; using ProfileExplorer.Core.Utilities; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; namespace ProfileExplorer.UI.Profile; public partial class FlameGraphPanel : ToolPanelControl, IFunctionProfileInfoProvider, INotifyPropertyChanged { private FlameGraphSettings settings_; private bool panelVisible_; private ProfileCallTree callTree_; private ProfileCallTree pendingCallTree_; // Tree to show when panel becomes visible. private List searchResultNodes_; private int searchResultIndex_; private bool showSearchSection_; private string searchResultText_; private bool hasRootNode; private FlameGraphNode rootNode_; private OptionsPanelHostPopup optionsPanelPopup_; private CancelableTaskInstance searchTask_; public FlameGraphPanel() { InitializeComponent(); settings_ = App.Settings.FlameGraphSettings; searchTask_ = new CancelableTaskInstance(false); SetupEvents(); DataContext = this; CallTree = null; } public override ToolPanelKind PanelKind => ToolPanelKind.FlameGraph; public override IUISession Session { get => base.Session; set { base.Session = value; GraphHost.Session = value; NodeDetailsPanel.Initialize(value, this); } } public FlameGraphSettings Settings { get => settings_; set { settings_ = value; ReloadSettings(); OnPropertyChanged(); } } public ProfileCallTree CallTree { get => callTree_; set { SetField(ref callTree_, value); OnPropertyChanged(nameof(HasCallTree)); } } public bool HasCallTree => callTree_ != null; public bool ShowSearchSection { get => showSearchSection_; set { if (showSearchSection_ != value) { showSearchSection_ = value; OnPropertyChanged(); } } } public string SearchResultText { get => searchResultText_; set { if (searchResultText_ != value) { searchResultText_ = value; OnPropertyChanged(); } } } public bool HasRootNode { get => hasRootNode; set { if (hasRootNode != value) { hasRootNode = value; OnPropertyChanged(); } } } public FunctionMarkingSettings MarkingSettings => App.Settings.MarkingSettings; public FlameGraphNode RootNode { get => rootNode_; set => SetField(ref rootNode_, value); } public List GetBacktrace(ProfileCallTreeNode node) { return callTree_.GetBacktrace(node); } public (List, List Modules) GetTopFunctionsAndModules( ProfileCallTreeNode node) { return callTree_.GetTopFunctionsAndModules(node); } public event PropertyChangedEventHandler PropertyChanged; public override async void OnShowPanel() { base.OnShowPanel(); panelVisible_ = true; await InitializePendingCallTree(); } public override async void OnSessionStart() { base.OnSessionStart(); await InitializePendingCallTree(); } public async Task DisplayFlameGraph() { var callTree = Session.ProfileData.CallTree; await SchedulePendingCallTree(callTree); } public override void OnSessionEnd() { base.OnSessionEnd(); NodeDetailsPanel.SaveListColumnSettings(); NodeDetailsPanel.Reset(); GraphHost.Reset(); CallTree = null; pendingCallTree_ = null; } public void MarkFunctions(List nodes) { GraphHost.MarkFunctions(nodes, GraphHost.GraphViewer.SelectedNodeStyle); } public void ClearMarkedFunctions() { GraphHost.ClearMarkedFunctions(); } public async Task SelectFunction(IRTextFunction function, bool bringIntoView = true) { if (!HasCallTree) { return; } GraphHost.ClearSelection(); var groupNode = callTree_.GetCombinedCallTreeNode(function); if (groupNode is {Nodes.Count: > 0}) { GraphHost.SelectNode(groupNode, true, bringIntoView); await NodeDetailsPanel.ShowWithDetailsAsync(groupNode); } } public async Task SelectFunction(ProfileCallTreeNode node, bool bringIntoView = true, bool showDetails = true) { if (!HasCallTree) { return; } if (node is ProfileCallTreeGroupNode groupNode) { node = groupNode.Nodes[0]; } GraphHost.ClearSelection(); GraphHost.SelectNode(node, true, bringIntoView); if (showDetails) { await NodeDetailsPanel.ShowWithDetailsAsync(node); } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private async Task SchedulePendingCallTree(ProfileCallTree callTree) { // Display flame graph once the panel is visible and visible area is valid. if (pendingCallTree_ == null) { pendingCallTree_ = callTree; await InitializePendingCallTree(); } } private async Task InitializePendingCallTree() { if (pendingCallTree_ != null && panelVisible_) { // Delay the initialization to ensure the panel is actually visible // and the available area is valid. await Dispatcher.BeginInvoke(async () => { await InitializeCallTree(pendingCallTree_); }, DispatcherPriority.Render); pendingCallTree_ = null; } } private async Task InitializeCallTree(ProfileCallTree callTree) { CallTree = callTree; NodeDetailsPanel.Reset(); await GraphHost.InitializeFlameGraph(callTree); } private void SetupEvents() { GraphHost.NodeSelected += GraphHost_NodeSelected; GraphHost.NodesDeselected += GraphHost_NodesDeselected; GraphHost.RootNodeChanged += GraphHostOnRootNodeChanged; GraphHost.RootNodeCleared += GraphHostOnRootNodeCleared; GraphHost.MarkingChanged += (sender, args) => UpdateMarkingUI(); // Setup events for the node details view. NodeDetailsPanel.NodeInstanceChanged += NodeDetailsPanel_NodeInstanceChanged; NodeDetailsPanel.BacktraceNodeClick += NodeDetailsPanel_NodeClick; NodeDetailsPanel.BacktraceNodeDoubleClick += NodeDetailsPanel_NodeDoubleClick; NodeDetailsPanel.InstanceNodeClick += NodeDetailsPanel_NodeClick; NodeDetailsPanel.InstanceNodeDoubleClick += NodeDetailsPanel_NodeDoubleClick; NodeDetailsPanel.FunctionNodeClick += NodeDetailsPanel_NodeClick; NodeDetailsPanel.FunctionNodeDoubleClick += NodeDetailsPanel_NodeDoubleClick; NodeDetailsPanel.NodesSelected += NodeDetailsPanel_NodesSelected; NodeDetailsPanel.MarkingChanged += (sender, args) => UpdateMarkingUI(); } private void GraphHostOnRootNodeCleared(object sender, EventArgs e) { HasRootNode = false; RootNode = null; GraphHost.ResetWidth(); } private void GraphHostOnRootNodeChanged(object sender, FlameGraphNode node) { HasRootNode = true; RootNode = node; GraphHost.ResetWidth(); } private async Task UpdateNodeDetailsPanel() { var selectedNodes = GraphHost.SelectedNodes; if (selectedNodes.Count == 0) { NodeDetailsPanel.Reset(); } else { var callTreeNodes = new List(); foreach (var node in selectedNodes) { if (node.HasFunction) { callTreeNodes.Add(node.CallTreeNode); } } // Display the a combined view of all selected nodes. var combinedNode = await Task.Run(() => ProfileCallTree.CombinedCallTreeNodes(callTreeNodes)); await NodeDetailsPanel.ShowWithDetailsAsync(combinedNode); } } private async void GraphHost_NodesDeselected(object sender, EventArgs e) { await UpdateNodeDetailsPanel(); if (settings_.SyncSelection) { await Session.ProfileFunctionDeselected(); } if (GraphHost.SelectedNodes.Count == 0) { Session.SetApplicationStatus(""); } } private async void GraphHost_NodeSelected(object sender, FlameGraphNode node) { if (!node.HasFunction) { return; } await UpdateNodeDetailsPanel(); if (settings_.SyncSourceFile) { // Load the source file and scroll to the hottest line. await Session.OpenProfileSourceFile(node.CallTreeNode); } if (settings_.SyncSelection) { await Session.ProfileFunctionSelected(node.CallTreeNode, PanelKind); } // When selecting multiple nodes, display the weight sum in the status bar. var selectedNodes = GraphHost.SelectedNodes; if (selectedNodes.Count > 1) { var nodes = new List(); foreach (var selectedNode in selectedNodes) { if (selectedNode.HasFunction) { nodes.Add(selectedNode.CallTreeNode); } } var selectionWeight = ProfileCallTree.CombinedCallTreeNodesWeight(nodes); double weightPercentage = 0; if (rootNode_ != null) { // Scale based on the current root node, which may be overriden. weightPercentage = selectionWeight.Ticks / (double)rootNode_.Weight.Ticks; } else { weightPercentage = Session.ProfileData.ScaleFunctionWeight(selectionWeight); } string text = $"Selected {nodes.Count}: {weightPercentage.AsPercentageString()} ({selectionWeight.AsMillisecondsString()})"; Session.SetApplicationStatus(text, "Sum of selected flame graph nodes"); } else { Session.SetApplicationStatus(""); } } private void NodeDetailsPanel_NodesSelected(object sender, List e) { GraphHost.SelectNodes(e, true); } private void NodeDetailsPanel_NodeInstanceChanged(object sender, ProfileCallTreeNode e) { GraphHost.SelectNode(e, true); } private async void NodeDetailsPanel_NodeClick(object sender, ProfileCallTreeNode e) { if (settings_.SyncSelection) { await Session.ProfileFunctionSelected(e, ToolPanelKind.FlameGraph); } } private async void NodeDetailsPanel_NodeDoubleClick(object sender, ProfileCallTreeNode e) { await OpenFunction(e); } private async Task OpenFunction(ProfileCallTreeNode node) { if (node is {HasFunction: true} && node.Function.HasSections) { var openMode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await Session.OpenProfileFunction(node, openMode); } } private void ExecuteGraphResetWidth(object sender, ExecutedRoutedEventArgs e) { GraphHost.ResetWidth(); } private void ExecuteGraphZoomIn(object sender, ExecutedRoutedEventArgs e) { GraphHost.ZoomIn(); } private void ExecuteGraphZoomOut(object sender, ExecutedRoutedEventArgs e) { GraphHost.ZoomOut(); } private void PanelToolbarTray_SettingsClicked(object sender, EventArgs e) { ShowOptionsPanel(); } private void ToolBar_Loaded(object sender, RoutedEventArgs e) { Utils.PatchToolbarStyle(sender as ToolBar); } private async void UndoButton_Click(object sender, RoutedEventArgs e) { await GraphHost.RestorePreviousState(); } private async void FunctionFilter_OnTextChanged(object sender, TextChangedEventArgs e) { string text = FunctionFilter.Text.Trim(); await SearchFlameGraph(text); } private async Task SearchFlameGraph(string text) { // Wait for a potentially ongoing search to finish. using var task = await searchTask_.CancelCurrentAndCreateTaskAsync(); // Reset marking of previous results. var prevSearchResultNodes = searchResultNodes_; searchResultNodes_ = null; if (prevSearchResultNodes != null) { GraphHost.GraphViewer.ResetSearchResultNodes(prevSearchResultNodes); } if (text.Length > 1) { bool caseInsensitive = !App.Settings.SectionSettings.FunctionSearchCaseSensitive; searchResultNodes_ = await Task.Run(() => GraphHost.FlameGraph.SearchNodes(text, caseInsensitive)); GraphHost.GraphViewer.MarkSearchResultNodes(searchResultNodes_); UpdateSearchResultText(); // Update search result navigation. searchResultIndex_ = -1; ShowSearchSection = true; SelectNextSearchResultNoLock(); } else { ShowSearchSection = false; } } private void UpdateSearchResultText() { SearchResultText = searchResultNodes_ is {Count: > 0} ? $"{searchResultIndex_ + 1} / {searchResultNodes_.Count}" : "Not found"; } private async Task SelectPreviousSearchResult() { using var task = await searchTask_.CancelCurrentAndCreateTaskAsync(); if (searchResultNodes_ != null && searchResultIndex_ > 0) { searchResultIndex_--; UpdateSearchResultText(); GraphHost.SelectNode(searchResultNodes_[searchResultIndex_], true); } } private async Task SelectNextSearchResult() { using var task = await searchTask_.CancelCurrentAndCreateTaskAsync(); SelectNextSearchResultNoLock(); } private void SelectNextSearchResultNoLock() { if (searchResultNodes_ != null && searchResultIndex_ < searchResultNodes_.Count - 1) { searchResultIndex_++; UpdateSearchResultText(); GraphHost.SelectNode(searchResultNodes_[searchResultIndex_], true); } } private async void PreviousSearchResultExecuted(object sender, ExecutedRoutedEventArgs e) { await SelectPreviousSearchResult(); } private async void NextSearchResultExecuted(object sender, ExecutedRoutedEventArgs e) { await SelectNextSearchResult(); } private void ClearSearchExecuted(object sender, ExecutedRoutedEventArgs e) { ((TextBox)e.Parameter).Text = string.Empty; } private void FocusSearchExecuted(object sender, ExecutedRoutedEventArgs e) { FunctionFilter.Focus(); FunctionFilter.SelectAll(); } private async void PanelToolbarTray_OnHelpClicked(object sender, EventArgs e) { await HelpPanel.DisplayPanelHelp(PanelKind, Session); } private async void RootNodeResetButton_OnClick(object sender, RoutedEventArgs e) { await GraphHost.ClearRootNode(); } private void ShowOptionsPanel() { if (optionsPanelPopup_ != null) { optionsPanelPopup_.ClosePopup(); optionsPanelPopup_ = null; return; } //? TODO: Redesign settings change detection, doesn't work well //? when a panel shows multiple settings objects. optionsPanelPopup_ = OptionsPanelHostPopup.Create( settings_.Clone(), GraphDetailsPanelHost, Session, async (newSettings, commit) => { if (!newSettings.Equals(settings_)) { Settings = newSettings; NodeDetailsPanel.Settings = App.Settings.CallTreeNodeSettings; App.Settings.FlameGraphSettings = newSettings; if (commit) { App.SaveApplicationSettings(); } return settings_.Clone(); } return null; }, () => optionsPanelPopup_ = null); } private async void ToggleButton_Click(object sender, RoutedEventArgs e) { // Force an update for toolbar buttons. await ReloadSettings(); } private async Task ReloadSettings() { GraphHost.SettingsUpdated(settings_); UpdateMarkingUI(); } private void UpdateMarkingUI() { UpdateMarkedFunctions(false); Session.FunctionMarkingChanged(ToolPanelKind.FlameGraph); } public override async Task OnReloadSettings() { Settings = App.Settings.FlameGraphSettings; } public void UpdateMarkedFunctions(bool externalCall) { GraphHost.Redraw(); NodeDetailsPanel.UpdateMarkedFunctions(); } } ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphRenderer.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Windows; using System.Windows.Media; using ProfileExplorer.Core.Profile.CallTree; namespace ProfileExplorer.UI.Profile; public class FlameGraphRenderer { private const double DefaultTextSize = 12; private const double DefaultNodeHeight = 18; private const double CompactTextSize = 11; private const double CompactNodeHeight = 15; private const string FontName = "Segoe UI"; private FlameGraphSettings settings_; private FlameGraph flameGraph_; private int maxNodeDepth_; private uint renderVersion_; private double nodeHeight_; private double maxWidth_; private double prevMaxWidth_; private double minVisibleRectWidth_; private Rect visibleArea_; private Rect quadVisibleArea_; private Rect quadGraphArea_; private Typeface font_; private Typeface nameFont_; private double fontSize_; private Pen defaultBorder_; private Pen kernelBorder_; private Pen managedBorder_; private Brush placeholderTileBrush_; private DrawingVisual graphVisual_; private GlyphRunCache glyphs_; private GlyphRunCache nameGlyphs_; private QuadTree nodesQuadTree_; private QuadTree dummyNodesQuadTree_; private Dictionary dummyNodeStyles_; private GuidelineSet cachedTextGuidelines_; private GuidelineSet cachedNodeGuidelines_; private GuidelineSet cachedDummyNodeGuidelines_; private SolidColorBrush nodeTextBrush_; private SolidColorBrush kernelNodeTextBrush_; private SolidColorBrush managedNodeTextBrush_; private SolidColorBrush nodeModuleBrush_; private SolidColorBrush nodeWeightBrush_; private SolidColorBrush nodePercentageBrush_; private SolidColorBrush searchResultMarkingBrush_; public FlameGraphRenderer(FlameGraph flameGraph, Rect visibleArea, FlameGraphSettings settings) { settings_ = settings; flameGraph_ = flameGraph; maxWidth_ = visibleArea.Width; prevMaxWidth_ = maxWidth_; visibleArea_ = visibleArea; UpdateGraphSizes(); ReloadSettings(); dummyNodeStyles_ = new Dictionary(); } public double MaxGraphWidth => maxWidth_; public double MaxGraphHeight => (maxNodeDepth_ + 1) * nodeHeight_; public Rect VisibleArea => visibleArea_; public Rect GraphArea => new(0, 0, MaxGraphWidth, MaxGraphHeight); public Dictionary SelectedNodes { get; set; } private void ReloadSettings() { settings_.ResedCachedPalettes(); App.Settings.MarkingSettings.ResetCachedPalettes(); defaultBorder_ = ColorPens.GetPen(settings_.NodeBorderColor, 0.5); kernelBorder_ = ColorPens.GetPen(settings_.KernelNodeBorderColor, 1); managedBorder_ = ColorPens.GetPen(settings_.ManagedNodeBorderColor, 1); font_ = new Typeface(FontName); nameFont_ = new Typeface(new FontFamily(FontName), FontStyles.Normal, FontWeights.Medium, FontStretches.Normal); nodeTextBrush_ = settings_.NodeTextColor.AsBrush(); kernelNodeTextBrush_ = settings_.KernelNodeTextColor.AsBrush(); managedNodeTextBrush_ = settings_.ManagedNodeTextColor.AsBrush(); nodeModuleBrush_ = settings_.NodeModuleColor.AsBrush(); nodeWeightBrush_ = settings_.NodeWeightColor.AsBrush(); nodePercentageBrush_ = settings_.NodePercentageColor.AsBrush(); searchResultMarkingBrush_ = settings_.SearchResultMarkingColor.AsBrush(); if (settings_.UseCompactMode) { nodeHeight_ = CompactNodeHeight; fontSize_ = CompactTextSize; } else { nodeHeight_ = DefaultNodeHeight; fontSize_ = DefaultTextSize; } if (graphVisual_ != null) { glyphs_ = new GlyphRunCache(font_, fontSize_, VisualTreeHelper.GetDpi(graphVisual_).PixelsPerDip); nameGlyphs_ = new GlyphRunCache(nameFont_, fontSize_, VisualTreeHelper.GetDpi(graphVisual_).PixelsPerDip); } } public void SettingsUpdated(FlameGraphSettings settings) { settings_ = settings; ReloadSettings(); // Use potentially new node style. SetupNode(flameGraph_.RootNode); RedrawGraph(); } public DrawingVisual Setup() { graphVisual_ = new DrawingVisual(); if (flameGraph_.RootNode != null) { SetupNode(flameGraph_.RootNode); } // Text glyph cache used to speed up rendering. glyphs_ = new GlyphRunCache(font_, fontSize_, VisualTreeHelper.GetDpi(graphVisual_).PixelsPerDip); nameGlyphs_ = new GlyphRunCache(nameFont_, fontSize_, VisualTreeHelper.GetDpi(graphVisual_).PixelsPerDip); RedrawGraph(); graphVisual_.Drawing?.Freeze(); return graphVisual_; } public HighlightingStyle GetNodeStyle(FlameGraphNode node) { var backColor = settings_.GetNodeDefaultBrush(node); var markingSettings = App.Settings.MarkingSettings; // Override color based on function name or module name, // with function name marking having priority. if (!string.IsNullOrEmpty(node.FunctionName) && markingSettings.UseFunctionColors && markingSettings.GetFunctionColor(node.FunctionName, out var functionColor)) { backColor = functionColor.AsBrush(); } else if (!string.IsNullOrEmpty(node.ModuleName)) { if (markingSettings.UseModuleColors && markingSettings.GetModuleColor(node.ModuleName, out var moduleColor)) { backColor = moduleColor.AsBrush(); } else if (markingSettings.UseAutoModuleColors) { // Use a color based on the module name. backColor = markingSettings.GetAutoModuleBrush(node.ModuleName); } } // Select border based on execution context. var border = defaultBorder_; if (node.CallTreeNode != null) { if (node.CallTreeNode.Kind == ProfileCallTreeNodeKind.NativeKernel) { border = kernelBorder_; } else if (node.CallTreeNode.Kind == ProfileCallTreeNodeKind.Managed) { border = managedBorder_; } } return new HighlightingStyle(backColor, border); } public void Redraw() { RedrawGraph(false); } public void UpdateMaxWidth(double maxWidth) { prevMaxWidth_ = maxWidth_; maxWidth_ = Math.Max(maxWidth, 1); RedrawGraph(); prevMaxWidth_ = maxWidth_; } public void UpdateVisibleArea(Rect visibleArea) { visibleArea_ = visibleArea; RedrawGraph(false); } public FlameGraphNode HitTestNode(Point point) { var queryRect = new Rect(point.X / maxWidth_, point.Y, 1.0 / maxWidth_, 1); if (nodesQuadTree_ != null) { var nodes = nodesQuadTree_.GetNodesInside(queryRect); foreach (var node in nodes) { return node; } } if (dummyNodesQuadTree_ != null) { var nodes = dummyNodesQuadTree_.GetNodesInside(queryRect); foreach (var node in nodes) { return node; } } return null; } public Rect ComputeNodeBounds(FlameGraphNode node) { return new Rect(node.Bounds.Left * maxWidth_, node.Bounds.Top, node.Bounds.Width * maxWidth_, node.Bounds.Height); } public void DrawNode(FlameGraphNode node, DrawingContext dc, bool issueDraw = true) { // Mark the node as part of this rendering step. node.RenderVersion = renderVersion_; if (node.IsDummyNode) { return; } var bounds = new Rect(node.Bounds.Left * maxWidth_, node.Bounds.Top, node.Bounds.Width * maxWidth_, node.Bounds.Height); if (bounds.Width <= 1) { return; } if (cachedNodeGuidelines_ == null) { cachedNodeGuidelines_ = CreateGuidelineSet(bounds, 0.5f); } if (issueDraw) { dc.PushGuidelineSet(cachedNodeGuidelines_); dc.DrawRectangle(node.Style.BackColor, node.Style.Border, bounds); } // Draw each text part of the node (module, func name, percentage, time). int index = 0; bool trimmed = false; bool alignedWithParent = false; bool setPercentagePosition = false; double margin = FlameGraphNode.DefaultMargin; // Start the text in the visible area. bool startsInView = bounds.Left >= visibleArea_.Left; double offsetY = bounds.Top + 1; double offsetX = startsInView ? bounds.Left : visibleArea_.Left; double maxWidth = bounds.Width - 2 * FlameGraphNode.DefaultMargin; if (!startsInView) { maxWidth -= visibleArea_.Left - bounds.Left; } // Compute layout and render each text part. while (maxWidth > 8 && index < FlameGraphNode.MaxTextParts && !trimmed) { string label = ""; bool useNameFont = false; var textColor = node.TextColor; void TryAlignTextWithParentNode() { if (alignedWithParent || node.Parent == null) { return; } // If the parent node is outside the view and was not rendered, // force a pass that only computes the coordinates, without actual // rendering. This is recursive and over the entire flame graph // will visit each node a single time. if (node.Parent.RenderVersion != renderVersion_) { DrawNode(node.Parent, dc, false); } // If the position of text after the function name is close enough // to the one in the parent and text will not get trimmed // because of it, use it to align the percentage/time text. double offsetDiff = node.Parent.PercentageTextPosition - offsetX; if (offsetDiff > 0 && offsetDiff < 150) { // Align by matching the parent offset. double availableWidth = maxWidth - margin - offsetDiff; if (availableWidth > 0) { (_, _, bool textTrimmed, var size) = TrimTextToWidth(label, availableWidth, useNameFont); if (!textTrimmed && size.Width < maxWidth) { offsetX = node.Parent.PercentageTextPosition - margin; maxWidth -= offsetDiff; } } } else if (offsetDiff < 0 && Math.Abs(offsetDiff) < margin * 0.5) { // Align by reducing the margin from previous text // to match the parent offset. margin += offsetDiff; } alignedWithParent = true; } switch (index) { case 0: { if (node.HasFunction) { label = node.FunctionName; if (settings_.PrependModuleToFunction) { string moduleLabel = node.ModuleName + "!"; (string modText, var modGlyphs, bool modTextTrimmed, var modTextSize) = TrimTextToWidth(moduleLabel, maxWidth - margin, false); if (modText.Length > 0 && issueDraw) { DrawText(modGlyphs, bounds, node.ModuleTextColor, offsetX + margin, offsetY, modTextSize, dc); } maxWidth -= modTextSize.Width + 1; offsetX += modTextSize.Width + 1; } } else { label = "All"; } margin = FlameGraphNode.DefaultMargin; useNameFont = true; break; } case 1: { if (settings_.AppendPercentageToFunction) { label = node.Percentage.AsPercentageString(); margin = FlameGraphNode.ExtraValueMargin; textColor = node.PercentageTextColor; useNameFont = true; TryAlignTextWithParentNode(); } break; } case 2: { if (settings_.AppendDurationToFunction) { label = settings_.AppendPercentageToFunction ? $"({node.Weight.AsMillisecondsString()})" : $"{node.Weight.AsMillisecondsString()}"; margin = FlameGraphNode.DefaultMargin; textColor = node.WeightTextColor; TryAlignTextWithParentNode(); } break; } default: { throw new InvalidOperationException(); } } // Trim the text to fit into the remaining space and draw it. (string text, var glyphs, bool textTrimmed, var textSize) = TrimTextToWidth(label, maxWidth - margin, useNameFont); if (text.Length > 0) { if (issueDraw) { if (index == 0 && node.SearchResult.HasValue) { DrawSearchResultSelection(node.SearchResult.Value, text, glyphs, bounds, offsetX + margin, offsetY, dc); } DrawText(glyphs, bounds, textColor, offsetX + margin, offsetY, textSize, dc); } // Remember starting position after function name // to be used for aligning the same text in descendants. if (index > 0 && !setPercentagePosition) { node.PercentageTextPosition = offsetX + margin; setPercentagePosition = true; } } trimmed = textTrimmed; maxWidth -= textSize.Width + margin; offsetX += textSize.Width + margin; index++; } if (issueDraw) { dc.Pop(); // PushGuidelineSet } } private void UpdateGraphSizes() { minVisibleRectWidth_ = FlameGraphNode.MinVisibleRectWidth / maxWidth_; quadGraphArea_ = new Rect(0, 0, 1.0, MaxGraphHeight); quadVisibleArea_ = new Rect(visibleArea_.Left / maxWidth_, visibleArea_.Top, visibleArea_.Width / maxWidth_, visibleArea_.Height); } private void SetupNode(FlameGraphNode node) { node.Style = GetNodeStyle(node); node.TextColor = GetNodeTextColor(node); node.ModuleTextColor = nodeModuleBrush_; node.WeightTextColor = nodeWeightBrush_; node.PercentageTextColor = nodePercentageBrush_; node.Owner = this; if (node.Children != null) { foreach (var childNode in node.Children) { SetupNode(childNode); } } } private Brush GetNodeTextColor(FlameGraphNode node) { var textBrush = nodeTextBrush_; if (node.CallTreeNode != null) { if (node.CallTreeNode.Kind == ProfileCallTreeNodeKind.NativeKernel) { textBrush = kernelNodeTextBrush_; } else if (node.CallTreeNode.Kind == ProfileCallTreeNodeKind.Managed) { textBrush = managedNodeTextBrush_; } } return textBrush; } private void RedrawGraph(bool updateLayout = true) { if (!RedrawGraphImpl(updateLayout)) { RedrawGraphImpl(true); // Force layout update. } } private bool RedrawGraphImpl(bool updateLayout = true) { using var graphDC = graphVisual_.RenderOpen(); bool nodeLayoutRecomputed = false; UpdateGraphSizes(); if (updateLayout) { // Recompute the position of all nodes and rebuild the quad tree. // This is done once, with node position/size being relative to the maxWidth, // except when dummy nodes get involved, which can force a re-layout. nodesQuadTree_ = new QuadTree(); dummyNodesQuadTree_ = new QuadTree(); nodesQuadTree_.Bounds = quadGraphArea_; dummyNodesQuadTree_.Bounds = quadGraphArea_; maxNodeDepth_ = 0; UpdateNodeLayout(flameGraph_.RootNode, 0, 0, true); nodeLayoutRecomputed = true; } // Update only the visible nodes on scrolling. bool layoutChanged = !nodeLayoutRecomputed && Math.Abs(maxWidth_ - prevMaxWidth_) > double.Epsilon; int shrinkingNodes = 0; renderVersion_++; // Mark a new rendering pass. foreach (var node in nodesQuadTree_.GetNodesInside(quadVisibleArea_)) { DrawNode(node, graphDC); if (layoutChanged && ScaleNode(node) < minVisibleRectWidth_) { shrinkingNodes++; } } if (shrinkingNodes > 0) { //? TODO: Removing from the quad tree is very slow, //? recompute the entire layout instead... return false; } // Draw the placeholders for insignificant nodes. bool unchanged = DrawDummyNodes(graphDC, layoutChanged); // Redraw selected nodes to show on top of everything else. DrawSelectedNodes(graphDC); return unchanged; } private void DrawSelectedNodes(DrawingContext graphDC) { foreach (var node in SelectedNodes.Keys) { // When a different root node is used, the selected nodes // may not be part of the view, don't draw them in that case. bool onPath = false; var pathNode = node; while (pathNode != null) { if (pathNode == flameGraph_.RootNode) { onPath = true; break; } else if (pathNode.IsHidden) { // If node is collapsed itself or a descendant // of a collapsed node, don't select it since it's not visible. break; } pathNode = pathNode.Parent; } if (onPath) { DrawNode(node, graphDC); } } } private double ScaleNode(FlameGraphNode node) { return flameGraph_.ScaleWeight(node); } private bool DrawDummyNodes(DrawingContext graphDC, bool layoutChanged) { int shrinkingNodes = 0; int growingNodes = 0; double halfMinVisibleRectWidth = minVisibleRectWidth_ * 0.5; foreach (var node in dummyNodesQuadTree_.GetNodesInside(quadVisibleArea_)) { double width = ScaleNode(node); if (width < halfMinVisibleRectWidth) { shrinkingNodes++; continue; } // Reconsider replacing the dummy node. if (layoutChanged && ScaleNode(node) > halfMinVisibleRectWidth) { growingNodes++; } else { DrawDummyNode(node, graphDC); } } if (growingNodes == 0 && shrinkingNodes == 0) { return true; } // Replace/split the enlarged dummy nodes. //? TODO: Still doesn't always expand like recomputing layout does #if false bool update = false; foreach (var node in enlargeList) { if (node.Parent == null) { continue; } dummyNodesQuadTree_.Remove(node); // The dummy node may be recreated back, don't update in that case. if (UpdateChildrenNodeLayout(node.Parent, node.Parent.Bounds.Left, node.Parent.Bounds.Top, node.ReplacedStartIndex, node.ReplacedEndIndex)) { update = true; } } // Redraw to show the newly create nodes replacing the dummy ones. if (update) { foreach (var node in nodesQuadTree_.GetNodesInside(quadVisibleArea_)) { DrawNode(node, graphDC); } foreach (var node in dummyNodesQuadTree_.GetNodesInside(quadVisibleArea_)) { DrawDummyNode(node, graphDC); } } #else return false; #endif } private void DrawDummyNode(FlameGraphGroupNode node, DrawingContext graphDC) { var scaledBounds = new Rect(node.Bounds.Left * maxWidth_, node.Bounds.Top, node.Bounds.Width * maxWidth_, node.Bounds.Height); if (cachedDummyNodeGuidelines_ == null) { cachedDummyNodeGuidelines_ = CreateGuidelineSet(scaledBounds, 0.5f); } graphDC.PushGuidelineSet(cachedDummyNodeGuidelines_); graphDC.DrawRectangle(node.Style.BackColor, node.Style.Border, scaledBounds); graphDC.DrawRectangle(CreatePlaceholderTiledBrush(8), null, scaledBounds); graphDC.Pop(); } private void DrawCenteredText(string text, double x, double y, DrawingContext dc) { var glyphInfo = glyphs_.GetGlyphs(text); x = Math.Max(0, x - glyphInfo.TextWidth / 2); y = Math.Max(0, y + glyphInfo.TextHeight / 2); dc.PushTransform(new TranslateTransform(x, y)); dc.DrawGlyphRun(Brushes.Black, glyphInfo.Glyphs); dc.Pop(); } private void UpdateNodeLayout(FlameGraphNode node, double x, double y, bool redraw) { double width = ScaleNode(node); node.Bounds = new Rect(x, y, width, nodeHeight_); node.IsDummyNode = !redraw; node.IsHidden = false; if (redraw) { maxNodeDepth_ = Math.Max(node.Depth, maxNodeDepth_); double minWidth = minVisibleRectWidth_; if (node.Bounds.Width > minWidth) { nodesQuadTree_.Insert(node, node.Bounds); } } if (node.Children == null || node.Children.Count == 0) { return; } // Children are sorted by weight or time. UpdateChildrenNodeLayout(node, x, y); } private bool UpdateChildrenNodeLayout(FlameGraphNode node, double x, double y, int startIndex = 0, int stopIndex = int.MaxValue) { int skippedChildren = 0; int totalSkippedChildren = 0; // Ignore children that have layout already computed. // Note that currently startIndex is always 0. for (int i = 0; i < startIndex; i++) { var childNode = node.Children[i]; double childWidth = flameGraph_.ScaleWeight(childNode); x += childWidth; } stopIndex = Math.Min(stopIndex, node.Children.Count); int range = stopIndex - startIndex; for (int i = startIndex; i < stopIndex; i++) { var childNode = node.Children[i]; double childWidth = flameGraph_.ScaleWeight(childNode); if (skippedChildren == 0) { if (childWidth < minVisibleRectWidth_) { // If multiple children below width, use a single dummy node. CreateSmallWeightDummyNode(node, x, y, i, stopIndex, out skippedChildren); totalSkippedChildren += skippedChildren; childNode.IsDummyNode = true; } } else { // Once children were combined into a dummy node and skipped, // all others are skipped since they are sorted by weight. childNode.IsDummyNode = true; } // If all child nodes were merged into a dummy node don't recurse. if (totalSkippedChildren < range) { UpdateNodeLayout(childNode, x, y + nodeHeight_, skippedChildren == 0); } x += childWidth; } return totalSkippedChildren < range; } private FlameGraphNode CreateSmallWeightDummyNode(FlameGraphNode node, double x, double y, int startIndex, int stopIndex, out int skippedChildren) { var totalWeight = TimeSpan.Zero; double totalWidth = 0; // Collect all the child nodes that have a small weight // and replace them by one dummy node. var startTime = TimeSpan.MaxValue; var endTime = TimeSpan.MinValue; int k; for (k = startIndex; k < stopIndex; k++) { var childNode = node.Children[k]; double childWidth = ScaleNode(childNode); // In case child sorting is not by weight, stop extending the range // when a larger one is found again. if (childWidth > minVisibleRectWidth_) { break; } totalWidth += childWidth; totalWeight += childNode.Weight; startTime = TimeSpan.FromTicks(Math.Min(startTime.Ticks, childNode.StartTime.Ticks)); endTime = TimeSpan.FromTicks(Math.Max(endTime.Ticks, childNode.EndTime.Ticks)); childNode.IsHidden = true; } skippedChildren = k - startIndex; // Caller should ignore these children. if (totalWidth < minVisibleRectWidth_) { return null; // Nothing to draw. } //? TODO: Use a pool for FlameGraphGroupNode instead of new (JIT_New dominates) var replacement = new Rect(x, y + nodeHeight_, totalWidth, nodeHeight_); var dummyNode = new FlameGraphGroupNode(node, startIndex, skippedChildren, totalWeight, node.Depth); dummyNode.IsDummyNode = true; dummyNode.Bounds = replacement; dummyNode.Style = PickDummyNodeStyle(node.Style); dummyNode.StartTime = startTime; dummyNode.EndTime = endTime; dummyNodesQuadTree_.Insert(dummyNode, replacement); return dummyNode; } private HighlightingStyle PickDummyNodeStyle(HighlightingStyle style) { if (!dummyNodeStyles_.TryGetValue(style, out var dummyStyle)) { var newColor = ColorUtils.AdjustSaturation(((SolidColorBrush)style.BackColor).Color, 0.2f); newColor = ColorUtils.AdjustLight(newColor, 2.0f); dummyStyle = new HighlightingStyle(newColor, defaultBorder_); dummyNodeStyles_[style] = dummyStyle; } return dummyStyle; } private Brush CreatePlaceholderTiledBrush(double tileSize) { // Create the brush once, freeze and reuse it everywhere. if (placeholderTileBrush_ != null) { return placeholderTileBrush_; } tileSize = Math.Ceiling(tileSize); var line = new LineSegment(new Point(0, 0), true); line.IsSmoothJoin = false; line.Freeze(); var figure = new PathFigure(); figure.IsClosed = false; figure.StartPoint = new Point(tileSize, tileSize); figure.Segments.Add(line); figure.Freeze(); var geometry = new PathGeometry(); geometry.Figures.Add(figure); geometry.Freeze(); var drawing = new GeometryDrawing(); drawing.Geometry = geometry; var penBrush = ColorBrushes.GetBrush(Colors.Gray); drawing.Pen = new Pen(penBrush, 1.0f); drawing.Freeze(); var brush = new DrawingBrush(); brush.Drawing = drawing; brush.Stretch = Stretch.None; brush.TileMode = TileMode.Tile; brush.Viewbox = new Rect(0, 0, tileSize, tileSize); brush.ViewboxUnits = BrushMappingMode.Absolute; brush.Viewport = new Rect(0, 0, tileSize, tileSize); brush.ViewportUnits = BrushMappingMode.Absolute; RenderOptions.SetCachingHint(brush, CachingHint.Cache); brush.Freeze(); placeholderTileBrush_ = brush; return placeholderTileBrush_; } private void DrawSearchResultSelection(TextSearchResult searchResult, string text, GlyphRun glyphs, Rect bounds, double offsetX, double offsetY, DrawingContext dc) { var glypWidths = glyphs.AdvanceWidths; int startIndex = Math.Min(searchResult.Offset, glypWidths.Count); int endIndex = Math.Min(searchResult.Offset + searchResult.Length, glypWidths.Count); if (startIndex == text.Length || startIndex == endIndex) { return; // Result outside of visible text part. } for (int i = 0; i < startIndex; i++) { offsetX += glypWidths[i]; } double width = 0; for (int i = startIndex; i < endIndex; i++) { width += glypWidths[i]; } var selectionBounds = new Rect(offsetX, offsetY, width, nodeHeight_ - 2); dc.DrawRectangle(searchResultMarkingBrush_, null, selectionBounds); } private void DrawText(GlyphRun glyphs, Rect bounds, Brush textColor, double offsetX, double offsetY, Size textSize, DrawingContext dc) { double x = offsetX; double y = bounds.Height * 0.5 + textSize.Height * 0.25 + offsetY; if (cachedTextGuidelines_ == null) { var rect = glyphs.ComputeAlignmentBox(); cachedTextGuidelines_ = CreateGuidelineSet(rect, 1.0f); } dc.PushTransform(new TranslateTransform(x, y)); dc.PushGuidelineSet(cachedTextGuidelines_); dc.DrawGlyphRun(textColor, glyphs); dc.Pop(); dc.Pop(); // PushGuidelineSet } private (string Text, GlyphRun glyphs, bool Trimmed, Size TextSize) TrimTextToWidth(string text, double maxWidth, bool useNameFont) { string originalText = text; var glyphsCache = useNameFont ? nameGlyphs_ : glyphs_; if (maxWidth <= 0 || string.IsNullOrEmpty(text)) { return ("", glyphsCache.GetGlyphs("").Glyphs, false, new Size(0, 0)); } var glyphInfo = glyphsCache.GetGlyphs(text, maxWidth); bool trimmed = glyphInfo.IsTrimmed; if (glyphInfo.TextWidth > maxWidth) { // The width of letters is the same only for monospace fonts, // use the glyph width to find where to trim the string instead. double trimmedWidth = 0; int trimmedLength = 0; var widths = glyphInfo.Glyphs.AdvanceWidths; double letterWidth = Math.Ceiling(glyphInfo.TextWidth / text.Length); double availableWidth = maxWidth - letterWidth * 2; // Space for .. for (trimmedLength = 0; trimmedLength < text.Length; trimmedLength++) { trimmedWidth += widths[trimmedLength]; if (trimmedWidth >= availableWidth) { break; } } trimmed = true; if (trimmedLength > 0) { text = text.Substring(0, trimmedLength) + ".."; glyphInfo = glyphsCache.GetGlyphs(text, maxWidth); } else { text = ""; glyphInfo = glyphsCache.GetGlyphs(text, maxWidth); glyphInfo.TextWidth = maxWidth; } } glyphInfo.IsTrimmed = trimmed; glyphsCache.CacheGlyphs(glyphInfo, originalText, maxWidth); return (text, glyphInfo.Glyphs, trimmed, new Size(glyphInfo.TextWidth, glyphInfo.TextHeight)); } private GuidelineSet CreateGuidelineSet(Rect rect, double penWidth) { var guidelines = new GuidelineSet(); guidelines.GuidelinesX.Add(rect.Left + penWidth); guidelines.GuidelinesX.Add(rect.Right + penWidth); guidelines.GuidelinesY.Add(rect.Top + penWidth); guidelines.GuidelinesY.Add(rect.Bottom + penWidth); return guidelines; } } ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphViewer.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/FlameGraph/FlameGraphViewer.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Utilities; namespace ProfileExplorer.UI.Profile; public partial class FlameGraphViewer : FrameworkElement { private FlameGraph flameGraph_; private FlameGraphRenderer renderer_; private DrawingVisual graphVisual_; private FlameGraphNode hoveredNode_; private FlameGraphNode selectedNode_; private bool isTimelineView_; private bool initialized_; private Brush markedNodeBackColor_; private Brush selectedNodeBackColor_; private Pen searchResultBorderColor_; private Pen selectedNodeBorderColor_; private Pen markedNodeBorderColor_; private Dictionary hoverNodes_; private Dictionary markedNodes_; private Dictionary fixedMarkedNodes_; private Dictionary selectedNodes_; private FlameGraphSettings settings_; public FlameGraphViewer() { InitializeComponent(); hoverNodes_ = new Dictionary(); markedNodes_ = new Dictionary(); fixedMarkedNodes_ = new Dictionary(); selectedNodes_ = new Dictionary(); SetupEvents(); } public new bool IsInitialized => initialized_; public FlameGraph FlameGraph => flameGraph_; public double MaxGraphWidth => renderer_.MaxGraphWidth; public Rect VisibleArea => renderer_.VisibleArea; public bool IsZoomed => Math.Abs(MaxGraphWidth - VisibleArea.Width) > 1; public FlameGraphNode SelectedNode => selectedNode_; public IUISession Session { get; set; } public HighlightingStyle SelectedNodeStyle { get; private set; } public HighlightingStyle MarkedNodeStyle { get; private set; } public List SelectedNodes => selectedNodes_.ToKeyList(); protected override int VisualChildrenCount => 1; public HighlightingStyle MarkedColoredNodeStyle(Color color) { return new HighlightingStyle(color, markedNodeBorderColor_); } public void SaveFixedMarkedNodes(List<(ProfileCallTreeNode Node, HighlightingStyle Style)> list) { foreach (var pair in fixedMarkedNodes_) { if (pair.Key.HasFunction) { list.Add((pair.Key.CallTreeNode, pair.Value)); } } } public List<(ProfileCallTreeNode Node, HighlightingStyle Style)> RestoreFixedMarkedNodes(List<(ProfileCallTreeNode Node, HighlightingStyle Style)> markedNodes, ProfileCallTree callTree) { if (markedNodes.Count == 0) { return null; } List<(ProfileCallTreeNode Node, HighlightingStyle Style)> unmatchedList = null; foreach (var pair in markedNodes) { // Find in the call tree node that corresponds to // a node from another instance of a call tree. // This happens when filtering the profile, which creates // a new call tree. Function marked in the flame graph // should still be marked in the filtered profile. bool added = false; var treeNode = callTree.FindMatchingNode(pair.Node); if (treeNode != null) { var fgNode = flameGraph_.GetFlameGraphNode(treeNode); if (fgNode != null) { MarkNodeImpl(fgNode, HighlighingType.Marked, pair.Style, true); added = true; } } // If a marked node could not be mapped to one in the current // call tree instance, remember it in case the filtering changes // later to a state where the call tree includes it again. if (!added) { unmatchedList ??= new List<(ProfileCallTreeNode Node, HighlightingStyle Style)>(); unmatchedList.Add(pair); } } renderer_.Redraw(); return unmatchedList; } public void RestoreFixedMarkedNodes() { if (fixedMarkedNodes_.Count == 0) { return; } foreach (var pair in fixedMarkedNodes_) { if (pair.Key.HasFunction) { // Map the call tree node to the current flame graph node, // needed in case the flame graph got rebuilt. var node = flameGraph_.GetFlameGraphNode(pair.Key.CallTreeNode); if (node != null) { MarkNodeImpl(node, HighlighingType.Marked, pair.Value); } } } renderer_.Redraw(); } public void ResetNodeHighlighting() { ResetHighlightedNodes(HighlighingType.Selected); ResetHighlightedNodes(HighlighingType.Hovered); selectedNodes_.Clear(); selectedNode_ = null; hoveredNode_ = null; Session.SetApplicationStatus(""); } public void SelectNode(FlameGraphNode graphNode, bool append = false, bool deselectIfSelected = true) { if (!selectedNodes_.ContainsKey(graphNode)) { // Select a currently unselected node. if (!append) { ResetNodeHighlighting(); // Deselect all other nodes. } HighlightNode(graphNode, HighlighingType.Selected); selectedNode_ = graphNode; // Last selected node. } else if (deselectIfSelected) { // Handle a currently selected node. if (append) { // Remove selection if node is already selected in append mode. selectedNodes_.Remove(graphNode); selectedNode_ = selectedNodes_.Count > 0 ? selectedNodes_.First().Key : null; RestoreNodeStyle(graphNode, true); } else { // Keep the node selected and deselect others. ResetNodeHighlighting(); HighlightNode(graphNode, HighlighingType.Selected); selectedNode_ = graphNode; // Last selected node. } } } public void SelectNodes(List nodes) { ResetNodeHighlighting(); foreach (var node in nodes) { MarkNodeImpl(node, HighlighingType.Selected); } renderer_.Redraw(); } public void MarkSearchResultNodes(List searchResultNodes) { foreach (var node in searchResultNodes) { MarkNodeImpl(node, HighlighingType.Marked); } renderer_.Redraw(); } public void ResetSearchResultNodes(List nodes, bool redraw = true) { ResetHighlightedNodes(HighlighingType.Marked, redraw); flameGraph_.ResetSearchResults(nodes); if (redraw) { renderer_.Redraw(); } } public void MarkNodes(List nodes, HighlightingStyle style, bool overwriteStyle) { foreach (var node in nodes) { MarkNodeNoRedraw(node, style, overwriteStyle); } renderer_.Redraw(); } public void MarkNode(FlameGraphNode node, HighlightingStyle style) { MarkNodeImpl(node, HighlighingType.Marked, style, true); renderer_.Redraw(); } public void ResetMarkedNodes(bool clearFixedNodes) { if (clearFixedNodes) { fixedMarkedNodes_.Clear(); } ResetHighlightedNodes(HighlighingType.Marked); } public FlameGraphNode SelectNode(ProfileCallTreeNode graphNode) { var fgNodes = flameGraph_.GetNodes(graphNode); // Because the flame graph can be rooted at a different node then // the call tree, parts of the call tree may not have a flame graph node. if (fgNodes is {Count: > 0}) { SelectNodes(fgNodes); return fgNodes[0]; } return null; } public List SelectNodes(ProfileCallTreeNode graphNode) { var fgNodes = flameGraph_.GetNodes(graphNode); SelectNodes(fgNodes); return fgNodes; } public List SelectNodes(List nodes) { if (nodes == null || nodes.Count == 0) { return null; } var fgNodes = new List(nodes.Count); foreach (var node in nodes) { flameGraph_.AppendNodes(node, fgNodes); } SelectNodes(fgNodes); return fgNodes; } public void ClearSelection() { if (!initialized_) { return; } ResetNodeHighlighting(); } public async Task Initialize(ProfileCallTree callTree, ProfileCallTreeNode rootNode, Rect visibleArea, FlameGraphSettings settings, IUISession session, bool isTimelineView = false, int threadId = -1) { if (initialized_) { Reset(); } Session = session; flameGraph_ = new FlameGraph(callTree, Session.CompilerInfo.NameProvider.FormatFunctionName); isTimelineView_ = isTimelineView; if (isTimelineView_) { // TODO: Timeline not implemented. // await Task.Run(() => flameGraph_.BuildTimeline(Session.ProfileData, threadId)); } else { await Task.Run(() => flameGraph_.Build(rootNode)); } settings_ = settings; ReloadSettings(); // Create the rendered and add the drawing surface as a child control. renderer_ = new FlameGraphRenderer(flameGraph_, visibleArea, settings); renderer_.SelectedNodes = selectedNodes_; graphVisual_ = renderer_.Setup(); AddVisualChild(graphVisual_); AddLogicalChild(graphVisual_); UpdateMaxWidth(renderer_.MaxGraphWidth); initialized_ = true; } public void Redraw() { // Force re-evaluating the styles and redraw. SettingsUpdated(settings_); } private void ReloadSettings() { markedNodeBackColor_ = ColorBrushes.GetBrush(settings_.SearchedNodeColor); markedNodeBorderColor_ = ColorPens.GetPen(settings_.NodeBorderColor, 2); selectedNodeBackColor_ = ColorBrushes.GetBrush(settings_.SelectedNodeColor); selectedNodeBorderColor_ = ColorPens.GetPen(settings_.SelectedNodeBorderColor, 2); searchResultBorderColor_ = ColorPens.GetPen(settings_.SearchedNodeBorderColor, 2); SelectedNodeStyle = new HighlightingStyle(selectedNodeBackColor_, selectedNodeBorderColor_); MarkedNodeStyle = new HighlightingStyle(markedNodeBackColor_, markedNodeBorderColor_); } public void SettingsUpdated(FlameGraphSettings settings) { settings_ = settings; ReloadSettings(); // Render the flame graph again. renderer_.SettingsUpdated(settings); InvalidateMeasure(); InvalidateVisual(); } public async Task Initialize(ProfileCallTree callTree, Rect visibleArea, FlameGraphSettings settings, IUISession session, bool isTimelineView = false, int threadId = -1) { await Initialize(callTree, null, visibleArea, settings, session, isTimelineView, threadId); } public void UpdateMaxWidth(double maxWidth) { if (!initialized_) { return; } renderer_.UpdateMaxWidth(maxWidth); InvalidateMeasure(); InvalidateVisual(); } public void AdjustMaxWidth(double amount) { if (!initialized_) { return; } renderer_.UpdateMaxWidth(renderer_.MaxGraphWidth + amount); InvalidateMeasure(); } public FlameGraphNode FindPointedNode(Point point) { if (!initialized_) { return null; } return renderer_.HitTestNode(point); } public Rect ComputeNodeBounds(FlameGraphNode node) { return renderer_.ComputeNodeBounds(node); } public Point ComputeNodePosition(FlameGraphNode node) { return ComputeNodeBounds(node).TopLeft; } public Size ComputeNodeSize(FlameGraphNode node) { return ComputeNodeBounds(node).Size; } public void UpdateVisibleArea(Rect visibleArea) { if (!initialized_) { return; } renderer_.UpdateVisibleArea(visibleArea); } public void Reset() { if (!initialized_) { return; } RemoveVisualChild(graphVisual_); RemoveLogicalChild(graphVisual_); hoverNodes_.Clear(); markedNodes_.Clear(); fixedMarkedNodes_.Clear(); selectedNodes_.Clear(); selectedNode_ = null; graphVisual_ = null; flameGraph_ = null; renderer_ = null; initialized_ = false; } protected override void OnMouseLeave(MouseEventArgs e) { if (!initialized_) { return; } ResetHighlightedNodes(HighlighingType.Hovered); } protected override Visual GetVisualChild(int index) { return graphVisual_; } protected override Size MeasureOverride(Size availableSize) { if (graphVisual_ == null) { return new Size(0, 0); } return renderer_.GraphArea.Size; } private void SetupEvents() { MouseLeftButtonUp += OnMouseLeftButtonUp; MouseRightButtonDown += OnMouseRightButtonDown; MouseMove += OnMouseMove; } private void OnMouseMove(object sender, MouseEventArgs e) { var point = e.GetPosition(this); var graphNode = FindPointedNode(point); if (graphNode != null) { if (hoveredNode_ != graphNode) { ResetHighlightedNodes(HighlighingType.Hovered); HighlightNode(graphNode, HighlighingType.Hovered); hoveredNode_ = graphNode; e.Handled = true; } } else { ResetHighlightedNodes(HighlighingType.Hovered); hoveredNode_ = null; e.Handled = true; } } private void HighlightNode(FlameGraphNode node, HighlighingType type) { node.Style = type switch { HighlighingType.Hovered => PickHoveredNodeStyle(node.Style), HighlighingType.Selected => PickSelectedNodeStyle(node.Style), _ => node.Style }; var group = GetHighlightedNodeGroup(type); group[node] = node.Style; renderer_.Redraw(); } private void MarkNodeImpl(FlameGraphNode node, HighlighingType type, HighlightingStyle style = null, bool overwriteStyle = false) { if (type == HighlighingType.Marked && !overwriteStyle && markedNodes_.TryGetValue(node, out var markedStyle)) { fixedMarkedNodes_[node] = markedStyle; // Save current marked style. } node.Style = type switch { HighlighingType.Hovered => PickHoveredNodeStyle(style), HighlighingType.Selected => PickSelectedNodeStyle(style), HighlighingType.Marked => PickMarkedNodeStyle(node, style), _ => node.Style }; var group = GetHighlightedNodeGroup(type); group[node] = node.Style; if (type == HighlighingType.Marked && overwriteStyle) { fixedMarkedNodes_[node] = style; } } private void ResetHighlightedNodes(HighlighingType type, bool redraw = true) { var group = GetHighlightedNodeGroup(type); if (group.Count == 0) { return; } var tempNodes = new List(group.Keys); group.Clear(); foreach (var node in tempNodes) { RestoreNodeStyle(node); } if (redraw) { renderer_.Redraw(); } } private void RestoreNodeStyle(FlameGraphNode node, bool redraw = false) { if (!markedNodes_.TryGetValue(node, out var style) && !selectedNodes_.TryGetValue(node, out style) && !hoverNodes_.TryGetValue(node, out style)) { // Check marked directly by user. if (fixedMarkedNodes_.TryGetValue(node, out style)) { MarkNodeImpl(node, HighlighingType.Marked, style); return; } style = renderer_.GetNodeStyle(node); } node.Style = style; if (redraw) { renderer_.Redraw(); } } private Dictionary GetHighlightedNodeGroup(HighlighingType type) { return type switch { HighlighingType.Hovered => hoverNodes_, HighlighingType.Selected => selectedNodes_, HighlighingType.Marked => markedNodes_, _ => throw new InvalidOperationException("Unsupported highlighting type") }; } private HighlightingStyle ApplyBorderToStyle(HighlightingStyle style, Pen border) { return new HighlightingStyle(style.BackColor, border); } private HighlightingStyle PickHoveredNodeStyle(HighlightingStyle style) { var newColor = ColorUtils.AdjustLight(((SolidColorBrush)style.BackColor).Color, 0.9f); return new HighlightingStyle(newColor, style.Border); } private HighlightingStyle PickSelectedNodeStyle(HighlightingStyle style) { var newColor = selectedNodeBackColor_; var newPen = selectedNodeBorderColor_; return new HighlightingStyle(newColor, newPen); } private HighlightingStyle PickMarkedNodeStyle(FlameGraphNode node, HighlightingStyle style = null) { if (style != null) { return style; } var newColor = markedNodeBackColor_; var newPen = markedNodeBorderColor_; if (node.SearchResult.HasValue) { newPen = searchResultBorderColor_; } return new HighlightingStyle(newColor, newPen); } private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e) { // On right click, don't deselect node if already selected. SelectPointedNode(e, false); } private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e) { // On left click, deselect node if already selected. SelectPointedNode(e, true); } private void SelectPointedNode(MouseButtonEventArgs e, bool deselectIfSelected) { var point = e.GetPosition(this); var graphNode = FindPointedNode(point); if (graphNode != null) { if (Utils.IsShiftModifierActive() && selectedNode_ != null) { // Try to extend the selection to include all nodes between // the currently selected one and new one. var nodes = FindNodesInBetween(graphNode, selectedNode_); if (nodes is {Count: > 0}) { foreach (var node in nodes) { SelectNode(node, true, false); } return; } } SelectNode(graphNode, append: Utils.IsControlModifierActive(), deselectIfSelected); } else { ClearSelection(); } } private List FindNodesInBetween(FlameGraphNode startNode, FlameGraphNode stopNode) { var list = new List(); bool found = false; // Ensure start node has a larger depth than end node. if (startNode.Depth < stopNode.Depth) { Utils.Swap(ref startNode, ref stopNode); } while (startNode.Depth >= stopNode.Depth) { list.Add(startNode); if (startNode == stopNode) { found = true; break; } startNode = startNode.Parent; } return found ? list : null; } private void MarkNodeNoRedraw(ProfileCallTreeNode node, HighlightingStyle style, bool overwriteStyle) { var fgNodes = flameGraph_.GetNodes(node); foreach (var fgNode in fgNodes) { MarkNodeImpl(fgNode, HighlighingType.Marked, style, overwriteStyle); } } } ================================================ FILE: src/ProfileExplorerUI/Profile/ProfileListView.xaml ================================================  ================================================ FILE: src/ProfileExplorerUI/Profile/ProfileListView.xaml.cs ================================================ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using ProfileExplorer.UI.Controls; using ProfileExplorer.UI.Document; using ProfileExplorer.Core.Profile.CallTree; using ProfileExplorer.Core.Profile.Data; using ProfileExplorer.Core.Profile.Processing; using ProfileExplorer.Core.Providers; namespace ProfileExplorer.UI.Profile; public class ProfileListViewItem : SearchableProfileItem { private CallTreeNodeSettings settings_; private object associatedObject_; private Brush functionBackColor_; private Brush moduleBackColor_; private ProfileListViewItem(FunctionNameFormatter funcNameFormatter, CallTreeNodeSettings settings) : base(funcNameFormatter) { settings_ = settings; } public ProfileCallTreeNode CallTreeNode { get => associatedObject_ as ProfileCallTreeNode; set => associatedObject_ = value; } public ModuleProfileInfo ModuleInfo { get => associatedObject_ as ModuleProfileInfo; set => associatedObject_ = value; } public FunctionMarkingCategory MarkingCategory { get => associatedObject_ as FunctionMarkingCategory; set => associatedObject_ = value; } public Brush FunctionBackColor { get => functionBackColor_; set => SetAndNotify(ref functionBackColor_, value); } public Brush ModuleBackColor { get => moduleBackColor_; set => SetAndNotify(ref moduleBackColor_, value); } protected override string GetFunctionName() { return CallTreeNode?.FunctionName; } public static ProfileListViewItem From(ProfileCallTreeNode node, ProfileData profileData, FunctionNameFormatter funcNameFormatter, CallTreeNodeSettings settings) { return new ProfileListViewItem(funcNameFormatter, settings) { CallTreeNode = node, ModuleName = node.ModuleName, Weight = node.Weight, ExclusiveWeight = node.ExclusiveWeight, Percentage = profileData.ScaleFunctionWeight(node.Weight), ExclusivePercentage = profileData.ScaleFunctionWeight(node.ExclusiveWeight) }; } public static ProfileListViewItem From(ModuleProfileInfo moduleInfo, ProfileData profileData, FunctionNameFormatter funcNameFormatter, CallTreeNodeSettings settings) { return new ProfileListViewItem(funcNameFormatter, settings) { ModuleInfo = moduleInfo, FunctionName = moduleInfo.Name, // Override name, disables GetFunctionName. Weight = moduleInfo.Weight, Percentage = moduleInfo.Percentage }; } public static ProfileListViewItem From(FunctionMarkingCategory category, ProfileData profileData, FunctionNameFormatter funcNameFormatter, CallTreeNodeSettings settings) { return new ProfileListViewItem(funcNameFormatter, settings) { MarkingCategory = category, FunctionName = category.Marking.Title, // Override name, disables GetFunctionName. Weight = category.Weight, Percentage = category.Percentage }; } protected override bool ShouldPrependModule() { return settings_.PrependModuleToFunction; } } public partial class ProfileListView : UserControl, INotifyPropertyChanged { private const double DefaultFunctionColumnWidth = 250; private string nameColumnTitle_; private string timeColumnTitle_; private string exclusiveTimeColumnTitle_; private bool showExclusiveTimeColumn_; private bool showTimeColumn_; private bool showCombinedTimeColumn_; private bool showCombinedTimeNameRow_; private bool showExclusiveTimeNameRow_; private bool showTimeNameRow_; private bool showModuleColumn_; private bool showContextColumn_; private double functionColumnWidth_; private IUISession session_; private IRDocumentPopupInstance previewPopup_; private CallTreeNodeSettings settings_; private bool searchPanelVisible_; private List itemList_; private List resultList_; private List categories_; private bool isCategoriesList_; public ProfileListView() { InitializeComponent(); FunctionColumnWidth = DefaultFunctionColumnWidth; DataContext = this; SearchPanel.SearchChanged += SearchPanel_SearchChanged; SearchPanel.CloseSearchPanel += SearchPanel_CloseSearchPanel; SearchPanel.NavigateToPreviousResult += SearchPanel_NaviateToPreviousResult; SearchPanel.NavigateToNextResult += SearchPanel_NavigateToNextResult; } public CallTreeNodeSettings Settings { get => settings_; set { settings_ = value; OnPropertyChanged(); if (settings_ != null && session_ != null) { SetupPreviewPopup(); } } } public IUISession Session { get => session_; set => session_ = value; } public double FunctionColumnWidth { get => functionColumnWidth_; set => SetField(ref functionColumnWidth_, value); } public bool IsCategoriesList { get => isCategoriesList_; set => SetField(ref isCategoriesList_, value); } public RelayCommand PreviewFunctionCommand => new(async obj => { if (ItemList.SelectedItem is ProfileListViewItem item && item.CallTreeNode != null) { var brush = GetMarkedNodeColor(item); await IRDocumentPopupInstance.ShowPreviewPopup(item.CallTreeNode.Function, "", ItemList, session_, null, false, brush); } }); public RelayCommand OpenFunctionCommand => new(async obj => { var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await OpenFunction(mode); }); public RelayCommand OpenFunctionInNewTabCommand => new(async obj => { await OpenFunction(OpenSectionKind.NewTab); }); public RelayCommand PreviewFunctionInstanceCommand => new(async obj => { if (ItemList.SelectedItem is ProfileListViewItem item && item.CallTreeNode != null) { var filter = new ProfileSampleFilter(item.CallTreeNode); await IRDocumentPopupInstance.ShowPreviewPopup(item.CallTreeNode.Function, "", ItemList, session_, filter); } }); public RelayCommand OpenInstanceCommand => new(async obj => { var mode = Utils.IsControlModifierActive() ? OpenSectionKind.NewTab : OpenSectionKind.ReplaceCurrent; await OpenFunction(mode); }); public RelayCommand OpenInstanceInNewTabCommand => new(async obj => { await OpenFunctionInstance(OpenSectionKind.NewTab); }); public RelayCommand SelectFunctionSummaryCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.Section); }); public RelayCommand SelectFunctionCallTreeCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.CallTree); }); public RelayCommand SelectFunctionFlameGraphCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.FlameGraph); }); public RelayCommand SelectFunctionTimelineCommand => new(async obj => { await SelectFunctionInPanel(ToolPanelKind.Timeline); }); public RelayCommand ToggleSearchCommand => new(async obj => { SearchPanelVisible = !SearchPanelVisible; }); public RelayCommand CopyFunctionNameCommand => new(async obj => { if (ItemList.SelectedItem is ProfileListViewItem item) { string text = Session.CompilerInfo.NameProvider.GetFunctionName(item.CallTreeNode.Function); Clipboard.SetText(text); } }); public RelayCommand CopyDemangledFunctionNameCommand => new(async obj => { if (ItemList.SelectedItem is ProfileListViewItem item) { var options = FunctionNameDemanglingOptions.Default; string text = Session.CompilerInfo.NameProvider.DemangleFunctionName(item.CallTreeNode.Function, options); Clipboard.SetText(text); } }); public RelayCommand CopyFunctionDetailsCommand => new(async obj => { if (ItemList.SelectedItems.Count > 0) { var funcList = new List(); foreach (object item in ItemList.SelectedItems) { funcList.Add((SearchableProfileItem)item); } SearchableProfileItem.CopyFunctionListAsHtml(funcList); } }); public RelayCommand MarkModuleCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; foreach (object item in ItemList.SelectedItems) { if (item is ProfileListViewItem profileItem && obj is SelectedColorEventArgs e) { markingSettings.AddModuleColor(profileItem.ModuleName, e.SelectedColor); } } markingSettings.UseModuleColors = true; UpdateMarkedFunctions(); MarkingChanged?.Invoke(this, EventArgs.Empty); }); public RelayCommand MarkFunctionCommand => new(async obj => { var markingSettings = App.Settings.MarkingSettings; foreach (object item in ItemList.SelectedItems) { if (item is ProfileListViewItem profileItem && obj is SelectedColorEventArgs e) { markingSettings.AddFunctionColor(profileItem.FunctionName, e.SelectedColor); } } markingSettings.UseFunctionColors = true; UpdateMarkedFunctions(); MarkingChanged?.Invoke(this, EventArgs.Empty); }); public RelayCommand CopyCategoriesCommand => new(async obj => { if (categories_ != null) { ProfilingExporting.CopyFunctionMarkingsAsHtml(categories_, Session); } }); public RelayCommand ExportCategoriesHtmlCommand => new(async obj => { if (categories_ != null) { await ProfilingExporting.ExportFunctionMarkingsAsHtmlFile(categories_, Session); } }); public RelayCommand ExportCategoriesMarkdownCommand => new(async obj => { if (categories_ != null) { await ProfilingExporting.ExportFunctionMarkingsAsMarkdownFile(categories_, Session); } }); public bool SearchPanelVisible { get => searchPanelVisible_; set { if (value != searchPanelVisible_) { searchPanelVisible_ = value; if (searchPanelVisible_) { SearchPanel.Visibility = Visibility.Visible; SearchPanel.Show(); } else { SearchPanel.Reset(); SearchPanel.Visibility = Visibility.Collapsed; } OnPropertyChanged(); } } } public string NameColumnTitle { get => nameColumnTitle_; set => SetField(ref nameColumnTitle_, value); } public string TimeColumnTitle { get => timeColumnTitle_; set => SetField(ref timeColumnTitle_, value); } public string ExclusiveTimeColumnTitle { get => exclusiveTimeColumnTitle_; set => SetField(ref exclusiveTimeColumnTitle_, value); } public bool ShowExclusiveTimeColumn { get => showExclusiveTimeColumn_; set => SetField(ref showExclusiveTimeColumn_, value); } public bool ShowTimeColumn { get => showTimeColumn_; set => SetField(ref showTimeColumn_, value); } public bool ShowCombinedTimeColumn { get => showCombinedTimeColumn_; set => SetField(ref showCombinedTimeColumn_, value); } public bool ShowCombinedTimeNameRow { get => showCombinedTimeNameRow_; set => SetField(ref showCombinedTimeNameRow_, value); } public bool ShowExclusiveTimeNameRow { get => showExclusiveTimeNameRow_; set => SetField(ref showExclusiveTimeNameRow_, value); } public bool ShowTimeNameRow { get => showTimeNameRow_; set => SetField(ref showTimeNameRow_, value); } public bool ShowModuleColumn { get => showModuleColumn_; set => SetField(ref showModuleColumn_, value); } public bool ShowContextColumn { get => showContextColumn_; set => SetField(ref showContextColumn_, value); } public event PropertyChangedEventHandler PropertyChanged; private void SearchPanel_NavigateToNextResult(object sender, SearchInfo e) { SelectSearchResult(e.CurrentResult); } private void SearchPanel_NaviateToPreviousResult(object sender, SearchInfo e) { SelectSearchResult(e.CurrentResult); } private void SearchPanel_CloseSearchPanel(object sender, SearchInfo e) { SearchPanelVisible = false; resultList_ = null; } private void SearchPanel_SearchChanged(object sender, SearchInfo e) { if (itemList_ == null) { return; } resultList_ = new List(); foreach (var item in itemList_) { var result = TextSearcher.FirstIndexOf(item.FunctionName, e.SearchedText, 0, e.SearchKind); if (result.HasValue) { item.SearchResult = result; item.ResetCachedName(); resultList_.Add(item); } else { item.SearchResult = null; item.ResetCachedName(); } } e.CurrentResult = 0; e.ResultCount = resultList_.Count; } private void SelectSearchResult(int index) { if (resultList_ == null) { return; } ItemList.SelectedItem = resultList_[index]; ItemList.ScrollIntoView(ItemList.SelectedItem); } ~ProfileListView() { previewPopup_?.UnregisterHoverEvents(); } private void SetupPreviewPopup() { if (previewPopup_ != null) { previewPopup_.UnregisterHoverEvents(); previewPopup_ = null; } if (!Settings.ShowPreviewPopup) { return; } previewPopup_ = new IRDocumentPopupInstance(App.Settings.PreviewPopupSettings, Session); previewPopup_.SetupHoverEvents(ItemList, TimeSpan.FromMilliseconds(Settings.PreviewPopupDuration), () => { var hoveredItem = Utils.FindPointedListViewItem(ItemList); if (hoveredItem == null) return null; var item = (ProfileListViewItem)hoveredItem.DataContext; if (item.CallTreeNode != null) { return PreviewPopupArgs.ForFunction(item.CallTreeNode.Function, ItemList); } return null; }); } public event EventHandler ModuleClick; public event EventHandler CategoryClick; public event EventHandler NodeClick; public event EventHandler NodeDoubleClick; public event EventHandler MarkingChanged; private Brush GetMarkedNodeColor(ProfileListViewItem node) { return App.Settings.MarkingSettings. GetMarkedNodeBrush(node.FunctionName, node.ModuleName); } private async Task OpenFunction(OpenSectionKind openMode) { if (ItemList.SelectedItem is ProfileListViewItem item && item.CallTreeNode != null) { await Session.OpenProfileFunction(item.CallTreeNode, openMode); } } private async Task OpenFunctionInstance(OpenSectionKind openMode) { if (ItemList.SelectedItem is ProfileListViewItem item && item.CallTreeNode != null) { var filter = new ProfileSampleFilter(item.CallTreeNode); await Session.OpenProfileFunction(item.CallTreeNode, openMode, filter); } } private async Task SelectFunctionInPanel(ToolPanelKind panelKind) { if (ItemList.SelectedItem is ProfileListViewItem item) { await Session.SelectProfileFunctionInPanel(item.CallTreeNode, panelKind); } } public void ShowSimpleList(List nodes) { ShowFunctions(nodes); //? TODO: Hack for what looks like a WPF bug where the // ProfileListView columns visibility is not read from the property // when in a popup and the popup was first created. GridViewColumnVisibility.RemoveAllColumnsExcept("FunctionColumnHeader", ItemList); } public void ShowFunctions(List nodes, ProfileListViewFilter filter = null) { var filteredNodes = new List(); if (filter is {IsEnabled: true}) { if (filter.SortByExclusiveTime) { nodes.Sort((a, b) => b.ExclusiveWeight.CompareTo(a.ExclusiveWeight)); } else { nodes.Sort((a, b) => b.Weight.CompareTo(a.Weight)); } // Filter out functions under the MinWeight threshold. var minWeight = filter.FilterByWeight ? TimeSpan.FromMilliseconds(filter.MinWeight) : TimeSpan.MaxValue; if (filter.FilterByWeight) { if (filter.SortByExclusiveTime) { foreach (var node in nodes) { if (node.ExclusiveWeight > minWeight) { filteredNodes.Add(node); } else break; } } else { foreach (var node in nodes) { if (node.Weight > minWeight) { filteredNodes.Add(node); } else break; } } } // Have at least MinItems functs, even if they are below the MinWeight threshold if (filteredNodes.Count < filter.MinItems && nodes.Count > filteredNodes.Count) { for (int i = filteredNodes.Count; i < nodes.Count && filteredNodes.Count < filter.MinItems; i++) { filteredNodes.Add(nodes[i]); } } itemList_ = new List(filteredNodes.Count); foreach (var node in filteredNodes) { var item = ProfileListViewItem.From(node, Session.ProfileData, Session.CompilerInfo.NameProvider.FormatFunctionName, Settings); // Stop once weight percentage drops under threshold. if (item.Percentage >= filter.MinPercentage || itemList_.Count < filter.MinItems || item.Weight > minWeight && itemList_.Count < filter.MinItems * 10) { itemList_.Add(item); } else { break; } } } else { // No filtering applied. filteredNodes = nodes; itemList_ = new List(filteredNodes.Count); filteredNodes.ForEach(node => itemList_.Add(ProfileListViewItem.From(node, Session.ProfileData, Session.CompilerInfo.NameProvider. FormatFunctionName, Settings))); } UpdateMarkedFunctions(); ItemList.ItemsSource = itemList_; GridViewColumnVisibility.UpdateListView(ItemList); } public void ShowModules(List modules) { itemList_ = new List(modules.Count); modules.ForEach(node => itemList_.Add(ProfileListViewItem.From(node, Session.ProfileData, Session.CompilerInfo.NameProvider.FormatFunctionName, Settings))); UpdateMarkedFunctions(); ItemList.ItemsSource = new ListCollectionView(itemList_); ItemList.ContextMenu = null; } public void ShowCategories(List categories) { itemList_ = new List(categories.Count); foreach (var node in categories) { if (node.SortedFunctions.Count == 0) { continue; } itemList_.Add(ProfileListViewItem.From(node, Session.ProfileData, Session.CompilerInfo.NameProvider.FormatFunctionName, Settings)); } UpdateMarkedFunctions(); ItemList.ItemsSource = new ListCollectionView(itemList_); IsCategoriesList = true; categories_ = categories; } public void UpdateMarkedFunctions() { if (itemList_ == null) { return; // Control not being used. } var fgSettings = App.Settings.MarkingSettings; foreach (var f in itemList_) { f.ModuleBackColor = null; f.FunctionBackColor = null; } if (!fgSettings.UseAutoModuleColors && !fgSettings.UseModuleColors && !fgSettings.UseFunctionColors) { return; } foreach (var item in itemList_) { if (item.ModuleName == null || item.FunctionName == null) { continue; } if (fgSettings.UseModuleColors && fgSettings.GetModuleBrush(item.ModuleName, out var brush)) { item.ModuleBackColor = brush; } else if (fgSettings.UseAutoModuleColors) { item.ModuleBackColor = fgSettings.GetAutoModuleBrush(item.ModuleName); } if (fgSettings.UseFunctionColors && fgSettings.GetFunctionColor(item.FunctionName, out var color)) { item.FunctionBackColor = color.AsBrush(); } } } protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected bool SetField(ref T field, T value, [CallerMemberName] string propertyName = null) { if (EqualityComparer.Default.Equals(field, value)) return false; field = value; OnPropertyChanged(propertyName); return true; } private void ItemList_MouseDoubleClick(object sender, MouseButtonEventArgs e) { var node = ((ListViewItem)sender).Content as ProfileListViewItem; if (node?.CallTreeNode != null) { NodeDoubleClick?.Invoke(this, node.CallTreeNode); } } private void ItemList_PreviewKeyDown(object sender, KeyEventArgs e) { var node = ((ListViewItem)sender).Content as ProfileListViewItem; if (node?.CallTreeNode != null) { NodeDoubleClick?.Invoke(this, node.CallTreeNode); } } private void ItemList_SelectionChanged(object sender, SelectionChangedEventArgs e) { var node = ItemList.SelectedItem as ProfileListViewItem; if (node?.CallTreeNode != null) { NodeClick?.Invoke(this, node.CallTreeNode); } else if (node?.ModuleInfo != null) { ModuleClick?.Invoke(this, node.ModuleInfo); } else if (node?.MarkingCategory != null) { CategoryClick?.Invoke(this, node.MarkingCategory); } // Show the sum of the selected functions. if (ItemList.SelectedItems.Count > 1) { var selectedNodes = new List(); foreach (object item in ItemList.SelectedItems) { if (item is ProfileListViewItem profileItem && profileItem.CallTreeNode != null) { selectedNodes.Add(profileItem.CallTreeNode); } } var weightSum = ProfileCallTree.CombinedCallTreeNodesWeight(selectedNodes); double weightPercentage = Session.ProfileData.ScaleFunctionWeight(weightSum); string text = $"Selected {ItemList.SelectedItems.Count}: {weightPercentage.AsPercentageString()} ({weightSum.AsMillisecondsString()})"; Session.SetApplicationStatus(text, "Sum of time for the selected functions"); } else { Session.SetApplicationStatus(""); } } public void Reset() { ItemList.ItemsSource = null; itemList_ = null; categories_ = null; } public void SelectFirstItem() { if (ItemList.Items.Count > 0) { ItemList.SelectedIndex = 0; } } public void SaveColumnsState(ColumnSettings settings) { settings.SaveColumnsState(ItemList); } public void RestoreColumnsState(ColumnSettings settings) { settings.RestoreColumnsState(ItemList); } } ================================================ FILE: src/ProfileExplorerUI/Profile/ProfileReportPanel.xaml ================================================